"use client"; import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { LoadingSpinner } from "@/components/common/LoadingSpinner"; import { CodeFormModal } from "./CodeFormModal"; import { SortableCodeItem } from "./SortableCodeItem"; import { AlertModal } from "@/components/common/AlertModal"; import { Search, Plus } from "lucide-react"; import { cn } from "@/lib/utils"; import { useCodes, useDeleteCode, useReorderCodes } from "@/hooks/queries/useCodes"; import type { CodeInfo } from "@/types/commonCode"; // Drag and Drop import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, DragOverlay, type DragStartEvent, type DragEndEvent, } from "@dnd-kit/core"; import { arrayMove, SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy, } from "@dnd-kit/sortable"; interface CodeDetailPanelProps { categoryCode: string; } export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) { // React Query로 코드 데이터 관리 const { data: codes = [], isLoading, error } = useCodes(categoryCode); const deleteCodeMutation = useDeleteCode(); const reorderCodesMutation = useReorderCodes(); // 로컬 상태 const [searchTerm, setSearchTerm] = useState(""); const [showActiveOnly, setShowActiveOnly] = useState(false); const [showFormModal, setShowFormModal] = useState(false); const [editingCode, setEditingCode] = useState(null); const [showDeleteModal, setShowDeleteModal] = useState(false); const [deletingCode, setDeletingCode] = useState(null); // 드래그 상태 const [activeId, setActiveId] = useState(null); // Drag and Drop 센서 const sensors = useSensors( useSensor(PointerSensor), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates, }), ); // 필터링된 코드 목록 const filteredCodes = codes.filter((code) => { const matchesSearch = code.code_name.toLowerCase().includes(searchTerm.toLowerCase()) || code.code_value.toLowerCase().includes(searchTerm.toLowerCase()); const matchesActive = !showActiveOnly || code.is_active === "Y"; return matchesSearch && matchesActive; }); // 새 코드 생성 const handleNewCode = () => { setEditingCode(null); setShowFormModal(true); }; // 코드 수정 const handleEditCode = (code: CodeInfo) => { setEditingCode(code); setShowFormModal(true); }; // 코드 삭제 확인 const handleDeleteCode = (code: CodeInfo) => { setDeletingCode(code); setShowDeleteModal(true); }; // 코드 삭제 실행 const handleConfirmDelete = async () => { if (!deletingCode) return; try { await deleteCodeMutation.mutateAsync({ categoryCode, codeValue: deletingCode.code_value, }); setShowDeleteModal(false); setDeletingCode(null); } catch (error) { console.error("코드 삭제 실패:", error); } }; // 드래그 시작 핸들러 const handleDragStart = (event: DragStartEvent) => { setActiveId(event.active.id as string); }; // 드래그 앤 드롭 처리 const handleDragEnd = async (event: DragEndEvent) => { setActiveId(null); const { active, over } = event; if (over && active.id !== over.id) { const oldIndex = filteredCodes.findIndex((code) => code.code_value === active.id); const newIndex = filteredCodes.findIndex((code) => code.code_value === over.id); const newOrder = arrayMove(filteredCodes, oldIndex, newIndex); // 순서 업데이트를 위한 데이터 준비 const reorderData = newOrder.map((code, index) => ({ codeValue: code.code_value, sortOrder: index + 1, })); try { await reorderCodesMutation.mutateAsync({ categoryCode, codes: reorderData, }); } catch (error) { console.error("코드 순서 변경 실패:", error); } } }; if (!categoryCode) { return (

카테고리를 선택하세요

); } if (error) { return (

코드를 불러오는 중 오류가 발생했습니다.

); } return (
{/* 검색 및 필터 */}
{/* 검색 */}
setSearchTerm(e.target.value)} className="pl-10" />
{/* 활성 필터 */}
setShowActiveOnly(e.target.checked)} className="rounded border-gray-300" />
{/* 새 코드 버튼 */}
{/* 코드 목록 */}
{isLoading ? (
) : filteredCodes.length === 0 ? (
{searchTerm ? "검색 결과가 없습니다." : "코드가 없습니다."}
) : (
code.code_value)} strategy={verticalListSortingStrategy} >
{filteredCodes.map((code) => ( handleEditCode(code)} onDelete={() => handleDeleteCode(code)} /> ))}
{activeId ? (
{(() => { const activeCode = filteredCodes.find((code) => code.code_value === activeId); if (!activeCode) return null; return (

{activeCode.code_name}

{activeCode.is_active === "Y" ? "활성" : "비활성"}

{activeCode.code_value}

{activeCode.description && (

{activeCode.description}

)}
); })()}
) : null}
)}
{/* 코드 폼 모달 */} {showFormModal && ( { setShowFormModal(false); setEditingCode(null); }} categoryCode={categoryCode} editingCode={editingCode} /> )} {/* 삭제 확인 모달 */} {showDeleteModal && ( setShowDeleteModal(false)} type="error" title="코드 삭제" message="정말로 이 코드를 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다." confirmText="삭제" onConfirm={handleConfirmDelete} /> )}
); }