빗물재이용 등록 수정 조회 기능추가

This commit is contained in:
leedj312
2025-04-02 13:02:53 +09:00
parent 46de361f3c
commit 8019660593
13 changed files with 665 additions and 492 deletions
@@ -87,8 +87,8 @@ export default function Home() {
return (
<>
<ContentsDiv>
<div className="grid grid-cols-2 gap-4 ">
<div className="col-span-2">
<div className="grid grid-cols-4 gap-4 ">
<div className="col-span-4">
<Title title={"빗물이용시설 등록"} />
<SearchDiv>
<SearchFormLeft>
@@ -100,8 +100,6 @@ export default function Home() {
throw new Error("Function not implemented.");
}}
/>
{/* <div className='w-4/5 grid grid-cols-12 gap-1 mx-4'>
</div> */}
</SearchFormLeft>
<SearchFormRight>
<Button className="mr-4 rounded-lg">조회</Button>
@@ -111,13 +109,12 @@ export default function Home() {
body={<BdstReg></BdstReg>}
bodyClass="sm:max-w-7xl"
/>
{/* <Button className='mr-4 rounded-lg' onClick={()=>bdstRegModal('ㅁ',divTest())}>신규등록</Button> */}
</SearchFormRight>
{/* <div className='w-1/5 flex items-center justify-end'>
</div> */}
</SearchDiv>
</div>
<div className="colsapn-1">
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-4">
<ListDiv>
<UiTable
tableData={bdstTable || []}
@@ -131,16 +128,18 @@ export default function Home() {
</UiTable>
</ListDiv>
</div>
<div className="colsapn-1 max-h-full ovreflow-y-scroll">
<div className="col-span-2 max-h-full ovreflow-y-scroll">
<ListDiv>
<ScrollArea>
<RainRegForm
rainForm={rainForm || null}
rainForm={rainForm || undefined}
isModal={false}
></RainRegForm>
</ScrollArea>
</ListDiv>
</div>
</div>
</ContentsDiv>
</>
+12 -1
View File
@@ -1,7 +1,7 @@
import { getFectch } from "@/components/lib/api";
// Description: 공통코드
type selectArray = {
export type selectArray = {
text: string;
val: string | number;
};
@@ -44,9 +44,18 @@ export const rainFcltCd = [
{ val: "10", text: "확인불가" },
];
export const chBuCd = [
{ val: "1", text: "증축" },
{ val: "2", text: "개축" },
{ val: "3", text: "재축" },
]
export type comCodeState = {
code: {
isInit: boolean;
chBuCd:selectArray[]
rainFcltCd: selectArray[];
bdstUsgCd: selectArray[];
cityCd: selectArray[];
@@ -89,6 +98,7 @@ export const comCodeStateExport: comCodeState = {
isInit: false,
rainFcltCd: rainFcltCd,
bdstUsgCd: bdstUsgCd,
chBuCd:chBuCd,
cityCd: [],
sggCd: [],
yn:yn
@@ -126,6 +136,7 @@ export const codeActionExport: (set: any) => comCodeActions = (set: any) => {
},
}));
},
divCityCd: async(cd: number) => {
set((state: comCodeState) => ({
code: {
@@ -1,4 +1,5 @@
import { getFectch } from "@/components/lib/api";
import type { RainyBuilding } from "../rainReg";
type TableUpperProps = {
id: string;
@@ -18,24 +19,30 @@ type TableUpperProps = {
{ id: "archChgArea", title: "면적", upName: "upChangeRe", upSequnce: 3 },
];
const bdstBase: bdstType[] = [];
const bdstBase: RainyBuilding[] = [];
export type bdstFulType = bdstState & bdstActions;
export type bdstState = {
bdst: {
bdstBase: bdstType[];
bdstBase: RainyBuilding[];
moUpHeadList:TableUpperProps[]
};
};
type bdstActions = {
findBdst: (val: string) => Promise<void>;
findBdst: (sggCd:string, searchTxt:string) => void ;
};
const findBdstInfo = async(sggCd:string, searchTxt:string)=>{
return await getFectch('wr', `/reuseFc/building/${sggCd}`+(searchTxt?`/${searchTxt}`:''))
}
export const bdstStateExport: bdstState = {
bdst: {
bdstBase: bdstBase, // Updated to match the array type
@@ -47,24 +54,25 @@ export const bdstActionsExport: (set: any) => bdstActions = (
set: any
) => {
return {
findBdst: async(val:string) =>{
try {
console.log(" val ", val);
// (val!=='' ?"/"+val:'')
const res = await getFectch('wr', "/reuseFc/building/42" +(val!=='' ?"/"+val:''));
console.log("res ", res)
// 여기서 상태 업데이트
return set((state: bdstState) => ({
bdst: {
...state.bdst,
bdstBase:res,
findBdst: async(sggCd:string, searchTxt:string) =>{
try{
const bdst = await findBdstInfo(sggCd, searchTxt);
return set((state:bdstState) =>({
...state,
bdst:{
...state.bdst,
bdstBase:bdst
}
}))
}catch(error1){
console.log("error ", error1)
}finally{
}
}));
} catch (error) {
console.log('error', error);
} finally {
console.log('finally');
}
},
};
@@ -1,27 +1,119 @@
import type { selectArray } from "@/app/store/common/code";
import { getFectch, postFectch, putFectch } from "@/components/lib/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";
export const rainZod =
{ ctpvCd: z.number(),
sggCd: z.number(),
bdstNm: z.string(),
daddr: z.string(),
frstArchPrmsnDt: z.date(),
archArea: z.number(),
bdstInfoPk: z.number().nullish() ,
lawTrgtYn: z.string().nullish(),
bdstUsgCd: z.number(),
bdstRuseFcltPk: z.number().nullish(),
bdstInfoFk: z.number().nullish(),
operMngCd: z.number().nullish(),
anlOperCst: z.number().nullish(),
instlCmptnDt: z.date(),
instlCst: z.number(),
instlCstSprtYn: z.string(),
instlCstSprtAmt: z.number(),
grntchBdstCertYn: z.string(),
grntchBdstCertNo: z.string(),
grntchBdstCertGrd: z.string(),
grntchBdstCertYr: z.string(),
bdstReuseFcltFk:z.number().nullish(),
pntfColKnd: z.string(),
pntfColArea: z.number(),
dtfcltCpct:z.number().nullish(),
filtrTrtmfctCpct: z.number(),
filtrTrtmfctYn: z.string(),
filtrTrtmfctPrs: z.string(),
annRnwtQty:z.number().nullish(),
oilqMeasMthd:z.string().nullish(),
chgBuilding: z.array(
z.object({
archChgPrmsnDt: z.date().nullish(),
archChgArea: z.number().nullish(),
bdstChgNm: z.string().nullish(),
})
).default([]), //
}
export const rainDefZod= {
instlCmptnDt: new Date(),
instlCst: 0,
pntfColKnd: "",
pntfColArea: 0,
filtrTrtmfctYn: "Y",
filtrTrtmfctCpct: 0,
filtrTrtmfctPrs: "",
instlCstSprtYn: "",
instlCstSprtAmt: 0,
grntchBdstCertYn: "",
grntchBdstCertYr: "",
grntchBdstCertNo: "",
grntchBdstCertGrd: "",
}
export const bdstDefZod={
ctpvCd: 0, // 시도
sggCd: 0, // 시군구
daddr: '', // 위치
bdstUsgCd: 0, // 건축물용도
frstArchPrmsnDt: new Date(), // 최초건축허가일
archArea: 0, // 건축면적
lawTrgtYn: '', // 법적의무대상여부
bdstNm: '',
bdstChgnm:'',
archChgPrmsnDt: new Date(), // 건축변경 허가일시
archChgArea: 0, // 변경 면적
}
export type chgBuilding={
bdstInfoFk: number,
archChgPrmsnDt: Date,
archChgArea: number,
bdstChgNm: string
}
export type RainyBuilding = {
ctpvCd: string;
sggCd: string;
ctpvCd: number;
sggCd: number;
bdstNm: string;
daddr: string;
frstArchPrmsnDt: string;
frstArchPrmsnDt: Date;
archArea: string;
archChgArea: string;
archChgArea: number;
bdstInfoPk: number;
reuseBuilding: reuseBuilding[];
chgBuilding:chgBuilding[]
};
export type reuseBuilding = {
lawTrgtYn: string|undefined;
bdstUsgCd: string|undefined;
bdstUsgCd: number|undefined;
bdstRuseFcltPk: number;
bdstInfoFk: number;
operMngCd: number;
anlOperCst: number;
instlCmptnDt: Date;
instlCmptnDt: Date|undefined;
instlCst: number|undefined;
archChgPrmsnDt: string;
//archChgPrmsnDt: string;
instlCstSprtYn: string|undefined;
instlCstSprtAmt: number|undefined;
grntchBdstCertYn: string|undefined;
@@ -65,11 +157,56 @@ export const upHeadList: TableUpperProps[] = [
const rainRes: RainyBuilding[] = [];
export type selectArray = {
text: string;
val: string;
const regRainForm:RainyBuilding = {
ctpvCd: 0,
sggCd: 0,
bdstNm: "",
daddr: "",
frstArchPrmsnDt:new Date(),
archArea: "",
archChgArea: 0,
bdstInfoPk: 0,
reuseBuilding: [{
rainyObj: {
bdstReuseFcltFk: 0,
pntfColKnd: undefined,
pntfColArea: undefined,
dtfcltCpct: 0,
filtrTrtmfctCpct: undefined,
filtrTrtmfctYn: undefined,
filtrTrtmfctPrs: undefined,
annRnwtQty: 0,
oilqMeasMthd: undefined
},
lawTrgtYn: undefined,
bdstUsgCd: undefined,
bdstRuseFcltPk: 0,
bdstInfoFk: 0,
operMngCd: 0,
anlOperCst: 0,
instlCmptnDt: undefined,
instlCst: undefined,
// archChgPrmsnDt: "",
instlCstSprtYn: undefined,
instlCstSprtAmt: undefined,
grntchBdstCertYn: undefined,
grntchBdstCertNo: undefined,
grntchBdstCertGrd: undefined,
grntchBdstCertYr: undefined
}],
//추가됨
chgBuilding:[{
bdstInfoFk: 0,
archChgPrmsnDt: new Date(),
archChgArea: 0,
bdstChgNm: ""
}]
};
export const selectClass = "w-full h-full text-2xl";
const selectYN = [
{ text: "Y", val: "1" },
@@ -81,6 +218,8 @@ export type rainFacState = {
upHeadList: TableUpperProps[];
selectYN: selectArray[];
rainRes: RainyBuilding[];
regRainForm:RainyBuilding,
};
};
type rainFacSActions = {
@@ -98,9 +237,19 @@ export const rainFacStateExport: rainFacState = {
rainRes: rainRes,
upHeadList: upHeadList,
selectYN: selectYN,
regRainForm:regRainForm,
},
};
const findBdstInfo = async(sggCd:string, searchTxt:string)=>{
return await getFectch('wr', `/reuseFc/building/${sggCd}/${searchTxt}`)
}
const initFetch = async () => {
return await getFectch("wr", "/reuseFc/rainyInfoList/1/20/41");
};
export const rainFacActionsExport: (set: any) => rainFacSActions = (
set: any
) => {
@@ -108,7 +257,7 @@ export const rainFacActionsExport: (set: any) => rainFacSActions = (
init: async () => {
try {
// 파라이터 수정 통합관리자 =0, 시관리자=시코드, 시군구 관리자= 시군구 코드 를 세번째 파라미터로 지정 / 건축물 서치가 있을경우 4번째 파라미터로 던지기 즉 1/20/42(서울시)/영현빌딩 이런식으로)
const rainRes = await getFectch("wr", "/reuseFc/rainyInfoList/1/20/42");
const rainRes = await initFetch();
// 여기서 상태 업데이트
return set((state: rainFacState) => ({
...state,
@@ -125,7 +274,7 @@ export const rainFacActionsExport: (set: any) => rainFacSActions = (
}
},
dataInit: () =>
set(async (state: rainFacState) => {
set((state: rainFacState) => {
console.log(" state ", state.rain);
return {
rain: {
@@ -134,30 +283,51 @@ export const rainFacActionsExport: (set: any) => rainFacSActions = (
},
};
}),
rainReg: async (data: RainyBuilding) => {
try {
const res = await postFectch("/reuseFc/rainyInfo", data);
const rainRes = await initFetch();
set((state: rainFacState) => ({
...state,
rain: {
...state.rain,
rainRes: rainRes,
isInit: false,
},
}));
} catch (e) {
console.log("e", e);
alert("등록 오류입니다.");
} finally {
alert("등록이 완료되었습니다.");
}
},
rainUpdate: async (data: RainyBuilding) => {
try {
console.log("data ", data)
const res = await putFectch("/reuseFc/rainyInfo", data);
console.log('rainUpdate', res);
if(res.ok){
alert(" 수정이 완료되었습니다.")
}
const rainRes = await initFetch();
set((state: rainFacState) => ({
...state,
rain: {
...state.rain,
rainRes: rainRes,
isInit: false,
},
}));
} catch (e) {
console.log("e", e);
alert("업데이트 오류입니다.");
} finally {
}
}
}}
rainReg: (data: RainyBuilding) =>
set(async () => {
try {
const res = postFectch("/reuseFc/rainyInfo", data);
console.log("res", res);
} catch (e) {
console.log("e", e);
alert("등록이 오류입니다.");
} finally {
alert("등록이 완료되었습니다.");
}
}),
rainUpdate: (data: RainyBuilding) =>
set(async () => {
try {
const res = putFectch("/reuseFc/rainyInfo", data);
console.log("res", res);
} catch (e) {
console.log("e", e);
alert("업데이트 오류입니다.");
} finally {
alert("업데이트가 완료되었습니다.");
}
}),
};
};
+2 -1
View File
@@ -1,6 +1,6 @@
//8880
import { DEV_URL_COMMON, DEV_URL_WR } from "../config/env";
import { DEV_URL_COMMON, DEV_URL_WR } from "../config/";
@@ -36,6 +36,7 @@ export const postFectch = async (url: string, params: any) => {
export const putFectch = async (url: string, params: any) => {
const response = await fetch(DEV_URL_WR+url, {
method: "PUT",
headers: {
-11
View File
@@ -1,11 +0,0 @@
const LOCAL_PORT = "3000";
const DEV_PORT = "8880";
const DEV_PORT_COMMON = "8881"; // common
export const LOCAL_URL_WR = `http://localhost:${LOCAL_PORT}/api/v1`;
export const DEV_URL_WR = `http://192.168.1.193:${DEV_PORT}/api/v1`;
export const DEV_URL_COMMON = `http:///192.168.1.193:${DEV_PORT_COMMON}/api/v1`;
+11 -1
View File
@@ -1 +1,11 @@
export * from './env';
const LOCAL_PORT = "3000";
const DEV_PORT = "8880";
const DEV_PORT_COMMON = "8881"; // common
export const LOCAL_URL_WR = `http://localhost:${LOCAL_PORT}/api/v1`;
export const DEV_URL_WR = `http://192.168.1.193:${DEV_PORT}/api/v1`;
export const DEV_URL_COMMON = `http:///192.168.1.193:${DEV_PORT_COMMON}/api/v1`;
+16
View File
@@ -0,0 +1,16 @@
import type { selectArray } from "@/app/store/common/code";
export const getCity = (val: string, sggCd: selectArray[]) => {
const data = sggCd
.filter((item) => String(item.val).substring(0, 2) === val)
.map((item) => ({
val: String(item.val),
text: item.text // 한국어 텍스트
}));
return data
};
@@ -1,101 +0,0 @@
import { z } from "zod";
export const rainZod =
{ ctpvCd: z.string(),
sggCd: z.string(),
bdstNm: z.string(),
daddr: z.string(),
frstArchPrmsnDt: z.date(),
archArea: z.number(),
archChgArea: z.string(),
bdstInfoPk: z.number(),
lawTrgtYn: z.string(),
bdstUsgCd: z.string(),
bdstRuseFcltPk: z.number(),
bdstInfoFk: z.number(),
operMngCd: z.number(),
anlOperCst: z.number(),
instlCmptnDt: z.date(),
instlCst: z.number(),
archChgPrmsnDt: z.string(),
instlCstSprtYn: z.string(),
instlCstSprtAmt: z.number(),
grntchBdstCertYn: z.string(),
grntchBdstCertNo: z.string(),
grntchBdstCertGrd: z.string(),
grntchBdstCertYr: z.string(),
bdstReuseFcltFk:z.number(),
pntfColKnd: z.string(),
pntfColArea: z.number(),
dtfcltCpct:z.number(),
filtrTrtmfctCpct: z.number(),
filtrTrtmfctYn: z.string(),
filtrTrtmfctPrs: z.string(),
annRnwtQty:z.number(),
oilqMeasMthd:z.string(),
}
// = {
// instlCmptnDt: z.date(),
// instlCst: z.number(),
// pntfColKnd: z.string(),
// pntfColArea: z.number(),
// filtrTrtmfctPrs: z.string(),
// filtrTrtmfctYn: z.string(),
// filtrTrtmfctCpct: z.number(),
// instlCstSprtYn: z.string(),
// instlCstSprtAmt: z.number(),
// grntchCstSprtYn: z.string(),
// // grntchCstSprtCst: z.string(),
// grntchBdstCertYn: z.string(),
// grntchBdstCertYr: z.string(),
// grntchBdstCertNo: z.string(),
// grntchBdstCertGrd: z.string(),
// }
export const rainDefZod= {
instlCmptnDt: new Date(),
instlCst: 0,
pntfColKnd: "",
pntfColArea: 0,
filtrTrtmfctYn: "Y",
filtrTrtmfctCpct: 0,
filtrTrtmfctPrs: "",
instlCstSprtYn: "",
instlCstSprtAmt: 0,
grntchCstSprtYn: "",
// grntchCstSprtCst: "",
grntchBdstCertYn: "",
grntchBdstCertYr: "",
grntchBdstCertNo: "",
grntchBdstCertGrd: "",
}
// export const bdstZod ={
// ctpvCd: z.string(), // 시도
// sggCd: z.string(), // 시군구
// daddr: z.string(), // 위치
// bdstUsgCd: z.string(), // 건축물용도
// frstArchPrmsnDt: z.date(), // 최초건축허가일
// archArea: z.number(), // 건축면적
// lawTrgtYn: z.string(), // 법적의무대상여부
// // archChgPrmsnDt: z.string(), // 건축변경 허가일시
// // archChgArea: z.number(), // 변경 면적
// bdstNm: z.string(),
// }
export const bdstDefZod={
ctpvCd: '', // 시도
sggCd: '', // 시군구
daddr: '', // 위치
bdstUsgCd: '', // 건축물용도
frstArchPrmsnDt: new Date(), // 최초건축허가일
archArea: 0, // 건축면적
lawTrgtYn: '', // 법적의무대상여부
// archChgPrmsnDt: '', // 건축변경 허가일시
// archChgArea: 0, // 변경 면적
bdstNm: '',
}
@@ -1,24 +1,28 @@
import { useWrStore } from "@/app/store";
import { selectClass } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { FormField, FormUi, SelectBox } from "@common/business_components";
import type { selectArray } from "@/app/store/common/code";
import { selectClass, type RainyBuilding } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { getCity } from "@/components/lib/func/commom";
import type { objSearchType } from "@/components/ui/modal/bdstReg/component";
import { FormField, FormUi, DatePicker, SelectBox } from "@common/business_components";
import { Button, Input } from "@common/components";
import { useEffect, useRef, useState } from "react";
import { useFieldArray } from "react-hook-form";
export default function BdstReg(form: any ) {
export default function BdstReg({ form, ud }: { form: any, ud: RainyBuilding }) {
const { code } = useWrStore((state) => {
return state;
});
const { fields, append, remove } = useFieldArray({
control: form.control,
name: "history"
name: "chgBuilding",
control: form?.control, // Provide a fallback to avoid errors
});
const plusHist = () => {
append({
bdstNm: '',
daddr: '',
bdstUsgCd: ''
bdstNm: "",
daddr: "",
bdstUsgCd: "",
});
};
@@ -26,193 +30,260 @@ export default function BdstReg(form: any ) {
if (fields.length > 0) {
remove(fields.length - 1);
}
};
};
const [selectSgg, setSelectSgg] = useState<selectArray[] | undefined>()
const [objSearch, setObjSearch] = useState<objSearchType>({sgg:"",city:""});
const getSelCity = (val: string) => {
const data= getCity(val,code.sggCd)
setSelectSgg(data);
const sgg =form.getValues('sggCd')
setObjSearch({ city:val , sgg:''})
};
const getSgg = (val: string | number) => {
const sgg =form.getValues('sggCd')
setObjSearch({...objSearch,sgg: val!=''?String(val):sgg })
};
// useEffect(()=>{
// console.log("18", ud);
// console.log("form", form.getValues());
// const city =form?.getValues('ctpvCd')
// const sgg =form?.getValues('sggCd')
// console.log('city ㄴㄴㄴ ', city)
// console.log('sgg ', sgg)
// if(city>0 && sgg>0){
// console.log(' if city ', city)
// // form?.setValue('ctpvCd' , city)
// //form?.setValue('sggCd' , sgg)
// //setSelectSgg(getCity(city,code.sggCd))
// }
// },[ud])
useEffect(()=>{
const city =form.getValues('ctpvCd')
const sgg =form.getValues('sggCd')
setObjSearch({city:city , sgg:sgg })
}, [selectSgg])
useEffect(() => {
const subscription = form.form?.watch((value) => {
console.log('vale', value)
});
return () => subscription?.unsubscribe();
}, [form]);
const safeDate = (value: any): Date | undefined => {
const date = new Date(value);
return isNaN(date.getTime()) ? undefined : date;
};
return (
<>
<h1 className="bg-gray-400 text-xl text-center border-2 p-2 mt-4 pl-6">
건축물 시설 정보
</h1>
<div className="grid grid-cols-6 gap-2 mt-4">
<div className="col-span-3">
<FormField
control={form.control}
name="ctpvCd"
render={({ field }) => (
<FormUi label="시도">
<SelectBox
className={""}
selectClass={selectClass}
label={""}
selectArray={code.cityCd}
onSelectValue={(val) => {
field.onChange(val);
}}
value={field.value}
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3">
<FormField
control={form.control}
name="sggCd"
render={({ field }) => (
<FormUi label="시군구">
<SelectBox
className={""}
selectClass={selectClass}
label={""}
selectArray={code.sggCd }
onSelectValue={(val) => {
field.onChange(val);
}}
value={field.value}
/>
</FormUi>
)}
/>
</div>
<h1 className="bg-gray-400 text-xl text-center border-2 p-2 mt-4 pl-6">
건축물 시설 정보
</h1>
<div className="grid grid-cols-6 gap-2 mt-4">
<div className="col-span-3">
<FormField
control={form.control}
name="ctpvCd"
render={({ field }) => (
<FormUi label="시도">
<SelectBox
className="col-span-3 "
label={""}
selectClass={selectClass}
selectArray={code.cityCd}
onSelectValue={(val)=>{
getSelCity(String(val))
field.onChange(Number(val) );
}
}
value={field.value}
/>
</FormUi>
)}
/>
</div>
<div className="grid grid-cols-6 gap-2 mt-4 ">
<div className="col-span-2">
<FormField
control={form.control}
name="bdstNm"
render={({ field }) => (
<FormUi label="건축물명">
<Input
className=""
placeholder="1,000,000"
type="text"
{...field}
/>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
name="daddr"
render={({ field }) => (
<FormUi label="위치">
<Input
className=""
placeholder="1,000,000"
type="search"
{...field}
/>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
name="bdstUsgCd"
render={({ field }) => (
<FormUi label="건축물용도">
<SelectBox
className={""}
selectClass={selectClass}
label={""}
selectArray={code.bdstUsgCd}
onSelectValue={(val) => {
field.onChange(val);
}}
value={field.value}
/>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
name="frstArchPrmsnDt"
render={({ field }) => (
<FormUi label="최초건축허가일">
<Input
<div className="col-span-3">
<FormField
control={form.control}
name="sggCd"
render={({ field }) => (
<FormUi label="시군구">
<SelectBox
className="col-span-3"
label={""}
selectClass={selectClass}
selectArray={selectSgg? selectSgg:code.sggCd || []}
onSelectValue={(val) =>{
getSgg(val)
field.onChange(Number(val))
}}
value={field.value}
/>
</FormUi>
)}
/>
</div>
</div>
<div className="grid grid-cols-6 gap-2 mt-4 ">
<div className="col-span-2">
<FormField
control={form.control}
name="bdstNm"
render={({ field }) => (
<FormUi label="건축물명">
<Input
className=""
type="date"
onChange={(e) =>
field.onChange(
e.target.value ? new Date(e.target.value) : undefined
)
}
value={
field.value ? field?.value.toISOString().split("T")[0] : ""
}
/>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
name="archArea"
render={({ field }) => (
<FormUi label="건축면적(m³)">
<Input
className=""
placeholder="1,000,000"
type="number"
{... field}
onChange={(e) => {
const value = e.target.value;
field.onChange(value === '' ? '' : Number(value));
}}
/>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
name=""
render={({ field }) => (
<FormUi label="법정의무대상여부">
<SelectBox
className={""}
selectClass={selectClass}
label={""}
selectArray={code.yn}
onSelectValue={(val) => {
field.onChange(val);
}}
value={field.value}
/>
</FormUi>
)}
/>
</div>
placeholder="1,000,000"
type="text"
{...field}
/>
</FormUi>
)}
/>
</div>
<h1 className="bg-gray-400 text-xl text-center border-2 p-2 mt-4">
중축, 개축, 증축
</h1>
<div className="flex justify-end gap-2">
<Button className="rounded-lg" onClick={plusHist}>이력추가</Button>
<Button className="rounded-lg bg-red-500 text-white" onClick={removeLastItem}>삭제</Button>
<div className="col-span-2">
<FormField
control={form.control}
name="daddr"
render={({ field }) => (
<FormUi label="위치">
<Input
className=""
placeholder="1,000,000"
type="search"
{...field}
/>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
name="bdstUsgCd"
render={({ field }) => (
<FormUi label="건축물용도">
<SelectBox
className={""}
selectClass={selectClass}
label={""}
selectArray={code.bdstUsgCd}
onSelectValue={(val) => {
field.onChange(Number(val));
}}
value={field.value}
/>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
name="frstArchPrmsnDt"
render={({ field }) => (
<FormUi label="최초건축허가일">
<DatePicker
mode={"single"}
field={{
value: new Date(field.value),
onChange: (date: Date | undefined) =>
field.onChange(date),
}}
selectClass={selectClass}
></DatePicker>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
name="archArea"
render={({ field }) => (
<FormUi label="건축면적(m³)">
<Input
className=""
placeholder="1,000,000"
type="number"
{...field}
onChange={(e) => {
const value = e.target.value;
field.onChange(value === "" ? "" : Number(value));
}}
/>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
name=""
render={({ field }) => (
<FormUi label="법정의무대상여부">
<SelectBox
className={""}
selectClass={selectClass}
label={""}
selectArray={code.yn}
onSelectValue={(val) => {
field.onChange(val);
}}
value={field.value}
/>
</FormUi>
)}
/>
</div>
</div>
<h1 className="bg-gray-400 text-xl text-center border-2 p-2 mt-4">
중축, 개축, 재축
</h1>
<div className="flex justify-end gap-2">
<Button type="button" className="rounded-lg" onClick={plusHist}>
이력추가
</Button>
<Button
type="button"
className="rounded-lg bg-red-500 text-white"
onClick={removeLastItem}
>
삭제
</Button>
</div>
{fields.map((field, index) => (
<div key={field.id} className="grid grid-cols-6 gap-2 mt-4">
<div className="col-span-2">
<FormField
control={form.control}
name={`history.${index}.bdstNm`}
name={`chgBuilding.${index}.bdstChgNm`}
render={({ field }) => (
<FormUi label="구분">
<SelectBox
className={""}
selectClass={selectClass}
label={""}
selectArray={code.cityCd}
selectArray={code.chBuCd}
onSelectValue={(val) => {
field.onChange(val);
}}
@@ -225,15 +296,18 @@ export default function BdstReg(form: any ) {
<div className="col-span-2">
<FormField
control={form.control}
name={`history.${index}.daddr`}
name={`chgBuilding.${index}.archChgPrmsnDt`}
render={({ field }) => (
<FormUi label="허가일">
<Input
className=""
placeholder="1,000,000"
type="search"
{...field}
/>
<DatePicker
mode={"single"}
field={{
value: safeDate(field.value) || new Date(),
onChange: (date: Date | undefined) =>
field.onChange(date),
}}
selectClass={selectClass}
></DatePicker>
</FormUi>
)}
/>
@@ -241,7 +315,7 @@ export default function BdstReg(form: any ) {
<div className="col-span-2">
<FormField
control={form.control}
name={`history.${index}.bdstUsgCd`}
name={`chgBuilding.${index}.archChgArea`}
render={({ field }) => (
<FormUi label="면적">
<Input
@@ -3,31 +3,25 @@
import { useWrStore } from "@/app/store";
import {
selectClass,
type RainyBuilding,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import {
bdstDefZod,
rainDefZod,
rainZod,
} from "@/components/lib/type/zod/fcltReg/controlZod";
type RainyBuilding,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { DatePicker, FormUi } from "@common/business_components";
import { Form, FormField, SelectBox } from "@common/business_components/ui";
import { Button, Input } from "@common/components/ui";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { useEffect, useState } from "react";
import { useForm, type UseFormReturn } from "react-hook-form";
import { z } from "zod";
import BdstReg from "../bdstReg/component";
export function RainRegForm({
rainForm,
isModal,
}: {
rainForm: RainyBuilding | undefined;
isModal: boolean;
}) {
const formSchema = z.object(rainZod);
const form = useForm<z.infer<typeof formSchema>>({
export const formToObj = (
isModal: boolean,
formSchema: z.ZodObject<any, "strip", z.ZodTypeAny, any, any>
) => {
return useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: isModal
? {
@@ -38,14 +32,26 @@ export function RainRegForm({
...rainDefZod,
},
});
};
const { code, rainReg, rainUpdate, init } = useWrStore(
(state) => state
);
const formSchema = z.object(rainZod);
export type RainFormType = UseFormReturn<z.infer<typeof formSchema>>;
export function RainRegForm({
rainForm,
isModal,
}: {
rainForm: RainyBuilding;
isModal: boolean;
}) {
const form = formToObj(isModal, formSchema);
const { code, rainReg, rainUpdate, rain } = useWrStore((state) => state);
const { rainFcltCd } = code;
useEffect(() => {
// console.log( " data ", data)
console.log(rainForm);
if (rainForm != null) {
const data = rainForm;
@@ -55,101 +61,109 @@ export function RainRegForm({
String(data?.reuseBuilding?.at(0)?.rainyObj?.pntfColKnd ?? "")
);
let formData;
if (data?.reuseBuilding?.at(0)) {
const rb = data.reuseBuilding?.at(0);
formData = {
...data,
...rb?.rainyObj,
...data.reuseBuilding?.at(0),
pntfColKnd: selectedOption ? String(selectedOption.val) : undefined,
frstArchPrmsnDt: new Date(data.frstArchPrmsnDt)
};
form.reset(formData);
} else {
formData = {
ctpvCd: data.ctpvCd,
sggCd: data.sggCd,
bdstNm: data.bdstNm,
daddr: data.daddr,
frstArchPrmsnDt: new Date(data.frstArchPrmsnDt),
...data
};
form.reset(formData);
}
}
}, [rainForm, rainFcltCd]);
}, [rainForm]);
// form 값이 변경될 때마다 로그 출력
useEffect(() => {
const subscription = form.watch((value) => {});
const subscription = form.watch((value) => {
});
return () => subscription.unsubscribe();
}, [form]);
function onSubmit(values: z.infer<typeof formSchema>) {
console.log("valuesd");
console.log(values);
let regRainForm = { ...rainForm };
const raw = values;
const rawVal = {
ctpvCd: raw?.ctpvCd,
const objToForm = (raw: z.infer<typeof formSchema>) => {
let regRainForm: RainyBuilding;
// 1. 기본 정보 정리
const obj = !rainForm ? rain.regRainForm : rainForm;
regRainForm = {
...obj,
ctpvCd: raw?.ctpvCd ,
sggCd: raw?.sggCd,
daddr: raw?.daddr,
bdstNm: raw?.bdstNm,
frstArchPrmsnDt: raw?.frstArchPrmsnDt.toISOString(),
frstArchPrmsnDt: raw?.frstArchPrmsnDt ,
archArea: raw?.archArea + "",
// archChgArea: raw?.archChgArea || 0, // Ensure archChgArea is always a string
};
// 1. 기본 정보 정리
if (isModal)
regRainForm = {...rawVal};
if(regRainForm?.reuseBuilding?.at(0)?.rainyObj){
const rainObj = regRainForm?.reuseBuilding?.at(0)?.rainyObj;
regRainForm.reuseBuilding[0].rainyObj = {
...rainObj,
pntfColKnd: raw.pntfColKnd || rainObj?.pntfColKnd,
pntfColArea: raw.pntfColArea || rainObj?.pntfColArea,
filtrTrtmfctCpct: raw.filtrTrtmfctCpct || rainObj?.filtrTrtmfctCpct,
filtrTrtmfctYn: raw.filtrTrtmfctYn || rainObj?.filtrTrtmfctYn,
filtrTrtmfctPrs: raw.filtrTrtmfctPrs || rainObj?.filtrTrtmfctPrs,
oilqMeasMthd: rainObj?.oilqMeasMthd,
};
regRainForm.reuseBuilding[0] = {
...rainForm?.reuseBuilding[0],
instlCmptnDt: raw.instlCmptnDt,
instlCst: raw.instlCst || rainForm?.reuseBuilding[0]?.instlCst,
instlCstSprtYn:
raw.instlCstSprtYn || rainForm?.reuseBuilding[0]?.instlCstSprtYn,
instlCstSprtAmt:
raw.instlCstSprtAmt || rainForm?.reuseBuilding[0]?.instlCstSprtAmt,
grntchBdstCertYn:
raw.grntchBdstCertYn || rainForm?.reuseBuilding[0]?.grntchBdstCertYn,
grntchBdstCertYr:
raw.grntchBdstCertYr || rainForm?.reuseBuilding[0]?.grntchBdstCertYr,
grntchBdstCertNo:
raw.grntchBdstCertNo || rainForm?.reuseBuilding[0]?.grntchBdstCertNo,
grntchBdstCertGrd:
raw.grntchBdstCertGrd || rainForm?.reuseBuilding[0]?.grntchBdstCertGrd,
bdstUsgCd: raw.bdstUsgCd || rainForm?.reuseBuilding[0]?.bdstUsgCd,
lawTrgtYn: raw.lawTrgtYn || rainForm?.reuseBuilding[0]?.lawTrgtYn,
};
const rainObj = regRainForm?.reuseBuilding?.at(0)?.rainyObj;
if (!regRainForm.reuseBuilding) {
regRainForm.reuseBuilding = [];
}
regRainForm.reuseBuilding[0] = {
...rainForm?.reuseBuilding?.at(0),
instlCmptnDt: raw.instlCmptnDt,
instlCst: raw.instlCst || rainForm?.reuseBuilding?.at(0)?.instlCst,
instlCstSprtYn:
raw.instlCstSprtYn || rainForm?.reuseBuilding?.at(0)?.instlCstSprtYn,
instlCstSprtAmt:
raw.instlCstSprtAmt || rainForm?.reuseBuilding?.at(0)?.instlCstSprtAmt,
grntchBdstCertYn:
raw.grntchBdstCertYn || rainForm?.reuseBuilding?.at(0)?.grntchBdstCertYn,
grntchBdstCertYr:
raw.grntchBdstCertYr || rainForm?.reuseBuilding?.at(0)?.grntchBdstCertYr,
grntchBdstCertNo:
raw.grntchBdstCertNo || rainForm?.reuseBuilding?.at(0)?.grntchBdstCertNo,
grntchBdstCertGrd:
raw.grntchBdstCertGrd || rainForm?.reuseBuilding?.at(0)?.grntchBdstCertGrd,
bdstUsgCd: raw.bdstUsgCd || rainForm?.reuseBuilding?.at(0)?.bdstUsgCd,
lawTrgtYn: raw.lawTrgtYn || rainForm?.reuseBuilding?.at(0)?.lawTrgtYn,
}
regRainForm.reuseBuilding[0].rainyObj = {
...rainObj,
pntfColKnd: raw.pntfColKnd || rainObj?.pntfColKnd,
pntfColArea: raw.pntfColArea || rainObj?.pntfColArea,
filtrTrtmfctCpct: raw.filtrTrtmfctCpct || rainObj?.filtrTrtmfctCpct,
filtrTrtmfctYn: raw.filtrTrtmfctYn || rainObj?.filtrTrtmfctYn,
filtrTrtmfctPrs: raw.filtrTrtmfctPrs || rainObj?.filtrTrtmfctPrs,
};
if (isModal) {
rainReg(raw);
rainReg(regRainForm);
} else {
rainUpdate(raw);
console.log(" regRainForm ", regRainForm)
rainUpdate(regRainForm);
}
};
init();
function onSubmit(values: z.infer<typeof formSchema>) {
console.log(values);
objToForm(values);
}
useEffect(() => {
console.log("form errors:", form.formState.errors);
}, [form.formState.errors]);
return (
<div className="">
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
{/* <div className="flex justify-between items-center mx-3"> */}
<div>
<div className="grid grid-cols-12">
<h1 className="pl-3 text-xl col-span-10">
@@ -160,7 +174,7 @@ export function RainRegForm({
</Button>
</div>
</div>
{isModal ? <BdstReg form={form}></BdstReg> : <></>}
{isModal&&rainForm!=undefined ? <BdstReg form={form} ud={rainForm}/> : <></>}
{isModal ? (
<h1 className="pl-3 text-xl col-span-10 mt-4 ">
○ 빗물이용시설 운영정보{" "}
@@ -179,20 +193,6 @@ export function RainRegForm({
name="instlCmptnDt"
render={({ field }) => (
<FormUi label="설치완료일">
{/* <Input
className=""
type="date"
onChange={(e) =>
field.onChange(
e.target.value ? new Date(e.target.value) : undefined
)
}
value={
field.value
? field?.value.toISOString().split("T")[0]
: ""
}
/> */}
<DatePicker
mode={"single"}
field={{
@@ -394,7 +394,7 @@ export function RainRegForm({
<div className="col-span-3 pl-6">
<FormField
control={form.control}
name="grntchCstSprtYn"
name="grntchBdstCertYn"
render={({ field }) => (
<FormUi label="인증여부">
<SelectBox
@@ -3,41 +3,38 @@ import { headMakeColSpan } from "@/app/ruseFcltMng/fcltReg/rainReg/page";
import { useWrStore } from "@/app/store";
import {
selectClass,
type bdstType,
type RainyInfoResponse,
type selectArray,
type RainyBuilding,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { ScrollArea, SearchInput, SelectBox, UiTable } from "@common/business_components";
import { Button, Input, Label } from "@common/components";
import { useEffect, useState } from "react";
import { RainRegForm } from "../../form/fcltReg/rainReg/component";
import { getCityCd, type selectArray } from "@/app/store/common/code";
import { getCity } from "@/components/lib/func/commom";
export type objSearchType = {
sgg: string|number;
city: string|number;
};
export function BdstReg() {
const { rain, code, bdst, findBdst } = useWrStore((state) => {
const { rain, code, bdst,findBdst } = useWrStore((state) => {
return state;
});
type objSearchType = {
sgg: string;
city: string;
};
const [bdstTable, setbdstTable] = useState<RainyInfoResponse[]>();
const [rainBdstForm, setRainBdstForm] = useState<RainyInfoResponse | undefined>();
const { bdstObj, rainRuseObj } = rain;
const [selectSgg, setSelectSgg] = useState<selectArray[] | undefined>()
const [bdstTable, setbdstTable] = useState<RainyBuilding[]>();
const [rainBdstForm, setRainBdstForm] = useState<RainyBuilding>({} as RainyBuilding);
const [searchTxt, setSearchTxt] = useState<string>()
const [selectSgg, setSelectSgg] = useState<selectArray[] | undefined>()
const [objSearch, setObjSearch] = useState<objSearchType>({sgg:"",city:""});
const getCity = (val: string) => {
const data = code.sggCd
.filter((item) => String(item.val).substring(0, 2) === val)
.map((item) => ({
val: String(item.val),
text: item.text // 한국어 텍스트
}));
const getSelCity = (val: string) => {
const data= getCity(val,code.sggCd)
setSelectSgg(data);
setObjSearch({ city:val , sgg:''})
};
const getSgg = (val: string | number) => {
@@ -46,20 +43,19 @@ export function BdstReg() {
};
const searchBdst=()=>{
if(objSearch.sgg===""){
if(objSearch.city===""){
alert('시도조건은 필수 입니다.')
return
}
let data =objSearch.city;
if(objSearch.sgg !=="" ){
data = objSearch.sgg
}
findBdst(String(data), searchTxt || "")
}
useEffect(()=>{
findBdst(searchTxt || "")
},[searchTxt])
useEffect(() => {
if (code.sggCd.length > 0) {
const table = bdst?.bdstBase?.map((item) => {
@@ -77,14 +73,14 @@ export function BdstReg() {
}
}, [code, bdst]);
const tableClick: (val: number | undefined) => void = (val) => {
if(val!==undefined && bdst?.bdstBase.length>0){
const data =bdst?.bdstBase[val]
setRainBdstForm([data]);
}
}
setRainBdstForm(data);
}
}
const nodeList = headMakeColSpan(bdst.moUpHeadList);
return (
<>
@@ -94,7 +90,7 @@ export function BdstReg() {
label={"시도"}
selectClass={selectClass}
selectArray={code.cityCd}
onSelectValue={getCity}
onSelectValue={getSelCity}
>
{" "}
</SelectBox>
@@ -108,7 +104,7 @@ export function BdstReg() {
{" "}
</SelectBox>
<Label className="w-20 text-base text-gray-600 mt-4 text-right">건축물명</Label>
<Input className="w-full h-full text-2xl col-span-2 col-start-8" type="text" value={searchTxt} onChange={(e) => setSearchTxt(e.target.value)}/>
<Input className="w-full h-full text-2xl col-span-2 col-start-8" type="text" value={searchTxt || ''} onChange={(e) => setSearchTxt(e.target.value)}/>
{/* <SearchInput
className="col-span-3 col-start-8"
label="건물명"
@@ -135,7 +131,7 @@ export function BdstReg() {
<div className="border-t border-gray-300 my-4"></div>
<ScrollArea className="h-[60vh]">
<div>
<RainRegForm rainForm={rainBdstForm ||undefined} isModal={true}></RainRegForm>
<RainRegForm rainForm={rainBdstForm } isModal={true}/>
</div>
</ScrollArea>
</div>