빗물재이용 데이터 조회 개발 중

This commit is contained in:
leedj312
2025-03-24 14:42:07 +09:00
parent 8d904d6714
commit 27ea503260
12 changed files with 430 additions and 140 deletions
@@ -90,7 +90,7 @@ const resetContents = () => {
<div className="flex justify-between items-center">
<TabsList>
<TabsTrigger value="mng">운영정보</TabsTrigger>
<TabsTrigger value="buse">시설현황</TabsTrigger>
<TabsTrigger value="buse">시설정보</TabsTrigger>
</TabsList>
<Button className="rounded-lg" onClick={resetContents}>
신규등록
@@ -4,6 +4,7 @@ import type { TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"
import { RainRegForm } from "@/components/ui/form/fcltReg/rainReg/component";
import { ScrollArea, SearchDiv, SearchInput, UiTable } from "@common/business_components";
import { Button, TableHead, TableRow } from "@common/components";
import { useEffect } from "react";
export const headMakeColSpan = (upHeadList: TableUpperProps[]) => {
@@ -22,15 +23,29 @@ export const headMakeColSpan = (upHeadList: TableUpperProps[]) => {
export default function Home() {
const { rain } = useWrStore((state) => state);
const nodeList = headMakeColSpan(rain.upHeadList);
const { rain,init ,dataInit} = useWrStore((state) => {
console.log(state)
return state
});
const {bdstObj, rainRuseObj } =rain
const nodeList = headMakeColSpan(rain.upHeadList);
const headName = () => {
return (
<h1 className="pl-3 text-xl">○건축물 목록</h1>
)
}
useEffect(() => {
console.log(rain)
if (!rain.isInit) {
init();
}
}, [rain.isInit,init]);
return (
<>
<div className="grid grid-cols-2 gap-4 ">
@@ -42,8 +57,8 @@ export default function Home() {
<SearchInput className='col-span-3 my-7' label="건물명" />
</div>
<div className='w-1/5 flex items-center justify-end'>
<Button className='mr-4 rounded-lg'>조회</Button>
<Button className='mr-4 rounded-lg'>저장</Button>
<Button className='mr-4 rounded-lg'>조회</Button>
<Button className='mr-4 rounded-lg'>저장</Button>
<Button className='mr-4 rounded-lg'>신규등록</Button>
</div>
</SearchDiv>
@@ -51,13 +66,13 @@ export default function Home() {
</div>
<div className="colsapn-1 pl-11">
<UiTable tableData={rain.rainOfObject} headlist={rain.upHeadList} pageSize={100} total={10} headName={headName()}>
<UiTable tableData={rain.bdstObj} headlist={rain.upHeadList} pageSize={100} total={10} headName={headName()}>
{nodeList}
</UiTable>
</div>
<div className="colsapn-1 pr-11 max-h-full ovreflow-y-scroll">
<ScrollArea>
<RainRegForm></RainRegForm>
<RainRegForm ></RainRegForm>
</ScrollArea>
</div>
@@ -1,10 +1,10 @@
import {
upHeadList,
type rainFacOfType,
type bdstType,
type TableUpperProps,
} from "../rainReg";
const htdflOfObject: rainFacOfType[] = [
const htdflOfObject: bdstType[] = [
{
sido: "서울",
sigungo: "종로구",
@@ -53,7 +53,7 @@ export type htdflFacState = {
htdfl: {
isInit: boolean;
upHeadList: TableUpperProps[];
htdflOfObject: rainFacOfType[];
htdflOfObject: bdstType[];
};
};
type htdflFacSActions = {
@@ -1,134 +1,262 @@
import { getFectch } from "@/components/lib/api";
type RainyInfoResponse = {
ctpvCd: string;
sggCd: string;
bdstNm: string;
daddr: string;
bdstUsgCd: string;
frstArchPrmsnDt: string;
archArea: string;
lawTrgtYn: string;
archChgArea: string;
bdstInfoPk: number;
reuseBuilding: Array<{
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: {
pntfColKnd: string | null;
pntfColArea: number | null;
filtrTrtmfctCpct: number | null;
filtrTrtmfctYn: string | null;
filtrTrtmfctPrs: number | null;
} | null;
}>;
};
export type TableUpperProps = {
id: string;
title: string;
upName?: string;
upSequnce?: number;
}
export type rainFacOfType = {
sido: string,
sigungo: string,
facilityName: string,
location: string,
locationgubun: string,
firstConstructionPermission:string,
facilityCapacity: string,
buildingArea:string,
yn?: string,
permissionDay:string;
authoDay?: string,
area?: string,
reuse?: string,
register?: string,
legalTargetYn:string,
}
id: string;
title: string;
upName?: string;
upSequnce?: number;
};
export const upHeadList:TableUpperProps[] = [
{ id: "sido", title: "시도"},
{ id: "sigungo", title: "시군구"},
{ id: "facilityName", title: "시설명"},
{ id: "location", title: "위치"},
{ id: "locationgubun", title: "지역구분"},
{ id: "facilityCapacity", title: "시설용량"},
{ id: "yn", title: '여부', upName:'upChangeRe' , upSequnce:1 },
{ id: "authoDay", title: '허가일',upName:'upChangeRe', upSequnce:2 },
{ id: "area", title: '면적' ,upName:'upChangeRe',upSequnce:3 }];
const rainOfObject:rainFacOfType[] = [
{
sido: "서울",
sigungo: "종로구",
facilityName: "그랑서울",
location: "종로 33",
locationgubun: "업무시설",
firstConstructionPermission : '2024-10-10',
buildingArea: "50",
facilityCapacity: "800,000",
reuse: "Y",
permissionDay:'2024-10-10',
register: "Y",
legalTargetYn:"Y"
},
{
sido: "서울",
sigungo: "종로구",
facilityName: "그랑서울",
location: "종로 33",
locationgubun: "업무시설",
firstConstructionPermission : '2024-10-10',
buildingArea: "50",
facilityCapacity: "800,000",
reuse: "Y",
permissionDay:'2024-10-10',
register: "Y",
legalTargetYn:"Y"
},
{
sido: "서울",
sigungo: "종로구",
facilityName: "그랑서울",
location: "종로 33",
locationgubun: "업무시설",
firstConstructionPermission : '2024-10-10',
buildingArea: "50",
facilityCapacity: "800,000",
reuse: "Y",
permissionDay:'2024-10-10',
register: "Y",
legalTargetYn:"Y"
},
]
export type rainRuseType = {
bdstRuseFcltPk: number,
bdstInfoFk: number,
operMngCd:number|null,
anlOperCst: number|null,
instlCmptnDt: Date|null,
instlCst: number|null,
pntfColKnd: string|null,
pntfColArea: number|null,
filtrTrtmfctCpct: number|null,
filtrTrtmfctYn: string|null,
filtrTrtmfctPrs: number|null,
instlCstSprtYn: string|null,
instlCstSprtAmt: number|null,
grntchBdstCertYn: string|null,
grntchBdstCertNo: string|null,
grntchBdstCertGrd: string|null,
grntchBdstCertYr: string|null,
export type selectArray ={
text:string,
val:string
}
// crgRdctYn: string|null,
// crgRdctBsst: string|null,
// crgRdctAmt:number|null,
// ruseFcltFlg: string|null,
// bdstReuseFcltFk:number|null,
// annRnwtQty: number|null,
// oilqMeasMthd: string|null,
}
export const selectClass ="w-full h-full text-2xl";
export type bdstType = {
ctpvCd: string; // 시도
sggCd: string; // 시군구
bdstNm: string; // 시설명
daddr: string; // 위치
bdstUsgCd: string; // 건축물용도
frstArchPrmsnDt: string; // 최초건축허가일
archArea: string; // 건축면적
lawTrgtYn: string; // 법적의무대상여부
archChgPrmsnDt: string; // 건축변경 허가일시
archChgArea: string; // 변경 면적
bdstInfoPk: number;
};
export const upHeadList: TableUpperProps[] = [
{ id: "ctpvCd", title: "시도" },
{ id: "sggCd", title: "시군구" },
{ id: "bdstNm", title: "시설명" },
{ id: "daddr", title: "위치" },
{ id: "bdstUsgCd", title: "건축물용도" },
{ id: "frstArchPrmsnDt", 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: rainRuseType[] = []
// =[{
// sido: "",
// sigungo: "",
// facilityName: "",
// location: "",
// locationgubun: "",
// firstConstructionPermission: "",
// facilityCapacity: "",
// buildingArea: "",
// permissionDay: "",
// legalTargetYn: ""
// }]
// const rainFcltObj: rainFcltType[] = [{
// instlCmptnDt: "",
// instlCst: "",
// instlCstSprtYn: "",
// instlCstSprtAmt: "",
// grntchBdstCertYn: "",
// grntchBdstCertNo: "",
// grntchBdstCertGrd: "",
// grntchBdstCertYr: "",
// pntfColKnd: "",
// pntfColArea: 0,
// filtrTrtmfctCpct: 0,
// filtrTrtmfctYn: "",
// filtrTrtmfctPrsnl: 0
// }]
export type selectArray = {
text: string;
val: string;
};
export const selectClass = "w-full h-full text-2xl";
const selectHomeWater = [
{ text: '집수면', val: "1" },
{ text: "종류", val: "2" },
];
{ text: "집수면", val: "1" },
{ text: "종류", val: "2" },
];
const selectYN= [
{ text: 'Y', val: "1" },
{ text: 'N', val: "2" },
];
export type rainFacState ={ rain:{
const selectYN = [
{ text: "Y", val: "1" },
{ text: "N", val: "2" },
];
export type rainFacState = {
rain: {
isInit: boolean;
upHeadList: TableUpperProps[];
rainOfObject: rainFacOfType[];
selectHomeWater:selectArray[];
selectYN:selectArray[];
}}
rainRuseObj: rainRuseType[];
bdstObj: bdstType[];
// rainFcltObj: rainFcltType[];
// selectHomeWater: selectArray[];
selectYN: selectArray[];
};
};
type rainFacSActions = {
decrementList: () => void
}
init: () => void;
dataInit:( )=>void;
};
//const rainSelectApi = getFectch('v1/reuseFc/rainyInfo/1/20');
export type rainFacType = rainFacState & rainFacSActions;
export const rainFacStateExport:rainFacState= {rain:{
isInit:false,
export const rainFacStateExport: rainFacState = {
rain: {
isInit: false,
upHeadList: upHeadList,
rainOfObject: rainOfObject,
selectHomeWater:selectHomeWater,
selectYN:selectYN
}}
export const rainFacActionsExport:(set:any)=>rainFacSActions=(set: any) => {
return {
decrementList:()=>set(
(state:rainFacState) => {
return (
{rain:{
upHeadList: state.rain.upHeadList,
rainOfObject:
state.rain.rainOfObject.slice(0, state.rain.rainOfObject.length - 1)
}})}
)
}
}
rainRuseObj: rainRuseObj,
bdstObj: bdstObj,
//rainFcltObj:rainFcltObj,
// selectHomeWater: selectHomeWater,
selectYN: selectYN,
},
};
export const rainFacActionsExport: (set: any) => rainFacSActions = (
set: any
) => {
return {
init: async() =>{
try {
const res = await getFectch("/reuseFc/rainyInfoList/1/20");
const result = res.flatMap(({ reuseBuilding = [] as RainyInfoResponse["reuseBuilding"], ...item }) =>
reuseBuilding.map(rb => {
const rainy = rb.rainyObj || {};
const bdstObj: bdstType = {
ctpvCd: String(item.ctpvCd ?? ''),
sggCd: String(item.sggCd ?? ''),
bdstNm: item.bdstNm ?? '',
daddr: item.daddr ?? '',
bdstUsgCd: String(item.bdstUsgCd ?? ''),
frstArchPrmsnDt: item.frstArchPrmsnDt ?? '',
archArea: String(item.archArea ?? ''),
lawTrgtYn: item.lawTrgtYn ?? '',
archChgPrmsnDt: rb.archChgPrmsnDt ?? '',
archChgArea: String(item.archChgArea ?? ''),
bdstInfoPk: item.bdstInfoPk
};
const rainRuseObj: rainRuseType = {
bdstRuseFcltPk: rb.bdstRuseFcltPk,
bdstInfoFk: rb.bdstInfoFk,
operMngCd: rb.operMngCd,
anlOperCst: rb.anlOperCst,
instlCmptnDt: rb.instlCmptnDt ? new Date(rb.instlCmptnDt) : null,
instlCst: rb.instlCst,
pntfColKnd: rb.rainyObj?.pntfColKnd || null,
pntfColArea: rb.rainyObj?.pntfColArea || null,
filtrTrtmfctCpct: rb.rainyObj?.filtrTrtmfctCpct || null,
filtrTrtmfctYn: rb.rainyObj?.filtrTrtmfctYn || null,
filtrTrtmfctPrs: rb.rainyObj?.filtrTrtmfctPrs || null,
instlCstSprtYn: rb.instlCstSprtYn,
instlCstSprtAmt: rb.instlCstSprtAmt,
grntchBdstCertYn: rb.grntchBdstCertYn,
grntchBdstCertNo: rb.grntchBdstCertNo,
grntchBdstCertGrd: rb.grntchBdstCertGrd,
grntchBdstCertYr: rb.grntchBdstCertYr
};
return { bdstObj, rainRuseObj };
})
);
console.log('result', result )
// 여기서 상태 업데이트
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
}
}));
} catch (error) {
console.log('error', error);
} finally {
console.log('finally');
}
},
dataInit: () =>
set(async (state: rainFacState) => {
console.log(" state ", state.rain.bdstObj)
return ({
rain: {
...state.rain,
isInit: false,
},
})
}),
};
};
@@ -1,7 +1,7 @@
import { upHeadList, type rainFacOfType, type selectArray, type TableUpperProps } from "../rainReg";
import { upHeadList, type bdstType, type selectArray, type TableUpperProps } from "../rainReg";
const rswtOfObject:rainFacOfType[] = [
const rswtOfObject:bdstType[] = [
{
sido: "서울",
sigungo: "종로구",
@@ -60,7 +60,7 @@ const selectHomeWater = [
export type rswtFacState ={ rswt:{
isInit: boolean;
upHeadList: TableUpperProps[];
rswtOfObject: rainFacOfType[];
rswtOfObject: bdstType[];
selectHomeWater:selectArray[];
selectYN:selectArray[];
}}
+64
View File
@@ -0,0 +1,64 @@
//8880
import { DEV_URL_WR } from "../config/env";
export const getFectch = async (url: string) => {
const response = await fetch( DEV_URL_WR+url , {
method: "GET",
headers: {
accept: "application/json",
},
});
if(!response.ok) {
throw new Error(`오류 발생: ${response.status}`);
}
const res = await response.json()
return res.data;
}
export const postFectch = async (url: string, params: any) => {
const response = await fetch(DEV_URL_WR+url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(params),
});
if(!response.ok) {
throw new Error(`오류 발생: ${response.status}`);
}
return response;
}
export const putFectch = async (url: string, params: any) => {
const response = await fetch(DEV_URL_WR+url, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(params),
});
if(!response.ok) {
throw new Error(`오류 발생: ${response.status}`);
}
return response;
}
export const deleteFectch = async (url: string, params: any) => {
const response = await fetch(DEV_URL_WR+url, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(params),
});
if(!response.ok) {
throw new Error(`오류 발생: ${response.status}`);
}
return response;
}
+6
View File
@@ -0,0 +1,6 @@
const LOCAL_PORT = "3000";
const DEV_PORT = "8880";
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`;
+1
View File
@@ -0,0 +1 @@
export * from './env';
@@ -308,7 +308,7 @@ const nodeList = headMakeColSpan(pubMngUpHeadList);
</div>
</div>
<h1 className="bg-gray-400 text-xl text-center border-2 p-2 ">
<h1 className="bg-gray-400 text-xl text-center border-2 p-2 ">
농축수관리{" "}
</h1>
<div className="grid grid-cols-12 gap-4">
@@ -375,6 +375,51 @@ const nodeList = headMakeColSpan(pubMngUpHeadList);
</div>
</div>
<h1 className="bg-gray-400 text-xl text-center border-2 p-2 ">
폐수배출시설 정보
</h1>
<div className="grid grid-cols-12 gap-4">
<div className="col-span-4">
<FormField
control={form.control}
name="name_7678668236"
render={({ field }) => (
<FormUi label="폐수배출물신고 허가여부">
<Input placeholder="" type="" {...field} />
</FormUi>
)}
/>
</div>
<div className="col-span-4">
<FormField
control={form.control}
name="name_7913744238"
render={({ field }) => (
<FormUi label="Tms설치여부">
<Input placeholder="" type="" {...field} />
</FormUi>
)}
/>
</div>
<div className="col-span-4">
<FormField
control={form.control}
name="name_1368081408"
render={({ field }) => (
<FormUi label="공공하수도 유입제외 허가여부">
<Input placeholder="" type="" {...field} />
</FormUi>
)}
/>
</div>
</div>
<h1 className=" text-xl">
재이용 원수취수 현황
</h1>
</form>
</Form>
</div>
@@ -18,6 +18,7 @@ import {
type TableUpperProps,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import type { fcltOperInfoType, ruseFcltType } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg";
import { PbnstMngModal } from "@/components/ui/modal/pbnstMng/component";
const formSchema = z.object({
fcltNm: z.string().min(2).max(50),
@@ -37,6 +38,9 @@ export function PbnstMngForm({ data }: { data: ruseFcltType[] }) {
const { fcltOperInfo } = pubMng;
const [ruseOperData, setRuseOperData] = useState<fcltOperInfoType[]>();
const [files, setFiles] = useState(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
@@ -61,10 +65,7 @@ export function PbnstMngForm({ data }: { data: ruseFcltType[] }) {
}
};
const newReuseFclt = () => {
form.reset();
setRuseOperData([{}] as fcltOperInfoType[]);
};
useEffect(() => {
if (isInit) {
@@ -169,11 +170,12 @@ export function PbnstMngForm({ data }: { data: ruseFcltType[] }) {
</div>
</div>
<div className="flex justify-between items-center mx-3 mb-3">
<div className="flex justify-between items-center mx-3 mb-3 ">
<h1 className="pl-3 text-xl">○ 재이용시설 운영정보</h1>
<Button type="button" className="rounded-lg" onClick={newReuseFclt}>추가등록</Button>
<Button type="button" className="rounded-lg" onClick={() => setIsModalOpen(true)}>추가등록</Button>
{/* <PbnstMngModal /> */}
</div>
<div>
<div className="h-[200px] overflow-y-auto">
<UiTable
tableData={ruseOperData?ruseOperData:[]}
headlist={pubMngUpHeadList}
@@ -0,0 +1,29 @@
import { Button, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@common/components";
export function PbnstMngModal(butNm:string,chldrn:React.ReactNode) {
return (
<>
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">{butNm}</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Share link</DialogTitle>
<DialogDescription>
Anyone who has this link will be able to view this.
</DialogDescription>
</DialogHeader>
{chldrn}
<DialogFooter className="sm:justify-start">
<DialogClose asChild>
<Button type="button" variant="secondary">
닫기
</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
</>
);
}