From e3eba63071b721ff6cdd865a02a3c71efde5348d Mon Sep 17 00:00:00 2001 From: gunshiz Date: Sat, 12 Sep 2026 15:21:43 +0700 Subject: [PATCH] feat : remove dupe code of codition code --- components/admin/delete-condition-dialog.tsx | 33 ++ components/admin/guide-section-editor.tsx | 429 +++++++++---------- 2 files changed, 238 insertions(+), 224 deletions(-) create mode 100644 components/admin/delete-condition-dialog.tsx diff --git a/components/admin/delete-condition-dialog.tsx b/components/admin/delete-condition-dialog.tsx new file mode 100644 index 0000000..c9a3d82 --- /dev/null +++ b/components/admin/delete-condition-dialog.tsx @@ -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, + "trigger" | "onConfirm" +> & { + iconOnly?: boolean; +}; + +export function DeleteConditionDialog({ + trigger, + onConfirm, + iconOnly = false, +}: DeleteConditionDialogProps) { + return ( + + + ลบ Condition นี้ + + ); +} diff --git a/components/admin/guide-section-editor.tsx b/components/admin/guide-section-editor.tsx index 5caf0c1..84f3af1 100644 --- a/components/admin/guide-section-editor.tsx +++ b/components/admin/guide-section-editor.tsx @@ -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 & { + onAdd: () => void; + onDuplicate?: () => void; + onDelete: () => void; +}) { + const { items, activeIndex } = switcherProps; + const atLimit = items.length >= 20; + + return ( +
+ + + + + {onDuplicate ? ( + + + + ) : null} + {items.length > 1 ? ( + } + onConfirm={onDelete} + iconOnly + /> + ) : null} +
+ ); +} + function reorderConditions( items: T[], activeIndex: number, @@ -1390,50 +1430,44 @@ function WeaponEditor({ guide, weapons, characters, initial }: EditorBase) { onChange={(event) => setNote(event.target.value)} /> -
- { - const reordered = reorderConditions(groups, activeGroupIndex, from, to); - setGroups(reordered.items); - setActiveGroupIndex(reordered.activeIndex); - }} - /> - - -
+ }} + 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)); + }} + /> เพิ่มอาวุธ - {groups.length > 1 ? ( - - ) : null} -
- { - const reordered = reorderConditions(recommendedGroups, activeRecommendedGroupIndex, from, to); - setRecommendedGroups(reordered.items); - setActiveRecommendedGroupIndex(reordered.activeIndex); - }} - /> - { if (!open) setRenamingRecommendedGroupIndex(null); }} - onChange={(name) => setRecommendedGroups(recommendedGroups.map((group, index) => index === renamingRecommendedGroupIndex ? { ...group, name } : group))} - /> - - - - - - -
+ { + 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)); + }} + /> + { if (!open) setRenamingRecommendedGroupIndex(null); }} + onChange={(name) => setRecommendedGroups(recommendedGroups.map((group, index) => index === renamingRecommendedGroupIndex ? { ...group, name } : group))} + /> Condition note (optional)