313 lines
9.7 KiB
TypeScript
313 lines
9.7 KiB
TypeScript
"use client";
|
|
|
|
import { useDmStore } from "@/app/store";
|
|
import type { DemandCompBizType } from "@/app/store/sdmMng";
|
|
import { SdmInfoRegForm } from "@/components/ui/sdmInfoInsertForm/component";
|
|
import { UiModal } from "@common/business_components/ui/dialog_ui";
|
|
import { Button } from "@common/components/ui";
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
import { Suspense, useEffect, useState } from "react";
|
|
import { FormProvider, useForm, type SubmitHandler } from "react-hook-form";
|
|
import { Toaster } from "react-hot-toast";
|
|
import * as z from "zod";
|
|
import SdmLogin from "../sdmLogin/page";
|
|
|
|
const sdmInfoFormSchema = z.object({
|
|
sdmNm: z.string().min(1, "수요처를 선택해주세요"),
|
|
demandYmd: z.date().optional(),
|
|
demandQnty: z
|
|
.string()
|
|
.min(1, "요구수량을 입력해주세요")
|
|
.regex(/^[0-9]+$/, "요구수량은 숫자만 입력 가능합니다"),
|
|
usePurpose: z.string().optional(),
|
|
money: z.string().regex(/^[0-9]+$/, "희망단가는 숫자만 입력 가능합니다"),
|
|
/**요구수질 */
|
|
reqWaterQlty: z.string().optional(),
|
|
grssClfg: z.number().nullish(),
|
|
tn: z.number().nullish(),
|
|
combResdch: z.number().nullish(),
|
|
tph: z.number().nullish(),
|
|
trbt: z.number().nullish(),
|
|
ph: z.string().nullish(),
|
|
bod: z.number().nullish(),
|
|
/**컬럼확인필요 */
|
|
clIonQnt: z.number().nullish(),
|
|
smll: z.string(),
|
|
cdtnv: z.number().nullish(),
|
|
crmty: z.number().nullish(),
|
|
rmrk: z.string().optional(),
|
|
/* telno: z.string()
|
|
.min(8, "전화번호는 8자 이상 입력해주세요")
|
|
.max(12, "전화번호는 12자 이내로 입력해주세요")
|
|
.regex(/^[0-9-]+$/, "전화번호는 숫자와 하이픈(-)만 입력 가능합니다"), */
|
|
candidateTitle: z
|
|
.array(
|
|
z.object({
|
|
ruseUtztnFcltNm: z.string(),
|
|
ruseUtztnFcltCd: z.string(),
|
|
})
|
|
)
|
|
.optional(),
|
|
});
|
|
|
|
export type FormData = z.infer<typeof sdmInfoFormSchema>;
|
|
|
|
function SdmInfoInsertContent() {
|
|
const searchParams = useSearchParams();
|
|
const { insertSdmInfoData, Sdm, setSubsInfo } = useDmStore((state) => state);
|
|
const { successLogin } = Sdm;
|
|
const [ismoneyDisabled, setIsmoneyDisabled] = useState(false);
|
|
const formSchema = sdmInfoFormSchema;
|
|
|
|
const [isLogin, setIsLogin] = useState(false);
|
|
const [facilityName, setFacilityName] = useState<string>("");
|
|
const [defaultValues, setDefaultValues] = useState<FormData>({
|
|
sdmNm: "",
|
|
demandYmd: new Date(),
|
|
demandQnty: "",
|
|
usePurpose: "",
|
|
money: "",
|
|
/**요구수질 */
|
|
reqWaterQlty: "",
|
|
grssClfg: null,
|
|
tn: null,
|
|
combResdch: null,
|
|
tph: null,
|
|
trbt: null,
|
|
ph: null,
|
|
bod: null,
|
|
/**컬럼확인필요 */
|
|
clIonQnt: null,
|
|
smll: "",
|
|
cdtnv: null,
|
|
crmty: null,
|
|
rmrk: "",
|
|
/** 후보지 제목 */
|
|
candidateTitle: [
|
|
{ ruseUtztnFcltNm: "", ruseUtztnFcltCd: "" },
|
|
{ ruseUtztnFcltNm: "", ruseUtztnFcltCd: "" },
|
|
{ ruseUtztnFcltNm: "", ruseUtztnFcltCd: "" },
|
|
],
|
|
});
|
|
|
|
useEffect(() => {
|
|
const user = sessionStorage.getItem("user");
|
|
setDefaultValues((prev) => ({
|
|
...prev,
|
|
sdmNm: searchParams.get("dmdCoNm") || "",
|
|
}));
|
|
sessionStorage.setItem("user", searchParams.get("dmdInfoId") || "");
|
|
setIsLogin(user || searchParams.get("dmdInfoId") ? true : false);
|
|
}, [searchParams]);
|
|
|
|
useEffect(() => {
|
|
const local = localStorage.getItem("user");
|
|
if (local) {
|
|
setIsLogin(true);
|
|
}
|
|
setSubsInfo([]); // subsInfo 초기화 후보지 처음 화면 들어올때 초기화(스토어내 객체만)
|
|
}, [setSubsInfo]);
|
|
|
|
const form = useForm<FormData>({
|
|
resolver: zodResolver(formSchema),
|
|
defaultValues,
|
|
mode: "onChange",
|
|
});
|
|
|
|
const subsInfo = useDmStore((state) => state.map.subsInfo);
|
|
|
|
useEffect(() => {
|
|
//map.subsInfo 스토어 객체 값이 변경되면 해당 값이 폼에 자동으로 들어가도록 수정 대신 값이 있어야함
|
|
if (subsInfo.length > 0) {
|
|
form.setValue("candidateTitle", subsInfo);
|
|
}
|
|
}, [subsInfo, form]);
|
|
|
|
//후보지 팝업 값 셋팅
|
|
useEffect(() => {
|
|
const handleMessage = (event: MessageEvent) => {
|
|
if (event.data?.type === "SET_SUBS_INFO") {
|
|
setSubsInfo(event.data.payload); // zustand로 값 설정
|
|
}
|
|
};
|
|
|
|
window.addEventListener("message", handleMessage);
|
|
return () => window.removeEventListener("message", handleMessage);
|
|
}, [setSubsInfo]);
|
|
|
|
// 로그인 성공 시 모달 닫기 및 폼 업데이트
|
|
useEffect(() => {
|
|
if (successLogin) {
|
|
setIsLogin(true);
|
|
const user = sessionStorage.getItem("user");
|
|
if (user) {
|
|
try {
|
|
const userData = JSON.parse(user);
|
|
if (userData.dmdCoNm) {
|
|
setFacilityName(userData.dmdCoNm);
|
|
form.setValue("sdmNm", userData.dmdCoNm);
|
|
}
|
|
} catch (error) {
|
|
console.error("Error parsing user data:", error);
|
|
}
|
|
}
|
|
}
|
|
}, [successLogin, form]);
|
|
|
|
useEffect(() => {
|
|
console.log("Form state changed:", form.formState.errors);
|
|
}, [form.formState.errors]);
|
|
|
|
// 체크박스 상태가 변경될 때마다 money 필드의 에러를 초기화
|
|
useEffect(() => {
|
|
if (ismoneyDisabled) {
|
|
form.clearErrors("money");
|
|
form.setValue("money", "");
|
|
}
|
|
}, [ismoneyDisabled, form]);
|
|
const router = useRouter();
|
|
const onSubmit: SubmitHandler<FormData> = async (data) => {
|
|
try {
|
|
const dmSubsInfo = data.candidateTitle?.filter(
|
|
(item) => item.ruseUtztnFcltNm && item.ruseUtztnFcltCd
|
|
);
|
|
// Transform form data to madata.candidateTitletch API schema
|
|
const apiData: DemandCompBizType = {
|
|
dmdInfoId:
|
|
JSON.parse(
|
|
sessionStorage.getItem("user") || "{}"
|
|
)?.dmdInfoId?.toString() ||
|
|
searchParams.get("dmdInfoId") + (searchParams.get("bznmTotNo") || ""),
|
|
dmdInfoFk:
|
|
JSON.parse(
|
|
sessionStorage.getItem("user") || "{}"
|
|
)?.dmdInfoId?.toString() ||
|
|
searchParams.get("dmdInfoId") + (searchParams.get("bznmTotNo") || ""),
|
|
dmdCoNm:
|
|
JSON.parse(
|
|
sessionStorage.getItem("user") || "{}"
|
|
)?.dmdCoNm?.toString() || data.sdmNm,
|
|
ctpvCd:
|
|
JSON.parse(
|
|
sessionStorage.getItem("user") || "{}"
|
|
)?.ctpvCd?.toString() ||
|
|
searchParams.get("ctpvCd") ||
|
|
"",
|
|
sggCd:
|
|
JSON.parse(
|
|
sessionStorage.getItem("user") || "{}"
|
|
)?.sggCd?.toString() ||
|
|
searchParams.get("sggCd") ||
|
|
"",
|
|
daddr:
|
|
JSON.parse(
|
|
sessionStorage.getItem("user") || "{}"
|
|
)?.daddr?.toString() ||
|
|
searchParams.get("daddr") ||
|
|
"",
|
|
telno:
|
|
JSON.parse(
|
|
sessionStorage.getItem("user") || "{}"
|
|
)?.telno?.toString() ||
|
|
searchParams.get("telno") ||
|
|
"",
|
|
rgtr:
|
|
JSON.parse(
|
|
sessionStorage.getItem("user") || "{}"
|
|
)?.rgtr?.toString() ||
|
|
searchParams.get("rgtr") ||
|
|
"",
|
|
useUsgCd: data.usePurpose || "",
|
|
wntUntprc: Number(data.money) || "",
|
|
dmndTmng: data.demandYmd || new Date(),
|
|
dmndQty: Number(data.demandQnty) || "",
|
|
grssClfg: data.grssClfg === null ? -1 : Number(data.grssClfg),
|
|
tn: Number(data.tn) || null,
|
|
combResdch: Number(data.combResdch) || null,
|
|
tph: Number(data.tph) || null,
|
|
trbt: Number(data.trbt) || null,
|
|
ph: data.ph || "",
|
|
blgcOxygDmndQnt: Number(data.bod) ||null,
|
|
clIonQnt: Number(data.clIonQnt) || null,
|
|
smll: data.smll || "",
|
|
cdtnv: Number(data.cdtnv) ||null,
|
|
crmty: Number(data.crmty) || null,
|
|
rmrk: data.rmrk || "",
|
|
bzmnNo: "",
|
|
dmdAplyPswd: "",
|
|
index: 0,
|
|
reqDt: "",
|
|
dmdInfoSn: 0,
|
|
status: "",
|
|
splyCndtList: dmSubsInfo || [],
|
|
};
|
|
|
|
await insertSdmInfoData(apiData);
|
|
setTimeout(() => {
|
|
router.push("/");
|
|
}, 1000); // 0.8초 후 이동
|
|
} catch (error) {
|
|
console.error("Error submitting form:", error);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="min-h-screen bg-[#F2F2F2]">
|
|
<div className="container mx-auto px-4 py-8">
|
|
<div className="text-center mb-8">
|
|
<h1 className="text-4xl font-bold text-gray-900 underline">
|
|
수요정보 등록
|
|
</h1>
|
|
</div>
|
|
|
|
<div className="max-w-3xl mx-auto bg-white rounded-lg shadow-md p-6">
|
|
<FormProvider {...form}>
|
|
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
|
|
<SdmInfoRegForm
|
|
form={form}
|
|
onCheckboxChange={setIsmoneyDisabled}
|
|
facilityName={facilityName}
|
|
/>
|
|
<div className="flex justify-center pt-4">
|
|
<Button
|
|
color="sky"
|
|
size={"sm"}
|
|
type="submit"
|
|
className="w-40 font-semibold py-2 px-4 rounded-md "
|
|
>
|
|
수요정보 등록
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</FormProvider>
|
|
</div>
|
|
</div>
|
|
|
|
{!isLogin ? (
|
|
<UiModal
|
|
body={<SdmLogin />}
|
|
bodyClass="sm:max-w-[90vw] w-[530px] h-[430px]"
|
|
open={!isLogin}
|
|
onOpenChange={(open) => {
|
|
if (!open) {
|
|
router.push("/");
|
|
}
|
|
}}
|
|
noHeaderYn="Y"
|
|
noFooterYn="Y"
|
|
/>
|
|
) : null}
|
|
<Toaster position="top-center" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function MyForm() {
|
|
return (
|
|
<Suspense fallback={<div>Loading...</div>}>
|
|
<SdmInfoInsertContent />
|
|
</Suspense>
|
|
);
|
|
}
|