Merge commit '801966059375d5544bccf627269d124a71a7a6fa' into iipbs/wr/dev
iipbs_wr / build (push) Waiting to run

This commit is contained in:
leedj312
2025-04-02 13:03:36 +09:00
19 changed files with 1207 additions and 626 deletions
@@ -1,72 +1,94 @@
'use client'
"use client";
import { useWrStore } from "@/app/store";
import type { bdstType, rainRuseBd, TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"
import type {
RainyBuilding,
TableUpperProps,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { RainRegForm } from "@/components/ui/form/fcltReg/rainReg/component";
import { BdstReg } from "@/components/ui/modal/bdstReg/component";
import { ContentsDiv, ScrollArea, SearchDiv, SearchFormLeft, SearchFormRight, SearchInput, Title, UiModal, UiTable } from "@common/business_components";
import {
ContentsDiv,
ScrollArea,
SearchDiv,
SearchFormLeft,
SearchFormRight,
SearchInput,
Title,
UiModal,
UiTable,
} from "@common/business_components";
import ListDiv from "@common/business_components/ui/list_div";
import { Button, TableHead, TableRow } from "@common/components";
import { useEffect, useState } from "react";
import { useEffect, useState } from "react";
export const headMakeColSpan = (upHeadList: TableUpperProps[]) => {
return (<>
<TableRow>{
upHeadList.map((head: TableUpperProps) =>
(!head.upSequnce ? <TableHead rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead key={head.id} rowSpan={1} colSpan={3}>{'중축 개축 증축 '}</TableHead> : null))}
</TableRow>
<TableRow>
{upHeadList.map((head: TableUpperProps) =>
(head.upName === 'upChangeRe' ? <TableHead key={head.id}>{head.title}</TableHead> : null))}
</TableRow>
</>)
}
return (
<>
<TableRow>
{upHeadList.map((head: TableUpperProps) =>
!head.upSequnce ? (
<TableHead rowSpan={2} key={head.id}>
{head.title}
</TableHead>
) : head.upName === "upChangeRe" && head.upSequnce === 1 ? (
<TableHead key={head.id} rowSpan={1} colSpan={3}>
{"중축 개축 증축 "}
</TableHead>
) : null
)}
</TableRow>
<TableRow>
{upHeadList.map((head: TableUpperProps) =>
head.upName === "upChangeRe" ? (
<TableHead key={head.id}>{head.title}</TableHead>
) : null
)}
</TableRow>
</>
);
};
export default function Home() {
const { rain, code,init } = useWrStore((state) => {
return state
const { rain, code, init } = useWrStore((state) => {
return state;
});
const {bdstObj, rainRuseObj } =rain
const [rinBdstForm, setRinBdstForm] = useState <rainRuseBd[]> ();
const [bdstTable, setbdstTable] = useState <bdstType[]> ();
const { rainRes } = rain;
const [rainForm, setRainForm] = useState<RainyBuilding>();
const [bdstTable, setbdstTable] = useState<RainyBuilding[]>();
const nodeList = headMakeColSpan(rain.upHeadList);
useEffect(() => {
if (!rain.isInit) {
init();
}
}, [rain.isInit, init]);
useEffect(() => {
if (code.sggCd.length > 0) {
const table = rainRes.map((item) => {
const sggText = code.sggCd.find(
(cd) => cd.val.toString() === item.sggCd
)?.text;
const cityText = code.cityCd.find(
(cd) => cd.val.toString() === item.ctpvCd
)?.text;
return { ...item, sggText: sggText, cityText: cityText };
});
if (!rain.isInit) {
init();
}
}, [rain.isInit,init]);
useEffect ( () => {
if(code.sggCd.length>0){
const table= bdstObj.map((item) => {
const sggText= code.sggCd.find((cd)=>cd.val.toString() === item.sggCd )?.text;
const cityText= code.cityCd.find((cd)=>cd.val.toString() === item.ctpvCd )?.text;
return(
{...item,
sggText:sggText,
cityText:cityText
})
})
setbdstTable(table)
setbdstTable(table);
}
}, [code,bdstObj]);
}, [code, rainRes]);
const cellClick: (val: number | undefined) => void = (val) => {
let data
if((bdstTable ?? []).length > 0) {
data =rainRuseObj.filter((item)=> item.bdstInfoFk===bdstTable?.[val]?.bdstInfoPk)
setRinBdstForm(data)
}
}
if ((bdstTable ?? []).length > 0 && val !== undefined) {
{
setRainForm(rainRes[val]);
}
}
};
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>
@@ -74,12 +96,10 @@ export default function Home() {
className="col-span-3 my-7"
label="건물명"
textValue={""}
setText={function (val: string): void {
setText={function (): void {
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>
@@ -89,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 || []}
@@ -109,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
data={rinBdstForm || []}
rainForm={rainForm || undefined}
isModal={false}
></RainRegForm>
</ScrollArea>
</ListDiv>
</div>
</div>
</ContentsDiv>
</>
+20 -1
View File
@@ -1,11 +1,17 @@
import { getFectch } from "@/components/lib/api";
// Description: 공통코드
type selectArray = {
export type selectArray = {
text: string;
val: string | number;
};
export const yn :selectArray[]=[
{val:'Y', text:'Y'},
{val:'N', text:'N'},
]
export const bdstUsgCd: selectArray[] = [
{ val: 1, text: "운동장" },
{ val: 2, text: "체육관" },
@@ -38,13 +44,23 @@ 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[];
sggCd: selectArray[];
yn:selectArray[];
};
};
@@ -82,8 +98,10 @@ export const comCodeStateExport: comCodeState = {
isInit: false,
rainFcltCd: rainFcltCd,
bdstUsgCd: bdstUsgCd,
chBuCd:chBuCd,
cityCd: [],
sggCd: [],
yn:yn
},
};
@@ -118,6 +136,7 @@ export const codeActionExport: (set: any) => comCodeActions = (set: any) => {
},
}));
},
divCityCd: async(cd: number) => {
set((state: comCodeState) => ({
code: {
@@ -0,0 +1,79 @@
import { getFectch } from "@/components/lib/api";
import type { RainyBuilding } from "../rainReg";
type TableUpperProps = {
id: string;
title: string;
upName?: string;
upSequnce?: number;
};
const moUpHeadList: TableUpperProps[] = [
{ id: "cityText", title: "시도" },
{ id: "sggText", title: "시군구" },
{ id: "bdstNm", title: "시설명" },
{ id: "daddr", title: "위치" },
{ id: "frstArchPrmsnDt", title: "최초건축허가일" },
{ id: "archArea", title: "건축면적", },
{ id: "archChgYn", title: "여부", upName: "upChangeRe", upSequnce: 1 },
{ id: "archChgPrmsnDt", title: "허가일", upName: "upChangeRe", upSequnce: 2 },
{ id: "archChgArea", title: "면적", upName: "upChangeRe", upSequnce: 3 },
];
const bdstBase: RainyBuilding[] = [];
export type bdstFulType = bdstState & bdstActions;
export type bdstState = {
bdst: {
bdstBase: RainyBuilding[];
moUpHeadList:TableUpperProps[]
};
};
type bdstActions = {
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
moUpHeadList:moUpHeadList,
},
};
export const bdstActionsExport: (set: any) => bdstActions = (
set: any
) => {
return {
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{
}
},
};
};
@@ -1,46 +1,138 @@
import { bdstUsgCd, comCodeStateExport } from "@/app/store/common/code";
import { getFectch } from "@/components/lib/api";
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";
type RainyInfoResponse = {
ctpvCd: string;
sggCd: string;
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: number;
sggCd: number;
bdstNm: string;
daddr: string;
bdstUsgCd: string;
frstArchPrmsnDt: string;
frstArchPrmsnDt: Date;
archArea: string;
lawTrgtYn: string;
archChgArea: string;
archChgArea: number;
bdstInfoPk: number;
reuseBuilding: Array<{
bdstUsgCd: any;
bdstRuseFcltPk: number;
bdstInfoFk: number;
operMngCd: number | null;
anlOperCst: number | null;
instlCmptnDt: string | null;
instlCst: number | null;
archChgPrmsnDt: string | null;
instlCstSprtYn: string | null;
instlCstSprtAmt: number | null;
grntchBdstCertYn: string | null;
grntchBdstCertNo: string | null;
grntchBdstCertGrd: string | null;
grntchBdstCertYr: string | null;
rainyObj: {
bdstReuseFcltFk:number|null;
pntfColKnd: string | null;
pntfColArea: number | null;
dtfcltCpct:number|null;
filtrTrtmfctCpct: number | null;
filtrTrtmfctYn: string | null;
filtrTrtmfctPrs: number | null;
annRnwtQty:number|null;
oilqMeasMthd:string|null
} | null;
}>;
reuseBuilding: reuseBuilding[];
chgBuilding:chgBuilding[]
};
export type reuseBuilding = {
lawTrgtYn: string|undefined;
bdstUsgCd: number|undefined;
bdstRuseFcltPk: number;
bdstInfoFk: number;
operMngCd: number;
anlOperCst: number;
instlCmptnDt: Date|undefined;
instlCst: number|undefined;
//archChgPrmsnDt: string;
instlCstSprtYn: string|undefined;
instlCstSprtAmt: number|undefined;
grntchBdstCertYn: string|undefined;
grntchBdstCertNo: string|undefined;
grntchBdstCertGrd: string|undefined;
grntchBdstCertYr: string|undefined;
rainyObj: rainyObj | null;
};
export type rainyObj = {
bdstReuseFcltFk: number;
pntfColKnd: string | undefined;
pntfColArea: number | undefined;
dtfcltCpct: number;
filtrTrtmfctCpct: number | undefined;
filtrTrtmfctYn: string | undefined;
filtrTrtmfctPrs: string | undefined;
annRnwtQty: number;
oilqMeasMthd: string | undefined;
};
export type TableUpperProps = {
id: string;
@@ -49,76 +141,6 @@ export type TableUpperProps = {
upSequnce?: number;
};
export type rainRuseBd={
bdstRuseFcltPk: number, // 건축물 재이용시설 기본키
bdstInfoFk: number, // 건축물 정보 외부키
operMngCd:number|null, // 운영관리 코드 tb_wr_bdst_ruse_fclt 삭제 요망
anlOperCst: number|null, // 연간운영비용 tb_wr_bdst_ruse_fclt 삭제 요망
instlCmptnDt: Date|null, // 설치완료 일시 tb_wr_bdst_ruse_fclt 1
instlCst: number|null, // 설치 비용 tb_wr_bdst_ruse_fclt 2
instlCstSprtAmt: number|null, // 설치비용지원금액 tb_wr_bdst_ruse_fclt 8
grntchBdstCertYn: string|null, // 녹색 기술 건축물 인증여부 tb_wr_bdst_ruse_fclt 9
grntchBdstCertNo: string|null, // 녹색 기술 건축물 인증번호 tb_wr_bdst_ruse_fclt 10
grntchBdstCertGrd: string|null, // 녹색 기술 건축물 인증등급 tb_wr_bdst_ruse_fclt 11
grntchBdstCertYr: string|null, // 녹색 기술 건축물 인증년도 tb_wr_bdst_ruse_fclt 12
bdstReuseFcltFk:number|null;
dtfcltCpct:number|null, // 저류오 용량 tb_wr_rnwtr_utztn_fclt 3-1
pntfColKnd: string|null, // 접수지점 종류 tb_wr_rnwtr_utztn_fclt 3
pntfColArea: number|null, // 접수지점 지역 tb_wr_rnwtr_utztn_fclt 4
filtrTrtmfctCpct: number|null, // 여과 처리시설 용량 tb_wr_rnwtr_utztn_fclt 5
filtrTrtmfctYn: string|null, // 여과 처리시설 유무 tb_wr_rnwtr_utztn_fclt 6
filtrTrtmfctPrs: number|null, // 여과 처리시설 공정 tb_wr_rnwtr_utztn_fclt 7
annRnwtQty:number|null; //연간 빗물량
oilqMeasMthd:string|null // 유량측정 방법
}
export type reuseBuilding = {
bdstRuseFcltPk: number, // 건축물 재이용시설 기본키
bdstInfoFk: number, // 건축물 정보 외부키
operMngCd:number|null, // 운영관리 코드 tb_wr_bdst_ruse_fclt 삭제 요망
anlOperCst: number|null, // 연간운영비용 tb_wr_bdst_ruse_fclt 삭제 요망
instlCmptnDt: Date|null, // 설치완료 일시 tb_wr_bdst_ruse_fclt 1
instlCst: number|null, // 설치 비용 tb_wr_bdst_ruse_fclt 2
instlCstSprtAmt: number|null, // 설치비용지원금액 tb_wr_bdst_ruse_fclt 8
grntchBdstCertYn: string|null, // 녹색 기술 건축물 인증여부 tb_wr_bdst_ruse_fclt 9
grntchBdstCertNo: string|null, // 녹색 기술 건축물 인증번호 tb_wr_bdst_ruse_fclt 10
grntchBdstCertGrd: string|null, // 녹색 기술 건축물 인증등급 tb_wr_bdst_ruse_fclt 11
grntchBdstCertYr: string|null, // 녹색 기술 건축물 인증년도 tb_wr_bdst_ruse_fclt 12
rainyObj:rainyObj
}
export type rainyObj ={
bdstReuseFcltFk:number|null;
dtfcltCpct:number|null, // 저류오 용량 tb_wr_rnwtr_utztn_fclt 3-1
pntfColKnd: string|null, // 접수지점 종류 tb_wr_rnwtr_utztn_fclt 3
pntfColArea: number|null, // 접수지점 지역 tb_wr_rnwtr_utztn_fclt 4
filtrTrtmfctCpct: number|null, // 여과 처리시설 용량 tb_wr_rnwtr_utztn_fclt 5
filtrTrtmfctYn: string|null, // 여과 처리시설 유무 tb_wr_rnwtr_utztn_fclt 6
filtrTrtmfctPrs: number|null, // 여과 처리시설 공정 tb_wr_rnwtr_utztn_fclt 7
annRnwtQty:number|null; //연간 빗물량
oilqMeasMthd:string|null // 유량측정 방법
}
export type bdstType = {
ctpvCd: string; // 시도
sggCd: string; // 시군구
daddr: string; // 위치
bdstUsgCd: string; // 건축물용도
frstArchPrmsnDt: string; // 최초건축허가일
archArea: string; // 건축면적
lawTrgtYn: string; // 법적의무대상여부
archChgPrmsnDt: string; // 건축변경 허가일시
archChgArea: string; // 변경 면적
bdstInfoPk: number;
bdstNm: string;
};
export const upHeadList: TableUpperProps[] = [
{ id: "cityText", title: "시도" },
{ id: "sggText", title: "시군구" },
@@ -126,21 +148,65 @@ export const upHeadList: TableUpperProps[] = [
{ id: "daddr", title: "위치" },
{ id: "bdstUsgCd", title: "건축물용도" },
{ id: "frstArchPrmsnDt", title: "최초건축허가일" },
{ id: "archArea", title: "건축면적", },
{ id: "lawTrgtYn", title: "법적의무대상여부", },
{ id: "archArea", title: "건축면적" },
{ id: "lawTrgtYn", title: "법적의무대상여부" },
{ id: "archChgYn", title: "여부", upName: "upChangeRe", upSequnce: 1 },
{ id: "archChgPrmsnDt", title: "허가일", upName: "upChangeRe", upSequnce: 2 },
{ id: "archChgArea", title: "면적", upName: "upChangeRe", upSequnce: 3 },
];
const bdstObj: bdstType[] =[]
const rainRuseObj: rainRuseBd[] = []
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" },
@@ -150,96 +216,118 @@ export type rainFacState = {
rain: {
isInit: boolean;
upHeadList: TableUpperProps[];
rainRuseObj: rainRuseBd[];
bdstObj: bdstType[];
selectYN: selectArray[];
rainRes: RainyBuilding[];
regRainForm:RainyBuilding,
};
};
type rainFacSActions = {
init: () => void;
dataInit:( )=>void;
dataInit: () => void;
rainReg: (data: RainyBuilding) => void;
rainUpdate: (data: RainyBuilding) => void;
};
export type rainFacType = rainFacState & rainFacSActions;
export const rainFacStateExport: rainFacState = {
rain: {
isInit: false,
rainRes: rainRes,
upHeadList: upHeadList,
rainRuseObj: rainRuseObj,
bdstObj: bdstObj,
selectYN: selectYN,
regRainForm:regRainForm,
},
};
console.log(comCodeStateExport.code.sggCd)
const chBdstUsgCd =(value:string|number)=>{
const data = bdstUsgCd.find((item)=>item.val===value)?.text
return data;
}
const chCityCd =(value:string|number)=>{
const data = bdstUsgCd.find((item)=>item.val===value)?.text
return data;
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
) => {
return {
init: async() =>{
init: async () => {
try {
// 파라이터 수정 통합관리자 =0, 시관리자=시코드, 시군구 관리자= 시군구 코드 를 세번째 파라미터로 지정 / 건축물 서치가 있을경우 4번째 파라미터로 던지기 즉 1/20/42(서울시)/영현빌딩 이런식으로)
const res = await getFectch('wr', "/reuseFc/rainyInfoList/1/20/42");
const result = res.flatMap(({ reuseBuilding = [] as RainyInfoResponse["reuseBuilding"], ...item }) =>
reuseBuilding.map(rb => {
const { bdstUsgCd, archChgPrmsnDt, rainyObj, ...restRb } = rb;
const bdstObj = {
...item,
bdstUsgCd: bdstUsgCd ? chBdstUsgCd(bdstUsgCd) ?? '' : '',
archChgPrmsnDt: archChgPrmsnDt ?? ''
} as bdstType;
const rainRuseObj = {
...restRb,
...rainyObj
} as rainRuseBd;
return { bdstObj, rainRuseObj };
})
);
const rainRes = await initFetch();
// 여기서 상태 업데이트
return set((state: rainFacState) => ({
...state,
rain: {
...state.rain,
bdstObj: result.map((item: { bdstObj: any; }) => item.bdstObj),
rainRuseObj: result.map((item: { rainRuseObj: any; }) => item.rainRuseObj),
isInit: false
}
rainRes: rainRes,
isInit: false,
},
}));
} catch (error) {
console.log('error', error);
console.log("error", error);
} finally {
console.log('finally');
console.log("finally");
}
},
dataInit: () =>
set(async (state: rainFacState) => {
console.log(" state ", state.rain.bdstObj)
return ({
set((state: rainFacState) => {
console.log(" state ", state.rain);
return {
rain: {
...state.rain,
isInit: false,
},
})
};
}),
};
};
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 {
}
}
}}
+7 -2
View File
@@ -30,26 +30,30 @@ import {
type htdflFacType,
} from "./ruseFcltMng/fcltReg/htdflReg";
import { codeActionExport, comCodeStateExport, getCityCd, getSggCd, type comCodeState, type comCodeType } from "./common/code";
import { bdstActionsExport, bdstStateExport, type bdstFulType, type bdstState } from "./ruseFcltMng/fcltReg/bdstReg";
export type WrStore = comCodeType&
pubFacType &
rainFacType &
rswtFacType &
matDmdType &
htdflFacType;
htdflFacType&
bdstFulType;
export const StoreZus = (
initState: comCodeState&
rainFacState &
pubFacState &
rswtFacState &
matDmdState &
htdflFacState = {
htdflFacState &
bdstState= {
...comCodeStateExport,
...pubFacStateExport,
...rainFacStateExport,
...rswtFacStateExport,
...matDmdStateExport,
...htdflFacStateExport,
...bdstStateExport,
}
) => {
return createStore<WrStore>()((set) => {
@@ -63,6 +67,7 @@ export const StoreZus = (
...matDmdActionsExport(set),
...htdflFacActionsExport(set),
...codeActionExport(set),
...bdstActionsExport(set)
};
});
};
+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,67 +0,0 @@
import { z } from "zod";
export const rainZod = {
instlCmptnDt: z.date(),
instlCst: z.number(),
pntfColKnd: z.string(),
pntfColArea: z.number(),
filtrTrtmfctPrs: z.string(),
filtrTrtmfctYn: z.string(),
filtrTrtmfctCpct: z.string(),
instlCstSprtYn: z.string(),
instlCstSprtAmt: z.string(),
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: "N",
filtrTrtmfctCpct: "",
filtrTrtmfctPrs: "",
instlCstSprtYn: "",
instlCstSprtAmt: "",
grntchCstSprtYn: "",
grntchCstSprtCst: "",
grntchBdstCertYn: "",
grntchBdstCertYr: "",
grntchBdstCertNo: "",
grntchBdstCertGrd: "",
}
export const bdstZod ={
ctpvCd: z.string(), // 시도
sggCd: z.string(), // 시군구
daddr: z.string(), // 위치
bdstUsgCd: z.string(), // 건축물용도
frstArchPrmsnDt: z.string(), // 최초건축허가일
archArea: z.string(), // 건축면적
lawTrgtYn: z.string(), // 법적의무대상여부
archChgPrmsnDt: z.string(), // 건축변경 허가일시
archChgArea: z.string(), // 변경 면적
//bdstInfoPk: number;
bdstNm: z.string(),
}
export const bdstDefZod={
ctpvCd: '', // 시도
sggCd: '', // 시군구
daddr: '', // 위치
bdstUsgCd: '', // 건축물용도
frstArchPrmsnDt: '', // 최초건축허가일
archArea: '', // 건축면적
lawTrgtYn: '', // 법적의무대상여부
archChgPrmsnDt: '', // 건축변경 허가일시
archChgArea: '', // 변경 면적
//bdstInfoPk: number;
bdstNm: '',
}
@@ -1,68 +1,323 @@
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({
name: "chgBuilding",
control: form?.control, // Provide a fallback to avoid errors
});
const plusHist = () => {
append({
bdstNm: "",
daddr: "",
bdstUsgCd: "",
});
};
const removeLastItem = () => {
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 pl-6">
<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.cityCd}
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-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=""
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(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="bdstNm"
name={`chgBuilding.${index}.bdstChgNm`}
render={({ field }) => (
<FormUi label="건축물명">
<FormUi label="구분">
<SelectBox
className={""}
selectClass={selectClass}
label={""}
selectArray={code.chBuCd}
onSelectValue={(val) => {
field.onChange(val);
}}
value={field.value}
/>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
name={`chgBuilding.${index}.archChgPrmsnDt`}
render={({ field }) => (
<FormUi label="허가일">
<DatePicker
mode={"single"}
field={{
value: safeDate(field.value) || new Date(),
onChange: (date: Date | undefined) =>
field.onChange(date),
}}
selectClass={selectClass}
></DatePicker>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
name={`chgBuilding.${index}.archChgArea`}
render={({ field }) => (
<FormUi label="면적">
<Input
className=""
placeholder="1,000,000"
@@ -73,102 +328,9 @@ export default function BdstReg(form: any) {
)}
/>
</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.cityCd}
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
className=""
placeholder="1,000,000"
type="date"
{...field}
/>
</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}
/>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
name=""
render={({ field }) => (
<FormUi label="법정의무대상여부">
<SelectBox
className={""}
selectClass={selectClass}
label={""}
selectArray={code.cityCd}
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">
<Button className="mr-4 rounded-lg ">이력추가</Button>
</div>
<div className="border-b border-gray-300 my-4"> </div>
))}
<div className="border-b border-gray-300 my-4"> </div>
</>
);
}
@@ -1,96 +1,187 @@
"use client";
import { Form, FormField, SelectBox } from "@common/business_components/ui";
import { Button, Input } from "@common/components/ui";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { FormUi } from "@common/business_components";
import { useWrStore } from "@/app/store";
import {
selectClass,
type rainRuseBd,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { useEffect } from "react";
import {
bdstDefZod,
bdstZod,
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, useState } from "react";
import { useForm, type UseFormReturn } from "react-hook-form";
import { z } from "zod";
import BdstReg from "../bdstReg/component";
export function RainRegForm({
data,
isModal,
}: {
data: rainRuseBd[];
isModal: boolean;
}) {
console.log(isModal);
const formSchema = isModal
? z.object({ ...rainZod, ...bdstZod })
: z.object(rainZod);
const { rain, code } = useWrStore((state) => state);
const { rainFcltCd } = code;
useEffect(() => {
if (data && data.length > 0) {
console.log(data);
const selectedOption = rainFcltCd.find(
(item) => item.val === String(data[0]?.pntfColKnd ?? "")
);
const formData = {
...data[0],
pntfColKnd: selectedOption ? selectedOption.val : "",
instlCmptnDt: data[0]?.instlCmptnDt
? new Date(data[0].instlCmptnDt)
: undefined,
};
form.reset(formData);
}
}, [data, rainFcltCd]);
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
? { ...rainDefZod, ...bdstDefZod }
: { ...rainDefZod },
? {
...rainDefZod,
...bdstDefZod,
}
: {
...rainDefZod,
},
});
};
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(rainForm);
if (rainForm != null) {
const data = rainForm;
const selectedOption = rainFcltCd.find(
(item) =>
item.val ===
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 = {
...data
};
form.reset(formData);
}
}
}, [rainForm]);
// form 값이 변경될 때마다 로그 출력
useEffect(() => {
const subscription = form.watch((value) => {
console.log("form values changed:", value);
});
});
return () => subscription.unsubscribe();
}, [form]);
// 2. Define a submit handler.
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 ,
archArea: raw?.archArea + "",
// archChgArea: raw?.archChgArea || 0, // Ensure archChgArea is always a string
};
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(regRainForm);
} else {
console.log(" regRainForm ", regRainForm)
rainUpdate(regRainForm);
}
};
function onSubmit(values: z.infer<typeof formSchema>) {
// Do something with the form values.
// ✅ This will be type-safe and validated.
console.log(values);
objToForm(values);
}
const onSelectValue = (val: string) => {
console.log(val);
};
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">
{isModal ? "○건축물 운영정보" : "○ 빗물이용시설 운영정보"}
</h1>
<Button className="mr-4 rounded-lg col-span-2">저장</Button>
<Button type="submit" className="mr-4 rounded-lg col-span-2">
저장
</Button>
</div>
</div>
{isModal ? <BdstReg form={form}></BdstReg> : <></>}
{isModal ? <h1 className="pl-3 text-xl col-span-10 mt-4 ">○ 빗물이용시설 운영정보 </h1> : <></>}
{isModal&&rainForm!=undefined ? <BdstReg form={form} ud={rainForm}/> : <></>}
{isModal ? (
<h1 className="pl-3 text-xl col-span-10 mt-4 ">
○ 빗물이용시설 운영정보{" "}
</h1>
) : (
<></>
)}
<h1 className="bg-gray-400 text-xl text-center border-2 p-2 mt-4 ">
기본정보
</h1>
@@ -102,18 +193,15 @@ 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.toString().split("T")[0] : ""
}
/>
<DatePicker
mode={"single"}
field={{
value: new Date(field.value),
onChange: (date: Date | undefined) =>
field.onChange(date),
}}
selectClass={selectClass}
></DatePicker>
</FormUi>
)}
/>
@@ -130,6 +218,10 @@ export function RainRegForm({
placeholder="1,000,000"
type=""
{...field}
onChange={(e) => {
const value = e.target.value;
field.onChange(value === "" ? "" : Number(value));
}}
/>
</FormUi>
)}
@@ -158,7 +250,6 @@ export function RainRegForm({
selectArray={rainFcltCd}
onSelectValue={(val) => {
field.onChange(val);
onSelectValue(val);
}}
value={field.value}
/>
@@ -177,6 +268,10 @@ export function RainRegForm({
placeholder="1,000,000"
type=""
{...field}
onChange={(e) => {
const value = e.target.value;
field.onChange(value === "" ? "" : Number(value));
}}
/>
</FormUi>
)}
@@ -198,8 +293,8 @@ export function RainRegForm({
className={""}
selectClass={selectClass}
label={""}
selectArray={rain.selectYN}
onSelectValue={onSelectValue}
selectArray={code.yn}
onSelectValue={field.onChange}
{...field}
/>
</FormUi>
@@ -217,6 +312,10 @@ export function RainRegForm({
placeholder="1,000,000"
type=""
{...field}
onChange={(e) => {
const value = e.target.value;
field.onChange(value === "" ? "" : Number(value));
}}
/>
</FormUi>
)}
@@ -258,8 +357,8 @@ export function RainRegForm({
className={""}
selectClass={selectClass}
label={""}
selectArray={rain.selectYN}
onSelectValue={onSelectValue}
selectArray={code.yn}
onSelectValue={field.onChange}
value={field.value}
/>
</FormUi>
@@ -277,6 +376,10 @@ export function RainRegForm({
placeholder="1,000,000"
type=""
{...field}
onChange={(e) => {
const value = e.target.value;
field.onChange(value === "" ? "" : Number(value));
}}
/>
</FormUi>
)}
@@ -291,15 +394,15 @@ export function RainRegForm({
<div className="col-span-3 pl-6">
<FormField
control={form.control}
name="grntchCstSprtYn"
name="grntchBdstCertYn"
render={({ field }) => (
<FormUi label="인증여부">
<SelectBox
className={""}
selectClass={selectClass}
label={""}
selectArray={rain.selectYN}
onSelectValue={onSelectValue}
selectArray={code.yn}
onSelectValue={field.onChange}
value={field.value}
/>
</FormUi>
@@ -3,55 +3,94 @@ import { headMakeColSpan } from "@/app/ruseFcltMng/fcltReg/rainReg/page";
import { useWrStore } from "@/app/store";
import {
selectClass,
type bdstType,
type RainyBuilding,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { ScrollArea, SearchInput, SelectBox, UiTable } from "@common/business_components";
import { Button, Input } from "@common/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, init } = useWrStore((state) => {
const { rain, code, bdst,findBdst } = useWrStore((state) => {
return state;
});
const [bdstTable, setbdstTable] = useState<bdstType[]>();
const [rainBdstForm, setRainBdstForm] = useState<[]>();
const { bdstObj, rainRuseObj } = rain;
const getCity = (val: string | number) => {
console.log(val);
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 getSelCity = (val: string) => {
const data= getCity(val,code.sggCd)
setSelectSgg(data);
setObjSearch({ city:val , sgg:''})
};
const getSgg = (val: string | number) => {
console.log(val);
setObjSearch({...objSearch,sgg: String(val)})
};
const searchBdst=()=>{
if(objSearch.city===""){
alert('시도조건은 필수 입니다.')
return
}
let data =objSearch.city;
if(objSearch.sgg !=="" ){
data = objSearch.sgg
}
findBdst(String(data), searchTxt || "")
}
useEffect(() => {
if (code.sggCd.length > 0) {
const table = bdstObj.map((item) => {
const table = bdst?.bdstBase?.map((item) => {
const sggText = code.sggCd.find(
(cd) => cd.val.toString() === item.sggCd
(cd) => cd.val === Number(item.sggCd)
)?.text;
const cityText = code.cityCd.find(
(cd) => cd.val.toString() === item.ctpvCd
(cd) => cd.val === Number(item.ctpvCd)
)?.text;
return { ...item, sggText: sggText, cityText: cityText };
});
setbdstTable(table);
}
}, [code, bdstObj]);
}, [code, bdst]);
const cellClick = () => {};
const nodeList = headMakeColSpan(rain.upHeadList);
const tableClick: (val: number | undefined) => void = (val) => {
if(val!==undefined && bdst?.bdstBase.length>0){
const data =bdst?.bdstBase[val]
setRainBdstForm(data);
}
}
const nodeList = headMakeColSpan(bdst.moUpHeadList);
return (
<>
<div className="grid grid-cols-12 gap-4 pb-4">
<div className="grid grid-cols-12 gap-4 mt-4">
<SelectBox
className="col-span-3 col-start-4"
className="col-span-3 "
label={"시도"}
selectClass={selectClass}
selectArray={code.cityCd}
onSelectValue={getCity}
onSelectValue={getSelCity}
>
{" "}
</SelectBox>
@@ -59,41 +98,42 @@ export function BdstReg() {
className="col-span-3"
label={"시군구"}
selectClass={selectClass}
selectArray={code.sggCd}
selectArray={selectSgg || []}
onSelectValue={getSgg}
>
{" "}
</SelectBox>
<SearchInput
className="col-span-3 col-start-10"
<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)}/>
{/* <SearchInput
className="col-span-3 col-start-8"
label="건물명"
textValue={""}
setText={function (val: string): void {
throw new Error("Function not implemented.");
}}
/>
textValue={searchTxt}
setText={ setSearchTxt}
/> */}
<Button className="rounded-lg" onClick={()=>{searchBdst()}}>조회</Button>
</div>
<div className="border-t border-gray-300 my-4"></div>
<div className="h-auto">
<div>
<UiTable
tableData={bdstTable || []}
headlist={rain.upHeadList}
headlist={bdst.moUpHeadList}
pageSize={-10}
total={-1}
headName={undefined}
cellClick={cellClick}
cellClick={tableClick}
>
{nodeList}
</UiTable>
</div>
<div >
<div className="border-t border-gray-300 my-4"></div>
<ScrollArea className="h-[60vh]">
<div>
<RainRegForm data={rainBdstForm || []} isModal={true}></RainRegForm>
<RainRegForm rainForm={rainBdstForm } isModal={true}/>
</div>
</ScrollArea>
</div>
</div>
</>
);
@@ -0,0 +1,53 @@
import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@common/components";
import React from "react";
type ModalType = {
bodyClass: string;
butNm: string;
title: string;
body: React.ReactNode;
open?: boolean;
onOpenChange?: (open: boolean) => void;
}
export function UiModal({ bodyClass, butNm, title, body, open, onOpenChange }: ModalType) {
const dialogProps = open !== undefined && onOpenChange !== undefined
? { open, onOpenChange }
: {};
return (
<>
{!open && (
<Dialog>
<DialogTrigger asChild>
<Button className="mr-4 rounded-lg">{butNm}</Button>
</DialogTrigger>
<DialogContent className={bodyClass}>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>
</DialogDescription>
</DialogHeader>
{body}
<DialogFooter className="sm:justify-start">
</DialogFooter>
</DialogContent>
</Dialog>
)}
{open && (
<Dialog {...dialogProps}>
<DialogContent className={bodyClass}>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>
</DialogDescription>
</DialogHeader>
{body}
<DialogFooter className="sm:justify-start">
</DialogFooter>
</DialogContent>
</Dialog>
)}
</>
);
}
@@ -1,33 +1,50 @@
import { Button, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@common/components";
import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTrigger } from "@common/components";
type ModalType={
bodyClass:string
butNm:string
title:string
body:React.ReactNode
type ModalType = {
bodyClass: string;
butNm: string;
title: string | undefined;
body: React.ReactNode;
open?: boolean;
onOpenChange?: (open: boolean) => void;
}
export function UiModal({bodyClass,butNm,title ,body}:ModalType ) {
export function UiModal({ bodyClass, butNm, title, body, open, onOpenChange }: ModalType) {
const dialogProps = open !== undefined && onOpenChange !== undefined && title !== undefined
? { open, onOpenChange, title }
: {};
return (
<>
<Dialog >
<DialogTrigger asChild>
<Button className="mr-4 rounded-lg">{butNm}</Button>
</DialogTrigger>
<DialogContent className={bodyClass}>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>
</DialogDescription>
</DialogHeader>
{body}
<DialogFooter className="sm:justify-start">
</DialogFooter>
</DialogContent>
</Dialog>
{!open && (
<Dialog>
<DialogTrigger asChild>
<Button className="mr-4 rounded-lg">{butNm}</Button>
</DialogTrigger>
<DialogContent className={bodyClass}>
<DialogHeader>
<DialogDescription>
</DialogDescription>
</DialogHeader>
{body}
<DialogFooter className="sm:justify-start">
</DialogFooter>
</DialogContent>
</Dialog>
)}
{open && (
<Dialog {...dialogProps}>
<DialogContent className={bodyClass}>
<DialogHeader>
<DialogDescription>
</DialogDescription>
</DialogHeader>
{body}
<DialogFooter className="sm:justify-start">
</DialogFooter>
</DialogContent>
</Dialog>
)}
</>
);
}
@@ -3,13 +3,26 @@ import React from "react";
const SearchInput = React.forwardRef<HTMLInputElement, {className:string, label:string, textValue:string, setText:(val:string)=>void}>(({className, label, textValue, setText}, ref) => {
const changeText=(e:React.ChangeEvent<HTMLInputElement>)=>{
if(e?.target?.value) setText(e.target.value)
}
if(e?.target?.value){
setText(e.target.value)
}
}
const keyUp=(e:any)=>{
if(e.keyCode===8 && e.target.value.length==1){
setText('')
}
}
return (
<div className={className+" flex items-center"} >
{label && <Label className="w-20 text-base text-gray-600">{label}</Label>}
<Input className="flex-1 ml-8 w-3/4 h-10 border rounded" value={textValue} onChange={changeText}></Input>
<Input className="flex-1 ml-8 w-3/4 h-10 border rounded" value={textValue} onChange={changeText} onKeyUp={keyUp}></Input>
</div>
)
});
@@ -3,7 +3,7 @@ import UiPageNations from "./uiPageNations";
type UiTableProps = {
headName: React.ReactNode | undefined;
tableData: { [key: string]: string | number | boolean }[];
tableData: { [key: string]: string | number | boolean | object}[];
headlist: UiHeadProps[];
pageSize: number;
total: number;
@@ -34,9 +34,9 @@ export function UiTable({ tableData, headlist, pageSize, total, children, headNa
</TableRow>}
</TableHeader>
<TableBody className='text-center'>
{tableData?.map((el: { [key: string]: string | number | boolean }, index) => (
{tableData?.map((el: { [key: string]: string | number | boolean | object}, index) => (
<TableRow key={index + "row"} >
{headlist.map((head) => (
{headlist?.map((head) => (
<TableCell className="cursor-pointer" onClick={()=>cellClick && cellClick(index)} key={head.id + index}>{el[head.id]}</TableCell>
))}
</TableRow>
@@ -1,46 +1,78 @@
'use client'
'use client';
import { useEffect, useState } from "react";
import { Pagination, PaginationContent, PaginationItem, PaginationPrevious, PaginationLink, PaginationNext } from "./lib/pagination";
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationPrevious,
PaginationLink,
PaginationNext
} from "./lib/pagination";
interface CommonPageNationsProps {
total: number;
cur: number;
pageSize: number;
total: number;
cur: number;
pageSize: number;
}
export default function UiPageNations(commonPageNationsProps: CommonPageNationsProps) {
const [pageProps, setPageProps] = useState(commonPageNationsProps);
const [pageProps, setPageProps] = useState(commonPageNationsProps);
useEffect(() => {
setPageProps(commonPageNationsProps);
}, [commonPageNationsProps]);
useEffect(() => {
setPageProps(commonPageNationsProps);
} ,[commonPageNationsProps]);
const totalPages = Math.ceil(pageProps.total / pageProps.pageSize);
const pagesPerGroup = 10;
const currentGroup = Math.floor((pageProps.cur - 1) / pagesPerGroup);
const startPage = currentGroup * pagesPerGroup + 1;
const endPage = Math.min(startPage + pagesPerGroup - 1, totalPages);
const handlePageChange = (page: number) => {
setPageProps({ ...pageProps, cur: page });
};
return(
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="#" />
</PaginationItem>
return (
<Pagination>
<PaginationContent>
{/* 이전 그룹으로 이동 */}
<PaginationItem>
<PaginationPrevious
href="#"
onClick={() => {
if (startPage > 1) handlePageChange(startPage - 1);
}}
/>
</PaginationItem>
{/* 현재 그룹 페이지들 표시 */}
{
Array.from({length:Math.ceil(commonPageNationsProps.total/commonPageNationsProps.pageSize)},(_,i)=>i+1).map((el,index)=>(
<PaginationItem key={index}>
<PaginationLink href= '#'>{el}</PaginationLink>
</PaginationItem>
))
}
<PaginationItem>
<PaginationNext href="#" />
Array.from({ length: endPage - startPage + 1 }, (_, i) => startPage + i).map((pageNum) => (
<PaginationItem key={pageNum}>
<PaginationLink
href="#"
isActive={pageNum === pageProps.cur}
onClick={() => handlePageChange(pageNum)}
>
{pageNum}
</PaginationLink>
</PaginationItem>
</PaginationContent>
</Pagination>
);
))
}
{/* 다음 그룹으로 이동 */}
<PaginationItem>
<PaginationNext
href="#"
onClick={() => {
if (endPage < totalPages) handlePageChange(endPage + 1);
}}
/>
</PaginationItem>
</PaginationContent>
</Pagination>
);
}