diff --git a/apps/wr/app/matMng/coMng/ldrmntCoSttn/page.tsx b/apps/wr/app/matMng/coMng/ldrmntCoSttn/page.tsx index d5861e173..e14b25b55 100644 --- a/apps/wr/app/matMng/coMng/ldrmntCoSttn/page.tsx +++ b/apps/wr/app/matMng/coMng/ldrmntCoSttn/page.tsx @@ -5,6 +5,7 @@ import { btnClass } from "@/app/store/common/code"; import { type customLdrmnt } from "@/app/store/matDmd/ldrmntCoSttn"; import { ldrmntHeadListExport } from "@/app/store/matDmd/ldrmntCoSttn/headList"; import { + confirmToast, excelDownload, getCity, tableData @@ -29,9 +30,10 @@ import ListDiv from "@common/business_components/ui/list_div"; import { Button } from "@common/components/ui"; import { useCallback, useEffect, useState } from "react"; import { Toaster } from "react-hot-toast"; +import { useTranslation } from "react-i18next"; export default function LdrmntCoSttn() { - const { code, ldrmnt, ldrmntInit, ldrmntSearch, ldrmntUpdate} = useWrStore( + const { code, ldrmnt, ldrmntInit, ldrmntSearch, ldrmntUpdate } = useWrStore( (state) => state ); const { ldrmntRes, excelList, ldrmntResCount } = ldrmnt; @@ -43,6 +45,7 @@ export default function LdrmntCoSttn() { const [searchTxt, setSearchTxt] = useState(); const [excelData, setExcelData] = useState(); const [resetPage, isResetPage] = useState(false); + const { t } = useTranslation('base'); // const [isExcelDownload, setIsExcelDownload] = useState(false); const excelClick = useCallback(() => { @@ -141,7 +144,7 @@ export default function LdrmntCoSttn() { setBdstTable(tbData); }, [ldrmntRes, code]); - + useEffect(() => { const transData = Array.isArray(excelList) ? excelList : [excelList]; const exData = tableData(transData, { code }); @@ -261,10 +264,17 @@ export default function LdrmntCoSttn() { setDetailModal({ ...detailModal, isOpen: !detailModal.isOpen }) }} bodyClass={"w-[40vw] max-w-none max-h-[calc(100%-70px)]"} - body={{ - await ldrmntUpdate(value) - setDetailModal({ ...detailModal, isOpen: false }) - ldrmntSearch(false, pageNation, '20', computeCityNm(), searchTxt || ""); + body={ { + // confirmToast(t('isUpdateMsg'), await ldrmntUpdate(value)) + // // await ldrmntUpdate(value) + // setDetailModal({ ...detailModal, isOpen: false }) + // ldrmntSearch(false, pageNation, '20', computeCityNm(), searchTxt || ""); + const handleConfirm = async () => { + await ldrmntUpdate(value); + setDetailModal({ ...detailModal, isOpen: false }); + ldrmntSearch(false, pageNation, '20', computeCityNm(), searchTxt || ""); + }; + confirmToast(t('isUpdateMsg'), handleConfirm); }} />} /> diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/htdflSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/htdflSttn/page.tsx index e7685ebbd..d8a1cef52 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/htdflSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/htdflSttn/page.tsx @@ -34,6 +34,8 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { excelHtdflSttnParsing } from "@/app/store/ruseFcltMng/fcltSttn/htdflSttn/excel"; import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan"; import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal"; +import toast, { Toaster } from "react-hot-toast"; +import { useTranslation } from "react-i18next"; export default function HtdflSttn() { const { code, htdflSttn, htdflSttnSearch, initHtdfl } = useWrStore( @@ -42,7 +44,8 @@ export default function HtdflSttn() { const { htdflSttnRes, htdflSttnResCount } = htdflSttn; const ref = useRef({} as ReturnType); - + const isDownloadTriggered = useRef(false); + const { t } = useTranslation('base'); const [pageNation, setPageNation] = useState(1); const [isChHead, setIsChHead] = useState(false); const [resetPage, isResetPage] = useState(false); @@ -59,12 +62,6 @@ export default function HtdflSttn() { }>({ isOpen: false, chBuilding: [] }); const [fcltNm, setFcltNm] = useState(""); - const excelClick = useCallback(() => { - // 최신 검색 조건 반영 - const con = getConValue(); - htdflSttnSearch(true, 1, String(htdflSttnResCount), String(con), fcltNm, code.cityCd, code.sggCd); - }, [htdflSttnSearch, objSearch, code.cityCd, code.sggCd, fcltNm, htdflSttnResCount]); - useEffect(() => { htdflSttnSearch(false, pageNation, "20", String(getConValue()), fcltNm, code.cityCd, code.sggCd); isResetPage(false) @@ -108,16 +105,27 @@ export default function HtdflSttn() { setDetailModal({ isOpen: true, data: bdstTable[index] }); } }; + + const excelClick = useCallback(() => { + isDownloadTriggered.current = true; + htdflSttnSearch(true, 1, String(htdflSttnResCount), String(getConValue()), fcltNm, code.cityCd, code.sggCd); + }, [htdflSttnSearch, objSearch, code.cityCd, code.sggCd, fcltNm, htdflSttnResCount]); + useEffect(() => { + if (!isDownloadTriggered.current) { + return; + } if (htdflSttn.excelList.length > 0) { - if (htdflSttn.excelList.length === 0) return; excelDownload( htdflSttn.excelList, "온배수시설 현황", "sample_htdflSttn.xlsx", "A1:R3" ); + } else { + toast.error(t('excelDownErrMsg')); } + isDownloadTriggered.current = false; }, [htdflSttn.excelList, code]); useEffect(() => { @@ -256,6 +264,7 @@ export default function HtdflSttn() { body={} /> + ); } diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx index 78c11660c..74ea41ce0 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rainSttn/page.tsx @@ -34,6 +34,8 @@ import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeCo import SttnDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/sttnDetailModal"; import BdstChgModal from "@/components/ui/modal/fcltReg/bdstChgModal/bdstChgModal"; import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal"; +import toast, { Toaster } from "react-hot-toast"; +import { useTranslation } from "react-i18next"; export default function RainSttn() { const { code, rainSttn, rainSttnSearch, rainSttnInit } = useWrStore( @@ -47,6 +49,7 @@ export default function RainSttn() { const [bdstTable, setBdstTable] = useState(); const [selectSgg, setSelectSgg] = useState() const [resetPage, isResetPage] = useState(false); + const isDownloadTriggered = useRef(false); const [objSearch, setObjSearch] = useState({ sgg: "", city: "" }); const [detailModal, setDetailModal] = useState<{ isOpen: boolean, data: customRainBdst | undefined }>({ data: undefined, isOpen: false }) const [bdstChgProps, setBdstChgProps] = useState<{ @@ -54,7 +57,7 @@ export default function RainSttn() { chBuilding: chgBuilding[]; }>({ isOpen: false, chBuilding: [] }); const [fcltNm, setFcltNm] = useState(""); - + const { t } = useTranslation('base'); const cellClick = (index: number | undefined, headId: string) => { if (headId !== 'chBuildingYn' && index !== undefined && bdstTable !== undefined) { setDetailModal({ isOpen: true, data: bdstTable[index] }) @@ -135,21 +138,25 @@ export default function RainSttn() { }, [pageNation]); useEffect(() => { + if (!isDownloadTriggered.current) { + return; + } if (rainSttn.excelList.length > 0) { - if (rainSttn.excelList.length === 0) return; excelDownload( rainSttn.excelList, "빗물재이용시설 현황", "sample_rainSttn.xlsx", "A1:W3" ); + } else { + toast.error(t('excelDownErrMsg')); } + isDownloadTriggered.current = false; }, [rainSttn.excelList]); const excelClick = useCallback(() => { - // 최신 검색 조건 반영 - const con = getConValue(); - rainSttnSearch(true, 1, String(rainSttnResCount), String(con), fcltNm, code.cityCd, code.sggCd); + isDownloadTriggered.current = true; + rainSttnSearch(true, 1, String(rainSttnResCount), String(getConValue()), fcltNm, code.cityCd, code.sggCd); }, [rainSttnSearch, objSearch, code.cityCd, code.sggCd, fcltNm, rainSttnResCount]); return ( @@ -276,6 +283,7 @@ export default function RainSttn() { }} /> + ); } diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/rswtSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/rswtSttn/page.tsx index edf1f6ac0..e28286add 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/rswtSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/rswtSttn/page.tsx @@ -31,6 +31,8 @@ import ListDiv from "@common/business_components/ui/list_div"; import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan"; import { Button, Label } from "@common/components/ui"; import { useCallback, useEffect, useRef, useState } from "react"; +import toast, { Toaster } from "react-hot-toast"; +import { useTranslation } from "react-i18next"; export default function RswtSttn() { const { code, rswtSttn, rswtSttnSearch, rswtSttnInit } = useWrStore( @@ -43,6 +45,7 @@ export default function RswtSttn() { const [resetPage, isResetPage] = useState(false); const ref = useRef({} as ReturnType); const [bdstTable, setBdstTable] = useState(); + const isDownloadTriggered = useRef(false); const [selectSgg, setSelectSgg] = useState() const [objSearch, setObjSearch] = useState({ sgg: "", city: "" }); const [detailModal, setDetailModal] = useState<{ isOpen: boolean, data: customRswtBdst | undefined }>({ data: undefined, isOpen: false }) @@ -51,7 +54,7 @@ export default function RswtSttn() { chBuilding: chgBuilding[]; }>({ isOpen: false, chBuilding: [] }); const [fcltNm, setFcltNm] = useState(""); - + const { t } = useTranslation('base'); const cellClick = (index: number | undefined, headId: string) => { if (headId !== 'chBuildingYn' && index !== undefined && bdstTable !== undefined) { @@ -124,22 +127,25 @@ export default function RswtSttn() { }, [code, rswtSttnRes]); useEffect(() => { + if (!isDownloadTriggered.current) { + return; + } if (rswtSttn.excelList.length > 0) { - if (rswtSttn.excelList.length === 0) return; excelDownload( rswtSttn.excelList, "중수도시설 현황", "sample_rswtSttn.xlsx", "A1:W3", ); + } else { + toast.error(t('excelDownErrMsg')); } + isDownloadTriggered.current = false; }, [rswtSttn.excelList]); const excelClick = useCallback(() => { - // 최신 검색 조건 반영 - const con = getConValue(); - - rswtSttnSearch(true, 1, String(rswtSttnResCount), String(con), fcltNm, code.cityCd, code.sggCd); + isDownloadTriggered.current = true; + rswtSttnSearch(true, 1, String(rswtSttnResCount), String(getConValue()), fcltNm, code.cityCd, code.sggCd); }, [rswtSttnSearch, objSearch, code.cityCd, code.sggCd, fcltNm, rswtSttnResCount]); useEffect(() => { @@ -276,6 +282,7 @@ export default function RswtSttn() { }} /> + ); } diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx index ecd2fd0f6..cb3f2f9ef 100644 --- a/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncReg/chkgdnReg/page.tsx @@ -11,6 +11,7 @@ import { type rswtrChkDetailsZodType, } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn"; import { + confirmToast, excelArrayDownload, excelDownload, yearOptions, @@ -39,6 +40,7 @@ import { } from "@common/components/ui/tooltip"; import { useCallback, useEffect, useState } from "react"; import toast, { Toaster } from "react-hot-toast"; +import { useTranslation } from "react-i18next"; export default function Page() { const { @@ -201,12 +203,19 @@ export default function Page() { } }, [rainChkgdn.isSttn, rswtChkgdn.isSttn]); + const { t } = useTranslation('base'); const clickDelete = (data: number[], selFcltDiv: string) => { if (data.length > 0) { if (selFcltDiv === "RNB") { - rainChkDelete(data, searchYear); + const handleConfirm = async () => { + rainChkDelete(data, searchYear); + }; + confirmToast(t('isDeleteMsg'), handleConfirm); } else { - rswtChkDelete(data, searchYear); + const handleConfirm = async () => { + rswtChkDelete(data, searchYear); + }; + confirmToast(t('isDeleteMsg'), handleConfirm); } } }; diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx index 5ea418634..b8d486a32 100644 --- a/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx @@ -1,7 +1,7 @@ "use client"; import { useWrStore } from "@/app/store"; import type { pubHasuType } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type"; -import { excelDownload, yearOptions } from "@/components/lib/func/commom"; +import { confirmToast, excelDownload, yearOptions } from "@/components/lib/func/commom"; import PbnPrfExcelModal from "@/components/ui/modal/chkgd/pbnPrfExcelModal/pbnPrfExcelModal"; import { ContentsDiv, @@ -37,12 +37,13 @@ import { type PrfType, } from "@/app/store/prfmncReg/pbnstPrfmncReg/type"; import { excelToPbnPrfData } from "@/app/store/prfmncReg/pbnstPrfmncReg/excel"; +import { useTranslation } from "react-i18next"; export default function prfmncPrfmncReg() { - const { code, prfmnc, prfmncHasuInit, prfmnRegData,prfmncHasuNmSearch } = useWrStore( + const { code, prfmnc, prfmncHasuInit, prfmnRegData, prfmncHasuNmSearch } = useWrStore( (state) => state ); - const { pbnstPrfmncHeadList, monthHeadList, prfmncRes,prfmncResCount } = prfmnc; + const { pbnstPrfmncHeadList, monthHeadList, prfmncRes, prfmncResCount } = prfmnc; const [bdstTable, setbdstTable] = useState(); const [searchTxt, setSearchTxt] = useState(); const [isExcelOpen, setIsExcelOPen] = useState<{ @@ -65,20 +66,40 @@ export default function prfmncPrfmncReg() { "A1:O1" ); }, [prfmnc.excelList]); + /* + const onSave = useCallback( + async() => { + if (pbnstRuseFcltPk) { + await prfmnRegData(pageNation,'41', + excelToPbnPrfData( + inputData as unknown as JSON[], + searchYear, + pbnstRuseFcltPk + ) as unknown as PrfType + ); + // cellClick(cellNum) + } + }, [inputData, searchYear, pbnstRuseFcltPk, pageNation,cellNum]);*/ - const onSave = useCallback( - async() => { - if (pbnstRuseFcltPk) { - await prfmnRegData(pageNation,'41', + const { t } = useTranslation('base'); + const onSave = useCallback(() => { + const handleConfirm = async () => { + if (!pbnstRuseFcltPk) return; + + prfmnRegData( + pageNation, + '41', excelToPbnPrfData( inputData as unknown as JSON[], searchYear, pbnstRuseFcltPk - ) as unknown as PrfType + ) as unknown as PrfType, + searchYear ); - // cellClick(cellNum) - } - }, [inputData, searchYear, pbnstRuseFcltPk, pageNation,cellNum]); + }; + + confirmToast(t('isUpdateMsg'), handleConfirm); + }, [inputData, searchYear, pbnstRuseFcltPk, pageNation, cellNum]); const cellClick = useCallback( (index: number | undefined) => { @@ -165,13 +186,13 @@ export default function prfmncPrfmncReg() { useEffect(() => { if (!prfmnc.isInit) { const year = new Date().getFullYear() - prfmncHasuInit(1, "41",String(year)); + prfmncHasuInit(1, "41", String(year)); } }, [prfmnc.isInit, prfmncHasuInit]); useEffect(() => { - if(prfmncRes&&prfmncRes.length>0){ + if (prfmncRes && prfmncRes.length > 0) { setbdstTable(prfmncRes); } @@ -224,14 +245,14 @@ export default function prfmncPrfmncReg() {
@@ -282,8 +303,8 @@ export default function prfmncPrfmncReg() { setCellNum(index ?? 0); }} onPageChange={ - (page) =>{ - prfmncHasuInit(page, "41",searchYear); + (page) => { + prfmncHasuInit(page, "41", searchYear); setPageNation(page) }} children={undefined} @@ -303,7 +324,7 @@ export default function prfmncPrfmncReg() { {headMakeprfmnc(monthHeadList, [])} - + {InputTableBody(inputData ?? [], monthHeadList, setInputData)} @@ -319,14 +340,14 @@ export default function prfmncPrfmncReg() { setIsExcelOPen={(open) => { setIsExcelOPen({ ...isExcelOpen, isModal: open }) }} - setModalExcelData={ async(excelData ) =>{ - await prfmnRegData(pageNation,'41', + setModalExcelData={async (excelData) => { + await prfmnRegData(pageNation, '41', excelData, searchYear ); // 데이터 저장 후 UI 업데이트는 useEffect가 감지하여 처리하므로 여기서는 호출하지 않습니다. } - } + } > } open={isExcelOpen.isModal} diff --git a/apps/wr/app/ruseFcltMng/prfmncSttn/chkgdnSttn/page.tsx b/apps/wr/app/ruseFcltMng/prfmncSttn/chkgdnSttn/page.tsx index a191de9ee..6f1bd97f5 100644 --- a/apps/wr/app/ruseFcltMng/prfmncSttn/chkgdnSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncSttn/chkgdnSttn/page.tsx @@ -23,7 +23,8 @@ import { 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 toast, { Toaster } from "react-hot-toast"; +import { useTranslation } from "react-i18next"; export default function Page() { const { @@ -97,7 +98,6 @@ export default function Page() { useEffect(() => { if (!rainChkSttn.isInit) { isRainSttn(true) - console.log("여기", rainPageSize) rainChkSttnInit(1, rainPageSize, new Date().getFullYear().toString(), commonCd); setIsModal({ data: {}, open: false }); } @@ -119,8 +119,13 @@ export default function Page() { }, [isModal] ); + const { t } = useTranslation('base'); const excelDown = () => { if (rainChkSttn.sttnExcelList && selFcltDiv === "RNB") { + if (!rainChkSttn.sttnExcelList || rainChkSttn.sttnExcelList.length === 0) { + toast.error(t('excelDownErrMsg')); + return; + } excelDownload( rainChkSttn.sttnExcelList, "빗물이용시설 지도점검 현황", @@ -129,6 +134,10 @@ export default function Page() { 3 ); } else if (rswtChkSttn.sttnExcelList && selFcltDiv === "RST") { + if (!rswtChkSttn.sttnExcelList || rswtChkSttn.sttnExcelList.length === 0) { + toast.error(t('excelDownErrMsg')); + return; + } excelDownload( rswtChkSttn.sttnExcelList, "중수도시설 지도점검 현황", diff --git a/apps/wr/app/ruseFcltMng/prfmncSttn/pbnstPrfmncSttn/page.tsx b/apps/wr/app/ruseFcltMng/prfmncSttn/pbnstPrfmncSttn/page.tsx index c60ba1673..731ea1511 100644 --- a/apps/wr/app/ruseFcltMng/prfmncSttn/pbnstPrfmncSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncSttn/pbnstPrfmncSttn/page.tsx @@ -11,6 +11,7 @@ import ListDiv from "@common/business_components/ui/list_div"; import { Button, Label } from "@common/components/ui"; import { useCallback, useEffect, useRef, useState } from "react"; import toast, { Toaster } from "react-hot-toast"; +import { useTranslation } from "react-i18next"; export default function PbnstPrfmncSttn() { const { @@ -33,12 +34,16 @@ export default function PbnstPrfmncSttn() { const ref = useRef({} as ReturnType); const [swtrmtFcltNm, setSwtrmtFcltNm] = useState(); const [pbnRuseNm, setPbnRuseNm] = useState(""); - + const { t } = useTranslation('base'); const [searchYear, setSearchYear] = useState( String(new Date().getFullYear()) ); const [excelData, setExcelData] = useState([]); const excelClick = useCallback(() => { + if (!excelData || excelData.length === 0) { + toast.error(t('excelDownErrMsg')); + return; + } excelDownload( excelData, "하수재이용실적 현황", @@ -524,14 +529,7 @@ export default function PbnstPrfmncSttn() { selectUnitWaterShedData={code.lgbsnCd} selectMiddleRegionData={code.mdmbsnCd} selectEnvPartData={code.lclgvrnmntCd} - rightChildren={} + rightChildren={undefined} leftChildren={
diff --git a/apps/wr/components/lib/func/TableData.tsx b/apps/wr/components/lib/func/TableData.tsx index 8bed17187..2046bd15e 100644 --- a/apps/wr/components/lib/func/TableData.tsx +++ b/apps/wr/components/lib/func/TableData.tsx @@ -57,7 +57,7 @@ export const rswtChkTableData = (chkData: rswtChkZodType[]) => { const makeRswtData: any[] = []; - if(chkData&&chkData.length>0){ + if (chkData && chkData.length > 0) { chkData?.forEach((root) => { root.rswtrDetails.forEach((detail) => { @@ -99,10 +99,11 @@ export const chRowspanTable = ( let order = 0 // rowspan된 셀 렌더링 여부 추적용 const renderedMap = new Map>(); - + return ( <> - {makeTableData.map((row, rowIndex) => ( + {/* {makeTableData.map((row, rowIndex) => ( */} + {makeTableData && makeTableData.length > 0 ? (makeTableData.map((row, rowIndex) => ( {headList .map((head) => { @@ -177,7 +178,13 @@ export const chRowspanTable = ( })} - ))} + ))) : ( + + + 조회된 결과가 없습니다. + + + )} ); }; @@ -235,44 +242,44 @@ export const InputTableBody = ( } return span; }; - return ( + return ( <> {chgRes.map((data, dataIndex) => { // 소계/총합계 행 판별 const isSubTotal = data["용수명"] === "소계"; const isTotal = data["구분"] === 0; - + const bgClass = isTotal ? "bg-[#d5e1eb] font-bold" : isSubTotal - ? "bg-[#e6eef5] font-semibold" - : ""; + ? "bg-[#e6eef5] font-semibold" + : ""; return ( {headList.map((head, headIndex) => { - // 총합계 행이면 "구분"에서 colSpan=2로 병합 - if ( - data["구분"] === 0 && - head.id === "구분" - ) { - return ( - - 총합계 - - ); - } - // 총합계(합계) 행이면 "용수명" 컬럼은 렌더링하지 않음 - if ( - data["구분"] === 0 && - head.id === "용수명" - ) { - return null; - } + // 총합계 행이면 "구분"에서 colSpan=2로 병합 + if ( + data["구분"] === 0 && + head.id === "구분" + ) { + return ( + + 총합계 + + ); + } + // 총합계(합계) 행이면 "용수명" 컬럼은 렌더링하지 않음 + if ( + data["구분"] === 0 && + head.id === "용수명" + ) { + return null; + } // mergeCell 처리 if (head.mergeCell) { const rowSpan = getRowSpan(chgRes, head.id, dataIndex); diff --git a/apps/wr/components/lib/func/commom.tsx b/apps/wr/components/lib/func/commom.tsx index 7d8c2ffcc..6d96b3540 100644 --- a/apps/wr/components/lib/func/commom.tsx +++ b/apps/wr/components/lib/func/commom.tsx @@ -6,24 +6,26 @@ import { filePickedBlobArray, type SheetParameter, } from "@common/business_components/ui"; +import { Button } from "@common/components/ui"; import type { RefObject } from "react"; +import toast from "react-hot-toast"; export const getCity = (val: string, sggCd: SelectDataType[]) => { - let data:any - if(val !=='0'){ + let data: any + if (val !== '0') { data = sggCd - .filter((item) => String(item.val).substring(0, 2) === val) - .map((item) => ({ - val: item.val, - text: item.text, // 한국어 텍스트 - })); - }else{ + .filter((item) => String(item.val).substring(0, 2) === val) + .map((item) => ({ + val: item.val, + text: item.text, // 한국어 텍스트 + })); + } else { data = sggCd - .map((item) => ({ - val: item.val, - text: item.text, // 한국어 텍스트 - })); + .map((item) => ({ + val: item.val, + text: item.text, // 한국어 텍스트 + })); } data.unshift({ val: "0", text: "전체" }); return data; @@ -92,7 +94,7 @@ export const excelDownload = ( export const excelArrayDownload = ( fileNm: string, sampleFile: string, - sheetArray:SheetParameter [] + sheetArray: SheetParameter[] ) => { if (!sheetArray) return; fetch(`/${sampleFile}`, {}).then(async (response) => { @@ -113,7 +115,7 @@ export const handleCommaNumberChange = ( ) => { const raw = e.target.value.replace(/,/g, ""); if (!/^\d*$/.test(raw)) return; - onChange(raw === "" ? "" : Number(raw)); + onChange(raw === "" ? "" : Number(raw)); }; @@ -124,7 +126,7 @@ export const handleMinusNumberChange = ( ) => { const raw = e.target.value.replace(/,/g, ""); if (!/^\d*$/.test(raw)) return; - onChange(raw === "" ? -1 : Number(raw)); + onChange(raw === "" ? -1 : Number(raw)); }; // 숫자입력시 , 삽입 @@ -175,14 +177,14 @@ export const getdmdMatFlag = (flag: string | undefined | null) => { case "Matched": return "매칭완료"; case "Checked": - return '검토완료'; + return '검토완료'; default: return "신청"; } }; -export const formatPhoneNumber=(tel:string) => { +export const formatPhoneNumber = (tel: string) => { const onlyNums = tel.replace(/[^0-9]/g, ''); if (onlyNums.length === 10) { return onlyNums.replace(/(\d{2})(\d{4})(\d{4})/, '$1-$2-$3'); @@ -191,4 +193,32 @@ export const formatPhoneNumber=(tel:string) => { } else { return tel; // 유효하지 않으면 빈 문자열 } +} + +export const confirmToast = (content: string, saveFunc: () => void) => { + toast((t) => ( + +
+ {content} +
+
+ + +
+
+ ), + { + id: "global-confirm-toast", // 중복 토스트 방지 + duration: Infinity, // 자동 사라짐 방지 + }); } \ No newline at end of file diff --git a/apps/wr/components/ui/form/fcltReg/htdflReg/htdflRegForm.tsx b/apps/wr/components/ui/form/fcltReg/htdflReg/htdflRegForm.tsx index 7e92301b8..85bb67044 100644 --- a/apps/wr/components/ui/form/fcltReg/htdflReg/htdflRegForm.tsx +++ b/apps/wr/components/ui/form/fcltReg/htdflReg/htdflRegForm.tsx @@ -19,11 +19,13 @@ import { import { useEffect, useState } from "react"; import BdstReg from "../bdstReg/bdstReg"; import { + confirmToast, formatCommaNumber, handleCommaNumberChange, } from "@/components/lib/func/commom"; import { formH1Class } from "@/components/lib/class/comClass"; import toast from "react-hot-toast"; +import { useTranslation } from "react-i18next"; export default function HtdflRegForm({ htdflForm, @@ -48,20 +50,25 @@ export default function HtdflRegForm({ const bdstNm = form.watch("bdstNm"); const isPowerPlant = bdstNm?.includes("발전소"); - + const { t } = useTranslation('base'); const onSubmit = (values: z.infer) => { if (isModal) { const data = regCtpvCd ? regCtpvCd : regSggcd ? regSggcd : "noCd"; - if (data === "noCd") { toast.error("시도/시군구 코드를 선택해야합니다."); return; } - htdflBdstReg(values, data); - if (setIsModal) setIsModal(false); + const handleConfirm = async () => { + htdflBdstReg(values, data); + if (setIsModal) setIsModal(false); + }; + confirmToast(t('isInsertMsg'), handleConfirm); } else { + const handleConfirm = async () => { + htdflBdstUpdate(values, "0"); + }; + confirmToast(t('isUpdateMsg'), handleConfirm); - htdflBdstUpdate(values, "0"); } }; @@ -90,15 +97,15 @@ export default function HtdflRegForm({ }; }; const [divStyle, setDivStyle] = useState("h-[53vh]"); - useEffect(()=>{ - if(isModal===true){ + useEffect(() => { + if (isModal === true) { setDivStyle("h-[53vh] max-h-[37vh]") - }else if(readonly===true){ + } else if (readonly === true) { setDivStyle("h-[62vh]") - }else{ + } else { setDivStyle("h-[53vh]") } - },[isModal,readonly]); + }, [isModal, readonly]); useEffect(() => { console.log("form errors:", form.formState.errors); diff --git a/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx b/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx index bb62fee61..a454f69c8 100644 --- a/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx +++ b/apps/wr/components/ui/form/fcltReg/rainReg/rainRegForm.tsx @@ -8,6 +8,7 @@ import { } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import { formH1Class, formH2Class } from "@/components/lib/class/comClass"; import { + confirmToast, formatCommaNumber, handleMinusNumberChange, } from "@/components/lib/func/commom"; @@ -21,6 +22,7 @@ import { z } from "zod"; import BdstReg from "../bdstReg/bdstReg"; import toast from "react-hot-toast"; import BdstAdd from "../bdstReg/bdstAdd"; +import { useTranslation } from "react-i18next"; export default function RainRegForm({ rainForm, @@ -40,9 +42,10 @@ export default function RainRegForm({ const defaultValues: z.infer = rainZod.parse({}); const form = useForm>({ resolver: zodResolver(rainZod), - // defaultValues: defaultValues, + // defaultValues: defaultValues, }); const instlCst = form.watch(`reuseBuilding.0.instlCst`); + const { t } = useTranslation('base'); const [grntchBdstCertYn, instlCstSprtYn, filtrTrtmfctYn] = form.watch([ "reuseBuilding.0.grntchBdstCertYn", @@ -51,15 +54,15 @@ export default function RainRegForm({ ]); const [divStyle, setDivStyle] = useState("h-[53vh]"); - useEffect(()=>{ - if(isModal===true){ + useEffect(() => { + if (isModal === true) { setDivStyle("h-[53vh] max-h-[37vh]") - }else if(readonly===true){ + } else if (readonly === true) { setDivStyle("h-[62vh]") - }else{ + } else { setDivStyle("h-[53vh]") } - },[isModal,readonly]); + }, [isModal, readonly]); const cleanRainData = (raw: any): z.infer => { const buildings = @@ -122,7 +125,7 @@ export default function RainRegForm({ // form 값이 변경될 때마다 로그 출력 useEffect(() => { - const subscription = form.watch((value) => {}); + const subscription = form.watch((value) => { }); return () => subscription.unsubscribe(); }, [form]); @@ -139,10 +142,16 @@ export default function RainRegForm({ return; } - rainBdstReg(values, data); - if (setIsModal) setIsModal(false); + const handleConfirm = async () => { + rainBdstReg(values, data); + if (setIsModal) setIsModal(false); + }; + confirmToast(t('isInsertMsg'), handleConfirm); } else { - rainBdstUpdate(values, "41"); + const handleConfirm = async () => { + rainBdstUpdate(values, "41"); + }; + confirmToast(t('isUpdateMsg'), handleConfirm); } }; @@ -174,150 +183,97 @@ export default function RainRegForm({
- {isModal && rainForm != undefined ? : <>} - {isModal ? ( -

- 빗물이용시설 정보{" "} -

- ) : ( - <> - )} -

기본정보

-
-
- ( - - - field.onChange(date), - }} - selectClass={"w-full"} - readOnly={readonly} - /> - - )} - /> -
+ {isModal && rainForm != undefined ? : <>} + {isModal ? ( +

+ 빗물이용시설 정보{" "} +

+ ) : ( + <> + )} +

기본정보

+
+
+ ( + + + field.onChange(date), + }} + selectClass={"w-full"} + readOnly={readonly} + /> + + )} + /> +
-
- { - const value = field.value; - const isUnknown = value === null || value === -1; // 또는 Number(value) === -1 - return ( - - { - // 입력 시 자동으로 확인불가 해제 - if (isUnknown && !readonly) { - field.onChange(""); // 초기화 +
+ { + const value = field.value; + const isUnknown = value === null || value === -1; // 또는 Number(value) === -1 + return ( + + { - if (readonly) return; - handleMinusNumberChange(e, field.onChange); - }} - /> - - ); - }} - /> + onFocus={() => { + // 입력 시 자동으로 확인불가 해제 + if (isUnknown && !readonly) { + field.onChange(""); // 초기화 + } + }} + onChange={(e) => { + if (readonly) return; + handleMinusNumberChange(e, field.onChange); + }} + /> + + ); + }} + /> +
-
-
-

빗물이용시설 정보

-
-
-

집수면 및 저류조

-
-
-
- { - const isUnknown = field.value === null || field.value === -1; // 또는 Number(value) === -1 - return ( - - { - // 입력 시 자동으로 확인불가 해제 - if (isUnknown && !readonly) { - field.onChange(""); // 초기화 - } - }} - onChange={(e) => { - if (readonly) return; - handleMinusNumberChange(e, field.onChange); - }} - readOnly={readonly} - /> - - ); - }} - /> +
+

빗물이용시설 정보

-
- ( - - {} : field.onChange} - value={field.value ?? rainFcltCd[0]?.val} - readOnly={readonly} - /> - - )} - /> +
+

집수면 및 저류조

-
- { - const value = field.value; - const isUnknown = value === null || value === -1; // 또는 Number(value) === -1 - return ( -
- +
+
+ { + const isUnknown = field.value === null || field.value === -1; // 또는 Number(value) === -1 + return ( + { // 입력 시 자동으로 확인불가 해제 @@ -332,274 +288,327 @@ export default function RainRegForm({ readOnly={readonly} /> -
- ); - }} - /> -
-
- -
-

여과 등 처리시설

-
-
-
- ( - - {} : field.onChange} - value={field.value ?? code.yn[0]?.val} - readOnly={readonly} - /> - - )} - /> -
-
- { - const isUnknown = field.value === null || field.value === -1; // 또는 Number(value) === -1 - return ( - - { - // 입력 시 자동으로 확인불가 해제 - if (isUnknown && !readonly) { - field.onChange(""); // 초기화 - } - }} - onChange={(e) => { - if (readonly) return; - handleMinusNumberChange(e, field.onChange); - }} + ); + }} + /> +
+
+ ( + + { } : field.onChange} + value={field.value ?? rainFcltCd[0]?.val} readOnly={readonly} - disabled={filtrTrtmfctYn !== "Y"} /> - ); - }} - /> + )} + /> +
+
+ { + const value = field.value; + const isUnknown = value === null || value === -1; // 또는 Number(value) === -1 + return ( +
+ + { + // 입력 시 자동으로 확인불가 해제 + if (isUnknown && !readonly) { + field.onChange(""); // 초기화 + } + }} + onChange={(e) => { + if (readonly) return; + handleMinusNumberChange(e, field.onChange); + }} + readOnly={readonly} + /> + +
+ ); + }} + /> +
-
- { - const value = field.value; - const isUnknown = value === null || value === "-"; // 또는 Number(value) === -1 - return ( -
- +
+

여과 등 처리시설

+
+
+
+ ( + + { } : field.onChange} + value={field.value ?? code.yn[0]?.val} + readOnly={readonly} + /> + + )} + /> +
+
+ { + const isUnknown = field.value === null || field.value === -1; // 또는 Number(value) === -1 + return ( + { + // 입력 시 자동으로 확인불가 해제 + if (isUnknown && !readonly) { + field.onChange(""); // 초기화 + } + }} + onChange={(e) => { + if (readonly) return; + handleMinusNumberChange(e, field.onChange); + }} readOnly={readonly} disabled={filtrTrtmfctYn !== "Y"} /> -
- ); - }} - /> -
-
-
-

인센티브 정보

-
-
-

설치비 지원

-
-
-
- ( - - {} : field.onChange} - value={field.value ?? code.yn[0]?.val} - readOnly={readonly} - /> - - )} - /> -
-
- { - const value = field.value; - const isUnknown = value === null || value === -1; // 또는 Number(value) === -1 - return ( - - { - // 입력 시 자동으로 확인불가 해제 - if (isUnknown && !readonly) { - field.onChange(""); // 초기화 - } - }} - onChange={(e) => { - if (readonly) return; - handleMinusNumberChange(e, field.onChange); - }} - disabled={instlCstSprtYn !== "Y"} - /> - - ); - }} - /> -
-
-
-

녹색건축물 인증

-
-
-
- ( - - {} : field.onChange} - value={field.value ?? code.yn[0]?.val} - /> - - )} - /> -
-
- { - const isUnknown = - field.value === null || field.value === "0000"; // 또는 Number(value) === -1 - return ( - - { - // 입력 시 자동으로 확인불가 해제 - if (isUnknown && !readonly) { - field.onChange(""); // 초기화 - } - }} - value={isUnknown ? "확인불가" : (field.value ?? "")} - onChange={(e) => { - if (readonly) return; - if (e.target.value === "확인불가") { - field.onChange("0000"); - } else { - field.onChange(e.target.value); - } - }} - disabled={grntchBdstCertYn !== "Y"} - max={4} - /> - - ); - }} - /> -
-
- { - const isUnknown = - field.value === null || field.value === "0000"; // 또는 Number(value) === -1 - return ( - - { - // 입력 시 자동으로 확인불가 해제 - if (isUnknown && !readonly) { - field.onChange(""); // 초기화 - } - }} - value={isUnknown ? "확인불가" : (field.value ?? "")} - onChange={(e) => { - if (readonly) return; + ); + }} + /> +
+
+ { + const value = field.value; + const isUnknown = value === null || value === "-"; // 또는 Number(value) === -1 - if (e.target.value === "확인불가") { - field.onChange(""); - } else { - field.onChange(e.target.value); - } - }} - disabled={grntchBdstCertYn !== "Y"} + return ( +
+ + + +
+ ); + }} + /> +
+
+
+

