From dd20ba9785cdbd3d61f6b014d003d3bd9646ad13 Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Thu, 14 Aug 2025 00:26:53 +0000
Subject: (고건) 리스크 관리 페이지 추가
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/risk-management/table/risks-table.tsx | 176 ++++++++++++++++++++++++++++++
 1 file changed, 176 insertions(+)
 create mode 100644 lib/risk-management/table/risks-table.tsx

(limited to 'lib/risk-management/table/risks-table.tsx')

diff --git a/lib/risk-management/table/risks-table.tsx b/lib/risk-management/table/risks-table.tsx
new file mode 100644
index 00000000..d6317c26
--- /dev/null
+++ b/lib/risk-management/table/risks-table.tsx
@@ -0,0 +1,176 @@
+'use client';
+
+/* IMPORT */
+import { DataTable } from '@/components/data-table/data-table';
+import { DataTableAdvancedToolbar } from '@/components/data-table/data-table-advanced-toolbar';
+import getColumns from './risks-columns';
+import { getRisksView } from '../service';
+import { type RisksView } from '@/db/schema';
+import RisksMailDialog from './risks-mail-dialog';
+import RisksTableToolbarActions from './risks-table-toolbar-actions';
+import RisksUpdateSheet from './risks-update-sheet';
+import {
+  type DataTableFilterField,
+  type DataTableRowAction,
+  type DataTableAdvancedFilterField,
+} from '@/types/table';
+import { useDataTable } from '@/hooks/use-data-table';
+import { use, useCallback, useMemo, useState } from 'react';
+import { useRouter } from 'next/navigation';
+import { RISK_EVENT_TYPE_LIST, RISK_PROVIDER_LIST } from '@/config/risksConfig';
+
+// ----------------------------------------------------------------------------------------------------
+
+/* TYPES */
+interface RisksTableProps {
+  promises: Promise<[
+    Awaited<ReturnType<typeof getRisksView>>,
+  ]>;
+}
+
+// ----------------------------------------------------------------------------------------------------
+
+/* TABLE COMPONENT */
+function RisksTable({ promises }: RisksTableProps) {
+  const router = useRouter();
+  const [rowAction, setRowAction] = useState<DataTableRowAction<RisksView> | null>(null);
+  const [isMailDialogOpen, setIsMailDialogOpen] = useState(false);
+  const [promiseData] = use(promises);
+  const tableData = promiseData;
+  const columns = useMemo(
+    () => getColumns({ setRowAction }),
+    [setRowAction],
+  );
+
+  const filterFields: DataTableFilterField<RisksView>[] = [
+    {
+      id: 'eventType',
+      label: '리스크 항목',
+      placeholder: '리스크 항목 선택...',
+    },
+    {
+      id: 'vendorName',
+      label: '협력업체명',
+      placeholder: '협력업체명 입력...',
+    },
+    {
+      id: 'businessNumber',
+      label: '사업자등록번호',
+      placeholder: '사업자등록번호 입력...',
+    },
+    {
+      id: 'provider',
+      label: '신용평가사',
+      placeholder: '신용평가사 선택...',
+    },
+  ]
+  const advancedFilterFields: DataTableAdvancedFilterField<RisksView>[] = [
+    {
+      id: 'eventType',
+      label: '리스크 항목',
+      type: 'select',
+      options: RISK_EVENT_TYPE_LIST.map((item: string) => ({
+        label: item,
+        value: item,
+      })),
+    },
+    {
+      id: 'provider',
+      label: '신용평가사',
+      type: 'select',
+      options: RISK_PROVIDER_LIST.map((item: string) => ({
+        label: item,
+        value: item,
+      })),
+    },
+    {
+      id: 'vendorName',
+      label: '협력업체명',
+      type: 'text',
+    },
+    {
+      id: 'content',
+      label: '상세 내용',
+      type: 'text',
+    },
+  ];
+
+  // Data Table Setting
+  const { table } = useDataTable({
+    data: tableData.data,
+    columns,
+    pageCount: tableData.pageCount,
+    filterFields,
+    enablePinning: true,
+    enableAdvancedFilter: true,
+    initialState: {
+      sorting: [
+        { id: 'occuredAt', desc: true },
+      ],
+      columnPinning: { left: ['select'], right: ['actions'] },
+    },
+    getRowId: (originalRow) => String(originalRow.id),
+    shallow: false,
+    clearOnDefault: true,
+  });
+
+  const emptyRiskData: RisksView = {
+    id: 0,
+    vendorName: '',
+    vendorCode: '',
+    vendorId: 0,
+    businessNumber: '',
+    provider: '',
+    eventType: '',
+    content: '',
+    eventStatus: true,
+    managerId: 0,
+    managerName: '',
+    adminComment: '',
+    occuredAt: new Date(),
+  };
+
+  const refreshData = useCallback(() => {
+    router.refresh();
+  }, [router]);
+  
+  const handleModifySuccess = useCallback(() => {
+    setRowAction(null);
+    refreshData();
+  }, [refreshData]);
+
+  return (
+    <>
+      <DataTable table={table}>
+        <DataTableAdvancedToolbar
+          table={table}
+          filterFields={advancedFilterFields}
+          shallow={false}
+        >
+          <RisksTableToolbarActions
+            table={table}
+            onOpenMailDialog={() => setIsMailDialogOpen(true)}
+            onRefresh={refreshData}
+          />
+        </DataTableAdvancedToolbar>
+      </DataTable>
+      <RisksUpdateSheet
+        open={rowAction?.type === 'update'}
+        onOpenChange={() => setRowAction(null)}
+        riskData={rowAction?.row.original ?? emptyRiskData}
+        onSuccess={handleModifySuccess}
+      />
+      <RisksMailDialog
+        open={isMailDialogOpen}
+        onOpenChange={setIsMailDialogOpen}
+        riskDataList={table.getFilteredSelectedRowModel().rows?.map(row => row.original) ?? []}
+        onSuccess={refreshData}
+      />
+    </>
+  )
+}
+
+// ----------------------------------------------------------------------------------------------------
+
+/* EXPORT */
+export default RisksTable;
\ No newline at end of file
-- 
cgit v1.2.3

