diff options
Diffstat (limited to 'lib/techsales-rfq/table/project-detail-dialog.tsx')
| -rw-r--r-- | lib/techsales-rfq/table/project-detail-dialog.tsx | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/lib/techsales-rfq/table/project-detail-dialog.tsx b/lib/techsales-rfq/table/project-detail-dialog.tsx new file mode 100644 index 00000000..b8219d7f --- /dev/null +++ b/lib/techsales-rfq/table/project-detail-dialog.tsx @@ -0,0 +1,322 @@ +"use client" + +import * as React from "react" +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog" +import { Badge } from "@/components/ui/badge" +import { Separator } from "@/components/ui/separator" +import { Button } from "@/components/ui/button" +import { formatDateToQuarter } from "@/lib/utils" + +// 프로젝트 스냅샷 타입 정의 +interface ProjectSnapshot { + scDt?: string + klDt?: string + lcDt?: string + dlDt?: string + dockNo?: string + dockNm?: string + projNo?: string + projNm?: string + ownerNm?: string + kunnrNm?: string + cls1Nm?: string + projMsrm?: number + ptypeNm?: string + sector?: string + estmPm?: string +} + +// 시리즈 스냅샷 타입 정의 +interface SeriesSnapshot { + sersNo?: string + scDt?: string + klDt?: string + lcDt?: string + dlDt?: string + dockNo?: string + dockNm?: string +} + +// 기본적인 RFQ 타입 정의 (rfq-table.tsx와 일치) +interface TechSalesRfq { + id: number + rfqCode: string | null + itemId: number + itemName: string | null + materialCode: string | null + dueDate: Date + rfqSendDate: Date | null + status: "RFQ Created" | "RFQ Vendor Assignned" | "RFQ Sent" | "Quotation Analysis" | "Closed" + picCode: string | null + remark: string | null + cancelReason: string | null + createdAt: Date + updatedAt: Date + createdBy: number | null + createdByName: string + updatedBy: number | null + updatedByName: string + sentBy: number | null + sentByName: string | null + projectSnapshot: ProjectSnapshot | null + seriesSnapshot: SeriesSnapshot[] | null + pspid: string + projNm: string + sector: string + projMsrm: number + ptypeNm: string + attachmentCount: number + quotationCount: number +} + +interface ProjectDetailDialogProps { + open: boolean + onOpenChange: (open: boolean) => void + selectedRfq: TechSalesRfq | null +} + +export function ProjectDetailDialog({ + open, + onOpenChange, + selectedRfq, +}: ProjectDetailDialogProps) { + if (!selectedRfq) { + return null + } + + const projectSnapshot = selectedRfq.projectSnapshot + const seriesSnapshot = selectedRfq.seriesSnapshot + + return ( + <Dialog open={open} onOpenChange={onOpenChange}> + <DialogContent className="max-w-4xl w-[80vw] max-h-[80vh] overflow-hidden flex flex-col"> + <DialogHeader className="border-b pb-4"> + <DialogTitle className="flex items-center gap-2"> + 프로젝트 상세정보 + <Badge variant="outline">{selectedRfq.pspid}</Badge> + </DialogTitle> + <DialogDescription className="space-y-1"> + <div className="flex items-center gap-2 text-base font-medium"> + <span>RFQ:</span> + <Badge variant="secondary">{selectedRfq.rfqCode || "미할당"}</Badge> + <span>|</span> + <span>자재:</span> + <span className="text-foreground">{selectedRfq.materialCode || "N/A"}</span> + </div> + <div className="text-sm text-muted-foreground"> + {selectedRfq.projNm} - {selectedRfq.ptypeNm} ({selectedRfq.itemName || "자재명 없음"}) + </div> + </DialogDescription> + </DialogHeader> + <div className="space-y-6 p-1 overflow-y-auto"> + {/* 기본 프로젝트 정보 */} + <div className="space-y-4"> + <h3 className="text-lg font-semibold">기본 정보</h3> + <div className="grid grid-cols-1 md:grid-cols-2 gap-4"> + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">프로젝트 ID</div> + <div className="text-sm">{selectedRfq.pspid}</div> + </div> + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">프로젝트명</div> + <div className="text-sm">{selectedRfq.projNm}</div> + </div> + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">선종</div> + <div className="text-sm">{selectedRfq.ptypeNm}</div> + </div> + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">척수</div> + <div className="text-sm">{selectedRfq.projMsrm}</div> + </div> + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">섹터</div> + <div className="text-sm">{selectedRfq.sector}</div> + </div> + </div> + </div> + + <Separator /> + + {/* 프로젝트 스냅샷 정보 */} + {projectSnapshot && ( + <div className="space-y-4"> + <h3 className="text-lg font-semibold">프로젝트 스냅샷</h3> + <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 gap-4"> + {projectSnapshot.scDt && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">S/C</div> + <div className="text-sm">{formatDateToQuarter(projectSnapshot.scDt)}</div> + </div> + )} + {projectSnapshot.klDt && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">K/L</div> + <div className="text-sm">{formatDateToQuarter(projectSnapshot.klDt)}</div> + </div> + )} + {projectSnapshot.lcDt && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">L/C</div> + <div className="text-sm">{formatDateToQuarter(projectSnapshot.lcDt)}</div> + </div> + )} + {projectSnapshot.dlDt && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">D/L</div> + <div className="text-sm">{formatDateToQuarter(projectSnapshot.dlDt)}</div> + </div> + )} + {projectSnapshot.dockNo && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">도크번호</div> + <div className="text-sm">{projectSnapshot.dockNo}</div> + </div> + )} + {projectSnapshot.dockNm && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">도크명</div> + <div className="text-sm">{projectSnapshot.dockNm}</div> + </div> + )} + {projectSnapshot.projNo && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">공사번호</div> + <div className="text-sm">{projectSnapshot.projNo}</div> + </div> + )} + {projectSnapshot.projNm && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">공사명</div> + <div className="text-sm">{projectSnapshot.projNm}</div> + </div> + )} + {projectSnapshot.ownerNm && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">선주</div> + <div className="text-sm">{projectSnapshot.ownerNm}</div> + </div> + )} + {projectSnapshot.kunnrNm && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">선주명</div> + <div className="text-sm">{projectSnapshot.kunnrNm}</div> + </div> + )} + {projectSnapshot.cls1Nm && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">선급명</div> + <div className="text-sm">{projectSnapshot.cls1Nm}</div> + </div> + )} + {projectSnapshot.projMsrm && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">척수</div> + <div className="text-sm">{projectSnapshot.projMsrm}</div> + </div> + )} + {projectSnapshot.ptypeNm && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">선종명</div> + <div className="text-sm">{projectSnapshot.ptypeNm}</div> + </div> + )} + {projectSnapshot.sector && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">섹터</div> + <div className="text-sm">{projectSnapshot.sector}</div> + </div> + )} + {projectSnapshot.estmPm && ( + <div className="space-y-2"> + <div className="text-sm font-medium text-muted-foreground">견적 PM</div> + <div className="text-sm">{projectSnapshot.estmPm}</div> + </div> + )} + </div> + </div> + )} + + {/* 시리즈 스냅샷 정보 */} + {seriesSnapshot && Array.isArray(seriesSnapshot) && seriesSnapshot.length > 0 && ( + <> + <Separator /> + <div className="space-y-4"> + <h3 className="text-lg font-semibold">시리즈 정보 스냅샷</h3> + <div className="space-y-4"> + {seriesSnapshot.map((series: SeriesSnapshot, index: number) => ( + <div key={index} className="border rounded-lg p-4 space-y-3"> + <div className="flex items-center gap-2"> + <Badge variant="secondary">시리즈 {series.sersNo || index + 1}</Badge> + </div> + <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"> + {series.scDt && ( + <div className="space-y-1"> + <div className="text-xs font-medium text-muted-foreground">S/C</div> + <div className="text-sm">{formatDateToQuarter(series.scDt)}</div> + </div> + )} + {series.klDt && ( + <div className="space-y-1"> + <div className="text-xs font-medium text-muted-foreground">K/L</div> + <div className="text-sm">{formatDateToQuarter(series.klDt)}</div> + </div> + )} + {series.lcDt && ( + <div className="space-y-1"> + <div className="text-xs font-medium text-muted-foreground">L/C</div> + <div className="text-sm">{formatDateToQuarter(series.lcDt)}</div> + </div> + )} + {series.dlDt && ( + <div className="space-y-1"> + <div className="text-xs font-medium text-muted-foreground">D/L</div> + <div className="text-sm">{formatDateToQuarter(series.dlDt)}</div> + </div> + )} + {series.dockNo && ( + <div className="space-y-1"> + <div className="text-xs font-medium text-muted-foreground">도크번호</div> + <div className="text-sm">{series.dockNo}</div> + </div> + )} + {series.dockNm && ( + <div className="space-y-1"> + <div className="text-xs font-medium text-muted-foreground">도크명</div> + <div className="text-sm">{series.dockNm}</div> + </div> + )} + </div> + </div> + ))} + </div> + </div> + </> + )} + + {/* 추가 정보가 없는 경우 */} + {!projectSnapshot && !seriesSnapshot && ( + <div className="text-center py-8 text-muted-foreground"> + 추가 프로젝트 상세정보가 없습니다. + </div> + )} + </div> + + {/* 닫기 버튼 */} + <div className="sticky bottom-0 left-0 z-20 bg-background border-t pt-4 mt-4"> + <div className="flex justify-end"> + <Button variant="outline" onClick={() => onOpenChange(false)}> + 닫기 + </Button> + </div> + </div> + </DialogContent> + </Dialog> + ) +}
\ No newline at end of file |
