summaryrefslogtreecommitdiff
path: root/lib/projects
diff options
context:
space:
mode:
Diffstat (limited to 'lib/projects')
-rw-r--r--lib/projects/dialog/project-detail-dialog.tsx431
-rw-r--r--lib/projects/table/projects-table-columns.tsx29
-rw-r--r--lib/projects/table/projects-table.tsx25
3 files changed, 481 insertions, 4 deletions
diff --git a/lib/projects/dialog/project-detail-dialog.tsx b/lib/projects/dialog/project-detail-dialog.tsx
new file mode 100644
index 00000000..2ecb37a5
--- /dev/null
+++ b/lib/projects/dialog/project-detail-dialog.tsx
@@ -0,0 +1,431 @@
+"use client"
+
+import * as React from "react"
+import { type Project } from "@/db/schema/projects"
+
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog"
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableRow,
+} from "@/components/ui/table"
+import { Badge } from "@/components/ui/badge"
+import { formatDate } from "@/lib/utils"
+
+interface ProjectDetailDialogProps {
+ project: Project
+ open: boolean
+ onOpenChange: (open: boolean) => void
+}
+
+export function ProjectDetailDialog({
+ project,
+ open,
+ onOpenChange,
+}: ProjectDetailDialogProps) {
+ const formatValue = (value: string | null | undefined) => {
+ return value || "-"
+ }
+
+ return (
+ <Dialog open={open} onOpenChange={onOpenChange}>
+ <DialogContent className="max-w-6xl h-[90vh] flex flex-col">
+ <DialogHeader className="flex-shrink-0">
+ <DialogTitle className="flex items-center gap-2">
+ 프로젝트 상세 정보
+ <Badge variant="outline">{project.code}</Badge>
+ </DialogTitle>
+ <DialogDescription>
+ 프로젝트코드: {project.code} | {project.name}
+ </DialogDescription>
+ </DialogHeader>
+
+ <div className="flex-1 overflow-y-auto min-h-0">
+ <div className="space-y-6 p-4">
+ <h3 className="text-lg font-semibold mb-3">프로젝트 전체 정보</h3>
+ <Table>
+ <TableBody>
+ {/* 기본 프로젝트 정보 */}
+ <TableRow>
+ <TableCell className="font-medium w-1/4">프로젝트 코드</TableCell>
+ <TableCell>{formatValue(project.code)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">프로젝트명</TableCell>
+ <TableCell>{formatValue(project.name)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">프로젝트 타입</TableCell>
+ <TableCell>
+ <Badge variant={project.type === "ship" ? "default" : "secondary"}>
+ {project.type === "ship" ? "조선" : "해양"}
+ </Badge>
+ </TableCell>
+ </TableRow>
+
+ {/* 선주 및 기본 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">선주명</TableCell>
+ <TableCell>{formatValue(project.OWN_NM)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">선주약어</TableCell>
+ <TableCell>{formatValue(project.OWN_AB)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">선주1</TableCell>
+ <TableCell>{formatValue(project.OWN_1)}</TableCell>
+ </TableRow>
+
+ {/* 선급 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">선급1</TableCell>
+ <TableCell>{formatValue(project.CLS_1)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">선급2</TableCell>
+ <TableCell>{formatValue(project.CLS_2)}</TableCell>
+ </TableRow>
+
+ {/* 선박 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">선종</TableCell>
+ <TableCell>{formatValue(project.SKND)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">선형</TableCell>
+ <TableCell>{formatValue(project.SHTYPE)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">선형코드</TableCell>
+ <TableCell>{formatValue(project.SHTYPE_CD)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">선형군</TableCell>
+ <TableCell>{formatValue(project.SHTYPE_GRP)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">선형단위</TableCell>
+ <TableCell>{formatValue(project.SHTYPE_UOM)}</TableCell>
+ </TableRow>
+
+ {/* 도크 및 건조 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">도크</TableCell>
+ <TableCell>{formatValue(project.DOCK_CD)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">기준호선</TableCell>
+ <TableCell>{formatValue(project.MSHIP_NO)}</TableCell>
+ </TableRow>
+
+ {/* 계약 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">계약일자</TableCell>
+ <TableCell>{formatValue(project.CNRT_DT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">계약인도일자</TableCell>
+ <TableCell>{formatValue(project.CNRT_DL_DT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">실인도일자</TableCell>
+ <TableCell>{formatValue(project.RL_DL_DT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">선표인도일자</TableCell>
+ <TableCell>{formatValue(project.BP_DL_DT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">Sail Away Date</TableCell>
+ <TableCell>{formatValue(project.SA_DT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">고객발주번호</TableCell>
+ <TableCell>{formatValue(project.CSTM_PO_NO)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">계약존속여부</TableCell>
+ <TableCell>{formatValue(project.CNRT_CNTN_YN)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">계약유보여부</TableCell>
+ <TableCell>{formatValue(project.CNRT_RESV_YN)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">전체 계약 대수</TableCell>
+ <TableCell>{formatValue(project.TOT_CNRT_CNT)}</TableCell>
+ </TableRow>
+
+ {/* 프로젝트 상태 */}
+ <TableRow>
+ <TableCell className="font-medium">진행상태</TableCell>
+ <TableCell>{formatValue(project.PRGS_STAT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">공사진행여부</TableCell>
+ <TableCell>{formatValue(project.PROJ_PRGS_YN)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">시작일자</TableCell>
+ <TableCell>{formatValue(project.STDT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">인터페이스 진행단계</TableCell>
+ <TableCell>{formatValue(project.IF_STAT)}</TableCell>
+ </TableRow>
+
+ {/* 기술 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">IMO 번호</TableCell>
+ <TableCell>{formatValue(project.IMO_NO)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">국적</TableCell>
+ <TableCell>{formatValue(project.NTTP)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">Main engine type code</TableCell>
+ <TableCell>{formatValue(project.MN_ENGN_TP_CD)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">관청명</TableCell>
+ <TableCell>{formatValue(project.GOV)}</TableCell>
+ </TableRow>
+
+ {/* 조직 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">사업부</TableCell>
+ <TableCell>{formatValue(project.BIZCLS)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">사업장코드</TableCell>
+ <TableCell>{formatValue(project.BIZLOC_CD)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">사업영역</TableCell>
+ <TableCell>{formatValue(project.BIZ_DMN)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">영업그룹</TableCell>
+ <TableCell>{formatValue(project.SALE_GRP)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">영업조직</TableCell>
+ <TableCell>{formatValue(project.SALE_ORG_CD)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">손익센터</TableCell>
+ <TableCell>{formatValue(project.PRCTR)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">설계담당자</TableCell>
+ <TableCell>{formatValue(project.DSN_CHRGR)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">회사코드</TableCell>
+ <TableCell>{formatValue(project.CO_CD)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">플랜트 코드</TableCell>
+ <TableCell>{formatValue(project.PLNT_CD)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">관리회계영역</TableCell>
+ <TableCell>{formatValue(project.MNG_ACOT_DMN)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">품질사업부</TableCell>
+ <TableCell>{formatValue(project.QM_CLS)}</TableCell>
+ </TableRow>
+
+ {/* 프로젝트 세부 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">프로젝트 세부타입</TableCell>
+ <TableCell>{formatValue(project.PROJ_DTL_TP)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">프로젝트 기타타입</TableCell>
+ <TableCell>{formatValue(project.PROJ_ETC_TP)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">프로젝트구분</TableCell>
+ <TableCell>{formatValue(project.PROJ_GB)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">프로젝트 프로파일</TableCell>
+ <TableCell>{formatValue(project.PROJ_PROF)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">프로젝트범위</TableCell>
+ <TableCell>{formatValue(project.PROJ_SCP)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">프로젝트 WBS타입</TableCell>
+ <TableCell>{formatValue(project.PROJ_WBS_TP)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">원본 TYPE</TableCell>
+ <TableCell>{formatValue(project.TYPE)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">(중국)프로젝트타입</TableCell>
+ <TableCell>{formatValue(project.CHN_PROJ_TP)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">(풍력)프로젝트타입</TableCell>
+ <TableCell>{formatValue(project.WP_PROJ_TP)}</TableCell>
+ </TableRow>
+
+ {/* 시리즈 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">시리즈여부</TableCell>
+ <TableCell>{formatValue(project.SERS_YN)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">시리즈첫공사번호</TableCell>
+ <TableCell>{formatValue(project.SERS_NO)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">시리즈번호</TableCell>
+ <TableCell>{formatValue(project.REF_NO)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">세대수/시리즈</TableCell>
+ <TableCell>{formatValue(project.GENT_CNT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">연관프로젝트</TableCell>
+ <TableCell>{formatValue(project.RLTD_PROJ)}</TableCell>
+ </TableRow>
+
+ {/* 제품 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">제품 Level 4</TableCell>
+ <TableCell>{formatValue(project.PDT_LVL_4)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">전기전자 제품군</TableCell>
+ <TableCell>{formatValue(project.DIGT_PDT_GRP)}</TableCell>
+ </TableRow>
+
+ {/* 프로젝트 관리 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">프로젝트 생성요청일</TableCell>
+ <TableCell>{formatValue(project.PROJ_CRTE_REQ_DT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">프로젝트 생성요청자</TableCell>
+ <TableCell>{formatValue(project.PROJ_CRTE_REQ_EMPNO)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">모프로젝트 인도계획일</TableCell>
+ <TableCell>{formatValue(project.PROJ_DL_PLN_DT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">모프로젝트 인도실적일</TableCell>
+ <TableCell>{formatValue(project.PROJ_DL_RT_DT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">프로포절 프로젝트</TableCell>
+ <TableCell>{formatValue(project.PRO_PROJ_NO)}</TableCell>
+ </TableRow>
+
+ {/* 안건 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">안건번호</TableCell>
+ <TableCell>{formatValue(project.INQY_NO)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">안건순번</TableCell>
+ <TableCell>{formatValue(project.INQY_SEQ)}</TableCell>
+ </TableRow>
+
+ {/* 보증 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">A/S 보증기간</TableCell>
+ <TableCell>{formatValue(project.AS_GRNT_PRD)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">Project Warranty Start Date</TableCell>
+ <TableCell>{formatValue(project.GRNT_STDT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">주문주 보증기간</TableCell>
+ <TableCell>{formatValue(project.ORDR_GRNT_PRD)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">주문주 보증종료일</TableCell>
+ <TableCell>{formatValue(project.ORDR_GRNT_FN_DT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">최종수요자 보증종료일</TableCell>
+ <TableCell>{formatValue(project.FIN_GRNT_FN_DT)}</TableCell>
+ </TableRow>
+
+ {/* 기타 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">MC YN</TableCell>
+ <TableCell>{formatValue(project.NEW_MC_YN)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">사내외 구분</TableCell>
+ <TableCell>{formatValue(project.IO_GB)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">유통경로</TableCell>
+ <TableCell>{formatValue(project.DIST_PATH)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">인도전선명</TableCell>
+ <TableCell>{formatValue(project.DL_BF_PROJ_NM)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">인도고객 ID</TableCell>
+ <TableCell>{formatValue(project.DL_CSTM_CD)}</TableCell>
+ </TableRow>
+
+ {/* 시스템 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">시스템회계마감일자</TableCell>
+ <TableCell>{formatValue(project.SYS_ACOT_CLSD_DT)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">Source System</TableCell>
+ <TableCell>{formatValue(project.SRC_SYS_ID)}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">삭제 여부</TableCell>
+ <TableCell>
+ {project.DEL_YN ? (
+ <Badge variant="destructive">삭제됨</Badge>
+ ) : (
+ <Badge variant="secondary">활성</Badge>
+ )}
+ </TableCell>
+ </TableRow>
+
+ {/* 생성/수정 정보 */}
+ <TableRow>
+ <TableCell className="font-medium">생성일시</TableCell>
+ <TableCell>{formatDate(project.createdAt, "KR")}</TableCell>
+ </TableRow>
+ <TableRow>
+ <TableCell className="font-medium">수정일시</TableCell>
+ <TableCell>{formatDate(project.updatedAt, "KR")}</TableCell>
+ </TableRow>
+ </TableBody>
+ </Table>
+ </div>
+ </div>
+ </DialogContent>
+ </Dialog>
+ )
+}
diff --git a/lib/projects/table/projects-table-columns.tsx b/lib/projects/table/projects-table-columns.tsx
index 6926429a..95eeae85 100644
--- a/lib/projects/table/projects-table-columns.tsx
+++ b/lib/projects/table/projects-table-columns.tsx
@@ -3,8 +3,10 @@
import * as React from "react"
import { type DataTableRowAction } from "@/types/table"
import { type ColumnDef } from "@tanstack/react-table"
+import { Eye } from "lucide-react"
import { formatDate } from "@/lib/utils"
+import { Button } from "@/components/ui/button"
import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"
import { Project } from "@/db/schema"
@@ -12,13 +14,35 @@ import { projectsColumnsConfig } from "@/config/projectsColumnsConfig"
interface GetColumnsProps {
setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<Project> | null>>
+ onDetailClick: (project: Project) => void
}
/**
* tanstack table 컬럼 정의 (중첩 헤더 버전)
*/
-export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<Project>[] {
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+export function getColumns({ setRowAction, onDetailClick }: GetColumnsProps): ColumnDef<Project>[] {
+ // 상세보기 버튼 컬럼
+ const detailColumn: ColumnDef<Project> = {
+ id: "action",
+ header: "상세보기",
+ size: 100,
+ cell: ({ row }) => {
+ const project = row.original
+ return (
+ <Button
+ variant="ghost"
+ size="sm"
+ onClick={() => onDetailClick(project)}
+ className="h-8 w-8 p-0"
+ >
+ <Eye className="h-4 w-4" />
+ <span className="sr-only">상세보기</span>
+ </Button>
+ )
+ },
+ }
// ----------------------------------------------------------------
// 3) 일반 컬럼들을 "그룹"별로 묶어 중첩 columns 생성
@@ -82,9 +106,10 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<Project
})
// ----------------------------------------------------------------
- // 4) 최종 컬럼 배열: select, nestedColumns, actions
+ // 4) 최종 컬럼 배열: detailColumn, nestedColumns
// ----------------------------------------------------------------
return [
+ detailColumn,
...nestedColumns,
]
} \ No newline at end of file
diff --git a/lib/projects/table/projects-table.tsx b/lib/projects/table/projects-table.tsx
index 3da54b7c..462e8638 100644
--- a/lib/projects/table/projects-table.tsx
+++ b/lib/projects/table/projects-table.tsx
@@ -16,6 +16,7 @@ import { getColumns } from "./projects-table-columns"
import { getProjectLists } from "../service"
import { Project } from "@/db/schema"
import { ProjectTableToolbarActions } from "./projects-table-toolbar-actions"
+import { ProjectDetailDialog } from "@/lib/projects/dialog/project-detail-dialog"
interface ItemsTableProps {
promises: Promise<
@@ -26,17 +27,28 @@ interface ItemsTableProps {
}
export function ProjectsTable({ promises }: ItemsTableProps) {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
const { featureFlags } = useFeatureFlags()
const [{ data, pageCount }] =
React.use(promises)
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
const [rowAction, setRowAction] =
React.useState<DataTableRowAction<Project> | null>(null)
+ // 상세보기 다이얼로그 상태 관리
+ const [selectedProject, setSelectedProject] = React.useState<Project | null>(null)
+ const [dialogOpen, setDialogOpen] = React.useState(false)
+
+ const handleDetailClick = React.useCallback((project: Project) => {
+ setSelectedProject(project)
+ setDialogOpen(true)
+ }, [])
+
const columns = React.useMemo(
- () => getColumns({ setRowAction }),
- [setRowAction]
+ () => getColumns({ setRowAction, onDetailClick: handleDetailClick }),
+ [setRowAction, handleDetailClick]
)
/**
@@ -123,6 +135,15 @@ export function ProjectsTable({ promises }: ItemsTableProps) {
<ProjectTableToolbarActions table={table} />
</DataTableAdvancedToolbar>
</DataTable>
+
+ {/* 프로젝트 상세보기 다이얼로그 */}
+ {selectedProject && (
+ <ProjectDetailDialog
+ project={selectedProject}
+ open={dialogOpen}
+ onOpenChange={setDialogOpen}
+ />
+ )}
</>
)
}