조사사업 등록의 사업차수 입력과 행정구역 배치 보완

This commit is contained in:
kiminchan
2026-07-27 11:29:48 +09:00
parent 5a76ae8a88
commit a52dacf500
8 changed files with 112 additions and 25 deletions
@@ -19,7 +19,7 @@ export const EXMN_FILE_RULES: Record<ExmnFileType, { label: string; extensions:
export const validateExmnBusiness = (request: ExmnBusinessSaveRequest): string | null => {
if (!/^\d{4}$/.test(request.bizYr)) return "사업연도는 4자리 숫자로 입력해주세요.";
if (!request.bizNm.trim()) return "사업명을 입력해주세요.";
if (!Number.isInteger(request.bizCycl) || request.bizCycl < 0) return "사업차수는 0 이상의 정수로 입력해주세요.";
if (!Number.isInteger(request.bizCycl) || request.bizCycl < 1) return "사업차수는 1 이상의 정수로 입력해주세요.";
if (!request.ctpvNm || !request.sggNm) return "시도와 시군구를 선택해주세요.";
if (!Number.isFinite(request.prcisExmnPrlg) || request.prcisExmnPrlg < 0) return "정밀조사연장은 0 이상이어야 합니다.";
if (!Number.isFinite(request.tpco) || request.tpco < 0) return "총사업비는 0 이상이어야 합니다.";
@@ -49,6 +49,8 @@ const saveBlob = (blob: Blob, fileName: string) => {
/** 공통 WindowPopup 안에서 사업정보·대상 처리분구·조사양식을 등록하는 화면이다. */
export function ExmnBusinessRegisterPopupPage({ sampleMode }: ExmnBusinessRegisterPopupPageProps) {
const { ctpv, sgg, fetchCtpv, fetchSgg } = useStore();
/** 사업 확장 시 등록자가 직접 지정할 수 있도록 저장 요청에 전달하는 사업차수다. */
const [bizCycl, setBizCycl] = useState(sampleMode ? "3" : "1");
const [bizYr, setBizYr] = useState(String(new Date().getFullYear()));
const [bizNm, setBizNm] = useState(sampleMode ? "2026년 양평군 노후 하수관로 정밀조사사업" : "");
const [ctpvCd, setCtpvCd] = useState("0");
@@ -158,11 +160,11 @@ export function ExmnBusinessRegisterPopupPage({ sampleMode }: ExmnBusinessRegist
const buildRequest = (): ExmnBusinessSaveRequest => ({
bizYr: bizYr.trim(),
bizNm: bizNm.trim(),
// 사업차수와 총사업비는 현재 등록 화면 입력 대상이 아니므로 신규 기본값으로 전달한다.
bizCycl: 1,
bizCycl: Number(bizCycl),
ctpvNm,
sggNm,
prcisExmnPrlg: Number(prcisExmnPrlg),
// 총사업비는 현재 등록 화면 입력 대상이 아니므로 신규 기본값으로 전달한다.
tpco: 0,
trtdstIds: selectedDistrictIds,
});
@@ -279,18 +281,35 @@ export function ExmnBusinessRegisterPopupPage({ sampleMode }: ExmnBusinessRegist
<section className="border border-border">
<div className="border-b border-border bg-[#eaf3fb] px-4 py-3 font-semibold text-title">사업정보 입력</div>
<div className="space-y-4 p-4">
<div className="flex flex-wrap items-center gap-y-4">
<div className="flex flex-nowrap items-center gap-5">
<div className="flex items-center gap-2">
<Label className="shrink-0 whitespace-nowrap text-base">
<span className="text-red-500">* </span>사업차수
</Label>
<Input
style={{ width: "3.5rem", flex: "none" }}
type="text"
inputMode="numeric"
maxLength={3}
value={bizCycl}
disabled={Boolean(savedBusiness)}
onChange={(event) => {
if (/^\d{0,3}$/.test(event.target.value)) setBizCycl(event.target.value);
}}
/>
</div>
<SelectBox
label="사업년도"
labelClass="w-20 shrink-0 text-base"
className="mr-7 flex items-center gap-3"
selectClass="w-36 bg-white"
labelClass="shrink-0 whitespace-nowrap text-base"
className="flex items-center gap-2"
selectClass="w-[6.5rem] bg-white"
selectArray={getStartYearArray({ placeholder: "선택" })}
value={bizYr}
readOnly={Boolean(savedBusiness)}
onSelectValue={(value) => setBizYr(String(value))}
/>
<CtpvSggPrcsFcltSelectBox
compact
className="!mr-0 !justify-start"
sido={ctpvCd}
sigungu={sggCd}
@@ -310,10 +329,10 @@ export function ExmnBusinessRegisterPopupPage({ sampleMode }: ExmnBusinessRegist
if (!savedBusiness) setSggNm(nextSggNm === "전체" ? "" : nextSggNm);
}}
/>
<div className="ml-auto flex items-center gap-3" style={{ width: "280px" }}>
<Label className="shrink-0 text-base" style={{ whiteSpace: "nowrap" }}><span className="text-red-500">* </span>정밀조사 연장</Label>
<div className="flex items-center gap-2">
<Label className="shrink-0 whitespace-nowrap text-base"><span className="text-red-500">* </span>정밀조사 연장</Label>
<Input
style={{ width: "9rem", flex: "none" }}
style={{ width: "6rem", flex: "none" }}
type="text"
inputMode="decimal"
maxLength={10}
@@ -4,7 +4,7 @@ export const windowPopupDefinitions = {
exmnBusinessRegister: {
key: "exmnBusinessRegister",
title: "사업정보 등록",
width: 920,
width: 1000,
height: 620,
},
exmnResultRegister: {