feat : error when mulitple apply not supporting

This commit is contained in:
2026-09-04 18:32:19 +07:00 Unverified
parent 9d3717d0f3
commit 50a2a5428d
3 changed files with 102 additions and 4 deletions
+40 -2
View File
@@ -19,6 +19,7 @@ import {
XIcon,
} from "lucide-react";
import { useEffect, useMemo, useState, type ReactNode } from "react";
import { toast } from "sonner";
import {
closestCenter,
DndContext,
@@ -128,6 +129,7 @@ import { rarityGradientClass } from "@/lib/catalog/rarity";
import {
applyPresetFields,
applyTeamFields,
findUnsupportedTeamWeapon,
limitPresets,
parseTeamPresets,
teamPresetCookieKey,
@@ -2240,7 +2242,25 @@ function TeamEditor({
};
const applyChanges = () => {
if (!sourceTeamId || !selectedTeamIds.size || !applyFields.length) return;
setTeams((current) => applyTeamFields(current, sourceTeamId, selectedTeamIds, applyFields));
const nextTeams = applyTeamFields(
teams,
sourceTeamId,
selectedTeamIds,
applyFields,
);
const unsupported = findUnsupportedTeamWeapon(
nextTeams,
selectedTeamIds,
characters,
weapons,
);
if (unsupported) {
toast.error(
`${unsupported.characterName} ไม่รองรับอาวุธ ${unsupported.weaponName}`,
);
return;
}
setTeams(nextTeams);
setSelectedTeamIds(new Set());
setApplyOpen(false);
};
@@ -2265,7 +2285,25 @@ function TeamEditor({
};
const applyPreset = (preset: TeamPreset) => {
if (!selectedTeamIds.size || !applyFields.length) return;
setTeams((current) => applyPresetFields(current, preset, selectedTeamIds, applyFields));
const nextTeams = applyPresetFields(
teams,
preset,
selectedTeamIds,
applyFields,
);
const unsupported = findUnsupportedTeamWeapon(
nextTeams,
selectedTeamIds,
characters,
weapons,
);
if (unsupported) {
toast.error(
`${unsupported.characterName} ไม่รองรับอาวุธ ${unsupported.weaponName}`,
);
return;
}
setTeams(nextTeams);
setSelectedTeamIds(new Set());
};
return (
+26 -2
View File
@@ -1,8 +1,14 @@
import { describe, expect, it } from "vitest";
import { applyTeamFields, limitPresets, parseTeamPresets } from "./team-tools";
import {
applyTeamFields,
findUnsupportedTeamWeapon,
limitPresets,
parseTeamPresets,
type TeamToolValue,
} from "./team-tools";
const team = (id: string, title = id) => ({
const team = (id: string, title = id): TeamToolValue => ({
clientId: id, title, rotationSeconds: "20", combo: "E > Q",
members: [1, 2, 3, 4].map((n) => ({ characterKey: `${id}-${n}`, weaponKey: null, artifactKey: null, secondArtifactKey: null, constellation: 0, refinement: 1, damage: String(n) })),
});
@@ -41,6 +47,24 @@ describe("team bulk tools", () => {
expect(result[1].members.slice(1)).toEqual(target.members.slice(1));
});
it("detects an unsupported character and weapon after bulk apply", () => {
const target = team("target");
target.members[0] = {
...target.members[0],
characterKey: "varka",
weaponKey: "wolf-fang",
};
expect(
findUnsupportedTeamWeapon(
[target],
new Set(["target"]),
[{ key: "varka", name: "Varka", weaponType: "WEAPON_CLAYMORE" }],
[{ key: "wolf-fang", name: "Wolf-Fang", weaponType: "WEAPON_SWORD_ONE_HAND" }],
),
).toEqual({ characterName: "Varka", weaponName: "Wolf-Fang" });
});
it("deduplicates and limits presets", () => {
const presets = Array.from({ length: 7 }, (_, index) => ({ id: String(index), name: String(index), createdAt: String(index), team: { ...team(String(index)), clientId: undefined as never } }));
expect(limitPresets([presets[0], presets[0], ...presets.slice(1)])).toHaveLength(5);
+36
View File
@@ -1,3 +1,5 @@
import { supportsWeaponType } from "@/lib/catalog/lunaris";
export interface TeamToolMember {
characterKey: string;
weaponKey: string | null;
@@ -40,6 +42,40 @@ export interface TeamPreset {
team: Omit<TeamToolValue, "clientId">;
}
interface TeamToolCatalogItem {
key: string;
name: string;
weaponType?: string | null;
}
export function findUnsupportedTeamWeapon(
teams: readonly TeamToolValue[],
teamIds: ReadonlySet<string>,
characters: readonly TeamToolCatalogItem[],
weapons: readonly TeamToolCatalogItem[],
): { characterName: string; weaponName: string } | null {
const characterByKey = new Map(characters.map((item) => [item.key, item]));
const weaponByKey = new Map(weapons.map((item) => [item.key, item]));
for (const team of teams) {
if (!teamIds.has(team.clientId)) continue;
for (const member of team.members) {
if (!member.characterKey || !member.weaponKey) continue;
const character = characterByKey.get(member.characterKey);
const weapon = weaponByKey.get(member.weaponKey);
if (
character &&
weapon &&
!supportsWeaponType(character.weaponType, weapon.weaponType)
) {
return { characterName: character.name, weaponName: weapon.name };
}
}
}
return null;
}
function cloneMember(member: TeamToolMember): TeamToolMember {
return { ...member };
}