summaryrefslogtreecommitdiff
path: root/lib/basic-contract/status-detail
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-09-01 09:12:09 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-09-01 09:12:09 +0000
commit18954df6565108a469fb1608ea3715dd9bb1b02d (patch)
tree2675d254c547861a903a32459d89283a324e0e0d /lib/basic-contract/status-detail
parentf91cd16a872d9cda04aeb5c4e31538e3e2bd1895 (diff)
(대표님) 구매 기본계약, gtc 개발
Diffstat (limited to 'lib/basic-contract/status-detail')
-rw-r--r--lib/basic-contract/status-detail/basic-contract-detail-table-toolbar-actions.tsx10
-rw-r--r--lib/basic-contract/status-detail/basic-contracts-detail-columns.tsx72
-rw-r--r--lib/basic-contract/status-detail/basic-contracts-detail-table.tsx66
3 files changed, 123 insertions, 25 deletions
diff --git a/lib/basic-contract/status-detail/basic-contract-detail-table-toolbar-actions.tsx b/lib/basic-contract/status-detail/basic-contract-detail-table-toolbar-actions.tsx
index 3b5cdd21..37ae135c 100644
--- a/lib/basic-contract/status-detail/basic-contract-detail-table-toolbar-actions.tsx
+++ b/lib/basic-contract/status-detail/basic-contract-detail-table-toolbar-actions.tsx
@@ -21,7 +21,7 @@ import { Badge } from "@/components/ui/badge"
import { Textarea } from "@/components/ui/textarea"
import { Label } from "@/components/ui/label"
import { Separator } from "@/components/ui/separator"
-import { prepareFinalApprovalAction, quickFinalApprovalAction, requestLegalReviewAction } from "../service"
+import { prepareFinalApprovalAction, quickFinalApprovalAction, requestLegalReviewAction, resendContractsAction } from "../service"
import { BasicContractSignDialog } from "../vendor-table/basic-contract-sign-dialog"
interface BasicContractDetailTableToolbarActionsProps {
@@ -222,12 +222,12 @@ export function BasicContractDetailTableToolbarActions({ table }: BasicContractD
setFinalApproveDialog(true)
}
- // 재발송 확인
+ // 재요청 확인
const confirmResend = async () => {
setLoading(true)
try {
// TODO: 서버액션 호출
- // await resendContractsAction(resendContracts.map(c => c.id))
+ await resendContractsAction(resendContracts.map(c => c.id))
console.log("대량 재발송:", resendContracts)
toast.success(`${resendContracts.length}건의 계약서 재발송을 완료했습니다`)
@@ -339,7 +339,7 @@ export function BasicContractDetailTableToolbarActions({ table }: BasicContractD
</span>
</Button>
- {/* 재발송 버튼 */}
+ {/* 재요청 버튼 */}
<Button
variant="outline"
size="sm"
@@ -350,7 +350,7 @@ export function BasicContractDetailTableToolbarActions({ table }: BasicContractD
>
<Mail className="size-4" aria-hidden="true" />
<span className="hidden sm:inline">
- 재발송 {hasSelectedRows ? `(${selectedRows.length})` : ''}
+ 재요청 {hasSelectedRows ? `(${selectedRows.length})` : ''}
</span>
</Button>
diff --git a/lib/basic-contract/status-detail/basic-contracts-detail-columns.tsx b/lib/basic-contract/status-detail/basic-contracts-detail-columns.tsx
index 80c39d1e..9a140b27 100644
--- a/lib/basic-contract/status-detail/basic-contracts-detail-columns.tsx
+++ b/lib/basic-contract/status-detail/basic-contracts-detail-columns.tsx
@@ -1,4 +1,4 @@
-// basic-contracts-detail-columns.tsx
+// simple-basic-contracts-detail-columns.tsx
"use client"
import * as React from "react"
@@ -10,7 +10,16 @@ import { Badge } from "@/components/ui/badge"
import { Checkbox } from "@/components/ui/checkbox"
import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"
import { Button } from "@/components/ui/button"
-import { MoreHorizontal, Download, Eye, Mail, FileText, Clock } from "lucide-react"
+import {
+ MoreHorizontal,
+ Download,
+ Eye,
+ Mail,
+ FileText,
+ Clock,
+ MessageCircle,
+ Loader2
+} from "lucide-react"
import {
DropdownMenu,
DropdownMenuContent,
@@ -20,11 +29,18 @@ import {
import { BasicContractView } from "@/db/schema"
import { downloadFile, quickPreview } from "@/lib/file-download"
import { toast } from "sonner"
+import { useRouter } from "next/navigation"
interface GetColumnsProps {
setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<BasicContractView> | null>>
+ gtcData: Record<number, { gtcDocumentId: number | null; hasComments: boolean }>
+ isLoadingGtcData: boolean
+ router: NextRouter;
}
+type NextRouter = ReturnType<typeof useRouter>;
+
+
const CONTRACT_STATUS_CONFIG = {
PENDING: { label: "발송완료", color: "gray" },
VENDOR_SIGNED: { label: "협력업체 서명완료", color: "blue" },
@@ -35,7 +51,12 @@ const CONTRACT_STATUS_CONFIG = {
REJECTED: { label: "거절됨", color: "red" },
} as const
-export function getDetailColumns({ setRowAction }: GetColumnsProps): ColumnDef<BasicContractView>[] {
+export function getDetailColumns({
+ setRowAction,
+ gtcData,
+ isLoadingGtcData,
+ router
+}: GetColumnsProps): ColumnDef<BasicContractView>[] {
const selectColumn: ColumnDef<BasicContractView> = {
id: "select",
@@ -163,7 +184,7 @@ export function getDetailColumns({ setRowAction }: GetColumnsProps): ColumnDef<B
minSize: 120,
},
- // 업체명
+ // 업체명 (GTC 정보 포함)
{
accessorKey: "vendorName",
header: ({ column }) => (
@@ -171,11 +192,51 @@ export function getDetailColumns({ setRowAction }: GetColumnsProps): ColumnDef<B
),
cell: ({ row }) => {
const name = row.getValue("vendorName") as string | null
+ const contract = row.original
+ const isGTCTemplate = contract.templateName?.includes('GTC')
+ const contractGtcData = gtcData[contract.id]
+
+ const handleOpenGTC = (e: React.MouseEvent) => {
+ e.stopPropagation()
+ if (contractGtcData?.gtcDocumentId) {
+ const gtcUrl = `/evcp/basic-contract/vendor-gtc/${contractGtcData.gtcDocumentId}?vendorId=${contract.vendorId}&vendorName=${encodeURIComponent(contract.vendorName || '')}&contractId=${contract.id}&templateId=${contract.templateId}`
+ window.open(gtcUrl, '_blank')
+ }
+ }
+
return (
+ <div className="flex items-center gap-2">
<div className="font-medium">{name || "-"}</div>
+ {isGTCTemplate && (
+ <div className="flex items-center gap-1">
+ {isLoadingGtcData ? (
+ <Loader2 className="h-3 w-3 animate-spin text-gray-400" />
+ ) : contractGtcData ? (
+ <div className="flex items-center gap-1">
+ {contractGtcData.hasComments && (
+ <Badge
+ variant="secondary"
+ className="text-xs bg-orange-100 text-orange-700 cursor-pointer hover:bg-orange-200"
+ title={`GTC Document ID: ${contractGtcData.gtcDocumentId} - 클릭하여 협의이력 보기`}
+ onClick={handleOpenGTC}
+ >
+ <MessageCircle className="h-3 w-3 mr-1" />
+ 협의이력
+ </Badge>
+ )}
+
+ </div>
+ ) : (
+ <Badge variant="secondary" className="text-xs">
+ GTC
+ </Badge>
+ )}
+ </div>
+ )}
+ </div>
)
},
- minSize: 180,
+ minSize: 250,
},
// 진행상태
@@ -349,7 +410,6 @@ export function getDetailColumns({ setRowAction }: GetColumnsProps): ColumnDef<B
minSize: 120,
},
-
// 서명된 파일
{
accessorKey: "signedFileName",
diff --git a/lib/basic-contract/status-detail/basic-contracts-detail-table.tsx b/lib/basic-contract/status-detail/basic-contracts-detail-table.tsx
index 2698842e..f18359de 100644
--- a/lib/basic-contract/status-detail/basic-contracts-detail-table.tsx
+++ b/lib/basic-contract/status-detail/basic-contracts-detail-table.tsx
@@ -9,9 +9,11 @@ import type {
DataTableRowAction,
} from "@/types/table"
import { getDetailColumns } from "./basic-contracts-detail-columns"
-import { getBasicContractsByTemplateId } from "@/lib/basic-contract/service"
+import { getBasicContractsByTemplateId, checkGTCCommentsForContracts } from "@/lib/basic-contract/service"
import { BasicContractView } from "@/db/schema"
import { BasicContractDetailTableToolbarActions } from "./basic-contract-detail-table-toolbar-actions"
+import { toast } from "sonner"
+import { useRouter } from "next/navigation"
interface BasicContractsDetailTableProps {
templateId: number
@@ -25,14 +27,52 @@ interface BasicContractsDetailTableProps {
export function BasicContractsDetailTable({ templateId, promises }: BasicContractsDetailTableProps) {
const [rowAction, setRowAction] =
React.useState<DataTableRowAction<BasicContractView> | null>(null)
+
+ // GTC data 상태 관리
+ const [gtcData, setGtcData] = React.useState<Record<number, { gtcDocumentId: number | null; hasComments: boolean }>>({})
+ const [isLoadingGtcData, setIsLoadingGtcData] = React.useState(false)
const [{ data, pageCount }] = React.use(promises)
+ const router = useRouter()
- console.log(data,"data")
+ console.log(gtcData, "gtcData")
+ console.log(data, "data")
+
+ // GTC data 로딩
+ React.useEffect(() => {
+ const loadGtcData = async () => {
+ if (!data || data.length === 0) return;
+
+ // GTC가 포함된 template이 있는지 확인
+ const hasGtcTemplates = data.some(contract =>
+ contract.templateName?.includes('GTC')
+ );
+
+ if (!hasGtcTemplates) return;
+
+ setIsLoadingGtcData(true);
+ try {
+ const gtcResults = await checkGTCCommentsForContracts(data);
+ setGtcData(gtcResults);
+ } catch (error) {
+ console.error('Error checking GTC data:', error);
+ toast.error("GTC 데이터를 불러오는데 실패했습니다.");
+ } finally {
+ setIsLoadingGtcData(false);
+ }
+ };
+
+ loadGtcData();
+ }, [data]);
const columns = React.useMemo(
- () => getDetailColumns({ setRowAction }),
- [setRowAction]
+ () => getDetailColumns({
+ setRowAction,
+ gtcData,
+ isLoadingGtcData ,
+ router
+ }),
+ [setRowAction, gtcData, isLoadingGtcData, router]
)
const advancedFilterFields: DataTableAdvancedFilterField<BasicContractView>[] = [
@@ -76,15 +116,13 @@ export function BasicContractsDetailTable({ templateId, promises }: BasicContrac
})
return (
- <>
- <DataTable table={table}>
- <DataTableAdvancedToolbar
- table={table}
- filterFields={advancedFilterFields}
- >
- <BasicContractDetailTableToolbarActions table={table} />
- </DataTableAdvancedToolbar>
- </DataTable>
- </>
+ <DataTable table={table}>
+ <DataTableAdvancedToolbar
+ table={table}
+ filterFields={advancedFilterFields}
+ >
+ <BasicContractDetailTableToolbarActions table={table} />
+ </DataTableAdvancedToolbar>
+ </DataTable>
)
} \ No newline at end of file