diff --git a/apps/wr/app/matMng/coMat/ruseCaseMng/page.tsx b/apps/wr/app/matMng/coMat/ruseCaseMng/page.tsx index fecbb4ac6..ac68c4a66 100644 --- a/apps/wr/app/matMng/coMat/ruseCaseMng/page.tsx +++ b/apps/wr/app/matMng/coMat/ruseCaseMng/page.tsx @@ -118,7 +118,7 @@ export default function RuseCaseMng() {
- + ({ ...item, - ctpvCd: item.fctryAddr.split(" ")[0] || "", - sggCd: item.fctryAddr.split(" ")[1] || "" + ctpvCd: item.fctryAddr?.split(" ")[0] || "", + sggCd: item.fctryAddr?.split(" ")[1] || "" })) : []; @@ -114,8 +114,8 @@ export default function LdrmntCoSttn() { const data = Array.isArray(exData) ? exData.map((item: customLdrmnt) => { return { - "시도": item.fctryAddr.split(" ")[0] || "", - "시군구": item.fctryAddr.split(" ")[1] || "", + "시도": item.fctryAddr?.split(" ")[0] || "", + "시군구": item.fctryAddr?.split(" ")[1] || "", "회사명": item.dmdCoNm, "공장주소": item.fctryAddr, "공장관리번호": item.fctryMngNo, diff --git a/apps/wr/app/ruseFcltMng/fcltReg/pbnstReg/page.tsx b/apps/wr/app/ruseFcltMng/fcltReg/pbnstReg/page.tsx index 441eabf25..6b45dacc9 100644 --- a/apps/wr/app/ruseFcltMng/fcltReg/pbnstReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltReg/pbnstReg/page.tsx @@ -29,9 +29,9 @@ import { import { PbnstMngForm } from "@/components/ui/form/fcltReg/pbnstReg/mngReg/mngRegForm"; import { PbnstBuseForm } from "@/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm"; import { PbnstRegModal } from "@/components/ui/modal/fcltReg/pbnstRegModal/pbnstRegModal"; -import toast, { Toaster } from "react-hot-toast"; +import toast, { Toaster } from "react-hot-toast"; // toast 이미 import 되어 있음 import { writeRgtrAndMdfr } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg"; -import { useFieldArray, useForm } from "react-hook-form"; +import { useFieldArray, useForm, type FieldErrors } from "react-hook-form"; // FieldErrors 타입 추가 import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; @@ -105,6 +105,56 @@ export default function PublicReuseFaciltyInsert() { await pbnstRuseBizUpdate(bizs); }; + // 폼 유효성 검사 실패 시 호출될 함수 + const onInvalid = (errors: FieldErrors<{ items: z.infer[]; }>) => { + // 재귀 함수를 사용해 중첩된 에러 객체에서 모든 에러 메시지와 경로를 찾습니다. + const findAllErrors = ( + errorObject: any, + path: (string | number)[] = [] + ): { message: string; path: (string | number)[]; }[] => { + if (!errorObject) return []; + + return Object.keys(errorObject).flatMap((key) => { + const value = errorObject[key]; + const currentKey = !isNaN(parseInt(key)) ? parseInt(key) : key; + const newPath = [...path, currentKey]; + if (value && typeof value === "object") { + if (typeof value.message === "string") { + return [{ message: value.message, path: newPath }]; // 에러 메시지와 경로 반환 + } + return findAllErrors(value, newPath); + } + return []; + }); + }; + const errorList = findAllErrors(errors); + if (errorList.length > 0) { + errorList.forEach((errorInfo) => { + const { message, path } = errorInfo; + let prefix = ""; + const itemsIndex = path.indexOf("items"); + + if (itemsIndex > -1 && path.length > itemsIndex + 1) { + const itemIdx = path[itemsIndex + 1] as number; + const facilityName = form.getValues(`items.${itemIdx}.ruseUtztnFcltNm`); + if (facilityName) { + prefix += `[${facilityName}] `; + } + + const fcBizsIndex = path.indexOf("fcBizs"); + if (fcBizsIndex > -1 && path.length > fcBizsIndex + 1) { + const bizIdx = path[fcBizsIndex + 1] as number; + const cycle = form.getValues(`items.${itemIdx}.fcBizs.${bizIdx}.cycl`); + if (cycle) { + prefix += `[${cycle}차수] `; + } + } + } + toast.error(`${prefix}${message}`); + }); + } + }; + useEffect(() => { if (code.sggCd.length) { if (searchFclts) { @@ -250,7 +300,7 @@ useEffect(() =>{
- + {/* 높이 조정 */} { @@ -310,7 +360,7 @@ useEffect(() =>{ } diff --git a/apps/wr/app/ruseFcltMng/fcltReg/rainReg/page.tsx b/apps/wr/app/ruseFcltMng/fcltReg/rainReg/page.tsx index 31743aaa9..2fa8b12b8 100644 --- a/apps/wr/app/ruseFcltMng/fcltReg/rainReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltReg/rainReg/page.tsx @@ -38,8 +38,10 @@ export default function Home() { }>({ isOpen: false, chgBuilding: [] }); useEffect(() => { + setIsNewReg( false) if (!rain.isInit) { initRain('41'); + } }, [rain.isInit, initRain]); @@ -80,7 +82,6 @@ export default function Home() { }; useEffect(() => { - console.log("getPageNation", pageNation); getRainData(pageNation, "41"); }, [pageNation]); diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/pbnstSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/pbnstSttn/page.tsx index 8823abf6d..7a7a125d2 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/pbnstSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/pbnstSttn/page.tsx @@ -16,15 +16,8 @@ import { Button, Label } from "@common/components/ui"; import HeadChModal from "@/components/ui/modal/sttn/headChModal/headChModal"; import { useCallback, useEffect, useRef, useState } from "react"; import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan"; -import type { - customPbnst, - pubHasuType, -} from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type"; -import { - excelDownload, - getCityOrSgg, - yearOptions, -} from "@/components/lib/func/commom"; +import type { customPbnst } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type"; +import { excelDownload, yearOptions } from "@/components/lib/func/commom"; import SearchInputText from "@/components/ui/searchInput/searchInput"; import type { WaterReuseFacility } from "@/app/store/ruseFcltMng/fcltSttn/pbnstSttn/type"; import { PbnstSttnModal } from "@/components/ui/modal/sttn/pbnstSttnModal/pbnstSttnModal"; @@ -43,7 +36,6 @@ export default function PbnstSttn() { const [searchYear, setSearchYear] = useState( String(new Date().getFullYear()) ); - const [pageNation, setPageNation] = useState(1); const [isChHead, setIsChHead] = useState(false); const [bdstTable, setBdstTable] = useState(); const [pbnDetaileData, setPbnDetaileData] = useState<{ @@ -87,14 +79,17 @@ export default function PbnstSttn() { } }, [pbnstSttn.isInit, pbnSttnInit, ref.current]); useEffect(() => { - setBdstTable(pbnstSttn.pbnstSttnRes); }, [pbnstSttn.pbnstSttnRes]); - useEffect(() => { - if (pbnRuseNm.length > 1) - pbnNmSearch("1", "23", ref.current, pbnRuseNm, searchYear); - }, [pbnRuseNm]); + // useEffect(() => { + // pbnstSttnSearch("1", "20", ref.current, pbnRuseNm, searchYear); + // }, [pageNation, ref.current, pbnRuseNm, searchYear, pbnstSttnSearch]); + + // useEffect(() => { + // if (pbnRuseNm.length > 1) + // pbnNmSearch(String(pageNation), "23", ref.current, pbnRuseNm, searchYear); + // }, [pbnRuseNm,pageNation]); useEffect(() => { if (pbnstSttn.pbnstDetail.pbnstRuseFcltPk) @@ -104,15 +99,14 @@ export default function PbnstSttn() { }); }, [pbnstSttn.pbnstDetail]); - - useEffect(() => { - console.log('pbnDetaileData.isModal ', pbnDetaileData.isModal) -},[pbnDetaileData.isModal]) + useEffect(() => { + console.log("pbnDetaileData.isModal ", pbnDetaileData.isModal); + }, [pbnDetaileData.isModal]); return ( <> -
-
+
+
<SearchBaseForm selectSidoData={code.cityCd} @@ -132,41 +126,32 @@ export default function PbnstSttn() { </Button> } leftChildren={ - <> - <div className="flex flex-row space-x-2"> - <SelectBox - className="w-48 h-full text-2xl" - label="연도" - selectClass={""} - selectArray={yearOptions} - value={searchYear} - onSelectValue={(val: string | number) => - setSearchYear(String(val)) - } - /> - </div> - <SearchInputText - label={"하수처리시설"} - initValue={pbnRuseNm ?? ""} - setValue={(searchNm?: string) => { - setPbnRuseNm(searchNm || ""); - }} - setRtnData={function (rtnData: any[]): void { - setBdstTable(rtnData); - }} - searchList={pbnstSttn.pbnstSearchData || []} - ></SearchInputText> - </> + <div className="col-span-3 flex items-center"> + <SelectBox + className="w-48 h-full text-2xl" + label="연도" + selectClass={"w-full "} + selectArray={yearOptions} + value={searchYear} + onSelectValue={(val: string | number) => + setSearchYear(String(val)) + } + /> + <Label className="w-64 mt-2 mx-4 text-xl text-gray-600"> + {"하수처리시설명 "} + </Label> + <SearchInput + className={"text-2xl w-full ㅍ"} + label="" + textValue={pbnRuseNm || ""} + setText={(e) => { + setPbnRuseNm(e || ""); + }} + /> + </div> } queryClick={function (returnType: ReturnType): void { - // '{partValue: 'A', sidoValue: '0', sigunValue: '0', regionValue: '0', unitWaterShedValue: '0', …}' - let con; - if (returnType.sigunValue != "0") { - con = returnType.sigunValue; - } else { - con = returnType.sidoValue; - } - // pbnstSttnSearch(1, "20", con); + pbnstSttnSearch("1", "20", returnType, pbnRuseNm, searchYear); }} excelClick={excelClick} initClick={function (): void {}} @@ -191,7 +176,15 @@ export default function PbnstSttn() { cellClick={(index: number | undefined, headId: string) => { cellCLick(index); }} - onPageChange={setPageNation} + onPageChange={(page: number) => { + pbnstSttnSearch( + String(page), + String(13), + ref.current, + pbnRuseNm, + searchYear + ); + }} ></UiTable> </ListDiv> </div> diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx index 5e807d2e1..fd8e2a6d6 100644 --- a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx @@ -2,7 +2,10 @@ import { useWrStore } from "@/app/store"; import { type rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; -import type { rswtChkZodType, rswtrChkDetailsZodType } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn"; +import type { + rswtChkZodType, + rswtrChkDetailsZodType, +} from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn"; import { excelArrayDownload, excelDownload, @@ -26,6 +29,7 @@ import ListDiv from "@common/business_components/ui/list_div"; import { Button, Label } from "@common/components/ui"; import { useCallback, useEffect, useState } from "react"; import { Toaster } from "react-hot-toast"; +import { shallow } from "zustand/shallow"; //----------------------- export default function Page() { @@ -41,6 +45,7 @@ export default function Page() { isRainSttn, rswtChkgdnInit, + rswtChkPolInit, rswtChkDetilsUpdate, rswtChkDelete, rswtrChkExcelDownload, @@ -52,9 +57,9 @@ export default function Page() { const [updateRainDetail, setUpdateRainDetail] = useState<rainChkZodType[]>( [] ); - const [updateRswtDetail, setUpdateRSwtDetail] = useState<rswtrChkDetailsZodType[]>( - [] - ); + const [updateRswtDetail, setUpdateRSwtDetail] = useState< + rswtrChkDetailsZodType[] + >([]); const [deleteIdx, setDeleteIdx] = useState<number[]>([]); const [selFcltDiv, setSelFcltDiv] = useState("RNB"); @@ -63,15 +68,22 @@ export default function Page() { data: {}, }); const cellClick = () => { - if (searchYear) rainChkInit(searchYear, "0"); + if (searchYear) + if (selFcltDiv === "RNB") { + rainChkInit(searchYear, "0"); + } else { + rswtChkgdnInit(searchYear, "0"); + } }; - const [searchYear, setSearchYear] = useState<string>(String(new Date().getFullYear())); + const [searchYear, setSearchYear] = useState<string>( + String(new Date().getFullYear()) + ); useEffect(() => { if (!rainChkgdn.isInit) { rainChkInit(new Date().getFullYear().toString(), "0"); - isRainSttn(false) + isRainSttn(false); setIsModal({ data: {}, open: false }); setIsRegExcel(false); } @@ -84,13 +96,13 @@ export default function Page() { }, [rainChkgdn.isInit, rainChkInit]); useEffect(() => { - - if (rswtChkgdn.excelList[0]?.data.length > 1) + if (rswtChkgdn.excelList[0] && rswtChkgdn.excelList[0]?.data.length > 1) { excelArrayDownload( "중수도시설 지도점검", "sample_rs_chk.xlsx", rswtChkgdn.excelList ); + } }, [rswtChkgdn.excelList]); useEffect(() => { @@ -98,7 +110,8 @@ export default function Page() { rainChkgdn.excelList, "빗물이용시설 지도점검", "sample_rainy.xlsx", - "A1:AN1" + "A1:AN1", + 2 ); }, [rainChkgdn.excelList]); @@ -118,15 +131,14 @@ export default function Page() { const handleClick = useCallback( (data: any) => { - if (data) setIsModal({ open: !isModal.open, data: data }); }, [isModal] ); useEffect(() => { - rainChkgdn.isSttn = false - rswtChkgdn.isSttn = false + rainChkgdn.isSttn = false; + rswtChkgdn.isSttn = false; if (!rainChkgdn.isSttn && !rswtChkgdn.isSttn) { rainChkHeadChange({ rainChkgdn }, true); rswtChkHeadChange({ rswtChkgdn }, true); @@ -138,20 +150,17 @@ export default function Page() { if (selFcltDiv === "RNB") { rainChkDelete(data); } else { - rswtChkDelete(data) + rswtChkDelete(data); } } }; const chkUpdateTable = (selFcltDiv: string) => { if (selFcltDiv === "RNB") { - - rainChkDetilUpdate(updateRainDetail) + rainChkDetilUpdate(updateRainDetail); } else { - - rswtChkDetilsUpdate(updateRswtDetail) + rswtChkDetilsUpdate(updateRswtDetail); } - - } + }; return ( <ContentsDiv> @@ -161,7 +170,9 @@ export default function Page() { <SearchDiv> <SearchFormLeft> <div className="col-span-2 flex flex-row space-x-2"> - <Label className="w-48 mt-2 text-xl text-gray-600">{'지도점검년도'}</Label> + <Label className="w-48 mt-2 text-xl text-gray-600"> + {"지도점검년도"} + </Label> <SelectBox className="w-full h-full text-2xl" label="" @@ -174,21 +185,24 @@ export default function Page() { /> </div> <div className="col-span-2 flex flex-row space-x-2"> - <Label className="w-28 mt-2 text-xl text-gray-600">{'시설구분'}</Label> + <Label className="w-28 mt-2 text-xl text-gray-600"> + {"시설구분"} + </Label> <SelectBox className={"w-full h-full text-2xl"} label={""} selectClass={""} selectArray={rainChkgdn.fcltDiv} - onSelectValue={(val: string | number) => + onSelectValue={(val: string | number) => { + if (val === "RST") rswtChkPolInit(); setSelFcltDiv(String(val)) } + } value={selFcltDiv ?? rainChkgdn.fcltDiv[0]?.val} /> </div> </SearchFormLeft> - <SearchFormRight - className="w-2/12 mx-5 flex flex-col items-center justify-center space-x-2 "> + <SearchFormRight className="w-2/12 mx-5 flex flex-col items-center justify-center space-x-2 "> <div className="space-y"> <div className="flex flex-row space-x-2"> <Button @@ -210,7 +224,7 @@ export default function Page() { <Button size={"sm"} onClick={() => { - chkUpdateTable(selFcltDiv) + chkUpdateTable(selFcltDiv); }} > 저장 diff --git a/apps/wr/app/ruseFcltMng/prfmncSttn/chkgdnSttn/page.tsx b/apps/wr/app/ruseFcltMng/prfmncSttn/chkgdnSttn/page.tsx index f9a799c24..8960f468d 100644 --- a/apps/wr/app/ruseFcltMng/prfmncSttn/chkgdnSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncSttn/chkgdnSttn/page.tsx @@ -1,14 +1,10 @@ "use client"; import { useWrStore } from "@/app/store"; -import { type rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; -import type { rswtChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn"; import { - excelArrayDownload, excelDownload, - yearOptions, + yearOptions } from "@/components/lib/func/commom"; -import ChkgdExcel from "@/components/ui/modal/chkgd/chkgdExcel/chkgdExcel"; import ChkgdModal from "@/components/ui/modal/chkgd/chkgdModal/chkgdModal"; import RainChkgdTable from "@/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable"; import RswtChkgdTable from "@/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable"; @@ -17,29 +13,27 @@ import { SearchDiv, SearchFormLeft, SearchFormRight, - SearchInput, SelectBox, Title, - UiModal, + UiModal } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button, Label } from "@common/components/ui"; import { useCallback, useEffect, useState } from "react"; import { Toaster } from "react-hot-toast"; -//----------------------- export default function Page() { const { code, rainChkSttn, rswtChkSttn, - - rainChkSttnInit, rainChkSttnSearch, + rswtChkSttnSearch, rswtChkSttnInit, isRainSttn, - isRswtSttn + isRswtSttn, + rswtChkPolInit, } = useWrStore((state) => { return state; }); @@ -51,25 +45,31 @@ export default function Page() { }); const [searchYear, setSearchYear] = useState<string>(String(new Date().getFullYear())); const cellClick = () => { - if (searchYear) rainChkSttnSearch(searchYear, "0"); + if (searchYear) { + if (selFcltDiv === "RNB") { + rainChkSttnSearch(searchYear, "0"); + } else { + rswtChkSttnSearch(searchYear, "0"); + } + } }; useEffect(() => { if (!rainChkSttn.isInit) { isRainSttn(true) - rainChkSttnInit( "0"); + rainChkSttnInit(new Date().getFullYear().toString(), "0"); setIsModal({ data: {}, open: false }); } }, [rainChkSttn.isInit, rainChkSttnInit]); - useEffect(() => { + useEffect(() => { if (!rswtChkSttn.isInit) { setIsModal({ data: {}, open: false }); - rswtChkSttnInit( "0"); + rswtChkSttnInit(new Date().getFullYear().toString(), "0"); isRswtSttn(true) } - },[rswtChkSttn.isInit, rswtChkSttnInit]) + }, [rswtChkSttn.isInit, rswtChkSttnInit]) const handleClick = useCallback( @@ -78,25 +78,25 @@ export default function Page() { }, [isModal] ); -const excelDown=() =>{ - if(rainChkSttn.sttnExcelList && selFcltDiv === "RNB"){ - excelDownload( - rainChkSttn.sttnExcelList, - "빗물이용시설 지도점검 현황", - "sample_rainChkSttn.xlsx", - "A1:Q2", - 3 - ); - }else if(rswtChkSttn.sttnExcelList && selFcltDiv === "RST"){ - excelDownload( - rswtChkSttn.sttnExcelList, - "중수도시설 지도점검 현황", - "sample_rswtChkSttn.xlsx", - "A1:X2", - 3 - ); + const excelDown = () => { + if (rainChkSttn.sttnExcelList && selFcltDiv === "RNB") { + excelDownload( + rainChkSttn.sttnExcelList, + "빗물이용시설 지도점검 현황", + "sample_rainChkSttn.xlsx", + "A1:Q2", + 3 + ); + } else if (rswtChkSttn.sttnExcelList && selFcltDiv === "RST") { + excelDownload( + rswtChkSttn.sttnExcelList, + "중수도시설 지도점검 현황", + "sample_rswtChkSttn.xlsx", + "A1:X2", + 3 + ); + } } -} return ( <ContentsDiv> @@ -125,10 +125,12 @@ const excelDown=() =>{ label={""} selectClass={""} selectArray={rainChkSttn.fcltDiv} - onSelectValue={(val: string | number) => - setSelFcltDiv(String(val)) - } - value={selFcltDiv ?? rainChkSttn.fcltDiv[0]?.val} + onSelectValue={(val: string | number) => { + if (val === "RST") rswtChkPolInit(); + setSelFcltDiv(String(val)) + } + } + value={selFcltDiv ?? rainChkSttn.fcltDiv[0]?.val} /> </div> </SearchFormLeft> @@ -143,7 +145,7 @@ const excelDown=() =>{ > 조회 </Button> - <Button color="green" size={"sm"} onClick={(e) =>{excelDown()}}> + <Button color="green" size={"sm"} onClick={(e) => { excelDown() }}> 다운로드 </Button> </div> @@ -157,15 +159,15 @@ const excelDown=() =>{ <ListDiv> {selFcltDiv === "RNB" ? ( <RainChkgdTable - deleteData={() => {}} - detailUp={() => {}} + deleteData={() => { }} + detailUp={() => { }} handleClick={handleClick} rainChkData={rainChkSttn.rainChkRes} /> ) : ( <RswtChkgdTable - detaiRswtlUpdate={() => {}} - deleteRswtData={() => {}} + detaiRswtlUpdate={() => { }} + deleteRswtData={() => { }} handleRswtClick={handleClick} rswtChkData={rswtChkSttn.rswtChkRes} /> diff --git a/apps/wr/app/ruseFcltMng/prfmncSttn/pbnstPrfmncSttn/page.tsx b/apps/wr/app/ruseFcltMng/prfmncSttn/pbnstPrfmncSttn/page.tsx index 8064aa2bb..a50c08071 100644 --- a/apps/wr/app/ruseFcltMng/prfmncSttn/pbnstPrfmncSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncSttn/pbnstPrfmncSttn/page.tsx @@ -33,6 +33,10 @@ export default function PbnstPrfmncSttn() { const ref = useRef<ReturnType>({} as ReturnType); const [swtrmtFcltNm, setSwtrmtFcltNm] = useState<string>(); const [pbnRuseNm, setPbnRuseNm] = useState<string>(""); + + const [searchYear, setSearchYear] = useState<string>( + String(new Date().getFullYear()) + ); const [excelData, setExcelData] = useState<any[]>([]); const excelClick = useCallback(() => { excelDownload( @@ -43,7 +47,6 @@ export default function PbnstPrfmncSttn() { 2 ); }, [excelData]); - const [chartConfig, setChartConfig] = useState<ChartConfig>({}); const [chartData, setChartData] = useState<dnChartForm[]>([]); const [dnInUsage, setDnInUsage] = useState<dnChartForm[]>([]); @@ -88,6 +91,7 @@ export default function PbnstPrfmncSttn() { const prfFilter = prfList?.filter((e) => e.ym.slice(0, 4) === year) if (prfList && prfFilter.length > 0) { + prfList?.forEach((prfItem) => { const month = Number(prfItem?.ym?.slice(4)); // "MM" const monthKey = `${month}월`; @@ -138,7 +142,8 @@ export default function PbnstPrfmncSttn() { setPrfData([]); } } - + + const [chartId, setChartId] = useState<string>(); useEffect(() => { // 누적 변수 초기화 let wshwtr = 0, @@ -190,69 +195,73 @@ export default function PbnstPrfmncSttn() { const dnOutData: dnChartForm[] = []; if (rawData) { + prfTableData([], year) rawData.forEach((item) => { // 실적 테이블 데이터 - prfTableData(item.prfList, year); + if (chartId){ + if(item.prfList?.[0]?.ym.slice(0, 4) === year && item.prfList?.[0]?.pbnstRuseFcltFk === chartId){ + prfTableData(item.prfList, year); + } + item.prfList.filter((e) => e.ym.slice(0, 4) === year && e.pbnstRuseFcltFk === chartId).forEach((element) => { + // 누적 + wshwtr += element.wshwtr; + coolUswtr += element.coolUswtr; + cleanUswtr += element.cleanUswtr; + drwtUswtr += element.drwtUswtr; + dltnUswtr += element.dltnUswtr; + ithlRswtr += element.ithlRswtr; + ithlEtcUswtr += element.ithlEtcUswtr; + cleanToilUswtr += element.cleanToilUswtr; + resn += element.resn; + lndwtr += element.lndwtr; + hydUswtr += element.hydUswtr; + ugwtChr += element.ugwtChr; + farmUswtr += element.farmUswtr; + rvrKeepUswtr += element.rvrKeepUswtr; + indstUswtr += element.indstUswtr; - item.prfList.filter((e) => e.ym.slice(0, 4) === year).forEach((element) => { - // 누적 - wshwtr += element.wshwtr; - coolUswtr += element.coolUswtr; - cleanUswtr += element.cleanUswtr; - drwtUswtr += element.drwtUswtr; - dltnUswtr += element.dltnUswtr; - ithlRswtr += element.ithlRswtr; - ithlEtcUswtr += element.ithlEtcUswtr; - cleanToilUswtr += element.cleanToilUswtr; - resn += element.resn; - lndwtr += element.lndwtr; - hydUswtr += element.hydUswtr; - ugwtChr += element.ugwtChr; - farmUswtr += element.farmUswtr; - rvrKeepUswtr += element.rvrKeepUswtr; - indstUswtr += element.indstUswtr; + // 월별 합계 + inUsageSum = element.wshwtr + + element.coolUswtr + + element.cleanUswtr + + element.drwtUswtr + + element.dltnUswtr + + element.ithlRswtr + + element.ithlEtcUswtr + + element.cleanToilUswtr + + element.resn; + outUsageSum = element.lndwtr + + element.hydUswtr + + element.ugwtChr + + element.farmUswtr + + element.rvrKeepUswtr + + element.indstUswtr; + inUsageArr.push(inUsageSum); + outUsageArr.push(outUsageSum); - // 월별 합계 - inUsageSum = element.wshwtr - + element.coolUswtr - + element.cleanUswtr - + element.drwtUswtr - + element.dltnUswtr - + element.ithlRswtr - + element.ithlEtcUswtr - + element.cleanToilUswtr - + element.resn; - outUsageSum = element.lndwtr - + element.hydUswtr - + element.ugwtChr - + element.farmUswtr - + element.rvrKeepUswtr - + element.indstUswtr; - inUsageArr.push(inUsageSum); - outUsageArr.push(outUsageSum); + // 막대차트 + const month = Number(element.ym.slice(4, 6)); + barData.push({ label: `${month}월`, "장내용수": inUsageSum, "장외용수": outUsageSum }); - // 막대차트 - const month = Number(element.ym.slice(4, 6)); - barData.push({ label: `${month}월`, "장내용수": inUsageSum, "장외용수": outUsageSum }); + // 라인차트 + wshwtrData.push({ label: `${month}월`, val: element.wshwtr, color: "red" }); + coolUswtrData.push({ label: `${month}월`, val: element.coolUswtr, color: "orange" }); + cleanUswtrData.push({ label: `${month}월`, val: element.cleanUswtr, color: "yellow" }); + drwtUswtrData.push({ label: `${month}월`, val: element.drwtUswtr, color: "pink" }); + dltnUswtrData.push({ label: `${month}월`, val: element.dltnUswtr, color: "purple" }); + ithlRswtrData.push({ label: `${month}월`, val: element.ithlRswtr, color: "green" }); + ithlEtcUswtrData.push({ label: `${month}월`, val: element.ithlEtcUswtr, color: "blue" }); + cleanToilUswtrData.push({ label: `${month}월`, val: element.cleanToilUswtr, color: "magenta" }); + resnData.push({ label: `${month}월`, val: element.resn, color: "skyblue" }); - // 라인차트 - wshwtrData.push({ label: `${month}월`, val: element.wshwtr, color: "red" }); - coolUswtrData.push({ label: `${month}월`, val: element.coolUswtr, color: "orange" }); - cleanUswtrData.push({ label: `${month}월`, val: element.cleanUswtr, color: "yellow" }); - drwtUswtrData.push({ label: `${month}월`, val: element.drwtUswtr, color: "pink" }); - dltnUswtrData.push({ label: `${month}월`, val: element.dltnUswtr, color: "purple" }); - ithlRswtrData.push({ label: `${month}월`, val: element.ithlRswtr, color: "green" }); - ithlEtcUswtrData.push({ label: `${month}월`, val: element.ithlEtcUswtr, color: "blue" }); - cleanToilUswtrData.push({ label: `${month}월`, val: element.cleanToilUswtr, color: "magenta" }); - resnData.push({ label: `${month}월`, val: element.resn, color: "skyblue" }); - - lndwtrData.push({ label: `${month}월`, val: element.lndwtr, color: "red" }); - hydUswtrData.push({ label: `${month}월`, val: element.hydUswtr, color: "orange" }); - ugwtChrData.push({ label: `${month}월`, val: element.ugwtChr, color: "yellow" }); - farmUswtrData.push({ label: `${month}월`, val: element.farmUswtr, color: "green" }); - rvrKeepUswtrData.push({ label: `${month}월`, val: element.rvrKeepUswtr, color: "blue" }); - indstUswtrData.push({ label: `${month}월`, val: element.indstUswtr, color: "purple" }); - }); + lndwtrData.push({ label: `${month}월`, val: element.lndwtr, color: "red" }); + hydUswtrData.push({ label: `${month}월`, val: element.hydUswtr, color: "orange" }); + ugwtChrData.push({ label: `${month}월`, val: element.ugwtChr, color: "yellow" }); + farmUswtrData.push({ label: `${month}월`, val: element.farmUswtr, color: "green" }); + rvrKeepUswtrData.push({ label: `${month}월`, val: element.rvrKeepUswtr, color: "blue" }); + indstUswtrData.push({ label: `${month}월`, val: element.indstUswtr, color: "purple" }); + }); + } }); // 도넛차트 데이터 @@ -316,7 +325,7 @@ export default function PbnstPrfmncSttn() { setDnInUsage(dnInData); setDnOutUsage(dnOutData); } - }, [rawData, year]); + }, [rawData, year, chartId]); useEffect(() => { const newChartConfig = chartData.reduce((config, element) => { @@ -440,24 +449,38 @@ export default function PbnstPrfmncSttn() { }, [outLineData]); useEffect(() => { - if (!pbnstPrfmncSttn.isInit) { - pbnstPrfmncInit("1", "11"); + const returnType: ReturnType = { + sidoValue: "0", + sigunValue: "0", + partValue: "A", + regionValue: "0", + unitWaterShedValue: "", + middleRegionValue: "", + envPartValue: "", + sidoText: "", + sigunText: "" } - }, [pbnstPrfmncSttn.isInit, pbnstPrfmncInit]); + tableHeadMaker(Number(searchYear), Number(searchYear)); + pbnstPrfmncSearch(returnType, "", searchYear, searchYear) + }, []); useEffect(() => { setbdstTable(prfmncRes); + if(prfmncRes?.[0]?.pbnstRuseFcltPk) setChartId(prfmncRes[0].pbnstRuseFcltPk) }, [prfmncRes]); - const [searchYear, setSearchYear] = useState<string>( - String(new Date().getFullYear()) - ); + useEffect(() => { if (pbnRuseNm.length > 1) pbnNmSearch("1", "23", ref.current, pbnRuseNm, searchYear); }, [pbnRuseNm]); + const cellClick = (index: number | undefined, headId: string) => { + if (index !== undefined && headId !== undefined) { + setChartId(prfmncRes[index].pbnstRuseFcltPk) + } + } return ( <> @@ -506,21 +529,21 @@ export default function PbnstPrfmncSttn() { setPbnRuseNm(searchNm || ""); }} setRtnData={function (rtnData: any[]): void { - setbdstTable(rtnData); + // setbdstTable(rtnData); }} searchList={pbnstSttn.pbnstSearchData || []} ></SearchInputText> - <SelectBox + {/* <SelectBox className="h-full text-2xl" label="재이용시설명" selectClass={""} selectArray={[]} value={""} - onSelectValue={() => { }} /> + onSelectValue={() => { }} /> */} </div> </div>} queryClick={function (returnType: ReturnType): void { - pbnstPrfmncSearch(returnType, swtrmtFcltNm ?? "", fromDate, toDate); + pbnstPrfmncSearch(returnType, pbnRuseNm ?? "", fromDate, toDate); if (fromDate && toDate) { const fromNum = Number(fromDate); const toNum = Number(toDate); @@ -551,8 +574,12 @@ export default function PbnstPrfmncSttn() { headlist={pbnstPrfHeadList} pageSize={20} total={10000} - cellClick={() => { }} - onPageChange={() => { }} + cellClick={(index: number | undefined, headId: string) => { + cellClick(index ?? undefined, headId); + }} + onPageChange={() => { } + } + index={0} /> <hr /> diff --git a/apps/wr/app/store/common/code/index.ts b/apps/wr/app/store/common/code/index.ts index 74001b27c..e7fca8180 100644 --- a/apps/wr/app/store/common/code/index.ts +++ b/apps/wr/app/store/common/code/index.ts @@ -181,10 +181,20 @@ export type comCodeType = comCodeState & comCodeActions; export const getSggCd = async (set: any) => { const sgg = await getFetch("common", "/addr/sgg"); - const sggCd = sgg.map((item: any) => ({ + /* const sggCd = sgg.map((item: any) => ({ val: item.adstDstrCd, text: item.gugun, - })); + })); */ + + const sggCd = [ + { text: "전체", val: '0' }, + ...sgg + .map((item: any) => ({ + text: item.gugun || '', + val: String(item.adstDstrCd) || '' + })) + ]; + set((state: comCodeState) => ({ code: { ...state.code, @@ -332,7 +342,7 @@ export const codeActionExport: (set: any) => comCodeActions = (set: any) => { val: item.adstDstrCd, text: item.gugun, })); - + const city = await getFetch("common", "/addr/city"); const cityCd = city.map((item: any) => ({ val: item.adstDstrCd, diff --git a/apps/wr/app/store/common/searchCode/index.ts b/apps/wr/app/store/common/searchCode/index.ts index 8f05eca09..34c2c86c5 100644 --- a/apps/wr/app/store/common/searchCode/index.ts +++ b/apps/wr/app/store/common/searchCode/index.ts @@ -7,8 +7,50 @@ import { import type { pubHasuType } from "../../ruseFcltMng/fcltReg/pbnstReg/type"; import type { DemandCompType } from "@common/business_components/ui/sdmInsertForm/form"; import type { conCostFeeType, rateFeeType } from "./type"; + + +export const comFcltStateExport: comFcltState = { + searchFclts: [] as pubHasuType[], + demandCompList: [], + dmdIsSucees: '', + checkDemand: { + index: 0, + dmdInfoPk: "", + dmdInfoFk: "", + bzmnNo: "", + dmdCoNm: "", + daddr: "", + telno: "", + rgtr: "", + useUsgCd: "", + ctpvCd: "", + sggCd: "", + dmdAplyPswd: "", + wntUntprc: 0, + dmndTmng: "", + dmndQty: 0, + grssClfg: 0, + tn: 0, + combResdch: 0, + tph: 0, + trbt: 0, + ph: 0, + blgcOxygDmndQnt: 0, + clIonQnt: 0, + smll: 0, + cdtnv: 0, + crmty: 0, + rmrk: "", + reqDt: "" + }, + constCostRes:[], + rateFeeRes:[], +}; + +export type comFcltType = comFcltState & comFcltActions; + export type comFcltState = { - searchFclts: pubHasuType; + searchFclts: pubHasuType[]; demandCompList: DemandCompType[]; dmdIsSucees: string; checkDemand: DemandCompType; @@ -16,7 +58,7 @@ export type comFcltState = { rateFeeRes:rateFeeType[], }; -export type comFcltActions = { + type comFcltActions = { getSwtrmtFcltNm: (searchNm: string) => void; getDemandCompList: (searchNm: string, cnt: number) => void; regDemandCompany: (data: DemandCompType) => void; @@ -25,7 +67,7 @@ export type comFcltActions = { getRateFee: (year: string) => void; }; -export const searchActions: (set: any) => comFcltActions = (set: any) => { +export const comFcltSearchAction: (set: any) => comFcltActions = (set: any) => { return { getSwtrmtFcltNm: async (searchNm: string) => { const fcltNm = await getFetch( diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx index ed23740d0..5754c02fc 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx @@ -32,106 +32,106 @@ export const buildingToExcelType = ( 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, - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - ]); - }); + 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; - + }); + return excelData; + }; export const excelToRainChkData = (excelData: any, year: string) => { const rainChkgdData: rainChkZodType[] = excelData.map((item: any) => { if (item["점검일"] !== undefined) { - const checkYmd = item["점검일"].replace(/\./g, "") - let vltnDt = item["과태료 부과일(위반일)"] - if (vltnDt !== undefined) { - vltnDt = vltnDt .replace(/\./g, "") - } - 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: checkYmd, - splyUswtrUtztnQnt: splyData !== undefined ? splyData : 0, - ruseFcltUtztnQnt: ruseData !== undefined ? ruseData : 0, - flg: "RNB", - }; - }); - - return { - - bdstRuseFcltFk: Number(item["NO"]), - chckYmd: checkYmd, - spwtPositn: item["유량측정방법"], - rgtr: TEST_UUID, - oilqMeasMthd: item["운영관리형태"], - anlOperCst: Number(item["연간운영비(원/년)"]) ?? 0, - operMngCd: item["유량측정방법"], - guideDetails: makeGuidDetail, - rainyDetails: [ - { + const checkYmd = item["점검일"].replace(/\./g, "") + let vltnDt = item["과태료 부과일(위반일)"] + if (vltnDt !== undefined) { + vltnDt = vltnDt ? vltnDt.replace(/\./g, "") : ""; + } + 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["이용용도"], - ph: Number(item["PH"]) ?? 0, - trbt: Number(item["탁도"]) ?? 0, - grssClfg: Number(item["총대장균군수"]) ?? 0, - etc: item["기타"] ?? "", // 필드 누락 방지 - vltnDt: vltnDt, - vltnMttr: item["위반사항"], - levyAmt: Number(item["과태료부과금액(천원)"]) ?? 0, - rgtr: TEST_UUID, - }, - ], - }; - } + ym: year + month, + chckYmd: checkYmd, + splyUswtrUtztnQnt: Number(splyData ?? 0), + ruseFcltUtztnQnt: Number(ruseData ?? 0), + flg: "RNB", + }; + }); + + return { + + bdstRuseFcltFk: Number(item["NO"]), + chckYmd: checkYmd, + 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: vltnDt ?? "", + vltnMttr: item["위반사항"] ?? "", + levyAmt: Number(item["과태료부과금액(천원)"] ?? 0), + rgtr: TEST_UUID, + }, + ], + }; + } }).filter((el: any) => el !== undefined); 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 ff612a0fb..3bd10169f 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/index.tsx @@ -61,7 +61,7 @@ type rainChkgdnActions = { ): Promise<void>; rainChkExcelDataUPload(excelData: rainChkZodType[]): Promise<void>; rainChkDelete(chkgdnPks: number[]): Promise<void>; - rainChkHeadChange: (rainChkgdn: rainChkgdnState, isEdit :boolean) => void; + rainChkHeadChange: (rainChkgdn: rainChkgdnState, isEdit: boolean) => void; }; export type rainChkgdnType = rainChkgdnState & rainChkgdnActions; @@ -99,9 +99,10 @@ const makeMdfrChk = (data: rainChkZodType[], type: string, toDo: string) => { }; const initFetch = async (txt: string | undefined, sgg: string | undefined) => { + const currentYear = new Date().getFullYear().toString(); const rainRes = await getFetch( "wr", - `/reuseChk/rainy` + (txt ? `/${txt}` : "2024") + (sgg ? `/${sgg}` : "/0") + `/reuseChk/rainy` + (txt ? `/${txt}` : currentYear) + (sgg ? `/${sgg}` : "/0") ); return rainRes; }; @@ -130,13 +131,16 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( rainChkExcelDataUPload: async (excelData: rainChkZodType[]) => { try { const res = await postFectch("/reuseChk/rainy", excelData); + console.log("res", res); + console.log("res.ok", res.ok) if (res.ok) { ToastFormUi({ body: "지도점검 등록이 완료되었습니다. ", title: "지도점검 등록", }); } - const rainChkRes = await initFetch("2024", "0"); + const currentYear = new Date().getFullYear().toString(); + const rainChkRes = await initFetch(currentYear, "0"); return set((state: rainChkgdnState) => ({ ...state, rainChkgdn: { @@ -178,7 +182,8 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( title: "지도점검 수정", }); } - const rainChkRes = await initFetch("2024", "0"); + const currentYear = new Date().getFullYear().toString(); + const rainChkRes = await initFetch(currentYear, "0"); return set((state: rainChkgdnState) => ({ ...state, rainChkgdn: { @@ -201,7 +206,8 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( title: "지도점검 수정", }); } - const rainChkRes = await initFetch("2024", "0"); + const currentYear = new Date().getFullYear().toString(); + const rainChkRes = await initFetch(currentYear, "0"); return set((state: rainChkgdnState) => ({ ...state, rainChkgdn: { @@ -223,7 +229,8 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( title: "지도점검 삭제", }); } - const rainChkRes = await initFetch("2024", "0"); + const currentYear = new Date().getFullYear().toString(); + const rainChkRes = await initFetch(currentYear, "0"); return set((state: rainChkgdnState) => ({ ...state, rainChkgdn: { @@ -235,23 +242,23 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( ToastFormUi({ body: "삭제를 실패했습니다.. ", title: "지도점검 삭제" }); } }, - rainChkHeadChange: async (rainChkgdn: rainChkgdnState , isEdit :boolean) => { + rainChkHeadChange: async (rainChkgdn: rainChkgdnState, isEdit: boolean) => { try { const rainChkgdnHeadList = rainChkgdn.rainChkgdn.rainChkgdnHeadList; const splHeadList = rainChkgdn.rainChkgdn.splHeadList; const ruseHeadList = rainChkgdn.rainChkgdn.ruseHeadList; - rainChkgdnHeadList.forEach(( head) => { - if(head.edit!== undefined) - head.edit=isEdit; + rainChkgdnHeadList.forEach((head) => { + if (head.edit !== undefined) + head.edit = isEdit; }); splHeadList.forEach((head) => { - if(head.edit!== undefined) - head.edit=isEdit; + if (head.edit !== undefined) + head.edit = isEdit; }); ruseHeadList.forEach((head) => { - if(head.edit!== undefined) - head.edit=isEdit; + if (head.edit !== undefined) + head.edit = isEdit; }); return set((state: rainChkgdnState) => ({ @@ -259,8 +266,8 @@ export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = ( rainChkgdn: { ...state.rainChkgdn, rainChkgdnHeadList: rainChkgdnHeadList, - splHeadList:splHeadList, - ruseHeadList:ruseHeadList + splHeadList: splHeadList, + ruseHeadList: ruseHeadList }, })); } catch (error) { diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rswrtChkgdn/index.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rswrtChkgdn/index.tsx index c6737b31e..1cc7bd766 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rswrtChkgdn/index.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rswrtChkgdn/index.tsx @@ -1,10 +1,9 @@ import { TEST_UUID, - type TableUpperProps, } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import type { SelectDataType, - sheetParameter, + SheetParameter, } from "@common/business_components"; import { deleteFectch, @@ -25,6 +24,7 @@ import { import { z } from "zod"; import { ToastFormUi } from "@/components/ui/toast/toastFromUi"; import { type chHeadType } from "../rainChkgdn/headList"; +import type { TableUpperProps } from "@/app/store/common/type/header"; const rswtChkHeadList = rswtChkHeadListExport; const rswtDetailHeadList = rswtDetailHeadListExport; @@ -37,7 +37,7 @@ export type rswtChkgdnState = { rswtDetailHeadList: TableUpperProps[]; rswtHeadNm: chHeadType[]; - excelList: [typeof sheetParameter]; + excelList: SheetParameter[]; rswtChkRes: rswtChkZodType[]; rswtChkPolGuide: rswtChkZodType[]; isInit: boolean; @@ -55,6 +55,7 @@ type rswtChkgdnActions = { rswtChkDelete: (chkgdnPks: number[]) => void; rswtChkDetilsUpdate: (rswtChkDetails: rswtrChkDetailsZodType[]) => void; rswtChkPolAndGuide: (chkGdnPk: number) => void; + rswtChkPolInit: () => void; rwstPolAndGuideUpdate: (rswtChk: rswtChkZodType[]) => void; rswtChkHeadChange: (rswtChkgdn: rswtChkgdnState, isEdit: boolean) => void; }; @@ -69,7 +70,7 @@ export const rswtChkgdnStateExport: rswtChkgdnState = { excelList: [{ data: [[]], headerNum: 0, headerRange: "A1:V3", sheetName: "", - startCol: 0 + startCol: '1' }], rswtChkRes: [], rswtChkPolGuide: [], @@ -79,10 +80,11 @@ export const rswtChkgdnStateExport: rswtChkgdnState = { }; const initFetch = async (year: string | undefined, sgg: string | undefined) => { + const currentYear = new Date().getFullYear().toString(); const rswtChkRes = await getFetch( "wr", `/reuseChk/reuseWater/` + - (year ? `${year}` : "2024") + + (year ? `${year}` : currentYear) + (sgg ? `/${sgg}` : "/0") ); return rswtChkRes; @@ -120,12 +122,12 @@ export const rswtChkgdnActionsExport: (set: any) => rswtChkgdnActions = ( excelList.push({ data: exceldata.guideDetail, headerNum: 0, - headerRange: "A1:AI1", + headerRange: "A1:AJ1", }); excelList.push({ data: exceldata.polutions, headerNum: 0, - headerRange: "A1:AZ1", + headerRange: "A1:BB1", }); return set((state: rswtChkgdnState) => ({ @@ -137,7 +139,7 @@ export const rswtChkgdnActionsExport: (set: any) => rswtChkgdnActions = ( }, rswtChkgdnInit: async (year: string, sggCd: string) => { try { - const rswtChkRes = await initFetch("2024", sggCd); + const rswtChkRes = await initFetch(year, sggCd); return set((state: rswtChkgdnState) => ({ ...state, @@ -160,11 +162,13 @@ export const rswtChkgdnActionsExport: (set: any) => rswtChkgdnActions = ( title: "지도점검 등록", }); } - // const rainChkRes = await initFetch('2024', '0'); + const currentYear = new Date().getFullYear().toString(); + const rswtChkRes = await initFetch(currentYear, "0"); return set((state: rswtChkgdnState) => ({ ...state, rswtChkgdn: { ...state.rswtChkgdn, + rswtChkRes: rswtChkRes }, })); } catch (error) { @@ -175,9 +179,6 @@ export const rswtChkgdnActionsExport: (set: any) => rswtChkgdnActions = ( try { const chData = await makeMdfrChk(rswtChk); - console.log("chData ", chData); - - console.log("rswtChk ", rswtChk); const res = await putFectch("/reuseChk/reuseWater", chData); if (res.ok) { @@ -186,7 +187,8 @@ export const rswtChkgdnActionsExport: (set: any) => rswtChkgdnActions = ( title: "지도점검 수정", }); } - const rswtChkRes = await initFetch("2024", "0"); + const currentYear = new Date().getFullYear().toString(); + const rswtChkRes = await initFetch(currentYear, "0"); return set((state: rswtChkgdnState) => ({ ...state, rswtChkgdn: { @@ -209,7 +211,8 @@ export const rswtChkgdnActionsExport: (set: any) => rswtChkgdnActions = ( title: "지도점검 삭제", }); } - const rswtChkRes = await initFetch("2024", "0"); + const currentYear = new Date().getFullYear().toString(); + const rswtChkRes = await initFetch(currentYear, "0"); return set((state: rswtChkgdnState) => ({ ...state, rswtChkgdn: { @@ -237,6 +240,17 @@ export const rswtChkgdnActionsExport: (set: any) => rswtChkgdnActions = ( })); } catch (error) {} }, + rswtChkPolInit: () => { + try { + return set((state: rswtChkgdnState) => ({ + ...state, + rswtChkgdn: { + ...state.rswtChkgdn, + rswtChkPolGuide: undefined, + }, + })); + } catch (error) {} + }, rwstPolAndGuideUpdate: async (rswtChk: rswtChkZodType[]) => { try { const chData = await makeMdfrChk(rswtChk); @@ -250,7 +264,8 @@ export const rswtChkgdnActionsExport: (set: any) => rswtChkgdnActions = ( title: "지도점검 수정", }); } - const rswtChkRes = await initFetch("2024", "0"); + const currentYear = new Date().getFullYear().toString(); + const rswtChkRes = await initFetch(currentYear, "0"); return set((state: rswtChkgdnState) => ({ ...state, rswtChkgdn: { diff --git a/apps/wr/app/store/prfmncReg/pbnstPrfmncReg/index.tsx b/apps/wr/app/store/prfmncReg/pbnstPrfmncReg/index.tsx index 37c010890..82f2ed59c 100644 --- a/apps/wr/app/store/prfmncReg/pbnstPrfmncReg/index.tsx +++ b/apps/wr/app/store/prfmncReg/pbnstPrfmncReg/index.tsx @@ -33,7 +33,7 @@ export type pbnstPrfmncType = pbnstPrfmncState & pbnstPrfmncActions; type pbnstPrfmncActions = { prfmncHasuInit: (page: string, sggOrCity: string) => void; - prfmnRegData: (data:PrfType) =>void + prfmnRegData: (data: PrfType) => void; }; const checkWrRegList = async () => { @@ -47,21 +47,28 @@ const hasuListFetch = async (page: string, sggOrCity: string) => { checkWrRegListRes?.fcltCds, fetchType.COMMON ); - const data = checkWrRegListRes.fcPrfList.map((item: FcPrfType) => { - const findData = rainRes.data.find( - (fclt: pubHasuType) => - fclt.bscFctCd === item.pbnstRuseFcltPk.substring(0, 11) + + + const findData = rainRes.data.map((item: pubHasuType) => { + const data = checkWrRegListRes?.fcPrfList.find( + (fclt: FcPrfType) => + fclt.pbnstRuseFcltPk.substring(0, 11) === item?.bscFctCd ); - return { - sido: findData?.sido, - gugun: findData?.gugun, - bscFctNm: findData?.bscFctNm, - ruseUtztnFcltNm: item.ruseUtztnFcltNm, - pbnstRuseFcltPk: item.pbnstRuseFcltPk, - prfList : item.prfList - }; + if(data !==undefined){ + return( { + + sido: item.sido, + gugun: item.gugun, + bscFctNm: item.bscFctNm, + bscFctCd: item.bscFctCd, + ruseUtztnFcltNm: data.ruseUtztnFcltNm, + pbnstRuseFcltPk: data.pbnstRuseFcltPk, + prfList: data.prfList, + }); + } }); - return data; + + return findData; }; export const pbnstPrfmncActionsExport: (set: any) => pbnstPrfmncActions = ( set: any @@ -70,7 +77,6 @@ export const pbnstPrfmncActionsExport: (set: any) => pbnstPrfmncActions = ( prfmncHasuInit: async (page: string, sggOrCity: string) => { try { const prfmncRes = await hasuListFetch(page, sggOrCity); - console.log("prfmncRes", prfmncRes); return set((state: pbnstPrfmncState) => ({ ...state, prfmnc: { @@ -83,26 +89,21 @@ export const pbnstPrfmncActionsExport: (set: any) => pbnstPrfmncActions = ( console.log(errorHasu); } }, - prfmnRegData: async (data:PrfType,) => { - try{ - + prfmnRegData: async (data: PrfType) => { + try { const ressponse = await postFectch( "/reuseFc/pubFcPrf", data, fetchType.WR ); - console.log('ressponse ', ressponse) - - if(ressponse.status === 200){ - - toast.success("하수재이용 시설 실적 등록이 완료되었습니다.") - - } - }catch(e){ - console.log(e) - toast.error("하수재이용 시설 실적 등록이 실패하였습니다.") + if (ressponse.status === 200) { + toast.success("하수재이용 시설 실적 등록이 완료되었습니다."); + } + } catch (e) { + console.log(e); + toast.error("하수재이용 시설 실적 등록이 실패하였습니다."); } }, }; diff --git a/apps/wr/app/store/prfmncSttn/chkgdnSttn/rainChkgdnSttn/index.tsx b/apps/wr/app/store/prfmncSttn/chkgdnSttn/rainChkgdnSttn/index.tsx index 9fd948856..ea3f58a40 100644 --- a/apps/wr/app/store/prfmncSttn/chkgdnSttn/rainChkgdnSttn/index.tsx +++ b/apps/wr/app/store/prfmncSttn/chkgdnSttn/rainChkgdnSttn/index.tsx @@ -35,7 +35,7 @@ export type rainChkSttnState = { }; type rainChkSttnActions = { - rainChkSttnInit: ( sggCd: string) => void; + rainChkSttnInit: (searchTxt: string, sggCd: string) => void; rainChkSttnSearch: (searchTxt: string, sggCd: string) => void; isRainSttn:(isSttn:boolean) => void; getRainSttnExcel:(excelList:rainChkZodType[]) => void; @@ -58,9 +58,10 @@ export const rainChkSttnStateExport: rainChkSttnState = { }; const initFetch = async (txt: string | undefined, sgg: string | undefined) => { + const currentYear = new Date().getFullYear().toString(); const rainRes = await getFetch( "wr", - `/reuseChk/rainy/` + (txt ? `${txt}` : "2024") + (sgg ? `/${sgg}` : "/0") + `/reuseChk/rainy/` + (txt ? `${txt}` : currentYear) + (sgg ? `/${sgg}` : "/0") ); return rainRes; }; @@ -68,9 +69,9 @@ export const rainChkSttnActionsExport: (set: any) => rainChkSttnActions = ( set: any ) => { return { - rainChkSttnInit: async ( sggCd: string) => { + rainChkSttnInit: async (searchTxt: string, sggCd: string) => { try { - const rainChkRes = await initFetch(undefined, sggCd); + const rainChkRes = await initFetch(searchTxt, sggCd); return set((state: rainChkSttnState) => ({ ...state, diff --git a/apps/wr/app/store/prfmncSttn/chkgdnSttn/rswtChkgdnSttn/excel.tsx b/apps/wr/app/store/prfmncSttn/chkgdnSttn/rswtChkgdnSttn/excel.tsx index ff104bc91..6e6b5730c 100644 --- a/apps/wr/app/store/prfmncSttn/chkgdnSttn/rswtChkgdnSttn/excel.tsx +++ b/apps/wr/app/store/prfmncSttn/chkgdnSttn/rswtChkgdnSttn/excel.tsx @@ -19,6 +19,7 @@ export const buildingExcelRswtSttn = (excelList: any[]) => { String(item.trbt) ?? "", String(item.bod) ?? "", String(item.smll) ?? "", + String(item.crmty) ?? "", String(item.tn) ?? "", String(item.tph) ?? "", String(item.ph) ?? "", diff --git a/apps/wr/app/store/prfmncSttn/chkgdnSttn/rswtChkgdnSttn/headList.tsx b/apps/wr/app/store/prfmncSttn/chkgdnSttn/rswtChkgdnSttn/headList.tsx index f67e98101..91f6bf718 100644 --- a/apps/wr/app/store/prfmncSttn/chkgdnSttn/rswtChkgdnSttn/headList.tsx +++ b/apps/wr/app/store/prfmncSttn/chkgdnSttn/rswtChkgdnSttn/headList.tsx @@ -1,15 +1,15 @@ import type { TableUpperProps } from "@/app/store/common/type/header"; export const rswtChkSttnHeadListExport: 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: "anlOperCst", title: "연간운영비(원/년)", rowSpan: true }, - { id: "prcsCpct", title: "처리용량(m³)", rowSpan: true }, - { id: "spwtPositn", title: "채수지점", rowSpan: true }, - { id: "chckYmd", title: "점검일", rowSpan: true }, + { id: "order", title: "순번", mergeCell: true }, + { id: "cityText", title: "시도", mergeCell: true }, + { id: "sggText", title: "시군구", mergeCell: true }, + { id: "bdstNm", title: "시설명", mergeCell: true }, + { id: "operMngCd", title: "운영관리형태", mergeCell: true }, + { id: "anlOperCst", title: "연간운영비(원/년)", mergeCell: true }, + { id: "prcsCpct", title: "처리용량(m³)", mergeCell: true }, + { id: "spwtPositn", title: "채수지점", mergeCell: true }, + { id: "chckYmd", title: "점검일", mergeCell: true }, { id: "utztnUsgCd", title: "이용용도" }, { id: "splyUswtrUtztnQnt", title: "연간보급수이용량(m³)", type: "number" }, { id: "ruseFcltUtztnQnt", title: "연간중수도이용량(m³)", type: "number" }, diff --git a/apps/wr/app/store/prfmncSttn/chkgdnSttn/rswtChkgdnSttn/index.tsx b/apps/wr/app/store/prfmncSttn/chkgdnSttn/rswtChkgdnSttn/index.tsx index b985cd944..cd95ef1fc 100644 --- a/apps/wr/app/store/prfmncSttn/chkgdnSttn/rswtChkgdnSttn/index.tsx +++ b/apps/wr/app/store/prfmncSttn/chkgdnSttn/rswtChkgdnSttn/index.tsx @@ -24,10 +24,10 @@ export type rswtChkSttnState = { }; type rswtChkSttnActions = { - rswtChkSttnInit: ( sggCd: string) => void; - isRswtSttn: (isSttn:boolean) => void; - getRswtSttnExcel:(excelList:rswtChkZodType[]) => void; - + rswtChkSttnInit: (searchTxt: string, sggCd: string) => void; + isRswtSttn: (isSttn: boolean) => void; + getRswtSttnExcel: (excelList: rswtChkZodType[]) => void; + rswtChkSttnSearch: (searchTxt: string, sggCd: string) => void; }; export type rswtChkSttnType = rswtChkSttnState & rswtChkSttnActions; @@ -40,16 +40,17 @@ export const rswtChkStateExport: rswtChkSttnState = { sttnExcelList: [], rswtChkRes: [], isInit: false, - isSttn:false, + isSttn: false, }, }; const initFetch = async (year: string | undefined, sgg: string | undefined) => { + const currentYear = new Date().getFullYear().toString(); const rswtChkRes = await getFetch( "wr", `/reuseChk/reuseWater/` + - (year ? `${year}` : "2024") + - (sgg ? `/${sgg}` : "/0") + (year ? `${year}` : currentYear) + + (sgg ? `/${sgg}` : "/0") ); return rswtChkRes; }; @@ -59,9 +60,9 @@ export const rswtChkSttnActionsExport: (set: any) => rswtChkSttnActions = ( set: any ) => { return { - rswtChkSttnInit: async ( sggCd: string) => { + rswtChkSttnInit: async (searchTxt: string, sggCd: string) => { try { - const rswtChkRes = await initFetch("2024", sggCd); + const rswtChkRes = await initFetch(searchTxt, sggCd); return set((state: rswtChkSttnState) => ({ ...state, rswtChkSttn: { @@ -73,35 +74,50 @@ export const rswtChkSttnActionsExport: (set: any) => rswtChkSttnActions = ( } catch (error) { console.log(error); } - },isRswtSttn :(isSttn:boolean) =>{ - try { - return set((state: rswtChkSttnState) => ({ - ...state, - rswtChkSttn: { - ...state.rswtChkSttn, - isSttn:isSttn - }, - })); - } catch (error) { - console.log(error); - } - },getRswtSttnExcel: async (excelList:rswtChkZodType []) => { - try { - - const excelData = buildingExcelRswtSttn(excelList) - - return set((state: rswtChkSttnState) => ({ - ...state, - rswtChkSttn: { - ...state.rswtChkSttn, - sttnExcelList:excelData - }, - })); - } catch (error) { - console.log(error); - } - } + }, + isRswtSttn: (isSttn: boolean) => { + try { + return set((state: rswtChkSttnState) => ({ + ...state, + rswtChkSttn: { + ...state.rswtChkSttn, + isSttn: isSttn + }, + })); + } catch (error) { + console.log(error); + } + }, + getRswtSttnExcel: async (excelList: rswtChkZodType[]) => { + try { - + const excelData = buildingExcelRswtSttn(excelList) + + return set((state: rswtChkSttnState) => ({ + ...state, + rswtChkSttn: { + ...state.rswtChkSttn, + sttnExcelList: excelData + }, + })); + } catch (error) { + console.log(error); + } + }, + rswtChkSttnSearch: async (searchTxt: string, sggCd: string) => { + try { + const rswtChkRes = await initFetch(searchTxt, sggCd); + + return set((state: rswtChkSttnState) => ({ + ...state, + rswtChkSttn: { + ...state.rswtChkSttn, + rswtChkRes: rswtChkRes + }, + })); + } catch (error) { + console.log(error); + } + }, }; }; diff --git a/apps/wr/app/store/prfmncSttn/pbnstPrfmncSttn/index.tsx b/apps/wr/app/store/prfmncSttn/pbnstPrfmncSttn/index.tsx index d0e958785..b513085ae 100644 --- a/apps/wr/app/store/prfmncSttn/pbnstPrfmncSttn/index.tsx +++ b/apps/wr/app/store/prfmncSttn/pbnstPrfmncSttn/index.tsx @@ -75,7 +75,7 @@ export const pbnstPrfmncSttnActionsExport: (set: any) => pbnstPrfmncSttnActions for (let i = startYear; i <= endYear; i++) { const yearHead = JSON.parse(JSON.stringify(pbnstYearHeadListExport)); if (yearHead) { - yearHead.forEach((item: { id?: number; }) => { + yearHead.forEach((item: { id?: string; }) => { if (item.id) { item.id = i + item.id; @@ -92,6 +92,7 @@ export const pbnstPrfmncSttnActionsExport: (set: any) => pbnstPrfmncSttnActions return { ...state, pbnstPrfmncSttn: { + ...state.pbnstPrfmncSttn, pbnstPrfHeadList: [...yearHeader], selectYearList: selectList }, @@ -106,7 +107,7 @@ export const pbnstPrfmncSttnActionsExport: (set: any) => pbnstPrfmncSttnActions pbnstPrfmncSttn: { ...state.pbnstPrfmncSttn, prfmncRes: prfmncRes, - isInit: false, + isInit: true, }, })); } catch (e) { @@ -115,8 +116,7 @@ export const pbnstPrfmncSttnActionsExport: (set: any) => pbnstPrfmncSttnActions }, pbnstPrfmncSearch: async (returnType: ReturnType, swtrmtFcltNm: string, fromDate: string, toDate: string) => { let searchUrl = ""; - - if (returnType.sigunValue !== undefined) { + if (returnType.sigunValue !== "0") { if (swtrmtFcltNm !== "") { searchUrl = `/prcsFclt/info/1/20/${returnType.partValue}/${returnType.sigunValue}/0/1/SW${'/' + swtrmtFcltNm}`; } else { @@ -134,6 +134,7 @@ export const pbnstPrfmncSttnActionsExport: (set: any) => pbnstPrfmncSttnActions fetchType.COMMON, searchUrl ); + const bscFctCdList = pbnstRes.map((item: any) => { return item.bscFctCd; }) @@ -147,32 +148,59 @@ export const pbnstPrfmncSttnActionsExport: (set: any) => pbnstPrfmncSttnActions let usageSum = 0; let year = ""; const yearsData = [] + res.data.forEach((item) => { + if (item.prfList.length === 0) { + const year = ""; // 연도 정보가 없으면 빈 문자열, 필요시 item에서 추출 + const yearVal = { year: year, pbnstRuseFcltPk: item.pbnstRuseFcltPk ?? "", ruseUtztnFcltNm : item.ruseUtztnFcltNm ?? "" }; + yearVal[year + "inUsage"] = 0; + yearVal[year + "outUsage"] = 0; + yearVal[year + "total"] = 0; + yearsData.push(yearVal); + } item.prfList.forEach((acc) => { - year = acc.ym.substring(0, 4); - inUsageSum = acc.wshwtr + acc.coolUswtr + acc.cleanUswtr + acc.drwtUswtr + - acc.dltnUswtr + acc.ithlRswtr + acc.ithlEtcUswtr + acc.cleanToilUswtr + acc.resn; - outUsageSum = acc.lndwtr + acc.hydUswtr + acc.ugwtChr + acc.farmUswtr + acc.rvrKeepUswtr + acc.indstUswtr; - const yearData = yearsData.find(yearItem => yearItem.year === year && yearItem.pbnstRuseFcltPk == acc.pbnstRuseFcltPk) + year = acc.ym?.substring(0, 4) ?? ""; + inUsageSum = + (acc.wshwtr ?? 0) + + (acc.coolUswtr ?? 0) + + (acc.cleanUswtr ?? 0) + + (acc.drwtUswtr ?? 0) + + (acc.dltnUswtr ?? 0) + + (acc.ithlRswtr ?? 0) + + (acc.ithlEtcUswtr ?? 0) + + (acc.cleanToilUswtr ?? 0) + + (acc.resn ?? 0); + outUsageSum = + (acc.lndwtr ?? 0) + + (acc.hydUswtr ?? 0) + + (acc.ugwtChr ?? 0) + + (acc.farmUswtr ?? 0) + + (acc.rvrKeepUswtr ?? 0) + + (acc.indstUswtr ?? 0); + const yearData = yearsData.find( + (yearItem) => + yearItem.year === year && + yearItem.pbnstRuseFcltPk == acc.pbnstRuseFcltPk + ); if (yearData) { - yearData.inUsageSum += inUsageSum; - yearData.outUsageSum += outUsageSum; + yearData[year + "inUsage"] += inUsageSum; + yearData[year + "outUsage"] += outUsageSum; + yearData[year + "total"] += (inUsageSum + outUsageSum); } else { - const yearVal = { year: year, pbnstRuseFcltPk: acc.pbnstRuseFcltFk } - yearVal[year + 'inUsage'] = inUsageSum; - yearVal[year + 'outUsage'] = outUsageSum; - yearVal[year + 'total'] = inUsageSum + outUsageSum; + const yearVal = { year: year, pbnstRuseFcltPk: acc.pbnstRuseFcltFk, ruseUtztnFcltNm : item.ruseUtztnFcltNm ?? "" }; + yearVal[year + "inUsage"] = inUsageSum; + yearVal[year + "outUsage"] = outUsageSum; + yearVal[year + "total"] = inUsageSum + outUsageSum; yearsData.push(yearVal); } - - }) - }) + }); + }); const resData: any[] = [] pbnstRes.forEach((acc) => { let data = yearsData.find((item) => item.pbnstRuseFcltPk.substring(0, 11) === acc.bscFctCd) if (data) { - resData.push({ ...data, ...acc }) + resData.push({ ...acc, ...data }) } }) return set((state: pbnstPrfmncSttnState) => ({ diff --git a/apps/wr/app/store/ruseFcltMng/fcltReg/pbnstReg/type.tsx b/apps/wr/app/store/ruseFcltMng/fcltReg/pbnstReg/type.tsx index a34985810..9c390d076 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltReg/pbnstReg/type.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltReg/pbnstReg/type.tsx @@ -148,7 +148,7 @@ export const fcBizSchema = z.object({ pbnstRuseFcltFk: z.string().nullish(), superkey: z.string().default("").nullish(), cycl: zNum.default(1), - seCd: z.string().default(""), + seCd: z.string().max(10, "구분은 10자를 초과할 수 없습니다.").default(""), bizMthdCd: z.string().default(""), instlAprvSncnDt: zDateDefaultNow, bizCmcnDay: zDateDefaultNow, @@ -171,17 +171,17 @@ export const fcBizSchema = z.object({ wwtEmsnFcltPrmsnYn: z.string().default("Y"), tmsInstlYn: z.string().default("Y"), pbnstDrngInflwExclYn: z.string().default("Y"), - bod: zNumDefaultZero, - grssClfg: zNumDefaultZero, - combResdch: zNumDefaultZero, - trbt: zNumDefaultZero, - clIonQnt: zNumDefaultZero, - smll: zNumDefaultZero, - crmty: zNumDefaultZero, - tph: zNumDefaultZero, - tn: zNumDefaultZero, - ph: zNumDefaultZero, - cdtnv: zNumDefaultZero, + bod: z.preprocess((v) => (v !== null && v !== undefined ? Number(v) : v), z.number().max(9999, "BOD 값은 5자리 미만이어야 합니다.")).nullish(), + grssClfg: z.preprocess((v) => (v !== null && v !== undefined ? Number(v) : v), z.number().max(9999, "총대장균군 값은 5자리 미만이어야 합니다.")).nullish(), + combResdch: z.preprocess((v) => (v !== null && v !== undefined ? Number(v) : v), z.number().max(9999, "결합잔류염소 값은 5자리 미만이어야 합니다.")).nullish(), + trbt: z.preprocess((v) => (v !== null && v !== undefined ? Number(v) : v), z.number().max(9999, "탁도 값은 5자리 미만이어야 합니다.")).nullish(), + clIonQnt: z.preprocess((v) => (v !== null && v !== undefined ? Number(v) : v), z.number().max(9999, "염소이온량 값은 5자리 미만이어야 합니다.")).nullish(), + smll: z.preprocess((v) => (v !== null && v !== undefined ? Number(v) : v), z.number().max(9999, "냄새 값은 5자리 미만이어야 합니다.")).nullish(), + crmty: z.preprocess((v) => (v !== null && v !== undefined ? Number(v) : v), z.number().max(9999, "색도 값은 5자리 미만이어야 합니다.")).nullish(), + tph: z.preprocess((v) => (v !== null && v !== undefined ? Number(v) : v), z.number().max(9999, "총인 값은 5자리 미만이어야 합니다.")).nullish(), + tn: z.preprocess((v) => (v !== null && v !== undefined ? Number(v) : v), z.number().max(9999, "총질소 값은 5자리 미만이어야 합니다.")).nullish(), + ph: z.preprocess((v) => (v !== null && v !== undefined ? Number(v) : v), z.number().max(9999, "수소이온농도 값은 5자리 미만이어야 합니다.")).nullish(), + cdtnv: z.preprocess((v) => (v !== null && v !== undefined ? Number(v) : v), z.number().max(9999, "전기전도도 값은 5자리 미만이어야 합니다.")).nullish(), designCst: zNumNullish, cstrnSpvsCst: zNumNullish, fcltSbsdCst: zNumNullish, @@ -241,4 +241,3 @@ export type fcOrgwtType = z.infer<typeof fcOrgwtSchema>; export type ppInstlType = z.infer<typeof pplInstlSchema>; export type operType = z.infer<typeof fcOperSchema>; export type fcFileType = z.infer<typeof fcFileSchema>; - diff --git a/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx index d398b7f6e..a029bd869 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/index.tsx @@ -2,8 +2,33 @@ import type { TableUpperProps } from "@/app/store/common/type/header"; import { getFetch, postFectch, putFectch } from "@/components/lib/api"; import { z } from "zod"; import { makeMdfr, makeRstr } from "../bdstReg"; +import toast from "react-hot-toast"; +import { baseReuseBuildingSchema, chgBuildingSchema, validationMessages } from "./type"; export const TEST_UUID= '2d4b151d-1828-41e0-91d9-4cd28ea1cc7e' + +const rainyObjSchema = z.object({ + bdstReuseFcltFk: z.number().nullish(), + pntfColKnd: z.string().min(1, { message: validationMessages.requiredSelect("종류") }), + pntfColArea: z.number().positive({ message: validationMessages.required("면적(m³)") }), + dtfcltCpct: z.number().default(0), + filtrTrtmfctYn: z.string().default("Y"), + filtrTrtmfctCpct: z.number().nullish().default(0), + filtrTrtmfctPrs: z.string().default(""), + annRnwtQty: z.number().default(0), + oilqMeasMthd: z.string().default("").nullish(), + rgtr:z.string().nullish(), + mdfr:z.string().nullish(), +}); + + + + + + const rainBuildingSchema = baseReuseBuildingSchema.extend({ + rainyObj: rainyObjSchema, +}) + export const rainZod = z.object({ bdstInfoPk: z.number().optional(), ctpvCd: z.number().default(0), @@ -16,62 +41,9 @@ export const rainZod = z.object({ archChgArea: z.number().default(0), rgtr:z.string().nullish(), mdfr:z.string().nullish(), - reuseBuilding: z.array( - z.object({ - bdstRuseFcltPk: z.number().nullish(), - bdstInfoFk:z.number().nullish(), - instlCmptnDt: z.coerce.date().default(() => new Date()), - instlCst: z.number().nullish(), - operMngCd: z.string().optional().default(""), - anlOperCst: z.number().default(0), - instlCstSprtYn: z.string().default(""), - instlCstSprtAmt: z.number().nullish(), - grntchBdstCertYn: z.enum(["Y", "N"]).nullish(), - 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.string().default("N").nullish(), /// 안쓰는 값 - crgRdctBss: z.string().default("").nullish(), /// 안쓰는 값 - crgRdctAmt: z.number().default(0), // 안쓰는 값 - ruseFcltFlg: z.string().default(""), - bdstUsgCd: z.number().default(0), - lawTrgtYn: z.enum(["Y", "N"]), - rgtr:z.string().nullish(), - mdfr:z.string().nullish(), - - rainyObj: z.object({ - bdstReuseFcltFk: z.number().nullish(), - pntfColKnd: z.string().default(""), - pntfColArea: z.number().default(0), - dtfcltCpct: z.number().default(0), - filtrTrtmfctYn: z.enum(["Y", "N"]).nullish(), - filtrTrtmfctCpct: z.number().nullish().default(0), - filtrTrtmfctPrs: z.string().default(""), - annRnwtQty: z.number().default(0), - oilqMeasMthd: z.string().default("").nullish(), - rgtr:z.string().nullish(), - mdfr:z.string().nullish(), - - - }).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(), - mdfr:z.string().nullish(), - - }) - ).default([]) -}); + reuseBuilding: z.array(rainBuildingSchema).default([]), + chgBuilding: z.array(chgBuildingSchema).default([]) +}) export type chgBuilding={ bdstInfoFk?: number|null, @@ -203,15 +175,18 @@ export const rainFacActionsExport: (set: any) => rainFacSActions = ( bdstInfoFk: chPK, }) ); - const chch= postFectch("/reuseFc/chgBuilding", makeCh); + const chch= postFectch("/reuseFc/chgBuilding", makeCh); return chch; }).then((chch: any) => { - if(chch.ok) { - alert("등록이 완료되었습니다."); + + console.log('chch ', chch) + if(chch.status ===200) { + toast.success("등록이 완료되었습니다."); + } }) }else{ - alert("등록이 완료되었습니다."); + toast.success("등록이 완료되었습니다."); } } const rainRes = await initFetch(code); @@ -254,6 +229,3 @@ export const rainFacActionsExport: (set: any) => rainFacSActions = ( } }} - - - diff --git a/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/type.tsx b/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/type.tsx new file mode 100644 index 000000000..6e28c3e76 --- /dev/null +++ b/apps/wr/app/store/ruseFcltMng/fcltReg/rainReg/type.tsx @@ -0,0 +1,45 @@ +import { z } from "zod"; + + +export const validationMessages = { + required: (field: string) => `${field}을(를) 입력해주세요.`, + requiredSelect: (field: string) => `${field}을(를) 선택해주세요.`, + yearFormat: '4자리 연도만 입력하세요', + }; + +export const baseReuseBuildingSchema = z.object({ + bdstRuseFcltPk: z.number().nullish(), + bdstInfoFk: z.number().nullish(), + instlCmptnDt: z.coerce.date().default(() => new Date()), + instlCst: z.number().nullish(), + operMngCd: z.string().optional().default(""), + anlOperCst: z.number().default(0), + instlCstSprtYn: z.string().default("Y"), + instlCstSprtAmt: z.number().nullish(), + grntchBdstCertYn: z.string().default("Y"), + grntchBdstCertYr: z.string().default("").refine( + (year) => year.length === 0 || /^\d{4}$/.test(year), + { + message: validationMessages.yearFormat, + } + ), + grntchBdstCertNo: z.string().default(""), + grntchBdstCertGrd: z.string().default(""), + crgRdctYn: z.string().default("N").nullish(), /// 안쓰는 값 + crgRdctBss: z.string().default("").nullish(), /// 안쓰는 값 + crgRdctAmt: z.number().default(0), // 안쓰는 값 + ruseFcltFlg: z.string().default(""), + bdstUsgCd: z.number().min(1, { message: validationMessages.requiredSelect("건축물용도") }).default(0), + lawTrgtYn: z.string().default("Y"), + rgtr: z.string().nullish(), + mdfr: z.string().nullish(), +}); + +export const chgBuildingSchema = z.object({ + bdstInfoFk: z.number().nullish(), + archChgPrmsnDt: z.coerce.date({required_error: validationMessages.required("허가일")}), + archChgArea: z.string().default("-"), + bdstChgNm: z.string().min(1, { message: validationMessages.requiredSelect("구분") }), + rgtr:z.string().nullish(), + mdfr:z.string().nullish(), +}); diff --git a/apps/wr/app/store/ruseFcltMng/fcltSttn/pbnstSttn/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltSttn/pbnstSttn/index.tsx index 6ce27db86..33bce5520 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltSttn/pbnstSttn/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltSttn/pbnstSttn/index.tsx @@ -9,6 +9,7 @@ import { excelPbnstSttnParsing } from "./excel"; import type { FcPrfType } from "@/app/store/prfmncReg/pbnstPrfmncReg/type"; import type { ReturnType } from "@common/business_components/ui"; import type { WaterReuseFacility } from "./type"; +import moment from "moment"; const pbnstSttHeadList = pbnSttHeadListExport; const pbnstSttNodeList = pbnstSttNodeListExport; @@ -166,8 +167,8 @@ const hasuListFetch = async ( outUsage: usage.outUsage, operMthd: item.operList[0]?.operMthd, rprtvBzenty: item.operList[0]?.rprtvBzenty, - bgngDt: item.operList[0]?.bgngDt.toLocaleDateString ?? "", - endDt: item.operList[0]?.endDt.toLocaleDateString?? "", + bgngDt: moment(item.operList[0]?.bgngDt).format("YYYY-MM-DD") ?? "", + endDt: moment(item.operList[0]?.endDt).format("YYYY-MM-DD") ?? "", searchNm: findData.bscFctNm, searchPk: findData.bscFctCd, prfList:item?.prfList??[] diff --git a/apps/wr/app/store/store.tsx b/apps/wr/app/store/store.tsx index 4557662f8..7520f7998 100644 --- a/apps/wr/app/store/store.tsx +++ b/apps/wr/app/store/store.tsx @@ -86,7 +86,7 @@ import { import { rswtChkStateExport, rswtChkSttnActionsExport, type rswtChkSttnState, type rswtChkSttnType } from "./prfmncSttn/chkgdnSttn/rswtChkgdnSttn"; import { pbnstSttnActionsExport, pbnstSttnStateExport, type pbnstSttnState, type pbnstSttnType } from "./ruseFcltMng/fcltSttn/pbnstSttn"; import { coSttnActionsExport, coSttnStateExport, type coSttnState, type coSttnType } from "./matDmd/coSttn"; // 옮겨야함 -import { searchActions, type comFcltActions, type comFcltState } from "./common/searchCode"; +import { comFcltStateExport, comFcltSearchAction, type comFcltState, type comFcltType } from "./common/searchCode"; import { pbnstPrfmncActionsExport, pbnstPrfmncStateExport, type pbnstPrfmncState, type pbnstPrfmncType } from "./prfmncReg/pbnstPrfmncReg"; import { coRvwActionsExport, coRvwStateExport, type coRvwState, type coRvwType } from "./matDmd/coMatRvw"; import { ruseHstryActionsExport, ruseHstryStateExport, type ruseHstryState, type ruseHstryType } from "./matDmd/ruseRvwHstry"; @@ -113,7 +113,6 @@ export type WrStore = comCodeType & rainChkSttnType& rswtChkSttnType& pbnstSttnType& - comFcltActions&comFcltState& coSttnType& // 옮겨야함 ldrmntType& // 옮겨야함 pbnstPrfmncType& @@ -124,7 +123,8 @@ export type WrStore = comCodeType & ruseCaseType& rainStatType& rswtStatType& - matStatType + matStatType& + comFcltType ; export const StoreZus = ( @@ -141,6 +141,7 @@ export const StoreZus = ( rswtSttnState & htdflSttnState & rainChkSttnState& + comFcltState& rswtChkSttnState & pbnstSttnState& coSttnState& // 옮겨야함 @@ -180,7 +181,8 @@ export const StoreZus = ( ...ruseCaseStateExport, ...rainStatExport, ...rswtStatExport, - ...matStatExport + ...matStatExport, + ...comFcltStateExport } ) => { return createStore<WrStore>()((set) => { @@ -192,7 +194,7 @@ export const StoreZus = ( getEnvPartCd(set); return { ...initState, - ...searchActions(set), + ...comFcltSearchAction(set), ...pubFacActionsExport(set), ...rainFacActionsExport(set), ...rswtFacActionsExport(set), diff --git a/apps/wr/components/lib/func/TableData.tsx b/apps/wr/components/lib/func/TableData.tsx index c21a7e70a..dbb3aa7a6 100644 --- a/apps/wr/components/lib/func/TableData.tsx +++ b/apps/wr/components/lib/func/TableData.tsx @@ -152,7 +152,8 @@ export const chRowspanTable = ( onChange={(e) => { handleChange(rowIndex, head.id, e.target.value); }} - value={value} + value={value ?? ""} + disabled={!selectedIds.includes(row.chkgdnPk)} /> ) : ( (head.id === "totalSplyUswtrUtztnQnt" || head.id === "totalRuseFcltUtztnQnt" || head.id === "splyUswtrUtztnQnt" || head.id === "ruseFcltUtztnQnt") ? ( diff --git a/apps/wr/components/lib/func/commom.tsx b/apps/wr/components/lib/func/commom.tsx index 85e1a36b0..e5dfc8c0c 100644 --- a/apps/wr/components/lib/func/commom.tsx +++ b/apps/wr/components/lib/func/commom.tsx @@ -4,6 +4,7 @@ import { type SelectDataType, type ReturnType, filePickedBlobArray, + type SheetParameter, } from "@common/business_components/ui"; import type { RefObject } from "react"; @@ -81,7 +82,7 @@ export const excelDownload = ( export const excelArrayDownload = ( fileNm: string, sampleFile: string, - sheetArray: [] + sheetArray:SheetParameter [] ) => { if (!sheetArray) return; fetch(`/${sampleFile}`, {}).then(async (response) => { @@ -110,7 +111,12 @@ export const formatCommaNumber = ( value: number | string | undefined | null ): string => { if (value === undefined || value === null || value === "") return ""; - return Number(value).toLocaleString(); + const num = Number(value); + // 숫자로 변환할 수 없는 값이 들어올 경우 빈 문자열을 반환하여 예상치 못한 "NaN" 출력을 방지합니다. + if (isNaN(num)) { + return ""; + } + return num.toLocaleString(); }; export const getCityOrSgg = (ref: RefObject<ReturnType>) => { @@ -153,6 +159,3 @@ export const getdmdMatFlag = (flag: string|undefined) => { } return flagMat; }; - - - diff --git a/apps/wr/components/ui/form/fcltReg/bdstReg/bdstReg.tsx b/apps/wr/components/ui/form/fcltReg/bdstReg/bdstReg.tsx index 5ab5edf98..0d00454e2 100644 --- a/apps/wr/components/ui/form/fcltReg/bdstReg/bdstReg.tsx +++ b/apps/wr/components/ui/form/fcltReg/bdstReg/bdstReg.tsx @@ -171,7 +171,7 @@ export default function BdstReg({ form }: { form: any }) { <FormUi label="위치"> <Input className={selectClass} - placeholder="1,000,000" + placeholder="" type="search" {...field} /> @@ -193,7 +193,7 @@ export default function BdstReg({ form }: { form: any }) { onSelectValue={(val) => { field.onChange(Number(val)); }} - value={field.value} + value={field.value??code.bdstUsgCd[0]?.val} /> </FormUi> )} @@ -208,7 +208,7 @@ export default function BdstReg({ form }: { form: any }) { <DatePicker mode={"single"} field={{ - value: field.value || new Date(), + value: field.value?? new Date(), onChange: (date: Date | undefined) => field.onChange(date), }} selectClass={'w-full'} @@ -226,7 +226,7 @@ export default function BdstReg({ form }: { form: any }) { <Input className={selectClass} placeholder="1,000,000" - type="number" + type="text" onChange={(e) => { handleCommaNumberChange(e, field.onChange); }} @@ -250,7 +250,7 @@ export default function BdstReg({ form }: { form: any }) { onSelectValue={(val) => { field.onChange(val); }} - value={field.value} + value={field.value??code.yn[0]?.val } /> </FormUi> )} diff --git a/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx b/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx index df63b3520..a729b2533 100644 --- a/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx +++ b/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx @@ -55,8 +55,6 @@ export function PbnstBuseForm({ code, pbnst, demandCompList, - getpbnstInsertIndex, - appendRuseFclt, getDemandCompList, regDemandCompany, } = useWrStore((state) => state); @@ -65,7 +63,6 @@ export function PbnstBuseForm({ control: form.control, name: `items.${indexMng}.fcBizs`, }); - const [bizCycle, setBizCycle] = useState("1"); const [ppiSelectList, setPpiSelectList] = useState<[{ name: string; val: SelectDataType[] }]>(); @@ -499,7 +496,7 @@ export function PbnstBuseForm({ ) || [] ).map((field, index) => ( <div - key={`fcDemands-${indexMng}-${indexBiz}`} // 이게 핵심! + key={`fcDemands-${indexMng}-${indexBiz}=${index}`} // 이게 핵심! className="grid grid-cols-12 gap-4 mt-3" > <div key={index + "keySon1"} className="col-span-4"> @@ -664,6 +661,7 @@ export function PbnstBuseForm({ )} /> </div> + <br></br> </div> ))} </div> diff --git a/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx b/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx index 08f2b073e..fc4ed566e 100644 --- a/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx +++ b/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx @@ -46,28 +46,40 @@ export default function RainRegForm({ ]); const cleanRainData = (raw: any): z.infer<typeof rainZod> => { + const buildings = + raw?.reuseBuilding && raw.reuseBuilding.length > 0 + ? raw.reuseBuilding + : [{}]; return { ...raw, - frstArchPrmsnDt: new Date(raw?.frstArchPrmsnDt || null), + frstArchPrmsnDt: raw?.frstArchPrmsnDt + ? new Date(raw.frstArchPrmsnDt) + : new Date(), // raw?.frstArchPrmsnDt가 유효하지 않으면 현재 날짜로 초기화 archChgPrmsnDt: raw?.archChgPrmsnDt ? new Date(raw?.archChgPrmsnDt) : null, - reuseBuilding: (raw?.reuseBuilding || []).map((item: any) => ({ + reuseBuilding: buildings.map((item: any) => ({ ...item, - instlCmptnDt: new Date(item?.instlCmptnDt), + instlCmptnDt: item?.instlCmptnDt + ? new Date(item.instlCmptnDt) + : new Date(), // item?.instlCmptnDt가 유효하지 않으면 현재 날짜로 초기화 operMngCd: item?.operMngCd ?? "", // null → "" grntchBdstCertYr: typeof item?.grntchBdstCertYr === "string" ? item?.grntchBdstCertYr : "", // null → "" + instlCstSprtYn: item?.instlCstSprtYn ?? "Y", // null → "Y" + grntchBdstCertYn:item?.grntchBdstCertYn??"Y", rainyObj: { ...item?.rainyObj, + filtrTrtmfctYn: item?.rainyObj?.filtrTrtmfctYn ?? "Y", }, })), }; }; useEffect(() => { + if (grntchBdstCertYn === "N") { form.setValue("reuseBuilding.0.grntchBdstCertYr", ""); form.setValue("reuseBuilding.0.grntchBdstCertNo", ""); @@ -80,6 +92,9 @@ export default function RainRegForm({ } }, [grntchBdstCertYn, instlCstSprtYn, filtrTrtmfctYn]); + + + // form 값이 변경될 때마다 로그 출력 useEffect(() => { const subscription = form.watch((value) => { @@ -144,9 +159,8 @@ export default function RainRegForm({ 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), - + : new Date(), + onChange: (date: Date | undefined) => field.onChange(date), }} selectClass={"w-full"} readOnly={readonly} @@ -264,7 +278,8 @@ export default function RainRegForm({ if (!readonly) handleCommaNumberChange(e, field.onChange); }} value={formatCommaNumber(field.value)} - readOnly={filtrTrtmfctYn !== "Y"} + readOnly={readonly } + disabled={filtrTrtmfctYn !== "Y"} /> </FormUi> )} @@ -278,13 +293,12 @@ export default function RainRegForm({ <FormUi label="처리공정"> <Input className={selectClass} - placeholder="1,000,000" - type="" + placeholder="" + type="text" value={field.value ?? ""} - onChange={(e) => { - if (!readonly) handleCommaNumberChange(e, field.onChange); - }} - readOnly={filtrTrtmfctYn !== "Y"} + onChange={field.onChange} + readOnly={readonly } + disabled={filtrTrtmfctYn !== "Y"} /> </FormUi> )} diff --git a/apps/wr/components/ui/modal/chkgd/chkgdModal/chkgdModal.tsx b/apps/wr/components/ui/modal/chkgd/chkgdModal/chkgdModal.tsx index 9572d1228..4e3d61008 100644 --- a/apps/wr/components/ui/modal/chkgd/chkgdModal/chkgdModal.tsx +++ b/apps/wr/components/ui/modal/chkgd/chkgdModal/chkgdModal.tsx @@ -144,16 +144,16 @@ export default function ChkgdModal({ type, obj }: { type: string; obj: any }) { const average = { utztnUsgCd: "평균", edit: false, - grssClfgUswtr: total.grssClfgUswtr / onlyData.length, - combResdch: total.combResdch / onlyData.length, - trbt: total.trbt / onlyData.length, - bod: total.bod / onlyData.length, - smll: total.smll / onlyData.length, - crmty: total.crmty / onlyData.length, - tph: total.tph / onlyData.length, - tn: total.tn / onlyData.length, - ph: total.ph / onlyData.length, - clIonQnt: total.clIonQnt / onlyData.length, + grssClfgUswtr: (total.grssClfgUswtr / onlyData.length).toFixed(1), + combResdch: (total.combResdch / onlyData.length).toFixed(1), + trbt: (total.trbt / onlyData.length).toFixed(1), + bod: (total.bod / onlyData.length).toFixed(1), + smll: (total.smll / onlyData.length).toFixed(1), + crmty: (total.crmty / onlyData.length).toFixed(1), + tph: (total.tph / onlyData.length).toFixed(1), + tn: (total.tn / onlyData.length).toFixed(1), + ph: (total.ph / onlyData.length).toFixed(1), + clIonQnt: (total.clIonQnt / onlyData.length).toFixed(1), }; if (!resultPolution[nodeKey]) { diff --git a/apps/wr/components/ui/modal/fcltReg/bdstChgModal/bdstChgModal.tsx b/apps/wr/components/ui/modal/fcltReg/bdstChgModal/bdstChgModal.tsx index 03c257c59..0b071aa91 100644 --- a/apps/wr/components/ui/modal/fcltReg/bdstChgModal/bdstChgModal.tsx +++ b/apps/wr/components/ui/modal/fcltReg/bdstChgModal/bdstChgModal.tsx @@ -14,7 +14,6 @@ const {bdst,rain} = useWrStore((state) => { return state; }); const { bdstChgHeadList } = bdst; - console.log("chgBuilding", chgBuilding); return ( diff --git a/apps/wr/components/ui/modal/sttn/sttnDetailModal/coDatailModal.tsx b/apps/wr/components/ui/modal/sttn/sttnDetailModal/coDatailModal.tsx index edffcc71d..b7229a559 100644 --- a/apps/wr/components/ui/modal/sttn/sttnDetailModal/coDatailModal.tsx +++ b/apps/wr/components/ui/modal/sttn/sttnDetailModal/coDatailModal.tsx @@ -7,7 +7,7 @@ import { handleCommaNumberChange } from "@/components/lib/func/commom"; import { DatePicker, Form, FormField, FormUi, ScrollArea } from "@common/business_components/ui"; import { Button, Input } 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 type { z } from "zod"; @@ -33,8 +33,24 @@ export default function SttnDetailModal({ useEffect(() => { if (ldrmntZod) form.reset(formObj); - }, [formObj]); + + useEffect(() => { + const male = Number(form.watch("maleEmpCnt") ?? 0); + const female = Number(form.watch("fmaleEmpCnt") ?? 0); + const frgnrMale = Number(form.watch("frgnrMaleEmpCnt") ?? 0); + const frgnrFemale = Number(form.watch("frgnrFmaleEmpCnt") ?? 0); + + const total = male + female + frgnrMale + frgnrFemale; + + form.setValue("totalEmpCnt", total); + }, [ + form.watch("maleEmpCnt"), + form.watch("fmaleEmpCnt"), + form.watch("frgnrMaleEmpCnt"), + form.watch("frgnrFmaleEmpCnt"), + ]); + return ( <div> <ScrollArea className="h-[85vh]"> @@ -324,6 +340,7 @@ export default function SttnDetailModal({ handleCommaNumberChange(e, field.onChange); }} value={field.value ?? 0} + min={0} /> </FormUi> )} @@ -343,6 +360,7 @@ export default function SttnDetailModal({ field.onChange(e.target.value); }} value={field.value ?? 0} + min={0} /> </FormUi> )} @@ -362,6 +380,7 @@ export default function SttnDetailModal({ field.onChange(e.target.value); }} value={field.value ?? 0} + min={0} /> </FormUi> )} @@ -381,6 +400,7 @@ export default function SttnDetailModal({ field.onChange(e.target.value); }} value={field.value ?? 0} + min={0} /> </FormUi> )} @@ -400,6 +420,8 @@ export default function SttnDetailModal({ field.onChange(e.target.value); }} value={field.value ?? 0} + min={0} + readOnly={true} /> </FormUi> )} diff --git a/apps/wr/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable.tsx b/apps/wr/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable.tsx index 20db75f50..da6cacc9a 100644 --- a/apps/wr/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable.tsx +++ b/apps/wr/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable.tsx @@ -62,7 +62,7 @@ export default function RswtChkgdTable({ [makeTableData, handleRswtClick] ); useEffect(() => { - if (rswtChkgdn.rswtChkPolGuide.length > 0) + if (rswtChkgdn.rswtChkPolGuide?.length > 0) handleRswtClick(rswtChkgdn.rswtChkPolGuide[0]); }, [rswtChkgdn.rswtChkPolGuide]); diff --git a/apps/wr/public/sample_rainy.xlsx b/apps/wr/public/sample_rainy.xlsx index ee4b23edb..73a52d89c 100644 Binary files a/apps/wr/public/sample_rainy.xlsx and b/apps/wr/public/sample_rainy.xlsx differ diff --git a/packages/common/business_components/src/ui/excel/excelStyle.tsx b/packages/common/business_components/src/ui/excel/excelStyle.tsx index 3c8f8d219..221e1387c 100644 --- a/packages/common/business_components/src/ui/excel/excelStyle.tsx +++ b/packages/common/business_components/src/ui/excel/excelStyle.tsx @@ -53,7 +53,8 @@ export const excelArrayStyle = async (data: ArrayBuffer, range: SheetParameter[] if (item.data && item.data.length > 0) { const numCols = item.data[0]?.length || 0; const numRows = item.data.length; - const dataRange = workbook.activeSheet(index)?.sheet(index)?.range(`A1:${String.fromCharCode(65 + numCols - 1)}${numRows}`); + const lastColLetter = getExcelColumnLetter(numCols); + const dataRange = workbook.activeSheet(index)?.sheet(index)?.range(`A1:${lastColLetter}${numRows}`); dataRange?.style((styleQ) => { styleQ.verticalAlignment("center"); }); @@ -62,4 +63,60 @@ export const excelArrayStyle = async (data: ArrayBuffer, range: SheetParameter[] } makeExcelFile(workbook, fileNm) -} \ No newline at end of file +} + +export const excelStyleWithKoreanHeaders = async ( + data: ArrayBuffer, + range: string = "A1:V3", + fileNm: string, + headerMapping: { [key: string]: string }, + sampleData: any +) => { + const workbook = await XlsxPopulate.Workbook.fromData(data); + const sheet = workbook.activeSheet(); + + if (!sheet) { + throw new Error('워크시트를 찾을 수 없습니다.'); + } + + // 1. 영문 헤더를 한글로 교체 + const englishHeaders = Object.keys(sampleData); + englishHeaders.forEach((englishHeader, index) => { + const koreanHeader = headerMapping[englishHeader] || englishHeader; + const cellAddress = String.fromCharCode(65 + index) + '1'; // A1, B1, C1, ... + sheet.cell(cellAddress).value(koreanHeader); + }); + + // 2. 헤더 스타일 적용 + const headerCells = sheet.range(range); + headerCells?.style((styleQ) => { + makeCellStyle(styleQ); + }); + + // 3. 모든 데이터 셀에 세로 가운데 정렬 적용 + const numCols = englishHeaders.length; + const numRows = sheet.usedRange()?.endCell()?.rowNumber() || 1; + + if (numRows > 1) { + const dataRange = sheet.range(`A1:${String.fromCharCode(65 + numCols - 1)}${numRows}`); + dataRange?.style((styleQ) => { + styleQ.verticalAlignment("center"); + styleQ.borderEach({ style: "thin", color: { rgb: "CCCCCC" } }); + }); + } + + // 4. 파일 다운로드 + await makeExcelFile(workbook, fileNm); +}; + + +const getExcelColumnLetter = (colIndex: number): string => { + let letter = ''; + while (colIndex > 0) { + const mod = (colIndex - 1) % 26; + letter = String.fromCharCode(65 + mod) + letter; + colIndex = Math.floor((colIndex - 1) / 26); + } + return letter; + }; + diff --git a/packages/common/business_components/src/ui/excel/index.tsx b/packages/common/business_components/src/ui/excel/index.tsx index 96f3b3e5d..cbe77293b 100644 --- a/packages/common/business_components/src/ui/excel/index.tsx +++ b/packages/common/business_components/src/ui/excel/index.tsx @@ -1,5 +1,5 @@ import * as XLSX from 'xlsx'; -import { excelArrayStyle, excelStyle } from './excelStyle'; +import { excelArrayStyle, excelStyle, excelStyleWithKoreanHeaders } from './excelStyle'; type ExcelDownloadProps = { data: JSON | JSON[]; @@ -164,4 +164,38 @@ export const filePickedBlobArray = (oFile: ArrayBuffer, fileNm: string, sheetArr }); await excelArrayStyle(XLSX.write(wb, { bookType: "xlsx", type: "buffer" }), sheetArray, fileNm) }); -} \ No newline at end of file +} + +type ExcelDownloadWithHeaderProps = { + data: JSON | JSON[]; + fileName: string; + sheetNameArray: string[]; + headerRange?: string; + headerMapping: { [key: string]: string }; +} + +export const downloadExcelWithKoreanHeaders = async ({ + data, + fileName = new Date().getTime().toString() + '.xlsx', + sheetNameArray = ["Sheet1"], + headerRange = 'A1:V3', + headerMapping +}: ExcelDownloadWithHeaderProps) => { + + const dataArray = Array.isArray(data) ? data : [data]; + + if (dataArray.length === 0) { + throw new Error('데이터가 없습니다.'); + } + + // 1. 원본 데이터로 워크시트 생성 + const worksheet = XLSX.utils.json_to_sheet(dataArray); + const workbook = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(workbook, worksheet, sheetNameArray[0]); + + // 2. 워크북을 ArrayBuffer로 변환 + const buffer = XLSX.write(workbook, { bookType: "xlsx", type: "buffer" }); + + // 3. 헤더만 한글로 교체하는 커스텀 스타일 함수 호출 + await excelStyleWithKoreanHeaders(buffer, headerRange, fileName, headerMapping, dataArray[0]); +}; \ No newline at end of file diff --git a/packages/common/business_components/src/ui/file-upload/lib/file_upload.tsx b/packages/common/business_components/src/ui/file-upload/lib/file_upload.tsx index 96f150ee3..60bfdacfd 100644 --- a/packages/common/business_components/src/ui/file-upload/lib/file_upload.tsx +++ b/packages/common/business_components/src/ui/file-upload/lib/file_upload.tsx @@ -308,7 +308,6 @@ export const FileUploaderItem = forwardRef< {children} </div> <button - type="button" className={cn( "absolute", "!w-1/5 z-50", diff --git a/packages/common/business_components/src/ui/map/Gis.js b/packages/common/business_components/src/ui/map/Gis.js index 5b4344b57..f45fe4e12 100644 --- a/packages/common/business_components/src/ui/map/Gis.js +++ b/packages/common/business_components/src/ui/map/Gis.js @@ -223,7 +223,6 @@ function Gis({ isOpen , gisMaps, isSearchModalOpen, treeData = [], isSearch = fa {isSearch && ( <div className="absolute right-8 top-[305px] z-20"> <button - type="button" onClick={() => setIsSearchModalOpen(true)} className="overflow-hidden w-[40px] h-[40px] bg-white border border-[#9aa7b8] diff --git a/packages/common/business_components/src/ui/map/GisContent.js b/packages/common/business_components/src/ui/map/GisContent.js index a8ac408e8..a8595efb0 100644 --- a/packages/common/business_components/src/ui/map/GisContent.js +++ b/packages/common/business_components/src/ui/map/GisContent.js @@ -60,7 +60,6 @@ export default function GisContent({ edit = false, onFeatureSelect, isSearch, se {isSearch && ( <div className="absolute right-8 top-[254px] z-20"> <button - type="button" onClick={() => setIsSearchModalOpen(true)} className="overflow-hidden w-[40px] h-[40px] bg-white border border-[#9aa7b8] diff --git a/packages/common/business_components/src/ui/map/GisTab.js b/packages/common/business_components/src/ui/map/GisTab.js index 27dd36e2b..57d8a48e8 100644 --- a/packages/common/business_components/src/ui/map/GisTab.js +++ b/packages/common/business_components/src/ui/map/GisTab.js @@ -20,7 +20,6 @@ // <TabsTrigger value="layers" className="flex-1 h-10">레이어</TabsTrigger> // {/* {isSearch && ( // <button -// type="button" // onClick={() => setIsSearchModalOpen(true)} // className="h-10 w-10 flex items-center justify-center px-0" // > diff --git a/packages/common/business_components/src/ui/table/index.tsx b/packages/common/business_components/src/ui/table/index.tsx index a6c5cfdee..cd25bc8db 100644 --- a/packages/common/business_components/src/ui/table/index.tsx +++ b/packages/common/business_components/src/ui/table/index.tsx @@ -19,6 +19,8 @@ type UiTableProps = { resetPageNo?: boolean; children?: React.ReactNode | undefined; boldArray?: number[]; + resetSelection?: boolean; + index?:number; } type UiHeadProps = { @@ -28,9 +30,9 @@ type UiHeadProps = { visible?:boolean; } -export function UiTable({ tableData, headlist, pageSize, total, headName, children, cellClick, onPageChange, className = '', resetPageNo = false, boldArray = [] }: UiTableProps) { +export function UiTable({ tableData, headlist, pageSize, total, headName, children, cellClick, onPageChange, className = '', resetPageNo = false, boldArray = [], resetSelection = false, index=-1 }: UiTableProps) { const [cur, setCur] = useState<number>(1); - const [idx, setIdx] = useState<number>(-1); + const [idx, setIdx] = useState<number>(index); const [isCheck, seIsCheck] = useState<boolean>(false); @@ -41,6 +43,12 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr } }, [onPageChange, resetPageNo]); + useEffect(() => { + if (resetSelection) { + setIdx(-1); + } + }, [resetSelection]); + const handlePageChange = (page: number) => { setCur(page); onPageChange(page);