summaryrefslogtreecommitdiff
path: root/lib/welding/table/ocr-table-columns.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/welding/table/ocr-table-columns.tsx')
-rw-r--r--lib/welding/table/ocr-table-columns.tsx312
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