"use client" import * as React from "react" import { useReactTable, getCoreRowModel, getSortedRowModel, getFilteredRowModel, getPaginationRowModel } from "@tanstack/react-table" import { DataTableDetail } from "@/components/data-table/data-table-detail" import { DataTableAdvancedToolbarDetail } from "@/components/data-table/data-table-advanced-toolbar-detail" import { DragDropTable } from "@/lib/docu-list-rule/number-type-configs/table/drag-drop-table" import type { DataTableAdvancedFilterField, DataTableRowAction } from "@/types/table" import { Sheet, SheetContent, } from "@/components/ui/sheet" import { getDocumentClassSubOptions, updateDocumentClassOption } from "@/lib/docu-list-rule/document-class/service" import { getColumns } from "@/lib/docu-list-rule/document-class/table/document-class-options-table-columns" import { DocumentClassOptionEditSheet } from "@/lib/docu-list-rule/document-class/table/document-class-option-edit-sheet" import { DeleteDocumentClassOptionDialog } from "@/lib/docu-list-rule/document-class/table/delete-document-class-option-dialog" import { DocumentClassOptionsTableToolbarActions } from "@/lib/docu-list-rule/document-class/table/document-class-options-table-toolbar" import { documentClasses, documentClassOptions } from "@/db/schema/docu-list-rule" import { DragEndEvent } from '@dnd-kit/core' import { arrayMove } from '@dnd-kit/sortable' import { toast } from "sonner" type DocumentClassOption = typeof documentClassOptions.$inferSelect interface DocumentClassOptionsDetailSheetProps { open: boolean onOpenChange: (open: boolean) => void documentClass: typeof documentClasses.$inferSelect | null onSuccess?: () => void promises?: Promise<[{ data: DocumentClassOption[]; pageCount: number }]> } export function DocumentClassOptionsDetailSheet({ open, onOpenChange, documentClass, promises, }: DocumentClassOptionsDetailSheetProps) { const [rowAction, setRowAction] = React.useState | null>(null) const [rawData, setRawData] = React.useState<{ data: DocumentClassOption[]; pageCount: number }>({ data: [], pageCount: 0 }) React.useEffect(() => { if (promises) { promises.then(([result]) => { setRawData(result) }) } else if (open && documentClass) { // fallback: 클라이언트에서 직접 fetch (CSR) (async () => { try { const result = await getDocumentClassSubOptions(documentClass.id) if (result.success && result.data) { setRawData({ data: result.data, pageCount: 1 }) } } catch (error) { console.error("Error refreshing data:", error) } })() } }, [promises, open, documentClass]) const refreshData = React.useCallback(async () => { if (!documentClass) return try { const result = await getDocumentClassSubOptions(documentClass.id, { page: 1, perPage: 10, sort: [{ id: "sdq", desc: false }], }) if (result.success && result.data) { setRawData({ data: result.data, pageCount: 1 }) } } catch (error) { console.error("Error refreshing data:", error) } }, [documentClass]) const columns = React.useMemo(() => getColumns({ setRowAction }), [setRowAction]) // 고급 필터 필드 설정 const advancedFilterFields: DataTableAdvancedFilterField[] = [ { id: "optionCode", label: "코드", type: "text" }, { id: "description", label: "설명", type: "text" }, { id: "createdAt", label: "생성일", type: "date" }, ] const table = useReactTable({ data: rawData.data, columns, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), getFilteredRowModel: getFilteredRowModel(), getPaginationRowModel: getPaginationRowModel(), initialState: { sorting: [{ id: "sdq", desc: false }], pagination: { pageSize: 10, }, }, getRowId: (originalRow) => String(originalRow.id), }) // 드래그 종료 핸들러 const handleDragEnd = React.useCallback(async (event: DragEndEvent) => { const { active, over } = event console.log("Drag end event:", { active, over }) if (active.id !== over?.id) { const oldIndex = rawData.data.findIndex((item) => String(item.id) === active.id) const newIndex = rawData.data.findIndex((item) => String(item.id) === over?.id) console.log("Indices:", { oldIndex, newIndex }) if (oldIndex !== -1 && newIndex !== -1) { const reorderedData = arrayMove(rawData.data, oldIndex, newIndex) // 새로운 순서로 sdq 값 업데이트 const updatedOptions = reorderedData.map((item, index) => ({ ...item, sdq: index + 1 })) // 로컬 상태 먼저 업데이트 setRawData(prev => ({ ...prev, data: updatedOptions })) // 서버에 순서 업데이트 (Combo Box Settings와 같은 방식) try { // 모든 항목을 임시 값으로 먼저 업데이트 for (let i = 0; i < updatedOptions.length; i++) { const option = updatedOptions[i] await updateDocumentClassOption({ id: option.id, sdq: -(i + 1), // 임시 음수 값 }) } // 최종 순서로 업데이트 for (const option of updatedOptions) { await updateDocumentClassOption({ id: option.id, sdq: option.sdq, }) } toast.success("순서가 성공적으로 변경되었습니다.") } catch (error) { console.error("Error updating order:", error) toast.error("순서 변경 중 오류가 발생했습니다.") // 에러 시 원래 데이터로 복원 await refreshData() } } } }, [rawData.data, refreshData]) if (!documentClass) return null return (

{documentClass.value} 옵션 관리

{documentClass.value}의 Document Class 옵션들을 관리합니다.

setRowAction(null)} options={rowAction?.row.original ? [rowAction?.row.original] : []} showTrigger={false} onSuccess={() => { rowAction?.row.toggleSelected(false) refreshData() }} /> setRowAction(null)} data={rowAction?.row.original ?? null} onSuccess={refreshData} />
) }