From 50ae0b8f02c034e60d4cbb504620dfa1575a836f Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 28 Jul 2025 09:19:42 +0000 Subject: (박서영) 설계 document Numbering Rule 개발-최겸 업로드 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../table/combo-box-options-detail-sheet.tsx | 185 +++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 lib/docu-list-rule/combo-box-settings/table/combo-box-options-detail-sheet.tsx (limited to 'lib/docu-list-rule/combo-box-settings/table/combo-box-options-detail-sheet.tsx') diff --git a/lib/docu-list-rule/combo-box-settings/table/combo-box-options-detail-sheet.tsx b/lib/docu-list-rule/combo-box-settings/table/combo-box-options-detail-sheet.tsx new file mode 100644 index 00000000..1c145c55 --- /dev/null +++ b/lib/docu-list-rule/combo-box-settings/table/combo-box-options-detail-sheet.tsx @@ -0,0 +1,185 @@ +"use client" + +import * as React from "react" +import { useDataTable } from "@/hooks/use-data-table" +import { DataTable } from "@/components/data-table/data-table" +import { DataTableAdvancedToolbar } from "@/components/data-table/data-table-advanced-toolbar" +import type { DataTableAdvancedFilterField, DataTableRowAction } from "@/types/table" +import { + Sheet, + SheetContent, +} from "@/components/ui/sheet" + +import { getComboBoxOptions } from "../service" +import { getColumns } from "./combo-box-options-table-columns" +import { ComboBoxOptionsEditSheet } from "./combo-box-options-edit-sheet" +import { DeleteComboBoxOptionsDialog } from "./delete-combo-box-options-dialog" +import { ComboBoxOptionsTableToolbarActions } from "./combo-box-options-table-toolbar" +import { codeGroups } from "@/db/schema/codeGroups" + +type ComboBoxOption = { + id: number + codeGroupId: number + code: string + description: string + remark: string | null + isActive: boolean + createdAt: Date + updatedAt: Date +} + +interface ComboBoxOptionsDetailSheetProps { + open: boolean + onOpenChange: (open: boolean) => void + codeGroup: typeof codeGroups.$inferSelect | null + onSuccess?: () => void + promises?: Promise<[{ data: ComboBoxOption[]; pageCount: number }]> +} + +export function ComboBoxOptionsDetailSheet({ + open, + onOpenChange, + codeGroup, + onSuccess, + promises, +}: ComboBoxOptionsDetailSheetProps) { + const [rowAction, setRowAction] = React.useState | null>(null) + const [rawData, setRawData] = React.useState<{ data: ComboBoxOption[]; pageCount: number }>({ data: [], pageCount: 0 }) + + React.useEffect(() => { + if (promises) { + promises.then(([result]) => { + setRawData(result) + }) + } else if (open && codeGroup) { + // fallback: 클라이언트에서 직접 fetch (CSR) + (async () => { + try { + const result = await getComboBoxOptions(codeGroup.id, { + page: 1, + perPage: 10, + search: "", + sort: [{ id: "createdAt", desc: true }], + filters: [], + joinOperator: "and", + }) + if (result.success && result.data) { + // isActive 필드가 없는 경우 기본값 true로 설정 + const optionsWithIsActive = result.data.map(option => ({ + ...option, + isActive: (option as any).isActive ?? true + })) + setRawData({ + data: optionsWithIsActive, + pageCount: result.pageCount || 1 + }) + } + } catch (error) { + console.error("Error refreshing data:", error) + } + })() + } + }, [promises, open, codeGroup]) + + const refreshData = React.useCallback(async () => { + if (!codeGroup) return + + try { + const result = await getComboBoxOptions(codeGroup.id, { + page: 1, + perPage: 10, + search: "", + sort: [{ id: "createdAt", desc: true }], + filters: [], + joinOperator: "and", + }) + if (result.success && result.data) { + // isActive 필드가 없는 경우 기본값 true로 설정 + const optionsWithIsActive = result.data.map(option => ({ + ...option, + isActive: (option as any).isActive ?? true + })) + setRawData({ + data: optionsWithIsActive, + pageCount: result.pageCount || 1 + }) + } + } catch (error) { + console.error("Error refreshing data:", error) + } + }, [codeGroup]) + + const columns = React.useMemo(() => getColumns({ setRowAction: setRowAction as any }), [setRowAction]) + + // 고급 필터 필드 설정 + const advancedFilterFields: DataTableAdvancedFilterField[] = [ + { id: "code", label: "코드", type: "text" }, + { id: "description", label: "값", type: "text" }, + { id: "remark", label: "비고", type: "text" }, + ] + + const { table } = useDataTable({ + data: rawData.data as any, + columns: columns as any, + pageCount: rawData.pageCount, + enablePinning: true, + enableAdvancedFilter: true, + manualSorting: true, + manualFiltering: true, + initialState: { + sorting: [{ id: "createdAt", desc: true }], + columnPinning: { right: ["actions"] }, + }, + getRowId: (originalRow) => String((originalRow as any).id), + shallow: false, + clearOnDefault: true, + }) + + if (!codeGroup) return null + + return ( + + +
+
+

{codeGroup.description} 옵션 관리

+

+ {codeGroup.groupId}의 Combo Box 옵션들을 관리합니다. +

+
+
+ + + + + + + + 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} + /> +
+
+ ) +} \ No newline at end of file -- cgit v1.2.3