diff --git a/apps/wr/app/matMng/coMng/ldrmntCoSttn/page.tsx b/apps/wr/app/matMng/coMng/ldrmntCoSttn/page.tsx index 4b2fe4416..bd48782aa 100644 --- a/apps/wr/app/matMng/coMng/ldrmntCoSttn/page.tsx +++ b/apps/wr/app/matMng/coMng/ldrmntCoSttn/page.tsx @@ -2,11 +2,12 @@ import { useWrStore } from "@/app/store"; import { btnClass } from "@/app/store/common/code"; -import { type customLdrmntBdst } from "@/app/store/matDmd/ldrmntCoSttn"; -import { ldrmntNodeListExport } from "@/app/store/matDmd/ldrmntCoSttn/headList"; +import { type customLdrmnt } from "@/app/store/matDmd/ldrmntCoSttn"; +import { ldrmntHeadListExport, ldrmntNodeListExport } from "@/app/store/matDmd/ldrmntCoSttn/headList"; import { excelDownload, getCity, + getCityOrSgg, tableData } from "@/components/lib/func/commom"; import CoRegExcel from "@/components/ui/modal/coReg/coRegExcel/coRegExcelModal"; @@ -34,23 +35,20 @@ export default function LdrmntCoSttn() { (state) => state ); const { ldrmntRes } = ldrmnt; - const [detailModal, setDetailModal] = useState<{ isOpen: boolean, data: customLdrmntBdst | undefined }>({ data: undefined, isOpen: false }) + const [detailModal, setDetailModal] = useState<{ isOpen: boolean, data: customLdrmnt | undefined }>({ data: undefined, isOpen: false }) const [pageNation, setPageNation] = useState(1); const [selectSgg, setSelectSgg] = useState() const [objSearch, setObjSearch] = useState({ sgg: "", city: "" }); - const ref = useRef({} as ReturnType); - const [bdstTable, setBdstTable] = useState(); - const [codeData, setCodeData] = useState(); + const [bdstTable, setBdstTable] = useState(); const [searchTxt, setSearchTxt] = useState(); - const [bdstChgProps, setBdstChgProps] = useState<{ - isOpen: boolean; - data: customLdrmntBdst[]; - }>({ isOpen: false, data: [] }); + const ref = useRef({} as ReturnType); + const codeData = getCityOrSgg(ref); + const excelClick = useCallback(() => { excelDownload( [[]], "잠재수요처 관리", - "sample_ldrmnt.xlsx", + "sample_ldrmntCoSttn.xlsx", "A1:AL1", 2 ); @@ -80,17 +78,19 @@ export default function LdrmntCoSttn() { useEffect(() => { if (!ldrmnt.isInit) { - ldrmntInit(); + ldrmntInit(codeData ?? "0"); } }, [ldrmnt.isInit, ldrmntInit]); useEffect(() => { - const data = tableData(ldrmntRes, { code }); + const transData = Array.isArray(ldrmntRes) ? ldrmntRes : [ldrmntRes]; + const data = tableData(transData, { code }); const tbData = Array.isArray(data) - ? data.map((item: customLdrmntBdst) => ({ + ? data.map((item: customLdrmnt) => ({ ...item, - ctpvCd: item.fctryAddr.split(" ")[0] || "", + ctpvCd: item.fctryAddr.split(" ")[0] || "", sggCd: item.fctryAddr.split(" ")[1] || "" + })) : []; @@ -202,7 +202,7 @@ export default function LdrmntCoSttn() { { cellClick(index ?? undefined, headId) }} diff --git a/apps/wr/app/stats/rainStat/page.tsx b/apps/wr/app/stats/rainStat/page.tsx index f4d42e033..d1b2f54cc 100644 --- a/apps/wr/app/stats/rainStat/page.tsx +++ b/apps/wr/app/stats/rainStat/page.tsx @@ -1,81 +1,264 @@ "use client"; + import { useWrStore } from "@/app/store"; -import { yearOptions } from "@/components/lib/func/commom"; +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, - SearchFormLeft, SelectBox, Title, - UiTable, + UiTable } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button } from "@common/components/ui"; -import { useState } from "react"; +import { useEffect, useState } from "react"; + +export default function RainStat() { + const { code, rainStat, searchRainStatList } = useWrStore((state) => state); + const { rainStatList, excelList, rainDetailList } = rainStat; -export default function rainStat() { - const { code, rainStat } = useWrStore((state) => { - return state; - }); - const [pageNation, setPageNation] = useState(1); const [searchYear, setSearchYear] = useState( String(new Date().getFullYear()) ); + const [exData, setExData] = useState>>(); + const [bdstTable, setBdstTable] = useState(); + + useEffect(() => { + searchRainStatList(searchYear); + }, [code.cityCd, code.sggCd, searchRainStatList, searchYear]) + + 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()); + // sidoSummaryList와 rainDetailList를 합쳐서 엑셀 데이터 생성 + const excelData = [...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.ctpvCd, + "개소": 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.ctpvCd + }; + }) + : []; + setBdstTable(tbData); + }, [code, rainStatList]); return ( <>
- + <Title title={"빗물이용시설 통계"} /> <SearchDiv> - <SearchFormLeft> - <SelectBox - className="w-full h-full text-2xl" - label="통계년도" - selectClass={""} - selectArray={yearOptions} - value={searchYear} - onSelectValue={(val: string | number) => - setSearchYear(String(val)) - } - /> + <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={(e) => {}}> + <Button className="" size={"sm"} onClick={() => { }}> 조회 </Button> - <Button className="" size={"sm"} onClick={(e) => {}}> + <Button className="" size={"sm"} onClick={() => excelClick()}> 다운로드 </Button> - <Button className="" size={"sm"} onClick={(e) => {}}> + <Button className="" size={"sm"} onClick={() => excelDetailDownLoad()}> 전체통계다운로드 </Button> </div> - </SearchFormLeft> - {/* <SearchFormRight> - - </SearchFormRight> */} + </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="min-h-0"> - {/* <ScrollArea className="h-[60vh]"> */} - <UiTable - tableData={[]} - headlist={rainStat.rainStatHeadList} - pageSize={20} - total={10000} - headName={"건축물 목록"} - cellClick={(val, headId) => {}} - onPageChange={setPageNation} - ></UiTable> - {/* </ScrollArea> */} + <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> </> ); -} +} \ No newline at end of file diff --git a/apps/wr/app/stats/rswtStat/page.tsx b/apps/wr/app/stats/rswtStat/page.tsx index 7514f98b1..ce9a9c0f0 100644 --- a/apps/wr/app/stats/rswtStat/page.tsx +++ b/apps/wr/app/stats/rswtStat/page.tsx @@ -1,75 +1,278 @@ -'use client' +"use client"; import { useWrStore } from "@/app/store"; -import { yearOptions } from "@/components/lib/func/commom"; -import { ContentsDiv, SearchDiv, SearchFormLeft, SelectBox, Title, UiTable } from "@common/business_components/ui"; +import type { RswtStatProps } from "@/app/store/stats/rswtStat"; +import { excelDownload, tableData, yearOptions } from "@/components/lib/func/commom"; +import { + ContentsDiv, + downloadExcel, + 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 { useState } from "react"; +import { useEffect, useState } from "react"; export default function RswtStat() { - const { code, rswtStat } = useWrStore((state) => { - return state; - }); - const [pageNation, setPageNation] = useState(1); + const { code, rswtStat, searchRswtStatList } = useWrStore((state) => state); + const { rswtStatList, excelList, rswtDetailList } = rswtStat; + const [rswtTable, setRswtTable] = useState<RswtStatProps[]>(); const [searchYear, setSearchYear] = useState<string>( String(new Date().getFullYear()) ); + const [excelData, setExceData] = useState<Record<string, string | number>[]>(); - return( - <> - <ContentsDiv> - <div className="grid grid-cols-4 gap-4"> - <div className="col-span-4"> - <Title title={"재이용 통계"} /> - <SearchDiv> - <SearchFormLeft> + useEffect(() => { + searchRswtStatList(searchYear) + }, [searchRswtStatList, searchYear]) + + const excelClick = () => { + downloadExcel({ + data: (excelData as unknown as JSON[]) ?? [], + fileName: "중수도재이용통계", + sheetNameArray: ["Sheet1"], + headerRange: "A1:O1" + }) + } + + useEffect(() => { + const transData = Array.isArray(rswtStatList) ? rswtStatList : [rswtStatList]; + const data = tableData(transData, { code }); + const tbData = Array.isArray(data) + ? data.map((item: RswtStatProps) => { + return { + ...item, + ctpvCd: item.ctpvCd + }; + }) + : []; + setRswtTable(tbData); + }, [code, rswtStatList]) + + useEffect(() => { + const transExcel = Array.isArray(excelList) ? excelList : [excelList]; + const exData = tableData(transExcel, { code }); + const tbData = Array.isArray(exData) ? + exData.map((item: RswtStatProps) => { + return { + "시도": item.ctpvCd, + "개소": item.ctpvCnt, + "건축연면적(m³)": item.archArea, + "처리용량(m³)": item.filtrTrtmfctCpct, + "물사용량(m³/년)": item.wtrUsqty, + "중수도+대체수이용량(m³/년)": item.rswtAltSum, + "중수도이용량(m³/년)": item.rswtrUsqty, + "대체수이용량(m³/년)": item.altUswtrUtztnQnt, + "조경용수": item.lndwtr, + "청소화장실용수": item.cleanToilUswtr, + "농업용수": item.farmUswtr, + "공업용수": item.indstUswtr, + "친수용수": item.hydUswtr, + "기타": item.ithlEtcUswtr, + "연간운영비(백만원/년)": item.anlOperCst, + }; + }) : []; + setExceData(tbData); + }, [code, excelList]) + + const excelDetailDownLoad=() =>{ + const sidoList = new Set<string>(); + const sidoDataMap = new Map<string, (string | number)[]>(); // 시도별 데이터를 저장할 Map + const sidoDetailMap = new Map<string, (string | number)[][]>(); // 시도별 상세 데이터를 저장할 Map + + // 먼저 시도별 상세 데이터를 그룹화 + rswtDetailList.forEach((item: RswtStatProps[]) => { + 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 RswtStatProps; + } + if (item.length > 1) { + item[1] = sigunText as unknown as RswtStatProps; + } + if (item.length > 2) { + item[2] = sidoText+' '+sigunText as unknown as RswtStatProps; + } + + // 시도별 상세 데이터 수집 + 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); + } + }); + + // 시도별 합계 계산 + rswtDetailList.forEach((item: RswtStatProps[]) => { + 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 = rswtDetailList.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 = rswtDetailList.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==9){ + const value = Number(item[9]) || 0; + sidoData[i] = (Number(sidoData[i]) + value) as string | number; + } else if(i==10){ + const value = Number(item[10]) || 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==13){ + const value = Number(item[13]) || 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 if(i==16){ + const value = Number(item[16]) || 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()); + // sidoSummaryList와 rainDetailList를 합쳐서 엑셀 데이터 생성 + const excelData = [...sidoSummaryList, ...summaryExcelData]; + + excelDownload( + excelData as unknown as [][], + "중수도시설 통계", + "sample_rswtStats.xlsx", + "A1:Q3", + 4 + ); + } + + return (<> + <ContentsDiv> + <div className="grid grid-cols-4 gap-4"> + <div className="col-span-4"> + <Title title="중수도시설 통계" /> + <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={""} + selectClass="" selectArray={yearOptions} value={searchYear} - onSelectValue={(val: string | number) => - setSearchYear(String(val)) - } + onSelectValue={(val: string | number) => setSearchYear(String(val))} /> - <div className="flex flex-row space-x-2 items-center"> - <Button className="" size={"sm"} onClick={(e) => {}}> - 조회 - </Button> - <Button className="" size={"sm"} onClick={(e) => {}}> - 다운로드 - </Button> - <Button className="" size={"sm"} onClick={(e) => {}}> - 전체통계다운로드 - </Button> - </div> - </SearchFormLeft> - {/* <SearchFormRight> - - </SearchFormRight> */} - </SearchDiv> - </div> + </div> + <div className="flex flex-row space-x-2 items-center"> + <Button + className="" + size="sm" + onClick={() => { + searchRswtStatList(searchYear) + }} + > + 조회 + </Button> + <Button + className="" + size="sm" + onClick={() => excelClick()} + > + 다운로드 + </Button> + <Button + className="" + size="sm" + onClick={() => { excelDetailDownLoad() }} + > + 전체통계다운로드 + </Button> + </div> + </div> + </SearchDiv> </div> - <div className="grid grid-cols-6 gap-4"> - <div className="col-span-6 h-full min-h-0"> - <ListDiv className="min-h-0"> - {/* <ScrollArea className="h-[60vh]"> */} + </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={[]} + tableData={rswtTable || []} headlist={rswtStat.rswtStatHeadList} - pageSize={20} - total={10000} - headName={"건축물 목록"} - cellClick={(val, headId) => {}} - onPageChange={setPageNation} - ></UiTable> - {/* </ScrollArea> */} - </ListDiv> - </div> + pageSize={10} + total={0} + headName="" + cellClick={undefined} + onPageChange={() => { }} + /> + </ScrollArea> + </ListDiv> </div> - </ContentsDiv> - </> - ) - -} \ No newline at end of file + </div> + </ContentsDiv> + </> + ); +} diff --git a/apps/wr/app/store/matDmd/ldrmntCoSttn/excel.tsx b/apps/wr/app/store/matDmd/ldrmntCoSttn/excel.tsx index 5c0936357..dc0601127 100644 --- a/apps/wr/app/store/matDmd/ldrmntCoSttn/excel.tsx +++ b/apps/wr/app/store/matDmd/ldrmntCoSttn/excel.tsx @@ -46,16 +46,30 @@ export const names: nameMap = { } -export const excelToLdrmntData = (excelData: File[],) => { +export const excelPbnstSttnParsing = (data: any[]): string[][] => { - const ldrmntData = Object.values(excelData); - const data = ldrmntData.map((item) => { + const excelExportData: string[][] = []; - return ({ - ...(item as object), - rgtr: TEST_UUID, - mdfr: TEST_UUID, - }) + data.forEach((item) => { + excelExportData.push([ + item.rvbsn, + String(item.lgbsn), + item.mdmbsn ?? "", + item.rgnNm ?? "", + String(item.sido ?? ""), + String(item.gugun ?? ""), + String(item.bscFctNm ?? ""), + String(item.efflWqltStndrdNm ?? ""), + String(item.fctCpc ?? ""), + String(item.tel ?? ""), + String(item.ruseUtztnFcltNm ?? ""), + String(item.fcltCpct ?? ""), + String(item.splyExtraCpct ?? ""), + String(item.ruseCpct ?? ""), + String(item.usageTotal ?? ""), + String(item.inUsage ?? ""), + String(item.outUsage ?? ""), + ]) }) - return data; + return excelExportData; }; \ No newline at end of file diff --git a/apps/wr/app/store/matDmd/ldrmntCoSttn/headList.tsx b/apps/wr/app/store/matDmd/ldrmntCoSttn/headList.tsx index d9159e1b5..7a1695039 100644 --- a/apps/wr/app/store/matDmd/ldrmntCoSttn/headList.tsx +++ b/apps/wr/app/store/matDmd/ldrmntCoSttn/headList.tsx @@ -1,10 +1,12 @@ import { z } from "zod"; import type { CommonTableProps } from "../../common/type/header"; +import { TEST_UUID } from "../../ruseFcltMng/fcltReg/rainReg"; export const ldrmntZod = z.object({ + fctryMngSn: z.string().default(''), ctpvCd: z.string().default(''), sggCd: z.string().default(''), - mngInst: z.string().default('').nullish(), + mngInstNm: z.string().default('').nullish(), dmdCoNm: z.string().default(''), fctrySe: z.string().default(''), cmpxNm: z.string().default(''), @@ -40,6 +42,7 @@ export const ldrmntZod = z.object({ fctryAddr: z.string().default(''), fctryLotnoAddr: z.string().default(''), fctryMngNo: z.string().default(''), + rgtr:z.string().default(TEST_UUID).nullish() }) export const ldrmntHeadListExport: CommonTableProps[] = [ @@ -111,7 +114,7 @@ export const ldrmntNodeListExport: CommonTableProps[] = [ colSpan: 1, }, { - id: "mngInst", + id: "mngInstNm", title: "관리기관", visible: true, row: 1, diff --git a/apps/wr/app/store/matDmd/ldrmntCoSttn/index.tsx b/apps/wr/app/store/matDmd/ldrmntCoSttn/index.tsx index 958668b10..f5005654d 100644 --- a/apps/wr/app/store/matDmd/ldrmntCoSttn/index.tsx +++ b/apps/wr/app/store/matDmd/ldrmntCoSttn/index.tsx @@ -1,8 +1,9 @@ import type { CommonTableProps } from "@/app/store/common/type/header"; -import { fetchType, getFetch, postFectch, putFectch } from "@/components/lib/api"; +import { deleteFectch, fetchType, getFetch, postFectch, putFectch } from "@/components/lib/api"; import { ToastFormUi } from "@/components/ui/toast/toastFromUi"; import { z } from "zod"; import { ldrmntHeadListExport, ldrmntNodeListExport, ldrmntZod } from "./headList"; +import { TEST_UUID } from "../../ruseFcltMng/fcltReg/rainReg"; @@ -10,9 +11,9 @@ import { ldrmntHeadListExport, ldrmntNodeListExport, ldrmntZod } from "./headLis const ldrmntHeadList = ldrmntHeadListExport; const ldrmntNodeList = ldrmntNodeListExport; -export type customLdrmntBdst = z.infer<typeof ldrmntZod>; +export type customLdrmnt = z.infer<typeof ldrmntZod>; -const ldrmntRes: customLdrmntBdst[] = []; +const ldrmntRes: customLdrmnt[] = []; export type ldrmntState = { ldrmnt: { @@ -20,14 +21,16 @@ export type ldrmntState = { ldrmntNodeList: CommonTableProps[]; excelList: []; isInit: boolean; - ldrmntRes: customLdrmntBdst[]; + ldrmntRes: customLdrmnt[]; }; }; type ldrmntActions = { ldrmntRegData: (data: any[]) => void, - ldrmntInit: () => void; + ldrmntInit: (con: string) => void ldrmntSearch: (sggCd: string, coNm: string) => void; + ldrmntUpdate: (ldrmntRes: customLdrmnt) => void; + ldrmntDelete: () => void; }; export type ldrmntType = ldrmntState & ldrmntActions; @@ -46,20 +49,24 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = ( set: any ) => { return { - ldrmntInit: async () => { + ldrmntInit: async (con: string) => { try { + console.log("con", con) const ldrmntRes = await getFetch( fetchType.WR, - `/reuseFc/request/temp/1/20/0` + `/reuseFc/request/temp/1/20/${con}` ); - return set((state: ldrmntState) => ({ - ...state, - rain: { - ...state.ldrmnt, - ldrmntRes: ldrmntRes, - isInit: false, - }, - })); + console.log("initres", ldrmntRes) + set((state: ldrmntState) => { + return { + ...state, + ldrmnt: { + ...state.ldrmnt, + ldrmntRes: ldrmntRes, + isInit: false, + }, + } + }); } catch (e) { console.log(e) } @@ -124,17 +131,36 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = ( console.log(e) } }, - ldrmntUpdate: async (ldrmntRes: customLdrmntBdst[]) => { + ldrmntUpdate: async (ldrmntRes: customLdrmnt) => { try { - + ldrmntRes.rgtr = TEST_UUID; + console.log("ldrmntRes", ldrmntRes); const response = await putFectch( `/reuseFc/request/temp`, ldrmntRes ); + return set((state: ldrmntState) => ({ + ...state, + ldrmnt: { + ...state.ldrmnt, + ldrmntRes: ldrmntRes, + }, + })); + } catch (error) { console.error("Error ldrmntUpdate:", error); } }, + ldrmntDelete: async () => { + try { + const response = await deleteFectch( + `/reuseFc/request/temp`, + ); + + } catch (error) { + console.error("Error ldrmntDelete:", error); + } + }, } } \ No newline at end of file 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..db2099d9a --- /dev/null +++ b/apps/wr/app/store/stats/rainStat/excel.tsx @@ -0,0 +1,41 @@ +import type { RainStatProps } from "."; + +export const excelRainStat = (excelList:RainStatProps[]) : (string | number)[][] => { + const excelData: (string | number)[][] = []; + excelList.forEach((item) => { + excelData.push([ + //시도 + item.ctpvCd ?? "", + //시군구 + item.sggCd ?? "", + //행정구역명 + String(item.areaNm) ?? "", + //시설명 + String(item.bdstNm) ?? "", + //건축물용도코드 (값 없음) + //String(item.bdstUsgCd) ?? "", + "", + //주소 + String(item.daddr) ?? "", + //법적의무대상여부 + String(item.lawTrgtYn)==="Y" ? "대상" : "미대상", + //설치완료일자 + String(item.instlCmptnDt).substring(0, 10) ?? "", + //설치비용 + item.instlCst ?? "", + //접수면종류 + String(item.pntfColKnd) ?? "", + //여과등처리시설유무 + String(item.filtrTrtmfctYn) ?? "", + //처리용량(저류조용량) + item.dtfcltCpct ?? "", + //연간사용량 + item.wtrUsqty ?? "", + //이용용도코드 + item.utztnUsgCd ?? "", + //연간운영비 + item.anlOperCst ?? "", + ]); + }); + return excelData; +} \ No newline at end of file diff --git a/apps/wr/app/store/stats/rainStat/headList.tsx b/apps/wr/app/store/stats/rainStat/headList.tsx index cc5386589..664e060c4 100644 --- a/apps/wr/app/store/stats/rainStat/headList.tsx +++ b/apps/wr/app/store/stats/rainStat/headList.tsx @@ -2,34 +2,110 @@ import type { TableUpperProps } from "../../common/type/header"; export const rainStatHeadListExport: TableUpperProps[] = [ { - id: "시도", + id: "ctpvCd", title: "시도", row:0, rowSpan:2 }, { - id: "개소", + id: "tmp", title: "개소", row:0, rowSpan:2 }, { - id: "설치비", + id: "instlCst", title: "설치비(백만원)", row:0, rowSpan:2 }, { - id: "저류조용량", + id: "dtfcltCpct", title: "저류조용량(m³/년)", row:0, rowSpan:2 }, + { + id: "wtrUsqty", + title: "연간사용량(㎥/년)", + row:0, + rowSpan:2 + }, + { + id: "a", + title: "이용용도", + row:0, + colSpan:7 + }, + { + id: "lndwtr", + title: "조경용수", + row:1, + }, + { + id: "cleanToilUswtr", + title: "청소화장실용수", + row:1, + }, + { + id:"resn", + title:"세척살수용수", + row:1, + }, + { + id: "farmUswtr", + title: "농업용수", + row:1, + }, + { + id: "indstUswtr", + title: "공업용수", + row:1, + }, + { + id: "hydUswtr", + title: "친수용수", + row:1, + }, + { + id: "ithlEtcUswtr", + title: "기타", + row:1, + }, + { + id: "anlOperCst", + title: "연간운영비(백만원/년)", + row:0, + rowSpan:2 + }, +]; + +export const rainStatDetailHeadListExport: TableUpperProps[] = [ + { + id: "ctpvCd", + title: "시도", + row:0, + }, + { + id: "sggCd", + title: "시군구", + row:0, + }, + { + id: "areaNm", + title: "행정구역명", + row:0, + }, + { + id: "", + title: "시설명", + row:0, + }, { id: "이용용도", title: "이용용도", row:0, - colSpan:6 + colSpan:7 }, { id: "조경용수", @@ -41,6 +117,11 @@ export const rainStatHeadListExport: TableUpperProps[] = [ title: "청소화장실용수", row:1, }, + { + id:"세척살수용수", + title:"세척살수용수", + row:1, + }, { id: "농업용수", title: "농업용수", @@ -67,4 +148,4 @@ export const rainStatHeadListExport: TableUpperProps[] = [ row:0, rowSpan:2 }, -]; +]; \ 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 a50d54d58..d6e48a53e 100644 --- a/apps/wr/app/store/stats/rainStat/index.tsx +++ b/apps/wr/app/store/stats/rainStat/index.tsx @@ -1,13 +1,66 @@ +import { fetchType, getFetch } from "@/components/lib/api"; import type { TableUpperProps } from "../../common/type/header"; +import { excelRainStat } from "./excel"; import { rainStatHeadListExport } from "./headList"; -type rainStatActions = { +export type RainStatProps = { + ctpvCd: string //시도 + sggCd: string //시군구 + areaNm: string //행정구역명 + bdstNm: string //시설명 + bdstUsgCd: string //건축물용도코드 + daddr: string //주소 + lawTrgtYn: string //법적의무대상여부 + instlCmptnDt: string //설치완료일자 + instlCst: number //설치비용 + pntfColKnd: string //접수면종류 + filtrTrtmfctYn: string //여과등처리시설유무 + archArea: number //건축연면적 + dtfcltCpct: number //처리용량(저류조용량) + wtrUsqty: number //연간사용량 + utztnUsgCd: string //이용용도코드 + anlOperCst: number //연간운영비 + annRnwtQty: number //물사용량 + jungsudo: number //중수도​이용량 + dachae: number //대체수​이용량 + lndwtr: number //조경용수 + cleanToilUswtr: number //청소화장실용수 + resn: number //세척살수용수 + farmUswtr: number //농업용수 + indstUswtr: number //공업용수 + hydUswtr: number //친수용수 + ithlEtcUswtr: number //기타 + tmp: number //개소 + guideStats: GuideStatProps[] } +export type GuideStatProps = { + utztnUsgCd: string + splyUswtrUtztnQnt : number, + ruseFcltUtztnQnt: number +} + +type ExcelType = { + [key: string]: string | number | undefined; +}; + +const excelDownList: ExcelType[] = []; + +const fetchRainStatList = async (year: string) => { + const res = await getFetch(fetchType.WR, `/reuseChk/rainy/stat/${year}`) + return res; +} + +type rainStatActions = { + searchRainStatList: (year: string) => void +} export type rainStatState = { rainStat: { - rainStatHeadList:TableUpperProps[] + rainStatHeadList: TableUpperProps[], + rainStatList: RainStatProps[], + excelList: ExcelType[] + rainDetailList : [][] } } @@ -15,14 +68,117 @@ export type rainStatType = rainStatState & rainStatActions; export const rainStatExport: rainStatState = { rainStat: { - rainStatHeadList:rainStatHeadListExport + rainStatHeadList: rainStatHeadListExport, + rainStatList: [], + excelList: [], + rainDetailList : [] } } - -export const rainStatActionsExport: (set: any) => rainStatActions = ( - set: any +export const rainStatActionsExport = ( + set: (fn: (state: rainStatState) => rainStatState) => void ) => { return { - + searchRainStatList: async (year: string) => { + const res = await fetchRainStatList(year); + const cityArr: any[] = []; + res.forEach((item: RainStatProps) => { + + let obj = cityArr.find((e) => { + return e.ctpvCd == item.ctpvCd + }) + + if (obj) { + obj.instlCst += item.instlCst + obj.dtfcltCpct += item.dtfcltCpct + obj.wtrUsqty += item.wtrUsqty + obj.anlOperCst += item.anlOperCst + obj.tmp += 1 + } else { + obj = {}; + obj.ctpvCd = item.ctpvCd + obj.instlCst = item.instlCst + obj.tmp = 1 + obj.dtfcltCpct = item.dtfcltCpct + obj.wtrUsqty = item.wtrUsqty + obj.anlOperCst = item.anlOperCst + + cityArr.push(obj) + } + + if (item.guideStats && item.guideStats.length > 0) { + item.guideStats.forEach((guide: GuideStatProps) => { + rainStatHeadListExport.forEach((headItem: TableUpperProps) => { + + if (headItem.title == guide.utztnUsgCd) { + if (!obj[headItem.id] || typeof obj[headItem.id] !== "number") obj[headItem.id] = 0; + if (typeof obj[headItem.id] === "number") { + + obj[headItem.id] += guide.ruseFcltUtztnQnt; + } + } + }); + }) + } + }) + + cityArr.forEach(item => { + excelDownList.push({ + ctpvCd: item.ctpvCd, + tmp: item.tmp, + instlCst: item.instlCst, //설치비 + dtfcltCpct: item.dtfcltCpct, //저류조용량 + bdstUsgCd: item.bdstUsgCd, //연간사용량 + lndwtr: item.lndwtr, //조경용수 + cleanToilUswtr: item.cleanToilUswtr, //청소화장실용수 + resn: item.resn, //세척살수용수 + farmUswtr: item.farmUswtr, //농업용수 + indstUswtr: item.indstUswtr, //공업용수 + hydUswtr: item.hydUswtr, //친수용수 + ithlEtcUswtr: item.ithlEtcUswtr, //기타 + anlOperCst: item.anlOperCst, //연간운영비 + }) + }) + + //상세 + const rainDetailList : RainStatProps[] = []; + res.forEach((item:RainStatProps) => { + const utztnUsgArray = new Array<string>(); + 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 + } + })); + } } -} \ No newline at end of file +} diff --git a/apps/wr/app/store/stats/rswtStat/excel.tsx b/apps/wr/app/store/stats/rswtStat/excel.tsx new file mode 100644 index 000000000..35f567253 --- /dev/null +++ b/apps/wr/app/store/stats/rswtStat/excel.tsx @@ -0,0 +1,46 @@ +import type { RswtStatProps } from "."; + +export const excelRswtStat = (excelList:RswtStatProps[]) : (string | number)[][] => { + const excelData: (string | number)[][] = []; + 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)==="Y" ? "대상" : "미대상", + //설치완료일자 + item.instlCmptnDt ? String(item.instlCmptnDt).substring(0, 10) : "", + //가동개시일(빈칸) + //String(item.instlCst) ?? "", + "", + //건축물면적 + item.archArea ?? "", + //처리용량 + item.filtrTrtmfctCpct ?? "", + //물사용량 + item.wtrUsqty ?? "", + //중수도+대체수이용량 + item.rswtAltSum ?? "", + //중수도이용량 + item.rswtrUsqty ?? "", + //대체수이용량 + item.altUswtrUtztnQnt ?? "", + //중수도용도 + String(item.utztnUsgCd) ?? "", + //연간운영비 + item.anlOperCst ?? "", + ]); + }); + return excelData; +} \ No newline at end of file diff --git a/apps/wr/app/store/stats/rswtStat/headList.tsx b/apps/wr/app/store/stats/rswtStat/headList.tsx index 2c8aebec9..877089092 100644 --- a/apps/wr/app/store/stats/rswtStat/headList.tsx +++ b/apps/wr/app/store/stats/rswtStat/headList.tsx @@ -2,96 +2,96 @@ import type { TableUpperProps } from "../../common/type/header"; export const rswtStatHeadListExport :TableUpperProps[]=[ { - id: "시도", + id: "ctpvCd", title: "시도", row:0, rowSpan:2 }, { - id: "개소", + id: "ctpvCnt", title: "개소", row:0, rowSpan:2 }, { - id: "시설현황", + id: "a", title: "시설현황", row:0, colSpan:2 }, { - id: "건축연면적(m³)", + id: "archArea", title: "건축연면적(m³)", row:1, }, { - id: "처리용량", + id: "filtrTrtmfctCpct", title: "처리용량(m³)", row:1, }, { - id: "물사용량", + id: "wtrUsqty", title: "물사용량(m³/년)", row:0, rowSpan:2 }, { - id: "청소화장실용수", + id: "rswtAltSum", title: "중수도+대체수이용량(m³/년)", row:0, rowSpan:2 }, { - id: "중수도이용량", + id: "rswtrUsqty", title: "중수도이용량(m³/년)", row:0, rowSpan:2 }, { - id: "대체수이용량", + id: "altUswtrUtztnQnt", title: "대체수이용량(m³/년)", row:0, rowSpan:2 }, { - id: "용도", + id: "b", title: "용도", row:0, colSpan:6 }, { - id: "조경용수", + id: "lndwtr", title: "조경용수", row:1, }, { - id: "청소화장실용수", + id: "cleanToilUswtr", title: "청소화장실용수", row:1, }, { - id: "농업용수", + id: "farmUswtr", title: "농업용수", row:1, }, { - id: "공업용수", + id: "indstUswtr", title: "공업용수", row:1, }, { - id: "친수용수", + id: "hydUswtr", title: "친수용수", row:1, }, { - id: "기타", + id: "ithlEtcUswtr", title: "기타", row:1, }, { - id: "연간운영비", + id: "anlOperCst", title: "연간운영비(백만원/년)", row:0, rowSpan:2 diff --git a/apps/wr/app/store/stats/rswtStat/index.tsx b/apps/wr/app/store/stats/rswtStat/index.tsx index 652917bc3..4e2a7ecc8 100644 --- a/apps/wr/app/store/stats/rswtStat/index.tsx +++ b/apps/wr/app/store/stats/rswtStat/index.tsx @@ -1,13 +1,57 @@ +import { fetchType, getFetch } from "@/components/lib/api"; import type { TableUpperProps } from "../../common/type/header"; import { rswtStatHeadListExport } from "./headList"; +import { excelRswtStat } from "./excel"; + +export type RswtStatProps = { + ctpvCd: string //시도 + sggCd : string //시군구 + areaNm: string //행정구역명 + bdstNm: string //시설명 + daddr: string //주소 + ctpvCnt: string //개소 + archArea: number //건축연면적 + filtrTrtmfctCpct: number //처리용량 + wtrUsqty: number //물사용량 + rswtAltSum: number //중수도+대체수이용량 + rswtrUsqty: number //중수도이용량 + altUswtrUtztnQnt: number //대체수이용량 + lndwtr: number //조경용수 + cleanToilUswtr: number //청소화장실용수 + resn: number //세척살수용수 + farmUswtr: number //농업용수 + indstUswtr: number //공업용수 + hydUswtr: number //친수용수 + ithlEtcUswtr: number //기타 + anlOperCst: number //연간운영비 + guideStats: GuideStatProps[] + utztnUsgCd : string //이용코드 + lawTrgtYn : string //법적의무대상여부 + instlCmptnDt : string //설치완료일자 +} + +export type GuideStatProps = { + utztnUsgCd: string + ruseFcltUtztnQnt: number +} type rswtStatActions = { + searchRswtStatList: (year: string) => void; } +export type ExcelType = { + [key: string]: string | number | undefined; +}; + +const excelDownList: ExcelType[] = []; + export type rswtStatState = { rswtStat: { - rswtStatHeadList:TableUpperProps[] + rswtStatHeadList: TableUpperProps[]; + rswtStatList: RswtStatProps[]; + excelList: ExcelType[]; + rswtDetailList: RswtStatProps[][]; } } @@ -15,7 +59,10 @@ export type rswtStatType = rswtStatState & rswtStatActions; export const rswtStatExport: rswtStatState = { rswtStat: { - rswtStatHeadList:rswtStatHeadListExport + rswtStatHeadList: rswtStatHeadListExport, + rswtStatList: [], + excelList: [], + rswtDetailList: [] } } @@ -23,6 +70,99 @@ export const rswtStatActionsExport: (set: any) => rswtStatActions = ( set: any ) => { return { - + searchRswtStatList: async (year: string) => { + const res = await getFetch(fetchType.WR, `/reuseChk/reuseWater/stat/${year}`) + const rswtStatList: RswtStatProps[] = []; + + const cityArr: any[] = []; + res.forEach((item: RswtStatProps) => { + let obj = cityArr.find((e) => { + return e.ctpvCd == item.ctpvCd + }) + + if (obj) { + obj.ctpvCnt += 1 + obj.archArea += item.archArea + obj.filtrTrtmfctCpct += item.filtrTrtmfctCpct + obj.wtrUsqty += item.wtrUsqty + obj.rswtAltSum += (item.rswtrUsqty + item.altUswtrUtztnQnt) + obj.rswtrUsqty += item.rswtrUsqty + obj.altUswtrUtztnQnt += item.altUswtrUtztnQnt + obj.anlOperCst += item.anlOperCst + } else { + obj = {}; + obj.ctpvCd = item.ctpvCd + obj.ctpvCnt = 1 + obj.archArea = item.archArea + obj.filtrTrtmfctCpct = item.filtrTrtmfctCpct + obj.wtrUsqty = item.wtrUsqty + obj.rswtAltSum = item.rswtrUsqty + item.altUswtrUtztnQnt + obj.rswtrUsqty = item.rswtrUsqty + obj.altUswtrUtztnQnt = item.altUswtrUtztnQnt + obj.anlOperCst = item.anlOperCst + + cityArr.push(obj) + } + + if (item.guideStats && item.guideStats.length > 0) { + item.guideStats.forEach((guide: GuideStatProps) => { + rswtStatHeadListExport.forEach((headItem: TableUpperProps) => { + + if (headItem.title == guide.utztnUsgCd) { + if (!obj[headItem.id] || typeof obj[headItem.id] !== "number") obj[headItem.id] = 0; + if (typeof obj[headItem.id] === "number") { + + obj[headItem.id] += guide.ruseFcltUtztnQnt; + } + } + }); + }) + } + }); + + cityArr.forEach(item => { + excelDownList.push({ + ctpvCd: item.ctpvCd, + ctpvCnt: item.ctpvCnt, + archArea: item.archArea, + filtrTrtmfctCpct: item.filtrTrtmfctCpct, + wtrUsqty: item.wtrUsqty, + rswtAltSum: item.rswtAltSum, + rswtrUsqty: item.rswtrUsqty, + altUswtrUtztnQnt: item.altUswtrUtztnQnt, + lndwtr: item.lndwtr, + cleanToilUswtr: item.cleanToilUswtr, + farmUswtr: item.farmUswtr, + indstUswtr: item.indstUswtr, + hydUswtr: item.hydUswtr, + ithlEtcUswtr: item.ithlEtcUswtr, + anlOperCst: item.anlOperCst, + }) + }) + + //상세 + const rswtDetailList : RswtStatProps[] = []; + res.forEach((item:RswtStatProps) => { + const utztnUsgArray = new Array<string>(); + item.guideStats.forEach((guideStat) => { + utztnUsgArray.push(guideStat.utztnUsgCd); + }) + rswtDetailList.push({ + ...item, + rswtAltSum : item.rswtrUsqty + item.altUswtrUtztnQnt, + utztnUsgCd : utztnUsgArray.join(', '), + }) + }); + + const excelDetailData = excelRswtStat(rswtDetailList); + set((state: rswtStatState) => ({ + rswtStat: { + ...state.rswtStat, + rswtStatList: cityArr, + excelList: excelDownList, + rswtDetailList: excelDetailData + } + })); + } } } \ No newline at end of file diff --git a/apps/wr/components/ui/modal/coReg/coRegExcel/coRegExcelModal.tsx b/apps/wr/components/ui/modal/coReg/coRegExcel/coRegExcelModal.tsx index ffd255579..1fa8fa8f3 100644 --- a/apps/wr/components/ui/modal/coReg/coRegExcel/coRegExcelModal.tsx +++ b/apps/wr/components/ui/modal/coReg/coRegExcel/coRegExcelModal.tsx @@ -1,6 +1,6 @@ import { useWrStore } from "@/app/store"; import { coRegExcel } from "@/app/store/matDmd/coSttn/headList"; -import type { customLdrmntBdst } from "@/app/store/matDmd/ldrmntCoSttn"; +import type { customLdrmnt } from "@/app/store/matDmd/ldrmntCoSttn"; import { excelToLdrmntData, names } from "@/app/store/matDmd/ldrmntCoSttn/excel"; import { filePicked, FileUpload, FormUi, Title } from "@common/business_components/ui"; import { Form, FormField } from "@common/business_components/ui/form"; @@ -16,13 +16,14 @@ export default function CoRegExcel() { const form = useForm<z.infer<typeof coRegExcel>>({ resolver: zodResolver(coRegExcel), }); - const { ldrmntRegData } = useWrStore((state) => state); - const [excelData, setExcelData] = useState<customLdrmntBdst[]>(); + const { ldrmntRegData, ldrmntDelete } = useWrStore((state) => state); + const [excelData, setExcelData] = useState<customLdrmnt[]>(); const [file, setFiles] = useState<File | undefined>(); const onSubmit = (values: z.infer<typeof coRegExcel>) => { + ldrmntDelete(); if (file) { filePicked(file, 0).then((res) => { try { @@ -50,7 +51,7 @@ export default function CoRegExcel() { } }) ldrmntRegData(array); - console.log("array22", array) + console.log("array끝", array) } catch (e) { console.log(e) } diff --git a/apps/wr/components/ui/modal/sttn/sttnDetailModal/coDatailModal.tsx b/apps/wr/components/ui/modal/sttn/sttnDetailModal/coDatailModal.tsx index 708cb4b3c..edffcc71d 100644 --- a/apps/wr/components/ui/modal/sttn/sttnDetailModal/coDatailModal.tsx +++ b/apps/wr/components/ui/modal/sttn/sttnDetailModal/coDatailModal.tsx @@ -1,4 +1,6 @@ "use client"; +import { useWrStore } from "@/app/store"; +import type { customLdrmnt } from "@/app/store/matDmd/ldrmntCoSttn"; import { ldrmntZod } from "@/app/store/matDmd/ldrmntCoSttn/headList"; import { selectClass } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import { handleCommaNumberChange } from "@/components/lib/func/commom"; @@ -14,21 +16,25 @@ export default function SttnDetailModal({ }: { formObj: any; }) { + const { ldrmntUpdate } = useWrStore( + (state) => state + ); const defaultValues: z.infer<typeof ldrmntZod> = ldrmntZod.parse({}); const form = useForm<z.infer<typeof ldrmntZod>>({ resolver: zodResolver(ldrmntZod), defaultValues: defaultValues, }); - const onSubmit = (values: z.infer<typeof ldrmntZod>) => { + const onSubmit = (values: customLdrmnt) => { console.log("values", values) + if (values) + ldrmntUpdate(values) }; useEffect(() => { if (ldrmntZod) form.reset(formObj); }, [formObj]); - return ( <div> <ScrollArea className="h-[85vh]"> @@ -43,6 +49,23 @@ export default function SttnDetailModal({ </Button> </div> + <FormField + control={form.control} + name="fctryMngSn" + render={({ field }) => ( + <FormUi label=""> + <Input + className={selectClass} + placeholder="" + type="hidden" + onChange={(e) => { + }} + value={field.value ?? ""} + /> + </FormUi> + )} + /> + <div className="grid grid-cols-4 gap-2 mt-4"> <div className="col-span-2"> <FormField @@ -66,7 +89,7 @@ export default function SttnDetailModal({ <div className="col-span-2"> <FormField control={form.control} - name="mngInst" + name="mngInstNm" render={({ field }) => ( <FormUi label="관리기관"> <Input @@ -83,7 +106,7 @@ export default function SttnDetailModal({ /> </div> </div> - + <div className="grid grid-cols-4 gap-2 mt-4"> <div className="col-span-2"> <FormField @@ -709,7 +732,7 @@ export default function SttnDetailModal({ <FormField control={form.control} name="fctryMngNo" - render={({ field }) => ( + render={({ field, fieldState }) => ( <FormUi label="공장관리번호"> <Input className={selectClass} 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 diff --git a/apps/wr/public/sample_rswtStats.xlsx b/apps/wr/public/sample_rswtStats.xlsx new file mode 100644 index 000000000..702c4cec0 Binary files /dev/null and b/apps/wr/public/sample_rswtStats.xlsx differ diff --git a/packages/common/business_components/src/ui/map/Gis.js b/packages/common/business_components/src/ui/map/Gis.js index f68d0798a..5b4344b57 100644 --- a/packages/common/business_components/src/ui/map/Gis.js +++ b/packages/common/business_components/src/ui/map/Gis.js @@ -1,20 +1,19 @@ -import './lib/css/gis.common.css'; -import React, { createContext, useContext, useEffect, useMemo, useRef, useState, useCallback } from 'react'; +import { Search } from 'lucide-react'; import OlMap from 'ol/Map'; import View from 'ol/View'; import { defaults as defaultControls, OverviewMap } from 'ol/control'; import { defaults } from 'ol/interaction'; import * as olProj from 'ol/proj'; -import proj4 from 'proj4'; import { register } from 'ol/proj/proj4'; -import GisApp from './lib/gis.core'; -import GisContent from './GisContent'; -import GisTree from './GisTree'; +import proj4 from 'proj4'; +import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; import GisLonLat from './GisLonLat'; +import GisMapToggle from './GisMapToggle'; import GisSelect from './GisSelect'; import GisToolBar from './GisToolBar'; -import GisMapToggle from './GisMapToggle'; -import { Search } from 'lucide-react'; +import GisTree from './GisTree'; +import './lib/css/gis.common.css'; +import GisApp from './lib/gis.core'; export const GisContext = createContext({ gisCore: null, gisMap: null, treeData: null, checkedLayerIds: null }); export const useGisContext = () => useContext(GisContext);