"use client"; import { useEffect, useState } from "react"; import { useAlertStore } from "@/shared/lib"; import { Button, Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, } from "@common/components"; export interface MainFacilityMappingSaveDialogValues { prxyBzentyNmCn: string; /** 위탁비용(백만원/년) */ cnsgnCstVl: number; wholNope: number; /** YYYYMMDD~YYYYMMDD */ prxyCtrtCn: string; } export interface MainFacilityMappingSaveDialogProps { open: boolean; onOpenChange: (open: boolean) => void; initialPrxyBzentyNmCn: string; /** 위탁비용(백만원/년) 초기값 */ initialCnsgnCstVl: number; initialWholNope: number; /** 위탁계약기간 초기값 (YYYYMMDD~YYYYMMDD) */ initialPrxyCtrtCn: string; onConfirm?: (values: MainFacilityMappingSaveDialogValues) => void | Promise; } function isValidYmd(ymd: string): boolean { if (!/^\d{8}$/.test(ymd)) return false; const y = Number(ymd.slice(0, 4)); const m = Number(ymd.slice(4, 6)); const d = Number(ymd.slice(6, 8)); const dt = new Date(y, m - 1, d); return dt.getFullYear() === y && dt.getMonth() === m - 1 && dt.getDate() === d; } function validatePrxyCtrtCn(value: string): string | null { const t = value.trim(); if (!t) return "위탁계약기간을 입력해 주세요."; if (!/^\d{8}~\d{8}$/.test(t)) { return "위탁계약기간은 YYYYMMDD~YYYYMMDD 형식으로 입력해 주세요. (예: 20240101~20281231)"; } const start = t.slice(0, 8); const end = t.slice(9, 17); if (!isValidYmd(start) || !isValidYmd(end)) { return "시작일 또는 종료일이 유효한 날짜가 아닙니다."; } if (start > end) { return "시작일이 종료일보다 늦을 수 없습니다."; } return null; } export function MainFacilityMappingSaveDialog({ open, onOpenChange, initialPrxyBzentyNmCn, initialCnsgnCstVl, initialWholNope, initialPrxyCtrtCn, onConfirm, }: MainFacilityMappingSaveDialogProps) { const { setMessage: alert } = useAlertStore((state) => state); const [prxyBzentyNmCn, setPrxyBzentyNmCn] = useState(""); const [cnsgnCstInput, setCnsgnCstInput] = useState(""); const [wholNopeInput, setWholNopeInput] = useState(""); const [prxyCtrtCn, setPrxyCtrtCn] = useState(""); const [isSubmitting, setIsSubmitting] = useState(false); useEffect(() => { if (open) { setPrxyBzentyNmCn(initialPrxyBzentyNmCn ?? ""); const initCost = Number(initialCnsgnCstVl); setCnsgnCstInput( initialCnsgnCstVl === null || initialCnsgnCstVl === undefined || Number.isNaN(initCost) ? "" : String(initCost), ); setWholNopeInput( initialWholNope === null || initialWholNope === undefined || Number.isNaN(Number(initialWholNope)) ? "" : String(initialWholNope), ); setPrxyCtrtCn((initialPrxyCtrtCn ?? "").trim()); } }, [open, initialPrxyBzentyNmCn, initialCnsgnCstVl, initialWholNope, initialPrxyCtrtCn]); const handleDialogOpenChange = (nextOpen: boolean) => { if (!nextOpen && !isSubmitting) { setPrxyBzentyNmCn(""); setCnsgnCstInput(""); setWholNopeInput(""); setPrxyCtrtCn(""); } onOpenChange(nextOpen); }; const handleConfirm = async () => { const trimmedCost = cnsgnCstInput.trim(); const cnsgnCstVl = trimmedCost === "" ? 0 : Number.parseFloat(trimmedCost.replace(/,/g, "")); if (!Number.isFinite(cnsgnCstVl) || cnsgnCstVl < 0) { alert("위탁비용은 0 이상의 숫자로 입력해 주세요."); return; } const trimmedWhol = wholNopeInput.trim(); const wholNope = trimmedWhol === "" ? 0 : Number.parseInt(trimmedWhol, 10); if (!Number.isFinite(wholNope) || wholNope < 0) { alert("전체 인원은 0 이상의 정수로 입력해 주세요."); return; } const prxyCtrtErr = validatePrxyCtrtCn(prxyCtrtCn); if (prxyCtrtErr) { alert(prxyCtrtErr); return; } try { setIsSubmitting(true); await onConfirm?.({ prxyBzentyNmCn: prxyBzentyNmCn.trim(), cnsgnCstVl, wholNope, prxyCtrtCn: prxyCtrtCn.trim(), }); } finally { setIsSubmitting(false); } }; return ( 저장 정보 입력
setPrxyBzentyNmCn(e.target.value)} className="!text-[1.3rem]" placeholder="위탁사업자명을 입력하세요." disabled={isSubmitting} />
{ const v = e.target.value.replace(/[^\d.]/g, ""); const firstDot = v.indexOf("."); const next = firstDot === -1 ? v : v.slice(0, firstDot + 1) + v.slice(firstDot + 1).replace(/\./g, ""); setCnsgnCstInput(next); }} className="!text-[1.3rem]" placeholder="0" disabled={isSubmitting} />
{ const v = e.target.value.replace(/\D/g, ""); setWholNopeInput(v); }} className="!text-[1.3rem]" placeholder="0" disabled={isSubmitting} />
setPrxyCtrtCn(e.target.value)} className="!text-[1.3rem]" placeholder="YYYYMMDD~YYYYMMDD (예: 20240101~20281231)" autoComplete="off" disabled={isSubmitting} />
); }