diff options
| author | joonhoekim <26rote@gmail.com> | 2025-08-14 00:26:53 +0000 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-08-14 00:26:53 +0000 |
| commit | dd20ba9785cdbd3d61f6b014d003d3bd9646ad13 (patch) | |
| tree | 4e99d62311a6c115dbc894084714a29c34bca11a /lib/risk-management/table/risks-columns.tsx | |
| parent | 33be47506f0aa62b969d82521580a29e95080268 (diff) | |
(고건) 리스크 관리 페이지 추가
Diffstat (limited to 'lib/risk-management/table/risks-columns.tsx')
| -rw-r--r-- | lib/risk-management/table/risks-columns.tsx | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/lib/risk-management/table/risks-columns.tsx b/lib/risk-management/table/risks-columns.tsx new file mode 100644 index 00000000..fe98448a --- /dev/null +++ b/lib/risk-management/table/risks-columns.tsx @@ -0,0 +1,352 @@ +'use client'; + +/* IMPORT */ +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { Checkbox } from '@/components/ui/checkbox'; +import { CircleCheckBig, CircleX, Ellipsis, Handshake, OctagonAlert } from 'lucide-react'; +import { DataTableColumnHeaderSimple } from '@/components/data-table/data-table-column-simple-header'; +import { Dispatch, SetStateAction } from 'react'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu'; +import { type ColumnDef } from '@tanstack/react-table'; +import { type DataTableRowAction } from '@/types/table'; +import { type RisksView } from '@/db/schema'; + +// ---------------------------------------------------------------------------------------------------- + +/* TYPES */ +interface GetColumnsProps { + setRowAction: Dispatch<SetStateAction<DataTableRowAction<RisksView> | null>>, +}; + +// ---------------------------------------------------------------------------------------------------- + +/* FUNCTION FOR GETTING COLUMNS SETTING */ +function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<RisksView>[] { + + // [1] SELECT COLUMN - CHECKBOX + const selectColumn: ColumnDef<RisksView> = { + id: 'select', + header: ({ table }) => ( + <Checkbox + checked={ + table.getIsAllPageRowsSelected() || + (table.getIsSomePageRowsSelected() && 'indeterminate') + } + onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)} + aria-label="select-all" + className="translate-y-0.5" + /> + ), + cell: ({ row }) => ( + <Checkbox + checked={row.getIsSelected()} + onCheckedChange={(value) => row.toggleSelected(!!value)} + aria-label="select-row" + className="translate-y-0.5" + /> + ), + enableSorting: false, + enableHiding: false, + size: 40, + }; + + // [2] SOURCE COLUMNS + const sourceColumns: ColumnDef<RisksView>[] = [ + { + accessorKey: 'eventType', + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="항목" /> + ), + cell: ({ row }) => { + const value = row.getValue<string>('eventType'); + return ( + <Badge variant="default"> + {value} + </Badge> + ); + }, + enableSorting: true, + enableHiding: false, + meta: { + excelHeader: 'Risk Category', + group: 'Risk Information', + type: 'select', + }, + }, + { + accessorKey: 'vendorCode', + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="협력업체 코드" /> + ), + cell: ({ row }) => { + const value = row.getValue<string>('vendorCode'); + return ( + <div className="font-regular"> + {value} + </div> + ); + }, + enableSorting: true, + enableHiding: false, + meta: { + excelHeader: 'Vendor Code', + group: 'Risk Information', + type: 'text', + }, + }, + { + accessorKey: 'vendorName', + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="협력업체명" /> + ), + cell: ({ row }) => { + const value = row.getValue<string>('vendorName'); + return ( + <div className="font-regular"> + {value} + </div> + ); + }, + enableSorting: true, + enableHiding: false, + meta: { + excelHeader: 'Vendor Name', + group: 'Risk Information', + type: 'text', + }, + }, + { + accessorKey: 'businessNumber', + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="사업자등록번호" /> + ), + cell: ({ row }) => { + const value = row.getValue<string>('businessNumber'); + const digits = value.replace(/\D/g, ''); + const formattedValue = digits.length === 10 + ? `${digits.slice(0, 3)}-${digits.slice(3, 5)}-${digits.slice(5)}` + : value; + return ( + <div className="font-regular"> + {formattedValue} + </div> + ); + }, + enableSorting: true, + enableHiding: false, + meta: { + excelHeader: 'Business Number', + group: 'Risk Information', + type: 'text', + }, + }, + { + accessorKey: 'provider', + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="신용평가사" /> + ), + cell: ({ row }) => { + const value = row.getValue<string>('provider'); + return ( + <Badge variant="secondary"> + {value} + </Badge> + ); + }, + enableSorting: true, + enableHiding: false, + meta: { + excelHeader: 'Provider', + group: 'Risk Information', + type: 'text', + }, + }, + { + accessorKey: 'content', + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="상세 내용" /> + ), + cell: ({ row }) => { + const value = row.getValue<string>('content') ?? '-'; + return ( + <div className="font-regular max-w-[150px] truncate" title={value}> + {value} + </div> + ); + }, + enableSorting: true, + enableHiding: false, + meta: { + excelHeader: 'Risk Content', + group: 'Risk Information', + type: 'text', + }, + size: 100, + }, + { + accessorKey: 'occuredAt', + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="발생일시" /> + ), + cell: ({ row }) => { + const date = row.getValue<Date>('occuredAt'); + return ( + <div className="font-regular"> + {date ? new Date(date).toLocaleDateString('ko-KR') : '-'} + </div> + ); + }, + enableSorting: true, + enableHiding: false, + meta: { + excelHeader: 'Occured At', + group: 'Risk Information', + type: 'date', + }, + }, + ]; + + // [3] INPUT COLUMNS + const inputColumns: ColumnDef<RisksView>[] = [ + { + accessorKey: 'eventStatus', + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="리스크 해소 여부" /> + ), + cell: ({ row }) => { + const value = row.getValue<boolean>('eventStatus'); + + if (value) { + return ( + <div className="flex items-center gap-2 text-destructive font-bold"> + <CircleX size={20} strokeWidth={2} /> + 아니오 + </div> + ); + } + return ( + <div className="flex items-center gap-2 text-primary font-bold"> + <CircleCheckBig size={20} strokeWidth={2} /> + 예 + </div> + ); + }, + enableSorting: true, + enableHiding: false, + meta: { + excelHeader: 'Risk Not Cleared', + group: 'Risk Management', + type: 'text', + }, + }, + { + accessorKey: 'managerName', + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="구매 담당자" /> + ), + cell: ({ row }) => { + const value = row.getValue<string>('managerName') ?? '-'; + return ( + <div className="font-regular"> + {value} + </div> + ); + }, + enableSorting: true, + enableHiding: false, + meta: { + excelHeader: 'Procurement Manager Name', + group: 'Risk Management', + type: 'text', + }, + }, + { + accessorKey: 'adminComment', + header: ({ column }) => ( + <DataTableColumnHeaderSimple column={column} title="관리 담당자 의견" /> + ), + cell: ({ row }) => { + const value = row.getValue<string>('adminComment') ?? '-'; + return ( + <div className="font-regular max-w-[150px] truncate" title={value}> + {value} + </div> + ); + }, + enableSorting: true, + enableHiding: false, + meta: { + excelHeader: 'Risk Manager Comment', + group: 'Risk Management', + type: 'text', + }, + size: 300, + }, + ]; + + // [4] ACTIONS COLUMN - DROPDOWN MENU WITH VIEW ACTION + const actionsColumn: ColumnDef<RisksView> = { + id: 'actions', + enableHiding: false, + cell: function Cell({ row }) { + return ( + <DropdownMenu> + <DropdownMenuTrigger asChild> + <Button + aria-label="Open menu" + variant="ghost" + className="flex size-8 p-0 data-[state=open]:bg-muted" + > + <Ellipsis className="size-4" aria-hidden="true" /> + </Button> + </DropdownMenuTrigger> + <DropdownMenuContent align="end" className="w-60"> + <DropdownMenuItem + onSelect={() => setRowAction({ row, type: "update" })} + className="cursor-pointer" + > + <OctagonAlert className="mr-2 size-4" /> + 리스크 관리 + </DropdownMenuItem> + <DropdownMenuItem + onSelect={() => { + // 신용정보 관리화면으로 이동 + }} + className="cursor-pointer" + > + <Handshake className="mr-2 size-4" /> + 신용정보 확인 + </DropdownMenuItem> + </DropdownMenuContent> + </DropdownMenu> + ) + }, + size: 80, + }; + + return [ + selectColumn, + { + id: 'riskSource', + header: '리스크 정보', + columns: sourceColumns, + }, + { + id: 'riskInput', + header: '리스크 관리', + columns: inputColumns, + }, + actionsColumn, + ]; +}; + +// ---------------------------------------------------------------------------------------------------- + +/* EXPORT */ +export default getColumns;
\ No newline at end of file |
