summaryrefslogtreecommitdiff
path: root/lib/vendor-investigation/table/investigation-table-columns.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vendor-investigation/table/investigation-table-columns.tsx')
-rw-r--r--lib/vendor-investigation/table/investigation-table-columns.tsx313
1 files changed, 202 insertions, 111 deletions
diff --git a/lib/vendor-investigation/table/investigation-table-columns.tsx b/lib/vendor-investigation/table/investigation-table-columns.tsx
index fd76a9a5..6146d940 100644
--- a/lib/vendor-investigation/table/investigation-table-columns.tsx
+++ b/lib/vendor-investigation/table/investigation-table-columns.tsx
@@ -5,31 +5,30 @@ import { ColumnDef } from "@tanstack/react-table"
import { Checkbox } from "@/components/ui/checkbox"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
-import { Ellipsis, Users, Boxes } from "lucide-react"
-// import { toast } from "sonner" // If needed
+import { Edit, Ellipsis } from "lucide-react"
import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"
-import { formatDate } from "@/lib/utils" // or your date util
+import { formatDate } from "@/lib/utils"
-// Example: If you have a type for row actions
+// Import types
import { type DataTableRowAction } from "@/types/table"
-import { ContactItem, PossibleItem, vendorInvestigationsColumnsConfig, VendorInvestigationsViewWithContacts } from "@/config/vendorInvestigationsColumnsConfig"
+import {
+ vendorInvestigationsColumnsConfig,
+ VendorInvestigationsViewWithContacts
+} from "@/config/vendorInvestigationsColumnsConfig"
-// Props that define how we handle special columns (contacts, items, actions, etc.)
+// Props for the column generator function
interface GetVendorInvestigationsColumnsProps {
setRowAction?: React.Dispatch<
React.SetStateAction<
DataTableRowAction<VendorInvestigationsViewWithContacts> | null
>
>
- openContactsModal?: (investigationId: number, contacts: ContactItem[]) => void
- openItemsDrawer?: (investigationId: number, items: PossibleItem[]) => void
+ openVendorDetailsModal?: (vendorId: number) => void
}
-// This function returns the array of columns for TanStack Table
export function getColumns({
setRowAction,
- openContactsModal,
- openItemsDrawer,
+ openVendorDetailsModal,
}: GetVendorInvestigationsColumnsProps): ColumnDef<
VendorInvestigationsViewWithContacts
>[] {
@@ -63,25 +62,22 @@ export function getColumns({
}
// --------------------------------------------
- // 2) Actions column (optional)
+ // 2) Actions column
// --------------------------------------------
const actionsColumn: ColumnDef<VendorInvestigationsViewWithContacts> = {
id: "actions",
enableHiding: false,
cell: ({ row }) => {
- const inv = row.original
-
return (
<Button
variant="ghost"
className="flex size-8 p-0 data-[state=open]:bg-muted"
- aria-label="Open menu"
+ aria-label="실사 정보 수정"
onClick={() => {
- // e.g. open a dropdown or set your row action
setRowAction?.({ type: "update", row })
}}
>
- <Ellipsis className="size-4" aria-hidden="true" />
+ <Edit className="size-4" aria-hidden="true" />
</Button>
)
},
@@ -89,97 +85,44 @@ export function getColumns({
}
// --------------------------------------------
- // 3) Contacts column (badge count -> open modal)
+ // 3) Vendor Name with click handler
// --------------------------------------------
- const contactsColumn: ColumnDef<VendorInvestigationsViewWithContacts> = {
- id: "contacts",
- header: "Contacts",
+ const vendorNameColumn: ColumnDef<VendorInvestigationsViewWithContacts> = {
+ accessorKey: "vendorName",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="협력사명" />
+ ),
cell: ({ row }) => {
- const { contacts, investigationId } = row.original
- const count = contacts?.length ?? 0
-
- const handleClick = () => {
- openContactsModal?.(investigationId, contacts)
- }
+ const vendorId = row.original.vendorId
+ const vendorName = row.getValue("vendorName") as string
return (
<Button
- variant="ghost"
- size="sm"
- className="relative h-8 w-8 p-0 group"
- onClick={handleClick}
- aria-label={
- count > 0 ? `View ${count} contacts` : "Add contacts"
- }
+ variant="link"
+ className="p-0 h-auto font-normal"
+ onClick={() => openVendorDetailsModal?.(vendorId)}
>
- <Users className="h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" />
- {count > 0 && (
- <Badge
- variant="secondary"
- className="pointer-events-none absolute -top-1 -right-1 h-4 min-w-[1rem] p-0 text-[0.625rem] leading-none flex items-center justify-center"
- >
- {count}
- </Badge>
- )}
- <span className="sr-only">
- {count > 0 ? `${count} Contacts` : "Add Contacts"}
- </span>
+ {vendorName}
</Button>
)
},
- enableSorting: false,
- size: 60,
- }
-
- // --------------------------------------------
- // 4) Possible Items column (badge count -> open drawer)
- // --------------------------------------------
- const possibleItemsColumn: ColumnDef<VendorInvestigationsViewWithContacts> = {
- id: "possibleItems",
- header: "Items",
- cell: ({ row }) => {
- const { possibleItems, investigationId } = row.original
- const count = possibleItems?.length ?? 0
-
- const handleClick = () => {
- openItemsDrawer?.(investigationId, possibleItems)
- }
-
- return (
- <Button
- variant="ghost"
- size="sm"
- className="relative h-8 w-8 p-0 group"
- onClick={handleClick}
- aria-label={
- count > 0 ? `View ${count} items` : "Add items"
- }
- >
- <Boxes className="h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" />
- {count > 0 && (
- <Badge
- variant="secondary"
- className="pointer-events-none absolute -top-1 -right-1 h-4 min-w-[1rem] p-0 text-[0.625rem] leading-none flex items-center justify-center"
- >
- {count}
- </Badge>
- )}
- <span className="sr-only">
- {count > 0 ? `${count} Items` : "Add Items"}
- </span>
- </Button>
- )
+ meta: {
+ excelHeader: "협력사명",
+ group: "협력업체",
},
- enableSorting: false,
- size: 60,
}
// --------------------------------------------
- // 5) Build "grouped" columns from config
+ // 4) Build grouped columns from config
// --------------------------------------------
const groupMap: Record<string, ColumnDef<VendorInvestigationsViewWithContacts>[]> = {}
vendorInvestigationsColumnsConfig.forEach((cfg) => {
+ // Skip vendorName as we have a custom column for it
+ if (cfg.id === "vendorName") {
+ return
+ }
+
const groupName = cfg.group || "_noGroup"
if (!groupMap[groupName]) {
@@ -196,34 +139,120 @@ export function getColumns({
group: cfg.group,
type: cfg.type,
},
- cell: ({ row, cell }) => {
- const val = cell.getValue()
-
- // Example: Format date fields
+ cell: ({ row, column }) => {
+ const value = row.getValue(column.id)
+
+ // Handle date fields
if (
- cfg.id === "investigationCreatedAt" ||
- cfg.id === "investigationUpdatedAt" ||
- cfg.id === "scheduledStartAt" ||
- cfg.id === "scheduledEndAt" ||
- cfg.id === "completedAt"
+ column.id === "scheduledStartAt" ||
+ column.id === "scheduledEndAt" ||
+ column.id === "forecastedAt" ||
+ column.id === "requestedAt" ||
+ column.id === "confirmedAt" ||
+ column.id === "completedAt" ||
+ column.id === "createdAt" ||
+ column.id === "updatedAt"
) {
- const dateVal = val ? new Date(val as string) : null
- return dateVal ? formatDate(dateVal) : ""
+ if (!value) return ""
+ return formatDate(new Date(value as string), "KR")
+ }
+
+ // Handle status fields with badges
+ if (column.id === "investigationStatus") {
+ if (!value) return ""
+
+ return (
+ <Badge variant={getStatusVariant(value as string)}>
+ {formatStatus(value as string)}
+ </Badge>
+ )
+ }
+
+ // Handle evaluation type
+ if (column.id === "evaluationType") {
+ if (!value) return ""
+
+ return (
+ <span>
+ {formatEnumValue(value as string)}
+ </span>
+ )
+ }
+
+ // Handle evaluation result
+ if (column.id === "evaluationResult") {
+ if (!value) return ""
+
+ return (
+ <Badge variant={getResultVariant(value as string)}>
+ {formatEnumValue(value as string)}
+ </Badge>
+ )
+ }
+
+ // Handle IDs for pqSubmissionId (keeping for reference)
+ if (column.id === "pqSubmissionId") {
+ return value ? `#${value}` : ""
+ }
+
+ // Handle file attachment status
+ if (column.id === "hasAttachments") {
+ return (
+ <div className="flex items-center justify-center">
+ {value ? (
+ <Badge variant="default" className="text-xs">
+ 📎 첨부
+ </Badge>
+ ) : (
+ <span className="text-muted-foreground text-xs">-</span>
+ )}
+ </div>
+ )
}
- // Example: You could show an icon for "investigationStatus"
- if (cfg.id === "investigationStatus") {
- return <span className="capitalize">{val as string}</span>
+ if (column.id === "requesterName") {
+ if (!value && !row.original.requesterEmail) {
+ return <span className="text-muted-foreground">미배정</span>
+ }
+
+ return (
+ <div className="flex flex-col">
+ <span>{value || "미배정"}</span>
+ {row.original.requesterEmail && (
+ <span className="text-xs text-muted-foreground">{row.original.requesterEmail}</span>
+ )}
+ </div>
+ )
+ }
+
+ if (column.id === "qmManagerName") {
+ if (!value && !row.original.qmManagerEmail) {
+ return <span className="text-muted-foreground">미배정</span>
+ }
+
+ return (
+ <div className="flex flex-col">
+ <span>{value || "미배정"}</span>
+ {row.original.qmManagerEmail && (
+ <span className="text-xs text-muted-foreground">{row.original.qmManagerEmail}</span>
+ )}
+ </div>
+ )
}
- return val ?? ""
+ return value ?? ""
},
}
groupMap[groupName].push(childCol)
})
- // Turn the groupMap into nested columns
+ // Insert custom vendorNameColumn in the 협력업체 group
+ if (groupMap["협력업체"]) {
+ groupMap["협력업체"].unshift(vendorNameColumn)
+ }
+
+ // Convert the groupMap into nested columns
const nestedColumns: ColumnDef<VendorInvestigationsViewWithContacts>[] = []
for (const [groupName, colDefs] of Object.entries(groupMap)) {
if (groupName === "_noGroup") {
@@ -238,14 +267,76 @@ export function getColumns({
}
// --------------------------------------------
- // 6) Return final columns array
- // (You can reorder these as you wish.)
+ // 5) Return final columns array (simplified)
// --------------------------------------------
return [
selectColumn,
...nestedColumns,
- contactsColumn,
- possibleItemsColumn,
actionsColumn,
]
+}
+
+// Helper functions for formatting
+function formatStatus(status: string): string {
+ switch (status) {
+ case "PLANNED":
+ return "계획됨"
+ case "IN_PROGRESS":
+ return "진행 중"
+ case "COMPLETED":
+ return "완료됨"
+ case "CANCELED":
+ return "취소됨"
+ default:
+ return status
+ }
+}
+
+function formatEnumValue(value: string): string {
+ switch (value) {
+ // Evaluation types
+ case "SITE_AUDIT":
+ return "실사의뢰평가"
+ case "QM_SELF_AUDIT":
+ return "QM자체평가"
+
+ // Evaluation results
+ case "APPROVED":
+ return "승인"
+ case "SUPPLEMENT":
+ return "보완"
+ case "REJECTED":
+ return "불가"
+
+ default:
+ return value.replace(/_/g, " ").toLowerCase()
+ }
+}
+
+function getStatusVariant(status: string): "default" | "secondary" | "outline" | "destructive" {
+ switch (status) {
+ case "PLANNED":
+ return "secondary"
+ case "IN_PROGRESS":
+ return "default"
+ case "COMPLETED":
+ return "outline"
+ case "CANCELED":
+ return "destructive"
+ default:
+ return "default"
+ }
+}
+
+function getResultVariant(result: string): "default" | "secondary" | "outline" | "destructive" {
+ switch (result) {
+ case "APPROVED":
+ return "default"
+ case "SUPPLEMENT":
+ return "secondary"
+ case "REJECTED":
+ return "destructive"
+ default:
+ return "outline"
+ }
} \ No newline at end of file