358 lines
12 KiB
TypeScript
358 lines
12 KiB
TypeScript
"use client";
|
|
import { useWrStore } from "@/app/store";
|
|
import { excelToPbnPrfData } from "@/app/store/prfmncReg/pbnstPrfmncReg/excel";
|
|
import {
|
|
initValInUsage,
|
|
initValOutUsage,
|
|
subTotalObj,
|
|
totalObj,
|
|
type FcPrfType,
|
|
type PrfType,
|
|
} from "@/app/store/prfmncReg/pbnstPrfmncReg/type";
|
|
import { confirmToast, excelDownload, yearOptions } from "@/components/lib/func/commom";
|
|
import { InputTableBody } from "@/components/lib/func/TableData";
|
|
import PbnPrfExcelModal from "@/components/ui/modal/chkgd/pbnPrfExcelModal/pbnPrfExcelModal";
|
|
import {
|
|
ContentsDiv,
|
|
ScrollArea,
|
|
SearchDiv,
|
|
SearchFormLeft,
|
|
SearchFormRight,
|
|
SearchInput,
|
|
SelectBox,
|
|
Title,
|
|
UiModal,
|
|
UiTable,
|
|
} from "@common/business_components/ui";
|
|
import ListDiv from "@common/business_components/ui/list_div";
|
|
import {
|
|
Button,
|
|
Label,
|
|
Table,
|
|
TableBody,
|
|
TableHeader,
|
|
} from "@common/components/ui";
|
|
import { useCallback, useEffect, useState } from "react";
|
|
import toast, { Toaster } from "react-hot-toast";
|
|
import { useTranslation } from "react-i18next";
|
|
import { headMakeprfmnc } from "../chkgdnReg/TableHead";
|
|
|
|
export default function PrfmncPrfmncReg() {
|
|
const { prfmnc, prfmncHasuInit, prfmnRegData, prfmncHasuNmSearch } = useWrStore(
|
|
(state) => state
|
|
);
|
|
const { pbnstPrfmncHeadList, monthHeadList, prfmncRes, prfmncResCount } = prfmnc;
|
|
const [bdstTable, setbdstTable] = useState<FcPrfType[]>();
|
|
const [searchTxt, setSearchTxt] = useState<string>();
|
|
const [isExcelOpen, setIsExcelOPen] = useState<{
|
|
isModal: boolean;
|
|
data: FcPrfType;
|
|
}>({ isModal: false, data: {} as FcPrfType });
|
|
const [inputData, setInputData] = useState<any[]>();
|
|
const [pbnstRuseFcltId, setpbnstRuseFcltId] = useState<string>();
|
|
const [pageNation, setPageNation] = useState<number>(1);
|
|
const [cellNum, setCellNum] = useState<number>(1);
|
|
const [searchYear, setSearchYear] = useState<string>(
|
|
String(new Date().getFullYear())
|
|
);
|
|
|
|
const excelClick = useCallback(() => {
|
|
excelDownload(
|
|
[[]],
|
|
"하수재이용실적",
|
|
"sample_pbnstPrfmncReg.xlsx",
|
|
"A1:O1"
|
|
);
|
|
}, [prfmnc.excelList]);
|
|
/*
|
|
const onSave = useCallback(
|
|
async() => {
|
|
if (pbnstRuseFcltId) {
|
|
await prfmnRegData(pageNation,'41',
|
|
excelToPbnPrfData(
|
|
inputData as unknown as JSON[],
|
|
searchYear,
|
|
pbnstRuseFcltId
|
|
) as unknown as PrfType
|
|
);
|
|
// cellClick(cellNum)
|
|
}
|
|
}, [inputData, searchYear, pbnstRuseFcltId, pageNation,cellNum]);*/
|
|
|
|
const { t } = useTranslation('base');
|
|
const onSave = useCallback(() => {
|
|
const handleConfirm = async () => {
|
|
if (!pbnstRuseFcltId) return;
|
|
|
|
prfmnRegData(
|
|
pageNation,
|
|
'41',
|
|
excelToPbnPrfData(
|
|
inputData as unknown as JSON[],
|
|
searchYear,
|
|
pbnstRuseFcltId
|
|
) as unknown as PrfType
|
|
,searchYear
|
|
);
|
|
};
|
|
|
|
confirmToast(t('isUpdateMsg'), handleConfirm);
|
|
}, [inputData, searchYear, pbnstRuseFcltId, pageNation, cellNum]);
|
|
|
|
const cellClick = useCallback(
|
|
(index: number | undefined) => {
|
|
if (index !== undefined) {
|
|
setIsExcelOPen({
|
|
isModal: false,
|
|
data: prfmncRes[index] || ({} as FcPrfType),
|
|
});
|
|
const inUsageData = structuredClone(initValInUsage).map((row) => ({
|
|
...row,
|
|
구분: "장내용수",
|
|
}));
|
|
const outUsageData = structuredClone(initValOutUsage).map((row) => ({
|
|
...row,
|
|
구분: "장외용수",
|
|
}));
|
|
const inSubtotal = {
|
|
...structuredClone(subTotalObj),
|
|
구분: "장내용수",
|
|
};
|
|
const outSubtotal = {
|
|
...structuredClone(subTotalObj),
|
|
구분: "장외용수",
|
|
};
|
|
if (prfmncRes[index]?.prfList) {
|
|
prfmncRes[index].prfList?.forEach((prfItem) => {
|
|
const month = Number(prfItem?.ym?.slice(4)); // "MM"
|
|
const monthKey = `${month}월`;
|
|
|
|
inUsageData.forEach((inData: any) => {
|
|
const usageKey = inData.usage;
|
|
const value = (prfItem as any)[usageKey] ?? 0;
|
|
|
|
inData[monthKey] = value;
|
|
inData.total += value;
|
|
|
|
if (inSubtotal && usageKey !== "subtotal") {
|
|
(inSubtotal as any)[monthKey] =
|
|
((inSubtotal as any)[monthKey] ?? 0) + value;
|
|
inSubtotal.total += value;
|
|
}
|
|
});
|
|
|
|
outUsageData.forEach((outData: any) => {
|
|
const usageKey = outData.usage;
|
|
const value = (prfItem as any)[usageKey] ?? 0;
|
|
|
|
outData[monthKey] = value;
|
|
outData.total += value;
|
|
|
|
if (usageKey !== "subtotal") {
|
|
(outSubtotal as any)[monthKey] =
|
|
((outSubtotal as any)[monthKey] ?? 0) + value;
|
|
outSubtotal.total += value;
|
|
}
|
|
});
|
|
});
|
|
inUsageData.push(inSubtotal);
|
|
outUsageData.push(outSubtotal);
|
|
const usageTotalObj: { [key: string]: any } = {
|
|
...structuredClone(totalObj),
|
|
구분: "총합계",
|
|
용수명: "",
|
|
};
|
|
for (const key in usageTotalObj) {
|
|
if (["usage", "gubun", "edit"].includes(key)) continue;
|
|
const val =
|
|
(Number((inSubtotal as any)[key]) || 0) +
|
|
(Number((outSubtotal as any)[key]) || 0);
|
|
|
|
(usageTotalObj as any)[key] = val;
|
|
}
|
|
const tableData = [...inUsageData, ...outUsageData, usageTotalObj];
|
|
setpbnstRuseFcltId(prfmncRes[index].pbnstRuseFcltId);
|
|
setInputData(tableData);
|
|
} else {
|
|
setInputData([]);
|
|
}
|
|
}
|
|
},
|
|
[prfmncRes]
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (!prfmnc.isInit) {
|
|
const year = new Date().getFullYear()
|
|
prfmncHasuInit(1, "41", String(year));
|
|
}
|
|
}, [prfmnc.isInit, prfmncHasuInit]);
|
|
useEffect(() => {
|
|
|
|
|
|
if (prfmncRes && prfmncRes.length > 0) {
|
|
|
|
setbdstTable(prfmncRes);
|
|
}
|
|
|
|
// cellNum이 0일 경우(첫 번째 행)도 유효한 인덱스이므로 undefined 여부만 체크합니다.
|
|
if (cellNum !== undefined) {
|
|
cellClick(cellNum);
|
|
}
|
|
}, [prfmncRes, cellNum, cellClick]);
|
|
|
|
return (
|
|
<>
|
|
<ContentsDiv>
|
|
<div className="grid grid-cols-4 gap-4">
|
|
<div className="col-span-4">
|
|
<Title title={"하수재이용 실적 등록"} />
|
|
<SearchDiv>
|
|
<SearchFormLeft>
|
|
<div className="col-span-2 flex flex-row space-x-2">
|
|
<Label className="w-48 mt-2 text-xl text-gray-600">
|
|
{"실적등록년도"}
|
|
</Label>
|
|
<SelectBox
|
|
className="w-full h-full text-2xl"
|
|
label=""
|
|
selectClass={""}
|
|
selectArray={yearOptions}
|
|
value={searchYear}
|
|
onSelectValue={(val: string | number) =>
|
|
setSearchYear(String(val))
|
|
}
|
|
/>
|
|
</div>
|
|
<div className="col-span-2 flex flex-row space-x-2">
|
|
<Label className="w-28 mt-2 text-xl text-gray-600">
|
|
{"시설명"}
|
|
</Label>
|
|
<SearchInput
|
|
className={"w-full text-2xl"}
|
|
label=""
|
|
textValue={searchTxt || ""}
|
|
setText={(e) => {
|
|
setSearchTxt(e);
|
|
}}
|
|
/>
|
|
</div>
|
|
</SearchFormLeft>
|
|
<SearchFormRight className="w-2/12 mx-5 flex flex-col items-center justify-center space-x-2 ">
|
|
<div className="space-y">
|
|
<div className="flex flex-row space-x-2">
|
|
<Button size={"sm"} onClick={() => {
|
|
|
|
if (searchTxt && searchTxt?.length > 0) {
|
|
prfmncHasuNmSearch(1, '41', searchYear, searchTxt)
|
|
setPageNation(1)
|
|
} else {
|
|
prfmncHasuInit(1, '41', searchYear)
|
|
setPageNation(1)
|
|
}
|
|
|
|
}}>
|
|
조회
|
|
</Button>
|
|
<Button
|
|
size={"sm"}
|
|
onClick={() => {
|
|
onSave();
|
|
}}
|
|
>
|
|
저장
|
|
</Button>
|
|
<Button
|
|
size={"sm"}
|
|
onClick={() => {
|
|
if (cellNum === undefined) {
|
|
toast.error("하수처리재이용시설을 선택해주세요.");
|
|
return;
|
|
} else {
|
|
setIsExcelOPen({ ...isExcelOpen, isModal: true });
|
|
}
|
|
}}
|
|
>
|
|
파일등록
|
|
</Button>
|
|
<Button color="green" size={"sm"} onClick={excelClick}>
|
|
양식받기
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</SearchFormRight>
|
|
</SearchDiv>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-12 gap-4 h-full">
|
|
<div className="col-span-4 h-full min-h-0">
|
|
<ListDiv className="min-h-0">
|
|
<ScrollArea className="h-[60vh]">
|
|
<UiTable
|
|
key={'leftTable'}
|
|
tableData={bdstTable || []}
|
|
headlist={pbnstPrfmncHeadList}
|
|
pageSize={10}
|
|
total={prfmncResCount}
|
|
headName={"하수재이용시설 목록"}
|
|
cellClick={(index: number | undefined) => {
|
|
cellClick(index);
|
|
setCellNum(index ?? 0);
|
|
}}
|
|
onPageChange={
|
|
(page) => {
|
|
prfmncHasuInit(page, "41", searchYear);
|
|
setPageNation(page)
|
|
}}
|
|
/>
|
|
</ScrollArea>
|
|
</ListDiv>
|
|
</div>
|
|
<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(monthHeadList, [])}
|
|
</TableHeader>
|
|
<TableBody key={prfmnc.pageKey + 'pageKey'}>
|
|
{InputTableBody(inputData ?? [], monthHeadList, setInputData)}
|
|
</TableBody>
|
|
</Table>
|
|
</ScrollArea>
|
|
</ListDiv>
|
|
</div>
|
|
</ContentsDiv>
|
|
<UiModal
|
|
bodyClass={"w-[30vw] max-w-none"}
|
|
body={
|
|
<PbnPrfExcelModal
|
|
data={isExcelOpen.data}
|
|
setIsExcelOPen={(open) => {
|
|
setIsExcelOPen({ ...isExcelOpen, isModal: open })
|
|
}}
|
|
setModalExcelData={async (excelData) => {
|
|
await prfmnRegData(pageNation, '41',
|
|
excelData,
|
|
searchYear
|
|
);
|
|
// 데이터 저장 후 UI 업데이트는 useEffect가 감지하여 처리하므로 여기서는 호출하지 않습니다.
|
|
}
|
|
}
|
|
></PbnPrfExcelModal>
|
|
}
|
|
open={isExcelOpen.isModal}
|
|
onOpenChange={() => {
|
|
setIsExcelOPen({ isModal: false, data: {} as FcPrfType });
|
|
}}
|
|
></UiModal>
|
|
<Toaster position="top-center" />
|
|
</>
|
|
);
|
|
}
|