Files
frontend/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx
T

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" />
</>
);
}