Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b6e8ceedb | ||
|
|
b4e3d922b1 | ||
|
|
a028b6ae8b | ||
|
|
ad0803f405 | ||
|
|
03675aaa60 | ||
|
|
c0c19c0425 | ||
|
|
214d283366 | ||
|
|
7d95ddf6a5 | ||
|
|
a19c5c269a | ||
|
|
6102e0af6b | ||
|
|
225bae08d3 |
@@ -1,12 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { useWrStore } from "@/app/store";
|
||||
import { type RvwHistTableType } from "@/app/store/matDmd/coMatRvw/type";
|
||||
import {
|
||||
DmdCoReqSchema,
|
||||
type DmdCoReqType,
|
||||
type RvwHistTableType,
|
||||
} from "@/app/store/matDmd/coMatRvw/type";
|
||||
import {
|
||||
confirmToast,
|
||||
formatPhoneNumber,
|
||||
getCity,
|
||||
getdmdMatFlag,
|
||||
@@ -27,11 +24,10 @@ import {
|
||||
} from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Button, Label } from "@common/components/ui";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import moment from "moment";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import toast, { Toaster } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
export default function RuseRvwHstry() {
|
||||
const {
|
||||
code,
|
||||
@@ -51,6 +47,7 @@ export default function RuseRvwHstry() {
|
||||
sgg: "",
|
||||
city: "",
|
||||
});
|
||||
const { t } = useTranslation('base');
|
||||
|
||||
const [fromDate, setFromDate] = useState<string>(
|
||||
String(new Date().getFullYear())
|
||||
@@ -116,53 +113,65 @@ export default function RuseRvwHstry() {
|
||||
}
|
||||
};
|
||||
|
||||
const form = useForm<DmdCoReqType>({
|
||||
resolver: zodResolver(DmdCoReqSchema),
|
||||
mode: "onChange",
|
||||
});
|
||||
|
||||
const TableCellClick = useCallback(
|
||||
(index: number | undefined) => {
|
||||
if (
|
||||
index !== undefined &&
|
||||
index >= 0 &&
|
||||
rvwHistRes &&
|
||||
rvwHistRes[index]
|
||||
) {
|
||||
form.reset(rvwHistRes[index]);
|
||||
(index: number | undefined, headId: string) => {
|
||||
if (index !== undefined && index >= 0) {
|
||||
const selectedData = rvwHistData;
|
||||
if (selectedData && selectedData.length > 0) {
|
||||
if (
|
||||
selectedData[index]?.splyFcltFlg === "검토완료" &&
|
||||
headId === "completeYn"
|
||||
) {
|
||||
setRvwHistData([...selectedData]);
|
||||
} else if (
|
||||
selectedData[index]?.splyFcltFlg === "매칭완료" &&
|
||||
headId === "completeYn"
|
||||
) {
|
||||
toast.error(t("canNotChangeMatStateMsg"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[rvwHistRes, form]
|
||||
[rvwHistData]
|
||||
);
|
||||
const confrirmToast = () => {
|
||||
const completeData = rvwHistData
|
||||
?.map((item) => {
|
||||
form.clearErrors();
|
||||
if (item?.completeYn) {
|
||||
if (item?.completeYn.chk && item.splyFcltFlg === "검토완료") {
|
||||
return Number(item.dmdInfoSn);
|
||||
}
|
||||
})
|
||||
.filter((item) => item !== undefined);
|
||||
if (form.formState.isDirty) {
|
||||
toast((t) => (
|
||||
<span className="flex flex-col items-center">
|
||||
표준공사비 정보가 변경되었습니다. 검토 완료 진행시 입력한 정보는
|
||||
초기화 됩니다.
|
||||
<br />
|
||||
진행하시겠습니까?
|
||||
<button
|
||||
onClick={() => {
|
||||
toast.dismiss(t.id);
|
||||
ruseRvwComplete(completeData as number[]);
|
||||
}}
|
||||
>
|
||||
확인
|
||||
</button>
|
||||
<button onClick={() => toast.dismiss(t.id)}>취소</button>
|
||||
</span>
|
||||
));
|
||||
|
||||
if (completeData && completeData?.length > 0) {
|
||||
confirmToast(t('isMatchFinishMsg'), () => ruseRvwComplete(completeData as number[]));
|
||||
|
||||
// const handleConfirm = async () => {
|
||||
// ruseRvwComplete(completeData as number[]);
|
||||
// };
|
||||
// toast((t) => (
|
||||
// <span className="flex flex-col items-center">
|
||||
// 매칭완료를 진행하시겠습니까?
|
||||
// <br />
|
||||
// <div className="mt-2 flex flex-row space-x-2">
|
||||
// <Button
|
||||
// size={"sm"}
|
||||
// onClick={() => {
|
||||
// toast.dismiss(t.id);
|
||||
// ruseRvwComplete(completeData as number[]);
|
||||
// }}
|
||||
// >
|
||||
// 확인
|
||||
// </Button>
|
||||
// <Button size={"sm"} onClick={() => toast.dismiss(t.id)}>
|
||||
// 취소
|
||||
// </Button>
|
||||
// </div>
|
||||
// </span>
|
||||
// ));
|
||||
} else {
|
||||
ruseRvwComplete(completeData as number[]);
|
||||
toast.error( t('isNotMatchFinishMsg'));
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
@@ -203,11 +212,10 @@ export default function RuseRvwHstry() {
|
||||
|
||||
rvwCmptnYmd: formatDate(item.demandMatching?.rvwCmptnYmd),
|
||||
mtchnCmptnYmd: formatDate(item.demandMatching?.mtchnCmptnYmd),
|
||||
|
||||
ruseUtztnFcltNm: item.ruseUtztnFcltNm,
|
||||
dmndQty: item.dmndQty,
|
||||
splyFcltFlg: flag,
|
||||
completeYn: false,
|
||||
completeYn: {chk:flag=="매칭완료", readonly:flag=="매칭완료"},
|
||||
} as unknown as RvwHistTableType;
|
||||
});
|
||||
|
||||
@@ -215,9 +223,6 @@ export default function RuseRvwHstry() {
|
||||
}
|
||||
}, [rvwHistRes]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("변경여부 ", form.formState.isDirty);
|
||||
}, [form.formState]);
|
||||
|
||||
return (
|
||||
<ContentsDiv>
|
||||
@@ -301,7 +306,7 @@ export default function RuseRvwHstry() {
|
||||
조회
|
||||
</Button>
|
||||
<Button size={"sm"} onClick={confrirmToast}>
|
||||
검토완료
|
||||
저장
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -319,18 +324,14 @@ export default function RuseRvwHstry() {
|
||||
headlist={ruseHistHeadList}
|
||||
pageSize={20}
|
||||
total={rvwHistCount}
|
||||
cellClick={(index: number | undefined) => {
|
||||
TableCellClick(index);
|
||||
cellClick={(index: number | undefined, headId: string) => {
|
||||
console.log("테이블 클릭", index);
|
||||
TableCellClick(index, headId);
|
||||
}}
|
||||
onPageChange={(page) => {
|
||||
setPageNatiion(page);
|
||||
}}
|
||||
></UiTable>
|
||||
{/* <hr />
|
||||
<h3 className="mt-4 ml-2 text-2xl font-medium text-label">
|
||||
수요신청 상세현황
|
||||
</h3>
|
||||
<ConCostForm form={form} type={"hist"} selectionVersion={0} /> */}
|
||||
</ListDiv>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -364,6 +364,7 @@ export default function PublicReuseFaciltyInsert() {
|
||||
setIndexMng(index);
|
||||
}}
|
||||
indexMng={indexMng}
|
||||
readonly={false}
|
||||
/>
|
||||
</TabsContent>
|
||||
<TabsContent className="max-h-full" value="buse">
|
||||
|
||||
@@ -16,50 +16,44 @@ import {
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Button } from "@common/components/ui";
|
||||
import { useEffect, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function RainStat() {
|
||||
const { code, rainStat, searchRainStatList } = useWrStore((state) => state);
|
||||
const { rainStatList, excelList, rainDetailList } = rainStat;
|
||||
const { rainStatList, rainDetailList } = rainStat;
|
||||
|
||||
const [searchYear, setSearchYear] = useState<string>(
|
||||
String(new Date().getFullYear())
|
||||
);
|
||||
const [exData, setExData] = useState<Array<Record<string, string | number>>>();
|
||||
//const [exData, setExData] = useState<Array<Record<string, string | number>>>();
|
||||
const [bdstTable, setBdstTable] = useState<RainStatProps[]>();
|
||||
const { t } = useTranslation('base');
|
||||
|
||||
useEffect(() => {
|
||||
searchRainStatList(searchYear);
|
||||
}, [code.cityCd, code.sggCd, searchRainStatList])
|
||||
searchRainStatList(searchYear ,code.cityCd);
|
||||
}, [code.cityCd, searchRainStatList])
|
||||
|
||||
const excelDetailDownLoad=() =>{
|
||||
const excelDetailDownLoad = () => {
|
||||
const sidoList = new Set<string>();
|
||||
const sidoDataMap = new Map<string, (string | number)[]>(); // 시도별 데이터를 저장할 Map
|
||||
const sidoDetailMap = new Map<string, (string | number)[][]>(); // 시도별 상세 데이터를 저장할 Map
|
||||
|
||||
// 먼저 시도별 상세 데이터를 그룹화
|
||||
rainDetailList.forEach((item: RainStatProps[]) => {
|
||||
// 복사된 배열을 사용
|
||||
const transformedRainDetailList = rainDetailList.map((originItem: RainStatProps[]) => {
|
||||
const item = [...originItem]; // 원본 복사
|
||||
const sidoVal = item.at(0)?.toString().trim();
|
||||
const sigunVal = item.at(1)?.toString().trim();
|
||||
|
||||
let sidoText = '';
|
||||
let sigunText = '';
|
||||
|
||||
const sido = code.cityCd.find((city) => city.val === sidoVal);
|
||||
const sigun = code.sggCd.find((sgg) => sgg.val === sigunVal);
|
||||
|
||||
sidoText = sido?.text || '';
|
||||
sigunText = sigun?.text || '';
|
||||
|
||||
// 시도, 시군구 코드를 텍스트로 변환하여 데이터에 할당
|
||||
if (item.length > 0) {
|
||||
item[0] = sidoText as unknown as RainStatProps;
|
||||
}
|
||||
if (item.length > 1) {
|
||||
item[1] = sigunText as unknown as RainStatProps;
|
||||
}
|
||||
if (item.length > 2) {
|
||||
item[2] = sidoText+' '+sigunText as unknown as RainStatProps;
|
||||
}
|
||||
const sidoText = sido?.text || '';
|
||||
const sigunText = sigun?.text || '';
|
||||
|
||||
if (item.length > 0) item[0] = sidoText as unknown as RainStatProps;
|
||||
if (item.length > 1) item[1] = sigunText as unknown as RainStatProps;
|
||||
if (item.length > 2) item[2] = `${sidoText} ${sigunText}` as unknown as RainStatProps;
|
||||
|
||||
// 시도별 상세 데이터 수집
|
||||
if (sidoText) {
|
||||
@@ -72,53 +66,40 @@ export default function RainStat() {
|
||||
// 시도별 합계 데이터 수집
|
||||
if (sidoText && !sidoList.has(sidoText)) {
|
||||
sidoList.add(sidoText);
|
||||
// 시도별 초기 데이터 구조 생성 (예: [시도명, 0, 0, 0, ...])
|
||||
const initialData: (string | number)[] = [sidoText];
|
||||
// 데이터의 나머지 컬럼들을 0으로 초기화 (실제 컬럼 수에 맞게 조정 필요)
|
||||
for (let i = 1; i < item.length; i++) {
|
||||
initialData.push(0);
|
||||
}
|
||||
sidoDataMap.set(sidoText, initialData);
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
// 시도별 합계 계산
|
||||
rainDetailList.forEach((item: RainStatProps[]) => {
|
||||
// 이후 합계 계산에서도 transformedRainDetailList 사용
|
||||
transformedRainDetailList.forEach((item: RainStatProps[]) => {
|
||||
const sidoText = item[0]?.toString();
|
||||
if (sidoText && sidoDataMap.has(sidoText)) {
|
||||
const sidoData = sidoDataMap.get(sidoText)!;
|
||||
// 각 컬럼의 값을 합계에 더하기 (1번 인덱스부터 시작)
|
||||
for (let i = 1; i < item.length && i < sidoData.length; i++) {
|
||||
if(i == 2){
|
||||
if (i == 2) {
|
||||
sidoData[i] = '합계';
|
||||
} else if(i == 3){
|
||||
// 해당 시도의 데이터 개수를 계산
|
||||
const sidoDataCount = rainDetailList.filter((data: unknown[]) =>
|
||||
} else if (i == 3) {
|
||||
const sidoDataCount = transformedRainDetailList.filter((data: unknown[]) =>
|
||||
Array.isArray(data) && data.length > 0 && String(data[0]) === sidoText
|
||||
).length;
|
||||
sidoData[i] = sidoDataCount;
|
||||
} else if( i == 4){
|
||||
} else if (i == 4) {
|
||||
sidoData[i] = '';
|
||||
} else if(i == 6){
|
||||
// 법정 대상 건축물 개수 (인덱스 6이 'Y'인 경우)
|
||||
const bumCnt = rainDetailList.filter((data: unknown[]) =>
|
||||
} else if (i == 6) {
|
||||
const bumCnt = transformedRainDetailList.filter((data: unknown[]) =>
|
||||
Array.isArray(data) && data.length > 6 && String(data[0]) === sidoText
|
||||
).filter((data: unknown[]) => String(data[6]) === '대상').length;
|
||||
sidoData[i] = bumCnt;
|
||||
} else if(i==8){
|
||||
const value = Number(item[8]) || 0;
|
||||
} else if ([8, 11, 12, 14].includes(i)) {
|
||||
const value = Number(item[i]) || 0;
|
||||
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
|
||||
} else if(i==11){
|
||||
const value = Number(item[11]) || 0;
|
||||
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
|
||||
} else if(i==12){
|
||||
const value = Number(item[12]) || 0;
|
||||
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
|
||||
} else if(i==14){
|
||||
const value = Number(item[14]) || 0;
|
||||
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sidoData[i] = '';
|
||||
}
|
||||
}
|
||||
@@ -127,12 +108,12 @@ export default function RainStat() {
|
||||
|
||||
// 시도별로 합계와 상세 데이터를 순서대로 배치
|
||||
const summaryExcelData: (string | number)[][] = [];
|
||||
|
||||
|
||||
// 시도별로 순회하면서 합계와 상세 데이터를 추가
|
||||
Array.from(sidoList).forEach((sidoText) => {
|
||||
const sidoSummary = sidoDataMap.get(sidoText);
|
||||
const sidoDetails = sidoDetailMap.get(sidoText) || [];
|
||||
|
||||
|
||||
if (sidoSummary) {
|
||||
// 시도 합계 데이터 추가
|
||||
summaryExcelData.push(sidoSummary);
|
||||
@@ -144,62 +125,91 @@ export default function RainStat() {
|
||||
});
|
||||
|
||||
const sidoSummaryList = Array.from(sidoDataMap.values());
|
||||
const sidoTotalSummary = [['전체', '', '합계', 0, '', '', 0, '', '', 0, 0, 0, 0, 0, 0, '', 0]];
|
||||
const sidoTotalSummary = [['전국', '', '합계', 0, '', '', 0, '', '', 0, 0, 0, 0, 0, 0, '']];
|
||||
sidoSummaryList.forEach((item: (string | number)[]) => {
|
||||
item.forEach((value: string | number, index: number) => {
|
||||
if(typeof value === 'number') {
|
||||
if (typeof value === 'number') {
|
||||
if (sidoTotalSummary[0] && index < sidoTotalSummary[0].length) {
|
||||
sidoTotalSummary[0][index] = Number(sidoTotalSummary[0][index]) + Number(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// sidoSummaryList와 rainDetailList를 합쳐서 엑셀 데이터 생성
|
||||
const excelData = [...sidoTotalSummary, ...sidoSummaryList, ...summaryExcelData];
|
||||
|
||||
|
||||
console.log(' excelData ', excelData)
|
||||
excelDownload(
|
||||
excelData as unknown as [][],
|
||||
"빗물이용시설 통계",
|
||||
"sample_rainStats.xlsx",
|
||||
"A1:V3",
|
||||
"A1:O3",
|
||||
4
|
||||
);
|
||||
}
|
||||
|
||||
const excelClick = () => {
|
||||
if(bdstTable){
|
||||
const tbData = bdstTable .map((item: RainStatProps) => {
|
||||
return {
|
||||
"시도": item.cityText,
|
||||
"개소": item.tmp,
|
||||
"설치비(백만원)": item.instlCst,
|
||||
"저류조용량(m³/년)": item.dtfcltCpct,
|
||||
"연간사용량(m³/년)": item.wtrUsqty,
|
||||
"조경용수": item.lndwtr,
|
||||
"청소화장실용수": item.cleanToilUswtr,
|
||||
"세척살수용수": item.resn,
|
||||
"농업용수": item.farmUswtr,
|
||||
"공업용수": item.indstUswtr,
|
||||
"친수용수": item.hydUswtr,
|
||||
"기타": item.ithlEtcUswtr,
|
||||
"연간운영비(백만원/년)": item.anlOperCst,
|
||||
};
|
||||
})
|
||||
downloadExcel({
|
||||
data: (exData as unknown as JSON[]) ?? [],
|
||||
data: (tbData as unknown as JSON[]) ?? [],
|
||||
fileName: "재이용통계",
|
||||
sheetNameArray: ["Sheet1"],
|
||||
headerRange: "A1:M1"
|
||||
})
|
||||
}else{
|
||||
toast.error(t('excelDownErrMsg'));
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const transExcel = Array.isArray(excelList) ? excelList : [excelList];
|
||||
const excelData = tableData(transExcel, { code });
|
||||
const tbData = Array.isArray(excelData)
|
||||
? excelData.map((item: RainStatProps) => {
|
||||
return {
|
||||
"시도": item.cityText,
|
||||
"개소": item.tmp,
|
||||
"설치비(백만원)": item.instlCst,
|
||||
"저류조용량(m³/년)": item.dtfcltCpct,
|
||||
"연간사용량(m³/년)": item.wtrUsqty,
|
||||
"조경용수": item.lndwtr,
|
||||
"청소화장실용수": item.cleanToilUswtr,
|
||||
"세척살수용수": item.resn,
|
||||
"농업용수": item.farmUswtr,
|
||||
"공업용수": item.indstUswtr,
|
||||
"친수용수": item.hydUswtr,
|
||||
"기타": item.ithlEtcUswtr,
|
||||
"연간운영비(백만원/년)": item.anlOperCst,
|
||||
};
|
||||
})
|
||||
: [];
|
||||
setExData(tbData);
|
||||
}, [code, excelList])
|
||||
|
||||
// useEffect(() => {
|
||||
// if(excelList && excelList.length>0){
|
||||
// console.log('excelList ', excelList)
|
||||
|
||||
// const transExcel = Array.isArray(excelList) ? excelList : [excelList];
|
||||
// const excelData = tableData(transExcel, { code });
|
||||
// const tbData = Array.isArray(excelData)
|
||||
// ? excelData
|
||||
// .filter((item: RainStatProps) => item.cityText !== '없음')
|
||||
// .map((item: RainStatProps) => {
|
||||
// return {
|
||||
// "시도": item.cityText,
|
||||
// "개소": item.tmp,
|
||||
// "설치비(백만원)": item.instlCst,
|
||||
// "저류조용량(m³/년)": item.dtfcltCpct,
|
||||
// "연간사용량(m³/년)": item.wtrUsqty,
|
||||
// "조경용수": item.lndwtr,
|
||||
// "청소화장실용수": item.cleanToilUswtr,
|
||||
// "세척살수용수": item.resn,
|
||||
// "농업용수": item.farmUswtr,
|
||||
// "공업용수": item.indstUswtr,
|
||||
// "친수용수": item.hydUswtr,
|
||||
// "기타": item.ithlEtcUswtr,
|
||||
// "연간운영비(백만원/년)": item.anlOperCst,
|
||||
// };
|
||||
// })
|
||||
// : [];
|
||||
// setExData(tbData);
|
||||
// }
|
||||
// }, [code, excelList])
|
||||
|
||||
useEffect(() => {
|
||||
const transData = Array.isArray(rainStatList) ? rainStatList : [rainStatList];
|
||||
@@ -208,11 +218,13 @@ export default function RainStat() {
|
||||
? data.map((item: RainStatProps) => {
|
||||
return {
|
||||
...item,
|
||||
ctpvCd: item.cityText
|
||||
ctpvCd: item.cityText==='전체'?'전국': item.cityText,
|
||||
cityText: item.cityText==='전체'?'전국': item.cityText,
|
||||
};
|
||||
}).filter((item: RainStatProps) => item.cityText !== '없음')
|
||||
: [];
|
||||
|
||||
|
||||
setBdstTable(tbData);
|
||||
}, [code, rainStatList]);
|
||||
|
||||
@@ -237,7 +249,7 @@ export default function RainStat() {
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-row space-x-2 items-center">
|
||||
<Button className="" size={"sm"} onClick={()=>{searchRainStatList(searchYear);}}>
|
||||
<Button className="" size={"sm"} onClick={() => { searchRainStatList(searchYear ,code.cityCd); }}>
|
||||
조회
|
||||
</Button>
|
||||
<Button className="" size={"sm"} onClick={() => excelClick()}>
|
||||
@@ -264,7 +276,7 @@ export default function RainStat() {
|
||||
total={0}
|
||||
headName={""}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
onPageChange={() => { }}
|
||||
></UiTable>
|
||||
</ScrollArea>
|
||||
</ListDiv>
|
||||
|
||||
@@ -55,29 +55,31 @@ export default function RswtStat() {
|
||||
const transExcel = Array.isArray(excelList) ? excelList : [excelList];
|
||||
const exData = tableData(transExcel, { code });
|
||||
const tbData = Array.isArray(exData) ?
|
||||
exData.map((item: RswtStatProps) => {
|
||||
return {
|
||||
"시도": item.cityText,
|
||||
"개소": item.ctpvCnt,
|
||||
// "건축연면적(m³)": item.archArea,
|
||||
"처리용량(m³)": item.filtrTrtmfctCpct,
|
||||
"물사용량(m³/년)": item.wtrUsqty,
|
||||
"중수도+대체수이용량(m³/년)": item.rswtAltSum,
|
||||
"중수도이용량(m³/년)": item.rswtrUsqty,
|
||||
"대체수이용량(m³/년)": item.altUswtrUtztnQnt,
|
||||
"조경용수": item.lndwtr,
|
||||
"청소화장실용수": item.cleanToilUswtr,
|
||||
"농업용수": item.farmUswtr,
|
||||
"공업용수": item.indstUswtr,
|
||||
"친수용수": item.hydUswtr,
|
||||
"기타": item.ithlEtcUswtr,
|
||||
"연간운영비(백만원/년)": item.anlOperCst,
|
||||
};
|
||||
}) : [];
|
||||
exData
|
||||
.filter((item: RswtStatProps) => item.cityText !== '없음')
|
||||
.map((item: RswtStatProps) => {
|
||||
return {
|
||||
"시도": item.cityText,
|
||||
"개소": item.ctpvCnt,
|
||||
// "건축연면적(m³)": item.archArea,
|
||||
"처리용량(m³)": item.filtrTrtmfctCpct,
|
||||
"물사용량(m³/년)": item.wtrUsqty,
|
||||
"중수도+대체수이용량(m³/년)": item.rswtAltSum,
|
||||
"중수도이용량(m³/년)": item.rswtrUsqty,
|
||||
"대체수이용량(m³/년)": item.altUswtrUtztnQnt,
|
||||
"조경용수": item.lndwtr,
|
||||
"청소화장실용수": item.cleanToilUswtr,
|
||||
"농업용수": item.farmUswtr,
|
||||
"공업용수": item.indstUswtr,
|
||||
"친수용수": item.hydUswtr,
|
||||
"기타": item.ithlEtcUswtr,
|
||||
"연간운영비(백만원/년)": item.anlOperCst,
|
||||
};
|
||||
}) : [];
|
||||
setExceData(tbData);
|
||||
}, [code, excelList])
|
||||
|
||||
const excelDetailDownLoad=() =>{
|
||||
const excelDetailDownLoad = () => {
|
||||
const sidoList = new Set<string>();
|
||||
const sidoDataMap = new Map<string, (string | number)[]>(); // 시도별 데이터를 저장할 Map
|
||||
const sidoDetailMap = new Map<string, (string | number)[][]>(); // 시도별 상세 데이터를 저장할 Map
|
||||
@@ -94,7 +96,7 @@ export default function RswtStat() {
|
||||
|
||||
sidoText = sido?.text || '';
|
||||
sigunText = sigun?.text || '';
|
||||
|
||||
|
||||
// 시도, 시군구 코드를 텍스트로 변환하여 데이터에 할당
|
||||
if (item.length > 0) {
|
||||
item[0] = sidoText as unknown as RswtStatProps;
|
||||
@@ -103,7 +105,7 @@ export default function RswtStat() {
|
||||
item[1] = sigunText as unknown as RswtStatProps;
|
||||
}
|
||||
if (item.length > 2) {
|
||||
item[2] = sidoText+' '+sigunText as unknown as RswtStatProps;
|
||||
item[2] = sidoText + ' ' + sigunText as unknown as RswtStatProps;
|
||||
}
|
||||
|
||||
// 시도별 상세 데이터 수집
|
||||
@@ -113,7 +115,7 @@ export default function RswtStat() {
|
||||
}
|
||||
sidoDetailMap.get(sidoText)!.push(item as unknown as (string | number)[]);
|
||||
}
|
||||
|
||||
|
||||
// 시도별 합계 데이터 수집
|
||||
if (sidoText && !sidoList.has(sidoText)) {
|
||||
sidoList.add(sidoText);
|
||||
@@ -134,41 +136,41 @@ export default function RswtStat() {
|
||||
const sidoData = sidoDataMap.get(sidoText)!;
|
||||
// 각 컬럼의 값을 합계에 더하기 (1번 인덱스부터 시작)
|
||||
for (let i = 1; i < item.length && i < sidoData.length; i++) {
|
||||
if(i == 2){
|
||||
if (i == 2) {
|
||||
sidoData[i] = '합계';
|
||||
} else if(i == 3){
|
||||
} else if (i == 3) {
|
||||
// 해당 시도의 데이터 개수를 계산
|
||||
const sidoDataCount = rswtDetailList.filter((data: unknown[]) =>
|
||||
const sidoDataCount = rswtDetailList.filter((data: unknown[]) =>
|
||||
Array.isArray(data) && data.length > 0 && String(data[0]) === sidoText
|
||||
).length;
|
||||
sidoData[i] = sidoDataCount;
|
||||
} else if( i == 4){
|
||||
} else if (i == 4) {
|
||||
sidoData[i] = '';
|
||||
} else if(i == 6){
|
||||
} else if (i == 6) {
|
||||
// 법정 대상 건축물 개수 (인덱스 6이 'Y'인 경우)
|
||||
const bumCnt = rswtDetailList.filter((data: unknown[]) =>
|
||||
const bumCnt = rswtDetailList.filter((data: unknown[]) =>
|
||||
Array.isArray(data) && data.length > 6 && String(data[0]) === sidoText
|
||||
).filter((data: unknown[]) => String(data[6]) === '대상').length;
|
||||
sidoData[i] = bumCnt;
|
||||
} else if(i==9){
|
||||
} else if (i == 9) {
|
||||
const value = Number(item[9]) || 0;
|
||||
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
|
||||
} else if(i==10){
|
||||
} else if (i == 10) {
|
||||
const value = Number(item[10]) || 0;
|
||||
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
|
||||
} else if(i==11){
|
||||
} else if (i == 11) {
|
||||
const value = Number(item[11]) || 0;
|
||||
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
|
||||
} else if(i==12){
|
||||
} else if (i == 12) {
|
||||
const value = Number(item[12]) || 0;
|
||||
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
|
||||
}else if(i==13){
|
||||
} else if (i == 13) {
|
||||
const value = Number(item[13]) || 0;
|
||||
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
|
||||
} else if(i==14){
|
||||
} else if (i == 14) {
|
||||
const value = Number(item[14]) || 0;
|
||||
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
|
||||
} else if(i==16){
|
||||
} else if (i == 16) {
|
||||
const value = Number(item[16]) || 0;
|
||||
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
|
||||
} else {
|
||||
@@ -177,15 +179,15 @@ export default function RswtStat() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 시도별로 합계와 상세 데이터를 순서대로 배치
|
||||
const summaryExcelData: (string | number)[][] = [];
|
||||
|
||||
|
||||
// 시도별로 순회하면서 합계와 상세 데이터를 추가
|
||||
Array.from(sidoList).forEach((sidoText) => {
|
||||
const sidoSummary = sidoDataMap.get(sidoText);
|
||||
const sidoDetails = sidoDetailMap.get(sidoText) || [];
|
||||
|
||||
|
||||
if (sidoSummary) {
|
||||
// 시도 합계 데이터 추가
|
||||
summaryExcelData.push(sidoSummary);
|
||||
@@ -200,7 +202,7 @@ export default function RswtStat() {
|
||||
const sidoTotalSummary = [['전체', '', '합계', 0, '', '', 0, '', '', 0, 0, 0, 0, 0, 0, '', 0]];
|
||||
sidoSummaryList.forEach((item: (string | number)[]) => {
|
||||
item.forEach((value: string | number, index: number) => {
|
||||
if(typeof value === 'number') {
|
||||
if (typeof value === 'number') {
|
||||
if (sidoTotalSummary[0] && index < sidoTotalSummary[0].length) {
|
||||
sidoTotalSummary[0][index] = Number(sidoTotalSummary[0][index]) + Number(value);
|
||||
}
|
||||
@@ -209,7 +211,7 @@ export default function RswtStat() {
|
||||
});
|
||||
|
||||
// sidoSummaryList와 rainDetailList를 합쳐서 엑셀 데이터 생성
|
||||
const excelData = [...sidoTotalSummary,...sidoSummaryList, ...summaryExcelData];
|
||||
const excelData = [...sidoTotalSummary, ...sidoSummaryList, ...summaryExcelData];
|
||||
|
||||
excelDownload(
|
||||
excelData as unknown as [][],
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { ChkClass } from "@common/business_components/ui";
|
||||
import { z } from "zod";
|
||||
|
||||
const DemandInfoSchema = z.object({
|
||||
@@ -130,7 +131,7 @@ export type RvwHistTableType = {
|
||||
dmndQty: string;
|
||||
useUsgCd: string;
|
||||
splyFcltFlg: string;
|
||||
completeYn: boolean;
|
||||
completeYn: ChkClass;
|
||||
dmdInfoSn: string;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ export const ruseHstryHeadListExport:TableUpperProps[]= [
|
||||
id: "cityText",
|
||||
title: "시도",
|
||||
visible: true,
|
||||
|
||||
},
|
||||
{
|
||||
id: "sggText",
|
||||
|
||||
@@ -130,7 +130,7 @@ export const ruseHstryActionsExport: (set: any) => ruseHstryActions = (
|
||||
toast.success("매칭 계산 저장이 완료입니다.");
|
||||
const rvwHistRes = await irvwHistInit(
|
||||
1,
|
||||
10,
|
||||
13,
|
||||
new Date().getFullYear().toString(),
|
||||
new Date().getFullYear().toString(),
|
||||
);
|
||||
@@ -217,10 +217,10 @@ export const ruseHstryActionsExport: (set: any) => ruseHstryActions = (
|
||||
fetchType.WR
|
||||
);
|
||||
if (complet.status === 200) {
|
||||
toast.success("완료 처리가 완료되었습니다.");
|
||||
toast.success("매칭완료가 완료되었습니다.");
|
||||
const rvwHistRes = await irvwHistInit(
|
||||
1,
|
||||
10,
|
||||
13,
|
||||
new Date().getFullYear().toString(),
|
||||
new Date().getFullYear().toString(),
|
||||
);
|
||||
@@ -236,7 +236,7 @@ export const ruseHstryActionsExport: (set: any) => ruseHstryActions = (
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(" error ", e);
|
||||
toast.error("완료 처리 중 오류가 발생했습니다.");
|
||||
toast.error("매칭 완료 처리 중 오류가 발생했습니다.");
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -195,7 +195,7 @@ export const rainChkgdnHeadListExport: TableUpperProps[] = [
|
||||
title: "부과금액(천원)",
|
||||
upName: "feeHist",
|
||||
upSequnce: 3,
|
||||
type: "number",
|
||||
type: "text",
|
||||
edit: true,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -2,158 +2,215 @@ import { fetchType, getFetch } from "@/components/lib/api";
|
||||
import type { TableUpperProps } from "../../common/type/header";
|
||||
import { excelRainStat } from "./excel";
|
||||
import { rainStatHeadListExport } from "./headList";
|
||||
import type { SelectDataType } from "@common/business_components/ui";
|
||||
|
||||
export type RainStatProps = {
|
||||
cityText: string
|
||||
ctpvCd: string //시도
|
||||
sggCd: string //시군구
|
||||
areaNm: string //행정구역명
|
||||
bdstNm: string //시설명
|
||||
bdstUsgCd: string //건축물용도코드
|
||||
daddr: string //주소
|
||||
lawTrgtYn: string //법적의무대상여부
|
||||
instlCmptnDt: string //설치완료일자
|
||||
instlCst: number //설치비용
|
||||
pntfColKnd: string //접수면종류
|
||||
filtrTrtmfctYn: string //여과등처리시설유무
|
||||
archArea: number //건축연면적
|
||||
dtfcltCpct: number //처리용량(저류조용량)
|
||||
wtrUsqty: number //연간사용량
|
||||
utztnUsgCd: string //이용용도코드
|
||||
anlOperCst: number //연간운영비
|
||||
annRnwtQty: number //물사용량
|
||||
jungsudo: number //중수도이용량
|
||||
dachae: number //대체수이용량
|
||||
lndwtr: number //조경용수
|
||||
cleanToilUswtr: number //청소화장실용수
|
||||
resn: number //세척살수용수
|
||||
farmUswtr: number //농업용수
|
||||
indstUswtr: number //공업용수
|
||||
hydUswtr: number //친수용수
|
||||
ithlEtcUswtr: number //기타
|
||||
tmp: number //개소
|
||||
guideStats: GuideStatProps[]
|
||||
}
|
||||
cityText: string;
|
||||
ctpvCd: string; //시도
|
||||
sggCd: string; //시군구
|
||||
areaNm: string; //행정구역명
|
||||
bdstNm: string; //시설명
|
||||
bdstUsgCd: string; //건축물용도코드
|
||||
daddr: string; //주소
|
||||
lawTrgtYn: string; //법적의무대상여부
|
||||
instlCmptnDt: string; //설치완료일자
|
||||
instlCst: number; //설치비용
|
||||
pntfColKnd: string; //접수면종류
|
||||
filtrTrtmfctYn: string; //여과등처리시설유무
|
||||
archArea: number; //건축연면적
|
||||
dtfcltCpct: number; //처리용량(저류조용량)
|
||||
wtrUsqty: number; //연간사용량
|
||||
utztnUsgCd: string; //이용용도코드
|
||||
anlOperCst: number; //연간운영비
|
||||
annRnwtQty: number; //물사용량
|
||||
jungsudo: number; //중수도이용량
|
||||
dachae: number; //대체수이용량
|
||||
lndwtr: number; //조경용수
|
||||
cleanToilUswtr: number; //청소화장실용수
|
||||
resn: number; //세척살수용수
|
||||
farmUswtr: number; //농업용수
|
||||
indstUswtr: number; //공업용수
|
||||
hydUswtr: number; //친수용수
|
||||
ithlEtcUswtr: number; //기타
|
||||
tmp: number; //개소
|
||||
guideStats: GuideStatProps[];
|
||||
};
|
||||
|
||||
export type GuideStatProps = {
|
||||
utztnUsgCd: string
|
||||
splyUswtrUtztnQnt : number,
|
||||
ruseFcltUtztnQnt: number
|
||||
}
|
||||
utztnUsgCd: string;
|
||||
splyUswtrUtztnQnt: number;
|
||||
ruseFcltUtztnQnt: number;
|
||||
};
|
||||
|
||||
type ExcelType = {
|
||||
[key: string]: string | number | undefined;
|
||||
[key: string]: string | number | undefined;
|
||||
};
|
||||
|
||||
const excelDownList: ExcelType[] = [];
|
||||
|
||||
const fetchRainStatList = async (year: string) => {
|
||||
const res = await getFetch(fetchType.WR, `/reuseChk/rainy/stat/${year}`)
|
||||
return res;
|
||||
}
|
||||
const res = await getFetch(fetchType.WR, `/reuseChk/rainy/stat/${year}`);
|
||||
return res;
|
||||
};
|
||||
|
||||
type rainStatActions = {
|
||||
searchRainStatList: (year: string) => void
|
||||
}
|
||||
searchRainStatList: (year: string, city: SelectDataType[]) => void;
|
||||
};
|
||||
|
||||
export type rainStatState = {
|
||||
rainStat: {
|
||||
rainStatHeadList: TableUpperProps[],
|
||||
rainStatList: RainStatProps[],
|
||||
excelList: ExcelType[]
|
||||
rainDetailList : [][]
|
||||
}
|
||||
}
|
||||
rainStat: {
|
||||
rainStatHeadList: TableUpperProps[];
|
||||
rainStatList: RainStatProps[];
|
||||
excelList: ExcelType[];
|
||||
rainDetailList: [][];
|
||||
};
|
||||
};
|
||||
|
||||
export type rainStatType = rainStatState & rainStatActions;
|
||||
|
||||
export const rainStatExport: rainStatState = {
|
||||
rainStat: {
|
||||
rainStatHeadList: rainStatHeadListExport,
|
||||
rainStatList: [],
|
||||
excelList: [],
|
||||
rainDetailList : []
|
||||
}
|
||||
}
|
||||
rainStat: {
|
||||
rainStatHeadList: rainStatHeadListExport,
|
||||
rainStatList: [],
|
||||
excelList: [],
|
||||
rainDetailList: [],
|
||||
},
|
||||
};
|
||||
export const rainStatActionsExport = (
|
||||
set: (fn: (state: rainStatState) => rainStatState) => void
|
||||
set: (fn: (state: rainStatState) => rainStatState) => void
|
||||
) => {
|
||||
return {
|
||||
searchRainStatList: async (year: string) => {
|
||||
const res = await fetchRainStatList(year);
|
||||
const cityArr: any[] = [];
|
||||
res.forEach((item: RainStatProps) => {
|
||||
return {
|
||||
searchRainStatList: async (year: string, city: SelectDataType[]) => {
|
||||
const res = await fetchRainStatList(year);
|
||||
const cityArr: any[] = [];
|
||||
|
||||
|
||||
let obj = cityArr.find((e) => {
|
||||
return e.ctpvCd == item.ctpvCd
|
||||
})
|
||||
res.filter((resFilter: RainStatProps) =>
|
||||
city.some((cityCd) =>
|
||||
resFilter.ctpvCd?.trim() === cityCd.val.trim()
|
||||
)
|
||||
)
|
||||
.forEach((item: RainStatProps) => {
|
||||
let obj = cityArr.find((e) => {
|
||||
return e.ctpvCd == item.ctpvCd;
|
||||
});
|
||||
|
||||
if (obj) {
|
||||
obj.instlCst += item.instlCst
|
||||
obj.dtfcltCpct += item.dtfcltCpct
|
||||
obj.wtrUsqty += item.wtrUsqty
|
||||
obj.anlOperCst += item.anlOperCst
|
||||
obj.tmp += 1
|
||||
} else {
|
||||
obj = {};
|
||||
obj.ctpvCd = item.ctpvCd
|
||||
obj.instlCst = item.instlCst
|
||||
obj.tmp = 1
|
||||
obj.dtfcltCpct = item.dtfcltCpct
|
||||
obj.wtrUsqty = item.wtrUsqty
|
||||
obj.anlOperCst = item.anlOperCst
|
||||
if (obj) {
|
||||
obj.instlCst += item.instlCst;
|
||||
obj.dtfcltCpct += item.dtfcltCpct;
|
||||
obj.wtrUsqty += item.wtrUsqty;
|
||||
obj.anlOperCst += item.anlOperCst;
|
||||
obj.tmp += 1;
|
||||
} else {
|
||||
obj = {};
|
||||
obj.ctpvCd = item.ctpvCd;
|
||||
obj.instlCst = item.instlCst;
|
||||
obj.tmp = 1;
|
||||
obj.dtfcltCpct = item.dtfcltCpct;
|
||||
obj.wtrUsqty = item.wtrUsqty;
|
||||
obj.anlOperCst = item.anlOperCst;
|
||||
|
||||
cityArr.push(obj)
|
||||
cityArr.push(obj);
|
||||
}
|
||||
|
||||
if (item.guideStats && item.guideStats.length > 0) {
|
||||
item.guideStats.forEach((guide: GuideStatProps) => {
|
||||
rainStatHeadListExport.forEach((headItem: TableUpperProps) => {
|
||||
if (headItem.title == guide.utztnUsgCd) {
|
||||
if (!obj[headItem.id] || typeof obj[headItem.id] !== "number")
|
||||
obj[headItem.id] = 0;
|
||||
if (typeof obj[headItem.id] === "number") {
|
||||
obj[headItem.id] += guide.ruseFcltUtztnQnt;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (item.guideStats && item.guideStats.length > 0) {
|
||||
item.guideStats.forEach((guide: GuideStatProps) => {
|
||||
rainStatHeadListExport.forEach((headItem: TableUpperProps) => {
|
||||
const totalObj = {
|
||||
ctpvCd: "0",
|
||||
tmp: 0,
|
||||
instlCst: 0, //설치비
|
||||
dtfcltCpct: 0, //저류조용량
|
||||
bdstUsgCd: 0, //연간사용량
|
||||
lndwtr: 0, //조경용수
|
||||
cleanToilUswtr: 0, //청소화장실용수
|
||||
resn: 0, //세척살수용수
|
||||
farmUswtr: 0, //농업용수
|
||||
indstUswtr: 0, //공업용수
|
||||
hydUswtr: 0, //친수용수
|
||||
ithlEtcUswtr: 0, //기타
|
||||
anlOperCst: 0, //연간운영비
|
||||
} as any;
|
||||
|
||||
if (headItem.title == guide.utztnUsgCd) {
|
||||
if (!obj[headItem.id] || typeof obj[headItem.id] !== "number") obj[headItem.id] = 0;
|
||||
if (typeof obj[headItem.id] === "number") {
|
||||
cityArr.forEach((item) => {
|
||||
// if(item.ctpvCd === '0') return; // Skip total object if exists
|
||||
totalObj.tmp += !isNaN(Number(item.tmp)) ? Number(item.tmp) : 0;
|
||||
totalObj.instlCst += !isNaN(Number(item.instlCst))
|
||||
? Number(item.instlCst)
|
||||
: 0;
|
||||
totalObj.dtfcltCpct += !isNaN(Number(item.dtfcltCpct))
|
||||
? Number(item.dtfcltCpct)
|
||||
: 0;
|
||||
totalObj.bdstUsgCd += !isNaN(Number(item.bdstUsgCd))
|
||||
? Number(item.bdstUsgCd)
|
||||
: 0;
|
||||
totalObj.lndwtr += !isNaN(Number(item.lndwtr))
|
||||
? Number(item.lndwtr)
|
||||
: 0;
|
||||
totalObj.cleanToilUswtr += !isNaN(Number(item.cleanToilUswtr))
|
||||
? Number(item.cleanToilUswtr)
|
||||
: 0;
|
||||
totalObj.resn += !isNaN(Number(item.resn)) ? Number(item.resn) : 0;
|
||||
totalObj.farmUswtr += !isNaN(Number(item.farmUswtr))
|
||||
? Number(item.farmUswtr)
|
||||
: 0;
|
||||
totalObj.indstUswtr += !isNaN(Number(item.indstUswtr))
|
||||
? Number(item.indstUswtr)
|
||||
: 0;
|
||||
totalObj.hydUswtr += !isNaN(Number(item.hydUswtr))
|
||||
? Number(item.hydUswtr)
|
||||
: 0;
|
||||
totalObj.ithlEtcUswtr += !isNaN(Number(item.ithlEtcUswtr))
|
||||
? Number(item.ithlEtcUswtr)
|
||||
: 0;
|
||||
totalObj.anlOperCst += !isNaN(Number(item.anlOperCst))
|
||||
? Number(item.anlOperCst)
|
||||
: 0;
|
||||
|
||||
obj[headItem.id] += guide.ruseFcltUtztnQnt;
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
})
|
||||
excelDownList.push({
|
||||
ctpvCd: item.ctpvCd,
|
||||
tmp: item.tmp,
|
||||
instlCst: item.instlCst, //설치비
|
||||
dtfcltCpct: item.dtfcltCpct, //저류조용량
|
||||
bdstUsgCd: item.bdstUsgCd, //연간사용량
|
||||
lndwtr: item.lndwtr, //조경용수
|
||||
cleanToilUswtr: item.cleanToilUswtr, //청소화장실용수
|
||||
resn: item.resn, //세척살수용수
|
||||
farmUswtr: item.farmUswtr, //농업용수
|
||||
indstUswtr: item.indstUswtr, //공업용수
|
||||
hydUswtr: item.hydUswtr, //친수용수
|
||||
ithlEtcUswtr: item.ithlEtcUswtr, //기타
|
||||
anlOperCst: item.anlOperCst, //연간운영비
|
||||
});
|
||||
});
|
||||
|
||||
cityArr.forEach(item => {
|
||||
excelDownList.push({
|
||||
ctpvCd: item.ctpvCd,
|
||||
tmp: item.tmp,
|
||||
instlCst: item.instlCst, //설치비
|
||||
dtfcltCpct: item.dtfcltCpct, //저류조용량
|
||||
bdstUsgCd: item.bdstUsgCd, //연간사용량
|
||||
lndwtr: item.lndwtr, //조경용수
|
||||
cleanToilUswtr: item.cleanToilUswtr, //청소화장실용수
|
||||
resn: item.resn, //세척살수용수
|
||||
farmUswtr: item.farmUswtr, //농업용수
|
||||
indstUswtr: item.indstUswtr, //공업용수
|
||||
hydUswtr: item.hydUswtr, //친수용수
|
||||
ithlEtcUswtr: item.ithlEtcUswtr, //기타
|
||||
anlOperCst: item.anlOperCst, //연간운영비
|
||||
})
|
||||
})
|
||||
|
||||
//상세
|
||||
const rainDetailList : RainStatProps[] = [];
|
||||
res.forEach((item:RainStatProps) => {
|
||||
const utztnUsgArray = new Array<string>();
|
||||
item.guideStats.forEach((guideStat) => {
|
||||
utztnUsgArray.push(guideStat.utztnUsgCd);
|
||||
})
|
||||
rainDetailList.push({
|
||||
...item,
|
||||
utztnUsgCd : utztnUsgArray.join(', '),
|
||||
})
|
||||
})
|
||||
const excelDetailData = excelRainStat(rainDetailList);
|
||||
/* const rainStatHeadList = data.map((item:RainStatProps) => ({
|
||||
//상세
|
||||
const rainDetailList: RainStatProps[] = [];
|
||||
res.forEach((item: RainStatProps) => {
|
||||
const utztnUsgArray = new Array<string>();
|
||||
item.guideStats.forEach((guideStat) => {
|
||||
utztnUsgArray.push(guideStat.utztnUsgCd);
|
||||
});
|
||||
rainDetailList.push({
|
||||
...item,
|
||||
utztnUsgCd: utztnUsgArray.join(", "),
|
||||
});
|
||||
});
|
||||
const excelDetailData = excelRainStat(rainDetailList);
|
||||
/* const rainStatHeadList = data.map((item:RainStatProps) => ({
|
||||
...item,
|
||||
ctpvCd:item.ctpvCd,
|
||||
sggCd:item.sggCd,
|
||||
@@ -172,14 +229,19 @@ export const rainStatActionsExport = (
|
||||
way7:item.way7,
|
||||
yearMoney:item.yearMoney,
|
||||
})) */
|
||||
set((state: rainStatState) => ({
|
||||
rainStat: {
|
||||
...state.rainStat,
|
||||
rainDetailList: excelDetailData as [][],
|
||||
rainStatList: cityArr,
|
||||
excelList: excelDownList
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(" cityArr ", cityArr);
|
||||
console.log(" excelDownList ", excelDownList);
|
||||
|
||||
cityArr.unshift(totalObj);
|
||||
set((state: rainStatState) => ({
|
||||
rainStat: {
|
||||
...state.rainStat,
|
||||
rainDetailList: excelDetailData as [][],
|
||||
rainStatList: cityArr,
|
||||
excelList: excelDownList,
|
||||
},
|
||||
}));
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { TableUpperProps } from "@/app/store/common/type/header";
|
||||
import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn";
|
||||
import type { rswtChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn";
|
||||
import { Checkbox, Input, TableCell, TableRow } from "@common/components/ui";
|
||||
import { formatCommaNumber } from "./commom";
|
||||
import { formatCommaNumber, handleCommaNumberChange } from "./commom";
|
||||
|
||||
export const rainChkTableData = (chkData: rainChkZodType[]) => {
|
||||
// 1. chkgdnSn + utztnUsgCd 기준 누계 정보 만들기
|
||||
@@ -142,7 +142,12 @@ export const chRowspanTable = (
|
||||
) : key === "order" ? (
|
||||
++order
|
||||
) : (
|
||||
value
|
||||
// value
|
||||
(["anlOperCst", "dtfcltCpct", "prcsCpct"].includes(head.id)) ? (
|
||||
formatCommaNumber(value)
|
||||
) : (
|
||||
<>{value}</>
|
||||
)
|
||||
)}
|
||||
</TableCell>
|
||||
);
|
||||
@@ -156,26 +161,44 @@ export const chRowspanTable = (
|
||||
onClick={() => handleCellClick(rowIndex, head.id)}
|
||||
>
|
||||
{head.edit === true ? (
|
||||
<Input
|
||||
className={`${head.type === "number" ? "text-right" : "text-center"} !text-xl`}
|
||||
type={head.type}
|
||||
onChange={(e) => {
|
||||
handleChange(rowIndex, head.id, e.target.value);
|
||||
}}
|
||||
value={value || ""}
|
||||
disabled={!selectedIds.includes(row.chkgdnSn)}
|
||||
maxLength={numSize}
|
||||
//input type number일때 slice 처리
|
||||
onInput={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (head.type === 'number' && e.target.value.length > numSize) {
|
||||
e.target.value = e.target.value.slice(0, numSize);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
(["levyAmt", "anlOperCst", "dtfcltCpct", "prcsCpct"].includes(head.id)) ? (
|
||||
<Input
|
||||
className={`${head.type === "number" ? "text-right" : "text-center"} !text-xl`}
|
||||
type={head.type}
|
||||
onChange={(e) => {
|
||||
handleCommaNumberChange(e, val =>
|
||||
handleChange(rowIndex, head.id, val))
|
||||
}}
|
||||
value={formatCommaNumber(value) || ""}
|
||||
disabled={!selectedIds.includes(row.chkgdnSn)}
|
||||
maxLength={numSize}
|
||||
onInput={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (head.type === 'number' && e.target.value.length > numSize) {
|
||||
e.target.value = e.target.value.slice(0, numSize);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Input
|
||||
className={`${head.type === "number" ? "text-right" : "text-center"} !text-xl`}
|
||||
type={head.type}
|
||||
onChange={(e) => {
|
||||
handleChange(rowIndex, head.id, e.target.value);
|
||||
}}
|
||||
value={value || ""}
|
||||
disabled={!selectedIds.includes(row.chkgdnSn)}
|
||||
maxLength={numSize}
|
||||
onInput={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (head.type === 'number' && e.target.value.length > numSize) {
|
||||
e.target.value = e.target.value.slice(0, numSize);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
(head.id === "totalSplyUswtrUtztnQnt" || head.id === "totalRuseFcltUtztnQnt" || head.id === "splyUswtrUtztnQnt" || head.id === "ruseFcltUtztnQnt") ? (
|
||||
<span className="underline text-blue-600 cursor-pointer">
|
||||
{value}
|
||||
(["totalSplyUswtrUtztnQnt", "totalRuseFcltUtztnQnt", "splyUswtrUtztnQnt", "ruseFcltUtztnQnt", "levyAmt"].includes(head.id)) ? (
|
||||
<span className={["totalSplyUswtrUtztnQnt", "totalRuseFcltUtztnQnt", "splyUswtrUtztnQnt", "ruseFcltUtztnQnt"].includes(head.id) ? "underline text-blue-600 cursor-pointer" : ""}>
|
||||
{formatCommaNumber(value)}
|
||||
</span>
|
||||
) : (
|
||||
<>{value}</>
|
||||
@@ -183,7 +206,6 @@ export const chRowspanTable = (
|
||||
)}
|
||||
</TableCell>
|
||||
);
|
||||
|
||||
})}
|
||||
</TableRow>
|
||||
))) : (
|
||||
|
||||
@@ -494,7 +494,7 @@ export function PbnstBuseForm({
|
||||
sonClass="col-span-4"
|
||||
indexMng={indexMng}
|
||||
indexBiz={indexBiz}
|
||||
formType={""}
|
||||
readonly={false}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
+15
-15
@@ -13,7 +13,7 @@ export function BuseWaterQulity({
|
||||
sonClass,
|
||||
indexMng,
|
||||
indexBiz,
|
||||
formType,
|
||||
readonly,
|
||||
}: {
|
||||
form: UseFormReturn<{ items: PbnstRegArrrayType }>;
|
||||
h1Title: string;
|
||||
@@ -22,7 +22,7 @@ export function BuseWaterQulity({
|
||||
sonClass: string;
|
||||
indexMng: number;
|
||||
indexBiz: number;
|
||||
formType?: string;
|
||||
readonly?: boolean;
|
||||
}) {
|
||||
const [frontPHdata, setFrontPHdata] = useState("0");
|
||||
const [backPHdata, setBackPHdata] = useState("0");
|
||||
@@ -131,7 +131,7 @@ export function BuseWaterQulity({
|
||||
? `${field.value}`
|
||||
: ""
|
||||
}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
maxLength={6}
|
||||
/>
|
||||
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
|
||||
@@ -168,7 +168,7 @@ export function BuseWaterQulity({
|
||||
? `${field.value}`
|
||||
: ""
|
||||
}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
maxLength={6}
|
||||
/>
|
||||
{/* TODO: 총대장균군수 확인 필요*/}
|
||||
@@ -203,7 +203,7 @@ export function BuseWaterQulity({
|
||||
? `${field.value}`
|
||||
: ""
|
||||
}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
maxLength={6}
|
||||
/>
|
||||
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
|
||||
@@ -237,7 +237,7 @@ export function BuseWaterQulity({
|
||||
? `${field.value}`
|
||||
: ""
|
||||
}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
maxLength={6}
|
||||
/>
|
||||
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
|
||||
@@ -267,7 +267,7 @@ export function BuseWaterQulity({
|
||||
field.onChange(String(e.target.value));
|
||||
}}
|
||||
value={field.value ?? ""}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly === "sttn" ? true : false}
|
||||
maxLength={txtSize}
|
||||
/> */}
|
||||
<SelectBox
|
||||
@@ -278,7 +278,7 @@ export function BuseWaterQulity({
|
||||
{ val: "불쾌하지않을것", text: "불쾌하지않을것" },
|
||||
{ val: "없음", text: "없음" },
|
||||
]}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
onSelectValue={(val) => {
|
||||
field.onChange(val);
|
||||
}}
|
||||
@@ -310,7 +310,7 @@ export function BuseWaterQulity({
|
||||
? `${field.value}`
|
||||
: ""
|
||||
}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
maxLength={6}
|
||||
/>
|
||||
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
|
||||
@@ -344,7 +344,7 @@ export function BuseWaterQulity({
|
||||
? `${field.value}`
|
||||
: ""
|
||||
}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
maxLength={6}
|
||||
/>
|
||||
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
|
||||
@@ -379,7 +379,7 @@ export function BuseWaterQulity({
|
||||
? `${field.value}`
|
||||
: ""
|
||||
}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
maxLength={6}
|
||||
/>
|
||||
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
|
||||
@@ -413,7 +413,7 @@ export function BuseWaterQulity({
|
||||
? `${field.value}`
|
||||
: ""
|
||||
}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
maxLength={7}
|
||||
/>
|
||||
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
|
||||
@@ -448,7 +448,7 @@ export function BuseWaterQulity({
|
||||
? `${field.value}`
|
||||
: ""
|
||||
}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
maxLength={7}
|
||||
/>
|
||||
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
|
||||
@@ -472,7 +472,7 @@ export function BuseWaterQulity({
|
||||
isSetFrontPh(e.target.value)
|
||||
}
|
||||
value={frontPHdata ?? ""}
|
||||
readOnly={formType === "sttn"}
|
||||
readOnly={readonly}
|
||||
maxLength={3}
|
||||
/>
|
||||
<span className="text-xl">~</span>
|
||||
@@ -484,7 +484,7 @@ export function BuseWaterQulity({
|
||||
isSetBackPh(e.target.value);
|
||||
}}
|
||||
value={backPHdata ?? ""}
|
||||
readOnly={formType === "sttn"}
|
||||
readOnly={readonly}
|
||||
maxLength={3}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -41,11 +41,13 @@ export function PbnstMngForm({
|
||||
formType,
|
||||
indexMng,
|
||||
setIndexMng,
|
||||
readonly
|
||||
}: {
|
||||
form: UseFormReturn<{ items: PbnstRegArrrayType }>;
|
||||
formType: string;
|
||||
indexMng: number;
|
||||
setIndexMng: (index: number) => void;
|
||||
readonly:boolean
|
||||
}) {
|
||||
const { code, pbnst, fileDelete, fileDownLoad } = useWrStore(
|
||||
(state) => state
|
||||
@@ -293,7 +295,7 @@ export function PbnstMngForm({
|
||||
field.onChange(String(e.target.value));
|
||||
}}
|
||||
value={field.value ?? ""}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
maxLength={txtSize}
|
||||
/>
|
||||
</FormUi>
|
||||
@@ -374,7 +376,7 @@ export function PbnstMngForm({
|
||||
handleCommaNumberChange(e, field.onChange);
|
||||
}}
|
||||
value={formatCommaNumber(field.value)}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
/>
|
||||
</FormUi>
|
||||
)}
|
||||
@@ -398,7 +400,7 @@ export function PbnstMngForm({
|
||||
handleCommaNumberChange(e, field.onChange);
|
||||
}}
|
||||
value={formatCommaNumber(field.value)}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
/>
|
||||
</FormUi>
|
||||
)}
|
||||
@@ -421,7 +423,7 @@ export function PbnstMngForm({
|
||||
handleCommaNumberChange(e, field.onChange);
|
||||
}}
|
||||
value={formatCommaNumber(field.value)}
|
||||
readOnly={formType === "sttn" ? true : false}
|
||||
readOnly={readonly}
|
||||
/>
|
||||
</FormUi>
|
||||
)}
|
||||
|
||||
@@ -99,6 +99,7 @@ export function PbnstRegModal({
|
||||
formType={"reg"}
|
||||
indexMng={indexMng}
|
||||
setIndexMng={setIndexMng}
|
||||
readonly={false}
|
||||
/>
|
||||
</TabsContent>
|
||||
<TabsContent className="max-h-full" value="buse">
|
||||
|
||||
@@ -35,7 +35,7 @@ import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
|
||||
export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titleVisible?: boolean }) {
|
||||
const { pbnstSttn, prfmnc , pbnstPrfmncSttn} = useWrStore((state) => state);
|
||||
const { pbnstSttn, prfmnc, pbnstPrfmncSttn } = useWrStore((state) => state);
|
||||
const [fcltTab, setFcltTab] = useState<string>("fclt");
|
||||
const [ruseTab, setRuseTab] = useState<string>("totalPrf");
|
||||
const [ruseHeadList, setRuseHeadList] = useState<TableUpperProps[]>([]);
|
||||
@@ -67,10 +67,10 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
|
||||
cusrAlotm: item.cusrAlotm ?? "-",
|
||||
etc: item.etc ?? "-",
|
||||
totalMoney:
|
||||
Number(item.addr) +
|
||||
Number(item.gvsbs) +
|
||||
Number(item.lcep) +
|
||||
Number(item.cusrAlotm),
|
||||
Number(item.cusrAlotm) +
|
||||
(isNaN(Number(item.etc)) ? 0 : Number(item.etc)),
|
||||
instlAprvSncnDt: item.instlAprvSncnDt?.toISOString ?? "-",
|
||||
bizCmcnDay: item.bizCmcnDay?.toISOString ?? "-",
|
||||
rprcsFcltCpct: item.rprcsFcltCpct ?? "-",
|
||||
@@ -167,8 +167,8 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
|
||||
const getTablePrfData = (prfList: PrfType[]) => {
|
||||
const inUsageData = structuredClone(initValInUsage);
|
||||
const outUsageData = structuredClone(initValOutUsage);
|
||||
const inSubtotal = structuredClone(subTotalObj);
|
||||
const outSubtotal = structuredClone(subTotalObj);
|
||||
const inSubtotal = { ...structuredClone(subTotalObj), 구분: "장내용수" };
|
||||
const outSubtotal = { ...structuredClone(subTotalObj), 구분: "장외용수" };
|
||||
|
||||
if (prfList) {
|
||||
prfList?.forEach((prfItem) => {
|
||||
@@ -216,7 +216,9 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
|
||||
(usageTotalObj as any)[key] = val;
|
||||
}
|
||||
const tableData = [...inUsageData, ...outUsageData, usageTotalObj];
|
||||
|
||||
console.log("inusageData", inUsageData)
|
||||
console.log("outUsageData", outUsageData)
|
||||
console.log("tableData", tableData)
|
||||
setPrfData({
|
||||
inPrf: inUsageData,
|
||||
outPrf: outUsageData,
|
||||
@@ -264,6 +266,7 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
|
||||
formType={"sttn"}
|
||||
indexMng={indexMng}
|
||||
setIndexMng={setIndexMng}
|
||||
readonly={true}
|
||||
/>
|
||||
<div className="px-6">
|
||||
<div className="">
|
||||
@@ -300,8 +303,8 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
|
||||
}}
|
||||
>
|
||||
{fcltTab === "fclt" ? (
|
||||
<HeadMakeColSpan upHeadList={pbnstSttn.ruseFcltNodeList} />
|
||||
) : undefined}
|
||||
<HeadMakeColSpan upHeadList={pbnstSttn.ruseFcltNodeList} />
|
||||
) : undefined}
|
||||
</UiTable>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
@@ -323,22 +326,22 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
|
||||
<TabsContent className="max-h-full" value={ruseTab}>
|
||||
{prfData && (
|
||||
<ListDiv className="col-span-8 pr-6 ">
|
||||
<ScrollArea className="h-[60vh]">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">
|
||||
{"하수처리수재이용 실적(m³) 등록결과"}
|
||||
</h3>
|
||||
</div>
|
||||
<Table variant="secondary">
|
||||
<TableHeader className="font-bold">
|
||||
{headMakeprfmnc(pbnstPrfmncSttn.monthSttnHeadList, [])}
|
||||
</TableHeader>
|
||||
<TableBody key={prfmnc.pageKey + 'pageKey'}>
|
||||
{InputTableBody(prfData[ruseTab as keyof typeof prfData] || [], pbnstPrfmncSttn.monthSttnHeadList, setPrfData as any)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
</ListDiv>
|
||||
<ScrollArea className="h-[60vh]">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">
|
||||
{"하수처리수재이용 실적(m³) 등록결과"}
|
||||
</h3>
|
||||
</div>
|
||||
<Table variant="secondary">
|
||||
<TableHeader className="font-bold">
|
||||
{headMakeprfmnc(pbnstPrfmncSttn.monthSttnHeadList, [])}
|
||||
</TableHeader>
|
||||
<TableBody key={prfmnc.pageKey + 'pageKey'}>
|
||||
{InputTableBody(prfData[ruseTab as keyof typeof prfData] || [], pbnstPrfmncSttn.monthSttnHeadList, setPrfData as any)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
</ListDiv>
|
||||
)}
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
@@ -421,11 +421,11 @@ export default function CoDetailModal({
|
||||
<Input
|
||||
className={selectClass}
|
||||
placeholder=""
|
||||
type="number"
|
||||
type="text"
|
||||
onChange={(e) => {
|
||||
field.onChange(e.target.value);
|
||||
handleCommaNumberChange(e, field.onChange);
|
||||
}}
|
||||
value={field.value ?? 0}
|
||||
value={formatCommaNumber(field.value) ?? 0}
|
||||
min={0}
|
||||
readOnly={true}
|
||||
/>
|
||||
|
||||
@@ -12,8 +12,13 @@
|
||||
"isUpdateMsg": "수정한 정보를 저장하시겠습니까?",
|
||||
"isInsertMsg": "등록하시겠습니까?",
|
||||
"isUpdatetMsg": "수정하시겠습니까?",
|
||||
|
||||
"matchFinishMsg" : "{{name}}이(가) 완료되었습니다.",
|
||||
"excelDownErrMsg": "다운로드할 데이터가 없습니다.",
|
||||
"isMatchFinishMsg":" 매칭완료를 진행하시겠습니까?",
|
||||
"isNotMatchFinishMsg":"검토완료중 매칭완료 여부를 체크한 항목이 없습니다.",
|
||||
"canNotChangeMatStateMsg":"매칭완료된 항목은 상태를 변경할 수 없습니다.",
|
||||
|
||||
|
||||
|
||||
"alreadyInsertedErrMsg": "사업자번호 {{num}}(은)는 이미 등록되었습니다. 다시 등록해주세요.",
|
||||
"saveRowErrMsg": "수정을 원하는 행을 선택하고 저장버튼을 눌러주세요.",
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import { Checkbox, Table, TableBody, TableCell, TableHeader, TableRow } from "@common/components";
|
||||
import {
|
||||
Checkbox,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@common/components";
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
import { HeadMakeColSpan } from "./HeadMakeColSpan";
|
||||
import UiPageNations from "./uiPageNations";
|
||||
import { Check } from "lucide-react";
|
||||
|
||||
export type ChkClass = {
|
||||
chk: boolean;
|
||||
readonly: boolean;
|
||||
};
|
||||
type UiTableProps = {
|
||||
headName: React.ReactNode | undefined;
|
||||
tableData: { [key: string]: any }[];
|
||||
@@ -20,22 +30,35 @@ type UiTableProps = {
|
||||
boldArray?: number[];
|
||||
resetSelection?: boolean;
|
||||
index?: number;
|
||||
}
|
||||
};
|
||||
|
||||
type UiHeadProps = {
|
||||
id: string;
|
||||
title: string;
|
||||
align?: string;
|
||||
visible?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export function UiTable({ tableData, headlist, pageSize, total, headName, children, cellClick, onPageChange, className = '', resetPageNo = false, boldArray = [], resetSelection = false, index = -1 }: UiTableProps) {
|
||||
export function UiTable({
|
||||
tableData,
|
||||
headlist,
|
||||
pageSize,
|
||||
total,
|
||||
headName,
|
||||
children,
|
||||
cellClick,
|
||||
onPageChange,
|
||||
className = "",
|
||||
resetPageNo = false,
|
||||
boldArray = [],
|
||||
resetSelection = false,
|
||||
index = -1,
|
||||
}: UiTableProps) {
|
||||
const [cur, setCur] = useState<number>(1);
|
||||
const [idx, setIdx] = useState<number>(index);
|
||||
const [headerHeight, setHeaderHeight] = useState<number>(0);
|
||||
const headerRef = useRef<HTMLTableSectionElement>(null);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (resetPageNo) {
|
||||
setCur(1);
|
||||
@@ -51,14 +74,14 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr
|
||||
|
||||
useEffect(() => {
|
||||
if (headerRef.current) {
|
||||
setHeaderHeight(headerRef.current.offsetHeight-5);
|
||||
setHeaderHeight(headerRef.current.offsetHeight - 5);
|
||||
}
|
||||
}, [tableData, headlist]);
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCur(page);
|
||||
onPageChange(page);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCellClick = (index: number, headId: string) => {
|
||||
if (cellClick) {
|
||||
@@ -67,81 +90,158 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
{headName ? <div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">{headName}</h3>
|
||||
</div> : <></>}
|
||||
<div className={`card !m-[1.2rem] !p-0r ${className}`}>
|
||||
{headName ? (
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">{headName}</h3>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<div className={`card !p-0r !m-[1.2rem] ${className}`}>
|
||||
<Table variant="secondary">
|
||||
<TableHeader ref={headerRef} className="font-bold">
|
||||
{children ? children : <HeadMakeColSpan upHeadList={headlist} />}
|
||||
</TableHeader>
|
||||
<TableBody className='text-center'>
|
||||
{tableData.length > 0 ? tableData?.map((el: Record<string, unknown>, index) => (
|
||||
<TableRow key={`row-${index}`}>
|
||||
{headlist
|
||||
.filter((item) => item.visible != false)
|
||||
.map((head) => (
|
||||
head.id && head.id.length > 1 && (
|
||||
boldArray.includes(index)
|
||||
?
|
||||
<TableCell
|
||||
className={`${head.align === 'right' ? 'text-right' : head.align === 'center' ? 'text-center' : 'text-center'} ${cellClick && idx === index ? '!font-[1000] cursor-pointer' :
|
||||
cellClick ? 'cursor-pointer' : ''
|
||||
} !font-bold sticky bg-secondary z-40`}
|
||||
style={{ top: `${headerHeight + (index * 39)}px` }}
|
||||
onClick={() => handleCellClick(index, head.id)}
|
||||
key={`cell-${head.id}-${index}`}
|
||||
>
|
||||
{typeof el[head.id] !== 'number' ? String(el[head.id] ?? '') : String(el[head.id]).includes('.')
|
||||
? String(el[head.id]).split('.').map((part, index) =>
|
||||
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
|
||||
).join('.')
|
||||
: String(el[head.id] ?? '').replace(/\B(?=(\d{3})+(?!\d))/g, ",")}
|
||||
</TableCell>
|
||||
:
|
||||
<TableCell
|
||||
className={`${head.align === 'right' ? 'text-right' : head.align === 'center' ? 'text-center' : 'text-center'} ${cellClick && idx === index ? '!font-[1000] cursor-pointer' :
|
||||
cellClick ? 'cursor-pointer' : ''
|
||||
<TableBody className="text-center">
|
||||
{tableData.length > 0 ? (
|
||||
tableData?.map((el: Record<string, unknown>, index) => (
|
||||
<TableRow key={`row-${index}`}>
|
||||
{headlist
|
||||
.filter((item) => item.visible != false)
|
||||
.map(
|
||||
(head) =>
|
||||
head.id &&
|
||||
head.id.length > 1 &&
|
||||
(boldArray.includes(index) ? (
|
||||
<TableCell
|
||||
className={`${head.align === "right" ? "text-right" : head.align === "center" ? "text-center" : "text-center"} ${
|
||||
cellClick && idx === index
|
||||
? "cursor-pointer !font-[1000]"
|
||||
: cellClick
|
||||
? "cursor-pointer"
|
||||
: ""
|
||||
} sticky z-40 bg-secondary !font-bold`}
|
||||
style={{ top: `${headerHeight + index * 39}px` }}
|
||||
onClick={() => handleCellClick(index, head.id)}
|
||||
key={`cell-${head.id}-${index}`}
|
||||
>
|
||||
{typeof el[head.id] !== "number"
|
||||
? String(el[head.id] ?? "")
|
||||
: String(el[head.id]).includes(".")
|
||||
? String(el[head.id])
|
||||
.split(".")
|
||||
.map((part, index) =>
|
||||
index === 0
|
||||
? part.replace(
|
||||
/\B(?=(\d{3})+(?!\d))/g,
|
||||
",",
|
||||
)
|
||||
: part,
|
||||
)
|
||||
.join(".")
|
||||
: String(el[head.id] ?? "").replace(
|
||||
/\B(?=(\d{3})+(?!\d))/g,
|
||||
",",
|
||||
)}
|
||||
</TableCell>
|
||||
) : (
|
||||
<TableCell
|
||||
className={`${head.align === "right" ? "text-right" : head.align === "center" ? "text-center" : "text-center"} ${
|
||||
cellClick && idx === index
|
||||
? "cursor-pointer !font-[1000]"
|
||||
: cellClick
|
||||
? "cursor-pointer"
|
||||
: ""
|
||||
} mt-[${boldArray.length * 40}px]`}
|
||||
onClick={() => handleCellClick(index, head.id)}
|
||||
key={`cell-${head.id}-${index}`}
|
||||
>
|
||||
{typeof el[head.id] === 'boolean'
|
||||
? <Checkbox
|
||||
checked={el[head.id] === true}
|
||||
onCheckedChange={(checked) => {
|
||||
el[head.id] = checked;
|
||||
}}
|
||||
>
|
||||
<Check className="h-6 w-6 text-primary" />
|
||||
</Checkbox>
|
||||
:
|
||||
typeof el[head.id] !== 'number' ?
|
||||
String(el[head.id] ?? '') :
|
||||
String(el[head.id]).includes('.')
|
||||
? String(el[head.id]).split('.').map((part, index) =>
|
||||
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
|
||||
).join('.')
|
||||
:
|
||||
String(el[head.id] ?? '').replace(/\B(?=(\d{3})+(?!\d))/g, ",")}
|
||||
</TableCell>
|
||||
)
|
||||
))}
|
||||
</TableRow>
|
||||
)) : (
|
||||
onClick={() => handleCellClick(index, head.id)}
|
||||
key={`cell-${head.id}-${index}`}
|
||||
>
|
||||
{
|
||||
//체크박스 유형애서 readOnly가 필요한 경우를 위해서 ChkClass 를 사용해서 readOnly 처리함.
|
||||
typeof el[head.id] === "object" &&
|
||||
el[head.id] !== null &&
|
||||
"chk" in (el[head.id] as object) &&
|
||||
"readonly" in (el[head.id] as object) ? (
|
||||
<Checkbox
|
||||
checked={
|
||||
(el[head.id] as ChkClass)?.chk === true
|
||||
}
|
||||
onCheckedChange={(checked) => {
|
||||
{
|
||||
console.log(el[head.id]);
|
||||
}
|
||||
if (
|
||||
(el[head.id] as ChkClass).readonly == true
|
||||
)
|
||||
return;
|
||||
(el[head.id] as ChkClass).chk =
|
||||
Boolean(checked);
|
||||
}}
|
||||
>
|
||||
<Check className="h-6 w-6 text-primary" />
|
||||
</Checkbox>
|
||||
) : typeof el[head.id] === "boolean" ? (
|
||||
<Checkbox
|
||||
checked={el[head.id] === true}
|
||||
onCheckedChange={(checked) => {
|
||||
el[head.id] = checked;
|
||||
}}
|
||||
>
|
||||
<Check className="h-6 w-6 text-primary" />
|
||||
</Checkbox>
|
||||
) : typeof el[head.id] !== "number" ? (
|
||||
String(el[head.id] ?? "")
|
||||
) : String(el[head.id]).includes(".") ? (
|
||||
String(el[head.id])
|
||||
.split(".")
|
||||
.map((part, index) =>
|
||||
index === 0
|
||||
? part.replace(
|
||||
/\B(?=(\d{3})+(?!\d))/g,
|
||||
",",
|
||||
)
|
||||
: part,
|
||||
)
|
||||
.join(".")
|
||||
) : (
|
||||
String(el[head.id] ?? "").replace(
|
||||
/\B(?=(\d{3})+(?!\d))/g,
|
||||
",",
|
||||
)
|
||||
)
|
||||
}
|
||||
</TableCell>
|
||||
)),
|
||||
)}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={headlist.filter((item) => item.visible != false).length} className="h-24 text-center text-gray-500">
|
||||
<TableCell
|
||||
colSpan={
|
||||
headlist.filter((item) => item.visible != false).length
|
||||
}
|
||||
className="h-24 text-center text-gray-500"
|
||||
>
|
||||
조회된 결과가 없습니다.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
{total <= 0 ? <></> : <UiPageNations total={total} cur={cur} pageSize={pageSize} onPageChange={handlePageChange} />}
|
||||
{total <= 0 ? (
|
||||
<></>
|
||||
) : (
|
||||
<UiPageNations
|
||||
total={total}
|
||||
cur={cur}
|
||||
pageSize={pageSize}
|
||||
onPageChange={handlePageChange}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user