"use client"; import { useState, useEffect } 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 { useCommonCode } from "@/hooks/useCommonCode"; // import { useMultiLang } from "@/hooks/useMultiLang"; // 무한 루프 방지를 위해 임시 제거 import { CodeFormModal } from "./CodeFormModal"; import { AlertModal } from "@/components/common/AlertModal"; import { Search, Plus, Edit, Trash2, GripVertical } from "lucide-react"; import { cn } from "@/lib/utils"; import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, DragEndEvent, } from "@dnd-kit/core"; import { arrayMove, SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy, } from "@dnd-kit/sortable"; import { useSortable } from "@dnd-kit/sortable"; import { CSS } from "@dnd-kit/utilities"; interface CodeDetailPanelProps { categoryCode: string; } // 드래그 가능한 코드 아이템 컴포넌트 interface SortableCodeItemProps { code: any; onEdit: (code: any) => void; onDelete: (code: any) => void; } function SortableCodeItem({ code, onEdit, onDelete }: SortableCodeItemProps) { const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: `${code.code_category}-${code.code_value}`, }); const style = { transform: CSS.Transform.toString(transform), transition, }; return (
{/* 드래그 핸들 */}
{code.code_name} {code.is_active === "Y" ? ( 활성 ) : ( 비활성 )}
{code.code_value} {code.code_name_eng && ({code.code_name_eng})}
{code.description &&

{code.description}

}
); } export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) { // const { getText } = useMultiLang(); // 무한 루프 방지를 위해 임시 제거 const { codes, setCodes, codesLoading, codesError, fetchCodes, createCode, updateCode, deleteCode, reorderCodes } = useCommonCode(); // 드래그앤드롭 센서 설정 const sensors = useSensors( useSensor(PointerSensor), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates, }), ); // 카테고리 변경 시 코드 조회 useEffect(() => { if (categoryCode) { console.log("🔍 카테고리 변경됨, 코드 조회:", categoryCode); fetchCodes(categoryCode); } }, [categoryCode, fetchCodes]); // 로컬 상태 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<{ categoryCode: string; codeValue: string }>({ categoryCode: "", codeValue: "", }); // 검색 및 활성 상태 필터링 const filteredCodes = codes.filter((code) => { // 검색 조건 const matchesSearch = code.code_name.toLowerCase().includes(searchTerm.toLowerCase()) || code.code_value.toLowerCase().includes(searchTerm.toLowerCase()); // 활성 상태 필터 조건 const matchesActiveFilter = showActiveOnly ? code.is_active : true; return matchesSearch && matchesActiveFilter; }); // 코드 생성 핸들러 const handleCreateCode = () => { if (!categoryCode) return; setEditingCode(null); // 새 코드 모드 setShowFormModal(true); }; // 코드 수정 핸들러 const handleEditCode = (codeValue: string) => { console.log("🔧 코드 수정 핸들러 호출:", { categoryCode, codeValue }); const codeToEdit = codes.find((code) => code.code_value === codeValue); console.log("📋 수정할 코드 데이터:", codeToEdit); setEditingCode(codeToEdit || null); // 전체 코드 객체 전달 setShowFormModal(true); }; // 코드 삭제 핸들러 const handleDeleteCode = (codeValue: string) => { setDeletingCode({ categoryCode, codeValue }); setShowDeleteModal(true); }; // 삭제 확인 핸들러 const handleConfirmDelete = async () => { if (!deletingCode.categoryCode || !deletingCode.codeValue) return; try { await deleteCode(deletingCode.categoryCode, deletingCode.codeValue); setShowDeleteModal(false); setDeletingCode({ categoryCode: "", codeValue: "" }); } catch (error) { console.error("코드 삭제 오류:", error); // 에러 처리는 useCommonCode 훅에서 처리됨 } }; // 드래그 종료 핸들러 const handleDragEnd = async (event: DragEndEvent) => { const { active, over } = event; if (!over || active.id === over.id) { return; } const activeIndex = filteredCodes.findIndex((code) => `${code.code_category}-${code.code_value}` === active.id); const overIndex = filteredCodes.findIndex((code) => `${code.code_category}-${code.code_value}` === over.id); if (activeIndex !== overIndex) { // 전체 codes 배열에서 현재 카테고리의 코드들을 찾아서 재정렬 const currentCategoryCodes = codes.filter((code) => code.code_category === categoryCode); const otherCategoryCodes = codes.filter((code) => code.code_category !== categoryCode); // 현재 카테고리 코드들의 순서를 변경 const reorderedCategoryCodes = arrayMove(currentCategoryCodes, activeIndex, overIndex); // 전체 codes 배열 업데이트 const newCodesArray = [...otherCategoryCodes, ...reorderedCategoryCodes]; setCodes(newCodesArray); try { // 서버에 순서 변경 요청 console.log("🔄 코드 순서 변경:", { categoryCode, from: activeIndex, to: overIndex, reorderedCodes: reorderedCategoryCodes.map((code) => code.code_value), }); // 백엔드 API 호출 - 실제 DB에 순서 저장 await reorderCodes( categoryCode, reorderedCategoryCodes.map((code, index) => ({ codeValue: code.code_value, sortOrder: index + 1, })), ); } catch (error) { console.error("순서 변경 실패:", error); // 실패 시 원래 순서로 복원 fetchCodes(categoryCode); } } }; // 카테고리가 선택되지 않은 경우 if (!categoryCode) { return (

카테고리를 선택하세요

왼쪽에서 카테고리를 선택하면 해당 코드 목록이 표시됩니다.

); } // 에러 상태 if (codesError) { return (

❌ {codesError}

); } return (
{/* 검색 및 추가 버튼 */}
setSearchTerm(e.target.value)} className="pl-10" />
{/* 활성 상태 필터 토글 */}
{/* 코드 목록 (드래그앤드롭) */}
{codesLoading ? (

코드를 불러오는 중...

) : filteredCodes.length === 0 ? (

코드가 없습니다.

) : ( `${code.code_category}-${code.code_value}`)} strategy={verticalListSortingStrategy} >
{filteredCodes.map((code) => ( handleEditCode(code.code_value)} onDelete={(code) => handleDeleteCode(code.code_value)} /> ))}
)}
{/* 코드 폼 모달 */} {showFormModal && ( { setShowFormModal(false); setEditingCode(null); // 모달 닫을 때 편집 상태 초기화 }} categoryCode={categoryCode} editingCode={editingCode} // 전체 코드 객체 전달 codes={codes} // 현재 코드 목록 전달 onCreateCode={createCode} // 코드 생성 함수 전달 onUpdateCode={updateCode} // 코드 수정 함수 전달 /> )} {/* 삭제 확인 모달 */} {showDeleteModal && ( setShowDeleteModal(false)} onConfirm={handleConfirmDelete} type="error" title="삭제 확인" message="이 코드를 삭제하시겠습니까?" confirmText="삭제" /> )}
); }