summaryrefslogtreecommitdiff
path: root/lib/techsales-rfq/table/rfq-table-column.tsx
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-05-29 05:12:36 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-05-29 05:37:04 +0000
commite484964b1d78cedabbe182c789a8e4c9b53e29d3 (patch)
treed18133dde99e6feb773c95d04f7e79715ab24252 /lib/techsales-rfq/table/rfq-table-column.tsx
parent37f55540833c2d5894513eca9fc8f7c6233fc2d2 (diff)
(김준회) 기술영업 조선 RFQ 파일첨부 및 채팅 기능 구현 / menuConfig 수정 (벤더 기술영업)
Diffstat (limited to 'lib/techsales-rfq/table/rfq-table-column.tsx')
-rw-r--r--lib/techsales-rfq/table/rfq-table-column.tsx178
1 files changed, 59 insertions, 119 deletions
diff --git a/lib/techsales-rfq/table/rfq-table-column.tsx b/lib/techsales-rfq/table/rfq-table-column.tsx
index caaa1c97..125e800b 100644
--- a/lib/techsales-rfq/table/rfq-table-column.tsx
+++ b/lib/techsales-rfq/table/rfq-table-column.tsx
@@ -6,10 +6,8 @@ import { formatDate, formatDateTime } from "@/lib/utils"
import { Checkbox } from "@/components/ui/checkbox"
import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"
import { DataTableRowAction } from "@/types/table"
-import { Check, Pencil, X, Info } from "lucide-react"
+import { Info, Paperclip } from "lucide-react"
import { Button } from "@/components/ui/button"
-import { toast } from "sonner"
-import { Input } from "@/components/ui/input"
// 기본적인 RFQ 타입 정의 (rfq-table.tsx 파일과 일치해야 함)
type TechSalesRfq = {
@@ -32,8 +30,8 @@ type TechSalesRfq = {
updatedByName: string
sentBy: number | null
sentByName: string | null
- projectSnapshot: any
- seriesSnapshot: any
+ projectSnapshot: Record<string, unknown>
+ seriesSnapshot: Record<string, unknown>
pspid: string
projNm: string
sector: string
@@ -42,28 +40,22 @@ type TechSalesRfq = {
attachmentCount: number
quotationCount: number
// 나머지 필드는 사용할 때마다 추가
- [key: string]: any
+ [key: string]: unknown
}
+// 프로젝트 상세정보 타입 추가를 위한 확장
+// interface ExtendedDataTableRowAction<TData> extends DataTableRowAction<TData> {
+// type: DataTableRowAction<TData>["type"] | "project-detail"
+// }
+
interface GetColumnsProps {
setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<TechSalesRfq> | null>>;
- // 상태와 상태 설정 함수를 props로 받음
- editingCell: EditingCellState | null;
- setEditingCell: (state: EditingCellState | null) => void;
- updateRemark: (rfqId: number, remark: string) => Promise<void>;
-}
-
-export interface EditingCellState {
- rowId: string | number;
- value: string;
+ openAttachmentsSheet: (rfqId: number) => void;
}
-
export function getColumns({
setRowAction,
- editingCell,
- setEditingCell,
- updateRemark,
+ openAttachmentsSheet,
}: GetColumnsProps): ColumnDef<TechSalesRfq>[] {
return [
{
@@ -81,7 +73,7 @@ export function getColumns({
// Then select just this row
row.toggleSelected(true)
// Trigger the same action that was in the "Select" button
- setRowAction({ row, type: "select" })
+ setRowAction({ row, type: "select" as const })
} else {
// Just deselect this row
row.toggleSelected(false)
@@ -142,7 +134,10 @@ export function getColumns({
header: ({ column }) => (
<DataTableColumnHeaderSimple column={column} title="자재명" />
),
- cell: ({ row }) => <div>{row.getValue("itemName")}</div>,
+ cell: ({ row }) => {
+ const itemName = row.getValue("itemName");
+ return <div>{itemName || "자재명 없음"}</div>;
+ },
meta: {
excelHeader: "자재명"
},
@@ -211,6 +206,48 @@ export function getColumns({
size: 80,
},
{
+ id: "attachments",
+ header: ({ column }) => (
+ <DataTableColumnHeaderSimple column={column} title="첨부파일" />
+ ),
+ cell: ({ row }) => {
+ const rfq = row.original
+ const attachmentCount = rfq.attachmentCount || 0
+
+ const handleClick = () => {
+ openAttachmentsSheet(rfq.id)
+ }
+
+ return (
+ <Button
+ variant="ghost"
+ size="sm"
+ className="relative h-8 w-8 p-0 group"
+ onClick={handleClick}
+ aria-label={
+ attachmentCount > 0 ? `View ${attachmentCount} attachments` : "Add attachments"
+ }
+ >
+ <Paperclip className="h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" />
+ {attachmentCount > 0 && (
+ <span className="pointer-events-none absolute -top-1 -right-1 inline-flex h-4 min-w-[1rem] items-center justify-center rounded-full bg-primary px-1 text-[0.625rem] font-medium leading-none text-primary-foreground">
+ {attachmentCount}
+ </span>
+ )}
+ <span className="sr-only">
+ {attachmentCount > 0 ? `${attachmentCount} 첨부파일` : "첨부파일 추가"}
+ </span>
+ </Button>
+ )
+ },
+ enableSorting: false,
+ enableResizing: true,
+ size: 80,
+ meta: {
+ excelHeader: "첨부파일"
+ },
+ },
+ {
accessorKey: "rfqSendDate",
header: ({ column }) => (
<DataTableColumnHeaderSimple column={column} title="RFQ 전송일" />
@@ -283,103 +320,6 @@ export function getColumns({
enableResizing: true,
size: 160,
},
- // {
- // accessorKey: "remark",
- // header: ({ column }) => (
- // <DataTableColumnHeaderSimple column={column} title="비고" />
- // ),
- // cell: ({ row }) => {
- // const id = row.original.id;
- // const value = row.getValue("remark") as string;
-
- // const isEditing =
- // editingCell?.rowId === row.id &&
- // editingCell.value !== undefined;
-
- // const startEditing = () => {
- // setEditingCell({
- // rowId: row.id,
- // value: value || ""
- // });
- // };
-
- // const cancelEditing = () => {
- // setEditingCell(null);
- // };
-
- // const saveChanges = async () => {
- // if (!editingCell) return;
-
- // try {
- // await updateRemark(id, editingCell.value);
- // setEditingCell(null);
- // } catch (error) {
- // toast.error("비고 업데이트 중 오류가 발생했습니다.");
- // console.error("Error updating remark:", error);
- // }
- // };
-
- // const handleKeyDown = (e: React.KeyboardEvent) => {
- // if (e.key === "Enter") {
- // saveChanges();
- // } else if (e.key === "Escape") {
- // cancelEditing();
- // }
- // };
-
- // if (isEditing) {
- // return (
- // <div className="flex items-center gap-1">
- // <Input
- // value={editingCell?.value || ""}
- // onChange={(e) => setEditingCell({
- // rowId: row.id,
- // value: e.target.value
- // })}
- // onKeyDown={handleKeyDown}
- // autoFocus
- // className="h-8 w-full"
- // />
- // <Button
- // variant="ghost"
- // size="icon"
- // onClick={saveChanges}
- // className="h-8 w-8"
- // >
- // <Check className="h-4 w-4" />
- // </Button>
- // <Button
- // variant="ghost"
- // size="icon"
- // onClick={cancelEditing}
- // className="h-8 w-8"
- // >
- // <X className="h-4 w-4" />
- // </Button>
- // </div>
- // );
- // }
-
- // return (
- // <div className="flex items-center gap-1 group">
- // <span className="truncate">{value || ""}</span>
- // <Button
- // variant="ghost"
- // size="icon"
- // onClick={startEditing}
- // className="h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity"
- // >
- // <Pencil className="h-3 w-3" />
- // </Button>
- // </div>
- // );
- // },
- // meta: {
- // excelHeader: "비고"
- // },
- // enableResizing: true,
- // size: 200,
- // },
{
id: "actions",
header: ({ column }) => (
@@ -390,7 +330,7 @@ export function getColumns({
<Button
variant="ghost"
size="sm"
- onClick={() => setRowAction({ row, type: "project-detail" })}
+ onClick={() => setRowAction({ row, type: "view" as const })}
className="h-8 px-2 gap-1"
>
<Info className="h-4 w-4" />