"use client"; import { useWrStore } from "@/app/store"; import type { RainStatProps } from "@/app/store/stats/rainStat"; import { excelDownload, tableData, yearOptions } from "@/components/lib/func/commom"; import { downloadExcel } from "@common/business_components"; import { ContentsDiv, ScrollArea, SearchDiv, SelectBox, Title, UiTable } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button } from "@common/components/ui"; import { useEffect, useState } from "react"; export default function RainStat() { const { code, rainStat, searchRainStatList } = useWrStore((state) => state); const { rainStatList, excelList, rainDetailList } = rainStat; const [searchYear, setSearchYear] = useState( String(new Date().getFullYear()) ); const [exData, setExData] = useState>>(); const [bdstTable, setBdstTable] = useState(); useEffect(() => { searchRainStatList(searchYear); }, [code.cityCd, code.sggCd, searchRainStatList]) const excelDetailDownLoad=() =>{ const sidoList = new Set(); const sidoDataMap = new Map(); // 시도별 데이터를 저장할 Map const sidoDetailMap = 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) { if (!sidoDetailMap.has(sidoText)) { sidoDetailMap.set(sidoText, []); } sidoDetailMap.get(sidoText)!.push(item as unknown as (string | number)[]); } // 시도별 합계 데이터 수집 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]) === '대상').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] = ''; } } } }); // 시도별로 합계와 상세 데이터를 순서대로 배치 const summaryExcelData: (string | number)[][] = []; // 시도별로 순회하면서 합계와 상세 데이터를 추가 Array.from(sidoList).forEach((sidoText) => { const sidoSummary = sidoDataMap.get(sidoText); const sidoDetails = sidoDetailMap.get(sidoText) || []; if (sidoSummary) { // 시도 합계 데이터 추가 summaryExcelData.push(sidoSummary); // 해당 시도의 상세 데이터들 추가 sidoDetails.forEach(detail => { summaryExcelData.push(detail); }); } }); const sidoSummaryList = Array.from(sidoDataMap.values()); const sidoTotalSummary = [['전체', '', '합계', 0, '', '', 0, '', '', 0, 0, 0, 0, 0, 0, '', 0]]; sidoSummaryList.forEach((item: (string | number)[]) => { item.forEach((value: string | number, index: number) => { if(typeof value === 'number') { if (sidoTotalSummary[0] && index < sidoTotalSummary[0].length) { sidoTotalSummary[0][index] = Number(sidoTotalSummary[0][index]) + Number(value); } } }); }); // sidoSummaryList와 rainDetailList를 합쳐서 엑셀 데이터 생성 const excelData = [...sidoTotalSummary, ...sidoSummaryList, ...summaryExcelData]; excelDownload( excelData as unknown as [][], "빗물이용시설 통계", "sample_rainStats.xlsx", "A1:V3", 4 ); } const excelClick = () => { downloadExcel({ data: (exData as unknown as JSON[]) ?? [], fileName: "재이용통계", sheetNameArray: ["Sheet1"], headerRange: "A1:M1" }) } useEffect(() => { const transExcel = Array.isArray(excelList) ? excelList : [excelList]; const excelData = tableData(transExcel, { code }); const tbData = Array.isArray(excelData) ? excelData.map((item: RainStatProps) => { return { "시도": item.cityText, "개소": item.tmp, "설치비(백만원)": item.instlCst, "저류조용량(m³/년)": item.dtfcltCpct, "연간사용량(m³/년)": item.wtrUsqty, "조경용수": item.lndwtr, "청소화장실용수": item.cleanToilUswtr, "세척살수용수": item.resn, "농업용수": item.farmUswtr, "공업용수": item.indstUswtr, "친수용수": item.hydUswtr, "기타": item.ithlEtcUswtr, "연간운영비(백만원/년)": item.anlOperCst, }; }) : []; setExData(tbData); }, [code, excelList]) useEffect(() => { const transData = Array.isArray(rainStatList) ? rainStatList : [rainStatList]; const data = tableData(transData, { code }); const tbData = Array.isArray(data) ? data.map((item: RainStatProps) => { return { ...item, ctpvCd: item.cityText }; }).filter((item: RainStatProps) => item.cityText !== '없음') : []; setBdstTable(tbData); }, [code, rainStatList]); return ( <>
<SearchDiv> <div className="grid grid-cols-12 gap-5 m-4"> <div className="col-span-2"> <SelectBox className="w-full h-full text-2xl" label="통계년도" selectClass={""} selectArray={yearOptions} value={searchYear} onSelectValue={(val: string | number) => setSearchYear(String(val)) } /> </div> <div className="flex flex-row space-x-2 items-center"> <Button className="" size={"sm"} onClick={()=>{searchRainStatList(searchYear);}}> 조회 </Button> <Button className="" size={"sm"} onClick={() => excelClick()}> 다운로드 </Button> <Button className="" size={"sm"} onClick={() => excelDetailDownLoad()}> 전체통계다운로드 </Button> </div> </div> </SearchDiv> {/* <SearchFormRight> </SearchFormRight> */} </div> </div> <div className="grid grid-cols-6 gap-4"> <div className="col-span-6 h-full min-h-0"> <ListDiv className=""> <ScrollArea className="h-[67vh]"> <UiTable tableData={bdstTable || []} headlist={rainStat.rainStatHeadList} pageSize={10} total={0} headName={""} cellClick={undefined} onPageChange={() => {}} ></UiTable> </ScrollArea> </ListDiv> </div> </div> </ContentsDiv> </> ); }