From d35ff514ef459123d06c20376d6804bd05152bb4 Mon Sep 17 00:00:00 2001 From: leedj312 Date: Thu, 24 Apr 2025 19:16:35 +0900 Subject: [PATCH 01/29] =?UTF-8?q?=ED=98=84=ED=99=A9=20=EC=84=9C=EC=B9=98?= =?UTF-8?q?=ED=8F=BC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruseFcltMng/fcltSttn/rainSttn/page.tsx | 181 ++++++------------ apps/wr/app/store/common/code/index.ts | 164 ++++++++-------- .../prfmncReg/chkgdnReg/rainChkgdn/index.tsx | 5 +- apps/wr/components/lib/func/commom.ts | 5 +- apps/wr/tailwind.config.ts | 2 +- 5 files changed, 153 insertions(+), 204 deletions(-) diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index a938eef88..e3ef44da0 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -2,6 +2,7 @@ import { useWrStore } from "@/app/store"; import { ContentsDiv, + SearchBaseForm, SearchDiv, SearchFormLeft, SearchFormRight, @@ -9,17 +10,16 @@ import { Title, UiModal, UiTable, + type ReturnType, } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button, TableHead, TableRow } from "@common/components/ui"; -import { useEffect, useState } from "react"; -import type { - TableTripleProps, -} from "@/app/store/ruseFcltMng/fcltReg/rainReg"; +import { useEffect, useRef, useState } from "react"; +import type { TableTripleProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; import { tableData } from "@/components/lib/func/commom"; import HeadChModal from "@/components/ui/modal/headChModal/headChModal"; - +import { btnClass } from "@/app/store/common/code"; export const headMakeTriple = ( upHeadList: TableTripleProps[], @@ -29,13 +29,8 @@ export const headMakeTriple = ( return ( <> {Array.from({ length: rowCount }).map((_, i) => ( - - - - - { - upHeadList + {upHeadList .filter((head: TableTripleProps) => head.visible == true) .map((head: TableTripleProps) => !head.upSequnce[i] ? ( @@ -63,28 +58,31 @@ export const headMakeTriple = ( ))} - {upHeadList - .map((head: TableTripleProps) => - makeHeadNm.find((ch) => ch.headNm === head?.upName[1] && head.visible ==true ) ? ( - - {head.title} - - ) : null - )} + {upHeadList.map((head: TableTripleProps) => + makeHeadNm.find( + (ch) => ch.headNm === head?.upName[1] && head.visible == true + ) ? ( + + {head.title} + + ) : null + )} ); }; export default function RainSttn() { - const { code, rain, init, sttnCommon } = useWrStore((state) => state); + const { code, rain, init, sttnCommon } = useWrStore((state) => state); const { rainRes } = rain; const [isChHead, setIsChHead] = useState(false); + + const ref = useRef({} as ReturnType ) ; const [bdstTable, setBdstTable] = useState(); const [tableHead, setTableHead] = useState([]); let nodeList = headMakeTriple( @@ -101,117 +99,64 @@ export default function RainSttn() { useEffect(() => { if (code.sggCd.length > 0) { const data = tableData(rainRes, { code }); - // data 는 위 JSON 객체라고 가정 + // data 는 위 JSON 객체라고 가정 - console.log("sttnCommon " , sttnCommon.rainSttHeadList) const unVisibleHead = sttnCommon.rainSttHeadList.filter( (item: TableTripleProps) => item.visible === false ); - console.log("unVisibleHead " , unVisibleHead) - const chData = data - .map((item:any) =>({ + const chData = data + .map((item: any) => ({ ...item, - ...item.reuseBuilding[0], - ...item.reuseBuilding[0].rainyObj - })).filter((item:any) => item.rainyObj !== undefined) + ...item.reuseBuilding[0], + ...item.reuseBuilding[0].rainyObj, + })) + .filter((item: any) => item.rainyObj !== undefined); - console.log("chData " , chData) + console.log("chData ", chData); + + setBdstTable(chData); + } + }, [code, rainRes, sttnCommon]); - setBdstTable( chData); - - - - } - - }, [code, rainRes,sttnCommon]); - return ( <>
- <SearchDiv> - <SearchFormLeft> - <SelectBox - className={"col-span-2 w-full h-full text-2xl"} - label={"권역"} - selectClass={""} - selectArray={code.yn} - onSelectValue={() => {}} - value={""} - /> - <SelectBox - className={"col-span-2 w-full h-full text-2xl"} - label={"단위유역"} - selectClass={""} - selectArray={code.yn} - onSelectValue={() => {}} - value={""} - /> - <SelectBox - className={"col-span-2 w-full h-full text-2xl"} - label={"중권역"} - selectClass={""} - selectArray={code.yn} - onSelectValue={() => {}} - value={""} - /> - <SelectBox - className={"col-span-2 w-full h-full text-2xl"} - label={"환경청"} - selectClass={""} - selectArray={code.yn} - onSelectValue={() => {}} - value={""} - /> - <SelectBox - className={"col-span-2 w-full h-full text-2xl"} - label={"시도"} - selectClass={""} - selectArray={code.yn} - onSelectValue={() => {}} - value={""} - /> - <SelectBox - className={"col-span-2 w-full h-full text-2xl"} - label={"시군구"} - selectClass={""} - selectArray={code.yn} - onSelectValue={() => {}} - value={""} - /> - </SearchFormLeft> - <SearchFormRight> - <div className="space-y"> - {/* 첫 줄: 버튼 3개 */} - <div className="flex flex-row space-x-2"> - <Button size={"sm"} onClick={(e) => {}}> - 조회 - </Button> - <Button size={"sm"} onClick={() => {}}> - 다운로드 - </Button> - </div> - <div className="flex flex-row space-x-2 pt-3"> - <Button - size={"sm"} - color="green" - onClick={() => { - setIsChHead(true); - }} - > - 조회항목설정 - </Button> - </div> - </div> - </SearchFormRight> - </SearchDiv> + <SearchBaseForm + selectSidoData={code.cityCd} + selectSigunData={code.sggCd} + selectRegionData={code.rvbsnCd} + selectUnitWaterShedData={code.lgbsnCd} + selectMiddleRegionData={code.mdmbsnCd} + selectEnvPartData={code.lclgvrnmntCd} + rightChildren={ + <Button + className={btnClass} + onClick={() => { + setIsChHead(true); + }} + > + 조회항목설정 + </Button>} + leftChildren={undefined} + + + queryClick={function (returnType: ReturnType): void { + throw new Error("Function not implemented."); + } } excelClick={function (returnType: ReturnType): void { + throw new Error("Function not implemented."); + } } initClick={function (): void { + throw new Error("Function not implemented."); + } } btnClass={btnClass } + ref={ref} /> + </div> </div> <div className="grid grid-cols-6 gap-4 "> @@ -233,13 +178,13 @@ export default function RainSttn() { </ListDiv> </div> </div> - <UiModal + <UiModal open={isChHead} onOpenChange={() => { setIsChHead(!isChHead); }} bodyClass={""} - body={<HeadChModal type={'rain'}/>} + body={<HeadChModal type={"rain"} />} /> </ContentsDiv> </> diff --git a/apps/wr/app/store/common/code/index.ts b/apps/wr/app/store/common/code/index.ts index 2a9e77d8e..21b2ea9a3 100644 --- a/apps/wr/app/store/common/code/index.ts +++ b/apps/wr/app/store/common/code/index.ts @@ -1,35 +1,33 @@ import { getFetch } from "@/components/lib/api"; +import type { EnvPartSelectDataType, SelectDataType } from "@common/business_components/ui"; -// Description: 공통코드 -export type selectArray = { - text: string; - val: string | number; - adstDliStrCd?: string -}; -export const yn :selectArray[]=[ + +export const btnClass= "p-4 m-2 text-white rounded-sm text-lg font-medium " + +export const yn :SelectDataType[]=[ {val:'Y', text:'Y'}, {val:'N', text:'N'}, ] //공통 건축물 용도 -export const bdstUsgCd: selectArray[] = [ - { val: 1, text: "운동장" }, - { val: 2, text: "체육관" }, - { val: 3, text: "공공업무시설" }, - { val: 4, text: "공공기관의청사" }, - { val: 5, text: "아파트" }, - { val: 6, text: "연립주택" }, - { val: 7, text: "다세대주택" }, - { val: 8, text: "기숙사" }, - { val: 9, text: "초등학교" }, - { val: 10, text: "중학교" }, - { val: 11, text: "고등학교" }, - { val: 12, text: "전문대학" }, - { val: 13, text: "대학및대학교" }, - { val: 14, text: "골프장" }, - { val: 15, text: "대규모점포" }, - { val: 16, text: "기타" }, +export const bdstUsgCd: SelectDataType[] = [ + { val: '1', text: "운동장" }, + { val: '2', text: "체육관" }, + { val: '3', text: "공공업무시설" }, + { val: '4', text: "공공기관의청사" }, + { val: '5', text: "아파트" }, + { val: '6', text: "연립주택" }, + { val: '7', text: "다세대주택" }, + { val: '8', text: "기숙사" }, + { val: '9', text: "초등학교" }, + { val: '10', text: "중학교" }, + { val: '11', text: "고등학교" }, + { val: '12', text: "전문대학" }, + { val: '13', text: "대학및대학교" }, + { val: '14', text: "골프장" }, + { val: '15', text: "대규모점포" }, + { val: '16', text: "기타" }, ]; //빗물 집수면 종류 용도 export const rainFcltCd = [ @@ -45,36 +43,36 @@ export const rainFcltCd = [ { val: "10", text: "확인불가" }, ]; // 중수도 필수 원수종류 -export const rswtBdstType: selectArray[] = [ - { text: "숙박업", val: 17 }, - { text: "목욕장업", val: 18 }, - { text: "공장", val: 19 }, - { text: "발전시설", val: 20 }, - { text: "관광단지개발사업", val: 21 }, - { text: "도시개발사업", val: 22 }, - { text: "산업단지개발사업", val: 23 }, - { text: "택지개발사업", val: 24 }, - { text: "대규모점포(대형마트)", val: 25 }, - { text: "대규모점포(전문점)", val: 26 }, - { text: "대규모점포(백화점)", val: 27 }, - { text: "대규모점포(쇼핑센터)", val: 28 }, - { text: "대규모점포(복합쇼핑몰)", val: 29 }, - { text: "물류시설", val: 30 }, - { text: "운수시설(여객자동차터미널)", val: 31 }, - { text: "운수시설(철도시설)", val: 32 }, - { text: "운수시설(공항시설)", val: 33 }, - { text: "운수시설(항만시설)", val: 34 }, - { text: "업무시설(공공업무시설)", val: 35 }, - { text: "업무시설(금융업소)", val: 36 }, - { text: "업무시설(사무소)", val: 37 }, - { text: "업무시설(결혼상담소 등 소개업소)", val: 38 }, - { text: "업무시설(출판사)", val: 39 }, - { text: "업무시설(신문사)", val: 40 }, - { text: "업무시설(오피스텔)", val: 41 }, - { text: "교정시설", val: 42 }, - { text: "방송국", val: 43 }, - { text: "전신전화국", val: 44 }, - { text: "기타", val: 45 }, +export const rswtBdstType: SelectDataType[] = [ + { text: "숙박업", val: "17" }, + { text: "목욕장업", val: "18" }, + { text: "공장", val: "19" }, + { text: "발전시설", val: "20" }, + { text: "관광단지개발사업", val: "21" }, + { text: "도시개발사업", val: "22" }, + { text: "산업단지개발사업", val: "23" }, + { text: "택지개발사업", val: "24" }, + { text: "대규모점포(대형마트)", val: "25" }, + { text: "대규모점포(전문점)", val: "26" }, + { text: "대규모점포(백화점)", val: "27" }, + { text: "대규모점포(쇼핑센터)", val: "28" }, + { text: "대규모점포(복합쇼핑몰)", val: "29" }, + { text: "물류시설", val: "30" }, + { text: "운수시설(여객자동차터미널)", val: "31" }, + { text: "운수시설(철도시설)", val: "32" }, + { text: "운수시설(공항시설)", val: "33" }, + { text: "운수시설(항만시설)", val: "34" }, + { text: "업무시설(공공업무시설)", val: "35" }, + { text: "업무시설(금융업소)", val: "36" }, + { text: "업무시설(사무소)", val: "37" }, + { text: "업무시설(결혼상담소 등 소개업소)", val: "38" }, + { text: "업무시설(출판사)", val: "39" }, + { text: "업무시설(신문사)", val: "40" }, + { text: "업무시설(오피스텔)", val: "41" }, + { text: "교정시설", val: "42" }, + { text: "방송국", val: "43" }, + { text: "전신전화국", val: "44" }, + { text: "기타", val: "45" } ]; const orgwtKndCd = [ @@ -96,23 +94,23 @@ export const chBuCd = [ export type comCodeState = { code: { isInit: boolean; - chBuCd:selectArray[] - rainFcltCd: selectArray[]; - bdstUsgCd: selectArray[]; - cityCd: selectArray[]; - sggCd: selectArray[]; + chBuCd:SelectDataType[] + rainFcltCd: SelectDataType[]; + bdstUsgCd: SelectDataType[]; + cityCd: SelectDataType[]; + sggCd: SelectDataType[]; - rvbsnCd:selectArray[]; - mdmbsnCd:selectArray[]; - lgbsnCd:selectArray[]; - lclgvrnmntCd:selectArray[]; + rvbsnCd:SelectDataType[]; + mdmbsnCd:SelectDataType[]; + lgbsnCd:SelectDataType[]; + lclgvrnmntCd:EnvPartSelectDataType[]; - orgwtKndCd:selectArray[]; - yn:selectArray[]; + orgwtKndCd:SelectDataType[]; + yn:SelectDataType[]; }; }; @@ -121,7 +119,7 @@ export type comCodeType = comCodeState & comCodeActions; export const getSggCd = async (set: any) => { const sgg = await getFetch("common", "/addr/sgg"); const sggCd = sgg.map((item: any) => ({ - val: Number(item.adstDstrCd), + val:item.adstDstrCd, text: item.gugun, })); set((state: comCodeState) => ({ @@ -134,10 +132,10 @@ export const getSggCd = async (set: any) => { export const getCityCd = async (set: any) => { const city = await getFetch("common", "/addr/city"); const cityCd = city.map((item: any) => ({ - val: Number(item.adstDstrCd), + val: item.adstDstrCd, text: item.sido, })); - cityCd.unshift({val:0,text:'전체'}) + cityCd.unshift({val:'0',text:'전체'}) set((state: comCodeState) => ({ code: { ...state.code, @@ -151,10 +149,10 @@ export const getRegionCd = async (set: any) => { try{ const rvbsn = await getFetch("common", "/addr/sarea"); const rvbsnCd = rvbsn.map((item: any) => ({ - val: Number(item.rvbsnCd), + val: item.rvbsnCd, text: item.rvbsn, })); - rvbsnCd.unshift({val:0,text:'전체'}) + rvbsnCd.unshift({val:'0',text:'전체'}) set((state: comCodeState) => ({ code: { ...state.code, @@ -171,10 +169,10 @@ export const getMiddleRegionCd = async (set: any) => { try{ const mdmbsn = await getFetch("common", "/addr/midArea"); const mdmbsnCd = mdmbsn.map((item: any) => ({ - val: Number(item.rvbsnCd), + val: item.rvbsnCd, text: item.mdmbsn, })); - mdmbsnCd.unshift({val:0,text:'전체'}) + mdmbsnCd.unshift({val:'0',text:'전체'}) set((state: comCodeState) => ({ code: { ...state.code, @@ -192,10 +190,10 @@ export const getUnitWaterShedCd =async (set: any) => { try{ const lgbsn = await getFetch("common", "/addr/largeArea"); const lgbsnCd = lgbsn.map((item: any) => ({ - val: Number(item.rvbsnCd), + val: item.rvbsnCd, text: item.lgbsn, })); - lgbsnCd.unshift({val:0,text:'전체'}) + lgbsnCd.unshift({val:'0',text:'전체'}) set((state: comCodeState) => ({ code: { ...state.code, @@ -214,11 +212,12 @@ export const getEnvPartCd =async (set: any) => { try{ const lclgvrnmnt = await getFetch('common', '/addr/govArea'); const lclgvrnmntCd = lclgvrnmnt.map((item: any) => ({ - val: Number(item.lclgvrnmntCd), + val: item.lclgvrnmntCd, text: item.lclgvrnmntNm, - adstDliStrCd:item.adstDliStrCd + adstDliStrCd: item.adstDliStrCd || '' + })); - lclgvrnmntCd.unshift({val:0,text:'전체' ,adstDliStrCd:''}) + lclgvrnmntCd.unshift({val:'0',text:'전체' ,adstDliStrCd: '' }) set((state: comCodeState) => ({ code: { ...state.code, @@ -245,7 +244,8 @@ export const comCodeStateExport: comCodeState = { mdmbsnCd:[], lgbsnCd:[], lclgvrnmntCd:[], - yn:yn + yn:yn, + }, }; @@ -262,13 +262,13 @@ export const codeActionExport: (set: any) => comCodeActions = (set: any) => { const sgg = await getFetch("common", "/addr/sgg"); const sggCd = sgg.map((item: any) => ({ - val: Number(item.adstDstrCd), + val: item.adstDstrCd, text: item.gugun, })); const city = await getFetch("common", "/addr/city"); const cityCd = city.map((item: any) => ({ - val: Number(item.adstDstrCd), + val: item.adstDstrCd, text: item.sido, })); @@ -281,11 +281,11 @@ export const codeActionExport: (set: any) => comCodeActions = (set: any) => { })); }, - divCityCd: async(cd: number) => { + divCityCd: async(cd: string) => { set((state: comCodeState) => ({ code: { ...state.code, - sggCd:state.code.sggCd.filter((item) => { return Number(item.val.toString().slice(0,2)) === cd }), + sggCd:state.code.sggCd.filter((item) => { return item.val.toString().slice(0,2) === cd }), }, })); }, diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx index 9b26b68f3..2eee0c93c 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx @@ -63,7 +63,10 @@ export type rainChkZodType = z.infer<typeof rainChkZod>; export const rainRegExcel = z.object({ bdstInfoPk: z.number().default(111111111), - chckYmd: z.date().default(new Date()), + chckYr: z .string().default("") + .refine((year) =>year.length ===0 || /^\d{4}$/.test(year),{ + message:'4자리 연도만 입력하세요' + }), file: z.instanceof(File).optional(), }); diff --git a/apps/wr/components/lib/func/commom.ts b/apps/wr/components/lib/func/commom.ts index 3e5be1593..5b75d8000 100644 --- a/apps/wr/components/lib/func/commom.ts +++ b/apps/wr/components/lib/func/commom.ts @@ -1,10 +1,11 @@ -import type { comCodeState, selectArray } from "@/app/store/common/code"; +import type { comCodeState, } from "@/app/store/common/code"; +import type { SelectDataType } from "@common/business_components/ui"; -export const getCity = (val: string, sggCd: selectArray[]) => { +export const getCity = (val: string, sggCd: SelectDataType[]) => { const data = sggCd .filter((item) => String(item.val).substring(0, 2) === val) .map((item) => ({ diff --git a/apps/wr/tailwind.config.ts b/apps/wr/tailwind.config.ts index dc688050e..00237ea18 100644 --- a/apps/wr/tailwind.config.ts +++ b/apps/wr/tailwind.config.ts @@ -5,7 +5,7 @@ import presetConfig from "../../tailwind.config.preset"; export default { presets: [presetConfig], content: [ - "./src/**/*.{js,ts,jsx,tsx,mdx}", + "./app/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}", "../../packages/common/components/src/ui/**/*.{js,ts,jsx,tsx,mdx}", "../../packages/common/business_components/src/ui/**/*.{js,ts,jsx,tsx,mdx}", From 0057d4b61ef0d6b59bee43e5a1cd6cc53656696c Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Thu, 24 Apr 2025 19:44:23 +0900 Subject: [PATCH 02/29] =?UTF-8?q?=EC=83=98=ED=94=8C=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=98=AC=EB=A0=A4=EC=84=9C=20=EB=B0=9B=EC=9D=80=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=B6=94=EA=B0=80.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruseFcltMng/fcltSttn/rainSttn/page.tsx | 63 ++++++++++-------- apps/wr/public/sample_rainy.xlsx | Bin 0 -> 15020 bytes 2 files changed, 34 insertions(+), 29 deletions(-) create mode 100644 apps/wr/public/sample_rainy.xlsx diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index e3ef44da0..9886950be 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -1,25 +1,22 @@ "use client"; import { useWrStore } from "@/app/store"; +import { btnClass } from "@/app/store/common/code"; +import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; +import type { TableTripleProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; +import { tableData } from "@/components/lib/func/commom"; +import HeadChModal from "@/components/ui/modal/headChModal/headChModal"; import { ContentsDiv, + filePickedPath, SearchBaseForm, - SearchDiv, - SearchFormLeft, - SearchFormRight, - SelectBox, Title, UiModal, UiTable, - type ReturnType, + type ReturnType } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button, TableHead, TableRow } from "@common/components/ui"; import { useEffect, useRef, useState } from "react"; -import type { TableTripleProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; -import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; -import { tableData } from "@/components/lib/func/commom"; -import HeadChModal from "@/components/ui/modal/headChModal/headChModal"; -import { btnClass } from "@/app/store/common/code"; export const headMakeTriple = ( upHeadList: TableTripleProps[], @@ -82,7 +79,7 @@ export default function RainSttn() { const [isChHead, setIsChHead] = useState(false); - const ref = useRef<ReturnType>({} as ReturnType ) ; + const ref = useRef<ReturnType>({} as ReturnType); const [bdstTable, setBdstTable] = useState<any[]>(); const [tableHead, setTableHead] = useState<any[]>([]); let nodeList = headMakeTriple( @@ -138,25 +135,33 @@ export default function RainSttn() { selectEnvPartData={code.lclgvrnmntCd} rightChildren={ <Button - className={btnClass} - onClick={() => { - setIsChHead(true); - }} - > - 조회항목설정 - </Button>} - leftChildren={undefined} + className={btnClass} + onClick={() => { + setIsChHead(true); + }} + > + 조회항목설정 + </Button>} + leftChildren={undefined} + queryClick={function (returnType: ReturnType): void { + + }} + excelClick={function (returnType: ReturnType): void { + fetch('/sample_rainy.xlsx', {}) + .then(async (response) => { + if (!response.ok) { + throw Error(response.statusText) + } + const ret =await filePickedPath(await (await response.blob()).arrayBuffer()) + console.log('ret', ret); + console.log(returnType); + }) + }} + initClick={function (): void { + }} + btnClass={btnClass} + ref={ref} /> - - queryClick={function (returnType: ReturnType): void { - throw new Error("Function not implemented."); - } } excelClick={function (returnType: ReturnType): void { - throw new Error("Function not implemented."); - } } initClick={function (): void { - throw new Error("Function not implemented."); - } } btnClass={btnClass } - ref={ref} /> - </div> </div> <div className="grid grid-cols-6 gap-4 "> diff --git a/apps/wr/public/sample_rainy.xlsx b/apps/wr/public/sample_rainy.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ee4b23edbed49636ca8244b1ba1ed4829b24699a GIT binary patch literal 15020 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 literal 0 HcmV?d00001 From 114b761d50a6fa4f65c1a660846bd9361fcdf812 Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Thu, 24 Apr 2025 19:44:57 +0900 Subject: [PATCH 03/29] =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=A7=81=EC=A0=91?= =?UTF-8?q?=20=EB=B0=9B=EC=95=84=EC=84=9C=20=EC=B2=98=EB=A6=AC=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/excel_download/index.tsx | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/common/business_components/src/ui/excel_download/index.tsx b/packages/common/business_components/src/ui/excel_download/index.tsx index 21d009dbc..f250b9969 100644 --- a/packages/common/business_components/src/ui/excel_download/index.tsx +++ b/packages/common/business_components/src/ui/excel_download/index.tsx @@ -49,4 +49,24 @@ export const filePicked=(oFile: File, headerNum:number=0):Promise<JSON | undefin // Tell JS To Start Reading The File.. You could delay this if desired reader.readAsBinaryString(oFile); }); +} +export const filePickedPath=(oFile: ArrayBuffer, headerNum:number=0):Promise<JSON | undefined> =>{ + // Create A File Reader HTML5 + return new Promise<JSON | undefined>((resolve) => { + // Ready The Event For When A File Gets Selected + const wb = XLSX.read(oFile, { type: 'binary' }); + let jsonXls: JSON | undefined; + // Loop Over Each Sheet + wb.SheetNames.forEach(function (sheetName) { + // Obtain The Current Row As CSV + const sheet = wb.Sheets[sheetName]; + if (sheet) { + jsonXls = XLSX.utils.sheet_to_json(sheet, { range: headerNum }) as unknown as JSON; + console.log("jsonXls", jsonXls); + } else { + console.error(`Sheet "${sheetName}" is undefined.`); + } + }); + resolve(jsonXls); + }); } \ No newline at end of file From a1818301c9e6e2427e90631850eb8c05baa8a03f Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Thu, 24 Apr 2025 19:56:21 +0900 Subject: [PATCH 04/29] =?UTF-8?q?=EB=8B=A4=EC=9A=B4=EB=B0=9B=EC=9D=80=20?= =?UTF-8?q?=EC=97=91=EC=85=80=20=ED=8C=8C=EC=9D=BC=20=EB=82=B4=EB=B6=80?= =?UTF-8?q?=EC=A0=81=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=B6=80=EB=B6=84=20=EC=99=84=EB=A3=8C.=20(?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=9A=A9=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=EB=A1=9C=20=EC=B2=98=EB=A6=AC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index 9886950be..bc2c2a0fa 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -7,7 +7,7 @@ import { tableData } from "@/components/lib/func/commom"; import HeadChModal from "@/components/ui/modal/headChModal/headChModal"; import { ContentsDiv, - filePickedPath, + filePickedBlob, SearchBaseForm, Title, UiModal, @@ -147,12 +147,18 @@ export default function RainSttn() { }} excelClick={function (returnType: ReturnType): void { + //내부적인 파일 샘플 받아서 처리하는 부분 추가. fetch('/sample_rainy.xlsx', {}) .then(async (response) => { if (!response.ok) { throw Error(response.statusText) } - const ret =await filePickedPath(await (await response.blob()).arrayBuffer()) + // 받은 파일 바인너리 처리 + const blobRet = await response.blob() + // 받은 파일을 버퍼에 넣는 작업 + const arrBuffer = await blobRet.arrayBuffer() + // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 + const ret =await filePickedBlob(arrBuffer) console.log('ret', ret); console.log(returnType); }) From d534bc4373cac422deec8713a43011caa8723c41 Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Thu, 24 Apr 2025 19:56:49 +0900 Subject: [PATCH 05/29] =?UTF-8?q?buffer=20=EB=B0=9B=EC=95=84=EC=84=9C=20?= =?UTF-8?q?=EC=9E=84=EC=8B=9C=EC=A0=81=EC=9C=BC=EB=A1=9C=20=EB=82=B4?= =?UTF-8?q?=EB=B6=80=20=EC=88=98=EC=A0=95=ED=95=98=EB=8A=94=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=A0=81=EC=9A=A9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/excel_download/index.tsx | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/common/business_components/src/ui/excel_download/index.tsx b/packages/common/business_components/src/ui/excel_download/index.tsx index f250b9969..3b0d7109c 100644 --- a/packages/common/business_components/src/ui/excel_download/index.tsx +++ b/packages/common/business_components/src/ui/excel_download/index.tsx @@ -50,22 +50,26 @@ export const filePicked=(oFile: File, headerNum:number=0):Promise<JSON | undefin reader.readAsBinaryString(oFile); }); } -export const filePickedPath=(oFile: ArrayBuffer, headerNum:number=0):Promise<JSON | undefined> =>{ +export const filePickedBlob=(oFile: ArrayBuffer, headerNum:number=0):Promise<JSON | undefined> =>{ // Create A File Reader HTML5 return new Promise<JSON | undefined>((resolve) => { // Ready The Event For When A File Gets Selected const wb = XLSX.read(oFile, { type: 'binary' }); let jsonXls: JSON | undefined; // Loop Over Each Sheet - wb.SheetNames.forEach(function (sheetName) { + wb.SheetNames.forEach(function (sheetName, index) { // Obtain The Current Row As CSV - const sheet = wb.Sheets[sheetName]; - if (sheet) { - jsonXls = XLSX.utils.sheet_to_json(sheet, { range: headerNum }) as unknown as JSON; - console.log("jsonXls", jsonXls); - } else { - console.error(`Sheet "${sheetName}" is undefined.`); - } + if(index==0){ + const sheet = wb.Sheets[sheetName]; + if (sheet) { + XLSX.utils.sheet_add_json(sheet, [["시작"]], { origin: "A20" }); + jsonXls = XLSX.utils.sheet_to_json(sheet, { range: headerNum }) as unknown as JSON; + XLSX.writeFile(wb, "test.xlsx"); + console.log("jsonXls", jsonXls); + } else { + console.error(`Sheet "${sheetName}" is undefined.`); + } + } }); resolve(jsonXls); }); From be72b89edd7d685f528bfb8e1976dae145f5420d Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Fri, 25 Apr 2025 13:35:43 +0900 Subject: [PATCH 06/29] =?UTF-8?q?=EC=97=91=EC=85=80=20=EC=96=91=EC=8B=9D?= =?UTF-8?q?=20=EB=8B=A4=EC=9A=B4=EB=A1=9C=EB=93=9C=20=EB=B0=9B=EB=8A=94=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=99=84=EB=A3=8C.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fcltSttn/rainSttn/TableHead.tsx | 57 +++++++++ .../ruseFcltMng/fcltSttn/rainSttn/page.tsx | 101 ++------------- .../ruseFcltMng/prfmncReg/chkgdnReg/page.tsx | 28 ++++- apps/wr/app/store/common/code/index.ts | 6 - .../prfmncReg/chkgdnReg/rainChkgdn/excel.tsx | 115 ++++++++++++++++++ .../prfmncReg/chkgdnReg/rainChkgdn/index.tsx | 17 ++- .../store/ruseFcltMng/fcltSttn/sttn/index.tsx | 16 +-- apps/wr/app/store/store.tsx | 52 ++++---- apps/wr/components/lib/api/index.ts | 6 +- 9 files changed, 260 insertions(+), 138 deletions(-) create mode 100644 apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/TableHead.tsx create mode 100644 apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/TableHead.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/TableHead.tsx new file mode 100644 index 000000000..7b7065ffa --- /dev/null +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/TableHead.tsx @@ -0,0 +1,57 @@ +import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; +import type { TableTripleProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; +import { TableHead, TableRow } from "@common/components/ui"; + +export const headMakeTriple = ( + upHeadList: TableTripleProps[], + makeHeadNm: chHeadType[], + rowCount: number = 2 +) => { + return ( + <> + {Array.from({ length: rowCount }).map((_, i) => ( + <TableRow key={i}> + {upHeadList + .filter((head: TableTripleProps) => head.visible == true) + .map((head: TableTripleProps) => + !head.upSequnce[i] ? ( + <TableHead + className={`border border-gray-600 px-2 py-1 `} + rowSpan={2} + key={head.id} + > + {head.title} + </TableHead> + ) : head.upSequnce[i] === 1 ? ( + <TableHead + className={`border border-gray-600 px-2 py-1 `} + key={head.id} + rowSpan={1} + colSpan={ + makeHeadNm.find((ch) => ch.headNm === head.upName[i]) + ?.length + } + > + {makeHeadNm.find((ch) => ch.headNm === head.upName[i])?.text} + </TableHead> + ) : null + )} + </TableRow> + ))} + <TableRow> + {upHeadList.map((head: TableTripleProps) => + makeHeadNm.find( + (ch) => ch.headNm === head?.upName[1] && head.visible == true + ) ? ( + <TableHead + className={`border border-gray-600 px-2 py-1 `} + key={head.id} + > + {head.title} + </TableHead> + ) : null + )} + </TableRow> + </> + ); +}; \ No newline at end of file diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index bc2c2a0fa..77bce97e8 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -1,13 +1,12 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ "use client"; import { useWrStore } from "@/app/store"; import { btnClass } from "@/app/store/common/code"; -import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; import type { TableTripleProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import { tableData } from "@/components/lib/func/commom"; import HeadChModal from "@/components/ui/modal/headChModal/headChModal"; import { ContentsDiv, - filePickedBlob, SearchBaseForm, Title, UiModal, @@ -15,94 +14,36 @@ import { type ReturnType } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; -import { Button, TableHead, TableRow } from "@common/components/ui"; -import { useEffect, useRef, useState } from "react"; - -export const headMakeTriple = ( - upHeadList: TableTripleProps[], - makeHeadNm: chHeadType[], - rowCount: number = 2 -) => { - return ( - <> - {Array.from({ length: rowCount }).map((_, i) => ( - <TableRow key={i}> - {upHeadList - .filter((head: TableTripleProps) => head.visible == true) - .map((head: TableTripleProps) => - !head.upSequnce[i] ? ( - <TableHead - className={`border border-gray-600 px-2 py-1 `} - rowSpan={2} - key={head.id} - > - {head.title} - </TableHead> - ) : head.upSequnce[i] === 1 ? ( - <TableHead - className={`border border-gray-600 px-2 py-1 `} - key={head.id} - rowSpan={1} - colSpan={ - makeHeadNm.find((ch) => ch.headNm === head.upName[i]) - ?.length - } - > - {makeHeadNm.find((ch) => ch.headNm === head.upName[i])?.text} - </TableHead> - ) : null - )} - </TableRow> - ))} - <TableRow> - {upHeadList.map((head: TableTripleProps) => - makeHeadNm.find( - (ch) => ch.headNm === head?.upName[1] && head.visible == true - ) ? ( - <TableHead - className={`border border-gray-600 px-2 py-1 `} - key={head.id} - > - {head.title} - </TableHead> - ) : null - )} - </TableRow> - </> - ); -}; +import { Button } from "@common/components/ui"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { headMakeTriple } from "./TableHead"; export default function RainSttn() { - const { code, rain, init, sttnCommon } = useWrStore((state) => state); + const { code, rain, init, sttnCommon, excelExportAction } = useWrStore((state) => state); const { rainRes } = rain; const [isChHead, setIsChHead] = useState(false); - const ref = useRef<ReturnType>({} as ReturnType); const [bdstTable, setBdstTable] = useState<any[]>(); - const [tableHead, setTableHead] = useState<any[]>([]); - let nodeList = headMakeTriple( + const nodeList = headMakeTriple( sttnCommon.rainSttHeadList, sttnCommon.rainSttHeadNm ); - + useEffect(() => { if (!rain.isInit) { init(undefined); } }, [rain.isInit, init]); - useEffect(() => { if (code.sggCd.length > 0) { const data = tableData(rainRes, { code }); // data 는 위 JSON 객체라고 가정 - - + // TODO: 이게 뭐하는 작업이지? const unVisibleHead = sttnCommon.rainSttHeadList.filter( (item: TableTripleProps) => item.visible === false ); - const chData = data .map((item: any) => ({ ...item, @@ -115,11 +56,11 @@ export default function RainSttn() { setBdstTable(chData); } - }, [code, rainRes, sttnCommon]); - - - + }, [code, rainRes, sttnCommon.rainSttHeadList]); + const excelClick = useCallback(() => { + excelExportAction(code.cityCd, code.sggCd); + },[code.cityCd, code.sggCd, excelExportAction]); return ( <> <ContentsDiv> @@ -146,23 +87,7 @@ export default function RainSttn() { queryClick={function (returnType: ReturnType): void { }} - excelClick={function (returnType: ReturnType): void { - //내부적인 파일 샘플 받아서 처리하는 부분 추가. - fetch('/sample_rainy.xlsx', {}) - .then(async (response) => { - if (!response.ok) { - throw Error(response.statusText) - } - // 받은 파일 바인너리 처리 - const blobRet = await response.blob() - // 받은 파일을 버퍼에 넣는 작업 - const arrBuffer = await blobRet.arrayBuffer() - // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 - const ret =await filePickedBlob(arrBuffer) - console.log('ret', ret); - console.log(returnType); - }) - }} + excelClick={excelClick} initClick={function (): void { }} btnClass={btnClass} diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx index 7aef0b4e8..3150a1c44 100644 --- a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx @@ -13,6 +13,7 @@ import RainChkgdTable from "@/components/ui/table/chkgdTable/rainChkgd/rainChkgd import RswtChkgdTable from "@/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable"; import { ContentsDiv, + filePickedBlob, SearchDiv, SearchFormLeft, SearchFormRight, @@ -24,7 +25,7 @@ import { import ListDiv from "@common/business_components/ui/list_div"; import { TableHead, TableRow } from "@common/components"; import { Button } from "@common/components/ui"; -import { useEffect, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; export const headMakeprfmnc = ( upHeadList: TableUpperProps[], @@ -78,7 +79,7 @@ export const headMakeprfmnc = ( //----------------------- export default function Page() { - const { rainChkgdn, rainChkInit,rainChkDetilUpdate } = useWrStore((state) => { + const { code, rainChkgdn, rainChkInit,rainChkDetilUpdate, excelExportAction } = useWrStore((state) => { return state; }); @@ -100,7 +101,24 @@ export default function Page() { rainChkInit('2024','0'); } }, [rainChkgdn.isInit, rainChkInit]); - + useEffect(() => { + console.log("rainChkgdn.excelList", rainChkgdn.excelList); + if (rainChkgdn.excelList.length === 0) return; + fetch('/sample_rainy.xlsx', {}) + .then(async (response) => { + if (!response.ok) { + throw Error(response.statusText) + } + // 받은 파일 바인너리 처리 + const blobRet = await response.arrayBuffer() + // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 + const ret =await filePickedBlob(blobRet, rainChkgdn.excelList) + console.log('ret', ret); + }) + }, [rainChkgdn.excelList]); + const excelClick= useCallback(()=>{ + excelExportAction(code.cityCd, code.sggCd); + }, [excelExportAction, code.cityCd, code.sggCd]); return ( <ContentsDiv> <div className="grid grid-cols-4 gap-4 "> @@ -148,9 +166,7 @@ export default function Page() { <Button color="green" size={"sm"} - onClick={() => { - setIsExcel(!isDetail); - }} + onClick={excelClick} > 양식받기 </Button> diff --git a/apps/wr/app/store/common/code/index.ts b/apps/wr/app/store/common/code/index.ts index 21b2ea9a3..5d93811cc 100644 --- a/apps/wr/app/store/common/code/index.ts +++ b/apps/wr/app/store/common/code/index.ts @@ -99,16 +99,10 @@ export type comCodeState = { bdstUsgCd: SelectDataType[]; cityCd: SelectDataType[]; sggCd: SelectDataType[]; - rvbsnCd:SelectDataType[]; mdmbsnCd:SelectDataType[]; lgbsnCd:SelectDataType[]; lclgvrnmntCd:EnvPartSelectDataType[]; - - - - - orgwtKndCd:SelectDataType[]; yn:SelectDataType[]; }; diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx new file mode 100644 index 000000000..26f9a7e42 --- /dev/null +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx @@ -0,0 +1,115 @@ +import type { SelectDataType } from "@common/business_components" +const useTypes = [ + "조경용수", + "청소화장실용수", + "세척살수용수", + "농업용수", + "공업용수", + "친수용수", + "기타" +] +export type ExcelExportType = { + "NO": string, + "시도": string, + "시군구": string, + "상세주소": string, + "시설명": string, + "운영관리형태": string, + "유량측정방법": string, + "연간운영비(원/년)": string, + "점검일": string, + "이용용도": string, + "보급_1월": string, + "보급_2월": string, + "보급_3월": string, + "보급_4월": string, + "보급_5월": string, + "보급_6월": string, + "보급_7월": string, + "보급_8월": string, + "보급_9월": string, + "보급_10월": string, + "보급_11월": string, + "보급_12월": string, + "빗물_1월": string, + "빗물_2월": string, + "빗물_3월": string, + "빗물_4월": string, + "빗물_5월": string, + "빗물_6월": string, + "빗물_7월": string, + "빗물_8월": string, + "빗물_9월": string, + "빗물_10월": string, + "빗물_11월": string, + "빗물_12월": string, + "PH": string, + "탁도": string, + "총대장균군수": string, + "과태료 부과일(위반일)": string, + "위반사항": string, + "과태료부과금액(천원)": string +} +export type Buildingtype = { + bdstInfoPk: number, + ctpvCd: 1, + sggCd: 1001, + daddr: "string3", + bdstNm: "string", + frstArchPrmsnDt: "2025-03-25", + archArea: 0, + regDt: "2025-04-16", + rgtr: null, + mdfcnDt: "2025-04-16", + mdfr: null +} +export const buildingToExcelType = (buildings: Buildingtype[], sidoCode: SelectDataType[], sggCdoe: SelectDataType[]) => { + const excelData: ExcelExportType[] = []; + buildings.forEach((building) => { + useTypes.forEach((useType) => { + excelData.push({ + NO: building.bdstInfoPk.toString(), + 시도: sidoCode.find((sido) => sido.val === building.ctpvCd.toString())?.text || "", + 시군구: sggCdoe.find((sido) => sido.val === building.sggCd.toString())?.text || "", + 상세주소: building.daddr, + 시설명: building.bdstNm, + 운영관리형태: "", + 유량측정방법: "", + '연간운영비(원/년)': "", + 점검일: "", + 이용용도: useType, + 보급_1월: "", + 보급_2월: "", + 보급_3월: "", + 보급_4월: "", + 보급_5월: "", + 보급_6월: "", + 보급_7월: "", + 보급_8월: "", + 보급_9월: "", + 보급_10월: "", + 보급_11월: "", + 보급_12월: "", + 빗물_1월: "", + 빗물_2월: "", + 빗물_3월: "", + 빗물_4월: "", + 빗물_5월: "", + 빗물_6월: "", + 빗물_7월: "", + 빗물_8월: "", + 빗물_9월: "", + 빗물_10월: "", + 빗물_11월: "", + 빗물_12월: "", + PH: "", + 탁도: "", + 총대장균군수: "", + "과태료 부과일(위반일)": "", + 위반사항: "", + "과태료부과금액(천원)": "" + }) + }) + }) + return excelData; +} \ No newline at end of file diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx index 2eee0c93c..3734563a5 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx @@ -2,8 +2,10 @@ import { TEST_UUID, type TableUpperProps, } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; -import { getFetch, postFectch, putFectch } from "@/components/lib/api"; +import { fetchType, getFetch, postFectch, putFectch } from "@/components/lib/api"; +import type { SelectDataType } from "@common/business_components/ui"; import { z } from "zod"; +import { buildingToExcelType, type ExcelExportType } from "./excel"; export const rainChkZod = z.object({ chkgdnPk: z.number(), @@ -286,6 +288,7 @@ export type rainChkgdnState = { splHeadList: TableUpperProps[]; rswtDetailHeadList: TableUpperProps[]; isInit: boolean; + excelList:ExcelExportType[] }; }; @@ -293,6 +296,7 @@ type rainChkgdnActions = { rainChkInit: (sggCd: string, searchTxt: string) => void; rainChkDetilUpdate(rainChk: rainChkZodType[]): Promise<void>; rainChkGuidUpdate(rainChk: rainChkZodType): Promise<void>; + excelExportAction(sidoCode: SelectDataType[],sggCode: SelectDataType[]): Promise<void> }; export type rainChkgdnType = rainChkgdnState & rainChkgdnActions; @@ -306,6 +310,7 @@ export const rainChkgdnStateExport: rainChkgdnState = { ruseHeadList: ruseHeadList, rswtDetailHeadList: rswtDetailHeadList, isInit: false, + excelList:[] }, }; @@ -343,6 +348,16 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( set: any ) => { return { + excelExportAction:async(sidoCode:SelectDataType[], sggCode:SelectDataType[])=>{ + const data = await getFetch(fetchType.WR, "/reuseFc/building/RNB/0") + const excelList = buildingToExcelType(data, sidoCode, sggCode); + set((state: rainChkgdnState) => ({ + rainChkgdn: { + ...state.rainChkgdn, + excelList:excelList + }, + })); + }, rainChkInit: async (searchTxt: string, sggCd: string) => { try { const rainChkRes = await initFetch(searchTxt, sggCd); diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx index 727d8df1b..2df547da9 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx @@ -1,11 +1,11 @@ import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; +import { type ExcelExportType } from "../../../prfmncReg/chkgdnReg/rainChkgdn/excel"; import { - upHeadList, type TableTripleProps, - type TableUpperProps, + type TableUpperProps } from "../../fcltReg/rainReg"; -export const pbnSttHeadNm: chHeadType[] = [ +const pbnSttHeadNm: chHeadType[] = [ { headNm: "catchment", text: "유역", length: 3 }, { headNm: "adminDiv", text: "행정구역", length: 2 }, { headNm: "rusSup", text: "재이용수공급가능량", length: 3 }, @@ -14,7 +14,7 @@ export const pbnSttHeadNm: chHeadType[] = [ ]; // id는 다확인해야함 -export const pbnSttHeadList: TableUpperProps[] = [ +const pbnSttHeadList: TableUpperProps[] = [ { id: "a", title: "권역", upName: "catchment", upSequnce: 1, visible: true }, { id: "aaa", @@ -125,7 +125,7 @@ export const pbnSttHeadList: TableUpperProps[] = [ visible: true, }, ]; -export const rainSttHeadNm: chHeadType[] = [ +const rainSttHeadNm: chHeadType[] = [ { headNm: "bdnstInfo", text: "1.건축물정보", length: 9 }, { headNm: "rainFcltInfo", text: "2.빗물이용시설정보", length: 7 }, { headNm: "fcltMngInfo", text: "3.시설운영및 이용정보", length: 2 }, @@ -141,7 +141,7 @@ export const rainSttHeadNm: chHeadType[] = [ ]; // id는 다확인해야함 -export const rainSttHeadList: TableTripleProps[] = [ +const rainSttHeadList: TableTripleProps[] = [ { id: "ctpvCd", title: "시도", @@ -342,12 +342,12 @@ export type sttnState = { pbnSttHeadNm: chHeadType[]; rainSttHeadList: TableTripleProps[]; rainSttHeadNm: chHeadType[]; + excelList:ExcelExportType[] }; }; type sttnActions = { chSttnHead: (checkList: string[], type: string) => void; pbnSttnInit: (sggCd: string, searchTxt: string, flg: string) => void; - }; export type sttnType = sttnState & sttnActions; @@ -358,13 +358,13 @@ export const sttnStateExport: sttnState = { pbnSttHeadNm: pbnSttHeadNm, rainSttHeadList: rainSttHeadList, rainSttHeadNm: rainSttHeadNm, + excelList: [], }, }; export const sttnActionsExport: (set: any) => sttnActions = (set: any) => { return { pbnSttnInit: async (sggCd: string, searchTxt: string, flg: string) => {}, - chSttnHead: async (checkList: string[], type: string) => { const headList = type === "pbn" diff --git a/apps/wr/app/store/store.tsx b/apps/wr/app/store/store.tsx index f3e720add..f826689de 100644 --- a/apps/wr/app/store/store.tsx +++ b/apps/wr/app/store/store.tsx @@ -1,4 +1,20 @@ import { createStore } from "zustand/vanilla"; +import { codeActionExport, comCodeStateExport, getCityCd, getEnvPartCd, getMiddleRegionCd, getRegionCd, getSggCd, getUnitWaterShedCd, type comCodeState, type comCodeType } from "./common/code"; +import { + matDmdActionsExport, + matDmdStateExport, + type matDmdState, + type matDmdType, +} from "./matDmd"; +import { rainChkgdnActionsExport, rainChkgdnStateExport, type rainChkgdnState, type rainChkgdnType } from "./prfmncReg/chkgdnReg/rainChkgdn"; +import { rswtChkgdnActionsExport, rswtChkgdnStateExport, type rswtChkgdnState, type rswtChkgdnType } from "./prfmncReg/chkgdnReg/rswrtChkgdn"; +import { bdstActionsExport, bdstStateExport, type bdstFulType, type bdstState } from "./ruseFcltMng/fcltReg/bdstReg"; +import { + htdflFacActionsExport, + htdflFacStateExport, + type htdflFacState, + type htdflFacType, +} from "./ruseFcltMng/fcltReg/htdflReg"; import { pubFacActionsExport, pubFacStateExport, @@ -17,22 +33,6 @@ import { type rswtFacState, type rswtFacType, } from "./ruseFcltMng/fcltReg/rswtReg"; -import { - matDmdActionsExport, - matDmdStateExport, - type matDmdState, - type matDmdType, -} from "./matDmd"; -import { - htdflFacActionsExport, - htdflFacStateExport, - type htdflFacState, - type htdflFacType, -} from "./ruseFcltMng/fcltReg/htdflReg"; -import { codeActionExport, comCodeStateExport, getCityCd, getEnvPartCd, getMiddleRegionCd, getRegionCd, getSggCd, getUnitWaterShedCd, type comCodeState, type comCodeType } from "./common/code"; -import { bdstActionsExport, bdstStateExport, type bdstFulType, type bdstState } from "./ruseFcltMng/fcltReg/bdstReg"; -import { rainChkgdnActionsExport, rainChkgdnStateExport, type rainChkgdnState, type rainChkgdnType } from "./prfmncReg/chkgdnReg/rainChkgdn"; -import { rswtChkgdnActionsExport, rswtChkgdnStateExport, type rswtChkgdnState, type rswtChkgdnType } from "./prfmncReg/chkgdnReg/rswrtChkgdn"; import { sttnActionsExport, sttnStateExport, type sttnState, type sttnType } from "./ruseFcltMng/fcltSttn/sttn"; export type WrStore = comCodeType& @@ -72,11 +72,11 @@ export const StoreZus = ( } ) => { return createStore<WrStore>()((set) => { - getSggCd(set), - getCityCd(set), - getRegionCd(set), - getMiddleRegionCd(set), - getUnitWaterShedCd(set), + getSggCd(set); + getCityCd(set); + getRegionCd(set); + getMiddleRegionCd(set); + getUnitWaterShedCd(set) getEnvPartCd(set) return { ...initState, @@ -85,11 +85,11 @@ export const StoreZus = ( ...rswtFacActionsExport(set), ...matDmdActionsExport(set), ...htdflFacActionsExport(set), - ...codeActionExport(set), - ...bdstActionsExport(set), - ...rainChkgdnActionsExport(set), - ...rswtChkgdnActionsExport(set), - ...sttnActionsExport(set) + ...codeActionExport(set), + ...bdstActionsExport(set), + ...rainChkgdnActionsExport(set), + ...rswtChkgdnActionsExport(set), + ...sttnActionsExport(set) }; }); }; diff --git a/apps/wr/components/lib/api/index.ts b/apps/wr/components/lib/api/index.ts index 15b6d9aff..0ffa0d53c 100644 --- a/apps/wr/components/lib/api/index.ts +++ b/apps/wr/components/lib/api/index.ts @@ -1,11 +1,11 @@ //8880 -import { DEV_URL_FO, DEV_URL_WR } from "../config/"; - +import { DEV_URL_FO, DEV_URL_WR } from "../config/"; +export const fetchType={COMMON: "common", WR: "wr"} export const getFetch = async( type:string , url: string) => { - const div = type === 'common' ? DEV_URL_FO : DEV_URL_WR + const div = type === fetchType.COMMON ? DEV_URL_FO : DEV_URL_WR const response = await fetch( div+url , { method: "GET", headers: { From 0ba499edc27d6f79a40eb325d9dd3bb8bd66b924 Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Fri, 25 Apr 2025 13:36:17 +0900 Subject: [PATCH 07/29] =?UTF-8?q?json=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EB=B0=9B=EC=95=84=EC=84=9C=20excel=EC=97=90=20=EB=84=A3?= =?UTF-8?q?=EB=8A=94=20=EC=9E=91=EC=97=85=EA=B9=8C=EC=A7=80=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business_components/src/ui/excel_download/index.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/common/business_components/src/ui/excel_download/index.tsx b/packages/common/business_components/src/ui/excel_download/index.tsx index 3b0d7109c..7ebc53e2d 100644 --- a/packages/common/business_components/src/ui/excel_download/index.tsx +++ b/packages/common/business_components/src/ui/excel_download/index.tsx @@ -50,7 +50,7 @@ export const filePicked=(oFile: File, headerNum:number=0):Promise<JSON | undefin reader.readAsBinaryString(oFile); }); } -export const filePickedBlob=(oFile: ArrayBuffer, headerNum:number=0):Promise<JSON | undefined> =>{ +export const filePickedBlob=(oFile: ArrayBuffer, data:JSON[], headerNum:number=0):Promise<JSON | undefined> =>{ // Create A File Reader HTML5 return new Promise<JSON | undefined>((resolve) => { // Ready The Event For When A File Gets Selected @@ -62,10 +62,9 @@ export const filePickedBlob=(oFile: ArrayBuffer, headerNum:number=0):Promise<JSO if(index==0){ const sheet = wb.Sheets[sheetName]; if (sheet) { - XLSX.utils.sheet_add_json(sheet, [["시작"]], { origin: "A20" }); + XLSX.utils.sheet_add_json(sheet,data); jsonXls = XLSX.utils.sheet_to_json(sheet, { range: headerNum }) as unknown as JSON; XLSX.writeFile(wb, "test.xlsx"); - console.log("jsonXls", jsonXls); } else { console.error(`Sheet "${sheetName}" is undefined.`); } From 5cc97dbb49fcf52b1af4551fba7b4d2363d06aee Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Fri, 25 Apr 2025 13:44:39 +0900 Subject: [PATCH 08/29] =?UTF-8?q?=EC=8B=9C=EB=8F=84,=20=EC=8B=9C=EA=B5=B0?= =?UTF-8?q?=EA=B5=AC=20=EC=BD=94=EB=93=9C=20=EB=AA=85=20=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wr/components/lib/func/commom.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/wr/components/lib/func/commom.ts b/apps/wr/components/lib/func/commom.ts index 5b75d8000..ecae649dd 100644 --- a/apps/wr/components/lib/func/commom.ts +++ b/apps/wr/components/lib/func/commom.ts @@ -24,10 +24,10 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => { return data?.map((item: { sggCd: string; ctpvCd: string; reuseBuilding: { lawTrgtYn: any , bdstUsgCd:any}[]; }) => { let returnData = {}; const sggText = chCode.sggCd.find( - (cd) => cd.val === item.sggCd + (cd) => cd.val === String(item.sggCd) )?.text; const cityText = chCode.cityCd.find( - (cd) => cd.val === item.ctpvCd + (cd) => cd.val === String(item.ctpvCd) )?.text; if (item?.reuseBuilding?.length >0) { From a8ca2b4da6c63e85bd7f23adb236a69d567ba1a9 Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Fri, 25 Apr 2025 13:52:54 +0900 Subject: [PATCH 09/29] =?UTF-8?q?=EB=B9=97=EB=AC=BC=20=EC=8B=9C=EC=84=A4?= =?UTF-8?q?=ED=98=84=ED=99=A9=20=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=ED=97=A4?= =?UTF-8?q?=EB=8D=94=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/ruseFcltMng/fcltSttn/sttn/index.tsx | 53 +++---------------- 1 file changed, 8 insertions(+), 45 deletions(-) diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx index 2df547da9..21ef1831e 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx @@ -128,29 +128,27 @@ const pbnSttHeadList: TableUpperProps[] = [ const rainSttHeadNm: chHeadType[] = [ { headNm: "bdnstInfo", text: "1.건축물정보", length: 9 }, { headNm: "rainFcltInfo", text: "2.빗물이용시설정보", length: 7 }, - { headNm: "fcltMngInfo", text: "3.시설운영및 이용정보", length: 2 }, - { headNm: "insenInfo", text: "4.인센티브 정보", length: 9 }, + { headNm: "insenInfo", text: "3.인센티브 정보", length: 9 }, { headNm: "adminDiv", text: "행정구역", length: 2 }, { headNm: "pntfCol", text: "집수면", length: 2 }, { headNm: "filtrTrtmfct", text: "여과등 처리시설", length: 3 }, { headNm: "instlCstSprt", text: "설치비지원", length: 2 }, - { headNm: "crgRdct", text: "요금감면", length: 3 }, { headNm: "grntchBdstCert", text: "녹색건축물인증여부", length: 4 }, ]; // id는 다확인해야함 const rainSttHeadList: TableTripleProps[] = [ { - id: "ctpvCd", + id: "cityText", title: "시도", visible: true, upName: ["bdnstInfo", "adminDiv"], upSequnce: [1, 1], }, { - id: "sggCd", + id: "sggText", title: "시군구", visible: true, upName: ["bdnstInfo", "adminDiv"], @@ -256,21 +254,6 @@ const rainSttHeadList: TableTripleProps[] = [ upSequnce: [7], }, - { - id: "operMngCd", - title: "운영관리코드", - visible: true, - upName: ["fcltMngInfo"], - upSequnce: [1], - }, - { - id: "annRnwtQty", - title: "연간빗물운영량", - visible: true, - upName: ["fcltMngInfo"], - upSequnce: [2], - }, - { id: "instlCstSprtYn", title: "설치지원비용여부", @@ -285,54 +268,34 @@ const rainSttHeadList: TableTripleProps[] = [ upName: ["insenInfo", "instlCstSprt"], upSequnce: [2, 2], }, - { - id: "crgRdctYn", - title: "감면여부", - visible: true, - upName: ["insenInfo", "crgRdct"], - upSequnce: [3, 1], - }, // 확인필요 - { - id: "crgRdctBss", - title: "감면근거", - visible: true, - upName: ["insenInfo", "crgRdct"], - upSequnce: [4, 2], - }, // 확인필요 - { - id: "crgRdctAmt", - title: "감면금액", - visible: true, - upName: ["insenInfo", "crgRdct"], - upSequnce: [5, 3], - }, // 확인필요 + { id: "grntchBdstCertYn", title: "녹색건축물인증여부", visible: true, upName: ["insenInfo", "grntchBdstCert"], - upSequnce: [6, 1], + upSequnce: [3, 1], }, { id: "grntchBdstCertYr", title: "녹색건축물인증년도", visible: true, upName: ["insenInfo", "grntchBdstCert"], - upSequnce: [7, 2], + upSequnce: [4, 2], }, { id: "grntchBdstCertNo", title: "녹색건축물인증번호", visible: true, upName: ["insenInfo", "grntchBdstCert"], - upSequnce: [8, 3], + upSequnce: [5, 3], }, { id: "grntchBdstCertGrd", title: "녹색건축물인증등급", visible: true, upName: ["insenInfo", "grntchBdstCert"], - upSequnce: [9, 4], + upSequnce: [6, 4], }, ]; From e15b922b2e1147750cb562da47ea9ae0169b8716 Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Fri, 25 Apr 2025 14:43:42 +0900 Subject: [PATCH 10/29] =?UTF-8?q?=EC=97=91=EC=85=80=20=EB=B3=80=ED=99=98?= =?UTF-8?q?=20TODO=20=EC=9E=91=EC=84=B1=20=EC=99=84=EB=A3=8C.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruseFcltMng/fcltSttn/rainSttn/page.tsx | 14 ++++-- .../store/ruseFcltMng/fcltSttn/sttn/excel.tsx | 46 +++++++++++++++++++ .../store/ruseFcltMng/fcltSttn/sttn/index.tsx | 11 +++-- 3 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index 77bce97e8..6d4563efd 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -19,7 +19,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { headMakeTriple } from "./TableHead"; export default function RainSttn() { - const { code, rain, init, sttnCommon, excelExportAction } = useWrStore((state) => state); + const { code, rain, init, sttnCommon, excelRainSttn } = useWrStore((state) => state); const { rainRes } = rain; const [isChHead, setIsChHead] = useState(false); @@ -40,7 +40,6 @@ export default function RainSttn() { if (code.sggCd.length > 0) { const data = tableData(rainRes, { code }); // data 는 위 JSON 객체라고 가정 - // TODO: 이게 뭐하는 작업이지? const unVisibleHead = sttnCommon.rainSttHeadList.filter( (item: TableTripleProps) => item.visible === false ); @@ -57,10 +56,15 @@ export default function RainSttn() { setBdstTable(chData); } }, [code, rainRes, sttnCommon.rainSttHeadList]); - + useEffect(() => { + if(sttnCommon.excelList.length>0){ + // TODO: API 호출후 받은 데이터로 엑셀 변환. + } + }, [sttnCommon.excelList]); const excelClick = useCallback(() => { - excelExportAction(code.cityCd, code.sggCd); - },[code.cityCd, code.sggCd, excelExportAction]); + //TODO: 엑셀 버튼 클릭시 API 호출 후 데이터를 excelRainSttn호출하여 변환된 데이터 effect 이벤트 동작.excelRainSttn(code.cityCd, code.sggCd); + //FIXME: 현재 API 호출하는 함수 액션이 존재하지 않음. + },[code.cityCd, code.sggCd, excelRainSttn]); return ( <> <ContentsDiv> diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx new file mode 100644 index 000000000..1c8157d1d --- /dev/null +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx @@ -0,0 +1,46 @@ +export type ExcelSttnRainType={ + "1.건축물정보": { + "행정구역":{"시도": string, "시군구": string}, + "건축물명": string, + "주소": string, + "건축물용도코드": string, + "최초건축허가일": string, + "건축면적": string, + "법적의무대상": string, + "설치완료일시": string, + }, + "2.빗물이용시설정보":{ + "설치비용": string, + "집수면":{ + "집수지점종류": string, + "집수지점면적": string, + }, + "여과등 처리시설":{ + "여과처리시설유무": string, + "여과처리시설용량": string, + "여과처리시설처리공정": string, + } + "저류조용량": string, + }, + "3.시설운영및 이용정보":{ + "운영관리코드": string, + "연간빗물운영량": string + }, + "4.인센티브 정보":{ + "설치비지원":{ + "설치지원비용여부": string, + "설치지원비용": string, + }, + "요금감면":{ + "감면여부": string, + "감면근거": string, + "감면금액": string, + }, + "녹색건축물인증여부":{ + "녹색건축물인증여부": string, + "녹색건축물인증년도": string, + "녹색건축물인증번호": string, + "녹색건축물인증등급": string, + } + } +} \ No newline at end of file diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx index 2df547da9..db4a66553 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx @@ -1,9 +1,9 @@ import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; -import { type ExcelExportType } from "../../../prfmncReg/chkgdnReg/rainChkgdn/excel"; import { type TableTripleProps, type TableUpperProps } from "../../fcltReg/rainReg"; +import type { ExcelSttnRainType } from "./excel"; const pbnSttHeadNm: chHeadType[] = [ { headNm: "catchment", text: "유역", length: 3 }, @@ -215,14 +215,14 @@ const rainSttHeadList: TableTripleProps[] = [ }, { id: "pntfColKnd", - title: "접수지점종류", + title: "집수지점종류", visible: true, upName: ["rainFcltInfo", "pntfCol"], upSequnce: [2, 1], }, { id: "pntfColArea", - title: "접수지점면적", + title: "집수지점면적", visible: true, upName: ["rainFcltInfo", "pntfCol"], upSequnce: [3, 2], @@ -342,7 +342,7 @@ export type sttnState = { pbnSttHeadNm: chHeadType[]; rainSttHeadList: TableTripleProps[]; rainSttHeadNm: chHeadType[]; - excelList:ExcelExportType[] + excelList:ExcelSttnRainType[] }; }; type sttnActions = { @@ -365,6 +365,9 @@ export const sttnStateExport: sttnState = { export const sttnActionsExport: (set: any) => sttnActions = (set: any) => { return { pbnSttnInit: async (sggCd: string, searchTxt: string, flg: string) => {}, + excelRainSttn: async (data: JSON[]) => { + //TODO: 엑셀 데이터 array 생성해서 return 필요. ExcelSttnRainType[]으로 생성해서 던져주면 됨. + }, chSttnHead: async (checkList: string[], type: string) => { const headList = type === "pbn" From 256e71c67e4e8a946bb759e391c692249849d2af Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Fri, 25 Apr 2025 15:17:27 +0900 Subject: [PATCH 11/29] =?UTF-8?q?=EB=B9=97=EB=AC=BC=EC=8B=9C=EC=84=A4=20?= =?UTF-8?q?=ED=98=84=ED=99=A9=20=EC=A1=B0=ED=9A=8C=20api=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruseFcltMng/fcltSttn/rainSttn/page.tsx | 56 ++++++++------ .../prfmncReg/chkgdnReg/rainChkgdn/excel.tsx | 6 +- .../store/ruseFcltMng/fcltSttn/sttn/index.tsx | 74 +++++++++++++------ 3 files changed, 89 insertions(+), 47 deletions(-) diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index 77bce97e8..5fd3e4b9e 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -11,7 +11,7 @@ import { Title, UiModal, UiTable, - type ReturnType + type ReturnType, } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button } from "@common/components/ui"; @@ -19,31 +19,36 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { headMakeTriple } from "./TableHead"; export default function RainSttn() { - const { code, rain, init, sttnCommon, excelExportAction } = useWrStore((state) => state); - const { rainRes } = rain; + const { code, init, sttnCommon, excelExportAction, rainSttnInit } = + useWrStore((state) => state); + const { rainRes } = sttnCommon; const [isChHead, setIsChHead] = useState(false); - const ref = useRef<ReturnType>({} as ReturnType); const [bdstTable, setBdstTable] = useState<any[]>(); const nodeList = headMakeTriple( sttnCommon.rainSttHeadList, sttnCommon.rainSttHeadNm ); - + useEffect(() => { - if (!rain.isInit) { - init(undefined); + if (!sttnCommon.isInit) { + let con + if (ref.current.sigunValue != '0') { + con = ref.current.sigunValue + }else{ + con = ref.current.sidoValue + } + rainSttnInit('1', '20' ,con); } - }, [rain.isInit, init]); + }, [sttnCommon.isInit, rainSttnInit]); useEffect(() => { - if (code.sggCd.length > 0) { + + if (rainRes.length > 0) { const data = tableData(rainRes, { code }); // data 는 위 JSON 객체라고 가정 // TODO: 이게 뭐하는 작업이지? - const unVisibleHead = sttnCommon.rainSttHeadList.filter( - (item: TableTripleProps) => item.visible === false - ); + const chData = data .map((item: any) => ({ ...item, @@ -52,15 +57,14 @@ export default function RainSttn() { })) .filter((item: any) => item.rainyObj !== undefined); - console.log("chData ", chData); - setBdstTable(chData); } - }, [code, rainRes, sttnCommon.rainSttHeadList]); + }, [code, sttnCommon.rainRes]); const excelClick = useCallback(() => { excelExportAction(code.cityCd, code.sggCd); - },[code.cityCd, code.sggCd, excelExportAction]); + }, [ code.sggCd, excelExportAction]); + return ( <> <ContentsDiv> @@ -82,17 +86,25 @@ export default function RainSttn() { }} > 조회항목설정 - </Button>} + </Button> + } leftChildren={undefined} queryClick={function (returnType: ReturnType): void { - + // page: string, total: string, con: string + // '{partValue: 'A', sidoValue: '0', sigunValue: '0', regionValue: '0', unitWaterShedValue: '0', …}' + let con + if (returnType.sigunValue != '0') { + con = returnType.sigunValue + }else{ + con = returnType.sidoValue + } + rainSttnInit('1', '20' ,con); }} excelClick={excelClick} - initClick={function (): void { - }} + initClick={function (): void {}} btnClass={btnClass} - ref={ref} /> - + ref={ref} + /> </div> </div> <div className="grid grid-cols-6 gap-4 "> diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx index 26f9a7e42..ead156cb2 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx @@ -8,7 +8,7 @@ const useTypes = [ "친수용수", "기타" ] -export type ExcelExportType = { +export type ExcelExportType = { "NO": string, "시도": string, "시군구": string, @@ -49,7 +49,9 @@ export type ExcelExportType = { "과태료 부과일(위반일)": string, "위반사항": string, "과태료부과금액(천원)": string -} +} + + export type Buildingtype = { bdstInfoPk: number, ctpvCd: 1, diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx index 21ef1831e..ac55700b7 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx @@ -1,9 +1,11 @@ import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; import { type ExcelExportType } from "../../../prfmncReg/chkgdnReg/rainChkgdn/excel"; import { + type customRainBdst, type TableTripleProps, - type TableUpperProps + type TableUpperProps, } from "../../fcltReg/rainReg"; +import { fetchType, getFetch } from "@/components/lib/api"; const pbnSttHeadNm: chHeadType[] = [ { headNm: "catchment", text: "유역", length: 3 }, @@ -268,7 +270,7 @@ const rainSttHeadList: TableTripleProps[] = [ upName: ["insenInfo", "instlCstSprt"], upSequnce: [2, 2], }, - + { id: "grntchBdstCertYn", title: "녹색건축물인증여부", @@ -298,19 +300,22 @@ const rainSttHeadList: TableTripleProps[] = [ upSequnce: [6, 4], }, ]; +const rainRes: customRainBdst[] = []; export type sttnState = { sttnCommon: { + rainRes: customRainBdst[]; pbnSttHeadList: TableUpperProps[]; pbnSttHeadNm: chHeadType[]; rainSttHeadList: TableTripleProps[]; rainSttHeadNm: chHeadType[]; - excelList:ExcelExportType[] + excelList: ExcelExportType[]; + isInit:boolean }; }; type sttnActions = { + rainSttnInit: (page: string, total: string, con: string) => void; chSttnHead: (checkList: string[], type: string) => void; - pbnSttnInit: (sggCd: string, searchTxt: string, flg: string) => void; }; export type sttnType = sttnState & sttnActions; @@ -321,13 +326,34 @@ export const sttnStateExport: sttnState = { pbnSttHeadNm: pbnSttHeadNm, rainSttHeadList: rainSttHeadList, rainSttHeadNm: rainSttHeadNm, + rainRes: rainRes, excelList: [], + isInit:false }, }; export const sttnActionsExport: (set: any) => sttnActions = (set: any) => { return { - pbnSttnInit: async (sggCd: string, searchTxt: string, flg: string) => {}, + rainSttnInit: async (page: string, total: string, con: string) => { + try { + const rainRes = await getFetch( + fetchType.WR, + `/reuseFc/rainyInfoList/${page}/${total}/${con}` + ); + set((state: sttnState) => { + return { + ...state, + sttnCommon: { + ...state.sttnCommon, + rainRes: rainRes, + isInit: false, + }, + }; + }); + } catch (erTxt) { + console.log("error", erTxt); + } + }, chSttnHead: async (checkList: string[], type: string) => { const headList = type === "pbn" @@ -336,34 +362,36 @@ export const sttnActionsExport: (set: any) => sttnActions = (set: any) => { ? rainSttHeadList : null; - let chNm = type === "pbn" ? pbnSttHeadNm : rainSttHeadNm; + let chNm = type === "pbn" ? pbnSttHeadNm : rainSttHeadNm; headList?.forEach((item) => { if (checkList.find((ch) => ch === item.id)) { item.visible = false; if (item.upName) { - const upNames = Array.isArray(item.upName) ? item.upName : [item.upName]; - upNames?.forEach((up) => { + const upNames = Array.isArray(item.upName) + ? item.upName + : [item.upName]; + upNames?.forEach((up) => { chNm.find((ch) => { if (ch.headNm === up) { ch.length = ch.length - 1; } - } - ); - - }) - } - + }); + }); + } } }); - set((state: sttnState) => ({ - sttnCommon: { - ...state.sttnCommon, - pbnSttHeadList: type === "pbn" ? headList : state.sttnCommon.pbnSttHeadList, - rainSttHeadList: type === "rain" ? headList : state.sttnCommon.rainSttHeadList, - rainSttHeadNm: type === "rain" ? chNm : state.sttnCommon.rainSttHeadNm, - pbnSttHeadNm: type === "rain" ? chNm : state.sttnCommon.pbnSttHeadNm, - }, - })); + set((state: sttnState) => ({ + sttnCommon: { + ...state.sttnCommon, + pbnSttHeadList: + type === "pbn" ? headList : state.sttnCommon.pbnSttHeadList, + rainSttHeadList: + type === "rain" ? headList : state.sttnCommon.rainSttHeadList, + rainSttHeadNm: + type === "rain" ? chNm : state.sttnCommon.rainSttHeadNm, + pbnSttHeadNm: type === "rain" ? chNm : state.sttnCommon.pbnSttHeadNm, + }, + })); }, }; }; From 752371e09f7411972963b85d766d825df1240985 Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Sun, 27 Apr 2025 10:09:21 +0900 Subject: [PATCH 12/29] =?UTF-8?q?=EC=97=91=EC=85=80=EB=8B=A4=EC=9A=B4?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EC=9E=91=EC=97=85=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wr/app/store/common/code/index.ts | 10 ++-- .../prfmncReg/chkgdnReg/rainChkgdn/index.tsx | 2 +- .../ruseFcltMng/fcltReg/htdflReg/index.tsx | 2 +- .../ruseFcltMng/fcltReg/rainReg/index.tsx | 4 +- .../store/ruseFcltMng/fcltSttn/sttn/excel.tsx | 58 +++++++++++++++++-- .../store/ruseFcltMng/fcltSttn/sttn/index.tsx | 16 ++++- 6 files changed, 77 insertions(+), 15 deletions(-) diff --git a/apps/wr/app/store/common/code/index.ts b/apps/wr/app/store/common/code/index.ts index 5d93811cc..a0a761f3e 100644 --- a/apps/wr/app/store/common/code/index.ts +++ b/apps/wr/app/store/common/code/index.ts @@ -5,13 +5,13 @@ import type { EnvPartSelectDataType, SelectDataType } from "@common/business_com export const btnClass= "p-4 m-2 text-white rounded-sm text-lg font-medium " -export const yn :SelectDataType[]=[ + const yn :SelectDataType[]=[ {val:'Y', text:'Y'}, {val:'N', text:'N'}, ] //공통 건축물 용도 -export const bdstUsgCd: SelectDataType[] = [ + const bdstUsgCd: SelectDataType[] = [ { val: '1', text: "운동장" }, { val: '2', text: "체육관" }, { val: '3', text: "공공업무시설" }, @@ -30,7 +30,7 @@ export const bdstUsgCd: SelectDataType[] = [ { val: '16', text: "기타" }, ]; //빗물 집수면 종류 용도 -export const rainFcltCd = [ + const rainFcltCd = [ { val: "1", text: "지붕" }, { val: "2", text: "건물옥상" }, { val: "3", text: "골프장 연못" }, @@ -43,7 +43,7 @@ export const rainFcltCd = [ { val: "10", text: "확인불가" }, ]; // 중수도 필수 원수종류 -export const rswtBdstType: SelectDataType[] = [ + const rswtBdstType: SelectDataType[] = [ { text: "숙박업", val: "17" }, { text: "목욕장업", val: "18" }, { text: "공장", val: "19" }, @@ -83,7 +83,7 @@ const orgwtKndCd = [ { text: "기타", val: "5" }, ]; -export const chBuCd = [ + const chBuCd = [ { val: "증축", text: "증축" }, { val: "개축", text: "개축" }, { val: "재축", text: "재축" }, diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx index 3734563a5..542c6e8b1 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx @@ -288,7 +288,7 @@ export type rainChkgdnState = { splHeadList: TableUpperProps[]; rswtDetailHeadList: TableUpperProps[]; isInit: boolean; - excelList:ExcelExportType[] + excelList:ExcelExportType[] | JSON[] }; }; diff --git a/apps/wr/app/store/ruseFcltMng/fcltReg/htdflReg/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltReg/htdflReg/index.tsx index f19962010..2ac27be5a 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltReg/htdflReg/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltReg/htdflReg/index.tsx @@ -1,5 +1,5 @@ import { getFetch, postFectch, putFectch } from "@/components/lib/api"; -import { upHeadList, type bdstAll, type chgBuilding, type TableUpperProps } from "../rainReg"; +import { upHeadList, type chgBuilding, type TableUpperProps } from "../rainReg"; import { z } from "zod"; import { makeMdfr, makeRstr } from "../bdstReg"; diff --git a/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx index 55f203c19..0963cf72e 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx @@ -1,7 +1,7 @@ -import type { selectArray } from "@/app/store/common/code"; import { getFetch, postFectch, putFectch } from "@/components/lib/api"; import { z } from "zod"; import { makeMdfr, makeRstr } from "../bdstReg"; +import type { SelectDataType } from "@common/business_components/ui"; export const TEST_UUID= '2d4b151d-1828-41e0-91d9-4cd28ea1cc7e' @@ -138,7 +138,7 @@ export type rainFacState = { rain: { isInit: boolean; upHeadList: TableUpperProps[]; - selectYN: selectArray[]; + selectYN: SelectDataType[]; rainRes: customRainBdst[]; // regRainForm:customRainBdst, diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx index 1c8157d1d..b50d77923 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx @@ -1,3 +1,5 @@ +import type { customRainBdst } from "../../fcltReg/rainReg" + export type ExcelSttnRainType={ "1.건축물정보": { "행정구역":{"시도": string, "시군구": string}, @@ -19,19 +21,19 @@ export type ExcelSttnRainType={ "여과처리시설유무": string, "여과처리시설용량": string, "여과처리시설처리공정": string, - } + }, "저류조용량": string, }, - "3.시설운영및 이용정보":{ + "3.시설운영및 이용정보"?:{ "운영관리코드": string, "연간빗물운영량": string }, - "4.인센티브 정보":{ + "3.인센티브 정보":{ "설치비지원":{ "설치지원비용여부": string, "설치지원비용": string, }, - "요금감면":{ + "요금감면"?:{ "감면여부": string, "감면근거": string, "감면금액": string, @@ -43,4 +45,52 @@ export type ExcelSttnRainType={ "녹색건축물인증등급": string, } } +} + +const excelSttnParsing = (data: customRainBdst[]): ExcelSttnRainType[] => { + const excelExportData: ExcelSttnRainType[] = [] + data.forEach((item) => { + excelExportData.push( + { + "1.건축물정보": { + "행정구역":{"시도": String(item.ctpvCd), "시군구": String(item.sggCd)}, + "건축물명": item.bdstNm, + "주소": item.daddr, + "건축물용도코드": String(item.bdstInfoPk), + "최초건축허가일":String(item.frstArchPrmsnDt), + "건축면적": String(item.archArea), + "법적의무대상": String(item.reuseBuilding[0]?.lawTrgtYn??''), + "설치완료일시": String(item.reuseBuilding[0]?.instlCmptnDt??''), + }, + "2.빗물이용시설정보":{ + "설치비용": String(item.reuseBuilding[0]?.instlCst??''), + "집수면":{ + "집수지점종류": item.reuseBuilding[0]?.rainyObj.pntfColKnd??'', + "집수지점면적": String(item.reuseBuilding[0]?.rainyObj.pntfColArea??''), + }, + "여과등 처리시설":{ + "여과처리시설유무": String(item.reuseBuilding[0]?.rainyObj.filtrTrtmfctYn??''), + "여과처리시설용량": String(item.reuseBuilding[0]?.rainyObj.filtrTrtmfctCpct??''), + "여과처리시설처리공정":String(item.reuseBuilding[0]?.rainyObj.filtrTrtmfctPrs??''), + }, + "저류조용량": String(item.reuseBuilding[0]?.rainyObj.dtfcltCpct??''), + }, + "3.인센티브 정보":{ + "설치비지원":{ + "설치지원비용여부": String(item.reuseBuilding[0]?.instlCstSprtYn ) , + "설치지원비용": String(item.reuseBuilding[0]?.instlCstSprtAmt ), + }, + "녹색건축물인증여부":{ + "녹색건축물인증여부": String(item.reuseBuilding[0]?.grntchBdstCertYn) , + "녹색건축물인증년도": String(item.reuseBuilding[0]?.grntchBdstCertYr), + "녹색건축물인증번호": String(item.reuseBuilding[0]?.grntchBdstCertNo), + "녹색건축물인증등급": String(item.reuseBuilding[0]?.grntchBdstCertGrd), + } + } + }) + }); + // excelItem = {} as ExcelSttnRainType + // excelItem["1.건축물정보"]["행정구역"]["시도"] = item.sidoNm + // excelItem["1.건축물정보"]["행정구역"]["시군구"] = item.sggNm + return excelExportData; } \ No newline at end of file diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx index 62c29a93a..f8e2c6c09 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx @@ -314,7 +314,7 @@ export type sttnState = { }; }; type sttnActions = { - rainSttnInit: (page: string, total: string, con: string) => void; + rainSttnSearch: (page: string, total: string, con: string) => void; chSttnHead: (checkList: string[], type: string) => void; excelRainSttn:(data:JSON[] ) => void }; @@ -335,12 +335,24 @@ export const sttnStateExport: sttnState = { export const sttnActionsExport: (set: any) => sttnActions = (set: any) => { return { - rainSttnInit: async (page: string, total: string, con: string) => { + rainSttnSearch: async (page: string, total: string, con: string) => { try { const rainRes = await getFetch( fetchType.WR, `/reuseFc/rainyInfoList/${page}/${total}/${con}` ); + if(Number(total) > 9000){ + set((state: sttnState) => { + return { + ...state, + sttnCommon: { + ...state.sttnCommon, + excelList: rainRes, + }, + }; + }); + } + else set((state: sttnState) => { return { ...state, From 9b5c76239cc4cbf76f2cbecd14ceebc6661cb083 Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Sun, 27 Apr 2025 10:10:23 +0900 Subject: [PATCH 13/29] =?UTF-8?q?=ED=97=A4=ED=97=A4=EB=8D=94=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruseFcltMng/fcltReg/rainReg/TableHead.tsx | 30 ++++++++++ .../app/ruseFcltMng/fcltReg/rainReg/page.tsx | 29 +--------- .../app/ruseFcltMng/fcltReg/rswtReg/page.tsx | 2 +- .../ruseFcltMng/fcltSttn/rainSttn/page.tsx | 45 +++++++++----- .../prfmncReg/chkgdnReg/TableHead.tsx | 53 +++++++++++++++++ .../ruseFcltMng/prfmncReg/chkgdnReg/page.tsx | 58 ++----------------- .../ui/modal/bdstRegModal/bdstRegModal.tsx | 7 +-- 7 files changed, 125 insertions(+), 99 deletions(-) create mode 100644 apps/wr/app/ruseFcltMng/fcltReg/rainReg/TableHead.tsx create mode 100644 apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead.tsx diff --git a/apps/wr/app/ruseFcltMng/fcltReg/rainReg/TableHead.tsx b/apps/wr/app/ruseFcltMng/fcltReg/rainReg/TableHead.tsx new file mode 100644 index 000000000..39137d364 --- /dev/null +++ b/apps/wr/app/ruseFcltMng/fcltReg/rainReg/TableHead.tsx @@ -0,0 +1,30 @@ +import type { TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; +import { TableRow, TableHead } from "@common/components/ui"; + +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> + </> + ); + }; + \ No newline at end of file diff --git a/apps/wr/app/ruseFcltMng/fcltReg/rainReg/page.tsx b/apps/wr/app/ruseFcltMng/fcltReg/rainReg/page.tsx index 1434481be..af78efb00 100644 --- a/apps/wr/app/ruseFcltMng/fcltReg/rainReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltReg/rainReg/page.tsx @@ -23,35 +23,8 @@ import { import ListDiv from "@common/business_components/ui/list_div"; import { Button, TableHead, TableRow } from "@common/components"; import { useEffect, useState } from "react"; +import { headMakeColSpan } from "./TableHead"; -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> - </> - ); -}; - -//------------------------------------------------------------------------------------------------------- export default function Home() { const { rain, code, init } = useWrStore((state) => { diff --git a/apps/wr/app/ruseFcltMng/fcltReg/rswtReg/page.tsx b/apps/wr/app/ruseFcltMng/fcltReg/rswtReg/page.tsx index bf15631d9..473ac6889 100644 --- a/apps/wr/app/ruseFcltMng/fcltReg/rswtReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltReg/rswtReg/page.tsx @@ -14,13 +14,13 @@ import { } from "@common/business_components"; import ListDiv from "@common/business_components/ui/list_div"; import { Button } from "@common/components"; -import { headMakeColSpan } from "../rainReg/page"; import { useEffect, useState } from "react"; import type { customRswtBdst } from "@/app/store/ruseFcltMng/fcltReg/rswtReg"; import { tableData } from "@/components/lib/func/commom"; import RswtrRegForm from "@/components/ui/form/fcltReg/rswtrReg/rswtrRegForm"; import BdstChgModal from "@/components/ui/modal/bdstChgModal/bdstChgModal"; import type { chgBuilding } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; +import { headMakeColSpan } from "../rainReg/TableHead"; export default function Home() { const { code, rswt, initRswt } = useWrStore((state) => state); diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index 1ac48fe44..2f2afbac0 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -7,6 +7,7 @@ import { tableData } from "@/components/lib/func/commom"; import HeadChModal from "@/components/ui/modal/headChModal/headChModal"; import { ContentsDiv, + filePickedBlob, SearchBaseForm, Title, UiModal, @@ -19,7 +20,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { headMakeTriple } from "./TableHead"; export default function RainSttn() { - const { code, sttnCommon, excelRainSttn,excelExportAction, rainSttnInit } = + const { code, sttnCommon, excelRainSttn,excelExportAction, rainSttnSearch } = useWrStore((state) => state); const { rainRes } = sttnCommon; @@ -39,19 +40,18 @@ export default function RainSttn() { }else{ con = ref.current.sidoValue } - rainSttnInit('1', '20' ,con); + rainSttnSearch('1', '20' ,con); } - }, [sttnCommon.isInit, rainSttnInit]); + }, [sttnCommon.isInit, rainSttnSearch]); + + + useEffect(() => { if (rainRes.length > 0) { const data = tableData(rainRes, { code }); // data 는 위 JSON 객체라고 가정 - // TODO: 이게 뭐하는 작업이지? - - const unVisibleHead = sttnCommon.rainSttHeadList.filter( - (item: TableTripleProps) => item.visible === false - ); + const chData = data .map((item: any) => ({ ...item, @@ -65,13 +65,30 @@ export default function RainSttn() { }, [code, rainRes, sttnCommon.rainSttHeadList]); useEffect(() => { if(sttnCommon.excelList.length>0){ - // TODO: API 호출후 받은 데이터로 엑셀 변환. + if (sttnCommon.excelList.length === 0) return; + fetch('/sample_rainy.xlsx', {}) + .then(async (response) => { + if (!response.ok) { + throw Error(response.statusText) + } + // 받은 파일 바인너리 처리 + const blobRet = await response.arrayBuffer() + // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 + const ret =await filePickedBlob(blobRet, sttnCommon.excelList ) + console.log('ret', ret); + }) } }, [sttnCommon.excelList]); - const excelClick = useCallback(() => { - //TODO: 엑셀 버튼 클릭시 API 호출 후 데이터를 excelRainSttn호출하여 변환된 데이터 effect 이벤트 동작.excelRainSttn(code.cityCd, code.sggCd); - //FIXME: 현재 API 호출하는 함수 액션이 존재하지 않음. - },[code.cityCd, code.sggCd, excelRainSttn]); + + const excelClick = useCallback((returnType:ReturnType) => { + let con + if (returnType.sigunValue != '0') { + con = returnType.sigunValue + }else{ + con = returnType.sidoValue + } + rainSttnSearch('1', '10000' ,con); + },[rainSttnSearch]); return ( <> <ContentsDiv> @@ -105,7 +122,7 @@ export default function RainSttn() { }else{ con = returnType.sidoValue } - rainSttnInit('1', '20' ,con); + rainSttnSearch('1', '20' ,con); }} excelClick={excelClick} initClick={function (): void {}} diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead.tsx new file mode 100644 index 000000000..0d21b08e8 --- /dev/null +++ b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead.tsx @@ -0,0 +1,53 @@ +import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; +import type { TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; +import { TableHead, TableRow } from "@common/components/ui"; + +export const headMakeprfmnc = ( + upHeadList: TableUpperProps[], + makeHeadNm: chHeadType[] + ) => { + return ( + <> + <TableRow> + {upHeadList + .map((head: TableUpperProps) => + !head.upSequnce ? ( + <TableHead + className={`border border-gray-600 px-2 py-1 `} + rowSpan={2} + key={head.id} + > + {head.title} + </TableHead> + ) : head.upSequnce === 1 ? ( + <TableHead + className={`border border-gray-600 px-2 py-1 `} + key={head.id} + rowSpan={1} + colSpan={ + makeHeadNm.find((ch) => ch.headNm === head.upName)?.length + } + > + {makeHeadNm.find((ch) => ch.headNm === head.upName)?.text} + </TableHead> + ) : null + )} + </TableRow> + + <TableRow> + {upHeadList + .filter((data) => data.visible != false) + .map((head: TableUpperProps) => + makeHeadNm.find((ch) => ch.headNm === head.upName) ? ( + <TableHead + className={`border border-gray-600 px-2 py-1 `} + key={head.id} + > + {head.title} + </TableHead> + ) : null + )} + </TableRow> + </> + ); + }; \ No newline at end of file diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx index 3150a1c44..c29a33a1f 100644 --- a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx @@ -23,66 +23,15 @@ import { UiModal } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; -import { TableHead, TableRow } from "@common/components"; import { Button } from "@common/components/ui"; import { useCallback, useEffect, useState } from "react"; -export const headMakeprfmnc = ( - upHeadList: TableUpperProps[], - makeHeadNm: chHeadType[] -) => { - return ( - <> - <TableRow> - {upHeadList - .map((head: TableUpperProps) => - !head.upSequnce ? ( - <TableHead - className={`border border-gray-600 px-2 py-1 `} - rowSpan={2} - key={head.id} - > - {head.title} - </TableHead> - ) : head.upSequnce === 1 ? ( - <TableHead - className={`border border-gray-600 px-2 py-1 `} - key={head.id} - rowSpan={1} - colSpan={ - makeHeadNm.find((ch) => ch.headNm === head.upName)?.length - } - > - {makeHeadNm.find((ch) => ch.headNm === head.upName)?.text} - </TableHead> - ) : null - )} - </TableRow> - - <TableRow> - {upHeadList - .filter((data) => data.visible != false) - .map((head: TableUpperProps) => - makeHeadNm.find((ch) => ch.headNm === head.upName) ? ( - <TableHead - className={`border border-gray-600 px-2 py-1 `} - key={head.id} - > - {head.title} - </TableHead> - ) : null - )} - </TableRow> - </> - ); -}; //----------------------- export default function Page() { const { code, rainChkgdn, rainChkInit,rainChkDetilUpdate, excelExportAction } = useWrStore((state) => { return state; }); - const [isDetail, setIsDetail] = useState(false); const [isExcel, setIsExcel] = useState(false); const [searchTxt, setSearchTxt] = useState<string>(); @@ -101,6 +50,8 @@ export default function Page() { rainChkInit('2024','0'); } }, [rainChkgdn.isInit, rainChkInit]); + + useEffect(() => { console.log("rainChkgdn.excelList", rainChkgdn.excelList); if (rainChkgdn.excelList.length === 0) return; @@ -112,13 +63,16 @@ export default function Page() { // 받은 파일 바인너리 처리 const blobRet = await response.arrayBuffer() // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 - const ret =await filePickedBlob(blobRet, rainChkgdn.excelList) + const ret =await filePickedBlob(blobRet, rainChkgdn.excelList ) console.log('ret', ret); }) }, [rainChkgdn.excelList]); + const excelClick= useCallback(()=>{ excelExportAction(code.cityCd, code.sggCd); }, [excelExportAction, code.cityCd, code.sggCd]); + + return ( <ContentsDiv> <div className="grid grid-cols-4 gap-4 "> diff --git a/apps/wr/components/ui/modal/bdstRegModal/bdstRegModal.tsx b/apps/wr/components/ui/modal/bdstRegModal/bdstRegModal.tsx index 308c01241..c00f54bd1 100644 --- a/apps/wr/components/ui/modal/bdstRegModal/bdstRegModal.tsx +++ b/apps/wr/components/ui/modal/bdstRegModal/bdstRegModal.tsx @@ -1,20 +1,19 @@ "use client"; -import { headMakeColSpan } from "@/app/ruseFcltMng/fcltReg/rainReg/page"; import { useWrStore } from "@/app/store"; import { selectClass, type customRainBdst, } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; -import { ScrollArea, SelectBox, UiTable } from "@common/business_components"; +import { ScrollArea, SelectBox, UiTable, type SelectDataType } from "@common/business_components"; import { Button, Input, Label } from "@common/components"; import { useEffect, useState } from "react"; import RainRegForm from "../../form/fcltReg/rainReg/rainRegForm"; -import { type selectArray } from "@/app/store/common/code"; import { getCity, tableData } from "@/components/lib/func/commom"; import type { customRswtBdst } from "@/app/store/ruseFcltMng/fcltReg/rswtReg"; import HtdflRegForm from "../../form/fcltReg/htdflReg/htdflRegForm"; import type { customHtdflBdst } from "@/app/store/ruseFcltMng/fcltReg/htdflReg"; import RswtrRegForm from "../../form/fcltReg/rswtrReg/rswtrRegForm"; +import { headMakeColSpan } from "@/app/ruseFcltMng/fcltReg/rainReg/TableHead"; export type objSearchType = { sgg: string|number; @@ -40,7 +39,7 @@ export function BdstReg<T extends MoType>({ moType }: BdstRegProps<T>) { const [bdstTable, setbdstTable] = useState<BdstTypeMap[T][]>(); const [rainBdstForm, setRainBdstForm] = useState<BdstTypeMap[T]>({} as BdstTypeMap[T]); const [searchTxt, setSearchTxt] = useState<string>() - const [selectSgg, setSelectSgg] = useState<selectArray[] | []>() + const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>() const [objSearch, setObjSearch] = useState<objSearchType>({sgg:"",city:""}); const getSelCity = (val: string | number) => { From 97235d45cd6943de66de78821237e830b3a528d0 Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Tue, 29 Apr 2025 10:06:13 +0900 Subject: [PATCH 14/29] =?UTF-8?q?=EC=97=91=EC=85=80=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD=ED=95=A0=20=EC=88=98=20?= =?UTF-8?q?=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business_components/src/ui/search_base_form/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/common/business_components/src/ui/search_base_form/index.tsx b/packages/common/business_components/src/ui/search_base_form/index.tsx index 90ad0b05e..9dc1bf735 100644 --- a/packages/common/business_components/src/ui/search_base_form/index.tsx +++ b/packages/common/business_components/src/ui/search_base_form/index.tsx @@ -13,6 +13,7 @@ type SearchBaseType = { selectMiddleRegionData?: SelectDataType[] | []; selectEnvPartData?: EnvPartSelectDataType[] | []; queryClick:(returnType:ReturnType) => void; + excelName?:string; excelClick:(returnType:ReturnType) => void; initClick:() => void; btnClass:string; @@ -39,6 +40,7 @@ function SearchBaseForm ({ selectMiddleRegionData, selectEnvPartData, btnClass, + excelName, queryClick, excelClick, initClick, @@ -120,7 +122,7 @@ function SearchBaseForm ({ </SearchFormLeft> <SearchFormRight> <Button className={btnClass} color="green" onClick={excelDownload}> - 엑셀다운로드 + {excelName?excelName:"엑셀다운로드"} </Button> <div> <Button className={btnClass} onClick={initVal}> From 85421179471a706df4b116612c1604f24c2eb741 Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Tue, 29 Apr 2025 10:24:13 +0900 Subject: [PATCH 15/29] =?UTF-8?q?excel=20test=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruseFcltMng/fcltSttn/rainSttn/page.tsx | 20 +- .../ruseFcltMng/prfmncReg/chkgdnReg/page.tsx | 15 +- .../prfmncReg/chkgdnReg/rainChkgdn/index.tsx | 2 +- .../ruseFcltMng/fcltReg/rainReg/index.tsx | 4 + .../store/ruseFcltMng/fcltSttn/sttn/excel.tsx | 92 +++++++-- .../store/ruseFcltMng/fcltSttn/sttn/index.tsx | 24 +-- apps/wr/components/lib/func/TableData.tsx | 144 ++++++++++++++ .../lib/func/{commom.ts => commom.tsx} | 20 +- .../guideDetailTable/guideDetailTable.tsx | 6 +- .../chkgdTable/rainChkgd/rainChkgdTable.tsx | 181 ++---------------- apps/wr/public/sample.xlsx | Bin 0 -> 15020 bytes apps/wr/public/sample_rainSttn.xlsx | Bin 0 -> 9091 bytes apps/wr/public/sample_rainSttn_test.xlsx | Bin 0 -> 8482 bytes 13 files changed, 281 insertions(+), 227 deletions(-) create mode 100644 apps/wr/components/lib/func/TableData.tsx rename apps/wr/components/lib/func/{commom.ts => commom.tsx} (67%) create mode 100644 apps/wr/public/sample.xlsx create mode 100644 apps/wr/public/sample_rainSttn.xlsx create mode 100644 apps/wr/public/sample_rainSttn_test.xlsx diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index 2f2afbac0..aa5fd43e0 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -3,7 +3,7 @@ import { useWrStore } from "@/app/store"; import { btnClass } from "@/app/store/common/code"; import type { TableTripleProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; -import { tableData } from "@/components/lib/func/commom"; +import { excelDownload, tableData } from "@/components/lib/func/commom"; import HeadChModal from "@/components/ui/modal/headChModal/headChModal"; import { ContentsDiv, @@ -20,7 +20,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { headMakeTriple } from "./TableHead"; export default function RainSttn() { - const { code, sttnCommon, excelRainSttn,excelExportAction, rainSttnSearch } = + const { code, sttnCommon, excelExportAction, rainSttnSearch } = useWrStore((state) => state); const { rainRes } = sttnCommon; @@ -66,21 +66,14 @@ export default function RainSttn() { useEffect(() => { if(sttnCommon.excelList.length>0){ if (sttnCommon.excelList.length === 0) return; - fetch('/sample_rainy.xlsx', {}) - .then(async (response) => { - if (!response.ok) { - throw Error(response.statusText) - } - // 받은 파일 바인너리 처리 - const blobRet = await response.arrayBuffer() - // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 - const ret =await filePickedBlob(blobRet, sttnCommon.excelList ) - console.log('ret', ret); - }) + excelDownload(sttnCommon.excelList , '빗물재이용시설 현황','sample_rainSttn_test.xlsx') } + + }, [sttnCommon.excelList]); const excelClick = useCallback((returnType:ReturnType) => { + let con if (returnType.sigunValue != '0') { con = returnType.sigunValue @@ -114,7 +107,6 @@ export default function RainSttn() { } leftChildren={undefined} queryClick={function (returnType: ReturnType): void { - // page: string, total: string, con: string // '{partValue: 'A', sidoValue: '0', sigunValue: '0', regionValue: '0', unitWaterShedValue: '0', …}' let con if (returnType.sigunValue != '0') { diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx index c29a33a1f..5d8889db1 100644 --- a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx @@ -7,6 +7,7 @@ import { type rainChkZodType, } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; import type { TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; +import { excelDownload } from "@/components/lib/func/commom"; import ChkgdExcel from "@/components/ui/modal/chkgdExcel/chkgdExcel"; import ChkgdModal from "@/components/ui/modal/chkgdModal/chkgdModal"; import RainChkgdTable from "@/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable"; @@ -53,19 +54,7 @@ export default function Page() { useEffect(() => { - console.log("rainChkgdn.excelList", rainChkgdn.excelList); - if (rainChkgdn.excelList.length === 0) return; - fetch('/sample_rainy.xlsx', {}) - .then(async (response) => { - if (!response.ok) { - throw Error(response.statusText) - } - // 받은 파일 바인너리 처리 - const blobRet = await response.arrayBuffer() - // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 - const ret =await filePickedBlob(blobRet, rainChkgdn.excelList ) - console.log('ret', ret); - }) + excelDownload(rainChkgdn.excelList); }, [rainChkgdn.excelList]); const excelClick= useCallback(()=>{ diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx index 542c6e8b1..f8832a220 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx @@ -288,7 +288,7 @@ export type rainChkgdnState = { splHeadList: TableUpperProps[]; rswtDetailHeadList: TableUpperProps[]; isInit: boolean; - excelList:ExcelExportType[] | JSON[] + excelList:JSON[]; }; }; diff --git a/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx index 0963cf72e..ccf0e2b32 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx @@ -101,6 +101,10 @@ export type TableUpperProps = { type?: string; }; + + + + export type TableTripleProps = { id: string; title: string; diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx index b50d77923..5f4cc83ba 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx @@ -24,20 +24,13 @@ export type ExcelSttnRainType={ }, "저류조용량": string, }, - "3.시설운영및 이용정보"?:{ - "운영관리코드": string, - "연간빗물운영량": string - }, + "3.인센티브 정보":{ "설치비지원":{ "설치지원비용여부": string, "설치지원비용": string, }, - "요금감면"?:{ - "감면여부": string, - "감면근거": string, - "감면금액": string, - }, + "녹색건축물인증여부":{ "녹색건축물인증여부": string, "녹색건축물인증년도": string, @@ -47,7 +40,7 @@ export type ExcelSttnRainType={ } } -const excelSttnParsing = (data: customRainBdst[]): ExcelSttnRainType[] => { +export const excelSttnParsing = (data: customRainBdst[]): ExcelSttnRainType[] => { const excelExportData: ExcelSttnRainType[] = [] data.forEach((item) => { excelExportData.push( @@ -89,8 +82,85 @@ const excelSttnParsing = (data: customRainBdst[]): ExcelSttnRainType[] => { } }) }); + + console.log(excelExportData) // excelItem = {} as ExcelSttnRainType // excelItem["1.건축물정보"]["행정구역"]["시도"] = item.sidoNm // excelItem["1.건축물정보"]["행정구역"]["시군구"] = item.sggNm return excelExportData; -} \ No newline at end of file +} + + + + +export type ExcelSttnRainTypeFlat = { + 행정구역: string; + 건축물명: string; + 주소: string; + 건축물용도코드: string; + 최초건축허가일: string; + 건축면적: string; + 법적의무대상: string; + 설치완료일시: string; + + 설치비용: string; + 집수면: string; + 여과등처리시설: string; + 저류조용량: string; + + 운영관리코드?: string; + 연간빗물운영량?: string; + + 설치지원비용여부: string; + 설치지원비용: string; + + 녹색건축물인증여부: string; + }; + + +export const excelSttnParsingJson = (data: customRainBdst[]): ExcelSttnRainTypeFlat[] => { + const excelExportData: ExcelSttnRainTypeFlat[] = []; + + data.forEach((item) => { + excelExportData.push({ + // 1.건축물정보 + "행정구역": JSON.stringify({ + 시도: String(item.ctpvCd), + 시군구: String(item.sggCd) + }), + "건축물명": item.bdstNm ?? "", + "주소": item.daddr ?? "", + "건축물용도코드": String(item.bdstInfoPk ?? ""), + "최초건축허가일": String(item.frstArchPrmsnDt ?? ""), + "건축면적": String(item.archArea ?? ""), + "법적의무대상": String(item.reuseBuilding?.[0]?.lawTrgtYn ?? ""), + "설치완료일시": String(item.reuseBuilding?.[0]?.instlCmptnDt ?? ""), + + // 2.빗물이용시설정보 + "설치비용": String(item.reuseBuilding?.[0]?.instlCst ?? ""), + "집수면": JSON.stringify({ + 집수지점종류: item.reuseBuilding?.[0]?.rainyObj?.pntfColKnd ?? "", + 집수지점면적: String(item.reuseBuilding?.[0]?.rainyObj?.pntfColArea ?? "") + }), + "여과등처리시설": JSON.stringify({ + 여과처리시설유무: String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctYn ?? ""), + 여과처리시설용량: String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctCpct ?? ""), + 여과처리시설처리공정: String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctPrs ?? "") + }), + "저류조용량": String(item.reuseBuilding?.[0]?.rainyObj?.dtfcltCpct ?? ""), + + // 3.인센티브 정보 + "설치지원비용여부": String(item.reuseBuilding?.[0]?.instlCstSprtYn ?? ""), + "설치지원비용": String(item.reuseBuilding?.[0]?.instlCstSprtAmt ?? ""), + + "녹색건축물인증여부": JSON.stringify({ + 녹색건축물인증여부: String(item.reuseBuilding?.[0]?.grntchBdstCertYn ?? ""), + 녹색건축물인증년도: String(item.reuseBuilding?.[0]?.grntchBdstCertYr ?? ""), + 녹색건축물인증번호: String(item.reuseBuilding?.[0]?.grntchBdstCertNo ?? ""), + 녹색건축물인증등급: String(item.reuseBuilding?.[0]?.grntchBdstCertGrd ?? "") + }), + }); + }); + + return excelExportData; + }; \ No newline at end of file diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx index f8e2c6c09..7972a949b 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx @@ -4,7 +4,7 @@ import { type TableTripleProps, type TableUpperProps, } from "../../fcltReg/rainReg"; -import type { ExcelSttnRainType } from "./excel"; +import { excelSttnParsing, excelSttnParsingJson, type ExcelSttnRainType, type FlatExcelSttnRainType } from "./excel"; import { fetchType, getFetch } from "@/components/lib/api"; const pbnSttHeadNm: chHeadType[] = [ @@ -316,7 +316,6 @@ export type sttnState = { type sttnActions = { rainSttnSearch: (page: string, total: string, con: string) => void; chSttnHead: (checkList: string[], type: string) => void; - excelRainSttn:(data:JSON[] ) => void }; export type sttnType = sttnState & sttnActions; @@ -342,12 +341,14 @@ export const sttnActionsExport: (set: any) => sttnActions = (set: any) => { `/reuseFc/rainyInfoList/${page}/${total}/${con}` ); if(Number(total) > 9000){ + //const rainExcel= excelSttnParsing(rainRes) + const rainExcel= excelSttnParsing(rainRes) set((state: sttnState) => { return { ...state, sttnCommon: { ...state.sttnCommon, - excelList: rainRes, + excelList: rainExcel, }, }; }); @@ -367,21 +368,6 @@ export const sttnActionsExport: (set: any) => sttnActions = (set: any) => { console.log("error", erTxt); } }, - excelRainSttn: async (data: JSON[]) => { - //TODO: 엑셀 데이터 array 생성해서 return 필요. ExcelSttnRainType[]으로 생성해서 던져주면 됨. - - - set((state: sttnState) => { - return { - ...state, - sttnCommon: { - ...state.sttnCommon, - rainRes: rainRes, - isInit: false, - }, - }; - }); - }, chSttnHead: async (checkList: string[], type: string) => { const headList = type === "pbn" @@ -423,3 +409,5 @@ export const sttnActionsExport: (set: any) => sttnActions = (set: any) => { }, }; }; + + diff --git a/apps/wr/components/lib/func/TableData.tsx b/apps/wr/components/lib/func/TableData.tsx new file mode 100644 index 000000000..d6bc9f30e --- /dev/null +++ b/apps/wr/components/lib/func/TableData.tsx @@ -0,0 +1,144 @@ +import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; +import type { TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; +import { Checkbox, Input, TableCell, TableRow } from "@common/components/ui"; + +export const rightTableData = (rainChk: rainChkZodType[]) => { + // 1. chkgdnFk + utztnUsgCd 기준 누계 정보 만들기 + const maketotal = rainChk.map((item: any) => { + const selectTotal = item.guideDetails.reduce((acc: any, cur: any) => { + const code = cur.utztnUsgCd; + const fk = cur.chkgdnFk; + + const key = `${fk}_${code}`; + acc[key] = acc[key] || { + totalSplyUswtrUtztnQnt: 0, + totalRuseFcltUtztnQnt: 0, + }; + + acc[key].totalSplyUswtrUtztnQnt += cur.splyUswtrUtztnQnt; + acc[key].totalRuseFcltUtztnQnt += cur.ruseFcltUtztnQnt; + + return acc; + }, {}); + + return selectTotal; // 모든 키: `${chkgdnFk}_${utztnUsgCd}` 형태 + }); + + // 2. 누계 정보들을 하나의 객체로 합치기 (평탄화) + const flatTotalMap = Object.assign({}, ...maketotal); + + // 3. rainyDetails에 누계 정보 주입 + + const updatedRainyDetails: any[] = []; + rainChk.forEach((rd: any) => { + const details = rd.rainyDetails.forEach((rainyItem: any) => { + const key = `${rainyItem.chkgdnFk}_${rainyItem.utztnUsgCd}`; + const totals = flatTotalMap[key] || { + totalSplyUswtrUtztnQnt: 0, + totalRuseFcltUtztnQnt: 0, + }; + + updatedRainyDetails.push({ + ...rd, + ...rd.building, + ...rainyItem, + ...totals, + rowspan: rd.rainyDetails?.length, + }); + }); + }); + + return updatedRainyDetails; +}; + + + + + +export const chRowspanTable = ( + makeTableData: any[], + headList: TableUpperProps[], + handleChange: ( + rowIndex: number, + field: keyof (typeof makeTableData)[0], + value: string | number + ) => void, + toggleSelection: (pk: number, checked: boolean) => void, + selectedIds: number[], + handleCellClick: (index: number, headId: string) => void + ) => { + + + + + // rowspan된 셀 렌더링 여부 추적용 + const renderedMap = new Map<string, Set<number>>(); + return ( + <> + {makeTableData.map((row, rowIndex) => ( + <TableRow key={rowIndex}> + {headList.map((head) => { + const key = head.id; + const isMerged = head.rowSpan; + const value = row[key]; + + // 병합 대상이면 중복 렌더링 여부 판단 + if (isMerged) { + const renderedSet = renderedMap.get(key) ?? new Set<number>(); + if (renderedSet.has(rowIndex)) return null; // 이미 렌더링된 셀은 skip + + const rowspan = row.rowspan ?? 1; + for (let i = 0; i < rowspan; i++) { + renderedSet.add(rowIndex + i); + } + renderedMap.set(key, renderedSet); + + return ( + <TableCell + key={key} + rowSpan={rowspan} + className="align-middle text-center whitespace-nowrap" + > + {key === "order" ? ( + <Checkbox + checked={selectedIds.includes(row.chkgdnPk)} + onCheckedChange={(checked) => + toggleSelection(row.chkgdnPk, checked === true) + } + ></Checkbox> + ) : ( + value + )} + </TableCell> + ); + } + + // 기본 셀 + return ( + <TableCell + key={key} + className="text-center whitespace-nowrap" + onClick={() => handleCellClick(rowIndex, head.id)} + > + {key === "totalSplyUswtrUtztnQnt" || + key === "totalRuseFcltUtztnQnt" || + key === "utztnUsgCd" ? ( + `${value}` + ) : ( + <Input + className={`${head.type === "number" ? "text-right" : "text-center"} text-3xl`} + type={head.type} + onChange={(e) => { + handleChange(rowIndex, head.id, e.target.value); + }} + value={value} + /> + )} + </TableCell> + ); + })} + </TableRow> + ))} + </> + ); + }; \ No newline at end of file diff --git a/apps/wr/components/lib/func/commom.ts b/apps/wr/components/lib/func/commom.tsx similarity index 67% rename from apps/wr/components/lib/func/commom.ts rename to apps/wr/components/lib/func/commom.tsx index ecae649dd..6f18a5810 100644 --- a/apps/wr/components/lib/func/commom.ts +++ b/apps/wr/components/lib/func/commom.tsx @@ -1,5 +1,5 @@ import type { comCodeState, } from "@/app/store/common/code"; -import type { SelectDataType } from "@common/business_components/ui"; +import { filePickedBlob, type SelectDataType } from "@common/business_components/ui"; @@ -47,4 +47,20 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => { }); } - \ No newline at end of file + + + export const excelDownload =(excelList: JSON[], fileNm:string ,sampleFile:string ) =>{ + console.log("excelList", excelList); + if (excelList.length === 0) return; + fetch(`/${sampleFile}`, {}) + .then(async (response) => { + if (!response.ok) { + throw Error(response.statusText) + } + // 받은 파일 바인너리 처리 + const blobRet = await response.arrayBuffer() + // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 + const ret =await filePickedBlob(blobRet, excelList,fileNm ) + + }) +} \ No newline at end of file diff --git a/apps/wr/components/ui/table/chkgdTable/guideDetailTable/guideDetailTable.tsx b/apps/wr/components/ui/table/chkgdTable/guideDetailTable/guideDetailTable.tsx index c38fc93d3..d87f4ca28 100644 --- a/apps/wr/components/ui/table/chkgdTable/guideDetailTable/guideDetailTable.tsx +++ b/apps/wr/components/ui/table/chkgdTable/guideDetailTable/guideDetailTable.tsx @@ -1,8 +1,7 @@ "use client"; -import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/page"; +import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead"; import { useWrStore } from "@/app/store"; import type { - rainChkZodType, splRuseWaterType, } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; import type { TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; @@ -30,7 +29,6 @@ export function GuideDetailsTable({ const { code, rainChkgdn } = useWrStore((state) => state); const [guidData, setGuidData] = useState<splRuseWaterType[]>(); - const nodeList = headMakeprfmnc(headList, rainChkgdn?.rainHeadNm); const handleChange = ( rowIndex: number, @@ -89,7 +87,7 @@ export function GuideDetailsTable({ <> <div className={`card !m-[1.2rem] !p-0r `}> <Table variant="secondary"> - <TableHeader className="font-bold">{nodeList}</TableHeader> + <TableHeader className="font-bold">{headMakeprfmnc(headList, rainChkgdn?.rainHeadNm)}</TableHeader> <TableBody > {tableBody(guidData ?? [])} </TableBody> diff --git a/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable.tsx b/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable.tsx index f34efa467..19a1164bd 100644 --- a/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable.tsx +++ b/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable.tsx @@ -1,167 +1,20 @@ "use client"; -import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/page"; import { useWrStore } from "@/app/store"; import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; -import type { TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import { tableData } from "@/components/lib/func/commom"; import { UiModal } from "@common/business_components/ui"; import { - Checkbox, - Input, Table, TableBody, - TableCell, TableHeader, - TableRow, } from "@common/components/ui"; import { useEffect, useState } from "react"; import ChkgdModal from "../../../modal/chkgdModal/chkgdModal"; - -export const totalData = ( - makeTableData: any[], - headList: TableUpperProps[], - handleChange: ( - rowIndex: number, - field: keyof (typeof makeTableData)[0], - value: string | number - ) => void, - toggleSelection: (pk: number, checked: boolean) => void, - selectedIds: number[], - handleCellClick: (index: number, headId: string) => void -) => { - const mergeKeys = [ - "order", - "cityText", - "sggText", - "bdstNm", - "operMngCd", - "flowCheck", - "yearFee", - "rainDtnbaOpct", - "chckYmd", - ]; - - // rowspan된 셀 렌더링 여부 추적용 - const renderedMap = new Map<string, Set<number>>(); - return ( - <> - {makeTableData.map((row, rowIndex) => ( - <TableRow key={rowIndex}> - {headList.map((head) => { - const key = head.id; - const isMerged = head.rowSpan; - const value = row[key]; - - // 병합 대상이면 중복 렌더링 여부 판단 - if (isMerged) { - const renderedSet = renderedMap.get(key) ?? new Set<number>(); - if (renderedSet.has(rowIndex)) return null; // 이미 렌더링된 셀은 skip - - const rowspan = row.rowspan ?? 1; - for (let i = 0; i < rowspan; i++) { - renderedSet.add(rowIndex + i); - } - renderedMap.set(key, renderedSet); - - return ( - <TableCell - key={key} - rowSpan={rowspan} - className="align-middle text-center whitespace-nowrap" - > - {key === "order" ? ( - <Checkbox - checked={selectedIds.includes(row.chkgdnPk)} - onCheckedChange={(checked) => - toggleSelection(row.chkgdnPk, checked === true) - } - ></Checkbox> - ) : ( - value - )} - </TableCell> - ); - } - - // 기본 셀 - return ( - <TableCell - key={key} - className="text-center whitespace-nowrap" - onClick={() => handleCellClick(rowIndex, head.id)} - > - {key === "totalSplyUswtrUtztnQnt" || - key === "totalRuseFcltUtztnQnt" || - key === "utztnUsgCd" ? ( - `${value}` - ) : ( - <Input - className={`${head.type === "number" ? "text-right" : "text-center"} text-3xl`} - type={head.type} - onChange={(e) => { - handleChange(rowIndex, head.id, e.target.value); - }} - value={value} - /> - )} - </TableCell> - ); - })} - </TableRow> - ))} - </> - ); -}; - -export const rightTableData = (rainChk: rainChkZodType[]) => { - // 1. chkgdnFk + utztnUsgCd 기준 누계 정보 만들기 - const maketotal = rainChk.map((item: any) => { - const selectTotal = item.guideDetails.reduce((acc: any, cur: any) => { - const code = cur.utztnUsgCd; - const fk = cur.chkgdnFk; - - const key = `${fk}_${code}`; - acc[key] = acc[key] || { - totalSplyUswtrUtztnQnt: 0, - totalRuseFcltUtztnQnt: 0, - }; - - acc[key].totalSplyUswtrUtztnQnt += cur.splyUswtrUtztnQnt; - acc[key].totalRuseFcltUtztnQnt += cur.ruseFcltUtztnQnt; - - return acc; - }, {}); - - return selectTotal; // 모든 키: `${chkgdnFk}_${utztnUsgCd}` 형태 - }); - - // 2. 누계 정보들을 하나의 객체로 합치기 (평탄화) - const flatTotalMap = Object.assign({}, ...maketotal); - - // 3. rainyDetails에 누계 정보 주입 - - const updatedRainyDetails: any[] = []; - rainChk.forEach((rd: any) => { - const details = rd.rainyDetails.forEach((rainyItem: any) => { - const key = `${rainyItem.chkgdnFk}_${rainyItem.utztnUsgCd}`; - const totals = flatTotalMap[key] || { - totalSplyUswtrUtztnQnt: 0, - totalRuseFcltUtztnQnt: 0, - }; - - updatedRainyDetails.push({ - ...rd, - ...rd.building, - ...rainyItem, - ...totals, - rowspan: rd.rainyDetails?.length, - }); - }); - }); - - return updatedRainyDetails; -}; - +import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead"; +import { + chRowspanTable, + rightTableData, +} from "@/components/lib/func/TableData"; export default function RainChkgdTable({ detailUp, }: { @@ -172,14 +25,14 @@ export default function RainChkgdTable({ const { rainChk } = rainChkgdn; const [selectedIds, setSelectedIds] = useState<number[]>([]); const [upRaintDetail, setUpRaintDetail] = useState<rainChkZodType[]>([]); - const [isModal, setIsModal] = useState({open:false, data:{}}); + const [isModal, setIsModal] = useState({ open: false, data: {} }); const handleCellClick = (index: number, headId: string) => { if ( headId === "totalSplyUswtrUtztnQnt" || headId === "totalRuseFcltUtztnQnt" ) { - setIsModal({open:true, data: makeTableData[index]}); + setIsModal({ open: true, data: makeTableData[index] }); } }; @@ -200,10 +53,7 @@ export default function RainChkgdTable({ ); }; - const nodeList = headMakeprfmnc( - rainChkgdn?.rainChkgdnHeadList, - rainChkgdn?.rainHeadNm - ); + useEffect(() => { const rainChg = rainChk.map((item: any) => { @@ -219,8 +69,6 @@ export default function RainChkgdTable({ setMakeTableData(rightTableData(rainChg)); }, [rainChk, code]); - - useEffect(() => { const selectedData = makeTableData.filter((item) => selectedIds.includes(item.chkgdnPk) @@ -271,10 +119,15 @@ export default function RainChkgdTable({ return ( <> <Table variant="secondary"> - <TableHeader className="font-bold">{nodeList}</TableHeader> + <TableHeader className="font-bold"> + {headMakeprfmnc( + rainChkgdn?.rainChkgdnHeadList, + rainChkgdn?.rainHeadNm + )} + </TableHeader> <TableBody> - {totalData( + {chRowspanTable( makeTableData, rainChkgdn.rainChkgdnHeadList, handleChange, @@ -288,10 +141,10 @@ export default function RainChkgdTable({ <UiModal open={isModal.open} onOpenChange={() => { - setIsModal({ open:!open , data:{} }); + setIsModal({ open: !open, data: {} }); }} bodyClass={"w-[80vw] max-w-none"} - body={<ChkgdModal type={"RNB"} obj={isModal.data} />} + body={<ChkgdModal type={"RNB"} obj={isModal.data} />} ></UiModal> </> ); diff --git a/apps/wr/public/sample.xlsx b/apps/wr/public/sample.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ee4b23edbed49636ca8244b1ba1ed4829b24699a GIT binary patch literal 15020 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 literal 0 HcmV?d00001 diff --git a/apps/wr/public/sample_rainSttn.xlsx b/apps/wr/public/sample_rainSttn.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..006e06aba139750794657eec83dcb725105d9c8d GIT binary patch literal 9091 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 |Bm^zX<-R5Wa@K&Yb^&zQOw&`Z|w(&G0(I z`iFsw;4g;%U%vI4@OAd{58=uGAp9p6dd>3s1o?;Mj06Dqf1D?(3NT=`|6Hv>0?dMa KCztHc+kXMYgj1FP literal 0 HcmV?d00001 diff --git a/apps/wr/public/sample_rainSttn_test.xlsx b/apps/wr/public/sample_rainSttn_test.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..57ea2f2229f1b936624c59999803b51aa76396a1 GIT binary patch literal 8482 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 literal 0 HcmV?d00001 From 2bf254eb3c9d6e64deb1e9c5d9aeb1402f263dbf Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Tue, 29 Apr 2025 10:27:44 +0900 Subject: [PATCH 16/29] =?UTF-8?q?excel=20=ED=8C=8C=EC=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=EB=A1=9C=20?= =?UTF-8?q?=EB=84=A3=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/excel_download/index.tsx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/common/business_components/src/ui/excel_download/index.tsx b/packages/common/business_components/src/ui/excel_download/index.tsx index 7ebc53e2d..75b6485b6 100644 --- a/packages/common/business_components/src/ui/excel_download/index.tsx +++ b/packages/common/business_components/src/ui/excel_download/index.tsx @@ -50,7 +50,10 @@ export const filePicked=(oFile: File, headerNum:number=0):Promise<JSON | undefin reader.readAsBinaryString(oFile); }); } -export const filePickedBlob=(oFile: ArrayBuffer, data:JSON[], headerNum:number=0):Promise<JSON | undefined> =>{ + + + +export const filePickedBlob=(oFile: ArrayBuffer, data:JSON[],fileNm:string, headerNum:number=0):Promise<JSON | undefined> =>{ // Create A File Reader HTML5 return new Promise<JSON | undefined>((resolve) => { // Ready The Event For When A File Gets Selected @@ -62,14 +65,16 @@ export const filePickedBlob=(oFile: ArrayBuffer, data:JSON[], headerNum:number=0 if(index==0){ const sheet = wb.Sheets[sheetName]; if (sheet) { - XLSX.utils.sheet_add_json(sheet,data); + //오리진 확인 test 필요 + // XLSX.utils.sheet_add_json(sheet,data ,{origin: 3} ); + XLSX.utils.sheet_add_json(sheet,data ); jsonXls = XLSX.utils.sheet_to_json(sheet, { range: headerNum }) as unknown as JSON; - XLSX.writeFile(wb, "test.xlsx"); + XLSX.writeFile(wb, `${fileNm}.xlsx`); } else { console.error(`Sheet "${sheetName}" is undefined.`); } } }); resolve(jsonXls); - }); -} \ No newline at end of file + }); + } \ No newline at end of file From ae53bd43ce128ce3773fc792e65568762661946b Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Tue, 29 Apr 2025 10:53:50 +0900 Subject: [PATCH 17/29] =?UTF-8?q?=EC=97=91=EC=85=80=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=20=ED=95=98=EB=8A=94=20=EB=B6=80=EB=B6=84=20aoa=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruseFcltMng/fcltSttn/rainSttn/page.tsx | 12 +- .../store/ruseFcltMng/fcltSttn/sttn/excel.tsx | 191 +++--------------- .../store/ruseFcltMng/fcltSttn/sttn/index.tsx | 5 +- apps/wr/components/lib/func/commom.tsx | 8 +- 4 files changed, 39 insertions(+), 177 deletions(-) diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index aa5fd43e0..84fbdbd5c 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -2,17 +2,15 @@ "use client"; import { useWrStore } from "@/app/store"; import { btnClass } from "@/app/store/common/code"; -import type { TableTripleProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import { excelDownload, tableData } from "@/components/lib/func/commom"; import HeadChModal from "@/components/ui/modal/headChModal/headChModal"; import { ContentsDiv, - filePickedBlob, SearchBaseForm, Title, UiModal, UiTable, - type ReturnType, + type ReturnType } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button } from "@common/components/ui"; @@ -65,11 +63,11 @@ export default function RainSttn() { }, [code, rainRes, sttnCommon.rainSttHeadList]); useEffect(() => { if(sttnCommon.excelList.length>0){ - if (sttnCommon.excelList.length === 0) return; - excelDownload(sttnCommon.excelList , '빗물재이용시설 현황','sample_rainSttn_test.xlsx') + console.log('sttnCommon.excelList', sttnCommon.excelList); + + if (sttnCommon.excelList.length === 0) return; + excelDownload(sttnCommon.excelList , '빗물재이용시설 현황','sample_rainSttn.xlsx') } - - }, [sttnCommon.excelList]); const excelClick = useCallback((returnType:ReturnType) => { diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx index 5f4cc83ba..264e3b6cc 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx @@ -1,166 +1,33 @@ -import type { customRainBdst } from "../../fcltReg/rainReg" +import type { customRainBdst } from "../../fcltReg/rainReg"; -export type ExcelSttnRainType={ - "1.건축물정보": { - "행정구역":{"시도": string, "시군구": string}, - "건축물명": string, - "주소": string, - "건축물용도코드": string, - "최초건축허가일": string, - "건축면적": string, - "법적의무대상": string, - "설치완료일시": string, - }, - "2.빗물이용시설정보":{ - "설치비용": string, - "집수면":{ - "집수지점종류": string, - "집수지점면적": string, - }, - "여과등 처리시설":{ - "여과처리시설유무": string, - "여과처리시설용량": string, - "여과처리시설처리공정": string, - }, - "저류조용량": string, - }, - - "3.인센티브 정보":{ - "설치비지원":{ - "설치지원비용여부": string, - "설치지원비용": string, - }, - - "녹색건축물인증여부":{ - "녹색건축물인증여부": string, - "녹색건축물인증년도": string, - "녹색건축물인증번호": string, - "녹색건축물인증등급": string, - } - } -} +export const excelSttnParsing = (data: customRainBdst[]): string[][] => { + const excelExportData: string[][] = []; -export const excelSttnParsing = (data: customRainBdst[]): ExcelSttnRainType[] => { - const excelExportData: ExcelSttnRainType[] = [] data.forEach((item) => { - excelExportData.push( - { - "1.건축물정보": { - "행정구역":{"시도": String(item.ctpvCd), "시군구": String(item.sggCd)}, - "건축물명": item.bdstNm, - "주소": item.daddr, - "건축물용도코드": String(item.bdstInfoPk), - "최초건축허가일":String(item.frstArchPrmsnDt), - "건축면적": String(item.archArea), - "법적의무대상": String(item.reuseBuilding[0]?.lawTrgtYn??''), - "설치완료일시": String(item.reuseBuilding[0]?.instlCmptnDt??''), - }, - "2.빗물이용시설정보":{ - "설치비용": String(item.reuseBuilding[0]?.instlCst??''), - "집수면":{ - "집수지점종류": item.reuseBuilding[0]?.rainyObj.pntfColKnd??'', - "집수지점면적": String(item.reuseBuilding[0]?.rainyObj.pntfColArea??''), - }, - "여과등 처리시설":{ - "여과처리시설유무": String(item.reuseBuilding[0]?.rainyObj.filtrTrtmfctYn??''), - "여과처리시설용량": String(item.reuseBuilding[0]?.rainyObj.filtrTrtmfctCpct??''), - "여과처리시설처리공정":String(item.reuseBuilding[0]?.rainyObj.filtrTrtmfctPrs??''), - }, - "저류조용량": String(item.reuseBuilding[0]?.rainyObj.dtfcltCpct??''), - }, - "3.인센티브 정보":{ - "설치비지원":{ - "설치지원비용여부": String(item.reuseBuilding[0]?.instlCstSprtYn ) , - "설치지원비용": String(item.reuseBuilding[0]?.instlCstSprtAmt ), - }, - "녹색건축물인증여부":{ - "녹색건축물인증여부": String(item.reuseBuilding[0]?.grntchBdstCertYn) , - "녹색건축물인증년도": String(item.reuseBuilding[0]?.grntchBdstCertYr), - "녹색건축물인증번호": String(item.reuseBuilding[0]?.grntchBdstCertNo), - "녹색건축물인증등급": String(item.reuseBuilding[0]?.grntchBdstCertGrd), - } - } - }) - }); - - console.log(excelExportData) - // excelItem = {} as ExcelSttnRainType - // excelItem["1.건축물정보"]["행정구역"]["시도"] = item.sidoNm - // excelItem["1.건축물정보"]["행정구역"]["시군구"] = item.sggNm - return excelExportData; -} - - - - -export type ExcelSttnRainTypeFlat = { - 행정구역: string; - 건축물명: string; - 주소: string; - 건축물용도코드: string; - 최초건축허가일: string; - 건축면적: string; - 법적의무대상: string; - 설치완료일시: string; - - 설치비용: string; - 집수면: string; - 여과등처리시설: string; - 저류조용량: string; - - 운영관리코드?: string; - 연간빗물운영량?: string; - - 설치지원비용여부: string; - 설치지원비용: string; - - 녹색건축물인증여부: string; - }; - - -export const excelSttnParsingJson = (data: customRainBdst[]): ExcelSttnRainTypeFlat[] => { - const excelExportData: ExcelSttnRainTypeFlat[] = []; - - data.forEach((item) => { - excelExportData.push({ - // 1.건축물정보 - "행정구역": JSON.stringify({ - 시도: String(item.ctpvCd), - 시군구: String(item.sggCd) - }), - "건축물명": item.bdstNm ?? "", - "주소": item.daddr ?? "", - "건축물용도코드": String(item.bdstInfoPk ?? ""), - "최초건축허가일": String(item.frstArchPrmsnDt ?? ""), - "건축면적": String(item.archArea ?? ""), - "법적의무대상": String(item.reuseBuilding?.[0]?.lawTrgtYn ?? ""), - "설치완료일시": String(item.reuseBuilding?.[0]?.instlCmptnDt ?? ""), - - // 2.빗물이용시설정보 - "설치비용": String(item.reuseBuilding?.[0]?.instlCst ?? ""), - "집수면": JSON.stringify({ - 집수지점종류: item.reuseBuilding?.[0]?.rainyObj?.pntfColKnd ?? "", - 집수지점면적: String(item.reuseBuilding?.[0]?.rainyObj?.pntfColArea ?? "") - }), - "여과등처리시설": JSON.stringify({ - 여과처리시설유무: String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctYn ?? ""), - 여과처리시설용량: String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctCpct ?? ""), - 여과처리시설처리공정: String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctPrs ?? "") - }), - "저류조용량": String(item.reuseBuilding?.[0]?.rainyObj?.dtfcltCpct ?? ""), - - // 3.인센티브 정보 - "설치지원비용여부": String(item.reuseBuilding?.[0]?.instlCstSprtYn ?? ""), - "설치지원비용": String(item.reuseBuilding?.[0]?.instlCstSprtAmt ?? ""), - - "녹색건축물인증여부": JSON.stringify({ - 녹색건축물인증여부: String(item.reuseBuilding?.[0]?.grntchBdstCertYn ?? ""), - 녹색건축물인증년도: String(item.reuseBuilding?.[0]?.grntchBdstCertYr ?? ""), - 녹색건축물인증번호: String(item.reuseBuilding?.[0]?.grntchBdstCertNo ?? ""), - 녹색건축물인증등급: String(item.reuseBuilding?.[0]?.grntchBdstCertGrd ?? "") - }), + excelExportData.push([ + String(item.ctpvCd), + String(item.sggCd), + item.bdstNm ?? "", + item.daddr ?? "", + String(item.bdstInfoPk ?? ""), + String(item.frstArchPrmsnDt ?? ""), + String(item.archArea ?? ""), + String(item.reuseBuilding?.[0]?.lawTrgtYn ?? ""), + String(item.reuseBuilding?.[0]?.instlCmptnDt ?? ""), + String(item.reuseBuilding?.[0]?.instlCst ?? ""), + item.reuseBuilding?.[0]?.rainyObj?.pntfColKnd ?? "", + String(item.reuseBuilding?.[0]?.rainyObj?.pntfColArea ?? ""), + String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctYn ?? ""), + String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctCpct ?? ""), + String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctPrs ?? ""), + String(item.reuseBuilding?.[0]?.rainyObj?.dtfcltCpct ?? ""), + String(item.reuseBuilding?.[0]?.instlCstSprtYn ?? ""), + String(item.reuseBuilding?.[0]?.instlCstSprtAmt ?? ""), + String(item.reuseBuilding?.[0]?.grntchBdstCertYn ?? ""), + String(item.reuseBuilding?.[0]?.grntchBdstCertYr ?? ""), + String(item.reuseBuilding?.[0]?.grntchBdstCertNo ?? ""), + String(item.reuseBuilding?.[0]?.grntchBdstCertGrd ?? "") + ]); }); - }); - - return excelExportData; - }; \ No newline at end of file + return excelExportData; +}; diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx index 7972a949b..590c4574b 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx @@ -1,11 +1,11 @@ import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; +import { fetchType, getFetch } from "@/components/lib/api"; import { type customRainBdst, type TableTripleProps, type TableUpperProps, } from "../../fcltReg/rainReg"; -import { excelSttnParsing, excelSttnParsingJson, type ExcelSttnRainType, type FlatExcelSttnRainType } from "./excel"; -import { fetchType, getFetch } from "@/components/lib/api"; +import { excelSttnParsing, type ExcelSttnRainType } from "./excel"; const pbnSttHeadNm: chHeadType[] = [ { headNm: "catchment", text: "유역", length: 3 }, @@ -341,7 +341,6 @@ export const sttnActionsExport: (set: any) => sttnActions = (set: any) => { `/reuseFc/rainyInfoList/${page}/${total}/${con}` ); if(Number(total) > 9000){ - //const rainExcel= excelSttnParsing(rainRes) const rainExcel= excelSttnParsing(rainRes) set((state: sttnState) => { return { diff --git a/apps/wr/components/lib/func/commom.tsx b/apps/wr/components/lib/func/commom.tsx index 6f18a5810..d9282a9a6 100644 --- a/apps/wr/components/lib/func/commom.tsx +++ b/apps/wr/components/lib/func/commom.tsx @@ -1,4 +1,4 @@ -import type { comCodeState, } from "@/app/store/common/code"; +import type { comCodeState, } from "@/app/store/common/code"; import { filePickedBlob, type SelectDataType } from "@common/business_components/ui"; @@ -49,8 +49,7 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => { - export const excelDownload =(excelList: JSON[], fileNm:string ,sampleFile:string ) =>{ - console.log("excelList", excelList); + export const excelDownload =(excelList: [][], fileNm:string ,sampleFile:string ) =>{ if (excelList.length === 0) return; fetch(`/${sampleFile}`, {}) .then(async (response) => { @@ -60,7 +59,6 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => { // 받은 파일 바인너리 처리 const blobRet = await response.arrayBuffer() // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 - const ret =await filePickedBlob(blobRet, excelList,fileNm ) - + await filePickedBlob(blobRet, excelList,fileNm, 4) }) } \ No newline at end of file From daba76721ed61772f64c07e912d943f698c05b38 Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Tue, 29 Apr 2025 10:54:29 +0900 Subject: [PATCH 18/29] =?UTF-8?q?=EC=97=91=EC=85=80=20blob=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/excel_download/index.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/common/business_components/src/ui/excel_download/index.tsx b/packages/common/business_components/src/ui/excel_download/index.tsx index 75b6485b6..46f8b7cb1 100644 --- a/packages/common/business_components/src/ui/excel_download/index.tsx +++ b/packages/common/business_components/src/ui/excel_download/index.tsx @@ -53,12 +53,11 @@ export const filePicked=(oFile: File, headerNum:number=0):Promise<JSON | undefin -export const filePickedBlob=(oFile: ArrayBuffer, data:JSON[],fileNm:string, headerNum:number=0):Promise<JSON | undefined> =>{ +export const filePickedBlob=(oFile: ArrayBuffer, data:[][],fileNm:string, headerNum:number=0):Promise<JSON | undefined> =>{ // Create A File Reader HTML5 - return new Promise<JSON | undefined>((resolve) => { + return new Promise<JSON | undefined>(() => { // Ready The Event For When A File Gets Selected const wb = XLSX.read(oFile, { type: 'binary' }); - let jsonXls: JSON | undefined; // Loop Over Each Sheet wb.SheetNames.forEach(function (sheetName, index) { // Obtain The Current Row As CSV @@ -66,15 +65,14 @@ export const filePickedBlob=(oFile: ArrayBuffer, data:JSON[],fileNm:string, head const sheet = wb.Sheets[sheetName]; if (sheet) { //오리진 확인 test 필요 - // XLSX.utils.sheet_add_json(sheet,data ,{origin: 3} ); - XLSX.utils.sheet_add_json(sheet,data ); - jsonXls = XLSX.utils.sheet_to_json(sheet, { range: headerNum }) as unknown as JSON; + // const sheet = XLSX.utils.json_to_sheet(data); + XLSX.utils.sheet_add_aoa(sheet, data, { origin: 'A'+headerNum }); + // XLSX.utils.book_append_sheet(wb, sheet, 'test'); XLSX.writeFile(wb, `${fileNm}.xlsx`); } else { console.error(`Sheet "${sheetName}" is undefined.`); } } }); - resolve(jsonXls); }); } \ No newline at end of file From 945e21c6a57af81cc54c0ece0439e9d5b9344608 Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Tue, 29 Apr 2025 19:41:09 +0900 Subject: [PATCH 19/29] =?UTF-8?q?=EC=97=91=EC=85=80=EC=97=85=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=95=84=EC=9A=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruseFcltMng/fcltSttn/rainSttn/page.tsx | 2 +- .../ruseFcltMng/prfmncReg/chkgdnReg/page.tsx | 28 +- .../prfmncReg/chkgdnReg/rainChkgdn/excel.tsx | 244 ++++++++++-------- .../prfmncReg/chkgdnReg/rainChkgdn/index.tsx | 90 ++++--- .../store/ruseFcltMng/fcltSttn/sttn/index.tsx | 4 +- apps/wr/components/lib/func/commom.tsx | 17 +- .../ui/modal/chkgdExcel/chkgdExcel.tsx | 76 +++--- .../ui/modal/chkgdModal/chkgdModal.tsx | 2 +- 8 files changed, 268 insertions(+), 195 deletions(-) diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index 84fbdbd5c..371e03075 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -18,7 +18,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { headMakeTriple } from "./TableHead"; export default function RainSttn() { - const { code, sttnCommon, excelExportAction, rainSttnSearch } = + const { code, sttnCommon, rainSttnSearch } = useWrStore((state) => state); const { rainRes } = sttnCommon; diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx index 5d8889db1..cd915e33b 100644 --- a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx @@ -30,13 +30,11 @@ import { useCallback, useEffect, useState } from "react"; //----------------------- export default function Page() { - const { code, rainChkgdn, rainChkInit,rainChkDetilUpdate, excelExportAction } = useWrStore((state) => { + const { code, rainChkgdn, rainChkInit,rainChkDetilUpdate, rainChkExcelDownload } = useWrStore((state) => { return state; }); - const [isDetail, setIsDetail] = useState(false); - const [isExcel, setIsExcel] = useState(false); + const [isRegExcel, setIsRegExcel] = useState(false); const [searchTxt, setSearchTxt] = useState<string>(); - const [testObj, setTestObj] = useState({}); const [updateRainDetail, setUpdateRainDetail] = useState<rainChkZodType[]>([]); const [selFcltDiv, setSelFcltDiv] = useState("RNB"); @@ -53,13 +51,15 @@ export default function Page() { }, [rainChkgdn.isInit, rainChkInit]); + + useEffect(() => { - excelDownload(rainChkgdn.excelList); + excelDownload(rainChkgdn.excelList ,'빗물이용시설 지도점검','sample_rainy.xlsx'); }, [rainChkgdn.excelList]); const excelClick= useCallback(()=>{ - excelExportAction(code.cityCd, code.sggCd); - }, [excelExportAction, code.cityCd, code.sggCd]); + rainChkExcelDownload(code.cityCd, code.sggCd); + }, [excelDownload, code.cityCd, code.sggCd]); return ( @@ -103,7 +103,7 @@ export default function Page() { </Button> </div> <div className="flex flex-row space-x-2 pt-3"> - <Button size={"sm"} onClick={() => {}}> + <Button size={"sm"} onClick={() => {setIsRegExcel(!isRegExcel)}}> 결과등록 </Button> <Button @@ -126,17 +126,11 @@ export default function Page() { </ListDiv> </div> </div> + <UiModal - open={isDetail} - onOpenChange={setIsDetail} - bodyClass={"w-[40vw] max-w-none"} - body={<ChkgdModal type={selFcltDiv} obj={testObj}></ChkgdModal>} - /> - - <UiModal - open={isExcel} - onOpenChange={setIsExcel} + open={isRegExcel} + onOpenChange={setIsRegExcel} bodyClass={"w-[40vw] max-w-none"} body={<ChkgdExcel type={selFcltDiv}></ChkgdExcel>} /> diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx index ead156cb2..24c8cdebc 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx @@ -1,117 +1,133 @@ -import type { SelectDataType } from "@common/business_components" +import type { SelectDataType } from "@common/business_components"; +import type { rainChkZodType } from "."; +import { TEST_UUID } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; +import { excelSerialToDateString } from "@/components/lib/func/commom"; const useTypes = [ - "조경용수", - "청소화장실용수", - "세척살수용수", - "농업용수", - "공업용수", - "친수용수", - "기타" -] -export type ExcelExportType = { - "NO": string, - "시도": string, - "시군구": string, - "상세주소": string, - "시설명": string, - "운영관리형태": string, - "유량측정방법": string, - "연간운영비(원/년)": string, - "점검일": string, - "이용용도": string, - "보급_1월": string, - "보급_2월": string, - "보급_3월": string, - "보급_4월": string, - "보급_5월": string, - "보급_6월": string, - "보급_7월": string, - "보급_8월": string, - "보급_9월": string, - "보급_10월": string, - "보급_11월": string, - "보급_12월": string, - "빗물_1월": string, - "빗물_2월": string, - "빗물_3월": string, - "빗물_4월": string, - "빗물_5월": string, - "빗물_6월": string, - "빗물_7월": string, - "빗물_8월": string, - "빗물_9월": string, - "빗물_10월": string, - "빗물_11월": string, - "빗물_12월": string, - "PH": string, - "탁도": string, - "총대장균군수": string, - "과태료 부과일(위반일)": string, - "위반사항": string, - "과태료부과금액(천원)": string -} - + "조경용수", + "청소화장실용수", + "세척살수용수", + "농업용수", + "공업용수", + "친수용수", + "기타", +]; export type Buildingtype = { - bdstInfoPk: number, - ctpvCd: 1, - sggCd: 1001, - daddr: "string3", - bdstNm: "string", - frstArchPrmsnDt: "2025-03-25", - archArea: 0, - regDt: "2025-04-16", - rgtr: null, - mdfcnDt: "2025-04-16", - mdfr: null -} -export const buildingToExcelType = (buildings: Buildingtype[], sidoCode: SelectDataType[], sggCdoe: SelectDataType[]) => { - const excelData: ExcelExportType[] = []; - buildings.forEach((building) => { - useTypes.forEach((useType) => { - excelData.push({ - NO: building.bdstInfoPk.toString(), - 시도: sidoCode.find((sido) => sido.val === building.ctpvCd.toString())?.text || "", - 시군구: sggCdoe.find((sido) => sido.val === building.sggCd.toString())?.text || "", - 상세주소: building.daddr, - 시설명: building.bdstNm, - 운영관리형태: "", - 유량측정방법: "", - '연간운영비(원/년)': "", - 점검일: "", - 이용용도: useType, - 보급_1월: "", - 보급_2월: "", - 보급_3월: "", - 보급_4월: "", - 보급_5월: "", - 보급_6월: "", - 보급_7월: "", - 보급_8월: "", - 보급_9월: "", - 보급_10월: "", - 보급_11월: "", - 보급_12월: "", - 빗물_1월: "", - 빗물_2월: "", - 빗물_3월: "", - 빗물_4월: "", - 빗물_5월: "", - 빗물_6월: "", - 빗물_7월: "", - 빗물_8월: "", - 빗물_9월: "", - 빗물_10월: "", - 빗물_11월: "", - 빗물_12월: "", - PH: "", - 탁도: "", - 총대장균군수: "", - "과태료 부과일(위반일)": "", - 위반사항: "", - "과태료부과금액(천원)": "" - }) - }) - }) - return excelData; -} \ No newline at end of file + bdstInfoPk: number; + ctpvCd: 1; + sggCd: 1001; + daddr: "string3"; + bdstNm: "string"; + frstArchPrmsnDt: "2025-03-25"; + archArea: 0; + regDt: "2025-04-16"; + rgtr: null; + mdfcnDt: "2025-04-16"; + mdfr: null; +}; + +export const buildingToExcelType = ( + buildings: Buildingtype[], + sidoCode: SelectDataType[], + sggCdoe: SelectDataType[] +) => { + const excelData: string[][] = []; + buildings.forEach((building) => { + useTypes.forEach((useType) => { + excelData.push([ + building.bdstInfoPk.toString(), + sidoCode.find((sido) => sido.val === building.ctpvCd.toString()) + ?.text || "", + sggCdoe.find((sido) => sido.val === building.sggCd.toString())?.text || + "", + building.daddr, + building.bdstNm, + "", + "", + "", + "", + useType, + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ]); + }); + }); + return excelData; +}; + +export const excelToRainChkData = ( + excelData: any, + year: string, +) => { + + const rainChkgdData: rainChkZodType[] = excelData.map((item: any) => { + const makeGuidDetail = Array.from({ length: 12 }, (_, i) => { + let month = `${i + 1}`; + const splyData = item[`보급_${month}월`]; + const ruseData = item[`빗물_${month}월`]; + if (month.length < 2) month = "0" + month; + return { + utztnUsgCd: item["이용용도"], + ym: year + month, + chckYmd: excelSerialToDateString(item["점검일"]) , + splyUswtrUtztnQnt: splyData !== undefined ? splyData : 0, + ruseFcltUtztnQnt: ruseData !== undefined ? ruseData : 0, + flg: "RNB", + }; + }); + + return { + bdstRuseFcltFk: Number(item["NO"]), + chckYmd: excelSerialToDateString(item["점검일"]) , + spwtPositn: item["유량측정방법"], + rgtr: TEST_UUID, + oilqMeasMthd: item["운영관리형태"], + anlOperCst: Number(item["연간운영비(원/년)"])??0, + operMngCd: item["유량측정방법"], + guideDetails: makeGuidDetail, + rainyDetails: [ + { + utztnUsgCd: item["이용용도"], + ph: Number(item["PH"])??0, + trbt: Number(item["탁도"])??0, + grssClfg: Number(item["총대장균군수"])??0, + etc: item["기타"] ?? "", // 필드 누락 방지 + vltnDt: item["과태료 부과일(위반일)"], + vltnMttr: item["위반사항"], + levyAmt: Number(item["과태료부과금액(천원)"])??0, + rgtr: TEST_UUID, + }, + ], + }; + }); + + return rainChkgdData; +}; diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx index f8832a220..5a74d104d 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx @@ -5,22 +5,22 @@ import { import { fetchType, getFetch, postFectch, putFectch } from "@/components/lib/api"; import type { SelectDataType } from "@common/business_components/ui"; import { z } from "zod"; -import { buildingToExcelType, type ExcelExportType } from "./excel"; +import { buildingToExcelType, excelToRainChkData } from "./excel"; export const rainChkZod = z.object({ - chkgdnPk: z.number(), + chkgdnPk: z.number().nullable(), bdstRuseFcltFk: z.number(), chckYmd: z.string(), - prcsCpct: z.number(), - spwtPositn: z.string(), - regDt: z.string(), - rgtr: z.string(), + prcsCpct: z.number().nullable(), + spwtPositn: z.string().nullable(), + regDt: z.string().nullable(), + rgtr: z.string().nullable(), mdfcnDt: z.string().nullable(), mdfr: z.string().nullable(), - flg: z.string(), + flg: z.string().nullable(), guideDetails: z.array( z.object({ - chkgdnFk: z.number(), + chkgdnFk: z.number().nullable(), utztnUsgCd: z.string(), chckYmd: z.string(), ym: z.string(), @@ -41,20 +41,20 @@ export const rainChkZod = z.object({ rgtr: z.string().nullable(), mdfcnDt: z.string().nullable(), mdfr: z.string().nullable(), - }), + }).nullable() , rainyDetails: z.array( z.object({ - chkgdnFk: z.number(), + chkgdnFk: z.number().nullable(), utztnUsgCd: z.string(), - ph: z.number(), - trbt: z.number(), - grssClfg: z.number(), - etc: z.string(), - vltnDt: z.string(), - vltnMttr: z.string(), - levyAmt: z.number(), - regDt: z.string(), - rgtr: z.string(), + ph: z.number().nullable(), + trbt: z.number().nullable(), + grssClfg: z.number().nullable(), + etc: z.string().nullable(), + vltnDt: z.string().nullable(), + vltnMttr: z.string().nullable(), + levyAmt: z.number().nullable(), + regDt: z.string().nullable(), + rgtr: z.string().nullable(), mdfcnDt: z.string().nullable(), mdfr: z.string().nullable(), }) @@ -65,12 +65,22 @@ export type rainChkZodType = z.infer<typeof rainChkZod>; export const rainRegExcel = z.object({ bdstInfoPk: z.number().default(111111111), - chckYr: z .string().default("") - .refine((year) =>year.length ===0 || /^\d{4}$/.test(year),{ - message:'4자리 연도만 입력하세요' - }), - file: z.instanceof(File).optional(), -}); + chckYr: z.string() + .default("") + .refine( + (year) => year.length === 0 || /^\d{4}$/.test(year), + { message: "4자리 연도만 입력하세요" } + ) + .refine( + (year) => { + if (year.length === 0) return true; // 빈 문자열은 통과 + const numYear = Number(year); + return !isNaN(numYear) && numYear <= new Date().getFullYear(); + }, + { message: "현재 년도보다 높은 수를 입력할 수 없습니다." } + ), +file: z.instanceof(File).optional(), +}); export const fcltDiv = [ { val: "RST", text: "중수도시설" }, @@ -288,7 +298,7 @@ export type rainChkgdnState = { splHeadList: TableUpperProps[]; rswtDetailHeadList: TableUpperProps[]; isInit: boolean; - excelList:JSON[]; + excelList:[]; }; }; @@ -296,7 +306,8 @@ type rainChkgdnActions = { rainChkInit: (sggCd: string, searchTxt: string) => void; rainChkDetilUpdate(rainChk: rainChkZodType[]): Promise<void>; rainChkGuidUpdate(rainChk: rainChkZodType): Promise<void>; - excelExportAction(sidoCode: SelectDataType[],sggCode: SelectDataType[]): Promise<void> + rainChkExcelDownload(sidoCode: SelectDataType[],sggCode: SelectDataType[]): Promise<void> + excelDataUPload(excelData:rainChkZodType[]) : Promise<void> }; export type rainChkgdnType = rainChkgdnState & rainChkgdnActions; @@ -348,9 +359,11 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( set: any ) => { return { - excelExportAction:async(sidoCode:SelectDataType[], sggCode:SelectDataType[])=>{ + rainChkExcelDownload:async(sidoCode:SelectDataType[], sggCode:SelectDataType[])=>{ const data = await getFetch(fetchType.WR, "/reuseFc/building/RNB/0") - const excelList = buildingToExcelType(data, sidoCode, sggCode); + // const excelList = buildingToExcelType(data, sidoCode, sggCode); + + const excelList = buildingToExcelType(data, sidoCode, sggCode); set((state: rainChkgdnState) => ({ rainChkgdn: { ...state.rainChkgdn, @@ -358,6 +371,25 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( }, })); }, + excelDataUPload: async(excelData:rainChkZodType[] ) =>{ + try{ + const res = await postFectch("/reuseChk/rainyExcel", excelData); + if (res.ok) { + alert(" 데이터 입력 완료"); + } + const rainChkRes = await initFetch('2024', '0'); + return set((state: rainChkgdnState) => ({ + ...state, + rainChkgdn: { + ...state.rainChkgdn, + rainChk: rainChkRes, + }, + })); + }catch(error){ + console.log(error); + alert("데이터 입력을 실패하였습니다."); + } + }, rainChkInit: async (searchTxt: string, sggCd: string) => { try { const rainChkRes = await initFetch(searchTxt, sggCd); diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx index 590c4574b..d0dd648e7 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx @@ -5,7 +5,7 @@ import { type TableTripleProps, type TableUpperProps, } from "../../fcltReg/rainReg"; -import { excelSttnParsing, type ExcelSttnRainType } from "./excel"; +import { excelSttnParsing, } from "./excel"; const pbnSttHeadNm: chHeadType[] = [ { headNm: "catchment", text: "유역", length: 3 }, @@ -309,7 +309,7 @@ export type sttnState = { pbnSttHeadNm: chHeadType[]; rainSttHeadList: TableTripleProps[]; rainSttHeadNm: chHeadType[]; - excelList:ExcelSttnRainType[]; + excelList:[]; isInit:boolean }; }; diff --git a/apps/wr/components/lib/func/commom.tsx b/apps/wr/components/lib/func/commom.tsx index d9282a9a6..a25ea0278 100644 --- a/apps/wr/components/lib/func/commom.tsx +++ b/apps/wr/components/lib/func/commom.tsx @@ -61,4 +61,19 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => { // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 await filePickedBlob(blobRet, excelList,fileNm, 4) }) -} \ No newline at end of file +} + + + +//엑셀은 날짜가 숫자로 나와서 만든 함수 +export const excelSerialToDateString = (excelDate: number|undefined): string => { + const excelEpoch = new Date(1899, 11, 30); // Excel 기준일 (1900-01-01보다 하루 전) + let date + if(excelDate){ + date = new Date(excelEpoch.getTime() + excelDate * 86400000); + }else{ + date =new Date() + } + return date.toISOString().split("T")[0] || ""; // "YYYY-MM-DD" +}; + diff --git a/apps/wr/components/ui/modal/chkgdExcel/chkgdExcel.tsx b/apps/wr/components/ui/modal/chkgdExcel/chkgdExcel.tsx index 28aebe0f4..c57953781 100644 --- a/apps/wr/components/ui/modal/chkgdExcel/chkgdExcel.tsx +++ b/apps/wr/components/ui/modal/chkgdExcel/chkgdExcel.tsx @@ -1,4 +1,6 @@ -import { rainRegExcel } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; +import { useWrStore } from "@/app/store"; +import { rainChkZod, rainRegExcel, type rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; +import { excelToRainChkData } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel"; import { selectClass } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import { DatePicker, @@ -9,16 +11,18 @@ import { FormUi, Title, } from "@common/business_components/ui"; -import { Button } from "@common/components/ui"; +import { Button, Input } from "@common/components/ui"; import { zodResolver } from "@hookform/resolvers/zod"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import type { z } from "zod"; export default function ChkgdExcel({ type }: { type: string }) { - const [files, setFiles] = useState(null); - - const [dmdDate, setDmdDate] = useState(new Date()); + const { excelDataUPload } = useWrStore((state) => { + return state; + }); + const [files, setFiles] = useState<File[] | null>(null); + const [excelData , setExcelData] = useState<rainChkZodType[]>() const defaultValues: z.infer<typeof rainRegExcel> = rainRegExcel.parse({}); @@ -27,22 +31,34 @@ export default function ChkgdExcel({ type }: { type: string }) { defaultValues: defaultValues, }); - const onChangeDate = (val: Date | undefined) => { - if (val) setDmdDate(val); - }; - useEffect(() => { - if (files) { - const file = files[0]; - if(file) filePicked(file,1).then((res) => console.log(res)); - }else{ - + if (files) { + const file = files[0]; + + if(form.getValues("chckYr").length<1 ){ + alert("등록년도를 입력해주세요"); + return + } + if (file) + filePicked(file, 0).then((res) => { + if (res !== undefined) + + setExcelData(excelToRainChkData(res, form.getValues("chckYr"))) + }); + } + }, [files]); + + const onSubmit =(values: z.infer<typeof rainRegExcel>)=> { + if (excelData) { + excelDataUPload(excelData); } - }, [files]) + } + return ( <> <div> <Form {...form}> + <form onSubmit={form.handleSubmit(onSubmit)}> <div> <Title title={ @@ -57,25 +73,22 @@ export default function ChkgdExcel({ type }: { type: string }) { {"○점검정보 입력"} </h3> - <Button className="">저장</Button> + <Button className="" type="submit"> + 저장 + </Button> </div> <div> <FormField control={form.control} - name="chckYmd" + name="chckYr" render={({ field }) => ( - <FormUi label="점검일자"> - <DatePicker - mode="single" - field={{ - value: - field.value && !isNaN(new Date(field.value).getTime()) - ? new Date(field.value) - : new Date(), // Provide a default Date value - onChange: (date) => field.onChange(date), - }} - selectClass={selectClass} + <FormUi label="등록년도"> + <Input + className={`text-3xl`} + type="text" + value={field.value} + onChange={field.onChange} /> </FormUi> )} @@ -87,14 +100,17 @@ export default function ChkgdExcel({ type }: { type: string }) { render={({ field }) => ( <FormUi label="점검결과 파일"> <FileUpload - files={field.value} - setFiles={setFiles} + files={files || []} + setFiles={(files: File[] | null ) => { + if(files) setFiles(files) + } } fileTypes="xlsx" ></FileUpload> </FormUi> )} /> </div> + </form> </Form> </div> </> diff --git a/apps/wr/components/ui/modal/chkgdModal/chkgdModal.tsx b/apps/wr/components/ui/modal/chkgdModal/chkgdModal.tsx index 96b324b3c..c07a84341 100644 --- a/apps/wr/components/ui/modal/chkgdModal/chkgdModal.tsx +++ b/apps/wr/components/ui/modal/chkgdModal/chkgdModal.tsx @@ -1,10 +1,10 @@ -import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/page"; import { useWrStore } from "@/app/store"; import { ScrollArea, Title, UiTable } from "@common/business_components/ui"; import { Button } from "@common/components/ui"; import { useEffect, useState } from "react"; import { GuideDetailsTable } from "../../table/chkgdTable/guideDetailTable/guideDetailTable"; import type { splRuseWaterType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; +import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead"; export default function ChkgdModal({ type, obj }: { type: string; obj: any }) { const { rainChkgdn, rainChkDetilUpdate, rainChkGuidUpdate } = useWrStore( From 235f4bdb2966461271e0b703c4bdfed23834ffea Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Tue, 29 Apr 2025 19:43:14 +0900 Subject: [PATCH 20/29] =?UTF-8?q?=ED=8C=8C=EC=9D=BC=EC=97=85=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20and=20porps=20=EB=B0=A9=EC=8B=9D=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/excel_download/index.tsx | 6 ++++ .../src/ui/file-upload/index.tsx | 30 ++++++++++++------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/packages/common/business_components/src/ui/excel_download/index.tsx b/packages/common/business_components/src/ui/excel_download/index.tsx index 46f8b7cb1..58ecf8a52 100644 --- a/packages/common/business_components/src/ui/excel_download/index.tsx +++ b/packages/common/business_components/src/ui/excel_download/index.tsx @@ -14,6 +14,9 @@ export const downloadExcel = ({ data, fileName = new Date().getTime().toString() //XLSX.write(workbook, { bookType: "xlsx", type: "binary" }); XLSX.writeFile(workbook, fileName + '.xlsx'); }; + + + export const filePicked=(oFile: File, headerNum:number=0):Promise<JSON | undefined> =>{ // Create A File Reader HTML5 const reader = new FileReader(); @@ -28,10 +31,13 @@ export const filePicked=(oFile: File, headerNum:number=0):Promise<JSON | undefin } const wb = XLSX.read(data, { type: 'binary' }); let jsonXls: JSON | undefined; + + //TODO 시트가 2개이상일 경우 마지막 시트의 데이터만 표출됨 // Loop Over Each Sheet wb.SheetNames.forEach(function (sheetName) { // Obtain The Current Row As CSV const sheet = wb.Sheets[sheetName]; + if (sheet) { jsonXls = XLSX.utils.sheet_to_json(sheet, { range: headerNum }) as unknown as JSON; } else { diff --git a/packages/common/business_components/src/ui/file-upload/index.tsx b/packages/common/business_components/src/ui/file-upload/index.tsx index 3d581ed05..4c6dcec00 100644 --- a/packages/common/business_components/src/ui/file-upload/index.tsx +++ b/packages/common/business_components/src/ui/file-upload/index.tsx @@ -6,14 +6,22 @@ const dropZoneConfig = { maxSize: 1024 * 1024 * 4, multiple: true, }; + + + interface FileUploadProps { + files: File[]; // 파일 배열 + setFiles: (files: File[] | null) => void; // 파일 배열 세터 + fileTypes?: string; // 옵션 (파일 확장자 문자열) + } + export const FileUpload = -(({ ...props }) => { +({ files, setFiles, fileTypes }: FileUploadProps) => { return ( <FileUploader - value={props.files} - onValueChange={props.setFiles} + value={files} + onValueChange={setFiles} dropzoneOptions={dropZoneConfig} - acceptName={props?.fileTypes} + acceptName={fileTypes} className="relative bg-background rounded-lg p-2" > <FileInput @@ -23,18 +31,18 @@ export const FileUpload = <div className="flex items-center justify-center flex-col p-8 w-full "> <CloudUpload className='text-gray-500 w-10 h-10' /> <p className="mb-1 text-sm text-gray-500 dark:text-gray-400"> - <span className="font-semibold">Click to upload</span> -   or drag and drop + <span className="font-semibold">클릭 후 업로드 </span> +   혹은 파일을 드래그 해주세요 </p> <p className="text-xs text-gray-500 dark:text-gray-400"> - {!props?.fileTypes?"SVG, PNG, JPG, GIF":props?.fileTypes} + {!fileTypes?"SVG, PNG, JPG, GIF":fileTypes} </p> </div> </FileInput> <FileUploaderContent> - {props.files && - props.files.length > 0 && - props.files.map((file:File, i:number) => ( + {files&& + files.length > 0 && + files.map((file:File, i:number) => ( <FileUploaderItem key={i} index={i}> <Paperclip className="h-4 w-4 stroke-current" /> <span>{file.name}</span> @@ -43,4 +51,4 @@ export const FileUpload = </FileUploaderContent> </FileUploader> ) -}) \ No newline at end of file +} \ No newline at end of file From bf2eade3114e47b3fa093665cdea3f7f095d5655 Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Tue, 29 Apr 2025 19:46:06 +0900 Subject: [PATCH 21/29] =?UTF-8?q?=EC=98=A8=EB=B0=B0=EC=88=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wr/app/ruseFcltMng/fcltReg/htdflReg/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wr/app/ruseFcltMng/fcltReg/htdflReg/page.tsx b/apps/wr/app/ruseFcltMng/fcltReg/htdflReg/page.tsx index 233d2ed53..b252121dc 100644 --- a/apps/wr/app/ruseFcltMng/fcltReg/htdflReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltReg/htdflReg/page.tsx @@ -13,7 +13,6 @@ import { UiTable, } from "@common/business_components"; import { Button } from "@common/components"; -import { headMakeColSpan } from "../rainReg/page"; import ListDiv from "@common/business_components/ui/list_div"; import { useEffect, useState } from "react"; import { tableData } from "@/components/lib/func/commom"; @@ -22,6 +21,7 @@ import type { chgBuilding } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import BdstChgModal from "@/components/ui/modal/bdstChgModal/bdstChgModal"; import { BdstReg } from "@/components/ui/modal/bdstRegModal/bdstRegModal"; import type { customHtdflBdst } from "@/app/store/ruseFcltMng/fcltReg/htdflReg"; +import { headMakeColSpan } from "../rainReg/TableHead"; export default function Home() { const { code, htdfl, initHtdfl } = useWrStore((state) => state); From 05daa4200d90d1bfb4378651bdee37ce62c98930 Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Wed, 30 Apr 2025 15:57:59 +0900 Subject: [PATCH 22/29] =?UTF-8?q?=EC=97=91=EC=85=80=20=EC=83=81=EB=8B=A8?= =?UTF-8?q?=20=EC=83=89=EC=83=81=20=EB=84=A3=EB=8A=94=20=EB=B6=80=EB=B6=84?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80.=20=EC=97=91=EC=85=80=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=EC=8B=9C=20=EB=AA=A8=EB=8B=AC=20=EB=9D=84=EC=9A=B0?= =?UTF-8?q?=EB=8A=94=20=EB=B6=80=EB=B6=84=20=EB=AA=A8=EB=93=88=ED=99=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruseFcltMng/prfmncReg/chkgdnReg/page.tsx | 24 ++--- .../prfmncReg/chkgdnReg/rainChkgdn/index.tsx | 22 ++--- apps/wr/components/lib/config/index.ts | 4 +- apps/wr/components/lib/func/TableData.tsx | 17 ++-- apps/wr/components/lib/func/commom.tsx | 5 +- .../chkgdTable/rainChkgd/rainChkgdTable.tsx | 88 ++++++++----------- .../rainChkgd/rainChkgdTableModal.tsx | 13 +++ 7 files changed, 84 insertions(+), 89 deletions(-) create mode 100644 apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTableModal.tsx diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx index cd915e33b..2e93680a1 100644 --- a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx @@ -3,18 +3,15 @@ import { useWrStore } from "@/app/store"; import { fcltDiv, - type chHeadType, - type rainChkZodType, + type rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; -import type { TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import { excelDownload } from "@/components/lib/func/commom"; import ChkgdExcel from "@/components/ui/modal/chkgdExcel/chkgdExcel"; -import ChkgdModal from "@/components/ui/modal/chkgdModal/chkgdModal"; import RainChkgdTable from "@/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable"; +import RainChkgdTableModal from "@/components/ui/table/chkgdTable/rainChkgd/rainChkgdTableModal"; import RswtChkgdTable from "@/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable"; import { ContentsDiv, - filePickedBlob, SearchDiv, SearchFormLeft, SearchFormRight, @@ -37,7 +34,10 @@ export default function Page() { const [searchTxt, setSearchTxt] = useState<string>(); const [updateRainDetail, setUpdateRainDetail] = useState<rainChkZodType[]>([]); const [selFcltDiv, setSelFcltDiv] = useState("RNB"); - + const [isModal, setIsModal] = useState({ + open: false, + data: {}, + }); const cellClick = () => { if(searchTxt) rainChkInit(searchTxt,'41') @@ -54,13 +54,15 @@ export default function Page() { useEffect(() => { - excelDownload(rainChkgdn.excelList ,'빗물이용시설 지도점검','sample_rainy.xlsx'); + excelDownload(rainChkgdn.excelList ,'빗물이용시설 지도점검','sample_rainy.xlsx', 'A1:AN1'); }, [rainChkgdn.excelList]); const excelClick= useCallback(()=>{ rainChkExcelDownload(code.cityCd, code.sggCd); - }, [excelDownload, code.cityCd, code.sggCd]); - + }, [rainChkExcelDownload, code.cityCd, code.sggCd]); + const handleClick = useCallback((data:any) => { + if(data) setIsModal({ open: true, data: data }); + }, [isModal]); return ( <ContentsDiv> @@ -122,12 +124,12 @@ export default function Page() { <div className="grid grid-cols-6 gap-4 "> <div className="col-span-6"> <ListDiv> - {selFcltDiv === "RNB" ? <RainChkgdTable detailUp={setUpdateRainDetail} /> : <RswtChkgdTable />} + {selFcltDiv === "RNB" ? <RainChkgdTable detailUp={setUpdateRainDetail} handleClick={handleClick} /> : <RswtChkgdTable />} </ListDiv> </div> </div> - + <RainChkgdTableModal isModal={isModal} setIsModal={setIsModal}/> <UiModal open={isRegExcel} onOpenChange={setIsRegExcel} diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx index 5a74d104d..876964d36 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx @@ -5,8 +5,16 @@ import { import { fetchType, getFetch, postFectch, putFectch } from "@/components/lib/api"; import type { SelectDataType } from "@common/business_components/ui"; import { z } from "zod"; -import { buildingToExcelType, excelToRainChkData } from "./excel"; - +import { buildingToExcelType } from "./excel"; +const guideDetail=z.object({ + chkgdnFk: z.number().nullable(), + utztnUsgCd: z.string(), + chckYmd: z.string(), + ym: z.string(), + splyUswtrUtztnQnt: z.number(), + ruseFcltUtztnQnt: z.number(), + flg: z.string(), +}) export const rainChkZod = z.object({ chkgdnPk: z.number().nullable(), bdstRuseFcltFk: z.number(), @@ -19,15 +27,7 @@ export const rainChkZod = z.object({ mdfr: z.string().nullable(), flg: z.string().nullable(), guideDetails: z.array( - z.object({ - chkgdnFk: z.number().nullable(), - utztnUsgCd: z.string(), - chckYmd: z.string(), - ym: z.string(), - splyUswtrUtztnQnt: z.number(), - ruseFcltUtztnQnt: z.number(), - flg: z.string(), - }) + guideDetail ), building: z.object({ bdstInfoPk: z.number(), diff --git a/apps/wr/components/lib/config/index.ts b/apps/wr/components/lib/config/index.ts index 66ab1c169..4028f6cc3 100644 --- a/apps/wr/components/lib/config/index.ts +++ b/apps/wr/components/lib/config/index.ts @@ -1,14 +1,14 @@ const LOCAL_PORT = "3000"; const DEV_PORT = "11080"; -const DEV_PORT_NEW="8882" +const DEV_PORT_NEW="11082" export const LOCAL_URL_WR = `http://localhost:${LOCAL_PORT}/api/v1`; export const DEV_URL_WR = `http://con.mind-one.co.kr:${DEV_PORT}/api/v1`; //export const DEV_URL_FO = `http://con.mind-one.co.kr:${DEV_PORT_FO}/api/v1`; -export const DEV_URL_FO = `http://192.168.1.193:${DEV_PORT_NEW}/api/v1`; +export const DEV_URL_FO = `http://con.mind-one.co.kr:${DEV_PORT_NEW}/api/v1`; diff --git a/apps/wr/components/lib/func/TableData.tsx b/apps/wr/components/lib/func/TableData.tsx index d6bc9f30e..4540c4fc0 100644 --- a/apps/wr/components/lib/func/TableData.tsx +++ b/apps/wr/components/lib/func/TableData.tsx @@ -4,7 +4,7 @@ import { Checkbox, Input, TableCell, TableRow } from "@common/components/ui"; export const rightTableData = (rainChk: rainChkZodType[]) => { // 1. chkgdnFk + utztnUsgCd 기준 누계 정보 만들기 - const maketotal = rainChk.map((item: any) => { + const maketotal = rainChk.map((item: rainChkZodType) => { const selectTotal = item.guideDetails.reduce((acc: any, cur: any) => { const code = cur.utztnUsgCd; const fk = cur.chkgdnFk; @@ -23,6 +23,8 @@ export const rightTableData = (rainChk: rainChkZodType[]) => { return selectTotal; // 모든 키: `${chkgdnFk}_${utztnUsgCd}` 형태 }); + console.log("maketotal", maketotal); + // 2. 누계 정보들을 하나의 객체로 합치기 (평탄화) const flatTotalMap = Object.assign({}, ...maketotal); @@ -30,8 +32,8 @@ export const rightTableData = (rainChk: rainChkZodType[]) => { // 3. rainyDetails에 누계 정보 주입 const updatedRainyDetails: any[] = []; - rainChk.forEach((rd: any) => { - const details = rd.rainyDetails.forEach((rainyItem: any) => { + rainChk.forEach((rd: rainChkZodType) => { + rd.rainyDetails.forEach((rainyItem: any) => { const key = `${rainyItem.chkgdnFk}_${rainyItem.utztnUsgCd}`; const totals = flatTotalMap[key] || { totalSplyUswtrUtztnQnt: 0, @@ -51,10 +53,6 @@ export const rightTableData = (rainChk: rainChkZodType[]) => { return updatedRainyDetails; }; - - - - export const chRowspanTable = ( makeTableData: any[], headList: TableUpperProps[], @@ -67,10 +65,7 @@ export const chRowspanTable = ( selectedIds: number[], handleCellClick: (index: number, headId: string) => void ) => { - - - - + console.log('chRowspanTable', makeTableData); // rowspan된 셀 렌더링 여부 추적용 const renderedMap = new Map<string, Set<number>>(); return ( diff --git a/apps/wr/components/lib/func/commom.tsx b/apps/wr/components/lib/func/commom.tsx index a25ea0278..b5f5b3b38 100644 --- a/apps/wr/components/lib/func/commom.tsx +++ b/apps/wr/components/lib/func/commom.tsx @@ -41,7 +41,6 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => { returnData= { ...item, sggText: sggText, cityText: cityText}; } - // console.log(" returnData ", returnData) return returnData; }); @@ -49,7 +48,7 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => { - export const excelDownload =(excelList: [][], fileNm:string ,sampleFile:string ) =>{ + export const excelDownload =(excelList: [][], fileNm:string ,sampleFile:string, headerRange='A1:V3') =>{ if (excelList.length === 0) return; fetch(`/${sampleFile}`, {}) .then(async (response) => { @@ -59,7 +58,7 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => { // 받은 파일 바인너리 처리 const blobRet = await response.arrayBuffer() // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 - await filePickedBlob(blobRet, excelList,fileNm, 4) + await filePickedBlob(blobRet, excelList,fileNm, 4,headerRange) }) } diff --git a/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable.tsx b/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable.tsx index 19a1164bd..e9bc79108 100644 --- a/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable.tsx +++ b/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable.tsx @@ -1,41 +1,29 @@ "use client"; +import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead"; import { useWrStore } from "@/app/store"; import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; import { tableData } from "@/components/lib/func/commom"; -import { UiModal } from "@common/business_components/ui"; +import { + chRowspanTable, + rightTableData +} from "@/components/lib/func/TableData"; import { Table, TableBody, TableHeader, } from "@common/components/ui"; -import { useEffect, useState } from "react"; -import ChkgdModal from "../../../modal/chkgdModal/chkgdModal"; -import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead"; -import { - chRowspanTable, - rightTableData, -} from "@/components/lib/func/TableData"; +import { useCallback, useEffect, useState } from "react"; export default function RainChkgdTable({ - detailUp, + detailUp, handleClick=() => {} }: { detailUp: (data: rainChkZodType[]) => void; + handleClick?: (data:any) => void; }) { const { code, rainChkgdn } = useWrStore((state) => state); const [makeTableData, setMakeTableData] = useState<any[]>([]); const { rainChk } = rainChkgdn; const [selectedIds, setSelectedIds] = useState<number[]>([]); const [upRaintDetail, setUpRaintDetail] = useState<rainChkZodType[]>([]); - const [isModal, setIsModal] = useState({ open: false, data: {} }); - - const handleCellClick = (index: number, headId: string) => { - if ( - headId === "totalSplyUswtrUtztnQnt" || - headId === "totalRuseFcltUtztnQnt" - ) { - setIsModal({ open: true, data: makeTableData[index] }); - } - }; - const toggleSelection = (pk: number, checked: boolean) => { setSelectedIds((prev) => checked ? [...prev, pk] : prev.filter((item) => item !== pk) @@ -53,6 +41,15 @@ export default function RainChkgdTable({ ); }; + const handleCellClick= useCallback((index: number, headId: string) => { + if ( + headId === "totalSplyUswtrUtztnQnt" || + headId === "totalRuseFcltUtztnQnt" + ) { + handleClick(makeTableData[index]) + } + },[makeTableData, handleClick]); + useEffect(() => { @@ -65,8 +62,8 @@ export default function RainChkgdTable({ rowspan: item.rainyDetails?.length, }; }); - - setMakeTableData(rightTableData(rainChg)); + const tableTotalData = rightTableData(rainChg) + setMakeTableData(tableTotalData); }, [rainChk, code]); useEffect(() => { @@ -117,35 +114,24 @@ export default function RainChkgdTable({ detailUp(upRaintDetail); }, [upRaintDetail]); return ( - <> - <Table variant="secondary"> - <TableHeader className="font-bold"> - {headMakeprfmnc( - rainChkgdn?.rainChkgdnHeadList, - rainChkgdn?.rainHeadNm - )} - </TableHeader> + <Table variant="secondary"> + <TableHeader className="font-bold"> + {headMakeprfmnc( + rainChkgdn?.rainChkgdnHeadList, + rainChkgdn?.rainHeadNm + )} + </TableHeader> - <TableBody> - {chRowspanTable( - makeTableData, - rainChkgdn.rainChkgdnHeadList, - handleChange, - toggleSelection, - selectedIds, - handleCellClick - )} - </TableBody> - </Table> - - <UiModal - open={isModal.open} - onOpenChange={() => { - setIsModal({ open: !open, data: {} }); - }} - bodyClass={"w-[80vw] max-w-none"} - body={<ChkgdModal type={"RNB"} obj={isModal.data} />} - ></UiModal> - </> + <TableBody> + {chRowspanTable( + makeTableData, + rainChkgdn.rainChkgdnHeadList, + handleChange, + toggleSelection, + selectedIds, + handleCellClick + )} + </TableBody> + </Table> ); } diff --git a/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTableModal.tsx b/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTableModal.tsx new file mode 100644 index 000000000..3cc5bdbbb --- /dev/null +++ b/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTableModal.tsx @@ -0,0 +1,13 @@ +import ChkgdModal from "@/components/ui/modal/chkgdModal/chkgdModal"; +import { UiModal } from "@common/business_components"; + +export default function RainChkgdTableModal({ isModal, setIsModal }: { isModal: { open: boolean; data: any }; setIsModal: (value: { open: boolean; data: any }) => void }) { + return (<UiModal + open={isModal.open} + onOpenChange={() => { + setIsModal({ open: !open, data: {} }); + }} + bodyClass={"w-[80vw] max-w-none"} + body={<ChkgdModal type={"RNB"} obj={isModal.data} />} + ></UiModal>) +} \ No newline at end of file From 6447afd1629b6be0ed3ea82d11d8d1641d89e86c Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Wed, 30 Apr 2025 15:59:05 +0900 Subject: [PATCH 23/29] =?UTF-8?q?excel=20populate=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20=EC=83=81=EB=8B=A8=20range=EC=97=90=20=ED=97=A4?= =?UTF-8?q?=EB=8D=94=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=9E=85=ED=9E=88?= =?UTF-8?q?=EB=8A=94=20=EC=9E=91=EC=97=85=20=EC=99=84=EB=A3=8C.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/business_components/package.json | 2 + .../src/ui/excel/excelStyle.tsx | 24 ++++++ .../src/ui/excel/index.tsx | 84 +++++++++++++++++++ .../business_components/src/ui/index.ts | 3 +- 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 packages/common/business_components/src/ui/excel/excelStyle.tsx create mode 100644 packages/common/business_components/src/ui/excel/index.tsx diff --git a/packages/common/business_components/package.json b/packages/common/business_components/package.json index 1f02a708e..a23f31058 100644 --- a/packages/common/business_components/package.json +++ b/packages/common/business_components/package.json @@ -43,6 +43,7 @@ "sonner": "^2.0.1", "tailwind-merge": "^3.0.1", "xlsx": "^0.18.5", + "xlsx-populate": "^1.21.0", "zod": "^3.24.2" }, "devDependencies": { @@ -58,6 +59,7 @@ "@storybook/test": "^8.5.3", "@storybook/theming": "^8.5.5", "@vitejs/plugin-react": "^4.3.4", + "@xlsx/xlsx-populate": "^0.0.8", "autoprefixer": "^10.4.20", "eslint": "^9.17.0", "eslint-plugin-react-hooks": "^5.0.0", diff --git a/packages/common/business_components/src/ui/excel/excelStyle.tsx b/packages/common/business_components/src/ui/excel/excelStyle.tsx new file mode 100644 index 000000000..2475d1453 --- /dev/null +++ b/packages/common/business_components/src/ui/excel/excelStyle.tsx @@ -0,0 +1,24 @@ +import * as XlsxPopulate from '@xlsx/xlsx-populate'; +export const excelStyle = async (data: ArrayBuffer, range: string = "A1:V3", fileNm:string) => { + console.log("excelStyle", data, range, fileNm); + const workbook = await XlsxPopulate.Workbook.fromData(data); + const rangeCells = workbook.activeSheet(0)?.sheet(0)?.range(range); + console.log(rangeCells); + rangeCells?.style((styleQ)=>{ + console.log(styleQ); + styleQ.fill({ type: "solid", color: {rgb:"9bc1e7"} }); + styleQ.borderEach( { style: "thin", color: { rgb: "FFFFFF" } } ); + styleQ.wrapText(true); + // styleQ.fontColor({rgb:"FFFFFF"}); + styleQ.fontSize(15); + styleQ.horizontalAlignment("center"); + styleQ.verticalAlignment("center"); + styleQ.bold(true); + }); + const outputData = await workbook.output("array-buffer"); + const blob = new Blob([outputData], { type: "application/octet-stream" }); + const link = document.createElement("a"); + link.href = URL.createObjectURL(blob); + link.download = fileNm+".xlsx"; + link.click(); +} \ No newline at end of file diff --git a/packages/common/business_components/src/ui/excel/index.tsx b/packages/common/business_components/src/ui/excel/index.tsx new file mode 100644 index 000000000..0aa547c5c --- /dev/null +++ b/packages/common/business_components/src/ui/excel/index.tsx @@ -0,0 +1,84 @@ +import * as XLSX from 'xlsx'; +import { excelStyle } from './excelStyle'; + +type ExcelDownloadProps = { + data: JSON | JSON[]; + fileName: string; + sheetNameArray: string[]; +} + +export const downloadExcel = ({ data, fileName = new Date().getTime().toString() + '.xlsx', sheetNameArray = ["Sheet1"] }: ExcelDownloadProps) => { + const worksheet = XLSX.utils.json_to_sheet(Array.isArray(data) ? data : [data]); + const workbook = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(workbook, worksheet, sheetNameArray[0]); + //let buffer = XLSX.write(workbook, { bookType: "xlsx", type: "buffer" }); + //XLSX.write(workbook, { bookType: "xlsx", type: "binary" }); + XLSX.writeFile(workbook, fileName + '.xlsx'); +}; + + + +export const filePicked=(oFile: File, headerNum:number=0):Promise<JSON | undefined> =>{ + // Create A File Reader HTML5 + const reader = new FileReader(); + return new Promise<JSON | undefined>((resolve, reject) => { + // Ready The Event For When A File Gets Selected + reader.onload = function (e) { + const data = e.target?.result; + if (!data) { + console.error("Failed to read file: e.target.result is null"); + resolve(undefined); + return; + } + const wb = XLSX.read(data, { type: 'binary' }); + let jsonXls: JSON | undefined; + + //TODO 시트가 2개이상일 경우 마지막 시트의 데이터만 표출됨 + // Loop Over Each Sheet + wb.SheetNames.forEach(function (sheetName) { + // Obtain The Current Row As CSV + const sheet = wb.Sheets[sheetName]; + + if (sheet) { + jsonXls = XLSX.utils.sheet_to_json(sheet, { range: headerNum }) as unknown as JSON; + } else { + console.error(`Sheet "${sheetName}" is undefined.`); + } + }); + resolve(jsonXls); + }; + + reader.onerror = function () { + console.error("Error reading file"); + reject(undefined); + }; + + // Tell JS To Start Reading The File.. You could delay this if desired + reader.readAsBinaryString(oFile); + }); +} + + + +export const filePickedBlob=(oFile: ArrayBuffer, data:[][],fileNm:string, headerNum:number=0, headerRange='A1:V3'):Promise<JSON | undefined> =>{ // Create A File Reader HTML5 + return new Promise<JSON | undefined>(() => { + // Ready The Event For When A File Gets Selected + const wb = XLSX.read(oFile, { type: 'binary' }); + // Loop Over Each Sheet + wb.SheetNames.forEach(async function (sheetName, index) { + // Obtain The Current Row As CSV + if(index==0){ + const sheet = wb.Sheets[sheetName]; + if (sheet) { + //오리진 확인 test 필요 + // const sheet = XLSX.utils.json_to_sheet(data); + XLSX.utils.sheet_add_aoa(sheet, data, { origin: 'A'+headerNum }); + // XLSX.utils.book_append_sheet(wb, sheet, 'test'); + await excelStyle(XLSX.write(wb, { bookType: "xlsx", type: "buffer" }), headerRange, fileNm) + } else { + console.error(`Sheet "${sheetName}" is undefined.`); + } + } + }); + }); + } \ No newline at end of file diff --git a/packages/common/business_components/src/ui/index.ts b/packages/common/business_components/src/ui/index.ts index e591be5b5..90bf029c0 100644 --- a/packages/common/business_components/src/ui/index.ts +++ b/packages/common/business_components/src/ui/index.ts @@ -1,7 +1,7 @@ export * from "./chart"; export * from "./date_picker"; export * from "./dialog_ui"; -export * from "./excel_download"; +export * from "./excel"; export * from "./file-upload"; export * from "./form"; export * from "./form_ui"; @@ -19,3 +19,4 @@ export * from "./tab"; export * from "./table"; export * from "./table_div"; export * from "./title"; + From 370a1076b0351b92e26c75dc94cd133b7a3eb881 Mon Sep 17 00:00:00 2001 From: truthwing <truthplumage@gmail.com> Date: Wed, 30 Apr 2025 16:08:22 +0900 Subject: [PATCH 24/29] =?UTF-8?q?excel=5Fdownload=20=ED=8F=B4=EB=8D=94?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/excel/index.tsx | 7 +- .../src/ui/excel_download/index.tsx | 84 ------------------- 2 files changed, 3 insertions(+), 88 deletions(-) delete mode 100644 packages/common/business_components/src/ui/excel_download/index.tsx diff --git a/packages/common/business_components/src/ui/excel/index.tsx b/packages/common/business_components/src/ui/excel/index.tsx index 0aa547c5c..13a814114 100644 --- a/packages/common/business_components/src/ui/excel/index.tsx +++ b/packages/common/business_components/src/ui/excel/index.tsx @@ -5,15 +5,14 @@ type ExcelDownloadProps = { data: JSON | JSON[]; fileName: string; sheetNameArray: string[]; + headerRange: string; } -export const downloadExcel = ({ data, fileName = new Date().getTime().toString() + '.xlsx', sheetNameArray = ["Sheet1"] }: ExcelDownloadProps) => { +export const downloadExcel = ({ data, fileName = new Date().getTime().toString() + '.xlsx', sheetNameArray = ["Sheet1"], headerRange='A1:V3'}: ExcelDownloadProps) => { const worksheet = XLSX.utils.json_to_sheet(Array.isArray(data) ? data : [data]); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, sheetNameArray[0]); - //let buffer = XLSX.write(workbook, { bookType: "xlsx", type: "buffer" }); - //XLSX.write(workbook, { bookType: "xlsx", type: "binary" }); - XLSX.writeFile(workbook, fileName + '.xlsx'); + excelStyle(XLSX.write(workbook, { bookType: "xlsx", type: "buffer" }), headerRange, fileName); }; diff --git a/packages/common/business_components/src/ui/excel_download/index.tsx b/packages/common/business_components/src/ui/excel_download/index.tsx deleted file mode 100644 index 58ecf8a52..000000000 --- a/packages/common/business_components/src/ui/excel_download/index.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import * as XLSX from 'xlsx'; - -type ExcelDownloadProps = { - data: JSON | JSON[]; - fileName: string; - sheetNameArray: string[]; -} - -export const downloadExcel = ({ data, fileName = new Date().getTime().toString() + '.xlsx', sheetNameArray = ["Sheet1"] }: ExcelDownloadProps) => { - const worksheet = XLSX.utils.json_to_sheet(Array.isArray(data) ? data : [data]); - const workbook = XLSX.utils.book_new(); - XLSX.utils.book_append_sheet(workbook, worksheet, sheetNameArray[0]); - //let buffer = XLSX.write(workbook, { bookType: "xlsx", type: "buffer" }); - //XLSX.write(workbook, { bookType: "xlsx", type: "binary" }); - XLSX.writeFile(workbook, fileName + '.xlsx'); -}; - - - -export const filePicked=(oFile: File, headerNum:number=0):Promise<JSON | undefined> =>{ - // Create A File Reader HTML5 - const reader = new FileReader(); - return new Promise<JSON | undefined>((resolve, reject) => { - // Ready The Event For When A File Gets Selected - reader.onload = function (e) { - const data = e.target?.result; - if (!data) { - console.error("Failed to read file: e.target.result is null"); - resolve(undefined); - return; - } - const wb = XLSX.read(data, { type: 'binary' }); - let jsonXls: JSON | undefined; - - //TODO 시트가 2개이상일 경우 마지막 시트의 데이터만 표출됨 - // Loop Over Each Sheet - wb.SheetNames.forEach(function (sheetName) { - // Obtain The Current Row As CSV - const sheet = wb.Sheets[sheetName]; - - if (sheet) { - jsonXls = XLSX.utils.sheet_to_json(sheet, { range: headerNum }) as unknown as JSON; - } else { - console.error(`Sheet "${sheetName}" is undefined.`); - } - }); - resolve(jsonXls); - }; - - reader.onerror = function () { - console.error("Error reading file"); - reject(undefined); - }; - - // Tell JS To Start Reading The File.. You could delay this if desired - reader.readAsBinaryString(oFile); - }); -} - - - -export const filePickedBlob=(oFile: ArrayBuffer, data:[][],fileNm:string, headerNum:number=0):Promise<JSON | undefined> =>{ - // Create A File Reader HTML5 - return new Promise<JSON | undefined>(() => { - // Ready The Event For When A File Gets Selected - const wb = XLSX.read(oFile, { type: 'binary' }); - // Loop Over Each Sheet - wb.SheetNames.forEach(function (sheetName, index) { - // Obtain The Current Row As CSV - if(index==0){ - const sheet = wb.Sheets[sheetName]; - if (sheet) { - //오리진 확인 test 필요 - // const sheet = XLSX.utils.json_to_sheet(data); - XLSX.utils.sheet_add_aoa(sheet, data, { origin: 'A'+headerNum }); - // XLSX.utils.book_append_sheet(wb, sheet, 'test'); - XLSX.writeFile(wb, `${fileNm}.xlsx`); - } else { - console.error(`Sheet "${sheetName}" is undefined.`); - } - } - }); - }); - } \ No newline at end of file From a9b812936123679de66eb2e0d10a2bfe4c65f7f7 Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Fri, 2 May 2025 14:58:18 +0900 Subject: [PATCH 25/29] =?UTF-8?q?=EC=97=91=EC=85=80=20to=20json=20?= =?UTF-8?q?=EC=9E=91=EC=97=85=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruseFcltMng/fcltSttn/pbnstSttn/page.tsx | 6 +- .../ruseFcltMng/fcltSttn/rainSttn/page.tsx | 39 +- .../ruseFcltMng/prfmncReg/chkgdnReg/page.tsx | 2 +- .../prfmncReg/chkgdnReg/rainChkgdn/excel.tsx | 8 +- .../prfmncReg/chkgdnReg/rainChkgdn/index.tsx | 10 +- .../ruseFcltMng/fcltReg/rainReg/index.tsx | 2 +- .../fcltSttn/pbnstSttn/headList.tsx | 169 +++++++ .../fcltSttn/{sttn => rainSttn}/excel.tsx | 0 .../fcltSttn/rainSttn/headList.tsx | 428 ++++++++++++++++++ .../ruseFcltMng/fcltSttn/rainSttn/index.tsx | 109 +++++ .../store/ruseFcltMng/fcltSttn/sttn/index.tsx | 412 ----------------- apps/wr/app/store/store.tsx | 10 +- apps/wr/components/lib/func/TableData.tsx | 2 +- apps/wr/components/lib/func/commom.tsx | 2 +- .../ui/form/fcltReg/rainReg/rainRegForm.tsx | 14 +- .../ui/modal/chkgdExcel/chkgdExcel.tsx | 18 +- .../ui/modal/headChModal/headChModal.tsx | 16 +- .../chkgdTable/rswtChkgd/rswtChkgdTable.tsx | 2 +- apps/wr/components/ui/toast/toastFromUi.tsx | 83 ++-- 19 files changed, 817 insertions(+), 515 deletions(-) create mode 100644 apps/wr/app/store/ruseFcltMng/fcltSttn/pbnstSttn/headList.tsx rename apps/wr/app/store/ruseFcltMng/fcltSttn/{sttn => rainSttn}/excel.tsx (100%) create mode 100644 apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/headList.tsx create mode 100644 apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/index.tsx delete mode 100644 apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/pbnstSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/pbnstSttn/page.tsx index b7f47f0ca..6c865932e 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/pbnstSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/pbnstSttn/page.tsx @@ -17,10 +17,10 @@ import HeadChModal from "@/components/ui/modal/headChModal/headChModal"; import { useState } from "react"; export default function PbnstSttn() { - const { code, sttnCommon } = useWrStore((state) => state); + const { code, rainSttn } = useWrStore((state) => state); const [isChHead, setIsChHead] = useState(false); - const nodeList = headMakeprfmnc(sttnCommon.pbnSttHeadList, sttnCommon.pbnSttHeadNm); + const nodeList = headMakeprfmnc(rainSttn.pbnSttHeadList, rainSttn.pbnSttHeadNm); return ( <> @@ -113,7 +113,7 @@ export default function PbnstSttn() { <UiTable headName={undefined} tableData={[]} - headlist={sttnCommon.pbnSttHeadList} + headlist={rainSttn.pbnSttHeadList} pageSize={0} total={0} cellClick={undefined} diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index 371e03075..003e4cdf8 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -18,20 +18,19 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { headMakeTriple } from "./TableHead"; export default function RainSttn() { - const { code, sttnCommon, rainSttnSearch } = + const { code, rainSttn, rainSttnSearch } = useWrStore((state) => state); - const { rainRes } = sttnCommon; - + const { rainSttnRes } = rainSttn; const [isChHead, setIsChHead] = useState(false); const ref = useRef<ReturnType>({} as ReturnType); const [bdstTable, setBdstTable] = useState<any[]>(); - const nodeList = headMakeTriple( - sttnCommon.rainSttHeadList, - sttnCommon.rainSttHeadNm - ); + // const nodeList = headMakeTriple( + // rainSttn.rainSttHeadList, + // rainSttn.rainSttHeadNm + // ); useEffect(() => { - if (!sttnCommon.isInit) { + if (!rainSttn.isInit) { let con if (ref.current.sigunValue != '0') { con = ref.current.sigunValue @@ -40,15 +39,12 @@ export default function RainSttn() { } rainSttnSearch('1', '20' ,con); } - }, [sttnCommon.isInit, rainSttnSearch]); - - + }, [rainSttn.isInit, rainSttnSearch]); useEffect(() => { - if (rainRes.length > 0) { - const data = tableData(rainRes, { code }); - // data 는 위 JSON 객체라고 가정 + if (rainSttnRes.length > 0) { + const data = tableData(rainSttnRes, { code }); const chData = data .map((item: any) => ({ @@ -60,15 +56,14 @@ export default function RainSttn() { setBdstTable(chData); } - }, [code, rainRes, sttnCommon.rainSttHeadList]); + }, [code, rainSttnRes, rainSttn.rainSttHeadList]); useEffect(() => { - if(sttnCommon.excelList.length>0){ - console.log('sttnCommon.excelList', sttnCommon.excelList); + if(rainSttn.excelList.length>0){ - if (sttnCommon.excelList.length === 0) return; - excelDownload(sttnCommon.excelList , '빗물재이용시설 현황','sample_rainSttn.xlsx') + if (rainSttn.excelList.length === 0) return; + excelDownload(rainSttn.excelList , '빗물재이용시설 현황','sample_rainSttn.xlsx') } - }, [sttnCommon.excelList]); + }, [rainSttn.excelList]); const excelClick = useCallback((returnType:ReturnType) => { @@ -127,7 +122,7 @@ export default function RainSttn() { <UiTable headName={[]} tableData={bdstTable || []} - headlist={sttnCommon.rainSttHeadList} + headlist={rainSttn.rainSttHeadList} pageSize={0} total={0} cellClick={undefined} @@ -135,7 +130,7 @@ export default function RainSttn() { throw new Error("Function not implemented."); }} > - {nodeList} + {/* {nodeList} */} </UiTable> </ListDiv> </div> diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx index cd915e33b..220ff76f3 100644 --- a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx @@ -70,7 +70,7 @@ export default function Page() { <SearchDiv> <SearchFormLeft> <SearchInput - className="col-span-3 my-7" + className="col-span-3 my-7 !text-xl" label=" 지도점검년도" textValue={searchTxt??''} setText={(e) => {setSearchTxt(e);}} diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx index 24c8cdebc..d6c8d8345 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx @@ -97,16 +97,16 @@ export const excelToRainChkData = ( return { utztnUsgCd: item["이용용도"], ym: year + month, - chckYmd: excelSerialToDateString(item["점검일"]) , - splyUswtrUtztnQnt: splyData !== undefined ? splyData : 0, - ruseFcltUtztnQnt: ruseData !== undefined ? ruseData : 0, + chckYmd: item["점검일"] , + splyUswtrUtztnQnt: splyData !== "" ? splyData : 0, + ruseFcltUtztnQnt: ruseData !== "" ? ruseData : 0, flg: "RNB", }; }); return { bdstRuseFcltFk: Number(item["NO"]), - chckYmd: excelSerialToDateString(item["점검일"]) , + chckYmd: item["점검일"] , spwtPositn: item["유량측정방법"], rgtr: TEST_UUID, oilqMeasMthd: item["운영관리형태"], diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx index 5a74d104d..d80261d21 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx @@ -6,6 +6,8 @@ import { fetchType, getFetch, postFectch, putFectch } from "@/components/lib/api import type { SelectDataType } from "@common/business_components/ui"; import { z } from "zod"; import { buildingToExcelType, excelToRainChkData } from "./excel"; +import toast from "react-hot-toast"; +import { ToastFormUi } from "@/components/ui/toast/toastFromUi"; export const rainChkZod = z.object({ chkgdnPk: z.number().nullable(), @@ -307,7 +309,7 @@ type rainChkgdnActions = { rainChkDetilUpdate(rainChk: rainChkZodType[]): Promise<void>; rainChkGuidUpdate(rainChk: rainChkZodType): Promise<void>; rainChkExcelDownload(sidoCode: SelectDataType[],sggCode: SelectDataType[]): Promise<void> - excelDataUPload(excelData:rainChkZodType[]) : Promise<void> + rainChkExcelDataUPload(excelData:rainChkZodType[]) : Promise<void> }; export type rainChkgdnType = rainChkgdnState & rainChkgdnActions; @@ -371,11 +373,11 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( }, })); }, - excelDataUPload: async(excelData:rainChkZodType[] ) =>{ + rainChkExcelDataUPload: async(excelData:rainChkZodType[] ) =>{ try{ const res = await postFectch("/reuseChk/rainyExcel", excelData); if (res.ok) { - alert(" 데이터 입력 완료"); + ToastFormUi({body:"엑셀 데이터 업로드가 성공하였습니다. " ,title:'엑셀등록'}) } const rainChkRes = await initFetch('2024', '0'); return set((state: rainChkgdnState) => ({ @@ -387,7 +389,7 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( })); }catch(error){ console.log(error); - alert("데이터 입력을 실패하였습니다."); + ToastFormUi({body:"엑셀 데이터 업로드를 실패하였습니다. " ,title:'엑셀등록'}) } }, rainChkInit: async (searchTxt: string, sggCd: string) => { diff --git a/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx index ccf0e2b32..855d05d71 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx @@ -133,7 +133,7 @@ export const upHeadList: TableUpperProps[] = [ const rainRes: customRainBdst[] = []; -export const selectClass = "w-full h-full text-2xl"; +export const selectClass = "w-full h-full !text-2xl"; const selectYN = [ { text: "Y", val: "1" }, { text: "N", val: "2" }, diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/pbnstSttn/headList.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/pbnstSttn/headList.tsx new file mode 100644 index 000000000..d4c4fed31 --- /dev/null +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/pbnstSttn/headList.tsx @@ -0,0 +1,169 @@ +import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; +import type { TableUpperProps } from "../../fcltReg/rainReg"; + +export const pbnSttHeadNmExport: chHeadType[] = [ + { headNm: "catchment", text: "유역", length: 3 }, + { headNm: "adminDiv", text: "행정구역", length: 2 }, + { headNm: "rusSup", text: "재이용수공급가능량", length: 3 }, + { headNm: "yearResult", text: "연간실적정보(m³)", length: 3 }, + { headNm: "mngInfo", text: "운영정보", length: 4 }, +]; + +// id는 다확인해야함 +export const pbnSttHeadListExport: TableUpperProps[] = [ + { id: "a", title: "권역", upName: "catchment", upSequnce: 1, visible: true }, + { + id: "aaa", + title: "단위유역", + upName: "catchment", + upSequnce: 2, + visible: true, + }, + { + id: "aaaa", + title: "중권역", + upName: "catchment", + upSequnce: 3, + visible: false, + }, + { id: "operMngCd", title: "환경청", visible: true }, + { + id: "cityText", + title: "시도", + upName: "adminDiv", + upSequnce: 1, + visible: false, + }, + { + id: "sggText", + title: "시군구", + upName: "adminDiv", + upSequnce: 2, + visible: true, + }, + { id: "bdnstNm", title: "시설명", visible: true }, + { id: "locDiv", title: "지역구분", visible: true }, + { id: "phone", title: "전화번호", visible: true }, + + { id: "fcltQuantity", title: "시설용량(톤/일)", visible: true }, + { id: "rusNm", title: "재이용시설명", visible: true }, + + { + id: "fcltCpct", + title: "시설용량(m³/일)", + upName: "rusSup", + upSequnce: 1, + visible: true, + }, + { + id: "trbt", + title: "하수처리량(m³/일)", + upName: "rusSup", + upSequnce: 2, + visible: true, + }, + { + id: "ruseCpct", + title: "재이용량(m³/일)", + upName: "rusSup", + upSequnce: 3, + visible: true, + }, + + { + id: "total", + title: "합계", + upName: "yearResult", + upSequnce: 1, + visible: true, + }, + { + id: "ithlWtr", + title: "장내용수", + upName: "yearResult", + upSequnce: 2, + visible: true, + }, + { + id: "othlWtr", + title: "장외용수", + upName: "yearResult", + upSequnce: 3, + visible: true, + }, + + { + id: "mngMeth", + title: "운영방식", + upName: "mngInfo", + upSequnce: 1, + visible: true, + }, + { + id: "rprtvBzenty", + title: "대행업체", + upName: "mngInfo", + upSequnce: 2, + visible: true, + }, + { + id: "firstDay", + title: "시작일", + upName: "mngInfo", + upSequnce: 3, + visible: true, + }, + { + id: "LastDay", + title: "종료일", + upName: "mngInfo", + upSequnce: 4, + visible: true, + }, +]; + + + + +// 참고용 지워야함. +// rainChSttnHead: async (checkList: string[], type: string) => { +// const headList = +// type === "pbn" +// ? pbnSttHeadList +// : type === "rain" +// ? rainSttHeadList +// : null; + +// let chNm = type === "pbn" ? pbnSttHeadNm : rainSttHeadNm; +// headList?.forEach((item) => { +// if (checkList.find((ch) => ch === item.id)) { +// item.visible = false; +// if (item.upName) { +// const upNames = Array.isArray(item.upName) +// ? item.upName +// : [item.upName]; +// upNames?.forEach((up) => { +// chNm.find((ch) => { +// if (ch.headNm === up) { +// ch.length = ch.length - 1; +// } +// }); +// }); +// } +// } +// }); +// set((state: rainSttnState) => ({ +// sttnCommon: { +// ...state.sttnCommon, +// pbnSttHeadList: +// type === "pbn" ? headList : state.sttnCommon.pbnSttHeadList, +// rainSttHeadList: +// type === "rain" ? headList : state.sttnCommon.rainSttHeadList, +// rainSttHeadNm: +// type === "rain" ? chNm : state.sttnCommon.rainSttHeadNm, +// pbnSttHeadNm: type === "rain" ? chNm : state.sttnCommon.pbnSttHeadNm, +// }, +// })); +// }, +// }; +// }; \ No newline at end of file diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/excel.tsx similarity index 100% rename from apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/excel.tsx rename to apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/excel.tsx diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/headList.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/headList.tsx new file mode 100644 index 000000000..cf06687c4 --- /dev/null +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/headList.tsx @@ -0,0 +1,428 @@ +import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; +import type { TableTripleProps, TableUpperProps } from "../../fcltReg/rainReg"; + +export type TableUpperPropsTest = { + id: string; + title: string; + upName?: string; + upSequnce?: number; + row?: number; + rowSpan?: number; + colSpan?: number; + visible?: boolean; +}; + +// id는 다확인해야함 +export const rainSttHeadListExportTest: TableUpperPropsTest[] = [ + { + id: "bdnstInfo", + title: "1.건축물정보", + visible: true, + row: 1, + rowSpan: 1, + colSpan: 9, + }, + { + id: "rainFcltInfo", + title: "2.빗물이용시설정보", + visible: true, + row: 1, + rowSpan: 1, + colSpan: 6, + }, + { id: "insenInfo", + title: "3.인센티브 정보", + visible: true, + row: 1, + rowSpan: 1, + colSpan: 7 + }, + + // 2번째 줄 + { id: "adminDiv", + title: "행정구역", + visible: true, + row: 2, + rowSpan: 1, + colSpan: 2 }, + + // 1번째 줄 건축물정보 아래의 행으로 만들 헤더 + { + id: "bdstNm", + title: "건축물명", + visible: true, + row: 2, + rowSpan: 2, + colSpan: 1 }, + { + id: "daddr", + title: "주소", + visible: true, + row: 2, + rowSpan: 2, + colSpan: 1 }, + { + id: "bdstUsgCd", + title: "건축물용도코드", + row: 2, + rowSpan: 2, + colSpan: 1 }, + { + id: "frstArchPrmsnDt", + title: "최초건축허가일시", + visible: true, + row: 2, + rowSpan: 2, + colSpan: 1 }, + { + id: "archArea", + title: "건축면적", + visible: true, + row: 2, + rowSpan: 2, + colSpan: 1 }, + { + id: "lawTrgtYn", + title: "법적의무대상여부", + visible: true, + row: 2, + rowSpan: 2, + colSpan: 1 }, + { + id: "instlCmptnDt", + title: "설치완료일시", + visible: true, + row: 2, + rowSpan: 2, + colSpan: 1 }, + + + { + id: "instlCst", + title: "설치비용", + visible: true, + row: 2, + rowSpan: 1, + colSpan: 2 + }, + + { id: "pntfCol", + title: "집수면", + visible: true, + row: 2, + rowSpan: 1, + colSpan: 2 + }, + { id: "filtrTrtmfct", + title: "여과등 처리시설", + visible: true, + row: 2, + rowSpan: 1, + colSpan: 3 + }, + { + id: "dtfcltCpct", + title: "저류조용량", + visible: true, + row: 2, + rowSpan: 2, + colSpan: 1 + }, + + + { id: "instlCstSprt", + title: "설치비지원", + visible: true, + row: 2, + rowSpan: 1, + colSpan: 2 + }, + { id: "grntchBdstCert", + title: "녹색건축물인증여부", + visible: true, + row: 2, + rowSpan: 1, + colSpan: 4 + }, + + // 3번째줄 시작 + { + id: "cityText", + title: "시도", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, + { + id: "sggText", + title: "시군구", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, + + + + { + id: "pntfColKnd", + title: "집수지점종류", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, + { + id: "pntfColArea", + title: "집수지점면적", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, + { + id: "filtrTrtmfctYn", + title: "여과처리시설유무", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, + { + id: "filtrTrtmfctCpct", + title: "여과처리시설용량", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, + { + id: "filtrTrtmfctPrs", + title: "여과처리시설처리공정", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, + + + { + id: "instlCstSprtYn", + title: "설치지원비용여부", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, + { + id: "instlCstSprtAmt", + title: "설치지원비용", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, + + { + id: "grntchBdstCertYn", + title: "녹색건축물인증여부", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, + { + id: "grntchBdstCertYr", + title: "녹색건축물인증년도", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, + { + id: "grntchBdstCertNo", + title: "녹색건축물인증번호", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, + { + id: "grntchBdstCertGrd", + title: "녹색건축물인증등급", + visible: true, + row: 3, + rowSpan: 1, + colSpan: 1 + }, +]; + +export const rainSttHeadNmExport: chHeadType[] = [ + { headNm: "bdnstInfo", text: "1.건축물정보", length: 9 }, + { headNm: "rainFcltInfo", text: "2.빗물이용시설정보", length: 7 }, + { headNm: "insenInfo", text: "3.인센티브 정보", length: 9 }, + + +]; + +// id는 다확인해야함 +export const rainSttHeadListExport: TableTripleProps[] = [ + { + id: "cityText", + title: "시도", + visible: true, + upName: ["bdnstInfo", "adminDiv"], + upSequnce: [1, 1], + }, + { + id: "sggText", + title: "시군구", + visible: true, + upName: ["bdnstInfo", "adminDiv"], + upSequnce: [2, 2], + }, + { + id: "bdstNm", + title: "건축물명", + visible: true, + upName: ["bdnstInfo"], + upSequnce: [3], + }, + { + id: "daddr", + title: "주소", + visible: true, + upName: ["bdnstInfo"], + upSequnce: [4], + }, + { + id: "bdstUsgCd", + title: "건축물용도코드", + visible: true, + upName: ["bdnstInfo"], + upSequnce: [5], + }, + { + id: "frstArchPrmsnDt", + title: "최초건축허가일시", + visible: true, + upName: ["bdnstInfo"], + upSequnce: [6], + }, + { + id: "archArea", + title: "건축면적", + visible: true, + upName: ["bdnstInfo"], + upSequnce: [7], + }, + { + id: "lawTrgtYn", + title: "법적의무대상여부", + visible: true, + upName: ["bdnstInfo"], + upSequnce: [8], + }, + { + id: "instlCmptnDt", + title: "설치완료일시", + visible: true, + upName: ["bdnstInfo"], + upSequnce: [9], + }, + + { + id: "instlCst", + title: "설치비용", + visible: true, + upName: ["rainFcltInfo"], + upSequnce: [1], + }, + { + id: "pntfColKnd", + title: "집수지점종류", + visible: true, + upName: ["rainFcltInfo", "pntfCol"], + upSequnce: [2, 1], + }, + { + id: "pntfColArea", + title: "집수지점면적", + visible: true, + upName: ["rainFcltInfo", "pntfCol"], + upSequnce: [3, 2], + }, + { + id: "filtrTrtmfctYn", + title: "여과처리시설유무", + visible: true, + upName: ["rainFcltInfo", "filtrTrtmfct"], + upSequnce: [4, 1], + }, + { + id: "filtrTrtmfctCpct", + title: "여과처리시설용량", + visible: true, + upName: ["rainFcltInfo", "filtrTrtmfct"], + upSequnce: [5, 2], + }, + { + id: "filtrTrtmfctPrs", + title: "여과처리시설처리공정", + visible: true, + upName: ["rainFcltInfo", "filtrTrtmfct"], + upSequnce: [6, 3], + }, + { + id: "dtfcltCpct", + title: "저류조용량", + visible: true, + upName: ["rainFcltInfo"], + upSequnce: [7], + }, + + { + id: "instlCstSprtYn", + title: "설치지원비용여부", + visible: true, + upName: ["insenInfo", "instlCstSprt"], + upSequnce: [1, 1], + }, + { + id: "instlCstSprtAmt", + title: "설치지원비용", + visible: true, + upName: ["insenInfo", "instlCstSprt"], + upSequnce: [2, 2], + }, + + { + id: "grntchBdstCertYn", + title: "녹색건축물인증여부", + visible: true, + upName: ["insenInfo", "grntchBdstCert"], + upSequnce: [3, 1], + }, + { + id: "grntchBdstCertYr", + title: "녹색건축물인증년도", + visible: true, + upName: ["insenInfo", "grntchBdstCert"], + upSequnce: [4, 2], + }, + { + id: "grntchBdstCertNo", + title: "녹색건축물인증번호", + visible: true, + upName: ["insenInfo", "grntchBdstCert"], + upSequnce: [5, 3], + }, + { + id: "grntchBdstCertGrd", + title: "녹색건축물인증등급", + visible: true, + upName: ["insenInfo", "grntchBdstCert"], + upSequnce: [6, 4], + }, +]; diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/index.tsx new file mode 100644 index 000000000..7ebc9b7aa --- /dev/null +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/index.tsx @@ -0,0 +1,109 @@ +import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; +import { fetchType, getFetch } from "@/components/lib/api"; +import { + type customRainBdst, + type TableTripleProps, +} from "../../fcltReg/rainReg"; +import { excelSttnParsing } from "./excel"; +import { rainSttHeadListExport, rainSttHeadListExportTest, rainSttHeadNmExport, type TableUpperPropsTest } from "./headList"; + +// 테이블 헤드 리스트 +const rainSttHeadNm = rainSttHeadNmExport; + +//const rainSttHeadList = rainSttHeadListExport; +const rainSttHeadList = rainSttHeadListExportTest; +const rainSttnRes: customRainBdst[] = []; + +export type rainSttnState = { + rainSttn: { + rainSttnRes: customRainBdst[]; + // rainSttHeadList: TableTripleProps[]; + rainSttHeadList: TableUpperPropsTest[]; + rainSttHeadNm: chHeadType[]; + excelList: []; + isInit: boolean; + }; +}; +type rainSttnActions = { + rainSttnSearch: (page: string, total: string, con: string) => void; + rainChSttnHead: (checkList: string[]) => void; +}; + +export type rainSttnType = rainSttnState & rainSttnActions; + +export const rainSttnStateExport: rainSttnState = { + rainSttn: { + rainSttHeadList: rainSttHeadList, + rainSttHeadNm: rainSttHeadNm, + rainSttnRes: rainSttnRes, + excelList: [], + isInit: false, + }, +}; + +export const rainSttnActionsExport: (set: any) => rainSttnActions = ( + set: any +) => { + return { + rainSttnSearch: async (page: string, total: string, con: string) => { + try { + const rainSttnRes = await getFetch( + fetchType.WR, + `/reuseFc/rainyInfoList/${page}/${total}/${con}` + ); + if (Number(total) > 9000) { + const rainExcel = excelSttnParsing(rainSttnRes); + set((state: rainSttnState) => { + return { + ...state, + rainSttn: { + ...state.rainSttn, + excelList: rainExcel, + }, + }; + }); + } else + set((state: rainSttnState) => { + return { + ...state, + rainSttn: { + ...state.rainSttn, + rainSttnRes: rainSttnRes, + isInit: false, + }, + }; + }); + } catch (erTxt) { + console.log("error", erTxt); + } + }, + rainChSttnHead: async (checkList: string[]) => { + const headList = rainSttHeadList; + let chNm = rainSttHeadNm; + headList?.forEach((item) => { + if (checkList.find((ch) => ch === item.id)) { + item.visible = false; + if (item.upName) { + const upNames = Array.isArray(item.upName) + ? item.upName + : [item.upName]; + upNames?.forEach((up) => { + chNm.find((ch) => { + if (ch.headNm === up) { + ch.length = ch.length - 1; + } + }); + }); + } + } + }); + set((state: rainSttnState) => ({ + rainSttn: { + ...state.rainSttn, + rainSttHeadList: headList, + rainSttHeadNm: chNm, + }, + })); + }, + }; +}; diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx deleted file mode 100644 index d0dd648e7..000000000 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/sttn/index.tsx +++ /dev/null @@ -1,412 +0,0 @@ -import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; -import { fetchType, getFetch } from "@/components/lib/api"; -import { - type customRainBdst, - type TableTripleProps, - type TableUpperProps, -} from "../../fcltReg/rainReg"; -import { excelSttnParsing, } from "./excel"; - -const pbnSttHeadNm: chHeadType[] = [ - { headNm: "catchment", text: "유역", length: 3 }, - { headNm: "adminDiv", text: "행정구역", length: 2 }, - { headNm: "rusSup", text: "재이용수공급가능량", length: 3 }, - { headNm: "yearResult", text: "연간실적정보(m³)", length: 3 }, - { headNm: "mngInfo", text: "운영정보", length: 4 }, -]; - -// id는 다확인해야함 -const pbnSttHeadList: TableUpperProps[] = [ - { id: "a", title: "권역", upName: "catchment", upSequnce: 1, visible: true }, - { - id: "aaa", - title: "단위유역", - upName: "catchment", - upSequnce: 2, - visible: true, - }, - { - id: "aaaa", - title: "중권역", - upName: "catchment", - upSequnce: 3, - visible: false, - }, - { id: "operMngCd", title: "환경청", visible: true }, - { - id: "cityText", - title: "시도", - upName: "adminDiv", - upSequnce: 1, - visible: false, - }, - { - id: "sggText", - title: "시군구", - upName: "adminDiv", - upSequnce: 2, - visible: true, - }, - { id: "bdnstNm", title: "시설명", visible: true }, - { id: "locDiv", title: "지역구분", visible: true }, - { id: "phone", title: "전화번호", visible: true }, - - { id: "fcltQuantity", title: "시설용량(톤/일)", visible: true }, - { id: "rusNm", title: "재이용시설명", visible: true }, - - { - id: "fcltCpct", - title: "시설용량(m³/일)", - upName: "rusSup", - upSequnce: 1, - visible: true, - }, - { - id: "trbt", - title: "하수처리량(m³/일)", - upName: "rusSup", - upSequnce: 2, - visible: true, - }, - { - id: "ruseCpct", - title: "재이용량(m³/일)", - upName: "rusSup", - upSequnce: 3, - visible: true, - }, - - { - id: "total", - title: "합계", - upName: "yearResult", - upSequnce: 1, - visible: true, - }, - { - id: "ithlWtr", - title: "장내용수", - upName: "yearResult", - upSequnce: 2, - visible: true, - }, - { - id: "othlWtr", - title: "장외용수", - upName: "yearResult", - upSequnce: 3, - visible: true, - }, - - { - id: "mngMeth", - title: "운영방식", - upName: "mngInfo", - upSequnce: 1, - visible: true, - }, - { - id: "rprtvBzenty", - title: "대행업체", - upName: "mngInfo", - upSequnce: 2, - visible: true, - }, - { - id: "firstDay", - title: "시작일", - upName: "mngInfo", - upSequnce: 3, - visible: true, - }, - { - id: "LastDay", - title: "종료일", - upName: "mngInfo", - upSequnce: 4, - visible: true, - }, -]; -const rainSttHeadNm: chHeadType[] = [ - { headNm: "bdnstInfo", text: "1.건축물정보", length: 9 }, - { headNm: "rainFcltInfo", text: "2.빗물이용시설정보", length: 7 }, - { headNm: "insenInfo", text: "3.인센티브 정보", length: 9 }, - - { headNm: "adminDiv", text: "행정구역", length: 2 }, - { headNm: "pntfCol", text: "집수면", length: 2 }, - { headNm: "filtrTrtmfct", text: "여과등 처리시설", length: 3 }, - { headNm: "instlCstSprt", text: "설치비지원", length: 2 }, - - { headNm: "grntchBdstCert", text: "녹색건축물인증여부", length: 4 }, -]; - -// id는 다확인해야함 -const rainSttHeadList: TableTripleProps[] = [ - { - id: "cityText", - title: "시도", - visible: true, - upName: ["bdnstInfo", "adminDiv"], - upSequnce: [1, 1], - }, - { - id: "sggText", - title: "시군구", - visible: true, - upName: ["bdnstInfo", "adminDiv"], - upSequnce: [2, 2], - }, - { - id: "bdstNm", - title: "건축물명", - visible: true, - upName: ["bdnstInfo"], - upSequnce: [3], - }, - { - id: "daddr", - title: "주소", - visible: true, - upName: ["bdnstInfo"], - upSequnce: [4], - }, - { - id: "bdstUsgCd", - title: "건축물용도코드", - visible: true, - upName: ["bdnstInfo"], - upSequnce: [5], - }, - { - id: "frstArchPrmsnDt", - title: "최초건축허가일시", - visible: true, - upName: ["bdnstInfo"], - upSequnce: [6], - }, - { - id: "archArea", - title: "건축면적", - visible: true, - upName: ["bdnstInfo"], - upSequnce: [7], - }, - { - id: "lawTrgtYn", - title: "법적의무대상여부", - visible: true, - upName: ["bdnstInfo"], - upSequnce: [8], - }, - { - id: "instlCmptnDt", - title: "설치완료일시", - visible: true, - upName: ["bdnstInfo"], - upSequnce: [9], - }, - - { - id: "instlCst", - title: "설치비용", - visible: true, - upName: ["rainFcltInfo"], - upSequnce: [1], - }, - { - id: "pntfColKnd", - title: "집수지점종류", - visible: true, - upName: ["rainFcltInfo", "pntfCol"], - upSequnce: [2, 1], - }, - { - id: "pntfColArea", - title: "집수지점면적", - visible: true, - upName: ["rainFcltInfo", "pntfCol"], - upSequnce: [3, 2], - }, - { - id: "filtrTrtmfctYn", - title: "여과처리시설유무", - visible: true, - upName: ["rainFcltInfo", "filtrTrtmfct"], - upSequnce: [4, 1], - }, - { - id: "filtrTrtmfctCpct", - title: "여과처리시설용량", - visible: true, - upName: ["rainFcltInfo", "filtrTrtmfct"], - upSequnce: [5, 2], - }, - { - id: "filtrTrtmfctPrs", - title: "여과처리시설처리공정", - visible: true, - upName: ["rainFcltInfo", "filtrTrtmfct"], - upSequnce: [6, 3], - }, - { - id: "dtfcltCpct", - title: "저류조용량", - visible: true, - upName: ["rainFcltInfo"], - upSequnce: [7], - }, - - { - id: "instlCstSprtYn", - title: "설치지원비용여부", - visible: true, - upName: ["insenInfo", "instlCstSprt"], - upSequnce: [1, 1], - }, - { - id: "instlCstSprtAmt", - title: "설치지원비용", - visible: true, - upName: ["insenInfo", "instlCstSprt"], - upSequnce: [2, 2], - }, - - { - id: "grntchBdstCertYn", - title: "녹색건축물인증여부", - visible: true, - upName: ["insenInfo", "grntchBdstCert"], - upSequnce: [3, 1], - }, - { - id: "grntchBdstCertYr", - title: "녹색건축물인증년도", - visible: true, - upName: ["insenInfo", "grntchBdstCert"], - upSequnce: [4, 2], - }, - { - id: "grntchBdstCertNo", - title: "녹색건축물인증번호", - visible: true, - upName: ["insenInfo", "grntchBdstCert"], - upSequnce: [5, 3], - }, - { - id: "grntchBdstCertGrd", - title: "녹색건축물인증등급", - visible: true, - upName: ["insenInfo", "grntchBdstCert"], - upSequnce: [6, 4], - }, -]; -const rainRes: customRainBdst[] = []; - -export type sttnState = { - sttnCommon: { - rainRes: customRainBdst[]; - pbnSttHeadList: TableUpperProps[]; - pbnSttHeadNm: chHeadType[]; - rainSttHeadList: TableTripleProps[]; - rainSttHeadNm: chHeadType[]; - excelList:[]; - isInit:boolean - }; -}; -type sttnActions = { - rainSttnSearch: (page: string, total: string, con: string) => void; - chSttnHead: (checkList: string[], type: string) => void; -}; - -export type sttnType = sttnState & sttnActions; - -export const sttnStateExport: sttnState = { - sttnCommon: { - pbnSttHeadList: pbnSttHeadList, - pbnSttHeadNm: pbnSttHeadNm, - rainSttHeadList: rainSttHeadList, - rainSttHeadNm: rainSttHeadNm, - rainRes: rainRes, - excelList: [], - isInit:false - }, -}; - -export const sttnActionsExport: (set: any) => sttnActions = (set: any) => { - return { - rainSttnSearch: async (page: string, total: string, con: string) => { - try { - const rainRes = await getFetch( - fetchType.WR, - `/reuseFc/rainyInfoList/${page}/${total}/${con}` - ); - if(Number(total) > 9000){ - const rainExcel= excelSttnParsing(rainRes) - set((state: sttnState) => { - return { - ...state, - sttnCommon: { - ...state.sttnCommon, - excelList: rainExcel, - }, - }; - }); - } - else - set((state: sttnState) => { - return { - ...state, - sttnCommon: { - ...state.sttnCommon, - rainRes: rainRes, - isInit: false, - }, - }; - }); - } catch (erTxt) { - console.log("error", erTxt); - } - }, - chSttnHead: async (checkList: string[], type: string) => { - const headList = - type === "pbn" - ? pbnSttHeadList - : type === "rain" - ? rainSttHeadList - : null; - - let chNm = type === "pbn" ? pbnSttHeadNm : rainSttHeadNm; - headList?.forEach((item) => { - if (checkList.find((ch) => ch === item.id)) { - item.visible = false; - if (item.upName) { - const upNames = Array.isArray(item.upName) - ? item.upName - : [item.upName]; - upNames?.forEach((up) => { - chNm.find((ch) => { - if (ch.headNm === up) { - ch.length = ch.length - 1; - } - }); - }); - } - } - }); - set((state: sttnState) => ({ - sttnCommon: { - ...state.sttnCommon, - pbnSttHeadList: - type === "pbn" ? headList : state.sttnCommon.pbnSttHeadList, - rainSttHeadList: - type === "rain" ? headList : state.sttnCommon.rainSttHeadList, - rainSttHeadNm: - type === "rain" ? chNm : state.sttnCommon.rainSttHeadNm, - pbnSttHeadNm: type === "rain" ? chNm : state.sttnCommon.pbnSttHeadNm, - }, - })); - }, - }; -}; - - diff --git a/apps/wr/app/store/store.tsx b/apps/wr/app/store/store.tsx index f826689de..848ba0b03 100644 --- a/apps/wr/app/store/store.tsx +++ b/apps/wr/app/store/store.tsx @@ -33,7 +33,7 @@ import { type rswtFacState, type rswtFacType, } from "./ruseFcltMng/fcltReg/rswtReg"; -import { sttnActionsExport, sttnStateExport, type sttnState, type sttnType } from "./ruseFcltMng/fcltSttn/sttn"; +import { rainSttnActionsExport, rainSttnStateExport, type rainSttnState, type rainSttnType } from "./ruseFcltMng/fcltSttn/rainSttn"; export type WrStore = comCodeType& pubFacType & @@ -44,7 +44,7 @@ export type WrStore = comCodeType& bdstFulType& rainChkgdnType& rswtChkgdnType& - sttnType + rainSttnType ; export const StoreZus = ( @@ -57,7 +57,7 @@ export const StoreZus = ( bdstState & rainChkgdnState& rswtChkgdnState& - sttnState + rainSttnState = { ...comCodeStateExport, ...pubFacStateExport, @@ -68,7 +68,7 @@ export const StoreZus = ( ...bdstStateExport, ...rainChkgdnStateExport, ...rswtChkgdnStateExport, - ...sttnStateExport + ...rainSttnStateExport } ) => { return createStore<WrStore>()((set) => { @@ -89,7 +89,7 @@ export const StoreZus = ( ...bdstActionsExport(set), ...rainChkgdnActionsExport(set), ...rswtChkgdnActionsExport(set), - ...sttnActionsExport(set) + ...rainSttnActionsExport(set) }; }); }; diff --git a/apps/wr/components/lib/func/TableData.tsx b/apps/wr/components/lib/func/TableData.tsx index d6bc9f30e..b6718889a 100644 --- a/apps/wr/components/lib/func/TableData.tsx +++ b/apps/wr/components/lib/func/TableData.tsx @@ -126,7 +126,7 @@ export const chRowspanTable = ( `${value}` ) : ( <Input - className={`${head.type === "number" ? "text-right" : "text-center"} text-3xl`} + className={`${head.type === "number" ? "text-right" : "text-center"} !text-xl`} type={head.type} onChange={(e) => { handleChange(rowIndex, head.id, e.target.value); diff --git a/apps/wr/components/lib/func/commom.tsx b/apps/wr/components/lib/func/commom.tsx index a25ea0278..57e885d38 100644 --- a/apps/wr/components/lib/func/commom.tsx +++ b/apps/wr/components/lib/func/commom.tsx @@ -74,6 +74,6 @@ export const excelSerialToDateString = (excelDate: number|undefined): string => }else{ date =new Date() } - return date.toISOString().split("T")[0] || ""; // "YYYY-MM-DD" + return date.toISOString().split("T")[0]?.replaceAll("-",'') || ""; // "YYYY-MM-DD" }; diff --git a/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx b/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx index 88d7638cf..416561b99 100644 --- a/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx +++ b/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx @@ -101,7 +101,7 @@ useEffect(() =>{ - + const inputClass = '!text-lg' return ( <div className=""> @@ -109,7 +109,7 @@ useEffect(() =>{ <form onSubmit={form.handleSubmit(onSubmit)}> <div> <div className="grid grid-cols-12"> - <h1 className="pl-3 text-xl col-span-10"> + <h1 className="pl-3 !text-lg col-span-10"> {isModal ? "○건축물 운영정보" : "○ 빗물이용시설 정보"} </h1> <Button type="submit" className="mr-4 rounded-lg col-span-2"> @@ -145,7 +145,7 @@ useEffect(() =>{ : new Date(), // Provide a default Date value onChange: (date) => field.onChange(date), }} - selectClass={""} + selectClass={'w-full'} /> </FormUi> )} @@ -159,7 +159,7 @@ useEffect(() =>{ render={({ field }) => ( <FormUi label="설치비"> <Input - className="" + className={inputClass} placeholder="1,000,000" type="number" value={field.value ?? 0} @@ -207,7 +207,7 @@ useEffect(() =>{ render={({ field }) => ( <FormUi label="면적(m³)"> <Input - className="" + className={selectClass} placeholder="1,000,000" type="number" value={field.value ?? 0} @@ -248,7 +248,7 @@ useEffect(() =>{ render={({ field }) => ( <FormUi label="용량(m³/일)"> <Input - className="" + className={selectClass} placeholder="1,000,000" type="number" value={field.value ?? 0} @@ -267,7 +267,7 @@ useEffect(() =>{ render={({ field }) => ( <FormUi label="처리공정"> <Input - className="" + className={selectClass} placeholder="1,000,000" type="" value={field.value ?? ""} diff --git a/apps/wr/components/ui/modal/chkgdExcel/chkgdExcel.tsx b/apps/wr/components/ui/modal/chkgdExcel/chkgdExcel.tsx index c57953781..625fbdebd 100644 --- a/apps/wr/components/ui/modal/chkgdExcel/chkgdExcel.tsx +++ b/apps/wr/components/ui/modal/chkgdExcel/chkgdExcel.tsx @@ -15,10 +15,12 @@ import { Button, Input } from "@common/components/ui"; import { zodResolver } from "@hookform/resolvers/zod"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; +import toast, { Toaster } from "react-hot-toast"; import type { z } from "zod"; +import { ToastFormUi } from "../../toast/toastFromUi"; export default function ChkgdExcel({ type }: { type: string }) { - const { excelDataUPload } = useWrStore((state) => { + const { rainChkExcelDataUPload } = useWrStore((state) => { return state; }); const [files, setFiles] = useState<File[] | null>(null); @@ -37,20 +39,31 @@ export default function ChkgdExcel({ type }: { type: string }) { if(form.getValues("chckYr").length<1 ){ alert("등록년도를 입력해주세요"); + setFiles(null) return } if (file) filePicked(file, 0).then((res) => { if (res !== undefined) + console.log("exex ", excelToRainChkData(res, form.getValues("chckYr"))) setExcelData(excelToRainChkData(res, form.getValues("chckYr"))) }); } }, [files]); const onSubmit =(values: z.infer<typeof rainRegExcel>)=> { + if(values.chckYr ===''){ + console.log(values.chckYr) + ToastFormUi({body:"등록년도를 작성해주세요" ,title:'엑셀등록'}) + return + }else if(excelData ===undefined || excelData?.length === 0 ){ + ToastFormUi({body:"빈 파일입니다." ,title:'엑셀등록'}) + return + } if (excelData) { - excelDataUPload(excelData); + console.log("excelData ", excelData) + rainChkExcelDataUPload(excelData); } } @@ -113,6 +126,7 @@ export default function ChkgdExcel({ type }: { type: string }) { </form> </Form> </div> + <Toaster position="top-center" /> </> ); } diff --git a/apps/wr/components/ui/modal/headChModal/headChModal.tsx b/apps/wr/components/ui/modal/headChModal/headChModal.tsx index 979834dbb..d6b30c199 100644 --- a/apps/wr/components/ui/modal/headChModal/headChModal.tsx +++ b/apps/wr/components/ui/modal/headChModal/headChModal.tsx @@ -9,11 +9,12 @@ import { useForm } from "react-hook-form"; import { z } from "zod"; export default function HeadChModal({type }:{type: string }) { - const { sttnCommon ,chSttnHead} = useWrStore((state) => state); + const { rainSttn ,rainChSttnHead} = useWrStore((state) => state); - const { rainSttHeadList,pbnSttHeadList } =sttnCommon; - let items = rainSttHeadList.map(item => ({id:item.id, label:item.title})); + const { rainSttHeadList } =rainSttn; + let items = rainSttHeadList.map(item => ({id:item.id, label:item.title, val:item.visible })); + const FormSchema = z.object({ @@ -31,12 +32,17 @@ export default function HeadChModal({type }:{type: string }) { }) - + useEffect(() =>{ + form.reset({ data: items.map((el) => el.val!==undefined ? el.val.toString():undefined )}) + + + + },[rainSttHeadList]) const onSubmit = (val : z.infer<typeof FormSchema>) =>{ if(val?.data.length > 0) - chSttnHead(val?.data, 'rain') + rainChSttnHead(val?.data, ) } diff --git a/apps/wr/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable.tsx b/apps/wr/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable.tsx index 376ab7a95..b378167cc 100644 --- a/apps/wr/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable.tsx +++ b/apps/wr/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable.tsx @@ -1,6 +1,6 @@ 'use client' -import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/page"; +import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead"; import { useWrStore } from "@/app/store"; import { UiTable } from "@common/business_components/ui"; diff --git a/apps/wr/components/ui/toast/toastFromUi.tsx b/apps/wr/components/ui/toast/toastFromUi.tsx index 465870c8b..5886c2e0b 100644 --- a/apps/wr/components/ui/toast/toastFromUi.tsx +++ b/apps/wr/components/ui/toast/toastFromUi.tsx @@ -1,55 +1,46 @@ - import { Button } from "@common/components/ui"; import Link from "next/link"; import toast from "react-hot-toast"; +interface toastFormType { + body: string; + title: string; + url?: string; + buttonName?: string; +} - -export function ToastFormUi(body:string,title:string,url:string,buttonName:string){ - +export function ToastFormUi({ body, title, url, buttonName }: toastFormType) { //const router = useRouter(); - return( - - toast.custom((t) => ( - - <div - className={`${ - t.visible ? 'animate-enter' : 'animate-leave' - } w-4/12 h-40 bg-white shadow-lg rounded-lg pointer-events-auto flex ring-1 ring-black ring-opacity-5`} - > - <div className="w-full flex-1 py-10"> - <div className="flex items-start"> - <div className="flex-shrink-0 pt-0.5"> - - </div> - <div className="ml-3 flex-1"> - <p className="text-xl font-medium underline"> - {title} - </p> - <p className="mt-1 text-2xl"> - {body} - </p> - </div> - </div> - </div> - <div className="flex py-20"> - <Button - size='sm' - onClick={() => toast.dismiss(t.id)} - > - <Link href={url}> {buttonName}</Link> - </Button> - </div> - <div className="flex pl-4 pr-4 py-20"> - <Button - onClick={() => toast.dismiss(t.id)} - size='sm' - > - 닫기 - </Button> + return toast.custom((t) => ( + <div + className={`${ + t.visible ? "animate-enter" : "animate-leave" + } w-4/12 h-40 bg-white shadow-lg rounded-lg pointer-events-auto flex ring-1 ring-black ring-opacity-5`} + > + <div className="w-full flex-1 py-10"> + <div className="flex items-start"> + <div className="flex-shrink-0 pt-0.5"></div> + <div className="ml-3 flex-1"> + <p className="text-xl font-medium underline">{title}</p> + <p className="mt-1 text-2xl">{body}</p> </div> </div> - )) - ) -} \ No newline at end of file + </div> + <div className="flex py-20"> + {url && buttonName ? ( + <Button size="sm" onClick={() => toast.dismiss(t.id)}> + <Link href={url}> {buttonName}</Link> + </Button> + ) : ( + <></> + )} + </div> + <div className="flex pl-4 pr-4 py-20"> + <Button onClick={() => toast.dismiss(t.id)} size="sm"> + 닫기 + </Button> + </div> + </div> + )); +} From 8584ed0162b7dff59787109e88263b0031dca08c Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Fri, 2 May 2025 16:16:51 +0900 Subject: [PATCH 26/29] =?UTF-8?q?=EC=97=91=EC=85=80=20=EB=82=A0=EC=A7=9C?= =?UTF-8?q?=20=EB=B3=80=ED=99=98=20=20=ED=95=A8=EC=88=98=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx | 7 ++++--- apps/wr/components/lib/func/commom.tsx | 12 ------------ 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx index ddad628fa..a01a6e6a5 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx @@ -106,15 +106,16 @@ export const rainHeadNm: chHeadType[] = [ ]; + export const rainChkgdnHeadList: TableUpperProps[] = [ { id: "order", title: "순번", rowSpan: true }, { id: "cityText", title: "시도", rowSpan: true }, { id: "sggText", title: "시군구", rowSpan: true }, { id: "bdstNm", title: "시설명", rowSpan: true }, { id: "operMngCd", title: "운영관리형태", rowSpan: true }, - { id: "flowCheck", title: "유량측정방법", rowSpan: true }, - { id: "yearFee", title: "연간운영비(원/년)", rowSpan: true }, - { id: "rainDtnbaOpct", title: "빗물저류조용량(m³)", rowSpan: true }, + { id: "oilqMeasMthd", title: "유량측정방법", rowSpan: true }, + { id: "anlOperCst", title: "연간운영비(원/년)", rowSpan: true }, + { id: "dtfcltCpct", title: "빗물저류조용량(m³)", rowSpan: true }, { id: "chckYmd", title: "점검일", rowSpan: true }, { id: "utztnUsgCd", title: "이용용도" }, { id: "totalSplyUswtrUtztnQnt", title: "연간보급수이용량(m³)" }, diff --git a/apps/wr/components/lib/func/commom.tsx b/apps/wr/components/lib/func/commom.tsx index 0e53c981f..5f921e0a9 100644 --- a/apps/wr/components/lib/func/commom.tsx +++ b/apps/wr/components/lib/func/commom.tsx @@ -64,15 +64,3 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => { -//엑셀은 날짜가 숫자로 나와서 만든 함수 -export const excelSerialToDateString = (excelDate: number|undefined): string => { - const excelEpoch = new Date(1899, 11, 30); // Excel 기준일 (1900-01-01보다 하루 전) - let date - if(excelDate){ - date = new Date(excelEpoch.getTime() + excelDate * 86400000); - }else{ - date =new Date() - } - return date.toISOString().split("T")[0]?.replaceAll("-",'') || ""; // "YYYY-MM-DD" -}; - From 826b49d72afc6137643f7d449b240d4e8e9379e3 Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Fri, 2 May 2025 16:19:36 +0900 Subject: [PATCH 27/29] =?UTF-8?q?=EC=97=91=EC=85=80=20to=20json=20=200?= =?UTF-8?q?=EB=B2=88=EC=A7=B8=20=EC=8B=9C=ED=8A=B8=EB=A7=8C=20=EB=B0=94?= =?UTF-8?q?=EB=9D=BC=EB=B3=B4=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/excel/index.tsx | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/common/business_components/src/ui/excel/index.tsx b/packages/common/business_components/src/ui/excel/index.tsx index 13a814114..c17aa0660 100644 --- a/packages/common/business_components/src/ui/excel/index.tsx +++ b/packages/common/business_components/src/ui/excel/index.tsx @@ -29,19 +29,22 @@ export const filePicked=(oFile: File, headerNum:number=0):Promise<JSON | undefin resolve(undefined); return; } - const wb = XLSX.read(data, { type: 'binary' }); + //셀데이터에서 데이트 형식으로 입력하면 yyyymmdd 형식으로 변환 + const wb = XLSX.read(data, { type: 'binary', cellDates: true, dateNF: "yyyymmdd" }); let jsonXls: JSON | undefined; - //TODO 시트가 2개이상일 경우 마지막 시트의 데이터만 표출됨 // Loop Over Each Sheet - wb.SheetNames.forEach(function (sheetName) { + wb.SheetNames.forEach(function (sheetName,index ) { // Obtain The Current Row As CSV - const sheet = wb.Sheets[sheetName]; - - if (sheet) { - jsonXls = XLSX.utils.sheet_to_json(sheet, { range: headerNum }) as unknown as JSON; - } else { - console.error(`Sheet "${sheetName}" is undefined.`); + // 일단 첫번째 시트만 읽을 수 있도록 수정 + if(index ===0){ + const sheet = wb.Sheets[sheetName]; + + if (sheet) { + jsonXls = XLSX.utils.sheet_to_json(sheet, { range: headerNum, raw:false }) as unknown as JSON; + } else { + console.error(`Sheet "${sheetName}" is undefined.`); + } } }); resolve(jsonXls); From 4455cc3b55e98e23b45876d1c2dc4b679979223f Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Tue, 6 May 2025 23:08:26 +0900 Subject: [PATCH 28/29] =?UTF-8?q?=EC=A7=80=EB=8F=84=EC=A0=90=EA=B2=80=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B8=B0=ED=83=80=20=EC=88=98=EC=A0=95=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/ruseFcltMng/fcltReg/rainReg/page.tsx | 84 +-- .../app/ruseFcltMng/fcltReg/rswtReg/page.tsx | 35 +- .../fcltSttn/rainSttn/TableHead.tsx | 57 -- .../ruseFcltMng/fcltSttn/rainSttn/page.tsx | 36 +- .../ruseFcltMng/prfmncReg/chkgdnReg/page.tsx | 38 +- apps/wr/app/store/common/code/index.ts | 1 + apps/wr/app/store/common/type/headder.tsx | 23 + .../prfmncReg/chkgdnReg/rainChkgdn/index.tsx | 41 +- .../ruseFcltMng/fcltReg/rainReg/index.tsx | 113 ++-- .../ruseFcltMng/fcltReg/rswtReg/index.tsx | 316 +++++---- .../fcltSttn/pbnstSttn/headList.tsx | 6 +- .../fcltSttn/rainSttn/headList.tsx | 602 +++++++++--------- .../ruseFcltMng/fcltSttn/rainSttn/index.tsx | 120 +++- apps/wr/components/lib/func/TableData.tsx | 7 +- apps/wr/components/lib/func/commom.tsx | 29 +- .../ui/form/fcltReg/bdstReg/bdstReg.tsx | 166 +++-- .../ui/form/fcltReg/htdflReg/htdflRegForm.tsx | 180 ++++-- .../ui/form/fcltReg/rainReg/rainRegForm.tsx | 50 +- .../ui/form/fcltReg/rswtrReg/rswtrRegForm.tsx | 163 +++-- .../ui/modal/chkgdExcel/chkgdExcel.tsx | 14 +- .../ui/modal/headChModal/headChModal.tsx | 83 +-- .../chkgdTable/rainChkgd/rainChkgdTable.tsx | 50 +- .../rainChkgd/rainChkgdTableModal.tsx | 13 - 23 files changed, 1185 insertions(+), 1042 deletions(-) delete mode 100644 apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/TableHead.tsx create mode 100644 apps/wr/app/store/common/type/headder.tsx delete mode 100644 apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTableModal.tsx diff --git a/apps/wr/app/ruseFcltMng/fcltReg/rainReg/page.tsx b/apps/wr/app/ruseFcltMng/fcltReg/rainReg/page.tsx index af78efb00..30ddd1f4a 100644 --- a/apps/wr/app/ruseFcltMng/fcltReg/rainReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltReg/rainReg/page.tsx @@ -1,12 +1,11 @@ "use client"; import { useWrStore } from "@/app/store"; -import type { - chgBuilding, - customRainBdst, - TableUpperProps, +import { + type chgBuilding, + type customRainBdst, } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import { tableData } from "@/components/lib/func/commom"; -import RainRegForm from "@/components/ui/form/fcltReg/rainReg/rainRegForm"; +import RainRegForm from "@/components/ui/form/fcltReg/rainReg/rainRegForm"; import BdstChgModal from "@/components/ui/modal/bdstChgModal/bdstChgModal"; import { BdstReg } from "@/components/ui/modal/bdstRegModal/bdstRegModal"; import { @@ -21,19 +20,17 @@ import { UiTable, } from "@common/business_components"; import ListDiv from "@common/business_components/ui/list_div"; -import { Button, TableHead, TableRow } from "@common/components"; +import { Button } from "@common/components"; import { useEffect, useState } from "react"; -import { headMakeColSpan } from "./TableHead"; - export default function Home() { - const { rain, code, init } = useWrStore((state) => { + const { rain, code, initRain, rainSearch, getRainData } = useWrStore((state) => { return state; }); const { rainRes } = rain; const [rainForm, setRainForm] = useState<customRainBdst>(); const [issNewReg, setIsNewReg] = useState<boolean>(false); - + const [pageNation, setPageNation] = useState(1); const [bdstTable, setbdstTable] = useState<customRainBdst[]>(); const [searchTxt, setSearchTxt] = useState<string>(); const [bdstChgProps, setBdstChgProps] = useState<{ @@ -41,16 +38,24 @@ export default function Home() { chgBuilding: chgBuilding[]; }>({ isOpen: false, chgBuilding: [] }); - const nodeList = headMakeColSpan(rain.upHeadList); useEffect(() => { if (!rain.isInit) { - init(undefined); + initRain('41'); } - }, [rain.isInit, init]); + }, [rain.isInit, initRain]); useEffect(() => { if (code.sggCd.length > 0) { - setbdstTable(tableData(rainRes, { code })); + const rainData = tableData(rainRes, { code }).map( + (item: customRainBdst) => { + return { + ...item, + bdstChgYn: item.chgBuilding.length > 0 ? "Y" : "N", + }; + } + ); + + setbdstTable(rainData); } }, [code, rainRes]); const cellClick: (val: number | undefined, headId: string) => void = ( @@ -76,8 +81,9 @@ export default function Home() { }; useEffect(() => { - console.log("rainForm", rainForm); - }, [rainForm]); + console.log("getPageNation", pageNation); + getRainData(pageNation, "41"); + }, [pageNation]); return ( <> @@ -88,7 +94,7 @@ export default function Home() { <SearchDiv> <SearchFormLeft> <SearchInput - className="col-span-3 my-7" + className={" col-span-3 my-7 !text-3xl"} label="건물명" textValue={searchTxt || ""} setText={(e) => { @@ -96,24 +102,24 @@ export default function Home() { }} /> </SearchFormLeft> - <SearchFormRight > + <SearchFormRight> <div className="flex flex-row space-x-2"> - <Button - className="" - size={"sm"} - onClick={(e) => { - init(searchTxt || ""); - }} - > - 조회 - </Button> - <Button - size={"sm"} - className="" - onClick={() => setIsNewReg(!issNewReg)} - > - 신규등록 - </Button> + <Button + className="" + size={"sm"} + onClick={(e) => { + rainSearch(searchTxt || "", pageNation, "41"); + }} + > + 조회 + </Button> + <Button + size={"sm"} + className="" + onClick={() => setIsNewReg(!issNewReg)} + > + 신규등록 + </Button> </div> </SearchFormRight> </SearchDiv> @@ -121,19 +127,19 @@ export default function Home() { </div> <div className="h-screen grid grid-cols-6 gap-4 !overflow-y-scroll"> <div className="col-span-4 h-full min-h-0"> - <ListDiv className="h-full min-h-0"> + <ListDiv className="h-full min-h-0"> <ScrollArea className="h-[60vh]"> <UiTable tableData={bdstTable || []} headlist={rain.upHeadList} - pageSize={100} - total={10} + pageSize={20} + total={10000} headName={"○건축물 목록"} cellClick={(val, headId) => { cellClick(val, headId); }} + onPageChange={setPageNation} > - {nodeList} </UiTable> </ScrollArea> </ListDiv> @@ -149,7 +155,7 @@ export default function Home() { </div> <UiModal body={<BdstReg moType="RNB"></BdstReg>} - bodyClass="w-[90vw] max-w-none" + bodyClass="w-[30vw] max-w-none" open={issNewReg} onOpenChange={(open) => { setIsNewReg(open); diff --git a/apps/wr/app/ruseFcltMng/fcltReg/rswtReg/page.tsx b/apps/wr/app/ruseFcltMng/fcltReg/rswtReg/page.tsx index 473ac6889..597973ac9 100644 --- a/apps/wr/app/ruseFcltMng/fcltReg/rswtReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltReg/rswtReg/page.tsx @@ -23,28 +23,37 @@ import type { chgBuilding } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import { headMakeColSpan } from "../rainReg/TableHead"; export default function Home() { - const { code, rswt, initRswt } = useWrStore((state) => state); - const nodeList = headMakeColSpan(rswt.upHeadList); + const { code, rswt, initRswt ,rswtBdstSearch,getRswtBdstData} = useWrStore((state) => state); const [rswtForm, setRswtForm] = useState<customRswtBdst>(); const [searchTxt, setSearchTxt] = useState<string>(); const [issNewReg, setIsNewReg] = useState<boolean>(false); + const [pageNation, setPageNation] = useState(1); const [bdstTable, setbdstTable] = useState<customRswtBdst[]>(); const [bdstChgProps, setBdstChgProps] = useState<{ isOpen: boolean; chgBuilding: chgBuilding[]; }>({ isOpen: false, chgBuilding: [] }); - const { rswtRes } = rswt; useEffect(() => { if (!rswt.isInit) { - initRswt(undefined); + initRswt('41'); } }, [rswt.isInit, initRswt]); useEffect(() => { if (code.sggCd.length > 0) { - setbdstTable(tableData(rswtRes, { code })); + const rswtData = tableData(rswtRes, { code }).map( + (item: customRswtBdst) => { + return { + ...item, + bdstChgYn: item.chgBuilding.length > 0 ? "Y" : "N", + bdstUsgCd: item.reuseBuilding[0]?.bdstUsgCd + }; + } + ); + console.log(rswtData) + setbdstTable(rswtData); } }, [code, rswtRes]); const cellClick: (val: number | undefined, headId: string) => void = ( @@ -69,6 +78,10 @@ export default function Home() { const bdstChgModal = (chgBuilding: chgBuilding[]) => { setBdstChgProps({ isOpen: true, chgBuilding: chgBuilding }); }; + useEffect(() => { + getRswtBdstData(pageNation, "41"); + }, [pageNation]); + return ( <> @@ -93,7 +106,7 @@ export default function Home() { size={"sm"} className="mr-4 " onClick={(e) => { - initRswt(searchTxt || ""); + rswtBdstSearch(searchTxt || "",pageNation,'41'); }} > 조회 @@ -117,12 +130,12 @@ export default function Home() { <UiTable tableData={bdstTable || []} headlist={rswt.upHeadList} - pageSize={100} - total={10} + pageSize={20} + total={10000} headName={"○건축물 목록"} - cellClick={cellClick} - > - {nodeList} + cellClick={cellClick} + onPageChange={setPageNation} + > </UiTable> </ListDiv> </div> diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/TableHead.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/TableHead.tsx deleted file mode 100644 index 7b7065ffa..000000000 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/TableHead.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; -import type { TableTripleProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; -import { TableHead, TableRow } from "@common/components/ui"; - -export const headMakeTriple = ( - upHeadList: TableTripleProps[], - makeHeadNm: chHeadType[], - rowCount: number = 2 -) => { - return ( - <> - {Array.from({ length: rowCount }).map((_, i) => ( - <TableRow key={i}> - {upHeadList - .filter((head: TableTripleProps) => head.visible == true) - .map((head: TableTripleProps) => - !head.upSequnce[i] ? ( - <TableHead - className={`border border-gray-600 px-2 py-1 `} - rowSpan={2} - key={head.id} - > - {head.title} - </TableHead> - ) : head.upSequnce[i] === 1 ? ( - <TableHead - className={`border border-gray-600 px-2 py-1 `} - key={head.id} - rowSpan={1} - colSpan={ - makeHeadNm.find((ch) => ch.headNm === head.upName[i]) - ?.length - } - > - {makeHeadNm.find((ch) => ch.headNm === head.upName[i])?.text} - </TableHead> - ) : null - )} - </TableRow> - ))} - <TableRow> - {upHeadList.map((head: TableTripleProps) => - makeHeadNm.find( - (ch) => ch.headNm === head?.upName[1] && head.visible == true - ) ? ( - <TableHead - className={`border border-gray-600 px-2 py-1 `} - key={head.id} - > - {head.title} - </TableHead> - ) : null - )} - </TableRow> - </> - ); -}; \ No newline at end of file diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index 003e4cdf8..b537fcfcc 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -15,7 +15,8 @@ import { import ListDiv from "@common/business_components/ui/list_div"; import { Button } from "@common/components/ui"; import { useCallback, useEffect, useRef, useState } from "react"; -import { headMakeTriple } from "./TableHead"; +import type { customRainBdst } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; +import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan"; export default function RainSttn() { const { code, rainSttn, rainSttnSearch } = @@ -23,11 +24,7 @@ export default function RainSttn() { const { rainSttnRes } = rainSttn; const [isChHead, setIsChHead] = useState(false); const ref = useRef<ReturnType>({} as ReturnType); - const [bdstTable, setBdstTable] = useState<any[]>(); - // const nodeList = headMakeTriple( - // rainSttn.rainSttHeadList, - // rainSttn.rainSttHeadNm - // ); + const [bdstTable, setBdstTable] = useState<customRainBdst[]>(); useEffect(() => { if (!rainSttn.isInit) { @@ -41,22 +38,43 @@ export default function RainSttn() { } }, [rainSttn.isInit, rainSttnSearch]); + useEffect(() => { - if (rainSttnRes.length > 0) { + if (rainSttnRes.length > 0 && code.cityCd.length>0) { const data = tableData(rainSttnRes, { code }); - const chData = data .map((item: any) => ({ + ...item, ...item.reuseBuilding[0], ...item.reuseBuilding[0].rainyObj, + // cityText:item.cityText, + // sggText:item.sggText, + // bdstNm: item.bdstNm, + // daddr:item.daddr, + // bdstUsgCd:item.bdstUsgCd, + // frstArchPrmsnDt:item.frstArchPrmsnDt, + // archArea:item.archArea, + // lawTrgtYn:item.lawTrgtYn, + // instlCmptnDt:item.instlCmptnDt, + // instlCst:item.instlCst, + + + + })) .filter((item: any) => item.rainyObj !== undefined); setBdstTable(chData); } }, [code, rainSttnRes, rainSttn.rainSttHeadList]); + + + useEffect(() =>{ +console.log(rainSttn.rainSttNodeList) + },[rainSttn.rainSttNodeList]) + useEffect(() => { if(rainSttn.excelList.length>0){ @@ -122,6 +140,7 @@ export default function RainSttn() { <UiTable headName={[]} tableData={bdstTable || []} + children={<HeadMakeColSpan upHeadList={rainSttn.rainSttNodeList}/>} headlist={rainSttn.rainSttHeadList} pageSize={0} total={0} @@ -130,7 +149,6 @@ export default function RainSttn() { throw new Error("Function not implemented."); }} > - {/* {nodeList} */} </UiTable> </ListDiv> </div> diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx index 0e5feb399..fc8fb1e0a 100644 --- a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx @@ -7,6 +7,7 @@ import { } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; import { excelDownload } from "@/components/lib/func/commom"; import ChkgdExcel from "@/components/ui/modal/chkgdExcel/chkgdExcel"; +import ChkgdModal from "@/components/ui/modal/chkgdModal/chkgdModal"; import RainChkgdTable from "@/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable"; import RainChkgdTableModal from "@/components/ui/table/chkgdTable/rainChkgd/rainChkgdTableModal"; import RswtChkgdTable from "@/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable"; @@ -23,16 +24,18 @@ import { import ListDiv from "@common/business_components/ui/list_div"; import { Button } from "@common/components/ui"; import { useCallback, useEffect, useState } from "react"; +import { Toaster } from "react-hot-toast"; //----------------------- export default function Page() { - const { code, rainChkgdn, rainChkInit,rainChkDetilUpdate, rainChkExcelDownload } = useWrStore((state) => { + const { code, rainChkgdn, rainChkInit,rainChkDetilUpdate, rainChkDelete , rainChkExcelDownload } = useWrStore((state) => { return state; }); const [isRegExcel, setIsRegExcel] = useState(false); const [searchTxt, setSearchTxt] = useState<string>(); const [updateRainDetail, setUpdateRainDetail] = useState<rainChkZodType[]>([]); + const [deleteIdx, setDeleteIdx ] = useState<number[]> ([]); const [selFcltDiv, setSelFcltDiv] = useState("RNB"); const [isModal, setIsModal] = useState({ open: false, @@ -40,19 +43,19 @@ export default function Page() { }); const cellClick = () => { if(searchTxt) - rainChkInit(searchTxt,'41') + rainChkInit(searchTxt,'0') }; useEffect(() => { if (!rainChkgdn.isInit) { rainChkInit('2024','0'); + setIsModal({data:{}, open:rainChkgdn.isModalClose }) + setIsRegExcel(false) } }, [rainChkgdn.isInit, rainChkInit]); - - useEffect(() => { excelDownload(rainChkgdn.excelList ,'빗물이용시설 지도점검','sample_rainy.xlsx', 'A1:AN1'); }, [rainChkgdn.excelList]); @@ -60,10 +63,22 @@ export default function Page() { const excelClick= useCallback(()=>{ rainChkExcelDownload(code.cityCd, code.sggCd); }, [rainChkExcelDownload, code.cityCd, code.sggCd]); + + + const handleClick = useCallback((data:any) => { if(data) setIsModal({ open: true, data: data }); }, [isModal]); + const clickDelete=(data:number[])=>{ + if(data.length>0){ + data.forEach((data) =>{ + rainChkDelete( String(data) ) + }) + } + } + + return ( <ContentsDiv> <div className="grid grid-cols-4 gap-4 "> @@ -97,7 +112,7 @@ export default function Page() { > 조회 </Button> - <Button size={"sm"} onClick={() => {}}> + <Button size={"sm"} onClick={() => { clickDelete(deleteIdx) }}> 삭제 </Button> <Button size={"sm"} onClick={() => { rainChkDetilUpdate( updateRainDetail as rainChkZodType[]) }}> @@ -124,18 +139,25 @@ export default function Page() { <div className="grid grid-cols-6 gap-4 "> <div className="col-span-6"> <ListDiv> - {selFcltDiv === "RNB" ? <RainChkgdTable detailUp={setUpdateRainDetail} handleClick={handleClick} /> : <RswtChkgdTable />} + {selFcltDiv === "RNB" ? <RainChkgdTable deleteData={setDeleteIdx} detailUp={setUpdateRainDetail} handleClick={handleClick} /> : <RswtChkgdTable />} </ListDiv> </div> </div> - - <RainChkgdTableModal isModal={isModal} setIsModal={setIsModal}/> + <UiModal + open={isModal.open} + onOpenChange={() => { + setIsModal({ open: !open, data: {} }); + }} + bodyClass={"w-[80vw] max-w-none"} + body={<ChkgdModal type={"RNB"} obj={isModal.data} />} + ></UiModal> <UiModal open={isRegExcel} onOpenChange={setIsRegExcel} bodyClass={"w-[40vw] max-w-none"} body={<ChkgdExcel type={selFcltDiv}></ChkgdExcel>} /> + <Toaster position="top-center" /> </ContentsDiv> ); } diff --git a/apps/wr/app/store/common/code/index.ts b/apps/wr/app/store/common/code/index.ts index a0a761f3e..e5f25e318 100644 --- a/apps/wr/app/store/common/code/index.ts +++ b/apps/wr/app/store/common/code/index.ts @@ -12,6 +12,7 @@ export const btnClass= "p-4 m-2 text-white rounded-sm text-lg font-medium " //공통 건축물 용도 const bdstUsgCd: SelectDataType[] = [ + { val: '-1', text: "확인불가" }, { val: '1', text: "운동장" }, { val: '2', text: "체육관" }, { val: '3', text: "공공업무시설" }, diff --git a/apps/wr/app/store/common/type/headder.tsx b/apps/wr/app/store/common/type/headder.tsx new file mode 100644 index 000000000..e11fae01c --- /dev/null +++ b/apps/wr/app/store/common/type/headder.tsx @@ -0,0 +1,23 @@ +export type CommonTableProps = { + id: string; + title: string; + upName?: string; + upSequnce?: number; + row?: number; + rowSpan?: number; + colSpan?: number; + visible?: boolean; +}; + +export type TableUpperProps = { + id: string; + title: string; + upName?: string; + upSequnce?: number; + edit?:boolean; + visible?:boolean; + rowSpan?: true; + type?: string; + }; + + \ No newline at end of file diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx index a01a6e6a5..9f51eed50 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx @@ -2,7 +2,7 @@ import { TEST_UUID, type TableUpperProps, } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; -import { fetchType, getFetch, postFectch, putFectch } from "@/components/lib/api"; +import { deleteFectch, fetchType, getFetch, postFectch, putFectch } from "@/components/lib/api"; import type { SelectDataType } from "@common/business_components/ui"; import { z } from "zod"; import { buildingToExcelType, excelToRainChkData } from "./excel"; @@ -302,6 +302,7 @@ export type rainChkgdnState = { splHeadList: TableUpperProps[]; rswtDetailHeadList: TableUpperProps[]; isInit: boolean; + isModalClose:boolean; excelList:[]; }; }; @@ -312,6 +313,7 @@ type rainChkgdnActions = { rainChkGuidUpdate(rainChk: rainChkZodType): Promise<void>; rainChkExcelDownload(sidoCode: SelectDataType[],sggCode: SelectDataType[]): Promise<void> rainChkExcelDataUPload(excelData:rainChkZodType[]) : Promise<void> + rainChkDelete(chkgdnPk:string) :Promise<void> }; export type rainChkgdnType = rainChkgdnState & rainChkgdnActions; @@ -325,6 +327,7 @@ export const rainChkgdnStateExport: rainChkgdnState = { ruseHeadList: ruseHeadList, rswtDetailHeadList: rswtDetailHeadList, isInit: false, + isModalClose:false, excelList:[] }, }; @@ -379,7 +382,7 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( try{ const res = await postFectch("/reuseChk/rainyExcel", excelData); if (res.ok) { - ToastFormUi({body:"엑셀 데이터 업로드가 성공하였습니다. " ,title:'엑셀등록'}) + ToastFormUi({body:"지도점검 등록이 완료되었습니다. " ,title:'지도점검 등록'}) } const rainChkRes = await initFetch('2024', '0'); return set((state: rainChkgdnState) => ({ @@ -391,7 +394,7 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( })); }catch(error){ console.log(error); - ToastFormUi({body:"엑셀 데이터 업로드를 실패하였습니다. " ,title:'엑셀등록'}) + ToastFormUi({body:"지도점검 등록이 실패되었습니다." ,title:'지도점검 등록'}) } }, rainChkInit: async (searchTxt: string, sggCd: string) => { @@ -415,11 +418,9 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( const res = await postFectch("/reuseChk/rainyExcel", rainChk); if (res.ok) { - alert(" 수정이 완료되었습니다."); + ToastFormUi({body:"지도점검 보급수 및 밋물이용량 수정이 완료되었습니다. " ,title:'지도점검 수정'}) } - const rainChkRes = await initFetch('2024', '0'); - return set((state: rainChkgdnState) => ({ ...state, rainChkgdn: { @@ -433,13 +434,11 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( } }, rainChkGuidUpdate: async (rainChk: rainChkZodType) => { - try{ - //const chData = await makeMdfrChk(rainChk, "guideDetails", "rainDetil"); const res = await putFectch("/reuseChk/rainy", rainChk); if (res.ok) { - alert(" 수정이 완료되었습니다."); + ToastFormUi({body:"지도점검 수질 및 과태료 수정이 완료되었습니다. " ,title:'지도점검 수정'}) } const rainChkRes = await initFetch('2024', '0'); return set((state: rainChkgdnState) => ({ @@ -454,6 +453,30 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( } + }, + rainChkDelete: async (chkgdnPk:string) =>{ + try{ + const res = await deleteFectch(`/reuseChk/rainy/${chkgdnPk}`,''); + + if(res.ok){ + ToastFormUi({body:"삭제가 완료되었습니다. " ,title:'지도점검 삭제'}) + } + const rainChkRes = await initFetch('2024', '0'); + return set((state: rainChkgdnState) => ({ + ...state, + rainChkgdn: { + ...state.rainChkgdn, + rainChk: rainChkRes, + }, + })); + + + }catch(error){ + ToastFormUi({body:"삭제를 실패했습니다.. " ,title:'지도점검 삭제'}) + + } + + } diff --git a/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx index 855d05d71..f857671a9 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx @@ -1,11 +1,8 @@ import { getFetch, postFectch, putFectch } from "@/components/lib/api"; import { z } from "zod"; import { makeMdfr, makeRstr } from "../bdstReg"; -import type { SelectDataType } from "@common/business_components/ui"; - export const TEST_UUID= '2d4b151d-1828-41e0-91d9-4cd28ea1cc7e' - export const rainZod = z.object({ bdstInfoPk: z.number().optional(), ctpvCd: z.number().default(0), @@ -23,11 +20,11 @@ export const rainZod = z.object({ bdstRuseFcltPk: z.number().nullish(), bdstInfoFk:z.number().nullish(), instlCmptnDt: z.coerce.date().default(() => new Date()), - instlCst: z.number().default(0), + instlCst: z.number().nullish(), operMngCd: z.string().optional().default(""), anlOperCst: z.number().default(0), instlCstSprtYn: z.string().default(""), - instlCstSprtAmt: z.number().nullish(), + instlCstSprtAmt: z.number().nullish(), grntchBdstCertYn: z.enum(["Y", "N"]).nullish(), grntchBdstCertYr: z.string().default("") .refine((year)=> year.length===0 || /^\d{4}$/.test(year),{ @@ -35,7 +32,7 @@ export const rainZod = z.object({ }), grntchBdstCertNo: z.string().default(""), grntchBdstCertGrd: z.string().default(""), - crgRdctYn: z.enum(["Y", "N"]), // 안쓰는 값 + crgRdctYn: z.enum(["Y", "N"]).nullish(), // 안쓰는 값 crgRdctBss: z.string().default("").nullish(), /// 안쓰는 값 crgRdctAmt: z.number().default(0), // 안쓰는 값 ruseFcltFlg: z.string().default(""), @@ -75,8 +72,6 @@ export const rainZod = z.object({ ).default([]) }); - - export type chgBuilding={ bdstInfoFk?: number|null, archChgPrmsnDt?: Date, @@ -85,11 +80,7 @@ export type chgBuilding={ rgtr?:string|null; mdfr?:string|null; } - - export type customRainBdst = z.infer<typeof rainZod> - - export type TableUpperProps = { id: string; title: string; @@ -101,58 +92,38 @@ export type TableUpperProps = { type?: string; }; - - - - -export type TableTripleProps = { - id: string; - title: string; - upName: string[]; - upSequnce: number[]; - edit?:boolean; - visible?:boolean; -}; - - export const upHeadList: TableUpperProps[] = [ { id: "cityText", title: "시도" }, { id: "sggText", title: "시군구" }, { id: "bdstNm", title: "시설명" }, { id: "daddr", title: "위치" }, { id: "bdsgUsgText", title: "건축물용도" }, - // { id: "bdstUsgCd", title: "건축물용도" }, { id: "frstArchPrmsnDt", title: "최초건축허가일" }, { id: "archArea", title: "건축면적" }, { id: "lawTrgtYn", title: "법적의무대상여부" }, { id: "bdstChgYn", title: "건축물변경여부" }, - // { id: "archChgPrmsnDt", title: "허가일", upName: "upChangeRe", upSequnce: 2 }, - // { id: "archChgArea", title: "면적", upName: "upChangeRe", upSequnce: 3 }, ]; const rainRes: customRainBdst[] = []; export const selectClass = "w-full h-full !text-2xl"; -const selectYN = [ - { text: "Y", val: "1" }, - { text: "N", val: "2" }, -]; + export type rainFacState = { rain: { isInit: boolean; upHeadList: TableUpperProps[]; - selectYN: SelectDataType[]; rainRes: customRainBdst[]; // regRainForm:customRainBdst, }; }; type rainFacSActions = { - init: (txt:string|undefined) => void; - rainSearTxt: (txt:string) => void; - rainReg: (data: customRainBdst) => void; - rainUpdate: (data: customRainBdst) => void; + initRain: (code:string|number) => void; + getRainData:(pageNation:number, code:string|number) =>void; + rainSearch: (txt:string,pageNation:number,code:string|number) => void; + rainBdstReg: (data: customRainBdst, code:string|number) => void; + rainBdstUpdate: (data: customRainBdst, code:string|number) => void; }; export type rainFacType = rainFacState & rainFacSActions; @@ -162,37 +133,42 @@ export const rainFacStateExport: rainFacState = { isInit: false, rainRes: rainRes, upHeadList: upHeadList, - selectYN: selectYN, - //regRainForm:regRainForm, - }, }; - - - -const initFetch = async (txt:string|undefined) => { - - const rainRes =await getFetch("wr", `/reuseFc/rainyInfoList/1/20/41` +(txt? `/${txt}`:'')); - const chRainRes = rainRes.map((item: customRainBdst) => { - return { - ...item, - bdstChgYn: item.chgBuilding.length > 0 ? "Y" : "N", - } }) - return chRainRes; - - +const initFetch = async (code:string|number) => { + const rainRes =await getFetch("wr", `/reuseFc/rainyInfoList/1/20/${code}`); + return rainRes; }; export const rainFacActionsExport: (set: any) => rainFacSActions = ( set: any ) => { return { - init: async (txt:string|undefined) => { + getRainData: async(pageNation:number, code:string|number) =>{ + try{ + const rainRes =await getFetch("wr", `/reuseFc/rainyInfoList/${pageNation}/20/${code}`); + + + // 여기서 상태 업데이트 + return set((state: rainFacState) => ({ + ...state, + rain: { + ...state.rain, + rainRes: rainRes, + isInit: false, + }, + })); + + }catch(e){ + console.log(e) + + } + }, + + initRain: async (code:string|number) => { try { // 파라이터 수정 통합관리자 =0, 시관리자=시코드, 시군구 관리자= 시군구 코드 를 세번째 파라미터로 지정 / 건축물 서치가 있을경우 4번째 파라미터로 던지기 즉 1/20/42(서울시)/영현빌딩 이런식으로) - const rainRes = await initFetch(txt); - - + const rainRes = await initFetch(code); // 여기서 상태 업데이트 return set((state: rainFacState) => ({ ...state, @@ -204,14 +180,12 @@ export const rainFacActionsExport: (set: any) => rainFacSActions = ( })); } catch (error) { console.log("error", error); - } finally { - console.log("finally"); - } + } }, - rainSearTxt: async(txt:string) =>{ + rainSearch: async(txt:string,pageNation:number) =>{ try{ - const rainRes = await getFetch('wr' , `/reuseFc/rainyInfoList/1/20/41` +(txt? `/${txt}`:'')) + const rainRes = await getFetch('wr' , `/reuseFc/rainyInfoList/${pageNation}/20/41` +(txt? `/${txt}`:'')) set((state: rainFacState) => { return { rain: { @@ -225,7 +199,7 @@ export const rainFacActionsExport: (set: any) => rainFacSActions = ( console.log("error", erTxt) } }, - rainReg: async (data: customRainBdst) => { + rainBdstReg: async (data: customRainBdst,code:string|number) => { try { const test =await makeRstr(data); @@ -252,7 +226,7 @@ export const rainFacActionsExport: (set: any) => rainFacSActions = ( alert("등록이 완료되었습니다."); } } - const rainRes = await initFetch(undefined); + const rainRes = await initFetch(code); set((state: rainFacState) => ({ ...state, rain: { @@ -267,18 +241,15 @@ export const rainFacActionsExport: (set: any) => rainFacSActions = ( } finally { } }, - rainUpdate: async (data: customRainBdst) => { + rainBdstUpdate: async (data: customRainBdst,code:string|number) => { try { - - const chData =await makeMdfr(data); const res = await putFectch("/reuseFc/rainyInfo", chData); console.log('rainUpdate', res); if(res.ok){ alert(" 수정이 완료되었습니다.") } - - const rainRes = await initFetch(undefined); + const rainRes = await initFetch(code); set((state: rainFacState) => ({ ...state, rain: { diff --git a/apps/wr/app/store/ruseFcltMng/fcltReg/rswtReg/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltReg/rswtReg/index.tsx index da219b226..ea7f38244 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltReg/rswtReg/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltReg/rswtReg/index.tsx @@ -1,5 +1,5 @@ import { getFetch, postFectch, putFectch } from "@/components/lib/api"; -import { upHeadList, type chgBuilding, type TableUpperProps } from "../rainReg"; +import { upHeadList, type chgBuilding, type TableUpperProps } from "../rainReg"; import { z } from "zod"; import { makeMdfr, makeRstr } from "../bdstReg"; @@ -15,73 +15,77 @@ export const rswtZod = z.object({ archArea: z.number().default(0), archChgArea: z.number().default(0), - rgtr:z.string().nullish().default(null), - mdfr:z.string().nullish().default(null), + rgtr: z.string().nullish().default(null), + mdfr: z.string().nullish().default(null), - reuseBuilding: z.array( - z.object({ - bdstRuseFcltPk: z.number().nullish(), - bdstInfoFk: z.number().nullish(), - instlCmptnDt: z.coerce.date().default(() => new Date()), - instlCst: z.number().default(0), - operMngCd: z.string().nullish().default(""), + reuseBuilding: z + .array( + z.object({ + bdstRuseFcltPk: z.number().nullish(), + bdstInfoFk: z.number().nullish(), + instlCmptnDt: z.coerce.date().default(() => new Date()), + instlCst: z.number().default(0), + operMngCd: z.string().nullish().default(""), - anlOperCst: z.number().default(0), - instlCstSprtYn: z.enum(["Y", "N"]), - instlCstSprtAmt: z.number().default(0), + anlOperCst: z.number().default(0), + instlCstSprtYn: z.enum(["Y", "N"]), + instlCstSprtAmt: z.number().default(0), - grntchBdstCertYn: z.enum(["Y", "N"]), - grntchBdstCertYr: z.string().default("") - .refine((year)=> year.length===0 ||/^\d{4}$/.test(year),{ - message:'4자리 연도만 입력하세요' - }), - grntchBdstCertNo: z.string().default(""), - grntchBdstCertGrd: z.string().default(""), - - crgRdctYn: z.enum(["Y", "N"]), // 안쓰는 값 - crgRdctBss: z.string().default("").nullish(), /// 안쓰는 값 - crgRdctAmt: z.number().default(0), // 안쓰는 값 - ruseFcltFlg: z.string().default(""), - bdstUsgCd: z.number().default(0), - lawTrgtYn: z.string().default(""), - rgtr:z.string().nullish().default(null), - mdfr:z.string().nullish().default(null), + grntchBdstCertYn: z.enum(["Y", "N"]), + grntchBdstCertYr: z + .string() + .default("") + .refine((year) => year.length === 0 || /^\d{4}$/.test(year), { + message: "4자리 연도만 입력하세요", + }), + grntchBdstCertNo: z.string().default(""), + grntchBdstCertGrd: z.string().default(""), - rswtrObj: z.object({ - bdstRuseFcltFk: z.number().nullish(), - wtrUsqty: z.number().default(0), - oblgTrgtWtrUsqty: z.number().nullish().default(0), - orgwtKndCd: z.string().default(""), - filtrTrtmfctProcs: z.string().default(""), - filtrTrtmfctUsgCd: z.string().default(""), - rswtrUsqty: z.number().default(0), - altUswtrUtztnYn: z.enum(["Y", "N"]).nullish(),//안쓰는값 - altUswtrKndCd: z.string().default(""),//안쓰는값 - altUswtrUtztnQnt: z.number().default(0),//안쓰는값 - altUswtrIdntyMthdCd: z.string().default(""),//안쓰는값 - rgtr:z.string().nullish().default(null), - mdfr:z.string().nullish().default(null), - }).default({}) - }) - ).default([]), + crgRdctYn: z.enum(["Y", "N"]), // 안쓰는 값 + crgRdctBss: z.string().default("").nullish(), /// 안쓰는 값 + crgRdctAmt: z.number().default(0), // 안쓰는 값 + ruseFcltFlg: z.string().default(""), + bdstUsgCd: z.number().default(0), + lawTrgtYn: z.string().default(""), + rgtr: z.string().nullish().default(null), + mdfr: z.string().nullish().default(null), + + rswtrObj: z + .object({ + bdstRuseFcltFk: z.number().nullish(), + wtrUsqty: z.number().default(0), + oblgTrgtWtrUsqty: z.number().nullish().default(0), + orgwtKndCd: z.string().default(""), + filtrTrtmfctProcs: z.string().default(""), + filtrTrtmfctUsgCd: z.string().default(""), + rswtrUsqty: z.number().default(0), + altUswtrUtztnYn: z.enum(["Y", "N"]).nullish(), //안쓰는값 + altUswtrKndCd: z.string().default(""), //안쓰는값 + altUswtrUtztnQnt: z.number().default(0), //안쓰는값 + altUswtrIdntyMthdCd: z.string().default(""), //안쓰는값 + rgtr: z.string().nullish().default(null), + mdfr: z.string().nullish().default(null), + }) + .default({}), + }) + ) + .default([]), chgBuilding: z - .array( - z.object({ - bdstInfoFk: z.number().nullish(), - archChgPrmsnDt: z.coerce.date() , - archChgArea: z.string().default("-"), - bdstChgNm: z.string().default(""), - rgtr:z.string().nullish().default(null), - mdfr:z.string().nullish().default(null), - }) - ) - .default([]), - + .array( + z.object({ + bdstInfoFk: z.number().nullish(), + archChgPrmsnDt: z.coerce.date(), + archChgArea: z.string().default("-"), + bdstChgNm: z.string().default(""), + rgtr: z.string().nullish().default(null), + mdfr: z.string().nullish().default(null), + }) + ) + .default([]), }); - -export type customRswtBdst = z.infer<typeof rswtZod> +export type customRswtBdst = z.infer<typeof rswtZod>; const rswtRes: customRswtBdst[] = []; @@ -93,9 +97,11 @@ export type rswtFacState = { }; }; type rswtFacSActions = { - initRswt: (txt: string | undefined) => void; - rswtUpdate: (data: customRswtBdst) => void; - rswtReg: (data: customRswtBdst) => void; + initRswt: (code:string|number) => void; + rswtBdstUpdate: (data: customRswtBdst,code:string|number) => void; + getRswtBdstData:(pageNation:number, code:string|number) =>void; + rswtBdstSearch:(txt:string,pageNation:number, code:string|number) =>void; + rswtBdstReg: (data: customRswtBdst,code:string|number) => void; }; export type rswtFacType = rswtFacState & rswtFacSActions; @@ -108,25 +114,58 @@ export const rswtFacStateExport: rswtFacState = { }, }; -const initFetch = async (txt: string | undefined) => { - const rswtRes =await getFetch( +const initFetch = async (code:string|number) => { + const rswtRes = await getFetch( "wr", - `/reuseFc/waterreuseFc/1/20/41` + (txt ? `/${txt}` : "") - ); - const chRswtRes = rswtRes.map((item: customRswtBdst) => { - return { - ...item, - bdstChgYn: item.chgBuilding.length > 0 ? "Y" : "N", - } }) - return chRswtRes; + `/reuseFc/waterreuseFc/1/20/${code}`) + + return rswtRes; }; export const rswtFacActionsExport: (set: any) => rswtFacSActions = ( set: any ) => { return { - initRswt: async (txt: string | undefined) => { + rswtBdstSearch: async(txt:string,pageNation:number,code:string|number) =>{ + try{ + + const rswtRes = await getFetch('wr' , `/reuseFc/rainyInfoList/${pageNation}/20/${code}` +(txt? `/${txt}`:'')) + set((state: rswtFacState) => { + return { + ...state, + rswt: { + ...state.rswt, + rswtRes: rswtRes, + isInit: false, + }, + }; + })} + catch(erTxt){ + console.log("error", erTxt) + } + }, + getRswtBdstData: async (pageNation: number, code: string | number) => { try { - const rswtRes = await initFetch(txt); + const rswtRes = await getFetch( + "wr", + `/reuseFc/waterreuseFc/${pageNation}/20/${code}` + ); + console.log(pageNation) + // 여기서 상태 업데이트 + return set((state: rswtFacState) => ({ + ...state, + rswt: { + ...state.rswt, + rswtRes: rswtRes, + isInit: false, + }, + })); + } catch (e) { + console.log(e); + } + }, + initRswt: async (code: string | number) => { + try { + const rswtRes = await initFetch(code); return set((state: rswtFacState) => ({ ...state, rswt: { @@ -139,71 +178,72 @@ export const rswtFacActionsExport: (set: any) => rswtFacSActions = ( console.log(error); } }, - rswtUpdate: async (data: customRswtBdst) => { - try { - const chData=await makeMdfr(data) - const res = await putFectch("/reuseFc/waterreuseFc", chData); - if (res.ok) { - alert("등록이 완료되었습니다."); - } - const rswtRes = await initFetch(undefined); - set((state: rswtFacState) => ({ - ...state, - rain: { - ...state.rswt, - rswtRes: rswtRes, - isInit: false, - }, - })); - } catch (errorUpdate) { - alert("업데이트 오류입니다. " + (errorUpdate instanceof Error ? errorUpdate.message : "")); - } finally { - } + rswtBdstUpdate: async (data: customRswtBdst, code:string|number) => { + try { + const chData = await makeMdfr(data); + const res = await putFectch("/reuseFc/waterreuseFc", chData); + if (res.ok) { + alert("등록이 완료되었습니다."); + } + const rswtRes = await initFetch(code); + set((state: rswtFacState) => ({ + ...state, + rain: { + ...state.rswt, + rswtRes: rswtRes, + isInit: false, + }, + })); + } catch (errorUpdate) { + alert( + "업데이트 오류입니다. " + + (errorUpdate instanceof Error ? errorUpdate.message : "") + ); + } finally { + } }, - rswtReg: async (data: customRswtBdst) => { - try { - const chData=await makeRstr(data) - const res = await postFectch("/reuseFc/waterreuseFc", chData); - if(res.ok){ - if(data.chgBuilding.length > 0){ - await res - .json() - .then((resData: any) => { - const chPK = resData?.data?.bdstInfoPk; - const makeCh = resData.data.chgBuilding.map( - (item: chgBuilding) => ({ - ...item, - bdstInfoFk: chPK, - }) - ); - const chch = postFectch("/reuseFc/chgBuilding", makeCh); - return chch; + rswtBdstReg: async (data: customRswtBdst,code:string|number) => { + try { + const chData = await makeRstr(data); + const res = await postFectch("/reuseFc/waterreuseFc", chData); + if (res.ok) { + if (data.chgBuilding.length > 0) { + await res + .json() + .then((resData: any) => { + const chPK = resData?.data?.bdstInfoPk; + const makeCh = resData.data.chgBuilding.map( + (item: chgBuilding) => ({ + ...item, + bdstInfoFk: chPK, }) - .then((chch: any) => { - if (chch.ok) { - alert("등록이 완료되었습니다."); - } - }); - }else{ - alert("등록이 완료되었습니다."); - - } - } - const rainRes = await initFetch(undefined); - set((state: rswtFacState) => ({ - ...state, - rain: { - ...state.rswt, - rswtRes: rswtRes, - isInit: false, - }, - })); - } catch (e) { - console.log("e", e); - alert("등록 오류입니다."); - } finally { + ); + const chch = postFectch("/reuseFc/chgBuilding", makeCh); + return chch; + }) + .then((chch: any) => { + if (chch.ok) { + alert("등록이 완료되었습니다."); + } + }); + } else { + alert("등록이 완료되었습니다."); } - }, - + } + const rainRes = await initFetch(code); + set((state: rswtFacState) => ({ + ...state, + rain: { + ...state.rswt, + rswtRes: rswtRes, + isInit: false, + }, + })); + } catch (e) { + console.log("e", e); + alert("등록 오류입니다."); + } finally { + } + }, }; }; diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/pbnstSttn/headList.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/pbnstSttn/headList.tsx index d4c4fed31..98fcc4210 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/pbnstSttn/headList.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/pbnstSttn/headList.tsx @@ -134,7 +134,7 @@ export const pbnSttHeadListExport: TableUpperProps[] = [ // ? rainSttHeadList // : null; -// let chNm = type === "pbn" ? pbnSttHeadNm : rainSttHeadNm; +// let chNm = type === "pbn" ? pbnSttHeadNm : rainSttNodeList; // headList?.forEach((item) => { // if (checkList.find((ch) => ch === item.id)) { // item.visible = false; @@ -159,8 +159,8 @@ export const pbnSttHeadListExport: TableUpperProps[] = [ // type === "pbn" ? headList : state.sttnCommon.pbnSttHeadList, // rainSttHeadList: // type === "rain" ? headList : state.sttnCommon.rainSttHeadList, -// rainSttHeadNm: -// type === "rain" ? chNm : state.sttnCommon.rainSttHeadNm, +// rainSttNodeList: +// type === "rain" ? chNm : state.sttnCommon.rainSttNodeList, // pbnSttHeadNm: type === "rain" ? chNm : state.sttnCommon.pbnSttHeadNm, // }, // })); diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/headList.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/headList.tsx index cf06687c4..c283194a1 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/headList.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/headList.tsx @@ -1,19 +1,140 @@ -import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; -import type { TableTripleProps, TableUpperProps } from "../../fcltReg/rainReg"; +import { z } from "zod"; + + +export const rainSttnHeadListType = z.array( + z.object({ + id: z.string(), + title: z.string(), + visible: z.boolean(), + }) + ); + + +export const rainSttHeadListExport: z.infer<typeof rainSttnHeadListType> = [ + +{ + id: "cityText", + title: "시도", + visible: true, +}, +{ + id: "sggText", + title: "시군구", + visible: true, +}, +{ + id: "bdstNm", + title: "건축물명", + visible: true, +}, +{ + id: "daddr", + title: "주소", + visible: true, +}, +{ + id: "bdstUsgCd", + title: "건축물용도코드", + visible: true, +}, +{ + id: "frstArchPrmsnDt", + title: "최초건축허가일시", + visible: true, +}, +{ + id: "archArea", + title: "건축면적", + visible: true, +}, +{ + id: "lawTrgtYn", + title: "법적의무대상여부", + visible: true, +}, +{ + id: "instlCmptnDt", + title: "설치완료일시", + visible: true, +}, + +{ + id: "instlCst", + title: "설치비용", + visible: true, +}, + + +{ + id: "pntfColKnd", + title: "집수지점종류", + visible: true, +}, +{ + id: "pntfColArea", + title: "집수지점면적", + visible: true, +}, + +{ + id: "dtfcltCpct", + title: "저류조용량", + visible: true, +}, +{ + id: "filtrTrtmfctYn", + title: "여과처리시설유무", + visible: true, +}, +{ + id: "filtrTrtmfctCpct", + title: "여과처리시설용량", + visible: true, +}, +{ + id: "filtrTrtmfctPrs", + title: "여과처리시설처리공정", + visible: true, +}, + + +{ + id: "instlCstSprtYn", + title: "설치지원비용여부", + visible: true, +}, +{ + id: "instlCstSprtAmt", + title: "설치지원비용", + visible: true, +}, + +{ + id: "grntchBdstCertYn", + title: "녹색건축물인증여부", + visible: true, +}, +{ + id: "grntchBdstCertYr", + title: "녹색건축물인증년도", + visible: true, +}, +{ + id: "grntchBdstCertNo", + title: "녹색건축물인증번호", + visible: true, +}, +{ + id: "grntchBdstCertGrd", + title: "녹색건축물인증등급", + visible: true, +}, + +]; -export type TableUpperPropsTest = { - id: string; - title: string; - upName?: string; - upSequnce?: number; - row?: number; - rowSpan?: number; - colSpan?: number; - visible?: boolean; -}; // id는 다확인해야함 -export const rainSttHeadListExportTest: TableUpperPropsTest[] = [ +export const rainSttNodeListExport: CommonTableProps[] = [ { id: "bdnstInfo", title: "1.건축물정보", @@ -28,401 +149,272 @@ export const rainSttHeadListExportTest: TableUpperPropsTest[] = [ visible: true, row: 1, rowSpan: 1, - colSpan: 6, + colSpan: 7, }, - { id: "insenInfo", - title: "3.인센티브 정보", + { + id: "insenInfo", + title: "3.인센티브 정보", visible: true, row: 1, rowSpan: 1, - colSpan: 7 + colSpan: 6, + }, + { + id: "adminDiv", + title: "행정구역", + visible: true, + row: 2, + upName:'bdnstInfo', + rowSpan: 1, + colSpan: 2, + }, + + + + // 3번째줄 시작 + { + id: "cityText", + title: "시도", + visible: true, + upName:'adminDiv', + row: 3, + rowSpan: 1, + colSpan: 1, + }, + { + id: "sggText", + title: "시군구", + visible: true, + upName:'adminDiv', + row: 3, + rowSpan: 1, + colSpan: 1, }, // 2번째 줄 - { id: "adminDiv", - title: "행정구역", - visible: true, - row: 2, - rowSpan: 1, - colSpan: 2 }, - - // 1번째 줄 건축물정보 아래의 행으로 만들 헤더 - { - id: "bdstNm", - title: "건축물명", - visible: true, - row: 2, - rowSpan: 2, - colSpan: 1 }, - { - id: "daddr", - title: "주소", - visible: true, - row: 2, - rowSpan: 2, - colSpan: 1 }, - { - id: "bdstUsgCd", - title: "건축물용도코드", - row: 2, - rowSpan: 2, - colSpan: 1 }, - { - id: "frstArchPrmsnDt", - title: "최초건축허가일시", - visible: true, - row: 2, - rowSpan: 2, - colSpan: 1 }, - { - id: "archArea", - title: "건축면적", - visible: true, - row: 2, - rowSpan: 2, - colSpan: 1 }, - { - id: "lawTrgtYn", - title: "법적의무대상여부", - visible: true, - row: 2, - rowSpan: 2, - colSpan: 1 }, - { - id: "instlCmptnDt", - title: "설치완료일시", - visible: true, - row: 2, - rowSpan: 2, - colSpan: 1 }, - - - { - id: "instlCst", - title: "설치비용", - visible: true, - row: 2, - rowSpan: 1, - colSpan: 2 - }, - - { id: "pntfCol", - title: "집수면", - visible: true, - row: 2, - rowSpan: 1, - colSpan: 2 - }, - { id: "filtrTrtmfct", - title: "여과등 처리시설", - visible: true, - row: 2, - rowSpan: 1, - colSpan: 3 - }, - { - id: "dtfcltCpct", - title: "저류조용량", - visible: true, - row: 2, - rowSpan: 2, - colSpan: 1 - }, - - - { id: "instlCstSprt", - title: "설치비지원", - visible: true, - row: 2, - rowSpan: 1, - colSpan: 2 - }, - { id: "grntchBdstCert", - title: "녹색건축물인증여부", - visible: true, - row: 2, - rowSpan: 1, - colSpan: 4 - }, - - // 3번째줄 시작 - { - id: "cityText", - title: "시도", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, - { - id: "sggText", - title: "시군구", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, - - - - { - id: "pntfColKnd", - title: "집수지점종류", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, - { - id: "pntfColArea", - title: "집수지점면적", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, - { - id: "filtrTrtmfctYn", - title: "여과처리시설유무", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, - { - id: "filtrTrtmfctCpct", - title: "여과처리시설용량", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, - { - id: "filtrTrtmfctPrs", - title: "여과처리시설처리공정", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, - - - { - id: "instlCstSprtYn", - title: "설치지원비용여부", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, - { - id: "instlCstSprtAmt", - title: "설치지원비용", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, - - { - id: "grntchBdstCertYn", - title: "녹색건축물인증여부", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, - { - id: "grntchBdstCertYr", - title: "녹색건축물인증년도", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, - { - id: "grntchBdstCertNo", - title: "녹색건축물인증번호", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, - { - id: "grntchBdstCertGrd", - title: "녹색건축물인증등급", - visible: true, - row: 3, - rowSpan: 1, - colSpan: 1 - }, -]; - -export const rainSttHeadNmExport: chHeadType[] = [ - { headNm: "bdnstInfo", text: "1.건축물정보", length: 9 }, - { headNm: "rainFcltInfo", text: "2.빗물이용시설정보", length: 7 }, - { headNm: "insenInfo", text: "3.인센티브 정보", length: 9 }, - - -]; - -// id는 다확인해야함 -export const rainSttHeadListExport: TableTripleProps[] = [ - { - id: "cityText", - title: "시도", - visible: true, - upName: ["bdnstInfo", "adminDiv"], - upSequnce: [1, 1], - }, - { - id: "sggText", - title: "시군구", - visible: true, - upName: ["bdnstInfo", "adminDiv"], - upSequnce: [2, 2], - }, + // 1번째 줄 건축물정보 아래의 행으로 만들 헤더 { id: "bdstNm", title: "건축물명", visible: true, - upName: ["bdnstInfo"], - upSequnce: [3], + upName:'bdnstInfo', + row: 2, + rowSpan: 2, + colSpan: 1, }, { id: "daddr", title: "주소", visible: true, - upName: ["bdnstInfo"], - upSequnce: [4], + upName:'bdnstInfo', + row: 2, + rowSpan: 2, + colSpan: 1, }, { id: "bdstUsgCd", title: "건축물용도코드", + upName:'bdnstInfo', visible: true, - upName: ["bdnstInfo"], - upSequnce: [5], + row: 2, + rowSpan: 2, + colSpan: 1, }, { id: "frstArchPrmsnDt", title: "최초건축허가일시", + upName:'bdnstInfo', visible: true, - upName: ["bdnstInfo"], - upSequnce: [6], + row: 2, + rowSpan: 2, + colSpan: 1, }, { id: "archArea", title: "건축면적", + upName:'bdnstInfo', visible: true, - upName: ["bdnstInfo"], - upSequnce: [7], + row: 2, + rowSpan: 2, + colSpan: 1, }, { id: "lawTrgtYn", title: "법적의무대상여부", + upName:'bdnstInfo', visible: true, - upName: ["bdnstInfo"], - upSequnce: [8], + row: 2, + rowSpan: 2, + colSpan: 1, }, { id: "instlCmptnDt", title: "설치완료일시", + upName:'bdnstInfo', visible: true, - upName: ["bdnstInfo"], - upSequnce: [9], + row: 2, + rowSpan: 2, + colSpan: 1, }, { id: "instlCst", title: "설치비용", + upName:'rainFcltInfo', visible: true, - upName: ["rainFcltInfo"], - upSequnce: [1], + row: 2, + rowSpan: 2, + colSpan: 1, }, + + { + id: "pntfCol", + title: "집수면", + upName:'rainFcltInfo', + visible: true, + row: 2, + rowSpan: 1, + colSpan: 2, + }, + { id: "pntfColKnd", title: "집수지점종류", + upName:'pntfCol', visible: true, - upName: ["rainFcltInfo", "pntfCol"], - upSequnce: [2, 1], + row: 3, + rowSpan: 1, + colSpan: 1, }, { id: "pntfColArea", title: "집수지점면적", + upName:'pntfCol', visible: true, - upName: ["rainFcltInfo", "pntfCol"], - upSequnce: [3, 2], + row: 3, + rowSpan: 1, + colSpan: 1, + }, + + { + id: "dtfcltCpct", + title: "저류조용량", + upName:'rainFcltInfo', + visible: true, + row: 2, + rowSpan: 2, + colSpan: 1, }, { id: "filtrTrtmfctYn", title: "여과처리시설유무", + upName:'filtrTrtmfct', visible: true, - upName: ["rainFcltInfo", "filtrTrtmfct"], - upSequnce: [4, 1], + row: 3, + rowSpan: 1, + colSpan: 1, }, { id: "filtrTrtmfctCpct", title: "여과처리시설용량", + upName:'filtrTrtmfct', visible: true, - upName: ["rainFcltInfo", "filtrTrtmfct"], - upSequnce: [5, 2], + row: 3, + rowSpan: 1, + colSpan: 1, }, { id: "filtrTrtmfctPrs", title: "여과처리시설처리공정", + upName:'filtrTrtmfct', visible: true, - upName: ["rainFcltInfo", "filtrTrtmfct"], - upSequnce: [6, 3], - }, - { - id: "dtfcltCpct", - title: "저류조용량", - visible: true, - upName: ["rainFcltInfo"], - upSequnce: [7], + row: 3, + rowSpan: 1, + colSpan: 1, }, + { + id: "filtrTrtmfct", + title: "여과등 처리시설", + visible: true, + upName:'insenInfo', + row: 2, + rowSpan: 1, + colSpan: 3, + }, { id: "instlCstSprtYn", title: "설치지원비용여부", + upName:'instlCstSprt', visible: true, - upName: ["insenInfo", "instlCstSprt"], - upSequnce: [1, 1], + row: 3, + rowSpan: 1, + colSpan: 1, }, { id: "instlCstSprtAmt", title: "설치지원비용", + upName:'instlCstSprt', visible: true, - upName: ["insenInfo", "instlCstSprt"], - upSequnce: [2, 2], + row: 3, + rowSpan: 1, + colSpan: 1, + }, + + { + id: "instlCstSprt", + title: "설치비지원", + upName:'insenInfo', + visible: true, + row: 2, + rowSpan: 1, + colSpan: 2, }, { id: "grntchBdstCertYn", title: "녹색건축물인증여부", + upName:'grntchBdstCert', visible: true, - upName: ["insenInfo", "grntchBdstCert"], - upSequnce: [3, 1], + row: 3, + rowSpan: 1, + colSpan: 1, }, { id: "grntchBdstCertYr", title: "녹색건축물인증년도", + upName:'grntchBdstCert', visible: true, - upName: ["insenInfo", "grntchBdstCert"], - upSequnce: [4, 2], + row: 3, + rowSpan: 1, + colSpan: 1, }, { id: "grntchBdstCertNo", title: "녹색건축물인증번호", + upName:'grntchBdstCert', visible: true, - upName: ["insenInfo", "grntchBdstCert"], - upSequnce: [5, 3], + row: 3, + rowSpan: 1, + colSpan: 1, }, { id: "grntchBdstCertGrd", title: "녹색건축물인증등급", + upName:'grntchBdstCert', visible: true, - upName: ["insenInfo", "grntchBdstCert"], - upSequnce: [6, 4], + row: 3, + rowSpan: 1, + colSpan: 1, + }, + { + id: "grntchBdstCert", + title: "녹색건축물인증", + upName:'insenInfo', + visible: true, + row: 2, + rowSpan: 1, + colSpan: 4, }, ]; + diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/index.tsx index 7ebc9b7aa..3c9a507ac 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/rainSttn/index.tsx @@ -2,31 +2,100 @@ import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; import { fetchType, getFetch } from "@/components/lib/api"; import { type customRainBdst, - type TableTripleProps, } from "../../fcltReg/rainReg"; import { excelSttnParsing } from "./excel"; -import { rainSttHeadListExport, rainSttHeadListExportTest, rainSttHeadNmExport, type TableUpperPropsTest } from "./headList"; +import { + rainSttHeadListExport, + rainSttnHeadListType, + rainSttNodeListExport, +} from "./headList"; +import type { z } from "zod"; +import type { CommonTableProps } from "@/app/store/common/type/headder"; // 테이블 헤드 리스트 -const rainSttHeadNm = rainSttHeadNmExport; - -//const rainSttHeadList = rainSttHeadListExport; -const rainSttHeadList = rainSttHeadListExportTest; +const rainSttNodeList = rainSttNodeListExport; +const rainSttHeadList = rainSttHeadListExport; const rainSttnRes: customRainBdst[] = []; + + +const visibleHeadList = (falseHeads:CommonTableProps[], orgNodeList:CommonTableProps[])=>{ + const visibleHeads = orgNodeList.map((node) => { + const copyNode = {...node} + falseHeads.forEach((head)=>{ + if(copyNode.id ===head.id) + copyNode.visible = head.visible + }) + return copyNode; + }) + return visibleHeads +} + +const getColspanReductionMap = (falseHeads:CommonTableProps[], orgList:CommonTableProps[]):Record<string, number> => { + const reduceMap:Record<string, number> = {}; + falseHeads.forEach(head => { + const node = orgList.find(n => n.id === head.id); + if (node?.upName) { + reduceMap[node.upName] = (reduceMap[node.upName] || 0) + 1; + if (node.row&& node.row >= 3) { + const upperUpName = orgList.find(n => n.id === node.upName)?.upName; + if (upperUpName) { + reduceMap[upperUpName] = (reduceMap[upperUpName] || 0) + 1; + } + } + } + }); + return reduceMap; +}; + +// colSpan 반영 및 visible 처리 +const applyColspanReduction = ( + orgList: CommonTableProps[], + reduceMap: Record<string, number> +): CommonTableProps[] => { + return orgList.map(node => { + const newNode: CommonTableProps = { ...node }; + const reduceCount = reduceMap[node.id]; + + if ( + newNode.colSpan !== undefined && + reduceCount !== undefined && + typeof newNode.colSpan === "number" + ) { + newNode.colSpan -= reduceCount; + if (newNode.colSpan <= 0) { + newNode.visible = false; + } + } + + return newNode; + }); +}; +// 일단 헤더가 3개 이상인경우 visible 처리를 위해서 공통함수로 작업 +export const controlHeadView = (headList:CommonTableProps[], orgNodeList:CommonTableProps[] ) =>{ + const falseHeads = headList.filter((item) => item.visible == false); + + const viewHeadList = visibleHeadList(falseHeads, orgNodeList) + const reduceMap= getColspanReductionMap( falseHeads,viewHeadList) + return applyColspanReduction(viewHeadList,reduceMap); +} + + + export type rainSttnState = { rainSttn: { rainSttnRes: customRainBdst[]; - // rainSttHeadList: TableTripleProps[]; - rainSttHeadList: TableUpperPropsTest[]; - rainSttHeadNm: chHeadType[]; + rainSttHeadList: CommonTableProps[]; + rainSttNodeList: CommonTableProps[]; excelList: []; isInit: boolean; }; }; type rainSttnActions = { rainSttnSearch: (page: string, total: string, con: string) => void; - rainChSttnHead: (checkList: string[]) => void; + rainChSttnHead: ( + headList: z.infer<typeof rainSttnHeadListType>, + ) => void; }; export type rainSttnType = rainSttnState & rainSttnActions; @@ -34,7 +103,7 @@ export type rainSttnType = rainSttnState & rainSttnActions; export const rainSttnStateExport: rainSttnState = { rainSttn: { rainSttHeadList: rainSttHeadList, - rainSttHeadNm: rainSttHeadNm, + rainSttNodeList: rainSttNodeList, rainSttnRes: rainSttnRes, excelList: [], isInit: false, @@ -77,31 +146,16 @@ export const rainSttnActionsExport: (set: any) => rainSttnActions = ( console.log("error", erTxt); } }, - rainChSttnHead: async (checkList: string[]) => { - const headList = rainSttHeadList; - let chNm = rainSttHeadNm; - headList?.forEach((item) => { - if (checkList.find((ch) => ch === item.id)) { - item.visible = false; - if (item.upName) { - const upNames = Array.isArray(item.upName) - ? item.upName - : [item.upName]; - upNames?.forEach((up) => { - chNm.find((ch) => { - if (ch.headNm === up) { - ch.length = ch.length - 1; - } - }); - }); - } - } - }); - set((state: rainSttnState) => ({ + rainChSttnHead: async ( + headList: z.infer<typeof rainSttnHeadListType> + ) => { + const changeNodeList= controlHeadView(headList,rainSttNodeList) + + return set((state: rainSttnState) => ({ rainSttn: { ...state.rainSttn, rainSttHeadList: headList, - rainSttHeadNm: chNm, + rainSttNodeList: changeNodeList, }, })); }, diff --git a/apps/wr/components/lib/func/TableData.tsx b/apps/wr/components/lib/func/TableData.tsx index 0c42a5dbe..08126336e 100644 --- a/apps/wr/components/lib/func/TableData.tsx +++ b/apps/wr/components/lib/func/TableData.tsx @@ -2,6 +2,11 @@ import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn" import type { TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import { Checkbox, Input, TableCell, TableRow } from "@common/components/ui"; + + + + + export const rightTableData = (rainChk: rainChkZodType[]) => { // 1. chkgdnFk + utztnUsgCd 기준 누계 정보 만들기 const maketotal = rainChk.map((item: rainChkZodType) => { @@ -23,7 +28,6 @@ export const rightTableData = (rainChk: rainChkZodType[]) => { return selectTotal; // 모든 키: `${chkgdnFk}_${utztnUsgCd}` 형태 }); - console.log("maketotal", maketotal); // 2. 누계 정보들을 하나의 객체로 합치기 (평탄화) @@ -65,7 +69,6 @@ export const chRowspanTable = ( selectedIds: number[], handleCellClick: (index: number, headId: string) => void ) => { - console.log('chRowspanTable', makeTableData); // rowspan된 셀 렌더링 여부 추적용 const renderedMap = new Map<string, Set<number>>(); return ( diff --git a/apps/wr/components/lib/func/commom.tsx b/apps/wr/components/lib/func/commom.tsx index 5f921e0a9..b7f9d9eed 100644 --- a/apps/wr/components/lib/func/commom.tsx +++ b/apps/wr/components/lib/func/commom.tsx @@ -20,7 +20,6 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => { // cd text 넣기 export const tableData = ( data: any,code:comCodeState)=>{ const chCode = code.code; - return data?.map((item: { sggCd: string; ctpvCd: string; reuseBuilding: { lawTrgtYn: any , bdstUsgCd:any}[]; }) => { let returnData = {}; const sggText = chCode.sggCd.find( @@ -29,16 +28,20 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => { const cityText = chCode.cityCd.find( (cd) => cd.val === String(item.ctpvCd) )?.text; - + console + .log(item?.reuseBuilding) if (item?.reuseBuilding?.length >0) { + const bdsgUsgText = chCode.bdstUsgCd.find( - (cd) =>cd.val === item?.reuseBuilding[0]?.bdstUsgCd + (cd) =>Number(cd.val) === item?.reuseBuilding[0]?.bdstUsgCd )?.text const lawTrgtYn = item?.reuseBuilding[0]?.lawTrgtYn + console + .log(bdsgUsgText) - returnData= { ...item, sggText: sggText, cityText: cityText ,bdsgUsgText:bdsgUsgText ,lawTrgtYn:lawTrgtYn}; + returnData= { ...item, sggText: sggText??'없음', cityText: cityText??'없음' ,bdsgUsgText:bdsgUsgText ,lawTrgtYn:lawTrgtYn}; }else{ - returnData= { ...item, sggText: sggText, cityText: cityText}; + returnData= { ...item, sggText: sggText??'없음', cityText: cityText??'없음'}; } return returnData; @@ -63,4 +66,20 @@ export const getCity = (val: string, sggCd: SelectDataType[]) => { } +// onchange 텍스트를 숫자로 and ,제거 +export const handleCommaNumberChange = ( + e: React.ChangeEvent<HTMLInputElement>, + onChange: (value: number | "") => void +) => { + const raw = e.target.value.replace(/,/g, ""); + if (!/^\d*$/.test(raw)) return; + onChange(raw === "" ? "" : Number(raw)); +}; +// 숫자입력시 , 삽입 +export const formatCommaNumber = ( + value: number | string | undefined | null +): string => { + if (value === undefined || value === null || value === "") return ""; + return Number(value).toLocaleString(); +}; \ No newline at end of file diff --git a/apps/wr/components/ui/form/fcltReg/bdstReg/bdstReg.tsx b/apps/wr/components/ui/form/fcltReg/bdstReg/bdstReg.tsx index a4107268f..02610279f 100644 --- a/apps/wr/components/ui/form/fcltReg/bdstReg/bdstReg.tsx +++ b/apps/wr/components/ui/form/fcltReg/bdstReg/bdstReg.tsx @@ -1,9 +1,18 @@ import { useWrStore } from "@/app/store"; import type { selectArray } from "@/app/store/common/code"; import { selectClass } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; -import { getCity } from "@/components/lib/func/commom"; +import { + formatCommaNumber, + getCity, + handleCommaNumberChange, +} from "@/components/lib/func/commom"; import type { objSearchType } from "@/components/ui/modal/bdstRegModal/bdstRegModal"; -import { FormField, FormUi, DatePicker, SelectBox } from "@common/business_components"; +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"; @@ -30,49 +39,46 @@ export default function BdstReg({ form }: { 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') + const [selectSgg, setSelectSgg] = useState<selectArray[] | undefined>(); + const [objSearch, setObjSearch] = useState<objSearchType>({ + sgg: "", + city: "", + }); - setObjSearch({ city:val , sgg:''}) - - }; - - const getSgg = (val: string | number) => { + const getSelCity = (val: string) => { + const data = getCity(val, code.sggCd); + setSelectSgg(data); + const sgg = form.getValues("sggCd"); - const sgg =form.getValues('sggCd') - setObjSearch({...objSearch,sgg: val!=''?String(val):sgg }) - }; + setObjSearch({ city: val, sgg: "" }); + }; - - useEffect(()=>{ - const city =form.getValues('ctpvCd') - const sgg =form.getValues('sggCd') - setObjSearch({city:city , sgg:sgg }) - - }, [selectSgg]) + const getSgg = (val: string | number) => { + const sgg = form.getValues("sggCd"); + setObjSearch({ ...objSearch, sgg: val != "" ? String(val) : sgg }); + }; + + useEffect(() => { + const city = form.getValues("ctpvCd"); + const sgg = form.getValues("sggCd"); + setObjSearch({ city: city, sgg: sgg }); + }, [selectSgg]); useEffect(() => { const subscription = form.form?.watch((value: any) => { - console.log('vale', value) + console.log("vale", value); }); - + return () => subscription?.unsubscribe(); }, [form.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"> @@ -86,19 +92,15 @@ export default function BdstReg({ form }: { form: any }) { 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} - + className="col-span-3 " + label={""} + selectClass={selectClass} + selectArray={code.cityCd} + onSelectValue={(val) => { + getSelCity(String(val)); + field.onChange(Number(val)); + }} + value={field.value} /> </FormUi> )} @@ -111,16 +113,15 @@ export default function BdstReg({ form }: { form: any }) { 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} - + className="col-span-3" + label={""} + selectClass={selectClass} + selectArray={selectSgg ? selectSgg : code.sggCd || []} + onSelectValue={(val) => { + getSgg(val); + field.onChange(Number(val)); + }} + value={field.value} /> </FormUi> )} @@ -135,7 +136,7 @@ export default function BdstReg({ form }: { form: any }) { render={({ field }) => ( <FormUi label="건축물명"> <Input - className="" + className={selectClass} placeholder="1,000,000" type="text" {...field} @@ -151,7 +152,7 @@ export default function BdstReg({ form }: { form: any }) { render={({ field }) => ( <FormUi label="위치"> <Input - className="" + className={selectClass} placeholder="1,000,000" type="search" {...field} @@ -186,16 +187,14 @@ export default function BdstReg({ form }: { form: any }) { name="frstArchPrmsnDt" render={({ field }) => ( <FormUi label="최초건축허가일"> - <DatePicker - mode={"single"} - field={{ - value: field.value|| new Date(), - onChange: (date: Date | undefined) => - field.onChange(date), - }} - selectClass={selectClass} - ></DatePicker> - + <DatePicker + mode={"single"} + field={{ + value: field.value || new Date(), + onChange: (date: Date | undefined) => field.onChange(date), + }} + selectClass={'w-full'} + ></DatePicker> </FormUi> )} /> @@ -207,14 +206,13 @@ export default function BdstReg({ form }: { form: any }) { render={({ field }) => ( <FormUi label="건축면적(m³)"> <Input - className="" + className={selectClass} placeholder="1,000,000" type="number" - {...field} onChange={(e) => { - const value = e.target.value; - field.onChange(value === "" ? "" : Number(value)); + handleCommaNumberChange(e, field.onChange); }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -249,7 +247,7 @@ export default function BdstReg({ form }: { form: any }) { 이력추가 </Button> <Button - type="button" + type="button" className="rounded-lg bg-red-500 text-white" onClick={removeLastItem} > @@ -270,7 +268,6 @@ export default function BdstReg({ form }: { form: any }) { selectClass={selectClass} label={""} selectArray={code.chBuCd} - onSelectValue={(val) => { field.onChange(val); }} @@ -286,15 +283,15 @@ export default function BdstReg({ form }: { form: any }) { 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> + <DatePicker + mode={"single"} + field={{ + value: safeDate(field.value) || new Date(), + onChange: (date: Date | undefined) => + field.onChange(date), + }} + selectClass={'w-full'} + ></DatePicker> </FormUi> )} /> @@ -306,12 +303,13 @@ export default function BdstReg({ form }: { form: any }) { render={({ field }) => ( <FormUi label="면적"> <Input - className="" + className={selectClass} placeholder="-" type="text" - value={ field.value??"-"} - onChange={(e) => field.onChange((e.target.value))} - + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} diff --git a/apps/wr/components/ui/form/fcltReg/htdflReg/htdflRegForm.tsx b/apps/wr/components/ui/form/fcltReg/htdflReg/htdflRegForm.tsx index 5e58b9f8a..62af8cd19 100644 --- a/apps/wr/components/ui/form/fcltReg/htdflReg/htdflRegForm.tsx +++ b/apps/wr/components/ui/form/fcltReg/htdflReg/htdflRegForm.tsx @@ -18,6 +18,10 @@ import { } from "@/app/store/ruseFcltMng/fcltReg/htdflReg"; import { useEffect } from "react"; import BdstReg from "../bdstReg/bdstReg"; +import { + formatCommaNumber, + handleCommaNumberChange, +} from "@/components/lib/func/commom"; export default function HtdflRegForm({ htdflForm, @@ -35,19 +39,19 @@ export default function HtdflRegForm({ defaultValues: defaultValues, }); - const onSubmit=(values: z.infer<typeof hdtflZod>)=> { + const onSubmit = (values: z.infer<typeof hdtflZod>) => { if (isModal) { htdflReg(values); } else { htdflUpdate(values); } - } + }; const onSelectValue = (val: string | number) => { console.log(val); }; - const cleanHtdflData=(raw: any): z.infer<typeof hdtflZod> =>{ + const cleanHtdflData = (raw: any): z.infer<typeof hdtflZod> => { return { ...raw, frstArchPrmsnDt: new Date(raw?.frstArchPrmsnDt || null), @@ -70,16 +74,12 @@ export default function HtdflRegForm({ }, })), }; - } - - - + }; useEffect(() => { console.log("form errors:", form.formState.errors); }, [form.formState.errors]); - useEffect(() => { if (hdtflZod) form.reset(cleanHtdflData(htdflForm)); }, [htdflForm]); @@ -91,26 +91,24 @@ export default function HtdflRegForm({ <div> <div className="grid grid-cols-12"> <h1 className="pl-3 text-xl col-span-10">○온배수 시설 정보</h1> - <Button size={"sm"} type="submit" className="col-start-12 col-span-1"> + <Button + size={"sm"} + type="submit" + className="col-start-12 col-span-1" + > 저장 </Button> </div> </div> - { isModal && htdflForm != undefined ? ( - <BdstReg form={form} /> - ) : ( - <></> - )} - {isModal ? ( - <h1 className="pl-3 text-xl col-span-10 mt-4 "> - ○ 중수도 시설 정보{" "} - </h1> - ) : ( - <></> - )} - - + {isModal && htdflForm != undefined ? <BdstReg form={form} /> : <></>} + {isModal ? ( + <h1 className="pl-3 text-xl col-span-10 mt-4 "> + ○ 중수도 시설 정보{" "} + </h1> + ) : ( + <></> + )} <div className="grid grid-cols-6 gap-2 mt-4 pl-6"> <div className="col-span-2"> @@ -120,7 +118,7 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="발전유형(코드정비후 수정)"> <Input - className="" + className={selectClass} placeholder="1,000,000" type="text" value={field.value ?? ""} @@ -138,13 +136,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="설비용량"> <Input - className="" + className={selectClass} placeholder="1,000,000" type="text" - value={field.value ?? 0} onChange={(e) => { - field.onChange(Number(e.target.value)); + handleCommaNumberChange(e, field.onChange); }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -183,7 +181,7 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="원수취수 지점(코드정비후 수정)"> <Input - className="" + className={selectClass} placeholder="1,000,000" type="text" value={field.value ?? 0} @@ -202,7 +200,7 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="원수발생 공정"> <Input - className="" + className={selectClass} placeholder="1,000,000" type="" value={field.value ?? ""} @@ -219,13 +217,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="취수구 온도"> <Input - className="" + className={selectClass} placeholder="1,000,000" - type="" - value={field.value ?? 0} + type="text" onChange={(e) => { - field.onChange(Number(e.target.value)); + handleCommaNumberChange(e, field.onChange); }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -238,11 +236,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="발생량(m³/년)"> <Input - className="" + className={selectClass} placeholder="1,000,000" - type="" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + type="text" + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -273,11 +273,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="처리시설 용량(m³/년)"> <Input - className="" + className={selectClass} placeholder="1,000,000" - type="" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + type="text" + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -308,11 +310,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="이용량(m³/년)"> <Input - className="" + className={selectClass} placeholder="1,000,000" - type="" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + type="text" + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -325,7 +329,7 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="이용용도"> <Input - className="" + className={selectClass} placeholder="1,000,000" type="text" value={field.value ?? ""} @@ -351,10 +355,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="총대장균군"> <Input + className={selectClass} placeholder="10" type="text" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -368,10 +375,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="총질소"> <Input + className={selectClass} placeholder="10" type="text" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -387,10 +397,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="결합잔류염소"> <Input + className={selectClass} placeholder="10" type="text" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -404,10 +417,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="총인"> <Input + className={selectClass} placeholder="10" type="text" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -423,10 +439,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="탁도"> <Input + className={selectClass} placeholder="10" type="text" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -440,10 +459,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="수소이온농도"> <Input + className={selectClass} placeholder="10" type="text" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -459,10 +481,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="생물학적 산소요구량"> <Input + className={selectClass} placeholder="10" type="text" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -476,10 +501,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="염화물"> <Input + className={selectClass} placeholder="10" type="text" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -495,10 +523,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="냄새"> <Input + className={selectClass} placeholder="10" type="text" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -512,10 +543,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="전기전도도"> <Input + className={selectClass} placeholder="10" type="text" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -531,10 +565,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="색도"> <Input + className={selectClass} placeholder="10" type="text" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -548,10 +585,13 @@ export default function HtdflRegForm({ render={({ field }) => ( <FormUi label="배출구온도"> <Input + className={selectClass} placeholder="10" type="text" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} diff --git a/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx b/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx index 416561b99..30249fa68 100644 --- a/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx +++ b/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx @@ -15,6 +15,7 @@ import { useEffect, useState } from "react"; import { useForm, useWatch, type UseFormReturn } from "react-hook-form"; import { z } from "zod"; import BdstReg from "../bdstReg/bdstReg"; +import { formatCommaNumber, handleCommaNumberChange } from "@/components/lib/func/commom"; export default function RainRegForm({ rainForm, @@ -23,7 +24,7 @@ export default function RainRegForm({ rainForm: customRainBdst; isModal: boolean; }) { - const { code, rainReg, rainUpdate, rain } = useWrStore((state) => state); + const { code, rainBdstReg, rainBdstUpdate, rain } = useWrStore((state) => state); const { rainFcltCd } = code; const defaultValues: z.infer<typeof rainZod> = rainZod.parse({}); @@ -87,9 +88,9 @@ useEffect(() =>{ const onSubmit =(values: z.infer<typeof rainZod>)=> { if (isModal) { - rainReg(values); + rainBdstReg(values ,'41'); } else { - rainUpdate(values); + rainBdstUpdate(values, '41'); } } @@ -159,13 +160,11 @@ useEffect(() =>{ render={({ field }) => ( <FormUi label="설치비"> <Input - className={inputClass} - placeholder="1,000,000" - type="number" - value={field.value ?? 0} - onChange={(e) => { - field.onChange(e.target.value === "" ? "" : Number(e.target.value)); - }} + className={selectClass} + placeholder="1,000,000" + type="text" + onChange={(e) => {handleCommaNumberChange(e, field.onChange) }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -209,9 +208,9 @@ useEffect(() =>{ <Input className={selectClass} placeholder="1,000,000" - type="number" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + type="text" + onChange={(e) => {handleCommaNumberChange(e, field.onChange) }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -250,9 +249,9 @@ useEffect(() =>{ <Input className={selectClass} placeholder="1,000,000" - type="number" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + type="text" + onChange={(e) => {handleCommaNumberChange(e, field.onChange) }} + value={formatCommaNumber(field.value)} readOnly={filtrTrtmfctYn!=='Y'} /> @@ -314,15 +313,12 @@ useEffect(() =>{ render={({ field }) => ( <FormUi label="지원금액(원)"> <Input - className="" + className={selectClass} placeholder="1,000,000" - type="number" - onChange={(e) => { - const value = e.target.value; - field.onChange(value === "" ? "" : Number(value)); - }} - value={field.value ?? 0} - readOnly={instlCstSprtYn!=='Y'} + type="text" + onChange={(e) => {handleCommaNumberChange(e, field.onChange) }} + value={formatCommaNumber(field.value)} + readOnly={instlCstSprtYn !== 'Y'} /> </FormUi> )} @@ -358,7 +354,7 @@ useEffect(() =>{ name="reuseBuilding.0.grntchBdstCertYr" render={({ field }) => ( <FormUi label="인증년도"> - <Input className="" placeholder="2024" type="" value={field.value ?? ""} + <Input className={selectClass} placeholder="2024" type="" value={field.value ?? ""} onChange={field.onChange} readOnly={grntchBdstCertYn!=='Y'}/> @@ -373,7 +369,7 @@ useEffect(() =>{ render={({ field }) => ( <FormUi label="인증번호"> <Input - className="" + className={selectClass} placeholder="ab1234678" type="" value={field.value ?? ""} @@ -390,7 +386,7 @@ useEffect(() =>{ name="reuseBuilding.0.grntchBdstCertGrd" render={({ field }) => ( <FormUi label="인증등급"> - <Input className="" placeholder="A" type="" value={field.value ?? ""} + <Input className={selectClass} placeholder="A" type="" value={field.value ?? ""} onChange={field.onChange} readOnly={grntchBdstCertYn!=='Y'} /> diff --git a/apps/wr/components/ui/form/fcltReg/rswtrReg/rswtrRegForm.tsx b/apps/wr/components/ui/form/fcltReg/rswtrReg/rswtrRegForm.tsx index 11dccc189..7696e88d7 100644 --- a/apps/wr/components/ui/form/fcltReg/rswtrReg/rswtrRegForm.tsx +++ b/apps/wr/components/ui/form/fcltReg/rswtrReg/rswtrRegForm.tsx @@ -9,8 +9,8 @@ import { } 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 { useForm } from "react-hook-form"; +import { z } from "zod"; import { useWrStore } from "@/app/store"; import { selectClass } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import { @@ -19,6 +19,10 @@ import { } from "@/app/store/ruseFcltMng/fcltReg/rswtReg"; import { useEffect } from "react"; import BdstReg from "../bdstReg/bdstReg"; +import { + formatCommaNumber, + handleCommaNumberChange, +} from "@/components/lib/func/commom"; export default function RswtrRegForm({ rswtForm, @@ -27,78 +31,69 @@ export default function RswtrRegForm({ rswtForm: customRswtBdst; isModal: boolean; }) { - const { rswt, code ,rswtUpdate,rswtReg} = useWrStore((state) => state); - + const { rswt, code, rswtBdstUpdate, rswtBdstReg } = useWrStore((state) => state); const defaultValues: z.infer<typeof rswtZod> = rswtZod.parse({}); - const form = useForm<z.infer<typeof rswtZod>>({ resolver: zodResolver(rswtZod), defaultValues: defaultValues, - - }) + }); - const [grntchBdstCertYn, instlCstSprtYn,filtrTrtmfctProcs] = form.watch([ + const [grntchBdstCertYn, instlCstSprtYn, filtrTrtmfctProcs] = form.watch([ "reuseBuilding.0.grntchBdstCertYn", "reuseBuilding.0.instlCstSprtYn", "reuseBuilding.0.rswtrObj.filtrTrtmfctProcs", ]); - const onSubmit =(values: z.infer<typeof rswtZod>) => { + const onSubmit = (values: z.infer<typeof rswtZod>) => { if (isModal) { - rswtReg(values); - } else { - rswtUpdate(values); - } - } - const cleanRswtData = (raw: any): z.infer<typeof rswtZod> =>{ + rswtBdstReg(values,'41'); + } else { + rswtBdstUpdate(values,'41'); + } + }; + const cleanRswtData = (raw: any): z.infer<typeof rswtZod> => { return { ...raw, - frstArchPrmsnDt: new Date(raw?.frstArchPrmsnDt||null), - archChgPrmsnDt: raw?.archChgPrmsnDt ? new Date(raw?.archChgPrmsnDt) : null, + frstArchPrmsnDt: new Date(raw?.frstArchPrmsnDt || null), + archChgPrmsnDt: raw?.archChgPrmsnDt + ? new Date(raw?.archChgPrmsnDt) + : null, reuseBuilding: (raw?.reuseBuilding || []).map((item: any) => ({ ...item, instlCmptnDt: new Date(item?.instlCmptnDt), operMngCd: item?.operMngCd ?? "", // null → "" - grntchBdstCertYr: typeof item?.grntchBdstCertYr === "string" - ? item?.grntchBdstCertYr - : "", // null → "" + grntchBdstCertYr: + typeof item?.grntchBdstCertYr === "string" + ? item?.grntchBdstCertYr + : "", // null → "" rswtrObj: { - ...item?.rswtrObj - } - })) + ...item?.rswtrObj, + }, + })), }; - } + }; + useEffect(() => { + console.log("form errors:", form.formState.errors); + }, [form.formState.errors]); -useEffect(() => { - console.log("form errors:", form.formState.errors); -}, [form.formState.errors]); + useEffect(() => { + console.log("filtrTrtmfctProcs ", filtrTrtmfctProcs); + if (grntchBdstCertYn === "N") { + form.setValue("reuseBuilding.0.grntchBdstCertYr", ""); + form.setValue("reuseBuilding.0.grntchBdstCertNo", ""); + form.setValue("reuseBuilding.0.grntchBdstCertGrd", ""); + } else if (instlCstSprtYn === "N") { + form.setValue("reuseBuilding.0.instlCstSprtAmt", 0); + } + }, [grntchBdstCertYn, instlCstSprtYn, filtrTrtmfctProcs]); - - -useEffect(() =>{ - - console.log("filtrTrtmfctProcs ", filtrTrtmfctProcs) - if(grntchBdstCertYn ==='N'){ - form.setValue('reuseBuilding.0.grntchBdstCertYr' ,"" ) - form.setValue('reuseBuilding.0.grntchBdstCertNo' ,"" ) - form.setValue('reuseBuilding.0.grntchBdstCertGrd' ,"" ) - }else if(instlCstSprtYn ==='N'){ - form.setValue('reuseBuilding.0.instlCstSprtAmt' ,0 ) - } -},[grntchBdstCertYn,instlCstSprtYn,filtrTrtmfctProcs ]) - - - - -useEffect(() => { - if(rswtZod) - form.reset( cleanRswtData(rswtForm)) + useEffect(() => { + if (rswtZod) form.reset(cleanRswtData(rswtForm)); }, [rswtForm]); - return ( <div className=""> <Form {...form}> @@ -106,20 +101,18 @@ useEffect(() => { {/* <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"> - ○ 중수도 시설 정보 - </h1> - <Button size={"sm"} type="submit" className="col-start-12 col-span-1"> + <h1 className="pl-3 text-xl col-span-10">○ 중수도 시설 정보</h1> + <Button + size={"sm"} + type="submit" + className="col-start-12 col-span-1" + > 저장 </Button> </div> </div> - {isModal && rswtForm != undefined ? ( - <BdstReg form={form} /> - ) : ( - <></> - )} + {isModal && rswtForm != undefined ? <BdstReg form={form} /> : <></>} {isModal ? ( <h1 className="pl-3 text-xl col-span-10 mt-4 "> ○ 중수도 시설 정보{" "} @@ -160,11 +153,13 @@ useEffect(() => { render={({ field }) => ( <FormUi label="설치비"> <Input - className="" + className={selectClass} placeholder="1,000,000" - type="number" - value={field.value ?? ""} - onChange={(e) => field.onChange(Number(e.target.value))} + type="text" + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -179,11 +174,13 @@ useEffect(() => { render={({ field }) => ( <FormUi label="물사용량(m³)"> <Input - className="" + className={selectClass} placeholder="1,000,000" - type="number" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + type="text" + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -197,11 +194,13 @@ useEffect(() => { render={({ field }) => ( <FormUi label="의무대상 물사용량(m³)"> <Input - className="" + className={selectClass} placeholder="1,000,000" - type="number" - value={field.value ?? 0} - onChange={(e) => field.onChange(Number(e.target.value))} + type="text" + onChange={(e) => { + handleCommaNumberChange(e, field.onChange); + }} + value={formatCommaNumber(field.value)} /> </FormUi> )} @@ -240,7 +239,7 @@ useEffect(() => { render={({ field }) => ( <FormUi label="주요처리공정"> <Input - className="" + className={selectClass} placeholder="1,000,000" type="" value={field.value ?? ""} @@ -286,14 +285,14 @@ useEffect(() => { render={({ field }) => ( <FormUi label="지원금액(원)"> <Input - className="" + className={selectClass} placeholder="1,000,000" - type="number" - value={field.value ?? 0} + type="text" onChange={(e) => { - field.onChange(Number(e.target.value)); + handleCommaNumberChange(e, field.onChange); }} - readOnly={instlCstSprtYn!=='Y'} + value={formatCommaNumber(field.value)} + readOnly={instlCstSprtYn !== "Y"} /> </FormUi> )} @@ -330,13 +329,13 @@ useEffect(() => { render={({ field }) => ( <FormUi label="인증년도"> <Input - className="" + className={selectClass} placeholder="2024" type="text" {...field} value={field.value ?? ""} onChange={field.onChange} - readOnly={grntchBdstCertYn!=='Y'} + readOnly={grntchBdstCertYn !== "Y"} /> </FormUi> )} @@ -349,13 +348,12 @@ useEffect(() => { render={({ field }) => ( <FormUi label="인증번호"> <Input - className="" + className={selectClass} placeholder="ab1234678" type="" value={field.value ?? ""} onChange={field.onChange} - readOnly={grntchBdstCertYn!=='Y'} - + readOnly={grntchBdstCertYn !== "Y"} /> </FormUi> )} @@ -368,13 +366,12 @@ useEffect(() => { render={({ field }) => ( <FormUi label="인증등급"> <Input - className="" + className={selectClass} placeholder="A" type="" value={field.value ?? ""} onChange={field.onChange} - readOnly={grntchBdstCertYn!=='Y'} - + readOnly={grntchBdstCertYn !== "Y"} /> </FormUi> )} diff --git a/apps/wr/components/ui/modal/chkgdExcel/chkgdExcel.tsx b/apps/wr/components/ui/modal/chkgdExcel/chkgdExcel.tsx index 625fbdebd..895af4388 100644 --- a/apps/wr/components/ui/modal/chkgdExcel/chkgdExcel.tsx +++ b/apps/wr/components/ui/modal/chkgdExcel/chkgdExcel.tsx @@ -25,7 +25,6 @@ export default function ChkgdExcel({ type }: { type: string }) { }); const [files, setFiles] = useState<File[] | null>(null); const [excelData , setExcelData] = useState<rainChkZodType[]>() - const defaultValues: z.infer<typeof rainRegExcel> = rainRegExcel.parse({}); const form = useForm<z.infer<typeof rainRegExcel>>({ @@ -36,17 +35,14 @@ export default function ChkgdExcel({ type }: { type: string }) { useEffect(() => { if (files) { const file = files[0]; - if(form.getValues("chckYr").length<1 ){ - alert("등록년도를 입력해주세요"); + ToastFormUi({body:"파일업로드 이전에 등록년도를 작성해주세요 " ,title:'지도점검 등록'}) setFiles(null) return } if (file) filePicked(file, 0).then((res) => { if (res !== undefined) - - console.log("exex ", excelToRainChkData(res, form.getValues("chckYr"))) setExcelData(excelToRainChkData(res, form.getValues("chckYr"))) }); } @@ -54,15 +50,13 @@ export default function ChkgdExcel({ type }: { type: string }) { const onSubmit =(values: z.infer<typeof rainRegExcel>)=> { if(values.chckYr ===''){ - console.log(values.chckYr) - ToastFormUi({body:"등록년도를 작성해주세요" ,title:'엑셀등록'}) + ToastFormUi({body:"등록년도를 작성해주세요" ,title:'지도점검 등록'}) return }else if(excelData ===undefined || excelData?.length === 0 ){ - ToastFormUi({body:"빈 파일입니다." ,title:'엑셀등록'}) + ToastFormUi({body:"빈 파일 및 파일 오류 입니다." ,title:'지도점검 등록'}) return } if (excelData) { - console.log("excelData ", excelData) rainChkExcelDataUPload(excelData); } } @@ -126,7 +120,7 @@ export default function ChkgdExcel({ type }: { type: string }) { </form> </Form> </div> - <Toaster position="top-center" /> + </> ); } diff --git a/apps/wr/components/ui/modal/headChModal/headChModal.tsx b/apps/wr/components/ui/modal/headChModal/headChModal.tsx index d6b30c199..2f1236f27 100644 --- a/apps/wr/components/ui/modal/headChModal/headChModal.tsx +++ b/apps/wr/components/ui/modal/headChModal/headChModal.tsx @@ -1,10 +1,9 @@ import { useWrStore } from "@/app/store"; -import type { TableProps } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg"; -import type { TableTripleProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; +import { rainSttnHeadListType } from "@/app/store/ruseFcltMng/fcltSttn/rainSttn/headList"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@common/business_components/ui"; import { Button, Checkbox } from "@common/components/ui"; import { zodResolver } from "@hookform/resolvers/zod"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { z } from "zod"; @@ -12,38 +11,34 @@ export default function HeadChModal({type }:{type: string }) { const { rainSttn ,rainChSttnHead} = useWrStore((state) => state); - const { rainSttHeadList } =rainSttn; - let items = rainSttHeadList.map(item => ({id:item.id, label:item.title, val:item.visible })); + const { rainSttHeadList, rainSttNodeList } =rainSttn; + let items = rainSttHeadList.map(item => ({id:item.id, title:item.title, val:item.visible })); - const FormSchema = z.object({ - data: z.array(z.string()).refine((value) => value.some((item) => item), { - message: "최소한 하나를 선택해주시길 바랍니다.", - - }), - }) - - const form = useForm<z.infer<typeof FormSchema>>({ - resolver: zodResolver(FormSchema), - defaultValues: { - data: [], - }, - }) + // const FormSchema = + // z.object({ + // id: z.string().refine((value) => value.some((item) => item), { + // message: "최소한 하나를 선택해주시길 바랍니다.", + // }), + // visible: z.boolean() + // }) + + + const form = useForm<z.infer<typeof rainSttnHeadListType>>({ + resolver: zodResolver(rainSttnHeadListType), + defaultValues: [], + }) useEffect(() =>{ - form.reset({ data: items.map((el) => el.val!==undefined ? el.val.toString():undefined )}) - + form.reset(rainSttHeadList) },[rainSttHeadList]) - const onSubmit = (val : z.infer<typeof FormSchema>) =>{ - - if(val?.data.length > 0) - rainChSttnHead(val?.data, ) - + const onSubmit = (headList : z.infer<typeof rainSttnHeadListType> ) =>{ + rainChSttnHead(headList) } return ( @@ -51,57 +46,41 @@ export default function HeadChModal({type }:{type: string }) { <div> <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8"> - <FormField - control={form.control} - name="data" - render={() => ( - <FormItem> + <div className="mb-4"> - <FormLabel className="text-2xl"> 조회항목 설정</FormLabel> - + <h3>조회항목 설정</h3> </div> - {items.map((item) => ( + {items.map((item,index) => ( <FormField - key={item.id} + key={`${index}.id`} control={form.control} - name="data" + name={`${index}.visible`} render={({ field }) => { return ( <FormItem - key={item.id} + key={`${index}.id`+'item'} className="flex flex-row items-start space-x-3 space-y-0" > <FormControl> <Checkbox - checked={field.value?.includes(item.id)} + checked={field.value} onCheckedChange={(checked) => - { - return checked - ? field.onChange([...field.value, item.id]) - : field.onChange( - field.value?.filter( - (value) => value !== item.id - ) - ); - } - + field.onChange(checked); + return; + } } /> </FormControl> <FormLabel className="text-xl"> - {item.label} + {item.title} </FormLabel> </FormItem> ); }} /> ))} - <FormMessage /> - </FormItem> - )} - /> <Button type="submit">항목 표출 변경</Button> </form> </Form> diff --git a/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable.tsx b/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable.tsx index e9bc79108..4aa57fe5e 100644 --- a/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable.tsx +++ b/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable.tsx @@ -14,14 +14,16 @@ import { } from "@common/components/ui"; import { useCallback, useEffect, useState } from "react"; export default function RainChkgdTable({ - detailUp, handleClick=() => {} + detailUp, + handleClick=() => {}, + deleteData }: { detailUp: (data: rainChkZodType[]) => void; handleClick?: (data:any) => void; + deleteData:(selectedIds:number[])=>void }) { const { code, rainChkgdn } = useWrStore((state) => state); const [makeTableData, setMakeTableData] = useState<any[]>([]); - const { rainChk } = rainChkgdn; const [selectedIds, setSelectedIds] = useState<number[]>([]); const [upRaintDetail, setUpRaintDetail] = useState<rainChkZodType[]>([]); const toggleSelection = (pk: number, checked: boolean) => { @@ -34,9 +36,11 @@ export default function RainChkgdTable({ field: keyof (typeof makeTableData)[0], value: string | number ) => { + setMakeTableData((prev) => - prev.map((row, idx) => - idx === rowIndex ? { ...row, [field]: value } : row + prev.map((row, idx) => { + return idx === rowIndex ? { ...row, [field]: value } : row + } ) ); }; @@ -53,9 +57,9 @@ export default function RainChkgdTable({ useEffect(() => { - const rainChg = rainChk.map((item: any) => { + setSelectedIds([])// 셀렉트 초기화를 위한 작업 + const rainChg = rainChkgdn.rainChk.map((item: any) => { const bud = tableData([item.building], { code }); - return { ...item, ...bud[0], @@ -64,22 +68,28 @@ export default function RainChkgdTable({ }); const tableTotalData = rightTableData(rainChg) setMakeTableData(tableTotalData); - }, [rainChk, code]); + }, [rainChkgdn.rainChk, code]); useEffect(() => { - const selectedData = makeTableData.filter((item) => - selectedIds.includes(item.chkgdnPk) - ); - if (selectedData.length > 1) { - const updateTableData = rainChk + + + //데이터를 평탄화 한것중에 체크박스 선택한 테이블만 선택 + const selectedData = makeTableData.filter((item) =>selectedIds.includes(item.chkgdnPk)); + + if (selectedData.length > 0) { + const updateTableData = rainChkgdn.rainChk .map((rc) => { const newRainyDetail = rc.rainyDetails .map((rd) => { + + // 변경 데이터는 평탄화한 데이터 즉 루트에 변경되어 있음 이용용도까지 잇음 그걸로 찾기 const findRain = selectedData.find( (sd) => rd.chkgdnFk === sd.chkgdnPk && rd.utztnUsgCd === sd.utztnUsgCd ); + if (findRain != undefined) { + console.log(findRain) return { ...rd, ph: Number(findRain.ph), @@ -105,14 +115,28 @@ export default function RainChkgdTable({ } }) .filter(Boolean); + setUpRaintDetail(updateTableData as rainChkZodType[]); } - }, [makeTableData]); + }, [makeTableData,selectedIds]); useEffect(() => { detailUp(upRaintDetail); }, [upRaintDetail]); + + useEffect(() =>{ + if(selectedIds.length >0){ + // 삭제를 위한 데이터 삽입 + deleteData(selectedIds ) + } + },[selectedIds]) + + useEffect(() => { + + },[]) + + return ( <Table variant="secondary"> <TableHeader className="font-bold"> diff --git a/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTableModal.tsx b/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTableModal.tsx deleted file mode 100644 index 3cc5bdbbb..000000000 --- a/apps/wr/components/ui/table/chkgdTable/rainChkgd/rainChkgdTableModal.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import ChkgdModal from "@/components/ui/modal/chkgdModal/chkgdModal"; -import { UiModal } from "@common/business_components"; - -export default function RainChkgdTableModal({ isModal, setIsModal }: { isModal: { open: boolean; data: any }; setIsModal: (value: { open: boolean; data: any }) => void }) { - return (<UiModal - open={isModal.open} - onOpenChange={() => { - setIsModal({ open: !open, data: {} }); - }} - bodyClass={"w-[80vw] max-w-none"} - body={<ChkgdModal type={"RNB"} obj={isModal.data} />} - ></UiModal>) -} \ No newline at end of file From f04a463aebd60084f6430ed0c2ac780a750c5165 Mon Sep 17 00:00:00 2001 From: leedj312 <dlehd467@gmail.com> Date: Tue, 6 May 2025 23:09:34 +0900 Subject: [PATCH 29/29] =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=EC=97=90?= =?UTF-8?q?=EC=84=9C=20visible=20=EB=B0=8F=20filter=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/table/HeadMakeColSpan.tsx | 12 +++++++++--- .../business_components/src/ui/table/index.tsx | 5 ++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/common/business_components/src/ui/table/HeadMakeColSpan.tsx b/packages/common/business_components/src/ui/table/HeadMakeColSpan.tsx index dc859a55d..ebd611c1d 100644 --- a/packages/common/business_components/src/ui/table/HeadMakeColSpan.tsx +++ b/packages/common/business_components/src/ui/table/HeadMakeColSpan.tsx @@ -8,16 +8,20 @@ interface TableUpperProps { row? : number; rowSpan?: number; colSpan?: number; + visible?:boolean; } const HeadMakeColSpan = ({ upHeadList }: { upHeadList: TableUpperProps[] }) => { - const maxRow = upHeadList.reduce((max, head) => Math.max(max, head.row || 0), 0); + const maxRow = upHeadList?.reduce((max, head) => Math.max(max, head.row || 0), 0); + //upHeadList.forEach((item) => item.visible ?item.visible:true) if(maxRow == 0){ return ( <> <TableRow className="bg-gray-50"> - {upHeadList.map((head: TableUpperProps) => { + {upHeadList + .filter((item) => item.visible != false) + .map((head: TableUpperProps) => { return ( <TableHead key={head.id} @@ -38,7 +42,9 @@ const HeadMakeColSpan = ({ upHeadList }: { upHeadList: TableUpperProps[] }) => { <> {Array.from({ length: maxRow + 1 }, (_, rowIndex) => ( <TableRow key={rowIndex+ " headerRow"} className="bg-gray-50"> - {upHeadList.map((head: TableUpperProps) => { + {upHeadList + .filter((item) => item.visible != false) + .map((head: TableUpperProps) => { if (head.row === rowIndex) { return ( <TableHead diff --git a/packages/common/business_components/src/ui/table/index.tsx b/packages/common/business_components/src/ui/table/index.tsx index 45748fb37..00fc376e6 100644 --- a/packages/common/business_components/src/ui/table/index.tsx +++ b/packages/common/business_components/src/ui/table/index.tsx @@ -20,6 +20,7 @@ type UiHeadProps = { id: string; title: string; align?: string; + visible?:boolean; } export function UiTable({ tableData, headlist, pageSize, total, headName, children, cellClick, onPageChange, className = '', resetPageNo = false }: UiTableProps) { @@ -58,7 +59,9 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr <TableBody className='text-center'> {tableData.length > 0 ? tableData?.map((el: { [key: string]: any}, index) => ( <TableRow key={`row-${index}`}> - {headlist?.map((head) => ( + {headlist + .filter((item) => item.visible != false) + .map((head) => ( head.id && head.id.length > 1 && ( <TableCell className={`${head.align === 'right' ? 'text-right' : head.align === 'center' ? 'text-center' : typeof el[head.id] === 'number' ? 'text-right' : 'text-center'} ${