"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 { useDeleteCode, useReorderCodes } from "@/hooks/queries/useCodes"; import { useCodesInfinite } from "@/hooks/queries/useCodesInfinite"; import type { CodeInfo } from "@/types/commonCode"; // Drag and Drop import { DndContext, DragOverlay } from "@dnd-kit/core"; import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable"; import { useDragAndDrop } from "@/hooks/useDragAndDrop"; import { useSearchAndFilter } from "@/hooks/useSearchAndFilter"; interface CodeDetailPanelProps { categoryCode: string; } export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) { // 검색 및 필터 상태 (먼저 선언) const [searchTerm, setSearchTerm] = useState(""); const [showActiveOnly, setShowActiveOnly] = useState(false); // React Query로 코드 데이터 관리 (무한 스크롤) const { data: codes = [], isLoading, error, handleScroll, isFetchingNextPage, hasNextPage, } = useCodesInfinite(categoryCode, { search: searchTerm || undefined, active: showActiveOnly || undefined, }); const deleteCodeMutation = useDeleteCode(); const reorderCodesMutation = useReorderCodes(); // 드래그앤드롭을 위해 필터링된 코드 목록 사용 const { filteredItems: filteredCodes } = useSearchAndFilter(codes, { searchFields: ["code_name", "code_value"], }); // 모달 상태 const [showFormModal, setShowFormModal] = useState(false); const [editingCode, setEditingCode] = useState(null); const [showDeleteModal, setShowDeleteModal] = useState(false); const [deletingCode, setDeletingCode] = useState(null); // 드래그 앤 드롭 훅 사용 const dragAndDrop = useDragAndDrop({ items: filteredCodes, onReorder: async (reorderedItems) => { await reorderCodesMutation.mutateAsync({ categoryCode, codes: reorderedItems.map((item) => ({ codeValue: item.id, sortOrder: item.sortOrder, })), }); }, getItemId: (code: CodeInfo) => code.codeValue || code.code_value, }); // 새 코드 생성 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.codeValue || deletingCode.code_value, }); setShowDeleteModal(false); setDeletingCode(null); } catch (error) { console.error("코드 삭제 실패:", error); } }; // 드래그 앤 드롭 로직은 useDragAndDrop 훅에서 처리 if (!categoryCode) { return (

카테고리를 선택하세요

); } if (error) { return (

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

); } return (
{/* 검색 및 액션 */}
{/* 검색 + 버튼 */}
setSearchTerm(e.target.value)} className="h-10 pl-10 text-sm" />
{/* 활성 필터 */}
setShowActiveOnly(e.target.checked)} className="h-4 w-4 rounded border-input" />
{/* 코드 목록 (무한 스크롤) */}
{isLoading ? (
) : filteredCodes.length === 0 ? (

{codes.length === 0 ? "코드가 없습니다." : "검색 결과가 없습니다."}

) : ( <> code.codeValue || code.code_value)} strategy={verticalListSortingStrategy} > {filteredCodes.map((code, index) => ( handleEditCode(code)} onDelete={() => handleDeleteCode(code)} /> ))} {dragAndDrop.activeItem ? (
{(() => { const activeCode = dragAndDrop.activeItem; if (!activeCode) return null; return (

{activeCode.codeName || activeCode.code_name}

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

{activeCode.codeValue || activeCode.code_value}

{activeCode.description && (

{activeCode.description}

)}
); })()}
) : null}
{/* 무한 스크롤 로딩 인디케이터 */} {isFetchingNextPage && (
코드를 더 불러오는 중...
)} {/* 모든 코드 로드 완료 메시지 */} {!hasNextPage && codes.length > 0 && (
모든 코드를 불러왔습니다.
)} )}
{/* 코드 폼 모달 */} {showFormModal && ( { setShowFormModal(false); setEditingCode(null); }} categoryCode={categoryCode} editingCode={editingCode} codes={codes} /> )} {/* 삭제 확인 모달 */} {showDeleteModal && ( setShowDeleteModal(false)} type="error" title="코드 삭제" message="정말로 이 코드를 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다." confirmText="삭제" onConfirm={handleConfirmDelete} /> )}
); }