Merge commit '7733426636f08d68a85a8739f2ef6e3206078d4e' into iipbs/wr/hasuReg
This commit is contained in:
@@ -5,6 +5,7 @@ import { ruseUtzType } from "@/app/store/matDmd/ruseCaseMng/headList";
|
||||
import { excelDownload, getCity } from "@/components/lib/func/commom";
|
||||
import RuseCaseMngExcel from "@/components/ui/modal/coMat/ruseCaseMng/ruseCaseMngExcelModal";
|
||||
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
|
||||
import { ToastFormUi } from "@/components/ui/toast/toastFromUi";
|
||||
import {
|
||||
ContentsDiv,
|
||||
filePickedBlobArray,
|
||||
@@ -20,11 +21,12 @@ import {
|
||||
} from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Button } from "@common/components/ui";
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast, Toaster } from "react-hot-toast";
|
||||
|
||||
export default function RuseCaseMng() {
|
||||
const { code, ruseCaseMng, selectRuseCaseMng } = useWrStore((state) => state);
|
||||
const { ruseCaseMngList } = ruseCaseMng;
|
||||
const { ruseCaseMngList, status } = ruseCaseMng;
|
||||
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>([]);
|
||||
const [objSearch, setObjSearch] = useState<objSearchType>({ sgg: "", city: "" });
|
||||
|
||||
@@ -142,7 +144,7 @@ export default function RuseCaseMng() {
|
||||
}
|
||||
];
|
||||
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
|
||||
await filePickedBlobArray(blobRet, '시설정보및운영현황황', sheetParameter);
|
||||
await filePickedBlobArray(blobRet, '물재이용사례현황', sheetParameter);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -157,6 +159,12 @@ export default function RuseCaseMng() {
|
||||
);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if(status === 200){
|
||||
setIsExcelOpen({ isModal: false });
|
||||
}
|
||||
}, [status]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ContentsDiv>
|
||||
@@ -239,7 +247,7 @@ export default function RuseCaseMng() {
|
||||
</div>
|
||||
</div>
|
||||
</ContentsDiv>
|
||||
|
||||
<Toaster position="top-center" />
|
||||
{/* 엑셀 등록 모달 */}
|
||||
<UiModal
|
||||
open={isExcelOpen.isModal}
|
||||
|
||||
@@ -28,8 +28,10 @@ import {
|
||||
type SelectDataType
|
||||
} from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
import { Button } from "@common/components/ui";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { Toaster } from "react-hot-toast";
|
||||
|
||||
export default function LdrmntCoSttn() {
|
||||
const { code, ldrmnt, ldrmntInit, ldrmntSearch, } = useWrStore(
|
||||
@@ -273,7 +275,7 @@ export default function LdrmntCoSttn() {
|
||||
<div className="overflow-x-auto">
|
||||
<ListDiv className="min-w-max">
|
||||
<UiTable
|
||||
headName={[]}
|
||||
headName={undefined}
|
||||
tableData={bdstTable || []}
|
||||
headlist={ldrmntHeadListExport}
|
||||
pageSize={20}
|
||||
@@ -299,8 +301,9 @@ export default function LdrmntCoSttn() {
|
||||
setIsExcelOpen({ isModal: !isExcelOpen.isModal })
|
||||
}}
|
||||
bodyClass={"w-[40vw] max-w-none"}
|
||||
body={<CoRegExcel />}
|
||||
body={<CoRegExcel isModal={(isOpen) => setIsExcelOpen({ isModal: isOpen })} />}
|
||||
/>
|
||||
<Toaster position="top-center"></Toaster>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
|
||||
import {
|
||||
excelDownload,
|
||||
getCity,
|
||||
getCityOrSgg,
|
||||
tableData,
|
||||
} from "@/components/lib/func/commom";
|
||||
@@ -16,16 +17,22 @@ import SttnDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/sttnDeta
|
||||
import {
|
||||
ContentsDiv,
|
||||
SearchBaseForm,
|
||||
SearchDiv,
|
||||
SearchFormLeft,
|
||||
SearchFormRight,
|
||||
SelectBox,
|
||||
Title,
|
||||
UiModal,
|
||||
UiTable,
|
||||
type ReturnType,
|
||||
type SelectDataType,
|
||||
} from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Button } from "@common/components/ui";
|
||||
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";
|
||||
|
||||
export default function HtdflSttn() {
|
||||
const { code, htdflSttn, htdflSttnSearch, initHtdfl } = useWrStore(
|
||||
@@ -38,6 +45,8 @@ export default function HtdflSttn() {
|
||||
const [pageNation, setPageNation] = useState(1);
|
||||
const [isChHead, setIsChHead] = useState(false);
|
||||
const [bdstTable, setBdstTable] = useState<customRainBdst[]>();
|
||||
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>()
|
||||
const [objSearch, setObjSearch] = useState<objSearchType>({ sgg: "", city: "" });
|
||||
const [detailModal, setDetailModal] = useState<{
|
||||
isOpen: boolean;
|
||||
data: customRainBdst | undefined;
|
||||
@@ -50,13 +59,44 @@ export default function HtdflSttn() {
|
||||
const codeData = getCityOrSgg(ref);
|
||||
|
||||
const excelClick = useCallback(() => {
|
||||
if (codeData) htdflSttnSearch(1, "10000", codeData);
|
||||
}, [htdflSttnSearch, codeData]);
|
||||
// 최신 검색 조건 반영
|
||||
const con = getConValue();
|
||||
htdflSttnSearch(1, "10000", String(con), code.cityCd, code.sggCd);
|
||||
}, [htdflSttnSearch, objSearch, code.cityCd, code.sggCd]);
|
||||
|
||||
useEffect(() => {
|
||||
if (codeData != null) htdflSttnSearch(pageNation, "20", codeData);
|
||||
if (codeData != null) htdflSttnSearch(pageNation, "20", codeData, code.cityCd, code.sggCd);
|
||||
}, [pageNation]);
|
||||
|
||||
const getSelCity = (val: string | number) => {
|
||||
const cityValue = String(val);
|
||||
|
||||
if (cityValue === "0") {
|
||||
setSelectSgg([]);
|
||||
setObjSearch({ city: cityValue, sgg: "" });
|
||||
} else {
|
||||
const data = getCity(cityValue, code.sggCd);
|
||||
setSelectSgg(data);
|
||||
|
||||
const firstSggVal = data.find(item => item.val === "0")?.val || (data[0]?.val ?? "");
|
||||
setObjSearch({ city: cityValue, sgg: firstSggVal });
|
||||
}
|
||||
};
|
||||
|
||||
const getSgg = (val: string | number) => {
|
||||
setObjSearch({ ...objSearch, sgg: String(val) })
|
||||
};
|
||||
|
||||
const getConValue = () => {
|
||||
if (!objSearch.city || objSearch.city === "0") {
|
||||
return "0";
|
||||
}
|
||||
if (objSearch.sgg && objSearch.sgg !== "0") {
|
||||
return objSearch.sgg;
|
||||
}
|
||||
return objSearch.city;
|
||||
};
|
||||
|
||||
const cellClick = (index: number | undefined, headId: string) => {
|
||||
if (
|
||||
headId !== "chBuildingYn" &&
|
||||
@@ -67,20 +107,15 @@ export default function HtdflSttn() {
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
const excelDown = async () => {
|
||||
if (htdflSttn.excelList.length > 0) {
|
||||
if (htdflSttn.excelList.length === 0) return;
|
||||
const excelData = await tableData(htdflSttn.excelList, { code });
|
||||
const htdflExcel = excelHtdflSttnParsing(excelData, code.cityCd, code.sggCd);
|
||||
excelDownload(
|
||||
htdflExcel as [[]],
|
||||
"온배수시설 현황",
|
||||
"sample_htdflSttn.xlsx",
|
||||
"A1:S3"
|
||||
);
|
||||
}
|
||||
};
|
||||
excelDown();
|
||||
if (htdflSttn.excelList.length > 0) {
|
||||
if (htdflSttn.excelList.length === 0) return;
|
||||
excelDownload(
|
||||
htdflSttn.excelList,
|
||||
"온배수시설 현황",
|
||||
"sample_htdflSttn.xlsx",
|
||||
"A1:S3"
|
||||
);
|
||||
}
|
||||
}, [htdflSttn.excelList, code]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -90,19 +125,16 @@ export default function HtdflSttn() {
|
||||
}, [htdflSttn.isInit, initHtdfl]);
|
||||
|
||||
useEffect(() => {
|
||||
if (htdflSttnRes.length > 0 && code.cityCd.length > 0) {
|
||||
const data = tableData(htdflSttnRes, { code });
|
||||
const chData = data
|
||||
.map((item: any) => ({
|
||||
...item,
|
||||
...item.reuseBuilding[0],
|
||||
...item.reuseBuilding[0].htdflObj,
|
||||
chBuildingYn: item.chgBuilding[0]?.bdstChgNm !== null ? "Y" : "N",
|
||||
}))
|
||||
.filter((item: any) => item.htdflObj !== undefined);
|
||||
|
||||
setBdstTable(chData);
|
||||
}
|
||||
const data = tableData(htdflSttnRes, { code });
|
||||
const chData = data
|
||||
.map((item: any) => ({
|
||||
...item,
|
||||
...item.reuseBuilding[0],
|
||||
...item.reuseBuilding[0].htdflObj,
|
||||
chBuildingYn: item.chgBuilding[0]?.bdstChgNm !== null ? "Y" : "N",
|
||||
}))
|
||||
.filter((item: any) => item.htdflObj !== undefined);
|
||||
setBdstTable(chData);
|
||||
}, [code, htdflSttnRes, htdflSttn.htdflSttHeadList]);
|
||||
|
||||
return (
|
||||
@@ -111,43 +143,65 @@ export default function HtdflSttn() {
|
||||
<div className="grid grid-cols-4 gap-4 ">
|
||||
<div className="col-span-4">
|
||||
<Title title={"온배수 시설 현황"} />
|
||||
<SearchBaseForm
|
||||
selectSidoData={code.cityCd}
|
||||
selectSigunData={code.sggCd}
|
||||
selectRegionData={code.rvbsnCd}
|
||||
selectUnitWaterShedData={code.lgbsnCd}
|
||||
selectMiddleRegionData={code.mdmbsnCd}
|
||||
selectEnvPartData={code.lclgvrnmntCd}
|
||||
rightChildren={<Button
|
||||
className={btnClass}
|
||||
onClick={() => {
|
||||
setIsChHead(true);
|
||||
} }
|
||||
>
|
||||
조회항목설정
|
||||
</Button>}
|
||||
leftChildren={undefined}
|
||||
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;
|
||||
}
|
||||
htdflSttnSearch(pageNation, "20", con);
|
||||
} }
|
||||
excelClick={excelClick}
|
||||
initClick={function (): void { } }
|
||||
btnClass={btnClass}
|
||||
ref={ref} isAdmin={false} />
|
||||
|
||||
<SearchDiv>
|
||||
<SearchFormLeft>
|
||||
<div className="col-span-10 flex flex-row">
|
||||
<SelectBox
|
||||
className="col-span-2 w-1/6 h-full text-2xl"
|
||||
label="시도"
|
||||
selectClass={""}
|
||||
selectArray={code.cityCd}
|
||||
onSelectValue={getSelCity}
|
||||
/>
|
||||
<SelectBox
|
||||
className="col-span-2 w-1/6 h-full text-2xl ml-4"
|
||||
label="시군구"
|
||||
selectClass={""}
|
||||
selectArray={selectSgg || []}
|
||||
value={objSearch.sgg} // value props 추가
|
||||
onSelectValue={getSgg}
|
||||
/>
|
||||
</div>
|
||||
</SearchFormLeft>
|
||||
<SearchFormRight
|
||||
className="w-2/12 mx-5 flex flex-col items-center justify-center space-x-2 ">
|
||||
<div className="flex flex-row space-x-2 items-center">
|
||||
<Button
|
||||
size={"sm"}
|
||||
onClick={() => {
|
||||
const con = getConValue();
|
||||
htdflSttnSearch(1, "20", String(con), code.cityCd, code.sggCd);
|
||||
}}
|
||||
>
|
||||
조회
|
||||
</Button>
|
||||
<Button
|
||||
size={"sm"}
|
||||
className={`${btnClass} green`}
|
||||
onClick={excelClick}
|
||||
>
|
||||
다운로드
|
||||
</Button>
|
||||
<Button
|
||||
size={"sm"}
|
||||
className={btnClass}
|
||||
onClick={() => {
|
||||
setIsChHead(true);
|
||||
}}
|
||||
>
|
||||
조회항목설정
|
||||
</Button>
|
||||
</div>
|
||||
</SearchFormRight>
|
||||
</SearchDiv>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-6 gap-4 ">
|
||||
<div className="col-span-6">
|
||||
<ListDiv>
|
||||
<UiTable
|
||||
headName={[]}
|
||||
headName={undefined}
|
||||
tableData={bdstTable || []}
|
||||
children={
|
||||
<HeadMakeColSpan upHeadList={htdflSttn.htdflSttNodeList} />
|
||||
|
||||
@@ -82,7 +82,6 @@ export default function RainSttn() {
|
||||
};
|
||||
|
||||
const getSgg = (val: string | number) => {
|
||||
console.log("val", val)
|
||||
setObjSearch({ ...objSearch, sgg: String(val) })
|
||||
};
|
||||
|
||||
@@ -96,8 +95,6 @@ export default function RainSttn() {
|
||||
return objSearch.city;
|
||||
};
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!rainSttn.isInit) {
|
||||
rainSttnInit(codeData ?? "0");
|
||||
@@ -108,8 +105,6 @@ export default function RainSttn() {
|
||||
const data = tableData(rainSttnRes, { code });
|
||||
const chData = data
|
||||
.map((item: any) => {
|
||||
console.log("item", item);
|
||||
console.log("왜안돼", item.reuseBuilding[0].rainyObj.dtfcltCpct)
|
||||
return {
|
||||
...item,
|
||||
...item.reuseBuilding[0],
|
||||
@@ -124,10 +119,16 @@ export default function RainSttn() {
|
||||
? "확인불가"
|
||||
: item.reuseBuilding[0].instlCstSprtAmt,
|
||||
chBuildingYn: item.chgBuilding[0]?.bdstChgNm !== null ? "Y" : "N",
|
||||
pntfColArea: item.reuseBuilding[0].rainyObj.pntfColArea === -1
|
||||
? "확인불가"
|
||||
: item.reuseBuilding[0].rainyObj.pntfColArea,
|
||||
filtrTrtmfctCpct: item.reuseBuilding[0].rainyObj.filtrTrtmfctCpct === -1
|
||||
? "확인불가"
|
||||
: item.reuseBuilding[0].rainyObj.filtrTrtmfctCpct,
|
||||
archArea: Math.floor(item.archArea) === -1 ? "확인불가" : item.archArea,
|
||||
};
|
||||
})
|
||||
.filter((item: any) => item.rainyObj !== undefined);
|
||||
console.log("chData", chData)
|
||||
setBdstTable(chData);
|
||||
}, [code, rainSttnRes, rainSttn.rainSttHeadList]);
|
||||
|
||||
@@ -147,9 +148,6 @@ export default function RainSttn() {
|
||||
}
|
||||
}, [rainSttn.excelList]);
|
||||
|
||||
// const excelClick = useCallback(() => {
|
||||
// if (codeData) rainSttnSearch(1, "10000", codeData, code.cityCd, code.sggCd);
|
||||
// }, [rainSttnSearch, codeData, code.cityCd, code.sggCd]);
|
||||
const excelClick = useCallback(() => {
|
||||
// 최신 검색 조건 반영
|
||||
const con = getConValue();
|
||||
@@ -162,8 +160,6 @@ export default function RainSttn() {
|
||||
<div className="grid grid-cols-4 gap-4 ">
|
||||
<div className="col-span-4">
|
||||
<Title title={"빗물재이용 시설 현황"} />
|
||||
|
||||
|
||||
<SearchDiv>
|
||||
<SearchFormLeft>
|
||||
<div className="col-span-10 flex flex-row">
|
||||
@@ -215,50 +211,6 @@ export default function RainSttn() {
|
||||
</div>
|
||||
</SearchFormRight>
|
||||
</SearchDiv>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{/* <SearchBaseForm
|
||||
selectSidoData={code.cityCd}
|
||||
selectSigunData={code.sggCd}
|
||||
selectRegionData={code.rvbsnCd}
|
||||
selectUnitWaterShedData={code.lgbsnCd}
|
||||
selectMiddleRegionData={code.mdmbsnCd}
|
||||
selectEnvPartData={code.lclgvrnmntCd}
|
||||
rightChildren={
|
||||
<Button
|
||||
className={btnClass}
|
||||
onClick={() => {
|
||||
setIsChHead(true);
|
||||
}}
|
||||
>
|
||||
조회항목설정
|
||||
</Button>
|
||||
}
|
||||
leftChildren={undefined}
|
||||
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;
|
||||
}
|
||||
rainSttnSearch(1, "20", con, code.cityCd, code.sggCd);
|
||||
}}
|
||||
excelClick={excelClick}
|
||||
initClick={function (): void { }}
|
||||
btnClass={btnClass}
|
||||
ref={ref}
|
||||
isAdmin={false}
|
||||
/> */}
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-6 gap-4 ">
|
||||
|
||||
@@ -5,19 +5,26 @@ import type { chgBuilding } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
|
||||
import type { customRswtBdst } from "@/app/store/ruseFcltMng/fcltReg/rswtReg";
|
||||
import {
|
||||
excelDownload,
|
||||
getCity,
|
||||
getCityOrSgg,
|
||||
tableData,
|
||||
} from "@/components/lib/func/commom";
|
||||
import BdstChgModal from "@/components/ui/modal/fcltReg/bdstChgModal/bdstChgModal";
|
||||
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
|
||||
import HeadChModal from "@/components/ui/modal/sttn/headChModal/headChModal";
|
||||
import SttnDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/sttnDetailModal";
|
||||
import {
|
||||
ContentsDiv,
|
||||
SearchBaseForm,
|
||||
SearchDiv,
|
||||
SearchFormLeft,
|
||||
SearchFormRight,
|
||||
SelectBox,
|
||||
Title,
|
||||
UiModal,
|
||||
UiTable,
|
||||
type ReturnType,
|
||||
type SelectDataType,
|
||||
} from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
|
||||
@@ -34,6 +41,8 @@ export default function RswtSttn() {
|
||||
const [isChHead, setIsChHead] = useState(false);
|
||||
const ref = useRef<ReturnType>({} as ReturnType);
|
||||
const [bdstTable, setBdstTable] = useState<customRswtBdst[]>();
|
||||
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 })
|
||||
const [bdstChgProps, setBdstChgProps] = useState<{
|
||||
isOpen: boolean;
|
||||
@@ -58,6 +67,35 @@ export default function RswtSttn() {
|
||||
}
|
||||
}
|
||||
|
||||
const getSelCity = (val: string | number) => {
|
||||
const cityValue = String(val);
|
||||
|
||||
if (cityValue === "0") {
|
||||
setSelectSgg([]);
|
||||
setObjSearch({ city: cityValue, sgg: "" });
|
||||
} else {
|
||||
const data = getCity(cityValue, code.sggCd);
|
||||
setSelectSgg(data);
|
||||
|
||||
const firstSggVal = data.find(item => item.val === "0")?.val || (data[0]?.val ?? "");
|
||||
setObjSearch({ city: cityValue, sgg: firstSggVal });
|
||||
}
|
||||
};
|
||||
|
||||
const getSgg = (val: string | number) => {
|
||||
setObjSearch({ ...objSearch, sgg: String(val) })
|
||||
};
|
||||
|
||||
const getConValue = () => {
|
||||
if (!objSearch.city || objSearch.city === "0") {
|
||||
return "0";
|
||||
}
|
||||
if (objSearch.sgg && objSearch.sgg !== "0") {
|
||||
return objSearch.sgg;
|
||||
}
|
||||
return objSearch.city;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!rswtSttn.isInit) {
|
||||
rswtSttnInit("0");
|
||||
@@ -65,22 +103,25 @@ export default function RswtSttn() {
|
||||
}, [rswtSttn.isInit, rswtSttnInit]);
|
||||
|
||||
useEffect(() => {
|
||||
if (rswtSttnRes?.length > 0 && code.cityCd.length > 0) {
|
||||
const data = tableData(rswtSttnRes, { code });
|
||||
const chData = data
|
||||
.map((item: customRswtBdst) => ({
|
||||
const data = tableData(rswtSttnRes, { code });
|
||||
const chData = data
|
||||
.map((item: customRswtBdst) => {
|
||||
console.log("item", item)
|
||||
return {
|
||||
...item,
|
||||
...item.reuseBuilding[0],
|
||||
...item.reuseBuilding[0]?.rswtrObj,
|
||||
chBuildingYn: item?.chgBuilding[0]?.bdstChgNm !== null && item?.chgBuilding.length > 0 ? 'Y' : 'N'
|
||||
}))
|
||||
.filter(
|
||||
(item: customRswtBdst) =>
|
||||
item.reuseBuilding[0]?.rswtrObj !== undefined
|
||||
);
|
||||
chBuildingYn: item?.chgBuilding[0]?.bdstChgNm !== null && item?.chgBuilding.length > 0 ? 'Y' : 'N',
|
||||
instlCst: item.reuseBuilding[0]?.instlCst === -1 ? "확인불가" : item.reuseBuilding[0]?.instlCst,
|
||||
instlCstSprtAmt: item.reuseBuilding[0]?.instlCstSprtAmt === -1 ? "확인불가" : item.reuseBuilding[0]?.instlCstSprtAmt,
|
||||
}
|
||||
})
|
||||
.filter(
|
||||
(item: customRswtBdst) =>
|
||||
item.reuseBuilding[0]?.rswtrObj !== undefined
|
||||
);
|
||||
|
||||
setBdstTable(chData);
|
||||
}
|
||||
setBdstTable(chData);
|
||||
}, [code, rswtSttnRes]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -95,13 +136,11 @@ export default function RswtSttn() {
|
||||
}
|
||||
}, [rswtSttn.excelList]);
|
||||
|
||||
const excelClick = useCallback(
|
||||
(returnType: ReturnType) => {
|
||||
if (codeCityOrSgg)
|
||||
rswtSttnSearch(1, "10000", codeCityOrSgg, code.cityCd, code.sggCd);
|
||||
},
|
||||
[rswtSttnSearch, code.cityCd, code.sggCd, codeCityOrSgg]
|
||||
);
|
||||
const excelClick = useCallback(() => {
|
||||
// 최신 검색 조건 반영
|
||||
const con = getConValue();
|
||||
rswtSttnSearch(1, "10000", String(con), code.cityCd, code.sggCd);
|
||||
}, [rswtSttnSearch, objSearch, code.cityCd, code.sggCd]);
|
||||
|
||||
useEffect(() => {
|
||||
if (codeCityOrSgg != null) rswtSttnSearch(pageNation, "20", codeCityOrSgg, code.cityCd, code.sggCd);
|
||||
@@ -113,38 +152,64 @@ export default function RswtSttn() {
|
||||
<div className="grid grid-cols-4 gap-4 ">
|
||||
<div className="col-span-4">
|
||||
<Title title={"중수도시설 현황"} />
|
||||
<SearchBaseForm
|
||||
selectSidoData={code.cityCd}
|
||||
selectSigunData={code.sggCd}
|
||||
selectRegionData={code.rvbsnCd}
|
||||
selectUnitWaterShedData={code.lgbsnCd}
|
||||
selectMiddleRegionData={code.mdmbsnCd}
|
||||
selectEnvPartData={code.lclgvrnmntCd}
|
||||
rightChildren={<Button
|
||||
className={btnClass}
|
||||
onClick={() => {
|
||||
setIsChHead(true);
|
||||
} }
|
||||
>
|
||||
조회항목설정
|
||||
</Button>}
|
||||
leftChildren={undefined}
|
||||
queryClick={function (returnType: ReturnType): void {
|
||||
// '{partValue: 'A', sidoValue: '0', sigunValue: '0', regionValue: '0', unitWaterShedValue: '0', …}'
|
||||
if (codeCityOrSgg)
|
||||
rswtSttnSearch(1, "20", codeCityOrSgg, code.cityCd, code.sggCd);
|
||||
} }
|
||||
excelClick={excelClick}
|
||||
initClick={function (): void { } }
|
||||
btnClass={btnClass}
|
||||
ref={ref} isAdmin={false} />
|
||||
<SearchDiv>
|
||||
<SearchFormLeft>
|
||||
<div className="col-span-10 flex flex-row">
|
||||
<SelectBox
|
||||
className="col-span-2 w-1/6 h-full text-2xl"
|
||||
label="시도"
|
||||
selectClass={""}
|
||||
selectArray={code.cityCd}
|
||||
onSelectValue={getSelCity}
|
||||
/>
|
||||
<SelectBox
|
||||
className="col-span-2 w-1/6 h-full text-2xl ml-4"
|
||||
label="시군구"
|
||||
selectClass={""}
|
||||
selectArray={selectSgg || []}
|
||||
value={objSearch.sgg} // value props 추가
|
||||
onSelectValue={getSgg}
|
||||
/>
|
||||
</div>
|
||||
</SearchFormLeft>
|
||||
<SearchFormRight
|
||||
className="w-2/12 mx-5 flex flex-col items-center justify-center space-x-2 ">
|
||||
<div className="flex flex-row space-x-2 items-center">
|
||||
<Button
|
||||
size={"sm"}
|
||||
onClick={() => {
|
||||
const con = getConValue();
|
||||
rswtSttnSearch(1, "20", String(con), code.cityCd, code.sggCd);
|
||||
}}
|
||||
>
|
||||
조회
|
||||
</Button>
|
||||
<Button
|
||||
size={"sm"}
|
||||
className={`${btnClass} green`}
|
||||
onClick={excelClick}
|
||||
>
|
||||
다운로드
|
||||
</Button>
|
||||
<Button
|
||||
size={"sm"}
|
||||
className={btnClass}
|
||||
onClick={() => {
|
||||
setIsChHead(true);
|
||||
}}
|
||||
>
|
||||
조회항목설정
|
||||
</Button>
|
||||
</div>
|
||||
</SearchFormRight>
|
||||
</SearchDiv>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-6 gap-4 ">
|
||||
<div className="col-span-6">
|
||||
<ListDiv>
|
||||
<UiTable
|
||||
headName={[]}
|
||||
headName={undefined}
|
||||
tableData={bdstTable || []}
|
||||
children={
|
||||
<HeadMakeColSpan upHeadList={rswtSttn.rswtSttNodeList} />
|
||||
|
||||
@@ -68,8 +68,6 @@ export default function PbnstPrfmncSttn() {
|
||||
chartData5: lineChartDataProps[];
|
||||
chartData6: lineChartDataProps[];
|
||||
chartData7: lineChartDataProps[];
|
||||
chartData8: lineChartDataProps[];
|
||||
chartData9: lineChartDataProps[];
|
||||
}>();
|
||||
const [outLineData, setOutLineData] = useState<{
|
||||
chartData1: lineChartDataProps[];
|
||||
@@ -78,6 +76,8 @@ export default function PbnstPrfmncSttn() {
|
||||
chartData4: lineChartDataProps[];
|
||||
chartData5: lineChartDataProps[];
|
||||
chartData6: lineChartDataProps[];
|
||||
chartData7: lineChartDataProps[];
|
||||
chartData8: lineChartDataProps[];
|
||||
}>();
|
||||
|
||||
type dnChartForm = { label: string, val: number, fill?: string };
|
||||
@@ -228,16 +228,18 @@ export default function PbnstPrfmncSttn() {
|
||||
indstUswtr += element.indstUswtr;
|
||||
|
||||
// 월별 합계
|
||||
inUsageSum = element.wshwtr
|
||||
inUsageSum =
|
||||
element.wshwtr
|
||||
+ element.coolUswtr
|
||||
+ element.cleanUswtr
|
||||
+ element.drwtUswtr
|
||||
+ element.dltnUswtr
|
||||
+ element.ithlRswtr
|
||||
+ element.ithlEtcUswtr
|
||||
+ element.cleanToilUswtr
|
||||
+ element.resn;
|
||||
outUsageSum = element.lndwtr
|
||||
outUsageSum =
|
||||
element.cleanToilUswtr
|
||||
+ element.resn
|
||||
+ element.lndwtr
|
||||
+ element.hydUswtr
|
||||
+ element.ugwtChr
|
||||
+ element.farmUswtr
|
||||
@@ -258,9 +260,10 @@ export default function PbnstPrfmncSttn() {
|
||||
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" });
|
||||
@@ -271,22 +274,18 @@ export default function PbnstPrfmncSttn() {
|
||||
}
|
||||
});
|
||||
|
||||
let dnTotalIn = 0;
|
||||
let dnTotalOut = 0;
|
||||
inUsageArr.forEach((item) => {
|
||||
dnTotalIn += item
|
||||
})
|
||||
outUsageArr.forEach((item) => {
|
||||
dnTotalOut += item
|
||||
})
|
||||
|
||||
// 도넛차트 데이터
|
||||
dnData.push({ label: "세척수", val: wshwtr, fill: "#F7CFD8" });
|
||||
dnData.push({ label: "냉각수", val: coolUswtr, fill: "#F4F8D3" });
|
||||
dnData.push({ label: "청소수", val: cleanUswtr, fill: "#A6D6D6" });
|
||||
dnData.push({ label: "식수대", val: drwtUswtr, fill: "#8E7DBE" });
|
||||
dnData.push({ label: "희석용수", val: dltnUswtr, fill: "#FF8383" });
|
||||
dnData.push({ label: "중수도", val: ithlRswtr, fill: "#FFF574" });
|
||||
dnData.push({ label: "기타", val: ithlEtcUswtr, fill: "#A1D6CB" });
|
||||
dnData.push({ label: "청소화장실용수", val: cleanToilUswtr, fill: "#A19AD3" });
|
||||
dnData.push({ label: "세척살수용수", val: resn, fill: "#B1F0F7" });
|
||||
dnData.push({ label: "조경용수", val: lndwtr, fill: "#81BFDA" });
|
||||
dnData.push({ label: "친수용수", val: hydUswtr, fill: "#F5F0CD" });
|
||||
dnData.push({ label: "지하수충전", val: ugwtChr, fill: "#FADA7A" });
|
||||
dnData.push({ label: "농업용수", val: farmUswtr, fill: "#A6AEBF" });
|
||||
dnData.push({ label: "하천등유지용수", val: rvrKeepUswtr, fill: "#C5D3E8" });
|
||||
dnData.push({ label: "공업용수", val: indstUswtr, fill: "#D0E8C5" });
|
||||
dnData.push({ label: "장내용수", val: dnTotalIn, fill: "#8DD8FF" });
|
||||
dnData.push({ label: "장외용수", val: dnTotalOut, fill: "#FFF085" });
|
||||
|
||||
// 장내용수 도넛
|
||||
dnInData.push({ label: "세척수", val: wshwtr, fill: "#F7CFD8" });
|
||||
@@ -296,10 +295,10 @@ export default function PbnstPrfmncSttn() {
|
||||
dnInData.push({ label: "희석용수", val: dltnUswtr, fill: "#FF8383" });
|
||||
dnInData.push({ label: "중수도", val: ithlRswtr, fill: "#FFF574" });
|
||||
dnInData.push({ label: "기타", val: ithlEtcUswtr, fill: "#A1D6CB" });
|
||||
dnInData.push({ label: "청소화장실용수", val: cleanToilUswtr, fill: "#A19AD3" });
|
||||
dnInData.push({ label: "세척살수용수", val: resn, fill: "#B1F0F7" });
|
||||
|
||||
// 장외용수 도넛
|
||||
dnOutData.push({ label: "청소화장실용수", val: cleanToilUswtr, fill: "#A19AD3" });
|
||||
dnOutData.push({ label: "세척살수용수", val: resn, fill: "#B1F0F7" });
|
||||
dnOutData.push({ label: "조경용수", val: lndwtr, fill: "#81BFDA" });
|
||||
dnOutData.push({ label: "친수용수", val: hydUswtr, fill: "#F5F0CD" });
|
||||
dnOutData.push({ label: "지하수충전", val: ugwtChr, fill: "#FADA7A" });
|
||||
@@ -315,17 +314,17 @@ export default function PbnstPrfmncSttn() {
|
||||
chartData4: drwtUswtrData,
|
||||
chartData5: dltnUswtrData,
|
||||
chartData6: ithlRswtrData,
|
||||
chartData7: ithlEtcUswtrData,
|
||||
chartData8: cleanToilUswtrData,
|
||||
chartData9: resnData
|
||||
chartData7: ithlEtcUswtrData
|
||||
});
|
||||
setOutLineData({
|
||||
chartData1: lndwtrData,
|
||||
chartData2: hydUswtrData,
|
||||
chartData3: ugwtChrData,
|
||||
chartData4: farmUswtrData,
|
||||
chartData5: rvrKeepUswtrData,
|
||||
chartData6: indstUswtrData,
|
||||
chartData1: cleanToilUswtrData,
|
||||
chartData2: resnData,
|
||||
chartData3: lndwtrData,
|
||||
chartData4: hydUswtrData,
|
||||
chartData5: ugwtChrData,
|
||||
chartData6: farmUswtrData,
|
||||
chartData7: rvrKeepUswtrData,
|
||||
chartData8: indstUswtrData,
|
||||
});
|
||||
setBarData(barData);
|
||||
setChartData(dnData);
|
||||
@@ -408,15 +407,7 @@ export default function PbnstPrfmncSttn() {
|
||||
chartData7: {
|
||||
label: '기타',
|
||||
color: "blue",
|
||||
},
|
||||
chartData8: {
|
||||
label: '청소화장실용수',
|
||||
color: "magenta",
|
||||
},
|
||||
chartData9: {
|
||||
label: '세척살수용수',
|
||||
color: "skyblue",
|
||||
},
|
||||
}
|
||||
} satisfies ChartConfig;
|
||||
setLnInChartConfig(newChartConfig);
|
||||
}
|
||||
@@ -427,26 +418,34 @@ export default function PbnstPrfmncSttn() {
|
||||
if (outLineData?.chartData1) {
|
||||
const newChartConfig = {
|
||||
chartData1: {
|
||||
label: '조경용수',
|
||||
label: '청소화장실용수',
|
||||
color: "red",
|
||||
},
|
||||
chartData2: {
|
||||
label: '세척살수용수',
|
||||
color: "pink",
|
||||
},
|
||||
chartData3: {
|
||||
label: '조경용수',
|
||||
color: "gray",
|
||||
},
|
||||
chartData4: {
|
||||
label: '친수용수',
|
||||
color: "orange",
|
||||
},
|
||||
chartData3: {
|
||||
chartData5: {
|
||||
label: '지하수충전',
|
||||
color: "yellow",
|
||||
},
|
||||
chartData4: {
|
||||
chartData6: {
|
||||
label: '농업용수',
|
||||
color: "green",
|
||||
},
|
||||
chartData5: {
|
||||
chartData7: {
|
||||
label: '하천등유지용수',
|
||||
color: "blue",
|
||||
},
|
||||
chartData6: {
|
||||
chartData8: {
|
||||
label: '공업용수',
|
||||
color: "purple",
|
||||
},
|
||||
@@ -615,7 +614,7 @@ export default function PbnstPrfmncSttn() {
|
||||
<h1 className="">장내·외 월별 하수재이용실적 현황</h1>
|
||||
<div className="flex">
|
||||
<div className="w-1/3">
|
||||
<MainChart chartConfig={barChartConfig} chartData={barData} chartTitle={"월별 장내·외 용수 총 실적"} chartForm={CHART_FORM.DOUBLEBAR} />
|
||||
<MainChart chartConfig={barChartConfig} chartData={barData} chartTitle={"월별 장내·외 용수 총 실적"} chartForm={CHART_FORM.DOUBLEBAR} showLegend={true} />
|
||||
</div>
|
||||
<div className="w-1/3">
|
||||
<MainChart chartConfig={lnInChartConfig} chartData={inLineData} chartTitle={"월별 장내 용수 실적"} chartForm={CHART_FORM.LINE} />
|
||||
@@ -627,25 +626,25 @@ export default function PbnstPrfmncSttn() {
|
||||
<h1 className="">하수재이용실적 현황</h1>
|
||||
<ListDiv className="col-span-8 pr-6 ">
|
||||
{/* <ScrollArea className="h-[60vh]"> */}
|
||||
{/* <div className="card-header">
|
||||
{/* <div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">
|
||||
{"하수처리수재이용 실적(m3) 등록결과"}
|
||||
</h3>
|
||||
</div> */}
|
||||
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={prfData || []}
|
||||
headlist={monthHeadList}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={function (page: number): void {
|
||||
throw new Error("Function not implemented.");
|
||||
}}>
|
||||
</UiTable>
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={prfData || []}
|
||||
headlist={monthHeadList}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={function (page: number): void {
|
||||
throw new Error("Function not implemented.");
|
||||
}}>
|
||||
</UiTable>
|
||||
|
||||
{/* <ListDiv className="col-span-8 pr-6 ">
|
||||
{/* <ListDiv className="col-span-8 pr-6 ">
|
||||
<ScrollArea className="h-[60vh]">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">
|
||||
|
||||
@@ -210,8 +210,9 @@ export default function RainStat() {
|
||||
...item,
|
||||
ctpvCd: item.cityText
|
||||
};
|
||||
})
|
||||
}).filter((item: RainStatProps) => item.cityText !== '없음')
|
||||
: [];
|
||||
|
||||
setBdstTable(tbData);
|
||||
}, [code, rainStatList]);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ export default function RswtStat() {
|
||||
...item,
|
||||
ctpvCd: item.cityText
|
||||
};
|
||||
})
|
||||
}).filter((item: RswtStatProps) => item.cityText !== '없음')
|
||||
: [];
|
||||
setRswtTable(tbData);
|
||||
}, [code, rswtStatList])
|
||||
|
||||
@@ -20,6 +20,7 @@ export type ldrmntState = {
|
||||
excelList: ExcelType[];
|
||||
isInit: boolean;
|
||||
ldrmntRes: customLdrmnt[];
|
||||
isLoading: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -35,6 +36,7 @@ type ldrmntActions = {
|
||||
ldrmntSearch: (page: number, sggCd: string, total: string, coNm: string) => void;
|
||||
ldrmntUpdate: (ldrmntRes: customLdrmnt) => void;
|
||||
ldrmntDelete: () => void;
|
||||
loadingOpen: (isOpen: boolean) => void
|
||||
};
|
||||
|
||||
export type ldrmntType = ldrmntState & ldrmntActions;
|
||||
@@ -46,6 +48,7 @@ export const ldrmntStateExport: ldrmntState = {
|
||||
excelList: [],
|
||||
isInit: false,
|
||||
ldrmntRes: ldrmntRes,
|
||||
isLoading: false,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -75,31 +78,30 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = (
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
loadingOpen: (isOpen) => {
|
||||
return set((state: ldrmntState) => {
|
||||
return {
|
||||
...state,
|
||||
ldrmnt: {
|
||||
...state.ldrmnt,
|
||||
isLoading: isOpen,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
ldrmntRegData: async (data) => {
|
||||
try {
|
||||
const response = await postFectch(
|
||||
"/reuseFc/request/temp",
|
||||
data,
|
||||
fetchType.WR
|
||||
);
|
||||
await deleteFectch(
|
||||
`/reuseFc/request/temp`,
|
||||
);
|
||||
|
||||
console.log('response ', response)
|
||||
const response = await postFectch(
|
||||
"/reuseFc/request/temp",
|
||||
data,
|
||||
fetchType.WR
|
||||
);
|
||||
|
||||
if (response.status === 200) {
|
||||
ToastFormUi({
|
||||
body: "잠재수요처 등록이 완료되었습니다. ",
|
||||
title: "잠재수요처 등록",
|
||||
});
|
||||
console.log('response ', response)
|
||||
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
ToastFormUi({
|
||||
body: "잠재수요처 등록이 실패하였습니다. ",
|
||||
title: "잠재수요처 등록",
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
ldrmntSearch: async (page: number, total: string, sggCd: string, coNm: string) => {
|
||||
let searchUrl = "";
|
||||
@@ -111,6 +113,7 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = (
|
||||
searchUrl = `/reuseFc/request/temp/${page}/${total}/${sggCd}`;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const ldrmntRes = await getFetch(
|
||||
fetchType.WR,
|
||||
@@ -178,11 +181,30 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = (
|
||||
},
|
||||
ldrmntDelete: async () => {
|
||||
try {
|
||||
set((state: ldrmntState) => {
|
||||
return {
|
||||
...state,
|
||||
ldrmnt: {
|
||||
...state.ldrmnt,
|
||||
isLoading: true,
|
||||
},
|
||||
};
|
||||
});
|
||||
const response = await deleteFectch(
|
||||
`/reuseFc/request/temp`,
|
||||
);
|
||||
|
||||
} catch (error) {
|
||||
console.log("error", error)
|
||||
set((state: ldrmntState) => {
|
||||
return {
|
||||
...state,
|
||||
ldrmnt: {
|
||||
...state.ldrmnt,
|
||||
isLoading: false,
|
||||
},
|
||||
};
|
||||
});
|
||||
console.error("Error ldrmntDelete:", error);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { fetchType, getFetch, postFectch } from "@/components/lib/api";
|
||||
import type { TableUpperProps } from "../../common/type/header";
|
||||
import { ruseCaseHeadListExport } from "./headList";
|
||||
import { ToastFormUi } from "@/components/ui/toast/toastFromUi";
|
||||
|
||||
import { toast } from "react-hot-toast";
|
||||
export type ruseCaseState = {
|
||||
ruseCaseMng: {
|
||||
ruseHeadList:TableUpperProps[];
|
||||
ruseCaseMngList:ruseCaseMngExcelProps[];
|
||||
status: number;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -69,7 +69,6 @@ type ruseCaseActions = {
|
||||
};
|
||||
|
||||
export const fetchSearchRuseCaseMng = async (sidoCd: string, sigunguCd: string, usageCd : string, name: string) => {
|
||||
|
||||
const tailUrl = ((sigunguCd !== '전체' && sigunguCd !=='') ? `/${sigunguCd}` : (sidoCd != '전체' && sidoCd != '') ? `/${sidoCd}` : `/0`) + (usageCd? `/${usageCd}` : '/0') + (name? `/${name}` : '');
|
||||
const resp = await getFetch(fetchType.WR,`/reuseFc/pubFcRuseCase${tailUrl}`);
|
||||
return resp;
|
||||
@@ -77,7 +76,7 @@ export const fetchSearchRuseCaseMng = async (sidoCd: string, sigunguCd: string,
|
||||
|
||||
export const fetchInsertRuseCaseMng = async (data: any) => {
|
||||
const response = await postFectch('/reuseFc/pubFcRuseCase', data, fetchType.WR);
|
||||
return response.data;
|
||||
return {data:response.data, status:response.status};
|
||||
};
|
||||
|
||||
export type ruseCaseType = ruseCaseState & ruseCaseActions;
|
||||
@@ -86,6 +85,7 @@ export const ruseCaseStateExport: ruseCaseState = {
|
||||
ruseCaseMng: {
|
||||
ruseHeadList:ruseCaseHeadListExport,
|
||||
ruseCaseMngList:[],
|
||||
status: 0,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -95,7 +95,6 @@ export const ruseCaseActionsExport: (set: any) => ruseCaseActions = (
|
||||
return {
|
||||
selectRuseCaseMng: async (sidoCd: string, sigunguCd: string, usageCd : string, name: string) => {
|
||||
const res = await fetchSearchRuseCaseMng(sidoCd, sigunguCd, usageCd, name);
|
||||
console.log('res : ', res);
|
||||
set((state: ruseCaseState) => ({
|
||||
ruseCaseMng: {
|
||||
...state.ruseCaseMng,
|
||||
@@ -107,11 +106,16 @@ export const ruseCaseActionsExport: (set: any) => ruseCaseActions = (
|
||||
insertRuseCaseMng: async (data: any) => {
|
||||
const response = await fetchInsertRuseCaseMng(data);
|
||||
if(response.status === 200){
|
||||
ToastFormUi({
|
||||
body: "잠재수요처 등록이 완료되었습니다. ",
|
||||
title: "잠재수요처 등록",
|
||||
});
|
||||
toast.success("물재이용사례 등록이 완료되었습니다. ");
|
||||
}else{
|
||||
toast.error("물재이용사례 등록에 실패하였습니다. ");
|
||||
}
|
||||
set((state: ruseCaseState) => ({
|
||||
ruseCaseMng: {
|
||||
...state.ruseCaseMng,
|
||||
status: response.status,
|
||||
},
|
||||
}));
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -148,7 +148,7 @@ 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에서 추출
|
||||
@@ -161,26 +161,26 @@ export const pbnstPrfmncSttnActionsExport: (set: any) => pbnstPrfmncSttnActions
|
||||
item.prfList.forEach((acc) => {
|
||||
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);
|
||||
(acc.wshwtr ?? 0) + //조경용수
|
||||
(acc.coolUswtr ?? 0) + //냉각수
|
||||
(acc.cleanUswtr ?? 0) + //청소수
|
||||
(acc.drwtUswtr ?? 0) + //식수대
|
||||
(acc.dltnUswtr ?? 0) + //희석용수
|
||||
(acc.ithlRswtr ?? 0) + //중수도
|
||||
(acc.ithlEtcUswtr ?? 0) //기타
|
||||
outUsageSum =
|
||||
(acc.lndwtr ?? 0) +
|
||||
(acc.hydUswtr ?? 0) +
|
||||
(acc.ugwtChr ?? 0) +
|
||||
(acc.farmUswtr ?? 0) +
|
||||
(acc.rvrKeepUswtr ?? 0) +
|
||||
(acc.indstUswtr ?? 0);
|
||||
(acc.cleanToilUswtr ?? 0) + //청소화장실용수
|
||||
(acc.resn ?? 0)+ //세척살수용도
|
||||
(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
|
||||
yearItem.pbnstRuseFcltPk == acc.pbnstRuseFcltFk
|
||||
);
|
||||
|
||||
if (yearData) {
|
||||
|
||||
@@ -5,6 +5,8 @@ import type { z } from "zod";
|
||||
import { controlHeadView } from "../rainSttn";
|
||||
import type { customHtdflBdst } from "../../fcltReg/htdflReg";
|
||||
import { fetchType, getFetch } from "@/components/lib/api";
|
||||
import type { SelectDataType } from "@common/business_components";
|
||||
import { excelHtdflSttnParsing } from "./excel";
|
||||
|
||||
const htdflSttHeadList = htdflSttHeadListExport;
|
||||
const htdflSttNodeList = htdflSttNodeListExport;
|
||||
@@ -21,7 +23,8 @@ export type htdflSttnState = {
|
||||
};
|
||||
type htdflSttnActions = {
|
||||
initHtdfl: (con: string) => void;
|
||||
htdflSttnSearch: (page: number, total: string, con: string) => void;
|
||||
htdflSttnSearch: (page: number, total: string, con: string, sidoCode: SelectDataType[],
|
||||
sggCode: SelectDataType[]) => void;
|
||||
htdflChSttnHead: (
|
||||
headList: z.infer<typeof sttnHeadListType>,
|
||||
) => void;
|
||||
@@ -67,22 +70,23 @@ export const htdflSttnActionsExport: (set: any) => htdflSttnActions = (
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
htdflSttnSearch: async (page: number, total: string, con: string) => {
|
||||
htdflSttnSearch: async (page: number, total: string, con: string,
|
||||
sidoCode: SelectDataType[],
|
||||
sggCode: SelectDataType[]
|
||||
) => {
|
||||
try {
|
||||
const htdflSttnRes = await getFetch(
|
||||
fetchType.WR,
|
||||
`/drain/facilityList/${page}/${total}/${con}`
|
||||
);
|
||||
if (Number(total) > 9000) {
|
||||
|
||||
|
||||
const htdflExcel = excelHtdflSttnParsing(htdflSttnRes, sidoCode, sggCode);
|
||||
set((state: htdflSttnState) => {
|
||||
|
||||
return {
|
||||
...state,
|
||||
htdflSttn: {
|
||||
...state.htdflSttn,
|
||||
excelList: htdflSttnRes,
|
||||
excelList: htdflExcel,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -4,32 +4,36 @@ import type { customLdrmnt } from "@/app/store/matDmd/ldrmntCoSttn";
|
||||
import { names } from "@/app/store/matDmd/ldrmntCoSttn/excel";
|
||||
import { filePicked, FileUpload, FormUi, Title } from "@common/business_components/ui";
|
||||
import { Form, FormField } from "@common/business_components/ui/form";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
import { Button, Progress } from "@common/components/ui";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import toast from "react-hot-toast";
|
||||
import type { z } from "zod";
|
||||
|
||||
export default function CoRegExcel() {
|
||||
|
||||
|
||||
export default function CoRegExcel({ isModal }: { isModal: (open: boolean) => void }) {
|
||||
const { ldrmnt,loadingOpen } = useWrStore((state) => state);
|
||||
const { isLoading } = ldrmnt;
|
||||
const form = useForm<z.infer<typeof coRegExcel>>({
|
||||
resolver: zodResolver(coRegExcel),
|
||||
});
|
||||
const { ldrmntRegData, ldrmntDelete } = useWrStore((state) => state);
|
||||
const [excelData, setExcelData] = useState<customLdrmnt[]>();
|
||||
|
||||
|
||||
const [file, setFiles] = useState<File | undefined>();
|
||||
|
||||
useEffect(() => {
|
||||
console.log("ldrmnt", ldrmnt)
|
||||
}, [ldrmnt])
|
||||
|
||||
const onSubmit = (values: z.infer<typeof coRegExcel>) => {
|
||||
ldrmntDelete();
|
||||
loadingOpen(true);
|
||||
if (file) {
|
||||
filePicked(file, 0).then((res) => {
|
||||
//TODO:loading
|
||||
filePicked(file, 0).then(async (res) => {
|
||||
|
||||
try {
|
||||
let array: { [key: string]: string | number }[] = []
|
||||
let isError = false;
|
||||
if (Array.isArray(res)) {
|
||||
res.some((item, index) => {
|
||||
let object: { [key: string]: string | number } = {}
|
||||
@@ -43,26 +47,24 @@ export default function CoRegExcel() {
|
||||
}
|
||||
return false;
|
||||
})
|
||||
if (isError === true)
|
||||
return true;
|
||||
|
||||
array.push(object)
|
||||
|
||||
if (index != 0 && index % 5000 == 0) {
|
||||
ldrmntRegData(array);
|
||||
array = []
|
||||
array.length = 0;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
}
|
||||
if (isError === false)
|
||||
ldrmntRegData(array);
|
||||
await ldrmntRegData(array);
|
||||
isModal(false);
|
||||
loadingOpen(false);
|
||||
toast.success(`잠재수요처 등록이 완료되었습니다.`);
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
loadingOpen(false);
|
||||
alert(e)
|
||||
return true;
|
||||
}
|
||||
|
||||
}).catch((e)=>{
|
||||
console.log("file", e);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -70,6 +72,7 @@ export default function CoRegExcel() {
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<LoadingOverlay isLoading={isLoading}></LoadingOverlay>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)}>
|
||||
<div>
|
||||
|
||||
@@ -88,12 +88,12 @@ export default function Chart({chartConfig=undefined, chartData=[], chartTitle='
|
||||
return (
|
||||
<>
|
||||
{chartTitle && chartTitle !== "" && chartTitle !== "undefined" ? (
|
||||
<div className="!mt-3 text-[2.5rem] font-bold">
|
||||
<div className="!mt-3 text-[2.5rem] font-bold text-center">
|
||||
{chartTitle}
|
||||
</div>): null}
|
||||
<div className="flex justify-center">
|
||||
<ChartContainer config={chartConfig ?? {}} className={chartClassName + " !w-[90%]"}>
|
||||
<BarChart accessibilityLayer data={chartData}>
|
||||
<div className="flex justify-center h-full w-full">
|
||||
<ChartContainer config={chartConfig ?? {}} className={chartClassName + " !w-[88%]"}>
|
||||
<BarChart accessibilityLayer data={chartData} margin={{ top: 5, right: 20, left: 30, bottom: 5 }}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis
|
||||
dataKey="label"
|
||||
@@ -110,8 +110,13 @@ export default function Chart({chartConfig=undefined, chartData=[], chartTitle='
|
||||
axisLine={true}
|
||||
fontSize={12}
|
||||
fontWeight={500}
|
||||
domain={[0, Math.ceil(barMaxValue * 1)]}
|
||||
label={yFieldText ? { value: yFieldText, className:"text-[13px] font-bold", position: 'insideLeft', angle: -90, offset: 20 } : undefined}
|
||||
tickFormatter={(value) => {
|
||||
// 소수점이 있는 경우 소수점을 유지하고 천단위 콤마 추가
|
||||
return value.toString().includes('.')
|
||||
? value.toLocaleString('en-US', { minimumFractionDigits: 0, maximumFractionDigits: 2 })
|
||||
: value.toLocaleString();
|
||||
}}
|
||||
label={yFieldText ? { value: yFieldText, className:"text-[13px] font-bold", position: 'insideLeft', angle: -90, offset: -24, orientation: "left" } : undefined}
|
||||
/>
|
||||
<ChartTooltip cursor={false} content={<CustomTooltip active={undefined} payload={undefined} label={undefined} />}/>
|
||||
{chartData && chartData.length > 0 && (
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
} from "./lib/chart";
|
||||
import type { CSSProperties } from "react";
|
||||
|
||||
/*
|
||||
const customStyles = {
|
||||
legendContainer: {
|
||||
display: "flex",
|
||||
@@ -17,6 +18,22 @@ const customStyles = {
|
||||
marginTop: "10px",
|
||||
} as CSSProperties,
|
||||
};
|
||||
*/
|
||||
|
||||
const customStyles = {
|
||||
legendContainer: {
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
gap: "12px",
|
||||
fontSize: "13px",
|
||||
fontWeight: "normal",
|
||||
marginTop: "16px",
|
||||
marginBottom: "8px",
|
||||
minHeight: "32px",
|
||||
} as CSSProperties,
|
||||
};
|
||||
|
||||
type BarChartProps = {
|
||||
chartConfig: ChartConfig | undefined;
|
||||
@@ -60,7 +77,7 @@ const CustomTooltip = ({
|
||||
};
|
||||
|
||||
// 커스텀 범례 (글씨 크기 키우기 + 스타일 추가)
|
||||
const CustomLegend = (props: any) => {
|
||||
/*const CustomLegend = (props: any) => {
|
||||
const { payload } = props;
|
||||
return (
|
||||
<div style={customStyles.legendContainer}>
|
||||
@@ -72,6 +89,38 @@ const CustomLegend = (props: any) => {
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};*/
|
||||
const CustomLegend = (props: any) => {
|
||||
const { payload } = props;
|
||||
if (!payload) return null;
|
||||
|
||||
return (
|
||||
<div style={customStyles.legendContainer}>
|
||||
{payload.map((entry: any, index: number) => (
|
||||
<div
|
||||
key={`legend-${index}`}
|
||||
className="flex items-center"
|
||||
style={{
|
||||
minWidth: "90px",
|
||||
margin: "2px 0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: "14px",
|
||||
height: "14px",
|
||||
backgroundColor: entry.color,
|
||||
borderRadius: "3px",
|
||||
marginRight: "8px",
|
||||
minWidth: "14px",
|
||||
minHeight: "14px",
|
||||
}}
|
||||
></div>
|
||||
<span style={{ fontSize: "13px", whiteSpace: "nowrap" }}>{entry.value}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default function DoubleBarChart({chartConfig=undefined, chartData=[], chartTitle='차트', chartClassName='w-full h-full', graphSize=40, yFieldText='', showLegend=false} : BarChartProps) {
|
||||
@@ -83,7 +132,7 @@ export default function DoubleBarChart({chartConfig=undefined, chartData=[], cha
|
||||
.map(key => item[key])
|
||||
).flat());
|
||||
};
|
||||
console.log(chartData);
|
||||
|
||||
const barMaxValue = getMaxValue(chartData, 'barVal');
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -48,6 +48,7 @@ type LegendProps = {
|
||||
};
|
||||
|
||||
/** 차트 기본 스타일 */
|
||||
/*
|
||||
const customStyles = {
|
||||
legendContainer: {
|
||||
display: "flex",
|
||||
@@ -58,6 +59,23 @@ const customStyles = {
|
||||
marginTop: "10px",
|
||||
} as CSSProperties,
|
||||
};
|
||||
*/
|
||||
|
||||
/** 차트 기본 스타일 (라인차트와 동일하게) */
|
||||
const customStyles = {
|
||||
legendContainer: {
|
||||
display: "flex",
|
||||
flexWrap: "wrap", // 여러 줄로 자동 줄바꿈
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
gap: "12px", // 아이템 간 간격
|
||||
fontSize: "13px",
|
||||
fontWeight: "normal",
|
||||
marginTop: "16px",
|
||||
marginBottom: "8px",
|
||||
minHeight: "32px", // 범례 영역 높이 통일
|
||||
} as CSSProperties,
|
||||
};
|
||||
|
||||
// 커스텀 툴팁
|
||||
const CustomTooltip = ({ active, payload, label }: {
|
||||
@@ -82,6 +100,7 @@ const CustomTooltip = ({ active, payload, label }: {
|
||||
};
|
||||
|
||||
// 커스텀 범례
|
||||
/*
|
||||
const CustomLegend = (props: LegendProps) => {
|
||||
const { payload } = props;
|
||||
if (!payload) return null;
|
||||
@@ -97,12 +116,52 @@ const CustomLegend = (props: LegendProps) => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
*/
|
||||
|
||||
const CustomLegend = (props: LegendProps) => {
|
||||
const { payload } = props;
|
||||
if (!payload) return null;
|
||||
|
||||
return (
|
||||
<div style={customStyles.legendContainer}>
|
||||
{payload.map((entry: LegendEntry, index: number) => (
|
||||
<div
|
||||
key={`legend-${index}`}
|
||||
className="flex items-center"
|
||||
style={{
|
||||
minWidth: "90px",
|
||||
margin: "2px 0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: "14px",
|
||||
height: "14px",
|
||||
backgroundColor: entry.fill,
|
||||
borderRadius: "3px",
|
||||
marginRight: "8px",
|
||||
minWidth: "14px",
|
||||
minHeight: "14px",
|
||||
}}
|
||||
></div>
|
||||
<span style={{ fontSize: "13px", whiteSpace: "nowrap" }}>
|
||||
{entry.payload?.label || entry.value}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default function DoughnutChart(props: {
|
||||
chartConfig: any;
|
||||
chartData: ChartDataItem[] | undefined;
|
||||
chartTitle: string
|
||||
}) {
|
||||
const legendData = props.chartData?.map(item => ({
|
||||
value: item.label,
|
||||
fill: props.chartConfig?.[item.label]?.fill || 'blue',
|
||||
})) ?? [];
|
||||
return (
|
||||
<Card className="flex flex-col">
|
||||
<CardContent className="flex-1 pb-0">
|
||||
@@ -130,9 +189,9 @@ export default function DoughnutChart(props: {
|
||||
nameKey="label"
|
||||
innerRadius={60}
|
||||
/>
|
||||
<CustomLegend />
|
||||
</PieChart>
|
||||
</ChartContainer>
|
||||
<CustomLegend payload={legendData} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -127,7 +127,7 @@ export default function LineBarchart({
|
||||
className="text-[12px] font-bold"
|
||||
tickCount={6}
|
||||
orientation="left"
|
||||
domain={[0, Math.ceil(lineMaxValue * 1)]}
|
||||
tickFormatter={(value) => value.toLocaleString()}
|
||||
label={{ value: yFieldText, angle: -90, position: 'insideLeft' }}
|
||||
/>}
|
||||
{/* 오른쪽 Y축: barVal */}
|
||||
@@ -136,7 +136,7 @@ export default function LineBarchart({
|
||||
className="text-[12px] font-bold"
|
||||
tickCount={6}
|
||||
orientation="right"
|
||||
domain={[0, Math.ceil(barMaxValue * 1)]}
|
||||
tickFormatter={(value) => value.toLocaleString()}
|
||||
label={{ value: yFieldText2, angle: -90, position: 'insideRight' }}
|
||||
reversed={true}
|
||||
/>}
|
||||
|
||||
@@ -18,6 +18,7 @@ type LineChartProps = {
|
||||
}
|
||||
|
||||
/** 차트 기본 스타일 */
|
||||
/*
|
||||
const customStyles = {
|
||||
legendContainer: {
|
||||
display: "flex",
|
||||
@@ -28,6 +29,23 @@ const customStyles = {
|
||||
marginTop: "10px",
|
||||
} as CSSProperties,
|
||||
};
|
||||
*/
|
||||
|
||||
/** 차트 기본 스타일 */
|
||||
const customStyles = {
|
||||
legendContainer: {
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
gap: "12px",
|
||||
fontSize: "13px",
|
||||
fontWeight: "normal",
|
||||
marginTop: "16px",
|
||||
marginBottom: "8px",
|
||||
minHeight: "32px",
|
||||
} as CSSProperties,
|
||||
};
|
||||
|
||||
type LegendEntry = {
|
||||
value: string;
|
||||
@@ -60,7 +78,7 @@ const CustomTooltip = ({ active, payload, label }: { active?: boolean; payload?:
|
||||
};
|
||||
|
||||
// 커스텀 범례 (글씨 크기 키우기 + 스타일 추가)
|
||||
const CustomLegend = (props: LegendProps) => {
|
||||
/*const CustomLegend = (props: LegendProps) => {
|
||||
const { payload } = props;
|
||||
if (!payload) return null;
|
||||
|
||||
@@ -74,6 +92,40 @@ const CustomLegend = (props: LegendProps) => {
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};*/
|
||||
|
||||
// 커스텀 범례 (도넛차트와 동일하게)
|
||||
const CustomLegend = (props: LegendProps) => {
|
||||
const { payload } = props;
|
||||
if (!payload) return null;
|
||||
|
||||
return (
|
||||
<div style={customStyles.legendContainer}>
|
||||
{payload.map((entry: LegendEntry, index: number) => (
|
||||
<div
|
||||
key={`legend-${index}`}
|
||||
className="flex items-center"
|
||||
style={{
|
||||
minWidth: "90px",
|
||||
margin: "2px 0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: "14px",
|
||||
height: "14px",
|
||||
backgroundColor: entry.color,
|
||||
borderRadius: "3px",
|
||||
marginRight: "8px",
|
||||
minWidth: "14px",
|
||||
minHeight: "14px",
|
||||
}}
|
||||
></div>
|
||||
<span style={{ fontSize: "13px", whiteSpace: "nowrap" }}>{entry.value}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
type DataType = {label: string; val: string};
|
||||
@@ -141,7 +193,7 @@ export default function Linechart({
|
||||
>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="label" fontSize="8px" fontWeight="bold" />
|
||||
<YAxis yAxisId="left" className="text-[12px] font-bold" domain={[0, Math.ceil(lineMaxValue * 1.1)]} tickCount={6} orientation="left" label={{ value: yFieldText, className:"text-[12px] font-bold", angle: -90, position: 'insideLeft' }} />
|
||||
<YAxis yAxisId="left" className="text-[12px] font-bold" tickFormatter={(value) => value.toLocaleString()} tickCount={6} orientation="left" label={{ value: yFieldText, className:"text-[12px] font-bold", angle: -90, position: 'insideLeft' }} />
|
||||
<Tooltip content={<CustomTooltip />} />
|
||||
{showLegend && <Legend content={CustomLegend as ContentType}/>}
|
||||
{Object.keys(chartData).map((key) => {
|
||||
|
||||
@@ -17,6 +17,7 @@ type MonthPickerProps = {
|
||||
field: { value: string; onChange: (date: string) => void }; // yyyyMM 문자열
|
||||
selectClass?: string;
|
||||
readOnly?: boolean;
|
||||
startYear?: number; // 시작 연도 props 추가
|
||||
};
|
||||
|
||||
// yyyyMM → Date 객체
|
||||
@@ -37,6 +38,7 @@ export const DateMonthPicker = ({
|
||||
field,
|
||||
selectClass,
|
||||
readOnly = false,
|
||||
startYear,
|
||||
}: MonthPickerProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
@@ -75,6 +77,7 @@ export const DateMonthPicker = ({
|
||||
<MonthPicker
|
||||
currentMonth={parsedDate}
|
||||
onMonthChange={handleSelect}
|
||||
startYear={startYear}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
@@ -28,35 +28,41 @@ export type MonthPickerProps = {
|
||||
newMonth: Date | undefined,
|
||||
shouldClosePopover?: boolean
|
||||
) => void;
|
||||
startYear?: number;
|
||||
};
|
||||
|
||||
export function MonthPicker({ currentMonth, onMonthChange }: MonthPickerProps) {
|
||||
export function MonthPicker({ currentMonth, onMonthChange, startYear }: MonthPickerProps) {
|
||||
|
||||
const today = startOfToday();
|
||||
const currentYear = today.getFullYear();
|
||||
const currentYear = today.getFullYear();
|
||||
const yearFromProp = format(currentMonth, "yyyy");
|
||||
const selectedYear = parseInt(yearFromProp);
|
||||
const selectedYear = parseInt(yearFromProp);
|
||||
|
||||
// 현재 월의 시작 날짜
|
||||
const fullYearStart = parse(yearFromProp, "yyyy", new Date());
|
||||
|
||||
const yearEnd =
|
||||
selectedYear === currentYear ? today : endOfYear(fullYearStart);
|
||||
|
||||
|
||||
|
||||
|
||||
const yearRange = Array.from({ length: 21 }, (_, i) => currentYear - 20 + i);
|
||||
|
||||
|
||||
// startYear가 없으면 기존과 동일하게 (현재년도 - 20년부터 현재년도까지)
|
||||
// startYear가 있으면 해당 년도부터 현재년도까지, 내림차순으로 정렬
|
||||
const yearRange = startYear
|
||||
? Array.from({ length: currentYear - startYear + 1 }, (_, i) => currentYear - i)
|
||||
: Array.from({ length: 21 }, (_, i) => currentYear - 20 + i);
|
||||
|
||||
const months = eachMonthOfInterval({ start: fullYearStart, end: yearEnd });
|
||||
|
||||
const getMonthButtonClass = (month: Date) =>
|
||||
cn(
|
||||
"inline-flex h-9 w-16 items-center justify-center rounded-md p-0 text-sm font-normal ring-offset-white transition-colors hover:bg-slate-100 hover:text-slate-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-400 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 aria-selected:opacity-100 dark:ring-offset-slate-950 dark:hover:bg-slate-800 dark:hover:text-slate-50 dark:focus-visible:ring-slate-800",
|
||||
isEqual(month, currentMonth) &&
|
||||
"bg-slate-900 text-slate-50 hover:bg-slate-900 hover:text-slate-50 focus:bg-slate-900 focus:text-slate-50 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50 dark:hover:text-slate-900 dark:focus:bg-slate-50 dark:focus:text-slate-900",
|
||||
"bg-slate-900 text-slate-50 hover:bg-slate-900 hover:text-slate-50 focus:bg-slate-900 focus:text-slate-50 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50 dark:hover:text-slate-900 dark:focus:bg-slate-50 dark:focus:text-slate-900",
|
||||
!isEqual(month, currentMonth) &&
|
||||
isEqual(month, getStartOfCurrentMonth()) &&
|
||||
"bg-slate-100 text-slate-900 dark:bg-slate-800 dark:text-slate-50"
|
||||
isEqual(month, getStartOfCurrentMonth()) &&
|
||||
"bg-slate-100 text-slate-900 dark:bg-slate-800 dark:text-slate-50"
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -77,7 +83,7 @@ const selectedYear = parseInt(yearFromProp);
|
||||
onMonthChange(newDate, false);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="w-[120px] h-7">
|
||||
<SelectTrigger className="w-[140px] h-9 text-base">
|
||||
<SelectValue placeholder="년도" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -112,7 +118,7 @@ const selectedYear = parseInt(yearFromProp);
|
||||
onClick={() => onMonthChange(month, true)}
|
||||
>
|
||||
<time dateTime={format(month, "yyyy-MM-dd")}>
|
||||
{format(month, 'MMM', { locale: ko })}
|
||||
{format(month, 'MMM', { locale: ko })}
|
||||
</time>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -21,4 +21,5 @@ export * from "./table_div";
|
||||
export * from "./title";
|
||||
export * from "./sdmInsertForm";
|
||||
export * from "./popover_ui";
|
||||
export * from "./date_month_picker";
|
||||
export * from "./date_month_picker";
|
||||
export * from "./loadingBar";
|
||||
@@ -187,7 +187,7 @@ export default React.memo(function GisTree({ checkedNodes = [], setCheckedNodes
|
||||
image.src = canvas.toDataURL('image/png');
|
||||
return image;
|
||||
};
|
||||
|
||||
|
||||
if (!treeData || treeData.length === 0) return null;
|
||||
|
||||
return (
|
||||
@@ -220,6 +220,7 @@ export default React.memo(function GisTree({ checkedNodes = [], setCheckedNodes
|
||||
<input type="checkbox" checked={checked.includes(node.id)} onChange={() => handleCheck(node.id)} className="cursor-pointer" />
|
||||
{node.icon && <span>{node.icon}</span>}
|
||||
<span className="text-[1.3rem] font-medium text-label">{node.text}</span>
|
||||
{depth > 0 && <span><img className="cursor-pointer w-5 h-5" src='/images/map/layericon/Layer_Select_BTN.png' onClick={()=>{}} alt={node.text}></img></span>}
|
||||
</div>
|
||||
)}
|
||||
sort={(a, b) => {
|
||||
|
||||
@@ -40,7 +40,8 @@ export default function UiPageNations(commonPageNationsProps: CommonPageNationsP
|
||||
<PaginationItem>
|
||||
<PaginationPrevious
|
||||
href="#"
|
||||
onClick={() => {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
if (startPage > 1) handlePageChange(startPage - 1);
|
||||
}}
|
||||
/>
|
||||
@@ -53,7 +54,7 @@ export default function UiPageNations(commonPageNationsProps: CommonPageNationsP
|
||||
<PaginationLink
|
||||
href="#"
|
||||
isActive={pageNum === pageProps.cur}
|
||||
onClick={() => handlePageChange(pageNum)}
|
||||
onClick={(e) => {e.preventDefault(); handlePageChange(pageNum)}}
|
||||
>
|
||||
{pageNum}
|
||||
</PaginationLink>
|
||||
@@ -65,7 +66,8 @@ export default function UiPageNations(commonPageNationsProps: CommonPageNationsP
|
||||
<PaginationItem>
|
||||
<PaginationNext
|
||||
href="#"
|
||||
onClick={() => {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
if (endPage < totalPages) handlePageChange(endPage + 1);
|
||||
}}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user