From b8e8328b1ffffb80bf4ebb776a4a24e5680fc5bc Mon Sep 17 00:00:00 2001 From: dujinkim Date: Fri, 28 Mar 2025 00:42:08 +0000 Subject: 테이블 칼럼 리사이즈 및 핀 충돌 해결 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/po/table/po-table-columns.tsx | 300 ++++++++++++++++++++++++-------------- 1 file changed, 187 insertions(+), 113 deletions(-) (limited to 'lib/po/table/po-table-columns.tsx') diff --git a/lib/po/table/po-table-columns.tsx b/lib/po/table/po-table-columns.tsx index a13b2acf..6517b9b3 100644 --- a/lib/po/table/po-table-columns.tsx +++ b/lib/po/table/po-table-columns.tsx @@ -3,7 +3,7 @@ import * as React from "react" import { type DataTableRowAction } from "@/types/table" import { type ColumnDef } from "@tanstack/react-table" -import { InfoIcon, PenIcon } from "lucide-react" +import { InfoIcon, FileTextIcon, SendIcon, FileSignatureIcon, MoreHorizontalIcon, ExternalLinkIcon } from "lucide-react" import { formatDate } from "@/lib/utils" import { Button } from "@/components/ui/button" @@ -13,19 +13,28 @@ import { TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { Badge } from "@/components/ui/badge" import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" import { poColumnsConfig } from "@/config/poColumnsConfig" -import { ContractDetail } from "@/db/schema/contract" +import { ContractDetailParsed } from "@/db/schema/contract" interface GetColumnsProps { - setRowAction: React.Dispatch | null>> + setRowAction: React.Dispatch | null>> } /** * tanstack table column definitions with nested headers */ -export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef[] { +export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef[] { // ---------------------------------------------------------------- // 1) select column (checkbox) - if needed // ---------------------------------------------------------------- @@ -33,164 +42,229 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef = { + const actionsColumn: ColumnDef = { id: "actions", enableHiding: false, + header: () =>
Actions
, cell: function Cell({ row }) { // Check if this contract already has a signature envelope const hasSignature = row.original.hasSignature; - + const contract = row.original; + return ( -
- {/* Item Info Button */} +
+ {/* Items Button - Visually distinct with badge showing count */} - View Item Info + View contract items and details - - {/* Signature Request Button - only show if no signature exists */} - {!hasSignature && ( + + {/* Signature related actions */} + {hasSignature ? ( + + + + + + + View signature status and details + + + + ) : ( - Request Electronic Signature + Send electronic signature requests )} + + {/* Alternative: Dropdown menu for more actions */} + {/* + + + + + + Actions + setRowAction({ row, type: "items" })}> + + View Items + + + {hasSignature ? ( + setRowAction({ row, type: "esign-detail" })}> + + View Signatures + + ) : ( + setRowAction({ row, type: "signature" })}> + + Request Signatures + + )} + + + */}
); }, - size: 80, // Increased width to accommodate both buttons + size: 340, // Adjusted for multiple buttons + minSize:280 }; // ---------------------------------------------------------------- // 3) Regular columns grouped by group name // ---------------------------------------------------------------- - // 3-1) groupMap: { [groupName]: ColumnDef[] } - const groupMap: Record[]> = {}; - - // (1) JSON config를 읽어서 ColumnDef를 생성하는 부분 (일부 발췌) -poColumnsConfig.forEach((cfg) => { - const groupName = cfg.group || "_noGroup" - if (!groupMap[groupName]) { - groupMap[groupName] = [] - } - - let childCol: ColumnDef - - if (cfg.type === "custom" && cfg.customType === "esignStatus") { - // ======================================== - // (2) 전자서명 전용 커스텀 컬럼 - // ======================================== - childCol = { - id: cfg.id, - header: ({ column }) => ( - - ), - // 여기서 row.original.envelopes 등 활용하여 최신 전자서명 상태 표시 - cell: ({ row }) => { - const data = row.original - if (!data.envelopes || data.envelopes.length === 0) { + // 3-1) groupMap: { [groupName]: ColumnDef[] } + const groupMap: Record[]> = {}; + + // (1) JSON config를 읽어서 ColumnDef를 생성하는 부분 (일부 발췌) + poColumnsConfig.forEach((cfg) => { + const groupName = cfg.group || "_noGroup" + if (!groupMap[groupName]) { + groupMap[groupName] = [] + } + + let childCol: ColumnDef + + if (cfg.type === "custom") { + // ======================================== + // (2) 전자서명 전용 커스텀 컬럼 + // ======================================== + childCol = { + id: cfg.id, + header: ({ column }) => ( + + ), + // 여기서 row.original.envelopes 등 활용하여 최신 전자서명 상태 표시 + cell: ({ row }) => { + const data = row.original + if (!data.envelopes || data.envelopes.length === 0) { + return ( +
+ No E-Sign +
+ ) + } + + // envelopes가 여러 개 있으면 최신(가장 최근 updatedAt) 가져오기 + const sorted = [...data.envelopes].sort((a, b) => { + const dateA = new Date(a.updatedAt) + const dateB = new Date(b.updatedAt) + return dateB.getTime() - dateA.getTime() + }) + const latest = sorted[0] + + const status = latest.envelopeStatus; + + if (!status) { + // status가 null이면, 기본 색상이나 별도 표시 + return No Status + } + + const colorMap: Record = { + completed: "text-green-600", + sent: "text-blue-600", + voided: "text-red-600", + }; + + const colorClass = colorMap[status] ?? "text-gray-700"; + return ( -
- No E-Sign +
+ setRowAction({ row, type: "esign-detail" })} + className={`${colorClass} cursor-pointer flex items-center`} + > + {status} + +
) - } - - // envelopes가 여러 개 있으면 최신(가장 최근 updatedAt) 가져오기 - const sorted = [...data.envelopes].sort((a, b) => { - const dateA = new Date(a.updatedAt) - const dateB = new Date(b.updatedAt) - return dateB.getTime() - dateA.getTime() - }) - const latest = sorted[0] - - // 상태에 따라 다른 UI 색상/아이콘 - const status = latest.envelopeStatus // "sent", "completed", ... - const colorMap: Record = { - completed: "text-green-600", - sent: "text-blue-600", - voided: "text-red-600", + }, + meta: { + excelHeader: cfg.excelHeader, + group: cfg.group, + type: cfg.type, + }, + } + } else { + // ======================================== + // (3) 일반 컬럼 (type: text/date/number 등) + // ======================================== + childCol = { + accessorKey: cfg.id, + enableResizing: true, + header: ({ column }) => ( + + ), + meta: { + excelHeader: cfg.excelHeader, + group: cfg.group, + type: cfg.type, + }, + cell: ({ row, cell }) => { + // 날짜 포맷, 숫자 포맷 등 처리 + if (cfg.type === "date") { + const dateVal = cell.getValue() as Date + return formatDate(dateVal) + } // ... - } - const colorClass = colorMap[status] || "text-gray-700" - - return ( - - ) - }, - meta: { - excelHeader: cfg.excelHeader, - group: cfg.group, - type: cfg.type, - }, - } - } else { - // ======================================== - // (3) 일반 컬럼 (type: text/date/number 등) - // ======================================== - childCol = { - accessorKey: cfg.id, - enableResizing: true, - header: ({ column }) => ( - - ), - meta: { - excelHeader: cfg.excelHeader, - group: cfg.group, - type: cfg.type, - }, - cell: ({ row, cell }) => { - // 날짜 포맷, 숫자 포맷 등 처리 - if (cfg.type === "date") { - const dateVal = cell.getValue() as Date - return formatDate(dateVal) - } - // ... - return row.getValue(cfg.id) ?? "" - }, + return row.getValue(cfg.id) ?? "" + }, + } } - } - groupMap[groupName].push(childCol) -}) + groupMap[groupName].push(childCol) + }) // ---------------------------------------------------------------- // 3-2) Create actual parent columns (groups) from the groupMap // ---------------------------------------------------------------- - const nestedColumns: ColumnDef[] = []; + const nestedColumns: ColumnDef[] = []; // Order can be fixed by pre-defining group order or sorting // Here we just use Object.entries order -- cgit v1.2.3