feat : remove dupe code of codition code

This commit is contained in:
2026-09-12 15:21:43 +07:00 Unverified
parent 56b65b1b39
commit e3eba63071
2 changed files with 238 additions and 224 deletions
@@ -0,0 +1,33 @@
"use client";
import type { ComponentProps } from "react";
import { Trash2Icon } from "lucide-react";
import { DeleteConfirmationDialog } from "@/components/admin/delete-confirmation-dialog";
type DeleteConditionDialogProps = Pick<
ComponentProps<typeof DeleteConfirmationDialog>,
"trigger" | "onConfirm"
> & {
iconOnly?: boolean;
};
export function DeleteConditionDialog({
trigger,
onConfirm,
iconOnly = false,
}: DeleteConditionDialogProps) {
return (
<DeleteConfirmationDialog
trigger={trigger}
triggerTooltip={iconOnly ? "ลบ Condition นี้" : undefined}
title="ลบ Condition นี้?"
description="ข้อมูลทั้งหมดใน Condition นี้จะถูกลบออก"
showSuccessToast
onConfirm={onConfirm}
>
<Trash2Icon data-icon={iconOnly ? undefined : "inline-start"} />
<span className={iconOnly ? "sr-only" : undefined}>ลบ Condition นี้</span>
</DeleteConfirmationDialog>
);
}
+205 -224
View File
@@ -19,7 +19,7 @@ import {
Trash2Icon,
XIcon,
} from "lucide-react";
import { useEffect, useMemo, useState, type ReactNode, type SetStateAction } from "react";
import { useEffect, useMemo, useState, type ComponentProps, type ReactNode, type SetStateAction } from "react";
import { toast } from "sonner";
import {
closestCenter,
@@ -52,6 +52,7 @@ import {
} from "@/app/admin/actions";
import { AutosaveStatus } from "@/components/admin/autosave-status";
import { DeleteConfirmationDialog } from "@/components/admin/delete-confirmation-dialog";
import { DeleteConditionDialog } from "@/components/admin/delete-condition-dialog";
import { MediaUploader } from "@/components/admin/media-uploader";
import { ScrollableNav } from "@/components/public/scrollable-nav";
import { TeamArtifactIcon } from "@/components/public/team-search";
@@ -1256,6 +1257,45 @@ function SortableConditionSwitcher({
);
}
function ConditionControls({
onAdd,
onDuplicate,
onDelete,
...switcherProps
}: ComponentProps<typeof SortableConditionSwitcher> & {
onAdd: () => void;
onDuplicate?: () => void;
onDelete: () => void;
}) {
const { items, activeIndex } = switcherProps;
const atLimit = items.length >= 20;
return (
<div className="flex flex-wrap gap-2">
<SortableConditionSwitcher {...switcherProps} />
<SimpleTooltip text="เพิ่ม Condition">
<Button type="button" size="icon" variant="outline" aria-label="เพิ่ม Condition" disabled={atLimit} onClick={onAdd}>
<PlusIcon />
</Button>
</SimpleTooltip>
{onDuplicate ? (
<SimpleTooltip text="Duplicate Condition">
<Button type="button" size="icon" variant="outline" aria-label="Duplicate Condition" disabled={atLimit || !items[activeIndex]} onClick={onDuplicate}>
<CopyIcon />
</Button>
</SimpleTooltip>
) : null}
{items.length > 1 ? (
<DeleteConditionDialog
trigger={<Button type="button" size="icon" variant="outline" aria-label="ลบ Condition นี้" />}
onConfirm={onDelete}
iconOnly
/>
) : null}
</div>
);
}
function reorderConditions<T extends ConditionNavItem>(
items: T[],
activeIndex: number,
@@ -1390,50 +1430,44 @@ function WeaponEditor({ guide, weapons, characters, initial }: EditorBase) {
onChange={(event) => setNote(event.target.value)}
/>
</Field>
<div className="flex flex-wrap gap-2">
<SortableConditionSwitcher
ariaLabel="เลือกเงื่อนไขอาวุธ"
items={groups}
activeIndex={activeGroupIndex}
onActiveIndexChange={setActiveGroupIndex}
onRename={setRenamingWeaponGroupIndex}
onReorder={(from, to) => {
const reordered = reorderConditions(groups, activeGroupIndex, from, to);
setGroups(reordered.items);
setActiveGroupIndex(reordered.activeIndex);
}}
/>
<Button type="button" variant="outline" disabled={groups.length >= 20} onClick={() => {
<ConditionControls
ariaLabel="เลือกเงื่อนไขอาวุธ"
items={groups}
activeIndex={activeGroupIndex}
onActiveIndexChange={setActiveGroupIndex}
onRename={setRenamingWeaponGroupIndex}
onReorder={(from, to) => {
const reordered = reorderConditions(groups, activeGroupIndex, from, to);
setGroups(reordered.items);
setActiveGroupIndex(reordered.activeIndex);
}}
onAdd={() => {
setGroups([...groups, { clientId: createClientId("weapon-condition"), name: "", note: "", rows: [] }]);
setActiveGroupIndex(groups.length);
}}>
<PlusIcon data-icon="inline-start" />เพิ่ม Condition
</Button>
<Button
type="button"
variant="outline"
disabled={groups.length >= 20 || !groups[activeGroupIndex]}
onClick={() => {
const source = groups[activeGroupIndex];
if (!source) return;
setGroups([
...groups,
{
clientId: createClientId("weapon-condition"),
name: source.name,
note: source.note,
rows: source.rows.map((row) => ({
...row,
clientId: createClientId("weapon"),
})),
},
]);
setActiveGroupIndex(groups.length);
}}
>
<CopyIcon data-icon="inline-start" />Duplicate Condition
</Button>
</div>
}}
onDuplicate={() => {
const source = groups[activeGroupIndex];
if (!source) return;
setGroups([
...groups,
{
clientId: createClientId("weapon-condition"),
name: source.name,
note: source.note,
rows: source.rows.map((row) => ({
...row,
clientId: createClientId("weapon"),
})),
},
]);
setActiveGroupIndex(groups.length);
}}
onDelete={() => {
const next = groups.filter((_, index) => index !== activeGroupIndex);
setGroups(next);
setActiveGroupIndex(Math.min(activeGroupIndex, next.length - 1));
}}
/>
<ConditionRenameDialog
open={renamingWeaponGroupIndex !== null}
fallback={`Condition ${(renamingWeaponGroupIndex ?? 0) + 1}`}
@@ -1704,15 +1738,6 @@ function WeaponEditor({ guide, weapons, characters, initial }: EditorBase) {
<PlusIcon data-icon="inline-start" />
เพิ่มอาวุธ
</Button>
{groups.length > 1 ? (
<Button type="button" variant="ghost" onClick={() => {
const next = groups.filter((_, index) => index !== activeGroupIndex);
setGroups(next);
setActiveGroupIndex(Math.min(activeGroupIndex, next.length - 1));
}}>
<Trash2Icon data-icon="inline-start" />ลบ Condition นี้
</Button>
) : null}
<AutosaveStatus
state={autosave.state}
issues={
@@ -2200,41 +2225,39 @@ function ArtifactEditor({
</CardHeader>
<CardContent>
<FieldGroup>
<div className="flex flex-wrap gap-2">
<SortableConditionSwitcher
ariaLabel="เลือกเงื่อนไขค่าสถานะแนะนำ"
items={recommendedGroups}
activeIndex={activeRecommendedGroupIndex}
onActiveIndexChange={setActiveRecommendedGroupIndex}
onRename={setRenamingRecommendedGroupIndex}
onReorder={(from, to) => {
const reordered = reorderConditions(recommendedGroups, activeRecommendedGroupIndex, from, to);
setRecommendedGroups(reordered.items);
setActiveRecommendedGroupIndex(reordered.activeIndex);
}}
/>
<ConditionRenameDialog
open={renamingRecommendedGroupIndex !== null}
fallback={`Condition ${(renamingRecommendedGroupIndex ?? 0) + 1}`}
value={renamingRecommendedGroupIndex === null ? "" : recommendedGroups[renamingRecommendedGroupIndex]?.name ?? ""}
onOpenChange={(open) => { if (!open) setRenamingRecommendedGroupIndex(null); }}
onChange={(name) => setRecommendedGroups(recommendedGroups.map((group, index) => index === renamingRecommendedGroupIndex ? { ...group, name } : group))}
/>
<SimpleTooltip text="เพิ่ม Condition">
<Button type="button" size="icon" variant="outline" aria-label="เพิ่ม Condition" disabled={recommendedGroups.length >= 20} onClick={() => {
setRecommendedGroups([...recommendedGroups, { clientId: createClientId("recommended-condition"), name: "", note: "", sands: [], goblet: [], circlet: [], substats: [] }]);
setActiveRecommendedGroupIndex(recommendedGroups.length);
}}><PlusIcon /></Button>
</SimpleTooltip>
<SimpleTooltip text="Duplicate Condition">
<Button type="button" size="icon" variant="outline" aria-label="Duplicate Condition" disabled={recommendedGroups.length >= 20} onClick={() => {
const source = recommendedGroups[activeRecommendedGroupIndex];
if (!source) return;
setRecommendedGroups([...recommendedGroups, { clientId: createClientId("recommended-condition"), name: source.name, note: source.note, sands: [...source.sands], goblet: [...source.goblet], circlet: [...source.circlet], substats: [...source.substats] }]);
setActiveRecommendedGroupIndex(recommendedGroups.length);
}}><CopyIcon /></Button>
</SimpleTooltip>
</div>
<ConditionControls
ariaLabel="เลือกเงื่อนไขค่าสถานะแนะนำ"
items={recommendedGroups}
activeIndex={activeRecommendedGroupIndex}
onActiveIndexChange={setActiveRecommendedGroupIndex}
onRename={setRenamingRecommendedGroupIndex}
onReorder={(from, to) => {
const reordered = reorderConditions(recommendedGroups, activeRecommendedGroupIndex, from, to);
setRecommendedGroups(reordered.items);
setActiveRecommendedGroupIndex(reordered.activeIndex);
}}
onAdd={() => {
setRecommendedGroups([...recommendedGroups, { clientId: createClientId("recommended-condition"), name: "", note: "", sands: [], goblet: [], circlet: [], substats: [] }]);
setActiveRecommendedGroupIndex(recommendedGroups.length);
}}
onDuplicate={() => {
const source = recommendedGroups[activeRecommendedGroupIndex];
if (!source) return;
setRecommendedGroups([...recommendedGroups, { clientId: createClientId("recommended-condition"), name: source.name, note: source.note, sands: [...source.sands], goblet: [...source.goblet], circlet: [...source.circlet], substats: [...source.substats] }]);
setActiveRecommendedGroupIndex(recommendedGroups.length);
}}
onDelete={() => {
setRecommendedGroups(recommendedGroups.filter((_, index) => index !== activeRecommendedGroupIndex));
setActiveRecommendedGroupIndex(Math.max(0, activeRecommendedGroupIndex - 1));
}}
/>
<ConditionRenameDialog
open={renamingRecommendedGroupIndex !== null}
fallback={`Condition ${(renamingRecommendedGroupIndex ?? 0) + 1}`}
value={renamingRecommendedGroupIndex === null ? "" : recommendedGroups[renamingRecommendedGroupIndex]?.name ?? ""}
onOpenChange={(open) => { if (!open) setRenamingRecommendedGroupIndex(null); }}
onChange={(name) => setRecommendedGroups(recommendedGroups.map((group, index) => index === renamingRecommendedGroupIndex ? { ...group, name } : group))}
/>
<Field>
<FieldLabel htmlFor={`recommended-condition-note-${recommendedGroups[activeRecommendedGroupIndex]?.clientId}`}>Condition note (optional)</FieldLabel>
<Textarea id={`recommended-condition-note-${recommendedGroups[activeRecommendedGroupIndex]?.clientId}`} value={recommendedGroups[activeRecommendedGroupIndex]?.note ?? ""} onChange={(event) => setRecommendedGroups(recommendedGroups.map((group, index) => index === activeRecommendedGroupIndex ? { ...group, note: event.target.value } : group))} />
@@ -2278,12 +2301,6 @@ function ArtifactEditor({
elementIconUrls={elementIconUrls}
priorityColors
/>
{recommendedGroups.length > 1 ? (
<Button type="button" variant="ghost" onClick={() => {
setRecommendedGroups(recommendedGroups.filter((_, index) => index !== activeRecommendedGroupIndex));
setActiveRecommendedGroupIndex(Math.max(0, activeRecommendedGroupIndex - 1));
}}><Trash2Icon data-icon="inline-start" />ลบ Condition นี้</Button>
) : null}
</FieldGroup>
</CardContent>
</Card>
@@ -2298,41 +2315,39 @@ function ArtifactEditor({
<FieldGroup>
<FieldSet>
<FieldLegend>Target Stats</FieldLegend>
<div className="flex flex-wrap gap-2">
<SortableConditionSwitcher
ariaLabel="เลือกเงื่อนไขค่าสถานะเป้าหมาย"
items={targetGroups}
activeIndex={activeTargetGroupIndex}
onActiveIndexChange={setActiveTargetGroupIndex}
onRename={setRenamingTargetGroupIndex}
onReorder={(from, to) => {
const reordered = reorderConditions(targetGroups, activeTargetGroupIndex, from, to);
setTargetGroups(reordered.items);
setActiveTargetGroupIndex(reordered.activeIndex);
}}
/>
<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))}
/>
<SimpleTooltip text="เพิ่ม Condition">
<Button type="button" size="icon" variant="outline" aria-label="เพิ่ม Condition" disabled={targetGroups.length >= 20} onClick={() => {
setTargetGroups([...targetGroups, { clientId: createClientId("target-condition"), name: "", note: "", rows: targetStatDefaults.map((target) => ({ ...target })) }]);
setActiveTargetGroupIndex(targetGroups.length);
}}><PlusIcon /></Button>
</SimpleTooltip>
<SimpleTooltip text="Duplicate Condition">
<Button type="button" size="icon" variant="outline" aria-label="Duplicate Condition" disabled={targetGroups.length >= 20} onClick={() => {
const source = targetGroups[activeTargetGroupIndex];
if (!source) return;
setTargetGroups([...targetGroups, { clientId: createClientId("target-condition"), name: source.name, note: source.note, rows: source.rows.map((row) => ({ ...row })) }]);
setActiveTargetGroupIndex(targetGroups.length);
}}><CopyIcon /></Button>
</SimpleTooltip>
</div>
<ConditionControls
ariaLabel="เลือกเงื่อนไขค่าสถานะเป้าหมาย"
items={targetGroups}
activeIndex={activeTargetGroupIndex}
onActiveIndexChange={setActiveTargetGroupIndex}
onRename={setRenamingTargetGroupIndex}
onReorder={(from, to) => {
const reordered = reorderConditions(targetGroups, activeTargetGroupIndex, from, to);
setTargetGroups(reordered.items);
setActiveTargetGroupIndex(reordered.activeIndex);
}}
onAdd={() => {
setTargetGroups([...targetGroups, { clientId: createClientId("target-condition"), name: "", note: "", rows: targetStatDefaults.map((target) => ({ ...target })) }]);
setActiveTargetGroupIndex(targetGroups.length);
}}
onDuplicate={() => {
const source = targetGroups[activeTargetGroupIndex];
if (!source) return;
setTargetGroups([...targetGroups, { clientId: createClientId("target-condition"), name: source.name, note: source.note, rows: source.rows.map((row) => ({ ...row })) }]);
setActiveTargetGroupIndex(targetGroups.length);
}}
onDelete={() => {
setTargetGroups(targetGroups.filter((_, index) => index !== activeTargetGroupIndex));
setActiveTargetGroupIndex(Math.max(0, activeTargetGroupIndex - 1));
}}
/>
<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))}
/>
<Field>
<FieldLabel htmlFor={`target-condition-note-${targetGroups[activeTargetGroupIndex]?.clientId}`}>Condition note (optional)</FieldLabel>
<Textarea id={`target-condition-note-${targetGroups[activeTargetGroupIndex]?.clientId}`} value={targetGroups[activeTargetGroupIndex]?.note ?? ""} onChange={(event) => setTargetGroups(targetGroups.map((group, index) => index === activeTargetGroupIndex ? { ...group, note: event.target.value } : group))} />
@@ -2379,12 +2394,6 @@ function ArtifactEditor({
กรอกเฉพาะค่าเป็นตัวเลข เปอร์เซ็นต์ หรือข้อความ เช่น -%
หากไม่กรอกค่า ระบบจะไม่แสดงส่วนค่าสถานะเป้าหมาย
</FieldDescription>
{targetGroups.length > 1 ? (
<Button type="button" variant="ghost" onClick={() => {
setTargetGroups(targetGroups.filter((_, index) => index !== activeTargetGroupIndex));
setActiveTargetGroupIndex(Math.max(0, activeTargetGroupIndex - 1));
}}><Trash2Icon data-icon="inline-start" />ลบ Condition นี้</Button>
) : null}
</FieldSet>
</FieldGroup>
</CardContent>
@@ -2608,40 +2617,34 @@ function ConstellationEditor({
onChange={(event) => setNote(event.target.value)}
/>
</Field>
<div className="flex flex-wrap gap-2">
<SortableConditionSwitcher
ariaLabel="เลือกเงื่อนไขกลุ่มดาว"
items={groups}
activeIndex={activeConstellationGroupIndex}
onActiveIndexChange={setActiveConstellationGroupIndex}
onRename={setRenamingConstellationGroupIndex}
onReorder={(from, to) => {
const reordered = reorderConditions(groups, activeConstellationGroupIndex, from, to);
setGroups(reordered.items);
setActiveConstellationGroupIndex(reordered.activeIndex);
}}
/>
<Button
type="button"
variant="outline"
disabled={groups.length >= 20}
onClick={() => {
setGroups([
...groups,
{
clientId: createClientId("constellation-condition"),
name: "",
note: "",
rows: makeRows(),
},
]);
setActiveConstellationGroupIndex(groups.length);
}}
>
<PlusIcon data-icon="inline-start" />
เพิ่ม Condition
</Button>
</div>
<ConditionControls
ariaLabel="เลือกเงื่อนไขกลุ่มดาว"
items={groups}
activeIndex={activeConstellationGroupIndex}
onActiveIndexChange={setActiveConstellationGroupIndex}
onRename={setRenamingConstellationGroupIndex}
onReorder={(from, to) => {
const reordered = reorderConditions(groups, activeConstellationGroupIndex, from, to);
setGroups(reordered.items);
setActiveConstellationGroupIndex(reordered.activeIndex);
}}
onAdd={() => {
setGroups([
...groups,
{
clientId: createClientId("constellation-condition"),
name: "",
note: "",
rows: makeRows(),
},
]);
setActiveConstellationGroupIndex(groups.length);
}}
onDelete={() => {
setGroups(groups.filter((_, index) => index !== activeConstellationGroupIndex));
setActiveConstellationGroupIndex(Math.max(0, activeConstellationGroupIndex - 1));
}}
/>
<ConditionRenameDialog
open={renamingConstellationGroupIndex !== null}
fallback={`Condition ${(renamingConstellationGroupIndex ?? 0) + 1}`}
@@ -2658,26 +2661,6 @@ function ConstellationEditor({
<CardDescription>
ใช้ note เพื่ออธิบายอาวุธ ทีม หรือเงื่อนไขที่ใช้เปรียบเทียบ
</CardDescription>
{groups.length > 1 ? (
<CardAction>
<DeleteConfirmationDialog
trigger={
<Button type="button" variant="ghost" size="icon-sm" />
}
title={`ลบ Condition ${groupIndex + 1}?`}
description="เปอร์เซ็นต์กลุ่มดาวทั้งหมดในเงื่อนไขนี้จะถูกลบออก"
onConfirm={() => {
setGroups(groups.filter((item) => item.clientId !== group.clientId));
setActiveConstellationGroupIndex(Math.max(0, groupIndex - 1));
}}
>
<Trash2Icon />
<span className="sr-only">
ลบ Condition {groupIndex + 1}
</span>
</DeleteConfirmationDialog>
</CardAction>
) : null}
</CardHeader>
<CardContent className="flex flex-col gap-4">
<Field>
@@ -3292,39 +3275,30 @@ function TeamEditor({
</CardDescription>
</CardHeader>
<CardContent className="flex flex-col gap-4">
<div className="flex flex-wrap gap-2">
<SortableConditionSwitcher
ariaLabel="เลือกเงื่อนไข Team"
items={teamGroups}
activeIndex={activeTeamGroupIndex}
onActiveIndexChange={(nextIndex) => {
const group = teamGroups[nextIndex];
if (!group) return;
setActiveTeamGroupIndex(nextIndex);
setSelectedTeamIds(new Set());
setSourceTeamId(group.teams[0]?.clientId ?? "");
}}
onRename={setRenamingTeamGroupIndex}
onReorder={(from, to) => {
const reordered = reorderConditions(teamGroups, activeTeamGroupIndex, from, to);
setTeamGroups(reordered.items);
setActiveTeamGroupIndex(reordered.activeIndex);
}}
/>
<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={() => {
<ConditionControls
ariaLabel="เลือกเงื่อนไข Team"
items={teamGroups}
activeIndex={activeTeamGroupIndex}
onActiveIndexChange={(nextIndex) => {
const group = teamGroups[nextIndex];
if (!group) return;
setActiveTeamGroupIndex(nextIndex);
setSelectedTeamIds(new Set());
setSourceTeamId(group.teams[0]?.clientId ?? "");
}}
onRename={setRenamingTeamGroupIndex}
onReorder={(from, to) => {
const reordered = reorderConditions(teamGroups, activeTeamGroupIndex, from, to);
setTeamGroups(reordered.items);
setActiveTeamGroupIndex(reordered.activeIndex);
}}
onAdd={() => {
setTeamGroups([...teamGroups, { clientId: createClientId("team-condition"), name: "", note: "", teams: [] }]);
setActiveTeamGroupIndex(teamGroups.length);
setSelectedTeamIds(new Set());
setSourceTeamId("");
}}><PlusIcon data-icon="inline-start" />เพิ่ม Condition</Button>
<Button type="button" variant="outline" disabled={teamGroups.length >= 20} onClick={() => {
}}
onDuplicate={() => {
const source = teamGroups[activeTeamGroupIndex];
if (!source) return;
const copiedTeams = source.teams.map((team) => ({ ...team, clientId: createClientId("team"), members: team.members.map((member) => ({ ...member })) }));
@@ -3332,17 +3306,24 @@ function TeamEditor({
setActiveTeamGroupIndex(teamGroups.length);
setSelectedTeamIds(new Set());
setSourceTeamId(copiedTeams[0]?.clientId ?? "");
}}><CopyIcon data-icon="inline-start" />Duplicate Condition</Button>
</div>
}}
onDelete={() => {
setTeamGroups(teamGroups.filter((_, index) => index !== activeTeamGroupIndex));
setActiveTeamGroupIndex(Math.max(0, activeTeamGroupIndex - 1));
setSelectedTeamIds(new Set());
}}
/>
<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))}
/>
<Field>
<FieldLabel htmlFor={`team-condition-note-${teamGroups[activeTeamGroupIndex]?.clientId}`}>Condition note (optional)</FieldLabel>
<Textarea id={`team-condition-note-${teamGroups[activeTeamGroupIndex]?.clientId}`} value={teamGroups[activeTeamGroupIndex]?.note ?? ""} onChange={(event) => setTeamGroups(teamGroups.map((group, index) => index === activeTeamGroupIndex ? { ...group, note: event.target.value } : group))} />
</Field>
{teamGroups.length > 1 ? <Button className="self-start" type="button" variant="ghost" onClick={() => {
setTeamGroups(teamGroups.filter((_, index) => index !== activeTeamGroupIndex));
setActiveTeamGroupIndex(Math.max(0, activeTeamGroupIndex - 1));
setSelectedTeamIds(new Set());
}}><Trash2Icon data-icon="inline-start" />ลบ Condition นี้</Button> : null}
<div className="flex min-w-0 flex-wrap items-center gap-2 rounded-lg border bg-muted/30 p-3">
<Checkbox
checked={selectedTeamIds.size === teams.length && teams.length > 0}