빗물/중수도/온배수시설현황, 재이용실적현황, 지도점검현황 엑셀 다운로드시 빈데이터면 에러 메시지 추가

This commit is contained in:
jyha00
2025-07-11 16:10:10 +09:00
parent f7a3eec904
commit 6330c125c7
7 changed files with 103 additions and 62 deletions
@@ -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<ReturnType>({} 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<string>("");
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={<SttnDetailModal type={"HTB"} formObj={detailModal.data} />}
/>
</ContentsDiv>
<Toaster position="top-center" />
</>
);
}
@@ -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<customRainBdst[]>();
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>()
const [resetPage, isResetPage] = useState(false);
const isDownloadTriggered = useRef(false);
const [objSearch, setObjSearch] = useState<objSearchType>({ 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<string>("");
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() {
}}
/>
</ContentsDiv>
<Toaster position="top-center" />
</>
);
}
@@ -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<ReturnType>({} as ReturnType);
const [bdstTable, setBdstTable] = useState<customRswtBdst[]>();
const isDownloadTriggered = useRef(false);
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>()
const [objSearch, setObjSearch] = useState<objSearchType>({ 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<string>("");
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() {
}}
/>
</ContentsDiv>
<Toaster position="top-center" />
</>
);
}
@@ -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,
"중수도시설 지도점검 현황",
@@ -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<ReturnType>({} as ReturnType);
const [swtrmtFcltNm, setSwtrmtFcltNm] = useState<string>();
const [pbnRuseNm, setPbnRuseNm] = useState<string>("");
const { t } = useTranslation('base');
const [searchYear, setSearchYear] = useState<string>(
String(new Date().getFullYear())
);
const [excelData, setExcelData] = useState<any[]>([]);
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={<Button
className={btnClass}
onClick={() => {
setIsChHead(true);
}}
>
조회항목설정
</Button>}
rightChildren={undefined}
leftChildren={<div className="col-span-5">
<div className="flex flex-row">
<div className="flex flex-row items-center">
+37 -30
View File
@@ -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<string, Set<number>>();
return (
<>
{makeTableData.map((row, rowIndex) => (
{/* {makeTableData.map((row, rowIndex) => ( */}
{makeTableData && makeTableData.length > 0 ? (makeTableData.map((row, rowIndex) => (
<TableRow key={rowIndex}>
{headList
.map((head) => {
@@ -177,7 +178,13 @@ export const chRowspanTable = (
})}
</TableRow>
))}
))) : (
<TableRow>
<TableCell colSpan={headList.length} className="h-24 text-center text-gray-500">
조회된 결과가 없습니다.
</TableCell>
</TableRow>
)}
</>
);
};
@@ -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 (
<TableRow key={dataIndex + "row"}>
{headList.map((head, headIndex) => {
// 총합계 행이면 "구분"에서 colSpan=2로 병합
if (
data["구분"] === 0 &&
head.id === "구분"
) {
return (
<TableCell
key={head.id + headIndex}
colSpan={2}
className="font-bold text-center bg-[#d5e1eb]"
>
총합계
</TableCell>
);
}
// 총합계(합계) 행이면 "용수명" 컬럼은 렌더링하지 않음
if (
data["구분"] === 0 &&
head.id === "용수명"
) {
return null;
}
// 총합계 행이면 "구분"에서 colSpan=2로 병합
if (
data["구분"] === 0 &&
head.id === "구분"
) {
return (
<TableCell
key={head.id + headIndex}
colSpan={2}
className="font-bold text-center bg-[#d5e1eb]"
>
총합계
</TableCell>
);
}
// 총합계(합계) 행이면 "용수명" 컬럼은 렌더링하지 않음
if (
data["구분"] === 0 &&
head.id === "용수명"
) {
return null;
}
// mergeCell 처리
if (head.mergeCell) {
const rowSpan = getRowSpan(chgRes, head.id, dataIndex);
+5 -2
View File
@@ -8,12 +8,15 @@
"noChangedErrMsg": "변경사항이 없습니다.",
"dateErrMsg": "시작년도를 종료년도 이후로 설정할 수 없습니다.",
"fileDateErrMsg": "파일업로드 이전에 등록년도를 작성해주세요.",
"isDeleteMsg": "선택한 정보를 삭제하시겠습니까?",
"isUpdateMsg": "수정한 정보를 저장하시겠습니까?",
"excelDownErrMsg": "다운로드할 데이터가 없습니다.",
"alreadyInsertedErrMsg": "사업자번호 {{num}}(은)는 이미 등록되었습니다. 다시 등록해주세요.",
"saveRowErrMsg": "수정을 원하는 행을 선택하고 저장버튼을 눌러주세요.",
"costCalcErrMsg":"공사비 계산 진행 후 저장을 눌러주세요",
"costCalcErrMsg":"공사비 계산 진행 후 저장을 눌러주세요",
"maxYearErrMsg": "최대 {{year}}년까지 선택가능합니다.",
"checkQtyMsg": "요구수량(M3/d)을 확인해주세요 계산할수 없습니다."
"checkQtyMsg": "요구수량(M3/d)을 확인해주세요 계산할 수 없습니다."
}