diff --git a/apps/wr/app/stats/rainStat/page.tsx b/apps/wr/app/stats/rainStat/page.tsx index b2f2006bf..20ecf3ae9 100644 --- a/apps/wr/app/stats/rainStat/page.tsx +++ b/apps/wr/app/stats/rainStat/page.tsx @@ -2,8 +2,9 @@ import { useWrStore } from "@/app/store"; import type { RainStatProps } from "@/app/store/stats/rainStat"; -import { tableData, yearOptions } from "@/components/lib/func/commom"; +import { tableData, yearOptions, excelDownload } from "@/components/lib/func/commom"; import { downloadExcel } from "@common/business_components"; + import { ContentsDiv, SearchDiv, @@ -17,7 +18,7 @@ import { useCallback, useEffect, useState } from "react"; export default function RainStat() { const { code, rainStat, searchRainStatList } = useWrStore((state) => state); - const { rainStatHeadList, rainStatList, excelList } = rainStat; + const { rainStatHeadList, rainStatList, excelList, rainDetailList } = rainStat; const [pageNation, setPageNation] = useState(1); const [searchYear, setSearchYear] = useState( @@ -28,7 +29,104 @@ export default function RainStat() { useEffect(() => { searchRainStatList(searchYear); - }, [searchRainStatList, searchYear]) + }, [code.cityCd, code.sggCd, searchRainStatList, searchYear]) + + const excelDownLoad=() =>{ + const sidoList = new Set(); + const sidoDataMap = new Map(); // 시도별 데이터를 저장할 Map + + rainDetailList.forEach((item: RainStatProps[]) => { + const sidoVal = item.at(0)?.toString().trim(); + const sigunVal = item.at(1)?.toString().trim(); + + let sidoText = ''; + let sigunText = ''; + + const sido = code.cityCd.find((city) => city.val === sidoVal); + const sigun = code.sggCd.find((sgg) => sgg.val === sigunVal); + + sidoText = sido?.text || ''; + sigunText = sigun?.text || ''; + + // 시도, 시군구 코드를 텍스트로 변환하여 데이터에 할당 + if (item.length > 0) { + item[0] = sidoText as unknown as RainStatProps; + } + if (item.length > 1) { + item[1] = sigunText as unknown as RainStatProps; + } + if (item.length > 2) { + item[2] = sidoText+' '+sigunText as unknown as RainStatProps; + } + + // 시도별 데이터 수집 + if (sidoText && !sidoList.has(sidoText)) { + sidoList.add(sidoText); + // 시도별 초기 데이터 구조 생성 (예: [시도명, 0, 0, 0, ...]) + const initialData: (string | number)[] = [sidoText]; + // 데이터의 나머지 컬럼들을 0으로 초기화 (실제 컬럼 수에 맞게 조정 필요) + for (let i = 1; i < item.length; i++) { + initialData.push(0); + } + sidoDataMap.set(sidoText, initialData); + } + }); + // 시도별 합계 계산 + rainDetailList.forEach((item: RainStatProps[]) => { + const sidoText = item[0]?.toString(); + if (sidoText && sidoDataMap.has(sidoText)) { + const sidoData = sidoDataMap.get(sidoText); + // 각 컬럼의 값을 합계에 더하기 (1번 인덱스부터 시작) + for (let i = 1; i < item.length && i < sidoData.length; i++) { + if(i == 2){ + sidoData[i] = '합계'; + } else if(i == 3){ + // 해당 시도의 데이터 개수를 계산 + const sidoDataCount = rainDetailList.filter((data: unknown[]) => + Array.isArray(data) && data.length > 0 && String(data[0]) === sidoText + ).length; + sidoData[i] = sidoDataCount; + } else if( i == 4){ + sidoData[i] = ''; + } else if(i == 6){ + // 법정 대상 건축물 개수 (인덱스 6이 'Y'인 경우) + const bumCnt = rainDetailList.filter((data: unknown[]) => + Array.isArray(data) && data.length > 6 && String(data[0]) === sidoText + ).filter((data: unknown[]) => String(data[6]) === 'Y').length; + sidoData[i] = bumCnt; + } else if(i==8){ + const value = Number(item[8]) || 0; + sidoData[i] = (Number(sidoData[i]) + value) as string | number; + } else if(i==11){ + const value = Number(item[11]) || 0; + sidoData[i] = (Number(sidoData[i]) + value) as string | number; + } else if(i==12){ + const value = Number(item[12]) || 0; + sidoData[i] = (Number(sidoData[i]) + value) as string | number; + } else if(i==14){ + const value = Number(item[14]) || 0; + sidoData[i] = (Number(sidoData[i]) + value) as string | number; + } + else { + sidoData[i] = ''; + } + } + } + }); + + // Map을 배열로 변환 + const sidoSummaryList = Array.from(sidoDataMap.values()); + // sidoSummaryList와 rainDetailList를 합쳐서 엑셀 데이터 생성 + const excelData = [...sidoSummaryList, ...rainDetailList]; + + excelDownload( + excelData, + "빗물이용시설 통계", + "sample_rainStats.xlsx", + "A1:V3", + 4 + ); + } const excelClick = () => { downloadExcel({ @@ -38,8 +136,7 @@ export default function RainStat() { headerRange: "A1:M1" }) } - - + useEffect(() => { const transExcel = Array.isArray(excelList) ? excelList : [excelList]; const excelData = tableData(transExcel, { code }); @@ -63,7 +160,7 @@ export default function RainStat() { }) : []; setExData(tbData); - }, [excelList]) + }, [code, excelList]) useEffect(() => { const transData = Array.isArray(rainStatList) ? rainStatList : [rainStatList]; @@ -77,7 +174,7 @@ export default function RainStat() { }) : []; setBdstTable(tbData); - }, [rainStatList]); + }, [code, rainStatList]); return ( <> @@ -106,7 +203,7 @@ export default function RainStat() { - @@ -125,9 +222,9 @@ export default function RainStat() { headlist={rainStat.rainStatHeadList} pageSize={20} total={10000} - headName={""} - cellClick={(val, headId) => { }} - onPageChange={setPageNation} + headName={"건축물 목록"} + cellClick={() => {}} + onPageChange={() => {}} > {/* */} diff --git a/apps/wr/app/store/stats/rainStat/excel.tsx b/apps/wr/app/store/stats/rainStat/excel.tsx new file mode 100644 index 000000000..35a918d83 --- /dev/null +++ b/apps/wr/app/store/stats/rainStat/excel.tsx @@ -0,0 +1,40 @@ +import type { RainStatProps } from "."; + +export const excelRainStat = (excelList:RainStatProps[]) : string[][] => { + const excelData: string[][] = []; + excelList.forEach((item) => { + excelData.push([ + //시도 + String(item.ctpvCd) ?? "", + //시군구 + String(item.sggCd) ?? "", + //행정구역명 + String(item.areaNm) ?? "", + //시설명 + String(item.bdstNm) ?? "", + //건축물용도코드 + String(item.bdstUsgCd) ?? "", + //주소 + String(item.daddr) ?? "", + //법적의무대상여부 + String(item.lawTrgtYn) ?? "", + //설치완료일자 + String(item.instlCmptnDt) ?? "", + //설치비용 + String(item.instlCst) ?? "", + //접수면종류 + String(item.pntfColKnd) ?? "", + //여과등처리시설유무 + String(item.filtrTrtmfctYn) ?? "", + //처리용량(저류조용량) + String(item.dtfcltCpct) ?? "", + //연간사용량 + String(item.wtrUsqty) ?? "", + //이용용도코드 + String(item.utztnUsgCd) ?? "", + //연간운영비 + String(item.anlOperCst) ?? "", + ]); + }); + return excelData; +} \ No newline at end of file diff --git a/apps/wr/app/store/stats/rainStat/index.tsx b/apps/wr/app/store/stats/rainStat/index.tsx index edb5ab0d5..68b1a051d 100644 --- a/apps/wr/app/store/stats/rainStat/index.tsx +++ b/apps/wr/app/store/stats/rainStat/index.tsx @@ -1,6 +1,7 @@ import { fetchType, getFetch } from "@/components/lib/api"; import type { TableUpperProps } from "../../common/type/header"; import { rainStatHeadListExport } from "./headList"; +import { excelRainStat } from "./excel"; export type RainStatProps = { ctpvCd: string //시도 @@ -35,6 +36,7 @@ export type RainStatProps = { export type GuideStatProps = { utztnUsgCd: string + splyUswtrUtztnQnt : number, ruseFcltUtztnQnt: number } @@ -58,6 +60,7 @@ export type rainStatState = { rainStatHeadList: TableUpperProps[], rainStatList: RainStatProps[], excelList: ExcelType[] + rainDetailList : [][] } } @@ -67,7 +70,8 @@ export const rainStatExport: rainStatState = { rainStat: { rainStatHeadList: rainStatHeadListExport, rainStatList: [], - excelList: [] + excelList: [], + rainDetailList : [] } } export const rainStatActionsExport = ( @@ -76,8 +80,7 @@ export const rainStatActionsExport = ( return { searchRainStatList: async (year: string) => { const res = await fetchRainStatList(year); - - let cityArr: any[] = []; + const cityArr: any[] = []; res.forEach((item: RainStatProps) => { let obj = cityArr.find((e) => { @@ -136,9 +139,42 @@ export const rainStatActionsExport = ( }) }) + //상세세 + const rainDetailList : RainStatProps[] = []; + res.forEach((item:RainStatProps) => { + const utztnUsgArray = new Array(); + item.guideStats.forEach((guideStat) => { + utztnUsgArray.push(guideStat.utztnUsgCd); + }) + rainDetailList.push({ + ...item, + utztnUsgCd : utztnUsgArray.join(', '), + }) + }) + const excelDetailData = excelRainStat(rainDetailList); + /* const rainStatHeadList = data.map((item:RainStatProps) => ({ + ...item, + ctpvCd:item.ctpvCd, + sggCd:item.sggCd, + areaNm:item.areaNm, + archArea:item.archArea, + dtfcltCpct:item.dtfcltCpct, + annRnwtQty:item.annRnwtQty, + jungsudo:item.jungsudo, + dachae:item.dachae, + way1:item.way1, + way2:item.way2, + way3:item.way3, + way4:item.way4, + way5:item.way5, + way6:item.way6, + way7:item.way7, + yearMoney:item.yearMoney, + })) */ set((state: rainStatState) => ({ rainStat: { ...state.rainStat, + rainDetailList: excelDetailData as [][], rainStatList: cityArr, excelList: excelDownList } diff --git a/apps/wr/public/sample_rainStats.xlsx b/apps/wr/public/sample_rainStats.xlsx new file mode 100644 index 000000000..c8f8e69b5 Binary files /dev/null and b/apps/wr/public/sample_rainStats.xlsx differ