diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-05 01:53:35 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-05 01:53:35 +0000 |
| commit | 610d3bccf1cb640e2a21df28d8d2a954c2bf337e (patch) | |
| tree | e7e6d72fecf14ddcff1b5b52263d14119b7c488c /lib/welding/table/ocr-table-columns.tsx | |
| parent | 15969dfedffc4e215c81d507164bc2bb383974e5 (diff) | |
(대표님) 변경사항 0604 - OCR 관련 및 drizzle generated sqls
Diffstat (limited to 'lib/welding/table/ocr-table-columns.tsx')
| -rw-r--r-- | lib/welding/table/ocr-table-columns.tsx | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/lib/welding/table/ocr-table-columns.tsx b/lib/welding/table/ocr-table-columns.tsx new file mode 100644 index 00000000..85830405 --- /dev/null +++ b/lib/welding/table/ocr-table-columns.tsx @@ -0,0 +1,312 @@ +"use client" + +import * as React from "react" +import { type ColumnDef } from "@tanstack/react-table" +import { ArrowUpDown, Copy, MoreHorizontal } from "lucide-react" + +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import { Checkbox } from "@/components/ui/checkbox" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { DataTableColumnHeader } from "@/components/data-table/data-table-column-header" +import { toast } from "sonner" +import { formatDate } from "@/lib/utils" +import { OcrRow } from "@/db/schema" +import { type DataTableRowAction } from "@/types/table" + +interface GetColumnsProps { + setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<OcrRow> | null>> +} + +export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<OcrRow>[] { + return [ + // 체크박스 컬럼 + { + 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, + }, + + // Report No 컬럼 + { + accessorKey: "reportNo", + header: ({ column }) => ( + <DataTableColumnHeader column={column} title="Report No" /> + ), + cell: ({ getValue }) => { + const reportNo = getValue() as string + return ( + <div className="flex items-center gap-2"> + <Badge variant="outline" className="font-mono text-xs"> + {reportNo || "N/A"} + </Badge> + <Button + variant="ghost" + size="icon" + className="size-6" + onClick={() => { + navigator.clipboard.writeText(reportNo || "") + toast.success("Report No copied to clipboard") + }} + > + <Copy className="size-3" /> + </Button> + </div> + ) + }, + enableSorting: true, + enableHiding: false, + }, + + // No 컬럼 + { + accessorKey: "no", + header: ({ column }) => ( + <DataTableColumnHeader column={column} title="No" /> + ), + cell: ({ getValue }) => { + const no = getValue() as string + return ( + <div className="font-medium"> + {no || "-"} + </div> + ) + }, + enableSorting: true, + }, + + // Identification No 컬럼 + { + accessorKey: "identificationNo", + header: ({ column }) => ( + <DataTableColumnHeader column={column} title="Identification No" /> + ), + cell: ({ getValue }) => { + const identificationNo = getValue() as string + return ( + <div className="max-w-[200px] truncate font-mono text-sm" title={identificationNo}> + {identificationNo || "-"} + </div> + ) + }, + enableSorting: true, + }, + + // Tag No 컬럼 + { + accessorKey: "tagNo", + header: ({ column }) => ( + <DataTableColumnHeader column={column} title="Tag No" /> + ), + cell: ({ getValue }) => { + const tagNo = getValue() as string + return ( + <div className="font-mono text-sm"> + {tagNo || "-"} + </div> + ) + }, + enableSorting: true, + }, + + // Joint No 컬럼 + { + accessorKey: "jointNo", + header: ({ column }) => ( + <DataTableColumnHeader column={column} title="Joint No" /> + ), + cell: ({ getValue }) => { + const jointNo = getValue() as string + return ( + <div className="font-mono text-sm"> + {jointNo || "-"} + </div> + ) + }, + enableSorting: true, + }, + + // Joint Type 컬럼 + { + accessorKey: "jointType", + header: ({ column }) => ( + <DataTableColumnHeader column={column} title="Joint Type" /> + ), + cell: ({ getValue }) => { + const jointType = getValue() as string + return ( + <Badge variant={jointType === "B" ? "default" : "secondary"}> + {jointType || "N/A"} + </Badge> + ) + }, + enableSorting: true, + }, + + // Welding Date 컬럼 + { + accessorKey: "weldingDate", + header: ({ column }) => ( + <DataTableColumnHeader column={column} title="Welding Date" /> + ), + cell: ({ getValue }) => { + const weldingDate = getValue() as string + return ( + <div className="text-sm"> + {weldingDate || "-"} + </div> + ) + }, + enableSorting: true, + }, + + // Confidence 컬럼 + { + accessorKey: "confidence", + header: ({ column }) => ( + <DataTableColumnHeader column={column} title="Confidence" /> + ), + cell: ({ getValue }) => { + const confidence = parseFloat(getValue() as string) || 0 + const percentage = Math.round(confidence * 100) + + let variant: "default" | "secondary" | "destructive" = "default" + if (percentage < 70) variant = "destructive" + else if (percentage < 90) variant = "secondary" + + return ( + <Badge variant={variant}> + {percentage}% + </Badge> + ) + }, + enableSorting: true, + }, + + // Source Table 컬럼 + { + accessorKey: "sourceTable", + header: ({ column }) => ( + <DataTableColumnHeader column={column} title="Table" /> + ), + cell: ({ getValue }) => { + const sourceTable = getValue() as number + return ( + <div className="text-center"> + <Badge variant="outline" className="text-xs"> + T{sourceTable} + </Badge> + </div> + ) + }, + enableSorting: true, + }, + + // Source Row 컬럼 + { + accessorKey: "sourceRow", + header: ({ column }) => ( + <DataTableColumnHeader column={column} title="Row" /> + ), + cell: ({ getValue }) => { + const sourceRow = getValue() as number + return ( + <div className="text-center text-sm text-muted-foreground"> + {sourceRow} + </div> + ) + }, + enableSorting: true, + }, + + // Created At 컬럼 + { + accessorKey: "createdAt", + header: ({ column }) => ( + <DataTableColumnHeader column={column} title="생성일" /> + ), + cell: ({ cell }) => { + const date = cell.getValue() as Date + return ( + <div className="text-sm text-muted-foreground"> + {formatDate(date)} + </div> + ) + }, + enableSorting: true, + }, + + // Actions 컬럼 + { + id: "actions", + cell: ({ row }) => ( + <DropdownMenu> + <DropdownMenuTrigger asChild> + <Button + aria-label="Open menu" + variant="ghost" + className="flex size-8 p-0 data-[state=open]:bg-muted" + > + <MoreHorizontal className="size-4" aria-hidden="true" /> + </Button> + </DropdownMenuTrigger> + <DropdownMenuContent align="end" className="w-40"> + <DropdownMenuItem + onClick={() => { + const rowData = row.original + navigator.clipboard.writeText(JSON.stringify(rowData, null, 2)) + toast.success("Row data copied to clipboard") + }} + > + <Copy className="mr-2 size-4" aria-hidden="true" /> + Copy Row Data + </DropdownMenuItem> + <DropdownMenuSeparator /> + <DropdownMenuItem + onClick={() => { + setRowAction({ type: "view", row }) + }} + > + View Details + </DropdownMenuItem> + <DropdownMenuItem + onClick={() => { + setRowAction({ type: "delete", row }) + }} + className="text-destructive focus:text-destructive" + > + Delete + </DropdownMenuItem> + </DropdownMenuContent> + </DropdownMenu> + ), + enableSorting: false, + enableHiding: false, + }, + ] +}
\ No newline at end of file |
