feat : update
This commit is contained in:
@@ -118,6 +118,7 @@ export default async function StructuredEditorPage({
|
|||||||
artifactProfile: content.artifactProfile,
|
artifactProfile: content.artifactProfile,
|
||||||
constellationGroups: content.constellationGroups.map((group) => ({
|
constellationGroups: content.constellationGroups.map((group) => ({
|
||||||
id: group.id,
|
id: group.id,
|
||||||
|
name: group.name,
|
||||||
note: group.note,
|
note: group.note,
|
||||||
rows: group.rows,
|
rows: group.rows,
|
||||||
})),
|
})),
|
||||||
@@ -138,6 +139,7 @@ export default async function StructuredEditorPage({
|
|||||||
})),
|
})),
|
||||||
teamGroups: content.teamGroups.map((group) => ({
|
teamGroups: content.teamGroups.map((group) => ({
|
||||||
id: group.id,
|
id: group.id,
|
||||||
|
name: group.name,
|
||||||
note: group.note,
|
note: group.note,
|
||||||
teams: group.teams.map((team) => ({
|
teams: group.teams.map((team) => ({
|
||||||
id: team.id,
|
id: team.id,
|
||||||
|
|||||||
@@ -241,6 +241,7 @@ type ArtifactProfile = {
|
|||||||
substats: string[];
|
substats: string[];
|
||||||
targets: Array<{ stat: string; value: string }>;
|
targets: Array<{ stat: string; value: string }>;
|
||||||
targetConditions: Array<{
|
targetConditions: Array<{
|
||||||
|
name?: string | null;
|
||||||
note: string | null;
|
note: string | null;
|
||||||
rows: Array<{ stat: string; value: string }>;
|
rows: Array<{ stat: string; value: string }>;
|
||||||
}>;
|
}>;
|
||||||
@@ -255,6 +256,7 @@ type ConstellationValue = {
|
|||||||
};
|
};
|
||||||
type ConstellationGroupValue = {
|
type ConstellationGroupValue = {
|
||||||
id: string;
|
id: string;
|
||||||
|
name: string | null;
|
||||||
note: string | null;
|
note: string | null;
|
||||||
rows: ConstellationValue[];
|
rows: ConstellationValue[];
|
||||||
};
|
};
|
||||||
@@ -286,6 +288,7 @@ type TeamValue = {
|
|||||||
};
|
};
|
||||||
type TeamGroupValue = {
|
type TeamGroupValue = {
|
||||||
id: string;
|
id: string;
|
||||||
|
name: string | null;
|
||||||
note: string | null;
|
note: string | null;
|
||||||
teams: TeamValue[];
|
teams: TeamValue[];
|
||||||
};
|
};
|
||||||
@@ -315,6 +318,47 @@ function createClientId(prefix: string): string {
|
|||||||
return `${prefix}-${Date.now()}-${clientIdCounter}`;
|
return `${prefix}-${Date.now()}-${clientIdCounter}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ConditionRenameDialog({
|
||||||
|
open,
|
||||||
|
fallback,
|
||||||
|
value,
|
||||||
|
onOpenChange,
|
||||||
|
onChange,
|
||||||
|
}: {
|
||||||
|
open: boolean;
|
||||||
|
fallback: string;
|
||||||
|
value: string;
|
||||||
|
onOpenChange: (open: boolean) => void;
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Rename condition</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Leave blank to use {fallback}.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<Field>
|
||||||
|
<FieldLabel htmlFor="condition-name">Condition name</FieldLabel>
|
||||||
|
<Input
|
||||||
|
id="condition-name"
|
||||||
|
autoFocus
|
||||||
|
maxLength={120}
|
||||||
|
placeholder={fallback}
|
||||||
|
value={value}
|
||||||
|
onChange={(event) => onChange(event.target.value)}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button type="button" onClick={() => onOpenChange(false)}>Done</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function parseEditorDraft<Draft>(
|
function parseEditorDraft<Draft>(
|
||||||
value: unknown,
|
value: unknown,
|
||||||
arrayKeys: string[],
|
arrayKeys: string[],
|
||||||
@@ -1122,6 +1166,7 @@ function WeaponEditor({ guide, weapons, characters, initial }: EditorBase) {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
const [activeGroupIndex, setActiveGroupIndex] = useState(0);
|
const [activeGroupIndex, setActiveGroupIndex] = useState(0);
|
||||||
|
const [renamingWeaponGroupIndex, setRenamingWeaponGroupIndex] = useState<number | null>(null);
|
||||||
const rows = groups[activeGroupIndex]?.rows ?? [];
|
const rows = groups[activeGroupIndex]?.rows ?? [];
|
||||||
const setRows = (update: typeof rows | ((current: typeof rows) => typeof rows)) =>
|
const setRows = (update: typeof rows | ((current: typeof rows) => typeof rows)) =>
|
||||||
setGroups((current) => current.map((group, index) => index === activeGroupIndex
|
setGroups((current) => current.map((group, index) => index === activeGroupIndex
|
||||||
@@ -1206,6 +1251,7 @@ function WeaponEditor({ guide, weapons, characters, initial }: EditorBase) {
|
|||||||
key={group.clientId}
|
key={group.clientId}
|
||||||
value={String(index)}
|
value={String(index)}
|
||||||
className="aria-pressed:bg-primary aria-pressed:text-primary-foreground"
|
className="aria-pressed:bg-primary aria-pressed:text-primary-foreground"
|
||||||
|
onDoubleClick={() => setRenamingWeaponGroupIndex(index)}
|
||||||
>
|
>
|
||||||
{group.name.trim() || `Condition ${index + 1}`}
|
{group.name.trim() || `Condition ${index + 1}`}
|
||||||
</ToggleGroupItem>
|
</ToggleGroupItem>
|
||||||
@@ -1242,18 +1288,13 @@ function WeaponEditor({ guide, weapons, characters, initial }: EditorBase) {
|
|||||||
<CopyIcon data-icon="inline-start" />Duplicate Condition
|
<CopyIcon data-icon="inline-start" />Duplicate Condition
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<Field>
|
<ConditionRenameDialog
|
||||||
<FieldLabel htmlFor={`weapon-condition-name-${groups[activeGroupIndex]?.clientId}`}>
|
open={renamingWeaponGroupIndex !== null}
|
||||||
Condition name (optional)
|
fallback={`Condition ${(renamingWeaponGroupIndex ?? 0) + 1}`}
|
||||||
</FieldLabel>
|
value={renamingWeaponGroupIndex === null ? "" : groups[renamingWeaponGroupIndex]?.name ?? ""}
|
||||||
<Input
|
onOpenChange={(open) => { if (!open) setRenamingWeaponGroupIndex(null); }}
|
||||||
id={`weapon-condition-name-${groups[activeGroupIndex]?.clientId}`}
|
onChange={(name) => setGroups(groups.map((group, index) => index === renamingWeaponGroupIndex ? { ...group, name } : group))}
|
||||||
maxLength={120}
|
/>
|
||||||
placeholder={`Condition ${activeGroupIndex + 1}`}
|
|
||||||
value={groups[activeGroupIndex]?.name ?? ""}
|
|
||||||
onChange={(event) => setGroups(groups.map((group, index) => index === activeGroupIndex ? { ...group, name: event.target.value } : group))}
|
|
||||||
/>
|
|
||||||
</Field>
|
|
||||||
<Field>
|
<Field>
|
||||||
<FieldLabel htmlFor={`weapon-condition-note-${groups[activeGroupIndex]?.clientId}`}>
|
<FieldLabel htmlFor={`weapon-condition-note-${groups[activeGroupIndex]?.clientId}`}>
|
||||||
Condition note (optional)
|
Condition note (optional)
|
||||||
@@ -1583,7 +1624,7 @@ function ArtifactEditor({
|
|||||||
const [targetGroups, setTargetGroups] = useState(() => {
|
const [targetGroups, setTargetGroups] = useState(() => {
|
||||||
const source = profile?.targetConditions.length
|
const source = profile?.targetConditions.length
|
||||||
? profile.targetConditions
|
? profile.targetConditions
|
||||||
: [{ note: null, rows: profile?.targets ?? [] }];
|
: [{ name: null, note: null, rows: profile?.targets ?? [] }];
|
||||||
return source.map((group, index) => {
|
return source.map((group, index) => {
|
||||||
const existing = new Map(group.rows.flatMap((target) => {
|
const existing = new Map(group.rows.flatMap((target) => {
|
||||||
const stat = normalizeTargetStat(target.stat);
|
const stat = normalizeTargetStat(target.stat);
|
||||||
@@ -1591,12 +1632,14 @@ function ArtifactEditor({
|
|||||||
}));
|
}));
|
||||||
return {
|
return {
|
||||||
clientId: `target-condition-${index}`,
|
clientId: `target-condition-${index}`,
|
||||||
|
name: group.name ?? "",
|
||||||
note: group.note ?? "",
|
note: group.note ?? "",
|
||||||
rows: targetStatDefaults.map((target) => ({ stat: target.stat, value: existing.get(target.stat) ?? target.value })),
|
rows: targetStatDefaults.map((target) => ({ stat: target.stat, value: existing.get(target.stat) ?? target.value })),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
const [activeTargetGroupIndex, setActiveTargetGroupIndex] = useState(0);
|
const [activeTargetGroupIndex, setActiveTargetGroupIndex] = useState(0);
|
||||||
|
const [renamingTargetGroupIndex, setRenamingTargetGroupIndex] = useState<number | null>(null);
|
||||||
const targets = targetGroups[activeTargetGroupIndex]?.rows ?? [];
|
const targets = targetGroups[activeTargetGroupIndex]?.rows ?? [];
|
||||||
const setTargets = (rows: typeof targets) => setTargetGroups((current) => current.map((group, index) => index === activeTargetGroupIndex ? { ...group, rows } : group));
|
const setTargets = (rows: typeof targets) => setTargetGroups((current) => current.map((group, index) => index === activeTargetGroupIndex ? { ...group, rows } : group));
|
||||||
const [talents, setTalents] = useState<TalentPriority[]>(() => {
|
const [talents, setTalents] = useState<TalentPriority[]>(() => {
|
||||||
@@ -1635,6 +1678,7 @@ function ArtifactEditor({
|
|||||||
circlet,
|
circlet,
|
||||||
substats,
|
substats,
|
||||||
targetGroups: targetGroups.map((group) => ({
|
targetGroups: targetGroups.map((group) => ({
|
||||||
|
name: group.name.trim() || null,
|
||||||
note: group.note.trim() || null,
|
note: group.note.trim() || null,
|
||||||
rows: group.rows.filter((target) => target.value.trim()).map((target) => ({ stat: target.stat, value: target.value.trim() })),
|
rows: group.rows.filter((target) => target.value.trim()).map((target) => ({ stat: target.stat, value: target.value.trim() })),
|
||||||
})),
|
})),
|
||||||
@@ -1686,7 +1730,7 @@ function ArtifactEditor({
|
|||||||
setGoblet(draft.goblet);
|
setGoblet(draft.goblet);
|
||||||
setCirclet(draft.circlet);
|
setCirclet(draft.circlet);
|
||||||
setSubstats(draft.substats);
|
setSubstats(draft.substats);
|
||||||
setTargetGroups(draft.targetGroups);
|
setTargetGroups(draft.targetGroups.map((group) => ({ ...group, name: group.name ?? "" })));
|
||||||
setActiveTargetGroupIndex(draft.activeTargetGroupIndex ?? 0);
|
setActiveTargetGroupIndex(draft.activeTargetGroupIndex ?? 0);
|
||||||
setTalents(draft.talents);
|
setTalents(draft.talents);
|
||||||
setNote(draft.note);
|
setNote(draft.note);
|
||||||
@@ -2054,19 +2098,26 @@ function ArtifactEditor({
|
|||||||
if (values[0]) setActiveTargetGroupIndex(Number(values[0]));
|
if (values[0]) setActiveTargetGroupIndex(Number(values[0]));
|
||||||
}}>
|
}}>
|
||||||
{targetGroups.map((group, index) => (
|
{targetGroups.map((group, index) => (
|
||||||
<ToggleGroupItem key={group.clientId} value={String(index)} className="aria-pressed:bg-primary aria-pressed:text-primary-foreground">
|
<ToggleGroupItem key={group.clientId} value={String(index)} className="aria-pressed:bg-primary aria-pressed:text-primary-foreground" onDoubleClick={() => setRenamingTargetGroupIndex(index)}>
|
||||||
Condition {index + 1}
|
{group.name.trim() || `Condition ${index + 1}`}
|
||||||
</ToggleGroupItem>
|
</ToggleGroupItem>
|
||||||
))}
|
))}
|
||||||
</ToggleGroup>
|
</ToggleGroup>
|
||||||
|
<ConditionRenameDialog
|
||||||
|
open={renamingTargetGroupIndex !== null}
|
||||||
|
fallback={`Condition ${(renamingTargetGroupIndex ?? 0) + 1}`}
|
||||||
|
value={renamingTargetGroupIndex === null ? "" : targetGroups[renamingTargetGroupIndex]?.name ?? ""}
|
||||||
|
onOpenChange={(open) => { if (!open) setRenamingTargetGroupIndex(null); }}
|
||||||
|
onChange={(name) => setTargetGroups(targetGroups.map((group, index) => index === renamingTargetGroupIndex ? { ...group, name } : group))}
|
||||||
|
/>
|
||||||
<Button type="button" variant="outline" disabled={targetGroups.length >= 20} onClick={() => {
|
<Button type="button" variant="outline" disabled={targetGroups.length >= 20} onClick={() => {
|
||||||
setTargetGroups([...targetGroups, { clientId: createClientId("target-condition"), note: "", rows: targetStatDefaults.map((target) => ({ ...target })) }]);
|
setTargetGroups([...targetGroups, { clientId: createClientId("target-condition"), name: "", note: "", rows: targetStatDefaults.map((target) => ({ ...target })) }]);
|
||||||
setActiveTargetGroupIndex(targetGroups.length);
|
setActiveTargetGroupIndex(targetGroups.length);
|
||||||
}}><PlusIcon data-icon="inline-start" />เพิ่ม Condition</Button>
|
}}><PlusIcon data-icon="inline-start" />เพิ่ม Condition</Button>
|
||||||
<Button type="button" variant="outline" disabled={targetGroups.length >= 20} onClick={() => {
|
<Button type="button" variant="outline" disabled={targetGroups.length >= 20} onClick={() => {
|
||||||
const source = targetGroups[activeTargetGroupIndex];
|
const source = targetGroups[activeTargetGroupIndex];
|
||||||
if (!source) return;
|
if (!source) return;
|
||||||
setTargetGroups([...targetGroups, { clientId: createClientId("target-condition"), note: source.note, rows: source.rows.map((row) => ({ ...row })) }]);
|
setTargetGroups([...targetGroups, { clientId: createClientId("target-condition"), name: source.name, note: source.note, rows: source.rows.map((row) => ({ ...row })) }]);
|
||||||
setActiveTargetGroupIndex(targetGroups.length);
|
setActiveTargetGroupIndex(targetGroups.length);
|
||||||
}}><CopyIcon data-icon="inline-start" />Duplicate Condition</Button>
|
}}><CopyIcon data-icon="inline-start" />Duplicate Condition</Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -2278,17 +2329,20 @@ function ConstellationEditor({
|
|||||||
const [groups, setGroups] = useState(() => {
|
const [groups, setGroups] = useState(() => {
|
||||||
const source = initial.constellationGroups.length
|
const source = initial.constellationGroups.length
|
||||||
? initial.constellationGroups
|
? initial.constellationGroups
|
||||||
: [{ id: "constellation-condition-default", note: null, rows: [] }];
|
: [{ id: "constellation-condition-default", name: null, note: null, rows: [] }];
|
||||||
return source.map((group) => ({
|
return source.map((group) => ({
|
||||||
clientId: group.id,
|
clientId: group.id,
|
||||||
|
name: group.name ?? "",
|
||||||
note: group.note ?? "",
|
note: group.note ?? "",
|
||||||
rows: makeRows(group.rows),
|
rows: makeRows(group.rows),
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
const [activeConstellationGroupIndex, setActiveConstellationGroupIndex] = useState(0);
|
const [activeConstellationGroupIndex, setActiveConstellationGroupIndex] = useState(0);
|
||||||
|
const [renamingConstellationGroupIndex, setRenamingConstellationGroupIndex] = useState<number | null>(null);
|
||||||
const value = {
|
const value = {
|
||||||
note: note.trim() || null,
|
note: note.trim() || null,
|
||||||
groups: groups.map((group) => ({
|
groups: groups.map((group) => ({
|
||||||
|
name: group.name.trim() || null,
|
||||||
note: group.note.trim() || null,
|
note: group.note.trim() || null,
|
||||||
rows: group.rows
|
rows: group.rows
|
||||||
.filter((row) => row.description.trim() && row.cumulativePercent !== "")
|
.filter((row) => row.description.trim() && row.cumulativePercent !== "")
|
||||||
@@ -2319,7 +2373,7 @@ function ConstellationEditor({
|
|||||||
parseEditorDraft<typeof localDraft>(candidate, ["groups"], ["note"]),
|
parseEditorDraft<typeof localDraft>(candidate, ["groups"], ["note"]),
|
||||||
restoreLocalDraft: (draft) => {
|
restoreLocalDraft: (draft) => {
|
||||||
setNote(draft.note);
|
setNote(draft.note);
|
||||||
setGroups(draft.groups);
|
setGroups(draft.groups.map((group) => ({ ...group, name: group.name ?? "" })));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
@@ -2355,11 +2409,19 @@ function ConstellationEditor({
|
|||||||
key={group.clientId}
|
key={group.clientId}
|
||||||
value={String(index)}
|
value={String(index)}
|
||||||
className="aria-pressed:bg-primary aria-pressed:text-primary-foreground"
|
className="aria-pressed:bg-primary aria-pressed:text-primary-foreground"
|
||||||
|
onDoubleClick={() => setRenamingConstellationGroupIndex(index)}
|
||||||
>
|
>
|
||||||
Condition {index + 1}
|
{group.name.trim() || `Condition ${index + 1}`}
|
||||||
</ToggleGroupItem>
|
</ToggleGroupItem>
|
||||||
))}
|
))}
|
||||||
</ToggleGroup>
|
</ToggleGroup>
|
||||||
|
<ConditionRenameDialog
|
||||||
|
open={renamingConstellationGroupIndex !== null}
|
||||||
|
fallback={`Condition ${(renamingConstellationGroupIndex ?? 0) + 1}`}
|
||||||
|
value={renamingConstellationGroupIndex === null ? "" : groups[renamingConstellationGroupIndex]?.name ?? ""}
|
||||||
|
onOpenChange={(open) => { if (!open) setRenamingConstellationGroupIndex(null); }}
|
||||||
|
onChange={(name) => setGroups(groups.map((group, index) => index === renamingConstellationGroupIndex ? { ...group, name } : group))}
|
||||||
|
/>
|
||||||
{groups[activeConstellationGroupIndex] ? [groups[activeConstellationGroupIndex]].map((group) => {
|
{groups[activeConstellationGroupIndex] ? [groups[activeConstellationGroupIndex]].map((group) => {
|
||||||
const groupIndex = activeConstellationGroupIndex;
|
const groupIndex = activeConstellationGroupIndex;
|
||||||
return (
|
return (
|
||||||
@@ -2536,6 +2598,7 @@ function ConstellationEditor({
|
|||||||
...groups,
|
...groups,
|
||||||
{
|
{
|
||||||
clientId: createClientId("constellation-condition"),
|
clientId: createClientId("constellation-condition"),
|
||||||
|
name: "",
|
||||||
note: "",
|
note: "",
|
||||||
rows: makeRows(),
|
rows: makeRows(),
|
||||||
},
|
},
|
||||||
@@ -2586,9 +2649,10 @@ function TeamEditor({
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
const [teamGroups, setTeamGroups] = useState(() => initial.teamGroups.length
|
const [teamGroups, setTeamGroups] = useState(() => initial.teamGroups.length
|
||||||
? initial.teamGroups.map((group) => ({ clientId: group.id, note: group.note ?? "", teams: group.teams.map(({ id, ...team }) => ({ clientId: id, ...team })) }))
|
? initial.teamGroups.map((group) => ({ clientId: group.id, name: group.name ?? "", note: group.note ?? "", teams: group.teams.map(({ id, ...team }) => ({ clientId: id, ...team })) }))
|
||||||
: [{ clientId: "team-condition-default", note: "", teams: [] as TeamToolValue[] }]);
|
: [{ clientId: "team-condition-default", name: "", note: "", teams: [] as TeamToolValue[] }]);
|
||||||
const [activeTeamGroupIndex, setActiveTeamGroupIndex] = useState(0);
|
const [activeTeamGroupIndex, setActiveTeamGroupIndex] = useState(0);
|
||||||
|
const [renamingTeamGroupIndex, setRenamingTeamGroupIndex] = useState<number | null>(null);
|
||||||
const teams = useMemo(() => teamGroups[activeTeamGroupIndex]?.teams ?? [], [activeTeamGroupIndex, teamGroups]);
|
const teams = useMemo(() => teamGroups[activeTeamGroupIndex]?.teams ?? [], [activeTeamGroupIndex, teamGroups]);
|
||||||
const setTeams = (update: SetStateAction<TeamToolValue[]>) => setTeamGroups((current) => current.map((group, index) => index === activeTeamGroupIndex ? { ...group, teams: typeof update === "function" ? update(group.teams) : update } : group));
|
const setTeams = (update: SetStateAction<TeamToolValue[]>) => setTeamGroups((current) => current.map((group, index) => index === activeTeamGroupIndex ? { ...group, teams: typeof update === "function" ? update(group.teams) : update } : group));
|
||||||
const [selectedTeamIds, setSelectedTeamIds] = useState<Set<string>>(
|
const [selectedTeamIds, setSelectedTeamIds] = useState<Set<string>>(
|
||||||
@@ -2636,7 +2700,7 @@ function TeamEditor({
|
|||||||
}, searchQuery, searchTarget));
|
}, searchQuery, searchTarget));
|
||||||
}, [artifacts, characters, searchQuery, searchTarget, teams, weapons]);
|
}, [artifacts, characters, searchQuery, searchTarget, teams, weapons]);
|
||||||
const value = {
|
const value = {
|
||||||
groups: teamGroups.map((group) => ({ note: group.note.trim() || null, teams: group.teams.map((team) => ({
|
groups: teamGroups.map((group) => ({ name: group.name.trim() || null, note: group.note.trim() || null, teams: group.teams.map((team) => ({
|
||||||
title: team.title,
|
title: team.title,
|
||||||
rotationSeconds: Number(team.rotationSeconds),
|
rotationSeconds: Number(team.rotationSeconds),
|
||||||
combo: team.combo,
|
combo: team.combo,
|
||||||
@@ -2735,7 +2799,7 @@ function TeamEditor({
|
|||||||
parseLocalDraft: (candidate) =>
|
parseLocalDraft: (candidate) =>
|
||||||
parseEditorDraft<typeof localDraft>(candidate, ["teamGroups"]),
|
parseEditorDraft<typeof localDraft>(candidate, ["teamGroups"]),
|
||||||
restoreLocalDraft: (draft) => {
|
restoreLocalDraft: (draft) => {
|
||||||
setTeamGroups(draft.teamGroups);
|
setTeamGroups(draft.teamGroups.map((group) => ({ ...group, name: group.name ?? "" })));
|
||||||
setActiveTeamGroupIndex(draft.activeTeamGroupIndex ?? 0);
|
setActiveTeamGroupIndex(draft.activeTeamGroupIndex ?? 0);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -2962,13 +3026,20 @@ function TeamEditor({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{teamGroups.map((group, index) => (
|
{teamGroups.map((group, index) => (
|
||||||
<ToggleGroupItem key={group.clientId} value={String(index)}>
|
<ToggleGroupItem key={group.clientId} value={String(index)} onDoubleClick={() => setRenamingTeamGroupIndex(index)} className="aria-pressed:bg-primary aria-pressed:text-primary-foreground">
|
||||||
Condition {index + 1}
|
{group.name.trim() || `Condition ${index + 1}`}
|
||||||
</ToggleGroupItem>
|
</ToggleGroupItem>
|
||||||
))}
|
))}
|
||||||
</ToggleGroup>
|
</ToggleGroup>
|
||||||
|
<ConditionRenameDialog
|
||||||
|
open={renamingTeamGroupIndex !== null}
|
||||||
|
fallback={`Condition ${(renamingTeamGroupIndex ?? 0) + 1}`}
|
||||||
|
value={renamingTeamGroupIndex === null ? "" : teamGroups[renamingTeamGroupIndex]?.name ?? ""}
|
||||||
|
onOpenChange={(open) => { if (!open) setRenamingTeamGroupIndex(null); }}
|
||||||
|
onChange={(name) => setTeamGroups(teamGroups.map((group, index) => index === renamingTeamGroupIndex ? { ...group, name } : group))}
|
||||||
|
/>
|
||||||
<Button type="button" variant="outline" disabled={teamGroups.length >= 20} onClick={() => {
|
<Button type="button" variant="outline" disabled={teamGroups.length >= 20} onClick={() => {
|
||||||
setTeamGroups([...teamGroups, { clientId: createClientId("team-condition"), note: "", teams: [] }]);
|
setTeamGroups([...teamGroups, { clientId: createClientId("team-condition"), name: "", note: "", teams: [] }]);
|
||||||
setActiveTeamGroupIndex(teamGroups.length);
|
setActiveTeamGroupIndex(teamGroups.length);
|
||||||
setSelectedTeamIds(new Set());
|
setSelectedTeamIds(new Set());
|
||||||
setSourceTeamId("");
|
setSourceTeamId("");
|
||||||
@@ -2977,7 +3048,7 @@ function TeamEditor({
|
|||||||
const source = teamGroups[activeTeamGroupIndex];
|
const source = teamGroups[activeTeamGroupIndex];
|
||||||
if (!source) return;
|
if (!source) return;
|
||||||
const copiedTeams = source.teams.map((team) => ({ ...team, clientId: createClientId("team"), members: team.members.map((member) => ({ ...member })) }));
|
const copiedTeams = source.teams.map((team) => ({ ...team, clientId: createClientId("team"), members: team.members.map((member) => ({ ...member })) }));
|
||||||
setTeamGroups([...teamGroups, { clientId: createClientId("team-condition"), note: source.note, teams: copiedTeams }]);
|
setTeamGroups([...teamGroups, { clientId: createClientId("team-condition"), name: source.name, note: source.note, teams: copiedTeams }]);
|
||||||
setActiveTeamGroupIndex(teamGroups.length);
|
setActiveTeamGroupIndex(teamGroups.length);
|
||||||
setSelectedTeamIds(new Set());
|
setSelectedTeamIds(new Set());
|
||||||
setSourceTeamId(copiedTeams[0]?.clientId ?? "");
|
setSourceTeamId(copiedTeams[0]?.clientId ?? "");
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ type ArtifactExportSection = (typeof sectionOptions)[number][0];
|
|||||||
export function ArtifactImageExport({
|
export function ArtifactImageExport({
|
||||||
children,
|
children,
|
||||||
fileName,
|
fileName,
|
||||||
targetConditionCount,
|
targetConditionLabels,
|
||||||
}: {
|
}: {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
targetConditionCount: number;
|
targetConditionLabels: readonly string[];
|
||||||
}) {
|
}) {
|
||||||
const [sections, setSections] = useState<Set<ArtifactExportSection>>(
|
const [sections, setSections] = useState<Set<ArtifactExportSection>>(
|
||||||
() => new Set(sectionOptions.map(([value]) => value)),
|
() => new Set(sectionOptions.map(([value]) => value)),
|
||||||
@@ -99,7 +99,7 @@ export function ArtifactImageExport({
|
|||||||
</Field>
|
</Field>
|
||||||
))}
|
))}
|
||||||
</FieldGroup>
|
</FieldGroup>
|
||||||
{sections.has("target-stats") && targetConditionCount > 1 ? (
|
{sections.has("target-stats") && targetConditionLabels.length > 1 ? (
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<p className="text-sm font-medium">Target Stats condition</p>
|
<p className="text-sm font-medium">Target Stats condition</p>
|
||||||
<ToggleGroup
|
<ToggleGroup
|
||||||
@@ -109,13 +109,13 @@ export function ArtifactImageExport({
|
|||||||
if (values[0]) setTargetCondition(values[0]);
|
if (values[0]) setTargetCondition(values[0]);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{Array.from({ length: targetConditionCount }, (_, index) => (
|
{targetConditionLabels.map((label, index) => (
|
||||||
<ToggleGroupItem
|
<ToggleGroupItem
|
||||||
key={index}
|
key={index}
|
||||||
value={String(index)}
|
value={String(index)}
|
||||||
className="aria-pressed:bg-primary aria-pressed:text-primary-foreground"
|
className="aria-pressed:bg-primary aria-pressed:text-primary-foreground"
|
||||||
>
|
>
|
||||||
Condition {index + 1}
|
{label}
|
||||||
</ToggleGroupItem>
|
</ToggleGroupItem>
|
||||||
))}
|
))}
|
||||||
</ToggleGroup>
|
</ToggleGroup>
|
||||||
|
|||||||
@@ -603,16 +603,16 @@ function WeaponSectionContent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ArtifactSection({ guide }: { guide: PublicGuide }) {
|
function ArtifactSection({ guide }: { guide: PublicGuide }) {
|
||||||
const targetConditionCount = guide.artifactProfile?.targetConditions.filter(
|
const targetConditions = guide.artifactProfile?.targetConditions.filter(
|
||||||
(group) => group.rows.length,
|
(group) => group.rows.length,
|
||||||
).length ?? 0;
|
) ?? [];
|
||||||
return (
|
return (
|
||||||
<ArtifactSectionContent
|
<ArtifactSectionContent
|
||||||
guide={guide}
|
guide={guide}
|
||||||
action={
|
action={
|
||||||
<ArtifactImageExport
|
<ArtifactImageExport
|
||||||
fileName={`${guide.name}-Artifact.png`}
|
fileName={`${guide.name}-Artifact.png`}
|
||||||
targetConditionCount={targetConditionCount}
|
targetConditionLabels={targetConditions.map((group, index) => group.name || `Condition ${index + 1}`)}
|
||||||
>
|
>
|
||||||
<ArtifactSectionContent guide={guide} exporting />
|
<ArtifactSectionContent guide={guide} exporting />
|
||||||
</ArtifactImageExport>
|
</ArtifactImageExport>
|
||||||
@@ -821,7 +821,7 @@ function ArtifactSectionContent({
|
|||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<ConditionSwitcher label="เลือกเงื่อนไขค่าสถานะเป้าหมาย">
|
<ConditionSwitcher label="เลือกเงื่อนไขค่าสถานะเป้าหมาย" labels={profile.targetConditions.filter((group) => group.rows.length).map((group, index) => group.name || `Condition ${index + 1}`)}>
|
||||||
{profile.targetConditions.filter((group) => group.rows.length).map((group, groupIndex) => (
|
{profile.targetConditions.filter((group) => group.rows.length).map((group, groupIndex) => (
|
||||||
<div key={groupIndex}>
|
<div key={groupIndex}>
|
||||||
<p className="mb-2 text-sm font-medium">ค่าสถานะต่ำๆที่ควรจะปั้นไว้</p>
|
<p className="mb-2 text-sm font-medium">ค่าสถานะต่ำๆที่ควรจะปั้นไว้</p>
|
||||||
@@ -1116,12 +1116,12 @@ function ConstellationSection({ guide }: { guide: PublicGuide }) {
|
|||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
</header>
|
</header>
|
||||||
<ConditionSwitcher label="เลือกเงื่อนไขกลุ่มดาว">
|
<ConditionSwitcher label="เลือกเงื่อนไขกลุ่มดาว" labels={guide.constellationGroups.filter((group) => group.rows.length > 0).map((group, index) => group.name || `Condition ${index + 1}`)}>
|
||||||
{guide.constellationGroups.filter((group) => group.rows.length > 0).map((group, groupIndex, groups) => (
|
{guide.constellationGroups.filter((group) => group.rows.length > 0).map((group, groupIndex, groups) => (
|
||||||
<div key={group.id} className="flex flex-col gap-4">
|
<div key={group.id} className="flex flex-col gap-4">
|
||||||
<div>
|
<div>
|
||||||
<GuideImageExport
|
<GuideImageExport
|
||||||
fileName={`${guide.name}-Constellations${groups.length > 1 ? `-Condition-${groupIndex + 1}` : ""}.png`}
|
fileName={`${guide.name}-Constellations${groups.length > 1 ? `-${group.name || `Condition-${groupIndex + 1}`}` : ""}.png`}
|
||||||
width={1500}
|
width={1500}
|
||||||
height={1500}
|
height={1500}
|
||||||
captureClassName="p-0"
|
captureClassName="p-0"
|
||||||
@@ -1133,7 +1133,7 @@ function ConstellationSection({ guide }: { guide: PublicGuide }) {
|
|||||||
/>
|
/>
|
||||||
</GuideImageExport>
|
</GuideImageExport>
|
||||||
</div>
|
</div>
|
||||||
{groups.length > 1 ? <h2 className="font-heading text-2xl font-semibold">Condition {groupIndex + 1}</h2> : null}
|
{groups.length > 1 ? <h2 className="font-heading text-2xl font-semibold">{group.name || `Condition ${groupIndex + 1}`}</h2> : null}
|
||||||
{group.note ? <p className="whitespace-pre-wrap">{group.note}</p> : null}
|
{group.note ? <p className="whitespace-pre-wrap">{group.note}</p> : null}
|
||||||
<div className="grid gap-4 md:grid-cols-2">
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
{group.rows.map((row) => (
|
{group.rows.map((row) => (
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ export function TeamSearch({ groups }: { groups: PublicGuide["teamGroups"] }) {
|
|||||||
<ToggleGroup aria-label="เลือกเงื่อนไขทีม" variant="outline" value={[activeCondition]} onValueChange={(values) => {
|
<ToggleGroup aria-label="เลือกเงื่อนไขทีม" variant="outline" value={[activeCondition]} onValueChange={(values) => {
|
||||||
if (values[0]) setActiveCondition(values[0]);
|
if (values[0]) setActiveCondition(values[0]);
|
||||||
}}>
|
}}>
|
||||||
{groups.map((group, index) => <ToggleGroupItem key={group.id} value={String(index)}>Condition {index + 1}</ToggleGroupItem>)}
|
{groups.map((group, index) => <ToggleGroupItem key={group.id} value={String(index)} className="aria-pressed:bg-primary aria-pressed:text-primary-foreground">{group.name || `Condition ${index + 1}`}</ToggleGroupItem>)}
|
||||||
</ToggleGroup>
|
</ToggleGroup>
|
||||||
) : null}
|
) : null}
|
||||||
{activeGroup?.note ? <p className="whitespace-pre-wrap text-muted-foreground">{activeGroup.note}</p> : null}
|
{activeGroup?.note ? <p className="whitespace-pre-wrap text-muted-foreground">{activeGroup.note}</p> : null}
|
||||||
|
|||||||
+3
-1
@@ -662,7 +662,7 @@ export const artifactProfiles = guidesSchema.table("artifact_profile", {
|
|||||||
substats: jsonb("substats").$type<string[]>().default([]).notNull(),
|
substats: jsonb("substats").$type<string[]>().default([]).notNull(),
|
||||||
targets: jsonb("targets").$type<Array<{ stat: string; value: string }>>().default([]).notNull(),
|
targets: jsonb("targets").$type<Array<{ stat: string; value: string }>>().default([]).notNull(),
|
||||||
targetConditions: jsonb("target_conditions")
|
targetConditions: jsonb("target_conditions")
|
||||||
.$type<Array<{ note: string | null; rows: Array<{ stat: string; value: string }> }>>()
|
.$type<Array<{ name?: string | null; note: string | null; rows: Array<{ stat: string; value: string }> }>>()
|
||||||
.default([])
|
.default([])
|
||||||
.notNull(),
|
.notNull(),
|
||||||
talents: jsonb("talents").$type<Array<{ type: "NA" | "E" | "Q"; priority: number; level?: string; relationToNext?: "gt" | "gte" | "eq" }>>().default([]).notNull(),
|
talents: jsonb("talents").$type<Array<{ type: "NA" | "E" | "Q"; priority: number; level?: string; relationToNext?: "gt" | "gte" | "eq" }>>().default([]).notNull(),
|
||||||
@@ -675,6 +675,7 @@ export const teamConditions = guidesSchema.table(
|
|||||||
{
|
{
|
||||||
id: uuid("id").defaultRandom().primaryKey(),
|
id: uuid("id").defaultRandom().primaryKey(),
|
||||||
guideId: uuid("guide_id").notNull().references(() => guides.id, { onDelete: "cascade" }),
|
guideId: uuid("guide_id").notNull().references(() => guides.id, { onDelete: "cascade" }),
|
||||||
|
name: varchar("name", { length: 120 }),
|
||||||
note: text("note"),
|
note: text("note"),
|
||||||
sortOrder: integer("sort_order").default(0).notNull(),
|
sortOrder: integer("sort_order").default(0).notNull(),
|
||||||
},
|
},
|
||||||
@@ -686,6 +687,7 @@ export const constellationConditions = guidesSchema.table(
|
|||||||
{
|
{
|
||||||
id: uuid("id").defaultRandom().primaryKey(),
|
id: uuid("id").defaultRandom().primaryKey(),
|
||||||
guideId: uuid("guide_id").notNull().references(() => guides.id, { onDelete: "cascade" }),
|
guideId: uuid("guide_id").notNull().references(() => guides.id, { onDelete: "cascade" }),
|
||||||
|
name: varchar("name", { length: 120 }),
|
||||||
note: text("note"),
|
note: text("note"),
|
||||||
sortOrder: integer("sort_order").default(0).notNull(),
|
sortOrder: integer("sort_order").default(0).notNull(),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE "guides"."constellation_condition" ADD COLUMN "name" varchar(120);--> statement-breakpoint
|
||||||
|
ALTER TABLE "guides"."team_condition" ADD COLUMN "name" varchar(120);
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -274,6 +274,13 @@
|
|||||||
"when": 1788789610191,
|
"when": 1788789610191,
|
||||||
"tag": "0038_wonderful_kingpin",
|
"tag": "0038_wonderful_kingpin",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 39,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1788794054894,
|
||||||
|
"tag": "0039_flowery_smiling_tiger",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -219,7 +219,7 @@ export async function saveConstellations(guideId: string, input: unknown) {
|
|||||||
await tx.update(guideSections).set({ note: data.note }).where(and(eq(guideSections.guideId, guideId), eq(guideSections.slug, "constellations")));
|
await tx.update(guideSections).set({ note: data.note }).where(and(eq(guideSections.guideId, guideId), eq(guideSections.slug, "constellations")));
|
||||||
await tx.delete(constellationConditions).where(eq(constellationConditions.guideId, guideId));
|
await tx.delete(constellationConditions).where(eq(constellationConditions.guideId, guideId));
|
||||||
for (const [sortOrder, group] of data.groups.entries()) {
|
for (const [sortOrder, group] of data.groups.entries()) {
|
||||||
const [created] = await tx.insert(constellationConditions).values({ guideId, note: group.note, sortOrder }).returning();
|
const [created] = await tx.insert(constellationConditions).values({ guideId, name: group.name, note: group.note, sortOrder }).returning();
|
||||||
if (group.rows.length) await tx.insert(constellationRecommendations).values(group.rows.map((row) => ({ ...row, cumulativePercent: row.cumulativePercent.toString(), conditionId: created.id })));
|
if (group.rows.length) await tx.insert(constellationRecommendations).values(group.rows.map((row) => ({ ...row, cumulativePercent: row.cumulativePercent.toString(), conditionId: created.id })));
|
||||||
}
|
}
|
||||||
return updated;
|
return updated;
|
||||||
@@ -253,7 +253,7 @@ export async function saveTeams(guideId: string, input: unknown) {
|
|||||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion);
|
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion);
|
||||||
await tx.delete(teamConditions).where(eq(teamConditions.guideId, guideId));
|
await tx.delete(teamConditions).where(eq(teamConditions.guideId, guideId));
|
||||||
for (const [groupOrder, group] of data.groups.entries()) {
|
for (const [groupOrder, group] of data.groups.entries()) {
|
||||||
const [condition] = await tx.insert(teamConditions).values({ guideId, note: group.note, sortOrder: groupOrder }).returning();
|
const [condition] = await tx.insert(teamConditions).values({ guideId, name: group.name, note: group.note, sortOrder: groupOrder }).returning();
|
||||||
for (const [sortOrder, team] of group.teams.entries()) {
|
for (const [sortOrder, team] of group.teams.entries()) {
|
||||||
const [created] = await tx.insert(teamCompositions).values({ guideId, conditionId: condition.id, title: team.title, rotationSeconds: team.rotationSeconds.toString(), combo: team.combo, sortOrder }).returning();
|
const [created] = await tx.insert(teamCompositions).values({ guideId, conditionId: condition.id, title: team.title, rotationSeconds: team.rotationSeconds.toString(), combo: team.combo, sortOrder }).returning();
|
||||||
await tx.insert(teamMembers).values(team.members.map((member, position) => ({ ...member, teamId: created.id, position, damage: member.damage.toString() })));
|
await tx.insert(teamMembers).values(team.members.map((member, position) => ({ ...member, teamId: created.id, position, damage: member.damage.toString() })));
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ async function getGuideContent(slug: string, publicOnly: boolean) {
|
|||||||
weapons: weaponRows.map(({ recommendation, weapon }) => ({ ...recommendation, weapon: { ...weapon, aliases: groupedAliases.weapon.get(weapon.key) ?? [], imageUrl: publicMediaUrl(weapon.imageKey) } })),
|
weapons: weaponRows.map(({ recommendation, weapon }) => ({ ...recommendation, weapon: { ...weapon, aliases: groupedAliases.weapon.get(weapon.key) ?? [], imageUrl: publicMediaUrl(weapon.imageKey) } })),
|
||||||
weaponGroups: weaponConditionsRows.map((condition) => ({ ...condition, rows: weaponRows.filter(({ recommendation }) => recommendation.conditionId === condition.id).map(({ recommendation, weapon }) => ({ ...recommendation, weapon: { ...weapon, aliases: groupedAliases.weapon.get(weapon.key) ?? [], imageUrl: publicMediaUrl(weapon.imageKey) } })) })),
|
weaponGroups: weaponConditionsRows.map((condition) => ({ ...condition, rows: weaponRows.filter(({ recommendation }) => recommendation.conditionId === condition.id).map(({ recommendation, weapon }) => ({ ...recommendation, weapon: { ...weapon, aliases: groupedAliases.weapon.get(weapon.key) ?? [], imageUrl: publicMediaUrl(weapon.imageKey) } })) })),
|
||||||
artifactGroups: groups.map((group) => ({ ...group, rows: artifactRows.filter(({ recommendation }) => recommendation.groupId === group.id).map(({ recommendation, artifact }) => { const second = secondArtifacts.find((item) => item.key === recommendation.secondArtifactKey); return { ...recommendation, first: { ...artifact, aliases: groupedAliases.artifact.get(artifact.key) ?? [], imageUrl: publicMediaUrl(artifact.imageKey) }, second: second ? { ...second, aliases: groupedAliases.artifact.get(second.key) ?? [], imageUrl: publicMediaUrl(second.imageKey) } : null }; }) })),
|
artifactGroups: groups.map((group) => ({ ...group, rows: artifactRows.filter(({ recommendation }) => recommendation.groupId === group.id).map(({ recommendation, artifact }) => { const second = secondArtifacts.find((item) => item.key === recommendation.secondArtifactKey); return { ...recommendation, first: { ...artifact, aliases: groupedAliases.artifact.get(artifact.key) ?? [], imageUrl: publicMediaUrl(artifact.imageKey) }, second: second ? { ...second, aliases: groupedAliases.artifact.get(second.key) ?? [], imageUrl: publicMediaUrl(second.imageKey) } : null }; }) })),
|
||||||
artifactProfile: profile[0] ? { ...profile[0], targetConditions: profile[0].targetConditions.length ? profile[0].targetConditions : [{ note: null, rows: profile[0].targets }] } : null,
|
artifactProfile: profile[0] ? { ...profile[0], targetConditions: profile[0].targetConditions.length ? profile[0].targetConditions : [{ name: null, note: null, rows: profile[0].targets }] } : null,
|
||||||
constellationGroups: constellationGroups.map((group) => ({
|
constellationGroups: constellationGroups.map((group) => ({
|
||||||
...group,
|
...group,
|
||||||
rows: constellations.filter((recommendation) => recommendation.conditionId === group.id).map((recommendation) => {
|
rows: constellations.filter((recommendation) => recommendation.conditionId === group.id).map((recommendation) => {
|
||||||
@@ -316,7 +316,7 @@ async function getGuideContent(slug: string, publicOnly: boolean) {
|
|||||||
}),
|
}),
|
||||||
})),
|
})),
|
||||||
teams: hydratedTeams,
|
teams: hydratedTeams,
|
||||||
teamGroups: teamConditionRows.length ? teamConditionRows.map((condition) => ({ ...condition, teams: hydratedTeams.filter((team) => team.conditionId === condition.id) })) : [{ id: "team-condition-default", guideId: row.guide.id, note: null, sortOrder: 0, teams: hydratedTeams }],
|
teamGroups: teamConditionRows.length ? teamConditionRows.map((condition) => ({ ...condition, teams: hydratedTeams.filter((team) => team.conditionId === condition.id) })) : [{ id: "team-condition-default", guideId: row.guide.id, name: null, note: null, sortOrder: 0, teams: hydratedTeams }],
|
||||||
extras: sections.filter((section) => section.kind === "extra").map((section) => ({ ...section, rows: extraRows.filter(({ row: extraRow }) => extraRow.sectionId === section.id).map(({ row: extraRow, asset }) => ({
|
extras: sections.filter((section) => section.kind === "extra").map((section) => ({ ...section, rows: extraRows.filter(({ row: extraRow }) => extraRow.sectionId === section.id).map(({ row: extraRow, asset }) => ({
|
||||||
...extraRow,
|
...extraRow,
|
||||||
catalogItems: extraRow.catalogItems.map((reference) => {
|
catalogItems: extraRow.catalogItems.map((reference) => {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export const guideSectionKinds = ["weapon", "artifact", "constellations", "team"
|
|||||||
export type GuideSectionKind = (typeof guideSectionKinds)[number];
|
export type GuideSectionKind = (typeof guideSectionKinds)[number];
|
||||||
|
|
||||||
const percent = z.coerce.number().finite().min(-9999).max(9999);
|
const percent = z.coerce.number().finite().min(-9999).max(9999);
|
||||||
|
const conditionName = z.string().trim().max(120).nullable().optional().transform((value) => value || null);
|
||||||
const catalogKey = z.string().trim().min(1).max(64);
|
const catalogKey = z.string().trim().min(1).max(64);
|
||||||
export const weaponRefinementSchema = z.union([
|
export const weaponRefinementSchema = z.union([
|
||||||
z.number().int().min(1).max(5).transform(String),
|
z.number().int().min(1).max(5).transform(String),
|
||||||
@@ -52,7 +53,7 @@ export const weaponSectionSchema = z.strictObject({
|
|||||||
expectedVersion: z.number().int().positive(),
|
expectedVersion: z.number().int().positive(),
|
||||||
note: z.string().trim().max(2_000).nullable(),
|
note: z.string().trim().max(2_000).nullable(),
|
||||||
groups: z.array(z.strictObject({
|
groups: z.array(z.strictObject({
|
||||||
name: z.string().trim().max(120).nullable().optional().transform((value) => value || null),
|
name: conditionName,
|
||||||
note: z.string().trim().max(2_000).nullable(),
|
note: z.string().trim().max(2_000).nullable(),
|
||||||
rows: z.array(z.strictObject({
|
rows: z.array(z.strictObject({
|
||||||
weaponKey: catalogKey,
|
weaponKey: catalogKey,
|
||||||
@@ -97,6 +98,7 @@ export const artifactSectionSchema = z.strictObject({
|
|||||||
circlet: z.array(z.enum(mainStatOptions.circlet)).max(3),
|
circlet: z.array(z.enum(mainStatOptions.circlet)).max(3),
|
||||||
substats: z.array(z.enum(substatOptions)).max(substatOptions.length),
|
substats: z.array(z.enum(substatOptions)).max(substatOptions.length),
|
||||||
targetGroups: z.array(z.strictObject({
|
targetGroups: z.array(z.strictObject({
|
||||||
|
name: conditionName,
|
||||||
note: z.string().trim().max(2_000).nullable(),
|
note: z.string().trim().max(2_000).nullable(),
|
||||||
rows: z.array(z.strictObject({
|
rows: z.array(z.strictObject({
|
||||||
stat: z.enum(targetStatOptions),
|
stat: z.enum(targetStatOptions),
|
||||||
@@ -125,6 +127,7 @@ export const constellationSectionSchema = z.strictObject({
|
|||||||
expectedVersion: z.number().int().positive(),
|
expectedVersion: z.number().int().positive(),
|
||||||
note: z.string().trim().max(2_000).nullable(),
|
note: z.string().trim().max(2_000).nullable(),
|
||||||
groups: z.array(z.strictObject({
|
groups: z.array(z.strictObject({
|
||||||
|
name: conditionName,
|
||||||
note: z.string().trim().max(2_000).nullable(),
|
note: z.string().trim().max(2_000).nullable(),
|
||||||
rows: constellationRowsSchema,
|
rows: constellationRowsSchema,
|
||||||
})).max(20),
|
})).max(20),
|
||||||
@@ -133,6 +136,7 @@ export const constellationSectionSchema = z.strictObject({
|
|||||||
export const teamSectionSchema = z.strictObject({
|
export const teamSectionSchema = z.strictObject({
|
||||||
expectedVersion: z.number().int().positive(),
|
expectedVersion: z.number().int().positive(),
|
||||||
groups: z.array(z.strictObject({
|
groups: z.array(z.strictObject({
|
||||||
|
name: conditionName,
|
||||||
note: z.string().trim().max(2_000).nullable(),
|
note: z.string().trim().max(2_000).nullable(),
|
||||||
teams: z.array(z.strictObject({
|
teams: z.array(z.strictObject({
|
||||||
title: z.string().trim().min(1).max(160),
|
title: z.string().trim().min(1).max(160),
|
||||||
|
|||||||
Reference in New Issue
Block a user