인센티브 정보

+
+
+

설치비 지원

+
+
+
+ ( + + { } : field.onChange} + value={field.value ?? code.yn[0]?.val} + readOnly={readonly} /> - ); - }} - /> + )} + /> +
+
+ { + const value = field.value; + const isUnknown = value === null || value === -1; // 또는 Number(value) === -1 + return ( + + { + // 입력 시 자동으로 확인불가 해제 + if (isUnknown && !readonly) { + field.onChange(""); // 초기화 + } + }} + onChange={(e) => { + if (readonly) return; + handleMinusNumberChange(e, field.onChange); + }} + disabled={instlCstSprtYn !== "Y"} + /> + + ); + }} + /> +
-
- ( - - {} : field.onChange} - value={field.value ?? code.bdstGrntchClass[0]?.val} - readOnly={readonly} - /> - - )} - /> +
+

녹색건축물 인증

-
- +
+
+ ( + + { } : field.onChange} + value={field.value ?? code.yn[0]?.val} + /> + + )} + /> +
+
+ { + const isUnknown = + field.value === null || field.value === "0000"; // 또는 Number(value) === -1 + return ( + + { + // 입력 시 자동으로 확인불가 해제 + if (isUnknown && !readonly) { + field.onChange(""); // 초기화 + } + }} + value={isUnknown ? "확인불가" : (field.value ?? "")} + onChange={(e) => { + if (readonly) return; + if (e.target.value === "확인불가") { + field.onChange("0000"); + } else { + field.onChange(e.target.value); + } + }} + disabled={grntchBdstCertYn !== "Y"} + max={4} + /> + + ); + }} + /> +
+
+ { + const isUnknown = + field.value === null || field.value === "0000"; // 또는 Number(value) === -1 + return ( + + { + // 입력 시 자동으로 확인불가 해제 + if (isUnknown && !readonly) { + field.onChange(""); // 초기화 + } + }} + value={isUnknown ? "확인불가" : (field.value ?? "")} + onChange={(e) => { + if (readonly) return; + + if (e.target.value === "확인불가") { + field.onChange(""); + } else { + field.onChange(e.target.value); + } + }} + disabled={grntchBdstCertYn !== "Y"} + /> + + ); + }} + /> +
+
+ ( + + { } : field.onChange} + value={field.value ?? code.bdstGrntchClass[0]?.val} + readOnly={readonly} + /> + + )} + /> +
+
+ diff --git a/apps/wr/components/ui/form/fcltReg/rswtrReg/rswtrRegForm.tsx b/apps/wr/components/ui/form/fcltReg/rswtrReg/rswtrRegForm.tsx index a3d849b29..34765ae9a 100644 --- a/apps/wr/components/ui/form/fcltReg/rswtrReg/rswtrRegForm.tsx +++ b/apps/wr/components/ui/form/fcltReg/rswtrReg/rswtrRegForm.tsx @@ -8,6 +8,7 @@ import { } from "@/app/store/ruseFcltMng/fcltReg/rswtReg"; import { formH1Class, formH2Class } from "@/components/lib/class/comClass"; import { + confirmToast, formatCommaNumber, handleMinusNumberChange } from "@/components/lib/func/commom"; @@ -25,6 +26,7 @@ import { useForm } from "react-hook-form"; import { z } from "zod"; import BdstAdd from "../bdstReg/bdstAdd"; import BdstReg from "../bdstReg/bdstReg"; +import { useTranslation } from "react-i18next"; export default function RswtrRegForm({ rswtForm, @@ -41,20 +43,20 @@ export default function RswtrRegForm({ (state) => state ); const [divStyle, setDivStyle] = useState("h-[53vh]"); - useEffect(()=>{ - if(isModal===true){ + useEffect(() => { + if (isModal === true) { setDivStyle("h-[53vh] max-h-[37vh]") - }else if(readonly===true){ + } else if (readonly === true) { setDivStyle("h-[62vh]") - }else{ + } else { setDivStyle("h-[53vh]") } - },[isModal,readonly]); - // const defaultValues: z.infer = rswtZod.parse({}); + }, [isModal, readonly]); + // const defaultValues: z.infer = rswtZod.parse({}); const form = useForm>({ resolver: zodResolver(rswtZod), - // defaultValues: defaultValues, + // defaultValues: defaultValues, }); const [grntchBdstCertYn, instlCstSprtYn, filtrTrtmfctProcs] = form.watch([ @@ -63,12 +65,20 @@ export default function RswtrRegForm({ "reuseBuilding.0.rswtrObj.filtrTrtmfctProcs", ]); + const { t } = useTranslation('base'); const onSubmit = (values: z.infer) => { if (isModal) { - rswtBdstReg(values, "41"); - if (setIsModal) setIsModal(false); + const handleConfirm = async () => { + rswtBdstReg(values, "41"); + if (setIsModal) setIsModal(false); + }; + confirmToast(t('isInsertMsg'), handleConfirm); + } else { - rswtBdstUpdate(values, "41"); + const handleConfirm = async () => { + rswtBdstUpdate(values, "41"); + }; + confirmToast(t('isUpdateMsg'), handleConfirm); } }; diff --git a/apps/wr/public/locales/ko/message.json b/apps/wr/public/locales/ko/message.json index 78219a539..ee661980d 100644 --- a/apps/wr/public/locales/ko/message.json +++ b/apps/wr/public/locales/ko/message.json @@ -8,12 +8,16 @@ "noChangedErrMsg": "변경사항이 없습니다.", "dateErrMsg": "시작년도를 종료년도 이후로 설정할 수 없습니다.", "fileDateErrMsg": "파일업로드 이전에 등록년도를 작성해주세요.", + "isDeleteMsg": "선택한 정보를 삭제하시겠습니까?", + "isUpdateMsg": "수정한 정보를 저장하시겠습니까?", + "isInsertMsg": "등록하시겠습니까?", + "excelDownErrMsg": "다운로드할 데이터가 없습니다.", "alreadyInsertedErrMsg": "사업자번호 {{num}}(은)는 이미 등록되었습니다. 다시 등록해주세요.", "saveRowErrMsg": "수정을 원하는 행을 선택하고 저장버튼을 눌러주세요.", - "costCalcErrMsg":"공사비 계산 진행 후 저장을 눌러주세요", + "costCalcErrMsg":"공사비 계산 진행 후 저장을 눌러주세요", "maxYearErrMsg": "최대 {{year}}년까지 선택가능합니다.", - "checkQtyMsg": "요구수량(M3/d)을 확인해주세요 계산할수 없습니다." + "checkQtyMsg": "요구수량(M3/d)을 확인해주세요 계산할 수 없습니다." } diff --git a/packages/common/business_components/src/ui/table/index.tsx b/packages/common/business_components/src/ui/table/index.tsx index 01bb18ba2..93adfb25c 100644 --- a/packages/common/business_components/src/ui/table/index.tsx +++ b/packages/common/business_components/src/ui/table/index.tsx @@ -130,7 +130,13 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr ) ))} - )) : <>} + )) : ( + + item.visible != false).length} className="h-24 text-center text-gray-500"> + 조회된 결과가 없습니다. + + + )} {total <= 0 ? <> : }