diff --git a/apps/as/src/entities/elapr/lib/approval-utils.ts b/apps/as/src/entities/elapr/lib/approval-utils.ts index 00d7d7b2a..831c06949 100644 --- a/apps/as/src/entities/elapr/lib/approval-utils.ts +++ b/apps/as/src/entities/elapr/lib/approval-utils.ts @@ -6,11 +6,26 @@ export interface ApproverStatusConfig { } export const APPROVER_STATUS_MAP: Record = { - ATRZ_PRGRS_001: { label: "대기", badgeClass: "bg-gray-100 text-gray-700" }, - ATRZ_PRGRS_002: { label: "요청", badgeClass: "bg-yellow-100 text-yellow-700" }, - ATRZ_PRGRS_003: { label: "승인", badgeClass: "bg-green-100 text-green-700" }, - ATRZ_PRGRS_004: { label: "반려", badgeClass: "bg-red-100 text-red-700" }, - ATRZ_PRGRS_999: { label: "결재안함", badgeClass: "bg-blue-100 text-blue-700" }, + ATRZ_PRGRS_001: { + label: "대기", + badgeClass: "bg-gray-100 text-gray-700", + }, + ATRZ_PRGRS_002: { + label: "결재요청", + badgeClass: "bg-yellow-100 text-yellow-700", + }, + ATRZ_PRGRS_003: { + label: "결재승인", + badgeClass: "bg-green-100 text-green-700", + }, + ATRZ_PRGRS_004: { + label: "반려", + badgeClass: "bg-red-100 text-red-700", + }, + ATRZ_PRGRS_999: { + label: "결재안함", + badgeClass: "bg-blue-100 text-blue-700", + }, }; export function sortByAtrzSeqNo( @@ -19,10 +34,19 @@ export function sortByAtrzSeqNo( return list.slice().sort((a, b) => Number(a.atrzSeqNo ?? 0) - Number(b.atrzSeqNo ?? 0)); } -export function getApproverStatus(status: string | undefined): ApproverStatusConfig { +export function getApproverStatus( + atrzPrgrsSttsComCd?: string, + atrzSeComCd?: string, +): ApproverStatusConfig { + if (atrzPrgrsSttsComCd === "ATRZ_PRGRS_003" && atrzSeComCd === "ATRZ01") + return { + label: "기술검토 접수", + badgeClass: "bg-green-100 text-green-700", + }; + return ( - APPROVER_STATUS_MAP[status ?? ""] ?? { - label: status || "-", + APPROVER_STATUS_MAP[atrzPrgrsSttsComCd ?? ""] ?? { + label: "-", badgeClass: "bg-gray-100 text-gray-700", } ); diff --git a/apps/as/src/entities/elapr/ui/elapr-approval-dialog.tsx b/apps/as/src/entities/elapr/ui/elapr-approval-dialog.tsx index c4cb3956d..ad9abfa3e 100644 --- a/apps/as/src/entities/elapr/ui/elapr-approval-dialog.tsx +++ b/apps/as/src/entities/elapr/ui/elapr-approval-dialog.tsx @@ -314,8 +314,8 @@ function ElaprApprovalDialog({ - - + + diff --git a/apps/as/src/entities/elapr/ui/elapr-doc-prgrs-status.tsx b/apps/as/src/entities/elapr/ui/elapr-doc-prgrs-status.tsx index 731e39a07..4be4cf0c3 100644 --- a/apps/as/src/entities/elapr/ui/elapr-doc-prgrs-status.tsx +++ b/apps/as/src/entities/elapr/ui/elapr-doc-prgrs-status.tsx @@ -4,7 +4,9 @@ import { Fragment } from "react"; import { ChevronRight } from "lucide-react"; +import { dayjs, useUserStore } from "@/shared/lib"; import type { ElaprDocPrgrsClientResponseDto } from "@/shared/model"; +import { SectionCollapsible } from "@/shared/ui"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/shared/ui/tooltip"; import { cn, Skeleton } from "@common/components"; @@ -18,7 +20,7 @@ interface ElaprDocPrgrsStatusProps { } function ElaprDocPrgrsStep({ item }: { item: ElaprDocPrgrsClientResponseDto }) { - const status = getApproverStatus(item.atrzPrgrsSttsComCd); + const status = getApproverStatus(item.atrzPrgrsSttsComCd, item.atrzSeComCd); const isRejected = item.atrzPrgrsSttsComCd === REJECT_STATUS_CD; const rjctRsn = item.rjctRsn?.trim(); const metaParts = [item.ognzNm, item.jbpsSeNm].filter(Boolean); @@ -26,7 +28,7 @@ function ElaprDocPrgrsStep({ item }: { item: ElaprDocPrgrsClientResponseDto }) { const statusBadge = ( +
{isRejected && rjctRsn ? ( {statusBadge} @@ -49,11 +51,16 @@ function ElaprDocPrgrsStep({ item }: { item: ElaprDocPrgrsClientResponseDto }) { )}
- [{item.atrzSeComNm || "-"}] - {item.aprvrNm || item.aprvrUuid || "-"} +

+ [{item.atrzSeComNm || "-"}]{" "} + {item.aprvrNm || item.aprvrUuid || "-"} +

{metaParts.length > 0 && ( - {metaParts.join(" · ")} + {metaParts.join(" · ")} + )} + {item.atrzDt && ( + {dayjs(item.atrzDt).format("YYYY-MM-DD")} )}
@@ -61,34 +68,45 @@ function ElaprDocPrgrsStep({ item }: { item: ElaprDocPrgrsClientResponseDto }) { } function ElaprDocPrgrsStatus({ elaprDocNo }: ElaprDocPrgrsStatusProps) { + const userInfo = useUserStore((state) => state.userInfo); const { data, isLoading } = useElaprDocPrgrsByDocNo(elaprDocNo); const steps = sortByAtrzSeqNo(data ?? []); + if (userInfo?.dtlInstCd !== "ROLE_USER01") { + return null; + } + if (isLoading) { return ( -
- - - -
+ +
+ + + +
+
); } if (steps.length === 0) { - return
결재 정보가 없습니다.
; + return null; } return ( -
- {steps.map((item, index) => ( - -
- {index > 0 && } -
- -
- ))} -
+ +
+ {steps.map((item, index) => ( + + {index > 0 && ( +
+ {} +
+ )} + +
+ ))} +
+
); } diff --git a/apps/as/src/entities/elapr/ui/sortable-prgrs-stts-row.tsx b/apps/as/src/entities/elapr/ui/sortable-prgrs-stts-row.tsx index 601d272f2..3c2bb457a 100644 --- a/apps/as/src/entities/elapr/ui/sortable-prgrs-stts-row.tsx +++ b/apps/as/src/entities/elapr/ui/sortable-prgrs-stts-row.tsx @@ -73,14 +73,14 @@ function SortablePrgrsSttsRow({ const isDcarbable = isPrgrsSttsRowDcarbable(row); const rowDisabled = isLocked && !isEditing; const atrzSeLabel = row.atrzSeComNm || findCodeLabel(atrzSeCodes, row.atrzSeComCd); - const status = getApproverStatus(row.atrzPrgrsSttsComCd); + const status = getApproverStatus(row.atrzPrgrsSttsComCd, row.atrzSeComCd); const isRejectedRow = row.atrzPrgrsSttsComCd === "ATRZ_PRGRS_004"; const rjctRsn = row.rjctRsn?.trim(); const statusBadge = ( (); const MAIN_STEP_LABELS = { - save: "저장", - apply: "신청완료", - review: "설계자문 검토", - reply: "설계검토 회신", + apply: "설계자문 신청", + techReview: "기술검토", + reply: "검토결과 회신", } as const; -const REVIEW_STATUS_CODES = new Set(["CS", "CR"]); +export const PROGRESS_STATUS_COLUMNS = [ + { label: "설계자문 신청 (시군)", sttsComCd: "ER" }, + { label: "기술검토", sttsComCd: "TE" }, + { label: "기술검토 회신", sttsComCd: "CP" }, +]; -type BadgeState = "completed" | "current" | "pending" | "action"; +type BadgeState = "completed" | "current" | "pending"; interface ProgressBadge { label: string; state: BadgeState; } -function buildProgressBadges(prgrsSttsComCd: string, prgrsSttsCdNm: string): ProgressBadge[] { - const reviewLabel = prgrsSttsCdNm || MAIN_STEP_LABELS.review; - const replyLabel = prgrsSttsCdNm || MAIN_STEP_LABELS.reply; - +function buildProgressBadges(prgrsSttsComCd: string): ProgressBadge[] { if (prgrsSttsComCd === "CV") { return [ - { label: MAIN_STEP_LABELS.save, state: "current" }, { label: MAIN_STEP_LABELS.apply, state: "pending" }, - { label: MAIN_STEP_LABELS.review, state: "pending" }, + { label: MAIN_STEP_LABELS.techReview, state: "pending" }, { label: MAIN_STEP_LABELS.reply, state: "pending" }, ]; } - if (prgrsSttsComCd === "CT") { + if (prgrsSttsComCd === "ER" || prgrsSttsComCd === "CS" || prgrsSttsComCd === "SL") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, - { label: MAIN_STEP_LABELS.apply, state: "current" }, - { label: MAIN_STEP_LABELS.review, state: "pending" }, - { label: MAIN_STEP_LABELS.reply, state: "pending" }, - ]; - } - - if (REVIEW_STATUS_CODES.has(prgrsSttsComCd)) { - return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "completed" }, - { label: reviewLabel, state: "action" }, + { label: MAIN_STEP_LABELS.techReview, state: "current" }, { label: MAIN_STEP_LABELS.reply, state: "pending" }, ]; } - if (prgrsSttsComCd === "CP" || prgrsSttsComCd === "EP") { + if (prgrsSttsComCd === "CP") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "completed" }, - { label: MAIN_STEP_LABELS.review, state: "completed" }, - { label: replyLabel, state: "action" }, + { label: MAIN_STEP_LABELS.techReview, state: "completed" }, + { label: MAIN_STEP_LABELS.reply, state: "completed" }, ]; } - return [{ label: prgrsSttsCdNm || prgrsSttsComCd || "-", state: "current" }]; + return [ + { label: MAIN_STEP_LABELS.apply, state: "pending" }, + { label: MAIN_STEP_LABELS.techReview, state: "pending" }, + { label: MAIN_STEP_LABELS.reply, state: "pending" }, + ]; } function getBadgeColor(state: BadgeState) { @@ -77,8 +69,6 @@ function getBadgeColor(state: BadgeState) { return "blue"; case "pending": return "lightGray"; - case "action": - return "orange"; } } @@ -88,11 +78,10 @@ function formatOptional(value: string | undefined) { interface ProgressStepBadgeProps { prgrsSttsComCd: string; - prgrsSttsCdNm: string; } -function ProgressStepBadge({ prgrsSttsComCd, prgrsSttsCdNm }: ProgressStepBadgeProps) { - const badges = buildProgressBadges(prgrsSttsComCd, prgrsSttsCdNm); +function ProgressStepBadge({ prgrsSttsComCd }: ProgressStepBadgeProps) { + const badges = buildProgressBadges(prgrsSttsComCd); return (
@@ -142,12 +131,7 @@ export function createDesignCnstnColumns() { id: "progress", header: "진행상황", meta: { align: "center" }, - cell: ({ row }) => ( - - ), + cell: ({ row }) => , }), columnHelper.accessor("regDt", { header: "신청일", diff --git a/apps/as/src/pages/design-cnstn/ui/design-form-page.tsx b/apps/as/src/pages/design-cnstn/ui/design-form-page.tsx index b9bc230d9..e1a0ced7e 100644 --- a/apps/as/src/pages/design-cnstn/ui/design-form-page.tsx +++ b/apps/as/src/pages/design-cnstn/ui/design-form-page.tsx @@ -22,6 +22,7 @@ import { ContactInfoFormSection, isFormEsntlAtchComplete, PrivacyConsentSection, + ProgressStatusSection, } from "@/widgets/pbadms-sprt"; import { Button } from "@common/components"; @@ -31,6 +32,7 @@ import { formatTaskSeComCdForApi, } from "../lib/design-cnstn-regist-schema"; import { getCreateDefaultValues, mapDetailToFormData } from "../lib/form-data-mapper"; +import { PROGRESS_STATUS_COLUMNS } from "../model/columns"; import { BasicInfoFormSection } from "./sections/basic-info-form-section"; @@ -174,6 +176,13 @@ function DesignFormPage({ id, mode, initialData, createDefaults }: DesignFormPag return (
+ {initialData?.detDto?.designCnstnDocNo && ( + + )} diff --git a/apps/as/src/pages/design-cnstn/ui/design-view-page.tsx b/apps/as/src/pages/design-cnstn/ui/design-view-page.tsx index aefd42317..cc4315025 100644 --- a/apps/as/src/pages/design-cnstn/ui/design-view-page.tsx +++ b/apps/as/src/pages/design-cnstn/ui/design-view-page.tsx @@ -6,11 +6,12 @@ import { useUserStore } from "@/shared/lib"; import { useDesignCnstnMng } from "@/entities/design-cnstn"; import { ElaprDocPrgrsStatus } from "@/entities/elapr"; import { useRvwMnpwMngLoginUserList } from "@/entities/rvw-mnpw"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; +import { ProgressStatusSection } from "@/widgets/pbadms-sprt"; import { Skeleton } from "@common/components"; import { needsRoleUser01AtrzResolve } from "../lib/button-config"; import { getEditableReviewStep } from "../lib/review-step-utils"; +import { PROGRESS_STATUS_COLUMNS } from "../model/columns"; import { FloatingActionButtons } from "./components/floating-action-buttons"; import { AttachmentsSection } from "./sections/attachments-section"; @@ -65,11 +66,14 @@ function DesignViewPage({ id }: DesignViewPageProps) { return
상세 정보를 찾을 수 없습니다.
; } - const detDto = data.detDto; - const bizSclList = data.bizSclList ?? []; - const esntlFileList = data.esntlFileList ?? []; - const etcFileList = data.etcFileList ?? []; - const rvwList = data.rvwList ?? []; + const { + detDto, + bizSclList = [], + esntlFileList = [], + etcFileList = [], + rvwList = [], + sttsChgHstryList = [], + } = data; const editableReviewStep = getEditableReviewStep( userInfo?.dtlInstCd, @@ -78,11 +82,14 @@ function DesignViewPage({ id }: DesignViewPageProps) { return (
+ - - - + (); const MAIN_STEP_LABELS = { - save: "저장", - apply: "신청완료", + apply: "재원협의 신청", + envoReview: "환경청 검토", techReview: "기술검토", reply: "검토결과 회신", } as const; -const TECH_REVIEW_STATUS_CODES = new Set(["LE", "ER", "EE", "TE", "TS", "TR", "TP"]); +export const PROGRESS_STATUS_COLUMNS = [ + { label: "재원협의 신청 (시군)", sttsComCd: "ST" }, + { label: "재원협의 신청 (시도)", sttsComCd: "LE" }, + { label: "환경청 검토", sttsComCd: "ER" }, + { label: "기술검토", sttsComCd: "TE" }, + { label: "기술검토 회신", sttsComCd: "TP" }, + { label: "환경청 검토 결과 회신", sttsComCd: "EP" }, +]; -type BadgeState = "completed" | "current" | "pending" | "action"; +type BadgeState = "completed" | "current" | "pending"; interface ProgressBadge { label: string; state: BadgeState; } -function buildProgressBadges(prgrsSttsComCd: string, prgrsSttsCdNm: string): ProgressBadge[] { - const techReviewLabel = prgrsSttsCdNm || MAIN_STEP_LABELS.techReview; - const replyLabel = prgrsSttsCdNm || MAIN_STEP_LABELS.reply; - +function buildProgressBadges(prgrsSttsComCd: string, techRplyHstryYn: "Y" | "N"): ProgressBadge[] { if (prgrsSttsComCd === "SV") { return [ - { label: MAIN_STEP_LABELS.save, state: "current" }, { label: MAIN_STEP_LABELS.apply, state: "pending" }, + { label: MAIN_STEP_LABELS.envoReview, state: "pending" }, { label: MAIN_STEP_LABELS.techReview, state: "pending" }, { label: MAIN_STEP_LABELS.reply, state: "pending" }, ]; @@ -41,41 +45,61 @@ function buildProgressBadges(prgrsSttsComCd: string, prgrsSttsCdNm: string): Pro if (prgrsSttsComCd === "ST") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "current" }, + { label: MAIN_STEP_LABELS.envoReview, state: "pending" }, { label: MAIN_STEP_LABELS.techReview, state: "pending" }, { label: MAIN_STEP_LABELS.reply, state: "pending" }, ]; } - if (TECH_REVIEW_STATUS_CODES.has(prgrsSttsComCd)) { + if (prgrsSttsComCd === "LE") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "completed" }, - { label: techReviewLabel, state: "action" }, + { label: MAIN_STEP_LABELS.envoReview, state: "current" }, + { label: MAIN_STEP_LABELS.techReview, state: "pending" }, { label: MAIN_STEP_LABELS.reply, state: "pending" }, ]; } + if (prgrsSttsComCd === "ER" || prgrsSttsComCd === "TE" || prgrsSttsComCd === "SL") { + return [ + { label: MAIN_STEP_LABELS.apply, state: "completed" }, + { label: MAIN_STEP_LABELS.envoReview, state: "completed" }, + { label: MAIN_STEP_LABELS.techReview, state: "current" }, + { label: MAIN_STEP_LABELS.reply, state: "pending" }, + ]; + } + + if (prgrsSttsComCd === "TP") { + return [ + { label: MAIN_STEP_LABELS.apply, state: "completed" }, + { label: MAIN_STEP_LABELS.envoReview, state: "completed" }, + { + label: MAIN_STEP_LABELS.techReview, + state: techRplyHstryYn === "Y" ? "completed" : "pending", + }, + { label: MAIN_STEP_LABELS.reply, state: "current" }, + ]; + } + if (prgrsSttsComCd === "EP") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "completed" }, - { label: MAIN_STEP_LABELS.techReview, state: "completed" }, - { label: replyLabel, state: "action" }, - ]; - } - - if (prgrsSttsComCd === "TA" || prgrsSttsComCd === "TB") { - return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, - { label: MAIN_STEP_LABELS.apply, state: "completed" }, - { label: MAIN_STEP_LABELS.techReview, state: "completed" }, + { label: MAIN_STEP_LABELS.envoReview, state: "completed" }, + { + label: MAIN_STEP_LABELS.techReview, + state: techRplyHstryYn === "Y" ? "completed" : "pending", + }, { label: MAIN_STEP_LABELS.reply, state: "completed" }, ]; } - return [{ label: prgrsSttsCdNm || prgrsSttsComCd || "-", state: "current" }]; + return [ + { label: MAIN_STEP_LABELS.apply, state: "pending" }, + { label: MAIN_STEP_LABELS.envoReview, state: "pending" }, + { label: MAIN_STEP_LABELS.techReview, state: "pending" }, + { label: MAIN_STEP_LABELS.reply, state: "pending" }, + ]; } function getBadgeColor(state: BadgeState) { @@ -86,8 +110,6 @@ function getBadgeColor(state: BadgeState) { return "blue"; case "pending": return "lightGray"; - case "action": - return "orange"; } } @@ -97,11 +119,11 @@ function formatOptional(value: string | undefined) { interface ProgressStepBadgeProps { prgrsSttsComCd: string; - prgrsSttsCdNm: string; + techRplyHstryYn: "Y" | "N"; } -function ProgressStepBadge({ prgrsSttsComCd, prgrsSttsCdNm }: ProgressStepBadgeProps) { - const badges = buildProgressBadges(prgrsSttsComCd, prgrsSttsCdNm); +function ProgressStepBadge({ prgrsSttsComCd, techRplyHstryYn }: ProgressStepBadgeProps) { + const badges = buildProgressBadges(prgrsSttsComCd, techRplyHstryYn); return (
@@ -154,7 +176,7 @@ export function createFnrsCnsltnColumns() { cell: ({ row }) => ( ), }), diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/fnrs-form-page.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/fnrs-form-page.tsx index 5a4222553..e189e28f6 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/fnrs-form-page.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/fnrs-form-page.tsx @@ -30,6 +30,7 @@ import { isFormChecklistComplete, isFormEsntlAtchComplete, PrivacyConsentSection, + ProgressStatusSection, recalculateFnrsSharTotals, SplmntDmndFormSection, toFnrsSharSaveList, @@ -43,6 +44,7 @@ import { formatTaskSeComCdForApi, } from "../lib/fnrs-cnsltn-regist-schema"; import { getCreateDefaultValues, mapDetailToFormData } from "../lib/form-data-mapper"; +import { PROGRESS_STATUS_COLUMNS } from "../model/columns"; import { BasicInfoFormSection } from "./sections/basic-info-form-section"; interface FnrsFormPageProps { @@ -270,6 +272,13 @@ function FnrsFormPage({ id, mode, initialData, createDefaults }: FnrsFormPagePro return ( + {initialData?.detDto?.fnrsCnsltnDocNo && ( + + )} diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/fnrs-view-page.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/fnrs-view-page.tsx index 3ec2522d1..6fa957d44 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/fnrs-view-page.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/fnrs-view-page.tsx @@ -6,12 +6,13 @@ import { useUserStore } from "@/shared/lib"; import { ElaprDocPrgrsStatus } from "@/entities/elapr"; import { useFnrsCnsltnMng } from "@/entities/fnrs-cnsltn"; import { useRvwMnpwMngLoginUserList } from "@/entities/rvw-mnpw"; -import { SectionCollapsible, SupplementDemandSection } from "@/widgets/pbadms-sprt"; +import { ProgressStatusSection, SupplementDemandSection } from "@/widgets/pbadms-sprt"; import { Skeleton } from "@common/components"; import { needsRoleUser01AtrzResolve } from "../lib/button-config"; import { getEditableReviewStep } from "../lib/review-step-utils"; import { EMPTY_CKLST_RESULT_LIST, useChecklistFormState } from "../lib/use-checklist-form-state"; +import { PROGRESS_STATUS_COLUMNS } from "../model/columns"; import { FloatingActionButtons } from "./components/floating-action-buttons"; import { AttachmentsSection } from "./sections/attachments-section"; @@ -71,15 +72,18 @@ function FnrsViewPage({ id }: FnrsViewPageProps) { return
상세 정보를 찾을 수 없습니다.
; } - const detDto = data.detDto; - const bizSclList = data.bizSclList ?? []; - const bizCstList = data.bizCstList ?? []; - const cklstResultList = data.cklstResultList ?? []; - const esntlFileList = data.esntlFileList ?? []; - const etcFileList = data.etcFileList ?? []; - const rvwList = data.rvwList ?? []; - const splmntDmndList = data.splmntDmndList ?? []; - const fnrsSharList = data.fnrsSharList ?? []; + const { + detDto, + bizSclList = [], + bizCstList = [], + cklstResultList = [], + esntlFileList = [], + etcFileList = [], + rvwList = [], + splmntDmndList = [], + fnrsSharList = [], + sttsChgHstryList = [], + } = data; const editableReviewStep = getEditableReviewStep( userInfo?.dtlInstCd, @@ -88,11 +92,14 @@ function FnrsViewPage({ id }: FnrsViewPageProps) { return (
+ - - - + diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/sections/attachments-section.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/sections/attachments-section.tsx index 0ac529c18..b55b87c47 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/sections/attachments-section.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/sections/attachments-section.tsx @@ -1,12 +1,12 @@ "use client"; import { formatFileSize } from "@/shared/lib/file-utils"; +import { SectionCollapsible } from "@/shared/ui"; import { useDownloadAttachmentByAtflCd } from "@/entities/attach"; import type { AtflMngClientResponseDto, EsntlAtchFileMngTreeResponseDto, } from "@/entities/fnrs-cnsltn"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; interface AttachmentsSectionProps { diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/sections/basic-info-form-section.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/sections/basic-info-form-section.tsx index 751312ac6..759b1f0df 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/sections/basic-info-form-section.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/sections/basic-info-form-section.tsx @@ -3,10 +3,10 @@ import { useState } from "react"; import { Controller, useFormContext } from "react-hook-form"; +import { SectionCollapsible } from "@/shared/ui"; import { Field, FieldError, FieldGroup, FieldLabel, FieldSet } from "@/shared/ui/field"; import { findCodeLabel, useCodeList } from "@/entities/code"; import { type BnsApplyData, BnsPickerDialog } from "@/widgets/bns-picker"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Button, Checkbox, diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/sections/basic-info-section.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/sections/basic-info-section.tsx index 939af68fd..48f14eceb 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/sections/basic-info-section.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/sections/basic-info-section.tsx @@ -1,7 +1,7 @@ "use client"; +import { SectionCollapsible } from "@/shared/ui"; import type { FnrsCnsltnMngResponseDto } from "@/entities/fnrs-cnsltn"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Table, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; interface BasicInfoSectionProps { diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/sections/business-cost-section.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/sections/business-cost-section.tsx index 285fe8bed..d880811b6 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/sections/business-cost-section.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/sections/business-cost-section.tsx @@ -2,9 +2,9 @@ import { useMemo } from "react"; +import { SectionCollapsible } from "@/shared/ui"; import type { BizCstTreeDto } from "@/entities/fnrs-cnsltn"; import { calcDiffPercent, fmtNumber, indentPx } from "@/widgets/pbadms-sprt"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; import { sortBizCstListByTreePath } from "../../lib/business-cost-utils"; diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/sections/business-scale-section.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/sections/business-scale-section.tsx index f8849cf8f..c1f5a28af 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/sections/business-scale-section.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/sections/business-scale-section.tsx @@ -1,8 +1,8 @@ "use client"; +import { SectionCollapsible } from "@/shared/ui"; import type { BizSclTreeDto } from "@/entities/fnrs-cnsltn"; import { fmtNumber, indentPx } from "@/widgets/pbadms-sprt"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; interface BusinessScaleSectionProps { diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/sections/checklist-section.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/sections/checklist-section.tsx index 09aa48052..e50f5a6b8 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/sections/checklist-section.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/sections/checklist-section.tsx @@ -2,8 +2,8 @@ import { type Dispatch, type SetStateAction, useEffect, useMemo, useState } from "react"; +import { SectionCollapsible } from "@/shared/ui"; import type { CklstRvwRsltTreeDto } from "@/entities/fnrs-cnsltn"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@common/components"; import { diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/sections/contact-info-section.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/sections/contact-info-section.tsx index 7443460e8..f5273fb33 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/sections/contact-info-section.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/sections/contact-info-section.tsx @@ -1,7 +1,7 @@ "use client"; +import { SectionCollapsible } from "@/shared/ui"; import type { FnrsCnsltnMngResponseDto } from "@/entities/fnrs-cnsltn"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Table, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; interface ContactInfoSectionProps { diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/sections/fnrs-shar-section.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/sections/fnrs-shar-section.tsx index 198261c41..ad83c53e4 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/sections/fnrs-shar-section.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/sections/fnrs-shar-section.tsx @@ -2,8 +2,9 @@ import { useMemo } from "react"; +import { SectionCollapsible } from "@/shared/ui"; import type { FnrsSharBizCstTreeDto } from "@/entities/fnrs-shar-se"; -import { fmtNumber, indentPx, SectionCollapsible } from "@/widgets/pbadms-sprt"; +import { fmtNumber, indentPx } from "@/widgets/pbadms-sprt"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; interface FnrsSharSectionProps { diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/sections/tech-review-opinion-section.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/sections/tech-review-opinion-section.tsx index f8d416af1..bdbd4e622 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/sections/tech-review-opinion-section.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/sections/tech-review-opinion-section.tsx @@ -7,10 +7,10 @@ import { Paperclip } from "lucide-react"; import { PROXY_HOST } from "@/shared/config"; import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib"; import { TextShimmer } from "@/shared/ui"; +import { SectionCollapsible } from "@/shared/ui"; import { Field, FieldLabel, FieldSet } from "@/shared/ui/field"; import { attachService } from "@/entities/attach"; import type { FnrsCnsltnRvwOpnnResponseDto } from "@/entities/fnrs-cnsltn"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Button, RadioGroup, diff --git a/apps/as/src/pages/instl-sncn/model/columns.tsx b/apps/as/src/pages/instl-sncn/model/columns.tsx index 772e20df0..2dcca5c58 100644 --- a/apps/as/src/pages/instl-sncn/model/columns.tsx +++ b/apps/as/src/pages/instl-sncn/model/columns.tsx @@ -11,29 +11,34 @@ import { Badge } from "@common/components"; const columnHelper = createColumnHelper(); const MAIN_STEP_LABELS = { - save: "저장", - apply: "신청완료", + apply: "설치인가 신청", + envoReview: "환경청 검토", techReview: "기술검토", reply: "검토결과 회신", } as const; -const TECH_REVIEW_STATUS_CODES = new Set(["LE", "ER", "EE", "TE", "TS", "TR", "TP"]); +export const PROGRESS_STATUS_COLUMNS = [ + { label: "설치인가 신청 (시군)", sttsComCd: "ST" }, + { label: "설치인가 신청 (시도)", sttsComCd: "LE" }, + { label: "환경청 검토", sttsComCd: "ER" }, + { label: "기술검토", sttsComCd: "TE" }, + { label: "기술검토 회신", sttsComCd: "TP" }, + { label: "검토결과 회신", sttsComCd: "EP" }, + { label: "설치인가 승인", sttsComCd: "TA" }, +]; -type BadgeState = "completed" | "current" | "pending" | "action"; +type BadgeState = "completed" | "current" | "pending"; interface ProgressBadge { label: string; state: BadgeState; } -function buildProgressBadges(prgrsSttsComCd: string, prgrsSttsCdNm: string): ProgressBadge[] { - const techReviewLabel = prgrsSttsCdNm || MAIN_STEP_LABELS.techReview; - const replyLabel = prgrsSttsCdNm || MAIN_STEP_LABELS.reply; - +function buildProgressBadges(prgrsSttsComCd: string, techRplyHstryYn: "Y" | "N"): ProgressBadge[] { if (prgrsSttsComCd === "SV") { return [ - { label: MAIN_STEP_LABELS.save, state: "current" }, { label: MAIN_STEP_LABELS.apply, state: "pending" }, + { label: MAIN_STEP_LABELS.envoReview, state: "pending" }, { label: MAIN_STEP_LABELS.techReview, state: "pending" }, { label: MAIN_STEP_LABELS.reply, state: "pending" }, ]; @@ -41,41 +46,61 @@ function buildProgressBadges(prgrsSttsComCd: string, prgrsSttsCdNm: string): Pro if (prgrsSttsComCd === "ST") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "current" }, + { label: MAIN_STEP_LABELS.envoReview, state: "pending" }, { label: MAIN_STEP_LABELS.techReview, state: "pending" }, { label: MAIN_STEP_LABELS.reply, state: "pending" }, ]; } - if (TECH_REVIEW_STATUS_CODES.has(prgrsSttsComCd)) { + if (prgrsSttsComCd === "LE") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "completed" }, - { label: techReviewLabel, state: "action" }, + { label: MAIN_STEP_LABELS.envoReview, state: "current" }, + { label: MAIN_STEP_LABELS.techReview, state: "pending" }, { label: MAIN_STEP_LABELS.reply, state: "pending" }, ]; } - if (prgrsSttsComCd === "EP") { + if (prgrsSttsComCd === "ER" || prgrsSttsComCd === "TE" || prgrsSttsComCd === "SL") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "completed" }, - { label: MAIN_STEP_LABELS.techReview, state: "completed" }, - { label: replyLabel, state: "action" }, + { label: MAIN_STEP_LABELS.envoReview, state: "completed" }, + { label: MAIN_STEP_LABELS.techReview, state: "current" }, + { label: MAIN_STEP_LABELS.reply, state: "pending" }, + ]; + } + + if (prgrsSttsComCd === "TP" || prgrsSttsComCd === "EP") { + return [ + { label: MAIN_STEP_LABELS.apply, state: "completed" }, + { label: MAIN_STEP_LABELS.envoReview, state: "completed" }, + { + label: MAIN_STEP_LABELS.techReview, + state: techRplyHstryYn === "Y" ? "completed" : "pending", + }, + { label: MAIN_STEP_LABELS.reply, state: "current" }, ]; } if (prgrsSttsComCd === "TA" || prgrsSttsComCd === "TB") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "completed" }, - { label: MAIN_STEP_LABELS.techReview, state: "completed" }, + { label: MAIN_STEP_LABELS.envoReview, state: "completed" }, + { + label: MAIN_STEP_LABELS.techReview, + state: techRplyHstryYn === "Y" ? "completed" : "pending", + }, { label: MAIN_STEP_LABELS.reply, state: "completed" }, ]; } - return [{ label: prgrsSttsCdNm || prgrsSttsComCd || "-", state: "current" }]; + return [ + { label: MAIN_STEP_LABELS.apply, state: "pending" }, + { label: MAIN_STEP_LABELS.envoReview, state: "pending" }, + { label: MAIN_STEP_LABELS.techReview, state: "pending" }, + { label: MAIN_STEP_LABELS.reply, state: "pending" }, + ]; } function getBadgeColor(state: BadgeState) { @@ -86,8 +111,6 @@ function getBadgeColor(state: BadgeState) { return "blue"; case "pending": return "lightGray"; - case "action": - return "orange"; } } @@ -97,11 +120,11 @@ function formatOptional(value: string | undefined) { interface ProgressStepBadgeProps { prgrsSttsComCd: string; - prgrsSttsCdNm: string; + techRplyHstryYn: "Y" | "N"; } -function ProgressStepBadge({ prgrsSttsComCd, prgrsSttsCdNm }: ProgressStepBadgeProps) { - const badges = buildProgressBadges(prgrsSttsComCd, prgrsSttsCdNm); +function ProgressStepBadge({ prgrsSttsComCd, techRplyHstryYn }: ProgressStepBadgeProps) { + const badges = buildProgressBadges(prgrsSttsComCd, techRplyHstryYn); return (
@@ -154,7 +177,7 @@ export function createInstlSncnColumns() { cell: ({ row }) => ( ), }), diff --git a/apps/as/src/pages/instl-sncn/ui/instl-form-page.tsx b/apps/as/src/pages/instl-sncn/ui/instl-form-page.tsx index bc248e3b2..c2bd574b9 100644 --- a/apps/as/src/pages/instl-sncn/ui/instl-form-page.tsx +++ b/apps/as/src/pages/instl-sncn/ui/instl-form-page.tsx @@ -25,6 +25,7 @@ import { isFormChecklistComplete, isFormEsntlAtchComplete, PrivacyConsentSection, + ProgressStatusSection, SplmntDmndFormSection, } from "@/widgets/pbadms-sprt"; import { Button } from "@common/components"; @@ -35,6 +36,7 @@ import { type InstlSncnRegistFormData, instlSncnRegistSchema, } from "../lib/instl-sncn-regist-schema"; +import { PROGRESS_STATUS_COLUMNS } from "../model/columns"; import { BasicInfoFormSection } from "./sections/basic-info-form-section"; interface InstlFormPageProps { @@ -228,6 +230,13 @@ function InstlFormPage({ id, mode, initialData, createDefaults }: InstlFormPageP return ( + {initialData?.detDto.instlSncnDocNo && ( + + )} diff --git a/apps/as/src/pages/instl-sncn/ui/instl-view-page.tsx b/apps/as/src/pages/instl-sncn/ui/instl-view-page.tsx index 094072f1a..d8f637f59 100644 --- a/apps/as/src/pages/instl-sncn/ui/instl-view-page.tsx +++ b/apps/as/src/pages/instl-sncn/ui/instl-view-page.tsx @@ -6,12 +6,13 @@ import { useUserStore } from "@/shared/lib"; import { ElaprDocPrgrsStatus } from "@/entities/elapr"; import { useInstlSncnDetail } from "@/entities/instl-sncn"; import { useRvwMnpwMngLoginUserList } from "@/entities/rvw-mnpw"; -import { SectionCollapsible, SupplementDemandSection } from "@/widgets/pbadms-sprt"; +import { ProgressStatusSection, SupplementDemandSection } from "@/widgets/pbadms-sprt"; import { Skeleton } from "@common/components"; import { needsRoleUser01AtrzResolve } from "../lib/button-config"; import { getEditableReviewStep } from "../lib/review-step-utils"; import { EMPTY_CKLST_RESULT_LIST, useChecklistFormState } from "../lib/use-checklist-form-state"; +import { PROGRESS_STATUS_COLUMNS } from "../model/columns"; import { FloatingActionButtons } from "./components/floating-action-buttons"; import { AttachmentsSection } from "./sections/attachments-section"; @@ -79,6 +80,7 @@ function InstlViewPage({ id }: InstlViewPageProps) { etcFileList, rvwList = [], splmntDmndList = [], + sttsChgHstryList = [], } = data; const editableReviewStep = getEditableReviewStep( @@ -88,11 +90,14 @@ function InstlViewPage({ id }: InstlViewPageProps) { return (
+ - - - + (); const MAIN_STEP_LABELS = { - save: "저장", - apply: "신청완료", + apply: "기본계획 신청", envoReview: "환경청 검토", techReview: "기술검토", reply: "검토결과 회신", - supplement: "보완요청", } as const; -const TECH_REVIEW_STATUS_CODES = new Set(["ER", "TE", "TP"]); +export const PROGRESS_STATUS_COLUMNS = [ + { label: "기본계획 신청 (시군)", sttsComCd: "LE" }, + { label: "환경청 검토", sttsComCd: "ER" }, + { label: "기술검토", sttsComCd: "TE" }, + { label: "기술검토 회신", sttsComCd: "TP" }, + { label: "횐경청 검토 결과 회신", sttsComCd: "EP" }, +]; -type BadgeState = "completed" | "current" | "pending" | "action"; +type BadgeState = "completed" | "current" | "pending"; interface ProgressBadge { label: string; state: BadgeState; } -function buildProgressBadges(prgrsSttsComCd: string, prgrsSttsCdNm: string): ProgressBadge[] { - const techReviewLabel = prgrsSttsCdNm || MAIN_STEP_LABELS.techReview; - const replyLabel = prgrsSttsCdNm || MAIN_STEP_LABELS.reply; - +function buildProgressBadges(prgrsSttsComCd: string, techRplyHstryYn: "Y" | "N"): ProgressBadge[] { if (prgrsSttsComCd === "SV") { return [ - { label: MAIN_STEP_LABELS.save, state: "current" }, { label: MAIN_STEP_LABELS.apply, state: "pending" }, { label: MAIN_STEP_LABELS.envoReview, state: "pending" }, { label: MAIN_STEP_LABELS.techReview, state: "pending" }, @@ -42,57 +42,63 @@ function buildProgressBadges(prgrsSttsComCd: string, prgrsSttsCdNm: string): Pro ]; } + if (prgrsSttsComCd === "ST") { + return [ + { label: MAIN_STEP_LABELS.apply, state: "current" }, + { label: MAIN_STEP_LABELS.envoReview, state: "pending" }, + { label: MAIN_STEP_LABELS.techReview, state: "pending" }, + { label: MAIN_STEP_LABELS.reply, state: "pending" }, + ]; + } + if (prgrsSttsComCd === "LE") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "completed" }, - { label: MAIN_STEP_LABELS.envoReview, state: "action" }, + { label: MAIN_STEP_LABELS.envoReview, state: "current" }, { label: MAIN_STEP_LABELS.techReview, state: "pending" }, { label: MAIN_STEP_LABELS.reply, state: "pending" }, ]; } - if (prgrsSttsComCd === "SL") { + if (prgrsSttsComCd === "ER" || prgrsSttsComCd === "TE" || prgrsSttsComCd === "SL") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "completed" }, { label: MAIN_STEP_LABELS.envoReview, state: "completed" }, - { label: MAIN_STEP_LABELS.supplement, state: "action" }, + { label: MAIN_STEP_LABELS.techReview, state: "current" }, { label: MAIN_STEP_LABELS.reply, state: "pending" }, ]; } - if (TECH_REVIEW_STATUS_CODES.has(prgrsSttsComCd)) { + if (prgrsSttsComCd === "TP") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "completed" }, { label: MAIN_STEP_LABELS.envoReview, state: "completed" }, - { label: techReviewLabel, state: "action" }, - { label: MAIN_STEP_LABELS.reply, state: "pending" }, - ]; - } - - if (prgrsSttsComCd === "TA") { - return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, - { label: MAIN_STEP_LABELS.apply, state: "completed" }, - { label: MAIN_STEP_LABELS.envoReview, state: "completed" }, - { label: MAIN_STEP_LABELS.techReview, state: "completed" }, - { label: MAIN_STEP_LABELS.reply, state: "completed" }, + { + label: MAIN_STEP_LABELS.techReview, + state: techRplyHstryYn === "Y" ? "completed" : "pending", + }, + { label: MAIN_STEP_LABELS.reply, state: "current" }, ]; } if (prgrsSttsComCd === "EP") { return [ - { label: MAIN_STEP_LABELS.save, state: "completed" }, { label: MAIN_STEP_LABELS.apply, state: "completed" }, { label: MAIN_STEP_LABELS.envoReview, state: "completed" }, - { label: MAIN_STEP_LABELS.techReview, state: "completed" }, - { label: replyLabel, state: "completed" }, + { + label: MAIN_STEP_LABELS.techReview, + state: techRplyHstryYn === "Y" ? "completed" : "pending", + }, + { label: MAIN_STEP_LABELS.reply, state: "completed" }, ]; } - return [{ label: prgrsSttsCdNm || prgrsSttsComCd || "-", state: "current" }]; + return [ + { label: MAIN_STEP_LABELS.apply, state: "pending" }, + { label: MAIN_STEP_LABELS.envoReview, state: "pending" }, + { label: MAIN_STEP_LABELS.techReview, state: "pending" }, + { label: MAIN_STEP_LABELS.reply, state: "pending" }, + ]; } function getBadgeColor(state: BadgeState) { @@ -103,8 +109,6 @@ function getBadgeColor(state: BadgeState) { return "blue"; case "pending": return "lightGray"; - case "action": - return "orange"; } } @@ -114,11 +118,11 @@ function formatOptional(value: string | undefined) { interface ProgressStepBadgeProps { prgrsSttsComCd: string; - prgrsSttsCdNm: string; + techRplyHstryYn: "Y" | "N"; } -function ProgressStepBadge({ prgrsSttsComCd, prgrsSttsCdNm }: ProgressStepBadgeProps) { - const badges = buildProgressBadges(prgrsSttsComCd, prgrsSttsCdNm); +function ProgressStepBadge({ prgrsSttsComCd, techRplyHstryYn }: ProgressStepBadgeProps) { + const badges = buildProgressBadges(prgrsSttsComCd, techRplyHstryYn); return (
@@ -177,7 +181,7 @@ export function createSewerBscPlanColumns() { cell: ({ row }) => ( ), }), diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/previous-plan-lookup-dialog.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/previous-plan-lookup-dialog.tsx index 162efec34..0d0d6f4a8 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/previous-plan-lookup-dialog.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/previous-plan-lookup-dialog.tsx @@ -3,13 +3,13 @@ import { useEffect, useMemo, useState } from "react"; import { useAlertStore } from "@/shared/lib"; +import { SectionCollapsible } from "@/shared/ui"; import { type CmCdAdstDstrComboResponseDto, useFindGugunCombo, useFindSidoCombo, } from "@/entities/adstdstr"; import { useLvNowDmgMtncGnsvy, useNowDmgMtncGnsvy } from "@/entities/dc"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Button, Dialog, diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/attachments-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/attachments-section.tsx index f35cab5ff..e379d5097 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/attachments-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/attachments-section.tsx @@ -3,12 +3,12 @@ import { Paperclip } from "lucide-react"; import { formatFileSize } from "@/shared/lib/file-utils"; +import { SectionCollapsible } from "@/shared/ui"; import { useDownloadAttachmentByAtflCd } from "@/entities/attach"; import type { AtflMngClientResponseDto, EsntlAtchFileMngTreeResponseDto, } from "@/entities/sewer-bsc-plan"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; interface AttachmentsSectionProps { diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/basic-info-form-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/basic-info-form-section.tsx index 1af5a02b1..36544c2f4 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/basic-info-form-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/basic-info-form-section.tsx @@ -3,8 +3,8 @@ import { Controller, useFormContext } from "react-hook-form"; import { useUserStore } from "@/shared/lib"; +import { SectionCollapsible } from "@/shared/ui"; import { Field, FieldError } from "@/shared/ui/field"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Input, Select, diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/basic-info-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/basic-info-section.tsx index 3cfd3e4a9..3272c12b6 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/basic-info-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/basic-info-section.tsx @@ -1,10 +1,10 @@ "use client"; +import { SectionCollapsible } from "@/shared/ui"; import type { SewerBscPlanDtlResponseDto, SewerBscPlanResponseDto, } from "@/entities/sewer-bsc-plan"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Table, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; interface BasicInfoSectionProps { diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/biz-cst-matrix-form-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/biz-cst-matrix-form-section.tsx index f6cba8863..efbdfc462 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/biz-cst-matrix-form-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/biz-cst-matrix-form-section.tsx @@ -3,9 +3,10 @@ import { useEffect, useMemo } from "react"; import { useFormContext, useWatch } from "react-hook-form"; +import { SectionCollapsible } from "@/shared/ui"; import { Field } from "@/shared/ui/field"; import { useAcntgSeMngTree } from "@/entities/acntg"; -import { buildAcntgCostItems, SectionCollapsible } from "@/widgets/pbadms-sprt"; +import { buildAcntgCostItems } from "@/widgets/pbadms-sprt"; import { Input, Skeleton, diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/biz-cst-matrix-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/biz-cst-matrix-section.tsx index ae224238d..4b1ecba97 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/biz-cst-matrix-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/biz-cst-matrix-section.tsx @@ -2,12 +2,13 @@ import { useMemo } from "react"; +import { SectionCollapsible } from "@/shared/ui"; import { useAcntgSeMngTree } from "@/entities/acntg"; import type { SewerBscPlanBizCstResponseDto, SewerBscPlanDtlResponseDto, } from "@/entities/sewer-bsc-plan"; -import { buildAcntgCostItems, fmtNumber, SectionCollapsible } from "@/widgets/pbadms-sprt"; +import { buildAcntgCostItems, fmtNumber } from "@/widgets/pbadms-sprt"; import { Skeleton, Table, diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/checklist-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/checklist-section.tsx index 9bb85272b..14123d871 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/checklist-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/checklist-section.tsx @@ -2,8 +2,8 @@ import { type Dispatch, type SetStateAction, useEffect, useMemo, useState } from "react"; +import { SectionCollapsible } from "@/shared/ui"; import type { CklstRvwRsltTreeDto } from "@/entities/sewer-bsc-plan"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@common/components"; import { diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/contact-info-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/contact-info-section.tsx index 4abd171c1..11a99df12 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/contact-info-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/contact-info-section.tsx @@ -1,7 +1,7 @@ "use client"; +import { SectionCollapsible } from "@/shared/ui"; import type { SewerBscPlanDtlResponseDto } from "@/entities/sewer-bsc-plan"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Table, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; interface ContactInfoSectionProps { diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/fnrs-cst-form-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/fnrs-cst-form-section.tsx index 2082822d2..c27e2d34b 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/fnrs-cst-form-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/fnrs-cst-form-section.tsx @@ -3,9 +3,10 @@ import { useMemo } from "react"; import { useFormContext, useWatch } from "react-hook-form"; +import { SectionCollapsible } from "@/shared/ui"; import { Field } from "@/shared/ui/field"; import { useAcntgSeMngTree } from "@/entities/acntg"; -import { buildAcntgCostItems, SectionCollapsible } from "@/widgets/pbadms-sprt"; +import { buildAcntgCostItems } from "@/widgets/pbadms-sprt"; import { cn, Input, diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/fnrs-cst-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/fnrs-cst-section.tsx index 5ec099fda..92ae6851a 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/fnrs-cst-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/fnrs-cst-section.tsx @@ -2,12 +2,13 @@ import { useMemo } from "react"; +import { SectionCollapsible } from "@/shared/ui"; import { useAcntgSeMngTree } from "@/entities/acntg"; import type { SewerBscPlanDtlResponseDto, SewerBscPlanFnrsCstResponseDto, } from "@/entities/sewer-bsc-plan"; -import { buildAcntgCostItems, fmtNumber, SectionCollapsible } from "@/widgets/pbadms-sprt"; +import { buildAcntgCostItems, fmtNumber } from "@/widgets/pbadms-sprt"; import { Skeleton, Table, diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/outline-form-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/outline-form-section.tsx index 97674abbc..c6dcdfc2f 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/outline-form-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/outline-form-section.tsx @@ -4,8 +4,8 @@ import { useState } from "react"; import { useFormContext, useWatch } from "react-hook-form"; import dynamic from "next/dynamic"; +import { SectionCollapsible } from "@/shared/ui"; import { Field } from "@/shared/ui/field"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Button, Input, diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/outline-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/outline-section.tsx index 87f91fac9..9bb57b943 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/outline-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/outline-section.tsx @@ -1,10 +1,11 @@ "use client"; +import { SectionCollapsible } from "@/shared/ui"; import type { SewerBscPlanDtlResponseDto, SewerBscPlanOtlnResponseDto, } from "@/entities/sewer-bsc-plan"; -import { fmtNumber, SectionCollapsible } from "@/widgets/pbadms-sprt"; +import { fmtNumber } from "@/widgets/pbadms-sprt"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; interface OutlineSectionProps { diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/tech-review-opinion-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/tech-review-opinion-section.tsx index cf8135717..1781f183e 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/tech-review-opinion-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/tech-review-opinion-section.tsx @@ -7,10 +7,10 @@ import { Paperclip } from "lucide-react"; import { PROXY_HOST } from "@/shared/config"; import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib"; import { TextShimmer } from "@/shared/ui"; +import { SectionCollapsible } from "@/shared/ui"; import { Field, FieldLabel, FieldSet } from "@/shared/ui/field"; import { attachService } from "@/entities/attach"; import type { SewerBscPlanRvwOpnnResponseDto } from "@/entities/sewer-bsc-plan"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Button, RadioGroup, diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/tmplnt-form-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/tmplnt-form-section.tsx index dfd49b8bd..89b25aee9 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/tmplnt-form-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/tmplnt-form-section.tsx @@ -7,11 +7,11 @@ import { useConfirm } from "@frontend-opensource/use-react-hooks"; import { getDefaultFileKey, useTus } from "@/shared/lib"; import { TextShimmer } from "@/shared/ui"; +import { SectionCollapsible } from "@/shared/ui"; import { Field } from "@/shared/ui/field"; import { attachService } from "@/entities/attach"; import { useFacilityList } from "@/entities/bns-if"; import { useNowDmgMtncGnsvy } from "@/entities/dc"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Button, Checkbox, diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sections/tmplnt-section.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sections/tmplnt-section.tsx index 372f6cb60..7f87254d3 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sections/tmplnt-section.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sections/tmplnt-section.tsx @@ -4,6 +4,7 @@ import { useMemo, useState } from "react"; import { Paperclip } from "lucide-react"; +import { SectionCollapsible } from "@/shared/ui"; import { useDownloadAttachmentByAtflCd } from "@/entities/attach"; import { useFacilityList } from "@/entities/bns-if"; import { useNowDmgMtncGnsvy } from "@/entities/dc"; @@ -12,7 +13,7 @@ import type { SewerBscPlanResponseDto, SewerBscPlanTmplntResponseDto, } from "@/entities/sewer-bsc-plan"; -import { fmtNumber, SectionCollapsible } from "@/widgets/pbadms-sprt"; +import { fmtNumber } from "@/widgets/pbadms-sprt"; import { Table, TableBody, diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sewer-bsc-plan-form-page.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sewer-bsc-plan-form-page.tsx index 03c605ebe..ca8f2c9d0 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sewer-bsc-plan-form-page.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sewer-bsc-plan-form-page.tsx @@ -25,6 +25,7 @@ import { isFormChecklistComplete, isFormEsntlAtchComplete, PrivacyConsentSection, + ProgressStatusSection, SplmntDmndFormSection, } from "@/widgets/pbadms-sprt"; import { Button } from "@common/components"; @@ -39,6 +40,7 @@ import { type SewerBscPlanRegistFormData, sewerBscPlanRegistSchema, } from "../lib/sewer-bsc-plan-regist-schema"; +import { PROGRESS_STATUS_COLUMNS } from "../model/columns"; import { BasicInfoFormSection } from "./sections/basic-info-form-section"; import { BizCstMatrixFormSection } from "./sections/biz-cst-matrix-form-section"; @@ -242,6 +244,13 @@ function SewerBscPlanFormPage({ return ( + {initialData?.detDto?.sewerBscPlanDocNo && ( + + )} diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sewer-bsc-plan-view-page.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sewer-bsc-plan-view-page.tsx index 293d31bd8..e04483925 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sewer-bsc-plan-view-page.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sewer-bsc-plan-view-page.tsx @@ -6,12 +6,13 @@ import { useUserStore } from "@/shared/lib"; import { ElaprDocPrgrsStatus } from "@/entities/elapr"; import { useRvwMnpwMngLoginUserList } from "@/entities/rvw-mnpw"; import { useSewerBscPlanDetails } from "@/entities/sewer-bsc-plan"; -import { SectionCollapsible, SupplementDemandSection } from "@/widgets/pbadms-sprt"; +import { ProgressStatusSection, SupplementDemandSection } from "@/widgets/pbadms-sprt"; import { Skeleton } from "@common/components"; import { needsRoleUser01AtrzResolve } from "../lib/button-config"; import { getEditableReviewStep } from "../lib/review-step-utils"; import { EMPTY_CKLST_RESULT_LIST, useChecklistFormState } from "../lib/use-checklist-form-state"; +import { PROGRESS_STATUS_COLUMNS } from "../model/columns"; import { FloatingActionButtons } from "./components/floating-action-buttons"; import { AttachmentsSection } from "./sections/attachments-section"; @@ -74,17 +75,20 @@ function SewerBscPlanViewPage({ id, propChgCycl }: SewerBscPlanViewPageProps) { return
상세 정보를 찾을 수 없습니다.
; } - const detDto = data.detDto; - const activeDtlDto = data.activeDtlDto; - const otlnList = data.otlnList ?? []; - const bizCstList = data.bizCstList ?? []; - const fnrsCstList = data.fnrsCstList ?? []; - const tmplntList = data.tmplntList ?? []; - const cklstResultRows = data.cklstResultRows ?? []; - const esntlFileList = data.esntlFileList ?? []; - const etcFileList = data.etcFileList ?? []; - const rvwOpnnList = data.rvwOpnnList ?? []; - const splmntDmndList = data.splmntDmndList ?? []; + const { + detDto, + activeDtlDto, + otlnList = [], + bizCstList = [], + fnrsCstList = [], + tmplntList = [], + cklstResultRows = [], + esntlFileList = [], + etcFileList = [], + rvwOpnnList = [], + splmntDmndList = [], + sttsChgHstryList = [], + } = data; const editableReviewStep = getEditableReviewStep( userInfo?.dtlInstCd, @@ -93,11 +97,14 @@ function SewerBscPlanViewPage({ id, propChgCycl }: SewerBscPlanViewPageProps) { return (
+ - - - + diff --git a/apps/as/src/shared/model/index.ts b/apps/as/src/shared/model/index.ts index bdf339145..75c66834d 100644 --- a/apps/as/src/shared/model/index.ts +++ b/apps/as/src/shared/model/index.ts @@ -38,6 +38,7 @@ export type { CklstResultSaveBase, CklstRvwRsltTreeDto, DocPrgrsUpdateRequestDto, + DocSttsChgHstryResponseDto, ElaprDocPrgrsClientResponseDto, EsntlAtchFileMngTreeResponseDto, EsntlAtchFileSaveBase, diff --git a/apps/as/src/shared/model/pbadms-sprt.ts b/apps/as/src/shared/model/pbadms-sprt.ts index 67b0b831e..272e6d110 100644 --- a/apps/as/src/shared/model/pbadms-sprt.ts +++ b/apps/as/src/shared/model/pbadms-sprt.ts @@ -155,6 +155,22 @@ export interface ElaprDocPrgrsClientResponseDto { dcarbYn?: string; } +/** 문서 상태 변경 이력 응답 DTO */ +export interface DocSttsChgHstryResponseDto { + chgHstrySn: number; + docSeComCd: string; + docSeComNm: string; + docNo: string; + chgBfrSttsComCd: string; + chgBfrSttsComNm: string; + chgAftrSttsComCd: string; + chgAftrSttsComNm: string; + rmrk: string; + rgtrUuid: string; + rgtrNm: string; + regDt: string; +} + /** 사업규모 저장 공통 필드 */ export interface BzScaleSaveBase { cnstpSeCd?: string; @@ -244,4 +260,5 @@ export interface PbadmsMngDetResponseBase - - - - {children} - - ); -} - -export { SectionCollapsible }; +"use client"; + +import type { ReactNode } from "react"; + +import { ChevronDown } from "lucide-react"; + +import { cn, Collapsible, CollapsibleContent, CollapsibleTrigger } from "@common/components"; + +interface SectionCollapsibleProps { + title: ReactNode; + defaultOpen?: boolean; + children: ReactNode; +} + +function SectionCollapsible({ title, defaultOpen = true, children }: SectionCollapsibleProps) { + return ( + + + + + {children} + + ); +} + +export { SectionCollapsible }; diff --git a/apps/as/src/widgets/bns-picker/ui/bns-picker-dialog.tsx b/apps/as/src/widgets/bns-picker/ui/bns-picker-dialog.tsx index a259c8aca..4153aec1a 100644 --- a/apps/as/src/widgets/bns-picker/ui/bns-picker-dialog.tsx +++ b/apps/as/src/widgets/bns-picker/ui/bns-picker-dialog.tsx @@ -12,12 +12,12 @@ import { import { useDataTable } from "@/shared/lib"; import type { PageResponse } from "@/shared/model"; +import { SectionCollapsible } from "@/shared/ui"; import { NoData } from "@/shared/ui/no-data"; import type { CmCdAdstDstrComboResponseDto } from "@/entities/adstdstr"; import { useFindGugunCombo, useFindSidoCombo } from "@/entities/adstdstr"; import type { BnsDetailResponseDto, BnsListResponseDto, BnsSearchDto } from "@/entities/bns-if"; import { buildBnsSearchDto, useBnsDetail, useBnsList } from "@/entities/bns-if"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Button, Dialog, diff --git a/apps/as/src/widgets/cnfm/ui/attachments.tsx b/apps/as/src/widgets/cnfm/ui/attachments.tsx index dcd68209e..4a585d231 100644 --- a/apps/as/src/widgets/cnfm/ui/attachments.tsx +++ b/apps/as/src/widgets/cnfm/ui/attachments.tsx @@ -1,4 +1,5 @@ import React from "react"; + import { formatFileSize } from "@/shared/lib/file-utils"; type EtcFile = { diff --git a/apps/as/src/widgets/pbadms-sprt/index.ts b/apps/as/src/widgets/pbadms-sprt/index.ts index 8f2c44b95..4746b9097 100644 --- a/apps/as/src/widgets/pbadms-sprt/index.ts +++ b/apps/as/src/widgets/pbadms-sprt/index.ts @@ -39,7 +39,7 @@ export { type PbadmsTaskApplySelection, } from "./ui/pbadms-task-apply-dialog"; export { PrivacyConsentSection } from "./ui/privacy-consent-section"; -export { SectionCollapsible } from "./ui/section-collapsible"; +export { ProgressStatusSection } from "./ui/progress-status-section"; export { SplmntDmndDialog, type SplmntDmndDialogConfirmItem, diff --git a/apps/as/src/widgets/pbadms-sprt/lib/progress-status-utils.ts b/apps/as/src/widgets/pbadms-sprt/lib/progress-status-utils.ts new file mode 100644 index 000000000..2a936c6ad --- /dev/null +++ b/apps/as/src/widgets/pbadms-sprt/lib/progress-status-utils.ts @@ -0,0 +1,59 @@ +import type { + DocSttsChgHstryResponseDto, + ElaprDocPrgrsClientResponseDto, +} from "@/shared/model/pbadms-sprt"; + +interface ProgressStatusItem { + rgtrNm: string; + regDt: string; +} + +const TECH_REVIEW_STTS_COM_CD = "TE"; +const TECH_REVIEW_ATRZ_SE_COM_CD = "ATRZ02"; +const TECH_REVIEW_ATRZ_PRGRS_STTS_COM_CD = "ATRZ_PRGRS_003"; + +function findProgressStatusItem( + sttsChgHstryList: DocSttsChgHstryResponseDto[], + sttsComCd: string, +): ProgressStatusItem[] { + return sttsChgHstryList + .filter((item) => item.chgAftrSttsComCd === sttsComCd) + .map((item) => ({ + rgtrNm: item.rgtrNm, + regDt: item.regDt, + })); +} + +function findTechReviewProgressItem( + elaprDocPrgrsList: ElaprDocPrgrsClientResponseDto[], +): ProgressStatusItem[] { + return elaprDocPrgrsList + .filter( + (item) => + item.atrzSeComCd === TECH_REVIEW_ATRZ_SE_COM_CD && + item.atrzPrgrsSttsComCd === TECH_REVIEW_ATRZ_PRGRS_STTS_COM_CD, + ) + .map((item) => ({ + rgtrNm: item.aprvrNm ?? "", + regDt: item.atrzDt ?? "", + })); +} + +function resolveProgressStatusItem( + sttsComCd: string, + sttsChgHstryList: DocSttsChgHstryResponseDto[], + elaprDocPrgrsList: ElaprDocPrgrsClientResponseDto[], +): ProgressStatusItem[] { + if (sttsComCd === TECH_REVIEW_STTS_COM_CD) { + return findTechReviewProgressItem(elaprDocPrgrsList); + } + + return findProgressStatusItem(sttsChgHstryList, sttsComCd); +} + +export { + findProgressStatusItem, + findTechReviewProgressItem, + resolveProgressStatusItem, + TECH_REVIEW_STTS_COM_CD, +}; diff --git a/apps/as/src/widgets/pbadms-sprt/ui/attachments-form-section.tsx b/apps/as/src/widgets/pbadms-sprt/ui/attachments-form-section.tsx index 03d812211..b4bce6b8a 100644 --- a/apps/as/src/widgets/pbadms-sprt/ui/attachments-form-section.tsx +++ b/apps/as/src/widgets/pbadms-sprt/ui/attachments-form-section.tsx @@ -9,6 +9,7 @@ import { ENDPOINT } from "@/shared/config"; import { useTus } from "@/shared/lib"; import type { AtflMngClientResponseDto, EsntlAtchFileMngTreeResponseDto } from "@/shared/model"; import { TextShimmer } from "@/shared/ui"; +import { SectionCollapsible } from "@/shared/ui"; import { attachService } from "@/entities/attach"; import { useEsntlAtchFileMngTree } from "@/entities/esntl"; import { @@ -29,9 +30,7 @@ import { type FieldPrefix, isEtcFileKey, toFileAccept, -} from "../lib/attachments-form-utils"; - -import { SectionCollapsible } from "./section-collapsible"; +} from "../lib/attachments-form-utils"; interface AttachmentsFormData { esntlAtchFileList: Array<{ diff --git a/apps/as/src/widgets/pbadms-sprt/ui/business-cost-form-section.tsx b/apps/as/src/widgets/pbadms-sprt/ui/business-cost-form-section.tsx index 51d7a82a1..969a4613b 100644 --- a/apps/as/src/widgets/pbadms-sprt/ui/business-cost-form-section.tsx +++ b/apps/as/src/widgets/pbadms-sprt/ui/business-cost-form-section.tsx @@ -3,6 +3,7 @@ import { useEffect, useMemo } from "react"; import { Controller, useFormContext, useWatch } from "react-hook-form"; +import { SectionCollapsible } from "@/shared/ui"; import { Field } from "@/shared/ui/field"; import { useAcntgSeMngTree } from "@/entities/acntg"; import { @@ -17,9 +18,7 @@ import { } from "@common/components"; import { buildAcntgCostItems, recalculateBizCstTotals } from "../lib/business-cost-form-utils"; -import { calcDiffPercent } from "../lib/format-utils"; - -import { SectionCollapsible } from "./section-collapsible"; +import { calcDiffPercent } from "../lib/format-utils"; interface BusinessCostFormData { bizCstList: Array<{ diff --git a/apps/as/src/widgets/pbadms-sprt/ui/business-scale-form-section.tsx b/apps/as/src/widgets/pbadms-sprt/ui/business-scale-form-section.tsx index 63698dd08..2bee5e104 100644 --- a/apps/as/src/widgets/pbadms-sprt/ui/business-scale-form-section.tsx +++ b/apps/as/src/widgets/pbadms-sprt/ui/business-scale-form-section.tsx @@ -3,6 +3,7 @@ import { useEffect, useMemo } from "react"; import { Controller, useFormContext, useWatch } from "react-hook-form"; +import { SectionCollapsible } from "@/shared/ui"; import { Field } from "@/shared/ui/field"; import { useCnstpSeMngTree } from "@/entities/cnstp"; import { @@ -16,9 +17,7 @@ import { TableRow, } from "@common/components"; -import { buildCnstpScaleItems, recalculateBzScaleTotals } from "../lib/business-scale-form-utils"; - -import { SectionCollapsible } from "./section-collapsible"; +import { buildCnstpScaleItems, recalculateBzScaleTotals } from "../lib/business-scale-form-utils"; interface BusinessScaleFormData { bzScaleList: Array<{ diff --git a/apps/as/src/widgets/pbadms-sprt/ui/checklist-form-section.tsx b/apps/as/src/widgets/pbadms-sprt/ui/checklist-form-section.tsx index 36fb793ae..4b9866877 100644 --- a/apps/as/src/widgets/pbadms-sprt/ui/checklist-form-section.tsx +++ b/apps/as/src/widgets/pbadms-sprt/ui/checklist-form-section.tsx @@ -5,6 +5,7 @@ import { Controller, useFormContext, useWatch } from "react-hook-form"; import { useQuery } from "@tanstack/react-query"; +import { SectionCollapsible } from "@/shared/ui"; import { Field, FieldLabel } from "@/shared/ui/field"; import { cklstMngService, type CklstTreeNode } from "@/entities/cklst"; import { useCodeList } from "@/entities/code"; @@ -29,9 +30,7 @@ import { buildChecklistTabs, normalizeTaskSeComCdArray, syncCklstResultListFromTree, -} from "../lib/checklist-form-utils"; - -import { SectionCollapsible } from "./section-collapsible"; +} from "../lib/checklist-form-utils"; type FieldPrefix = "fnrsCnsltnMng" | "instlSncnMng" | "designCnstnMng" | "sewerBscPlan"; diff --git a/apps/as/src/widgets/pbadms-sprt/ui/contact-info-form-section.tsx b/apps/as/src/widgets/pbadms-sprt/ui/contact-info-form-section.tsx index c3dc02fcc..0f5b659a0 100644 --- a/apps/as/src/widgets/pbadms-sprt/ui/contact-info-form-section.tsx +++ b/apps/as/src/widgets/pbadms-sprt/ui/contact-info-form-section.tsx @@ -3,8 +3,8 @@ import { Controller, useFormContext } from "react-hook-form"; import { useUserStore } from "@/shared/lib"; +import { SectionCollapsible } from "@/shared/ui"; import { Field, FieldError } from "@/shared/ui/field"; -import { SectionCollapsible } from "@/widgets/pbadms-sprt"; import { Input, Table, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; type FieldPrefix = diff --git a/apps/as/src/widgets/pbadms-sprt/ui/fnrs-shar-form-section.tsx b/apps/as/src/widgets/pbadms-sprt/ui/fnrs-shar-form-section.tsx index 5365db9c9..0ab921ef9 100644 --- a/apps/as/src/widgets/pbadms-sprt/ui/fnrs-shar-form-section.tsx +++ b/apps/as/src/widgets/pbadms-sprt/ui/fnrs-shar-form-section.tsx @@ -5,6 +5,7 @@ import { Controller, useFormContext, useWatch } from "react-hook-form"; import { getDefaultFileKey, useTus } from "@/shared/lib"; import { TextShimmer } from "@/shared/ui"; +import { SectionCollapsible } from "@/shared/ui"; import { Field } from "@/shared/ui/field"; import { useAcntgSeMngTree } from "@/entities/acntg"; import type { AtflMngClientResponseDto } from "@/entities/fnrs-cnsltn"; @@ -34,7 +35,6 @@ import { import { calcDiffPercent } from "../lib/format-utils"; import { BizCstTotalDisplayTable } from "./biz-cst-total-display-table"; -import { SectionCollapsible } from "./section-collapsible"; const SHAR_FILE_KEY_PREFIX = "fnrs-shar::"; diff --git a/apps/as/src/widgets/pbadms-sprt/ui/privacy-consent-section.tsx b/apps/as/src/widgets/pbadms-sprt/ui/privacy-consent-section.tsx index d51d9aeef..eefd96163 100644 --- a/apps/as/src/widgets/pbadms-sprt/ui/privacy-consent-section.tsx +++ b/apps/as/src/widgets/pbadms-sprt/ui/privacy-consent-section.tsx @@ -2,6 +2,7 @@ import { Controller, useFormContext } from "react-hook-form"; +import { SectionCollapsible } from "@/shared/ui"; import { Field, FieldError, FieldLabel, FieldSet } from "@/shared/ui/field"; import { RadioGroup, @@ -11,9 +12,7 @@ import { TableHead, TableHeader, TableRow, -} from "@common/components"; - -import { SectionCollapsible } from "./section-collapsible"; +} from "@common/components"; interface PrivacyConsentFormData { privacyConsent: "Y" | "N"; diff --git a/apps/as/src/widgets/pbadms-sprt/ui/progress-status-section.tsx b/apps/as/src/widgets/pbadms-sprt/ui/progress-status-section.tsx new file mode 100644 index 000000000..4ce4d8a0a --- /dev/null +++ b/apps/as/src/widgets/pbadms-sprt/ui/progress-status-section.tsx @@ -0,0 +1,88 @@ +"use client"; + +import dayjs from "dayjs"; + +import { DocSttsChgHstryResponseDto } from "@/shared/model/pbadms-sprt"; +import { SectionCollapsible } from "@/shared/ui"; +import { useElaprDocPrgrsByDocNo } from "@/entities/elapr"; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; + +import { resolveProgressStatusItem } from "../lib/progress-status-utils"; + +interface ProgressStatusColumn { + label: string; + sttsComCd: string; +} + +interface ProgressStatusItem { + rgtrNm: string; + regDt: string; +} + +interface ProgressStatusSectionProps { + columns: ProgressStatusColumn[]; + sttsChgHstryList: DocSttsChgHstryResponseDto[]; + elaprDocNo: string; +} + +interface ProgressStatusCellProps { + items: ProgressStatusItem[]; +} + +function ProgressStatusCell({ items }: ProgressStatusCellProps) { + if (items.length === 0) return "-"; + + return ( +
+ {items.map((item, index) => ( +
+ {item.rgtrNm || "-"} + {item.regDt && ( +

+ {dayjs(item.regDt).format("YYYY-MM-DD")} +

+ )} +
+ ))} +
+ ); +} + +function ProgressStatusSection({ + columns, + sttsChgHstryList, + elaprDocNo, +}: ProgressStatusSectionProps) { + const { data: elaprDocPrgrsList = [] } = useElaprDocPrgrsByDocNo(elaprDocNo); + + return ( + + + + + {columns.map((column) => ( + {column.label} + ))} + + + + + {columns.map((column) => ( + + + + ))} + + +
+
+ ); +} + +export { ProgressStatusSection }; diff --git a/apps/as/src/widgets/pbadms-sprt/ui/splmnt-dmnd-form-section.tsx b/apps/as/src/widgets/pbadms-sprt/ui/splmnt-dmnd-form-section.tsx index 6a8d94670..a8efff36d 100644 --- a/apps/as/src/widgets/pbadms-sprt/ui/splmnt-dmnd-form-section.tsx +++ b/apps/as/src/widgets/pbadms-sprt/ui/splmnt-dmnd-form-section.tsx @@ -7,6 +7,7 @@ import { Paperclip } from "lucide-react"; import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib"; import { TextShimmer } from "@/shared/ui"; +import { SectionCollapsible } from "@/shared/ui"; import { attachService, useDownloadAttachmentByAtflCd } from "@/entities/attach"; import { Badge, @@ -20,8 +21,6 @@ import { Textarea, } from "@common/components"; -import { SectionCollapsible } from "./section-collapsible"; - const SPLMNT_CMPTN_FILE_KEY_PREFIX = "splmnt-cmptn::"; interface UploadedSplmntFile { diff --git a/apps/as/src/widgets/pbadms-sprt/ui/supplement-demand-section.tsx b/apps/as/src/widgets/pbadms-sprt/ui/supplement-demand-section.tsx index 8c7d6a8c7..1da222fdf 100644 --- a/apps/as/src/widgets/pbadms-sprt/ui/supplement-demand-section.tsx +++ b/apps/as/src/widgets/pbadms-sprt/ui/supplement-demand-section.tsx @@ -4,6 +4,7 @@ import { Paperclip } from "lucide-react"; import { dayjs } from "@/shared/lib"; import type { SplmntDmndResponseExtension, SplmntDmndSaveBase } from "@/shared/model"; +import { SectionCollapsible } from "@/shared/ui"; import { useDownloadAttachmentByAtflCd } from "@/entities/attach"; import { Badge, @@ -15,8 +16,6 @@ import { TableRow, } from "@common/components"; -import { SectionCollapsible } from "./section-collapsible"; - type SplmntDmndItem = SplmntDmndSaveBase & SplmntDmndResponseExtension; interface SupplementDemandSectionProps {