Merge commit '6249a73aa3aa9ac833ddab362643b71da7e00f93' into iipbs/wr/dev
iipbs_wr / build (push) Waiting to run

This commit is contained in:
leedj312
2025-07-14 10:22:18 +09:00
20 changed files with 343 additions and 352 deletions
@@ -24,7 +24,6 @@ import type {
import {
pbnstRegZod,
pbnstRegArrayZod,
fcBizSchema,
} from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import { PbnstMngForm } from "@/components/ui/form/fcltReg/pbnstReg/mngReg/mngRegForm";
import { PbnstBuseForm } from "@/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm";
@@ -36,8 +35,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { createDefaultPbnstItem } from "./utilsZod";
import { flushSync } from "react-dom";
export default function PublicReuseFaciltyInsert() {
const {
@@ -55,7 +53,7 @@ export default function PublicReuseFaciltyInsert() {
const [isRuseReg, setIsRuseReg] = useState<{
isModal: boolean;
}>({ isModal: false });
const [resetPage, isResetPage] = useState(false);
const [indexMng, setIndexMng] = useState<number>(0);
const [indexBiz, setIndexBiz] = useState<number>(0);
const [searchTxt, setSearchTxt] = useState<string>();
@@ -89,15 +87,16 @@ export default function PublicReuseFaciltyInsert() {
}, [pbnst.isInit, pubHasuInit]);
const onSubmit = async (valuse: { items: PbnstRegArrrayType }) => {
if (!isDirty) {
toast.error("변경사항이 없습니다."); // 변경사항이 없으면 메시지 표시
return;
} const data = writeRgtrAndMdfr(valuse.items);
}
const data = writeRgtrAndMdfr(valuse.items);
let bizs = [] as fcBizType[];
data.forEach((fclt) => {
bizs = [...bizs, ...fclt.fcBizs];
});
const pbnst = data.map((fclt) => {
return {
pbnstRuseFcltPk: fclt.pbnstRuseFcltPk,
@@ -111,42 +110,34 @@ export default function PublicReuseFaciltyInsert() {
};
});
Promise.allSettled([
pbnstRuseFcltUpdate(pbnst as customPbnst[]),
pbnstRuseBizUpdate(bizs)
pbnstRuseBizUpdate(bizs),
]).then(([resFclt, resBiz]) => {
const isFcltSuccess = resFclt.status === "fulfilled";
const isBizSuccess = resBiz.status === "fulfilled";
if (isFcltSuccess && isBizSuccess) {
toast.success('하수 재이용 시설 및 사업이 수정되었습니다. ')
toast.success("하수 재이용 시설 및 사업이 수정되었습니다. ");
// 메시지 표시, 페이지 이동 등
} else {
let message = ''
let message = "";
// ✅ 각각 어떤 항목이 실패했는지도 로그/알림 처리
if (!isFcltSuccess) {
message = '하수재이용 시설 '
message = "하수재이용 시설 ";
}
if (!isBizSuccess) {
message += '하수재이용 시설 사업 '
message += "하수재이용 시설 사업 ";
}
toast.error(message + '오류 입니다 ')
toast.error(message + "오류 입니다 ");
pubHasuInit("1", "41");
}
});
};
// 폼 유효성 검사 실패 시 호출될 함수
const onInvalid = (errors: FieldErrors<{ items: z.infer<typeof pbnstRegZod>[] }>) => {
console.log("errors:", errors);
const onInvalid = (
errors: FieldErrors<{ items: z.infer<typeof pbnstRegZod>[] }>
) => {
const findAllErrors = (
errorObject: any,
path: (string | number)[] = []
@@ -180,7 +171,9 @@ export default function PublicReuseFaciltyInsert() {
if (itemsIndex > -1 && path.length > itemsIndex + 1) {
const itemIdx = path[itemsIndex + 1] as number;
const facilityName = form.getValues(`items.${itemIdx}.ruseUtztnFcltNm`);
const facilityName = form.getValues(
`items.${itemIdx}.ruseUtztnFcltNm`
);
if (facilityName) {
prefix += `[${facilityName}] `;
}
@@ -188,13 +181,14 @@ export default function PublicReuseFaciltyInsert() {
const fcBizsIndex = path.indexOf("fcBizs");
if (fcBizsIndex > -1 && path.length > fcBizsIndex + 1) {
const bizIdx = path[fcBizsIndex + 1] as number;
const cycle = form.getValues(`items.${itemIdx}.fcBizs.${bizIdx}.cycl`);
const cycle = form.getValues(
`items.${itemIdx}.fcBizs.${bizIdx}.cycl`
);
if (cycle) {
prefix += `[${cycle}차수] `;
}
}
}
// 최종 오류 메시지 출력
toast.error(`${prefix}${message}`);
});
@@ -204,6 +198,10 @@ export default function PublicReuseFaciltyInsert() {
console.log("form errors:", form.formState.errors);
}, [form.formState.errors]);
useEffect(() => {
console.log("formState", items);
}, [items]);
useEffect(() => {
if (code.sggCd.length && pbnstHasuRes.length > 0) {
setbdstTable(tableData(pbnstHasuRes, { code }));
@@ -225,6 +223,12 @@ export default function PublicReuseFaciltyInsert() {
setCurrentTab(value);
};
useEffect(() => {
if (indexMng) {
setIndexBiz(0);
}
}, [indexMng]);
useEffect(() => {
if (pbnst.pbnstRes && pbnst.pbnstRes?.length > 0) {
form.reset({ items: pbnst.pbnstRes });
@@ -233,67 +237,25 @@ export default function PublicReuseFaciltyInsert() {
form.reset({ items: [] });
}
}, [pbnst.pbnstRes]);
useEffect(() => {
if (indexMng) {
setIndexBiz(0);
}
}, [indexMng]);
useEffect(() => {
console.log("form errors:", form.formState.errors);
}, [form.formState.errors]);
const appendPbnstRuseFclt = useCallback(() => {
const selecTableRow = selectRow;
if (pbnstRes && pbnstRes.length > 0) {
const lastPbnst = pbnstRes[pbnstRes.length - 1];
if (lastPbnst && selecTableRow) {
// append(
// pbnstRegZod.parse({
// pbnstRuseFcltPk:
// String(selecTableRow.bscFctCd) + String(pbnstRes.length + 1),
// ruseUtztnFcltNm: null,
// fcBizs: [
// fcBizSchema.parse({
// pbnstRuseFcltFk:
// String(lastPbnst.pbnstRuseFcltPk) +
// String(pbnstRes.length + 1),
// cycl: 1,
// }),
// ] as fcBizType[],
// })
// );
append(createDefaultPbnstItem(selecTableRow, pbnstRes.length));
if (selectRow) { // pbnstRes.length를 사용하여 새로운 항목의 인덱스를 결정
append(createDefaultPbnstItem(selectRow, pbnstRes.length));
setIsRuseReg({ isModal: true });
}
} else {
if (selecTableRow) {
append(createDefaultPbnstItem(selecTableRow, 0)
// {
// pbnstRuseFcltPk: String(selecTableRow.bscFctCd) + "1",
// ruseUtztnFcltNm: "",
// regDt: null,
// mdfcnDt: null,
// fcBizs: [
// fcBizSchema.parse({
// pbnstRuseFcltFk: String(selecTableRow.bscFctCd) + "1",
// cycl: 1,
// }),
// ] as fcBizType[],
// }
// )
);
if (selectRow) { // pbnstRes가 비어있으면 첫 항목이므로 인덱스 0
append(createDefaultPbnstItem(selectRow, 0));
setIsRuseReg({ isModal: true });
}
}
}, [pbnstRegZod, pbnstRes, append, selectRow, form]);
}, [pbnstRes, append, selectRow]);
useEffect(() => {
pubHasuInit(String(pageNation), "41");
isResetPage(false);
}, [pageNation, pubHasuInit]);
return (
@@ -320,6 +282,7 @@ export default function PublicReuseFaciltyInsert() {
searchTxt && searchTxt?.length > 0
? pubHasuSearch(String(pageNation), "41", searchTxt)
: pubHasuInit(String(pageNation), "41");
isResetPage(true);
}}
>
조회
@@ -362,6 +325,7 @@ export default function PublicReuseFaciltyInsert() {
cellClick={cellClick}
onPageChange={setPageNation}
children={undefined}
resetPageNo={resetPage}
/>
</ScrollArea>
</ListDiv>
@@ -390,7 +354,6 @@ export default function PublicReuseFaciltyInsert() {
formType="update"
form={form}
setIndexMng={(index: number) => {
console.log("setIndexMng", index);
setIndexMng(index);
}}
indexMng={indexMng}
@@ -407,7 +370,6 @@ export default function PublicReuseFaciltyInsert() {
indexBiz={indexBiz}
/>
</TabsContent>
</ScrollArea>
</Tabs>
) : (
@@ -438,7 +400,6 @@ export default function PublicReuseFaciltyInsert() {
</Button>
</div>
</>
)}
</ListDiv>
<UiModal
@@ -451,7 +412,6 @@ export default function PublicReuseFaciltyInsert() {
setIsRuseReg({ isModal: false });
}
}}
onInvalid={onInvalid}
></PbnstRegModal>
}
@@ -1,28 +1,37 @@
import type { fcBizType, pubHasuType } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import type { fcBizType, operType, pubHasuType } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
export function createDefaultPbnstItem(
selecTableRow: pubHasuType,
index: number
) {
const pk = String(selecTableRow.bscFctCd) + String(index + 1);
export function createDefaultPbnstItem(row: pubHasuType, index: number) {
const pk = row.bscFctCd + String(index + 1);
return JSON.parse(JSON.stringify({
pbnstRuseFcltPk: pk,
swtrmtFcltFk: "",
ruseUtztnFcltNm: "",
fcltCpct: 0,
ruseCpct: 0,
splyExtraCpct: 0,
regDt: null,
rgtr: "",
mdfcnDt: null,
mdfr: "",
fcFiles: [],
fcBizs: [createDefaultBiz(pk, 1)],
fcOpers: [], // 빈 배열 강제
}));
}
export function createDefaultOper(pbnstRuseFcltFk: string): operType {
return {
pbnstRuseFcltPk: pk,
swtrmtFcltFk: "",
ruseUtztnFcltNm: "", // 필수 입력이므로 빈 문자열로
fcltCpct: 0,
ruseCpct: 0,
splyExtraCpct: 0,
regDt: null,
rgtr: "test",
mdfcnDt: null,
mdfr: "test",
fcFiles: [],
fcBizs: [
createDefaultBiz(pk, 1), // 첫 차수
],
fcOpers: [],
};
pbnstRuseFcltFk,
operMthd: "",
rprtvBzenty: "",
bgngDt: new Date(),
endDt: new Date(),
choose: false,
rgtr: "",
mdfr: "",
} as operType;
}
@@ -93,8 +93,8 @@ export default function prfmncPrfmncReg() {
inputData as unknown as JSON[],
searchYear,
pbnstRuseFcltPk
) as unknown as PrfType,
searchYear
) as unknown as PrfType
,searchYear
);
};
@@ -319,7 +319,6 @@ export default function prfmncPrfmncReg() {
{"하수처리수재이용 실적(m3) 등록결과"}
</h3>
</div>
<Table variant="secondary">
<TableHeader className="font-bold">
{headMakeprfmnc(monthHeadList, [])}
@@ -89,12 +89,12 @@ export default function PbnstPrfmncSttn() {
const prfTableData = (prfList: PrfType[], year: string) => {
const inUsageData = structuredClone(initValInUsage).map(row => ({
...row,
구분: "장내용수",
...row
// 구분: "장내용수",
}));
const outUsageData = structuredClone(initValOutUsage).map(row => ({
...row,
구분: "장외용수",
...row
// 구분: "장외용수",
}));
const inSubtotal = { ...structuredClone(subTotalObj), 구분: "장내용수" };
const outSubtotal = { ...structuredClone(subTotalObj), 구분: "장외용수" };
+1
View File
@@ -22,6 +22,7 @@ export type TableUpperProps = {
selectData ?:string; // type 이 seelct 일경우 selectarray 정하기 위해
row?:number;
mergeCell?:boolean // 셀을 합칠경우
maxLength?:number
readonly?:boolean
};
@@ -2,6 +2,20 @@ import { z } from "zod";
import type { TableUpperProps } from "../../common/type/header";
import { fcOperSchema } from "../../ruseFcltMng/fcltReg/pbnstReg/type";
type Month = `${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12}월`;
export type PrfUsageSummary = {
구분: string;
usage: string;
용수명?: string;
total: number;
edit?:boolean
} & Record<Month, number>;
export const PrfSchema = z.object({
pbnstRuseFcltFk: z.string(),
ym: z.string(), // 예: "202310"
@@ -44,8 +58,9 @@ export const FcPrfSchema = z.object({
export type FcPrfType = z.infer<typeof FcPrfSchema>;
export type PrfType = z.infer<typeof PrfSchema>;
export const initValInUsage = [
export const initValInUsage:PrfUsageSummary[] = [
{
구분: "장내용수",
usage: "wshwtr",
용수명: "세척수",
total: 0,
@@ -63,6 +78,7 @@ export const initValInUsage = [
"12월": 0,
},
{
구분: "장내용수",
usage: "coolUswtr",
용수명: "냉각수",
total: 0,
@@ -80,6 +96,7 @@ export const initValInUsage = [
"12월": 0,
},
{
구분: "장내용수",
usage: "cleanUswtr",
용수명: "청소수",
total: 0,
@@ -97,6 +114,7 @@ export const initValInUsage = [
"12월": 0,
},
{
구분: "장내용수",
usage: "drwtUswtr",
용수명: "식수대",
total: 0,
@@ -114,6 +132,7 @@ export const initValInUsage = [
"12월": 0,
},
{
구분: "장내용수",
usage: "dltnUswtr",
용수명: "희석용수",
total: 0,
@@ -131,6 +150,7 @@ export const initValInUsage = [
"12월": 0,
},
{
구분: "장내용수",
usage: "ithlRswtr",
용수명: "중수도",
total: 0,
@@ -148,6 +168,7 @@ export const initValInUsage = [
"12월": 0,
},
{
구분: "장내용수",
usage: "ithlEtcUswtr",
용수명: "기타",
total: 0,
@@ -166,8 +187,9 @@ export const initValInUsage = [
},
];
export const initValOutUsage = [
export const initValOutUsage: PrfUsageSummary[] = [
{
구분: "장외용수",
usage: "resn",
용수명: "세척살수용수",
total: 0,
@@ -185,6 +207,7 @@ export const initValOutUsage = [
"12월": 0,
},
{
구분: "장외용수",
usage: "cleanToilUswtr",
용수명: "청소화장실용수",
total: 0,
@@ -202,6 +225,7 @@ export const initValOutUsage = [
"12월": 0,
},
{
구분: "장외용수",
usage: "lndwtr",
용수명: "조경용수",
total: 0,
@@ -219,6 +243,7 @@ export const initValOutUsage = [
"12월": 0,
},
{
구분: "장외용수",
usage: "hydUswtr",
용수명: "친수용수",
total: 0,
@@ -236,6 +261,7 @@ export const initValOutUsage = [
"12월": 0,
},
{
구분: "장외용수",
usage: "ugwtChr",
용수명: "지하수충전",
total: 0,
@@ -253,6 +279,7 @@ export const initValOutUsage = [
"12월": 0,
},
{
구분: "장외용수",
usage: "farmUswtr",
용수명: "농업용수",
total: 0,
@@ -271,6 +298,7 @@ export const initValOutUsage = [
},
{
구분: "장외용수",
usage: "rvrKeepUswtr",
용수명: "하천등유지용수",
total: 0,
@@ -289,6 +317,7 @@ export const initValOutUsage = [
},
{
구분: "장외용수",
usage: "indstUswtr",
용수명: "공업용수",
total: 0,
@@ -307,7 +336,7 @@ export const initValOutUsage = [
},
];
export const subTotalObj = {
export const subTotalObj:PrfUsageSummary = {
usage: "subtotal",
용수명: "소계",
edit: false,
@@ -326,7 +355,7 @@ export const subTotalObj = {
"12월": 0,
};
export const totalObj = {
export const totalObj:PrfUsageSummary = {
usage: "total",
용수명: "총합계",
edit: false,
@@ -1,5 +1,4 @@
import { z } from "zod";
import type { TableUpperProps } from "../../ruseFcltMng/fcltReg/rainReg";
import type { TableUpperProps } from "../../common/type/header";
export const pbnstPrfmncSttnHeadListExport: TableUpperProps[] = [
{
@@ -37,6 +36,7 @@ export const pbnstPrfmncSttnHeadListExport: TableUpperProps[] = [
export const pbnstYearHeadListExport: TableUpperProps[] = [
{
id: "year",
title: "년도",
colSpan: 3,
row: 0
@@ -57,3 +57,25 @@ export const pbnstYearHeadListExport: TableUpperProps[] = [
row: 1
},
]
export const monthSttnHeadListExport: TableUpperProps[] = [
{ id: "구분", title: "구분", mergeCell: true },
{ id: "용수명", title: "용수명" },
{ id: "total", title: "계" },
{ id: "1월", title: "1월" },
{ id: "2월", title: "2월" },
{ id: "3월", title: "3월" },
{ id: "4월", title: "4월" },
{ id: "5월", title: "5월" },
{ id: "6월", title: "6월" },
{ id: "7월", title: "7월" },
{ id: "8월", title: "8월" },
{ id: "9월", title: "9월" },
{ id: "10월", title: "10" },
{ id: "11월", title: "11월" },
{ id: "12월", title: "12월", },
];
@@ -1,6 +1,6 @@
import { fetchType, getFetch, postFectch } from "@/components/lib/api";
import type { TableUpperProps } from "../../common/type/header";
import { pbnstPrfmncSttnHeadListExport, pbnstYearHeadListExport } from "./headList";
import { monthSttnHeadListExport, pbnstPrfmncSttnHeadListExport, pbnstYearHeadListExport } from "./headList";
import type { FcPrfType, PrfType } from "../../prfmncReg/pbnstPrfmncReg/type";
import type { pubHasuType, selectLabel } from "../../ruseFcltMng/fcltReg/pbnstReg/type";
import type { ReturnType } from "@common/business_components";
@@ -22,6 +22,7 @@ export type pbnstPrfmncSttnState = {
isInit: boolean;
rawData: any[];
selectYearList: selectLabel[]
monthSttnHeadList:TableUpperProps[];
}
}
@@ -34,7 +35,8 @@ export const pbnstPrfmncSttnExport: pbnstPrfmncSttnState = {
prfmncRes: prfmncRes,
isInit: false,
rawData: [],
selectYearList: []
selectYearList: [],
monthSttnHeadList:monthSttnHeadListExport
}
}
@@ -147,15 +149,15 @@ export const pbnstPrfmncSttnActionsExport: (set: any) => pbnstPrfmncSttnActions
let outUsageSum = 0;
let usageSum = 0;
let year = "";
const yearsData = []
const yearsData = [] as any
res.data.forEach((item) => {
res.data.forEach((item : any) => {
if (item.prfList.length === 0) {
const year = ""; // 연도 정보가 없으면 빈 문자열, 필요시 item에서 추출
const yearVal = { year: year, pbnstRuseFcltPk: item.pbnstRuseFcltPk ?? "", ruseUtztnFcltNm : item.ruseUtztnFcltNm ?? "" };
yearVal[year + "inUsage"] = 0;
yearVal[year + "outUsage"] = 0;
yearVal[year + "total"] = 0;
const year: string = ""; // 연도 정보가 없으면 빈 문자열, 필요시 item에서 추출.
const yearVal: { [key: string]: any } = { year: year, pbnstRuseFcltPk: item.pbnstRuseFcltPk ?? "", ruseUtztnFcltNm : item.ruseUtztnFcltNm ?? "" };
yearVal[`${year}inUsage`] = 0;
yearVal[`${year}outUsage`] = 0;
yearVal[`${year}total`] = 0;
yearsData.push(yearVal);
}
item.prfList.forEach((acc) => {
@@ -184,14 +186,14 @@ export const pbnstPrfmncSttnActionsExport: (set: any) => pbnstPrfmncSttnActions
);
if (yearData) {
yearData[year + "inUsage"] += inUsageSum;
yearData[year + "outUsage"] += outUsageSum;
yearData[year + "total"] += (inUsageSum + outUsageSum);
yearData[`${year}inUsage`] += inUsageSum;
yearData[`${year}outUsage`] += outUsageSum;
yearData[`${year}total`] += (inUsageSum + outUsageSum);
} else {
const yearVal = { year: year, pbnstRuseFcltPk: acc.pbnstRuseFcltFk, ruseUtztnFcltNm : item.ruseUtztnFcltNm ?? "" };
yearVal[year + "inUsage"] = inUsageSum;
yearVal[year + "outUsage"] = outUsageSum;
yearVal[year + "total"] = inUsageSum + outUsageSum;
const yearVal: { [key: string]: any } = { year: year, pbnstRuseFcltPk: acc.pbnstRuseFcltFk, ruseUtztnFcltNm : item.ruseUtztnFcltNm ?? "" };
yearVal[`${year}inUsage`] = inUsageSum;
yearVal[`${year}outUsage`] = outUsageSum;
yearVal[`${year}total`] = inUsageSum + outUsageSum;
yearsData.push(yearVal);
}
});
@@ -14,8 +14,8 @@ export const pubFacHeadListExport: TableUpperProps[] = [
export const pbnstMngUpHeadListExport: TableUpperProps[] = [
{ id: "choose", title: "선택", type: "checkbox" },
{ id: "operMthd", title: "운영방식",type: "select", selectData: "ruseMngMtd" },
{ id: "rprtvBzenty", title: "대행업체", edit: true },
{ id: "operMthd", title: "운영방식",type: "select", selectData: "ruseMngMtd" },
{ id: "rprtvBzenty", title: "대행업체", edit: true ,maxLength:10 },
{
id: "bgngDt",
title: "시작일",
@@ -65,7 +65,6 @@ type pubFacActions = {
appendRuseFclt(array: customPbnst[]): void;
fileDelete: (atflCd: string) => void;
fileDownLoad: (atflCd: string) => void;
getpbnstInsertIndex: (data: pbnstInsertIndex) => void;
pbnstRuseFcltUpdate: (ruseRes: customPbnst[]) => void;
pbnstRuseBizUpdate: (ruseRes: fcBizType[]) => void;
pubHasuSearch :(page: string, sggOrCity: string , searchTxt:string) => void
@@ -177,9 +176,6 @@ export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
pubHasuInit: async (page: string, sggOrCity: string) => {
try {
const pbnstHasuRes = await hasuListFetch(page, sggOrCity);
return set((state: pubFacState) => ({
...state,
pbnst: {
@@ -222,22 +218,6 @@ export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
console.log(errorHasu);
}
},
// pbnstReg: async (txt: string | undefined) => {
// try {
// const pbnstRes = await hasuListFetch("11", "11");
// return set((state: pubFacState) => ({
// ...state,
// pbnst: {
// ...state.pbnst,
// pbnstRes: pbnstRes,
// isInit: false,
// },
// }));
// } catch (errorHasu) {
// console.log(errorHasu);
// }
// },
pbnstInsert: async (pbnstRes: customPbnst) => {
try {
@@ -249,8 +229,6 @@ export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
toast.success(`${pbnstRes.ruseUtztnFcltNm} 하수재이용 시설이 등록되었습니다.`);
}
const pbnstHasuRes = await hasuListFetch('1', '0');
return set((state: pubFacState) => ({
...state,
pbnst: {
@@ -276,25 +254,13 @@ export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
} ,pbnstRuseBizUpdate : async(ruseRes:fcBizType[])=>{
try {
console.log('ruseRes ', ruseRes)
const response = await putFectch(
`/reuseFc/pubFcBiz`,
ruseRes
);
// const pbnstRes = await hasuListFetch("11", "11");
// return set((state: pubFacState) => ({
// ...state,
// pbnst: {
// ...state.pbnst,
// pbnstRes: pbnstRes,
// isInit: false,
// },
// }));
} catch (error) {
console.error("Error pbnstRuseFcltUpdate:", error);
// toast.error(` 하수재이용 시설 사업이 수정이 실패되엇습니다..`);
}
} ,
getBizCycle: async (pbnstObj: customPbnst) => {
@@ -341,56 +307,13 @@ export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
fetchType.CS,
`/attach-service/api/v1/atflcd/download/${atflCd}`
);
if (!response.ok) {
throw new Error(`Error downloading file: ${response.statusText}`);
}
} catch (error) {
console.error("Error downloading file:", error);
throw new Error(`Error downloading file: ${error}`);
}
},
// pbnstMngData: (data: customPbnst[]) => {
// if (data.length > 0) {
// }
// return set((state: pubFacState) => {
// state.pbnst.pbnstMngRegData = data;
// state.pbnst.pbnstBizCycle =
// data.length <= 0
// ? [{ text: "없음", val: "1" }]
// : state.pbnst.pbnstBizCycle;
// return state;
// });
// },
// pbnstBizData: (data: fcBizType) => {
// return set((state: pubFacState) => {
// if (state.pbnst.pbnstMngRegData) {
// const regData = state.pbnst.pbnstMngRegData.find(
// (item) => data.pbnstRuseFcltFk === item.pbnstRuseFcltPk
// );
// if (regData) {
// const bizIdx = regData.fcBizs.findIndex(
// (item) => item.pbnstRuseFcltBizPk == data.pbnstRuseFcltBizPk
// );
// if (bizIdx >= 0) {
// regData.fcBizs[bizIdx] = data;
// const pbnstData = state.pbnst.pbnstMngRegData
// state.pbnst.pbnstMngRegData= [...pbnstData]
// }
// }
// }
// return state;
// });
// },
getpbnstInsertIndex: async (data: pbnstInsertIndex) => {
return set((state: pubFacState) => {
state.pbnst.pbnsUpdateIndex = data;
return state;
});
},
appendRuseFclt: async (array: customPbnst[]) => {
try {
return set((state: pubFacState) => ({
@@ -420,9 +343,7 @@ export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
fcOrgwtsNmList:fcOrgwtsNmList.data??[]
},
}));
}
};
};
@@ -82,6 +82,10 @@ const zNum = z.preprocess(
(v) => (v !== null && v !== undefined ? Number(v) : v),
z.number()
);
const zNumGte = z.preprocess(
(v) => (v !== null && v !== undefined ? Number(v) : v),
z.number().gt(0, { message: "0보다 큰 숫자만 가능합니다" })
);
const zNumNullish = zNum.nullish();
const zNumDefaultZero = zNum.default(0).nullish();
@@ -151,7 +155,6 @@ const dmdColist = z.object({
export const fcBizSchema = z.object({
pbnstRuseFcltBizPk: zNumNullish,
pbnstRuseFcltFk: z.string().nullish(),
superkey: z.string().default("").nullish(),
cycl: zNum.default(1),
seCd: z.string().max(10, "구분은 10자를 초과할 수 없습니다.").default(""),
bizMthdCd: z.string().default(""),
@@ -236,25 +239,31 @@ export const fcBizSchema = z.object({
export const pbnstRegZod = z.object({
pbnstRuseFcltPk: z.string().default(""),
swtrmtFcltFk: z.string().default(""),
ruseUtztnFcltNm: z
.preprocess(
ruseUtztnFcltNm: //z.string().default(''),
z.preprocess(
(v) => (v !== null && v !== undefined ? String(v).trim() : ""), // null/undefined → "", 공백 제거
z.string().min(1, "시설 이름을 입력하세요")),
fcltCpct: zNumDefaultZero,
ruseCpct: zNumDefaultZero,
splyExtraCpct: zNumDefaultZero,
fcltCpct: z.preprocess(
(v) => (v !== null && v !== undefined ? Number(v) : v),
z.number().gte(0, { message: "재이용시설 용량은 0보다 크거나 같아야 합니다" })
),
ruseCpct: z.preprocess(
(v) => (v !== null && v !== undefined ? Number(v) : v),
z.number().gte(0, { message: "재이용시설 재이용수 공급량은 0보다 크거나 같아야 합니다" })
),
splyExtraCpct: z.preprocess(
(v) => (v !== null && v !== undefined ? Number(v) : v),
z.number().gte(0, { message: "재이용시설 공급가능량은 0보다 크거나 같아야 합니다" })
),
regDt: zDateDefaultNow,
rgtr: z.string().default("test"),
mdfcnDt: zDateDefaultNow,
mdfr: z.string().default("test"),
fcFiles: z.array(fcFileSchema).default([]).nullish(),
fcBizs: z.array(fcBizSchema).default([]),
fcOpers: z
.array(fcOperSchema)
.refine((val) => val.length >= 1, {
message: "재이용시설의 운영정보를 최소 하나를 등록해주세요",
})
.default([]), // 기본값 설정
fcOpers://z.array(fcOperSchema).default([]),
z .array(fcOperSchema)
.min(1, { message: "재이용시설의 운영정보를 최소 하나를 등록해주세요" })
});
export const pbnstRegArrayZod = z.array(pbnstRegZod);
+12 -3
View File
@@ -108,8 +108,18 @@ export const postFectch = async (url: string, params: any, type?: string) => {
return await response.json();
};
export const putFectch = async (url: string, params: any) => {
const response = await fetch(DEV_URL_WR + url, {
export const putFectch = async (url: string, params: any,type?:string) => {
const div =
type === fetchType.COMMON
? DEV_URL_FO
: type === fetchType.LOCAL
? LOCAL_URL
: type === fetchType.CS
? ''
: DEV_URL_WR;
const response = await fetch(div + url, {
method: "PUT",
headers: {
"Content-Type": "application/json",
@@ -132,7 +142,6 @@ export const deleteFectch = async (url: string, params?: any, type?: string) =>
? ''
: DEV_URL_WR;
console.log("deleteFectch url", div + url);
const response = await fetch(div + url, {
method: "DELETE",
headers: {
+29 -2
View File
@@ -7,6 +7,9 @@ import {
} from "tus-js-client";
import { CS_TUS_UPLOAD, CS_URL } from "../config";
import type { FilesType } from "@/components/ui/form/fcltReg/pbnstReg/mngReg/mngRegForm";
import { fetchType, putFectch } from "../api";
import { error } from "console";
import toast from "react-hot-toast";
type UploadOptions = {
handleUploadStart?: (upload: Upload) => void;
@@ -60,8 +63,30 @@ export const TusClientUpload = (oFile: FilesType, options?: UploadOptions) =>
onSuccess(payload: OnSuccessPayload) {
options?.handleSuccess?.(payload);
if (fileInfo) {
console.log('fileInfo', fileInfo);
resolve(JSON.parse(fileInfo) as ReturnFileType);
const WrTableInfo = {
lnkgDmnNm: "tbWrRuseFcltFile",
lnkgDmnId: "fileTkn",
};
console.log('fileInfo ', fileInfo)
const fileParse = JSON.parse(fileInfo) as ReturnFileType;
putFectch(
`/attach-service/api/v1/atfl/attachments/${fileParse.atflCd}/info`,
WrTableInfo,
fetchType.CS
)
.then((res) => {
resolve(fileParse);
})
.catch((error) => {
reject({
causingError: {
cause: "파일 업로드 업데이트 실패",
},
} as DetailedError);
});
} else reject({} as DetailedError);
},
});
@@ -71,6 +96,8 @@ export const TusClientUpload = (oFile: FilesType, options?: UploadOptions) =>
} catch (e) {
console.log(e);
reject(e as DetailedError);
toast.error(String(e));
}
// setUpload(uploader);
});
@@ -111,12 +111,9 @@ export function PbnstBuseForm({
const fcOrgwts = form.watch(`items.${indexMng}.fcBizs.${indexBiz}.fcOrgwts`);
useEffect(() => {
console.log("fcOrgwts", fcOrgwts);
if (fcOrgwts && fcOrgwts?.length > 0) {
const swtrmtFcltFkList = fcOrgwts?.map((item) => item.swtrmtFcltFk);
console.log("swtrmtFcltFkList ", swtrmtFcltFkList);
if (swtrmtFcltFkList.length > 0) {
getFcOrgwts(
swtrmtFcltFkList.filter((item): item is string => item != null),
@@ -317,8 +314,6 @@ useEffect(() =>{
const pbnstBiz = form.watch(`items.${indexMng}.fcBizs`);
return (
<>
{pbnstBiz && pbnstBiz?.length > 0 ? (
@@ -488,24 +483,11 @@ useEffect(() =>{
}
headList={pbnst.pplInstlsHeadLisat}
code={ppiSelectList ?? []}
//ref={ref}
indexMng={indexMng}
indexBiz={indexBiz}
form={form}
formNm={"pplInstls"}
upHeadList={[]}
onTableSet={(val) => {
const pplSum = form.watch(
`items.${indexMng}.fcBizs.${indexBiz}.pplInstls`
);
if (!pplSum) return;
let sum = 0;
pplSum.forEach((item) => {
sum += Number(item.cpct) || 0;
});
setSumCpct(sum);
}}
/>
</div>
@@ -9,9 +9,8 @@ import {
} from "@common/business_components/ui";
import { Form, FormField } from "@common/business_components/ui/form";
import { Button, Input } from "@common/components";
import { useEffect, useState } from "react";
import { useFieldArray, useWatch, type UseFormReturn } from "react-hook-form";
import { z } from "zod";
import { useEffect, useRef, useState } from "react";
import { useFieldArray, type UseFormReturn } from "react-hook-form";
import {
commonButonSize,
formH1Class,
@@ -19,7 +18,6 @@ import {
} from "@/components/lib/class/comClass";
import { TusClientUpload } from "@/components/lib/useTus_wr/useTusWr";
import {
pbnstRegZod,
type customPbnst,
type fcFileType,
type PbnstRegArrrayType,
@@ -50,15 +48,19 @@ export function PbnstMngForm({
indexMng: number;
setIndexMng: (index: number) => void;
}) {
const { code, pbnst, pbnstInsert, fileDelete, fileDownLoad } = useWrStore(
const { code, pbnst, fileDelete, fileDownLoad } = useWrStore(
(state) => state
);
const { pbnstRes } = pbnst;
const fileInitRef = useRef<{ index: number; key: string } | null>(null);
const [regFileList, setRegFileList] = useState<fcFileType[] | null>(null);
const [planFiles, setPlanFiles] = useState<FilesType[] | null>(null);
const [relationfiles, setRelationFiles] = useState<FilesType[] | null>(null);
const [fcltNm, setFcltNm] = useState<selectLabel[] | null>(null);
const [opersKey, setOpersKey] = useState(0);
useEffect(() => {
setOpersKey((prev) => prev + 1);
}, [indexMng]);
const [mngMtdCode, setMngMtdCode] =
useState<{ name: string; val: SelectDataType[] }[]>();
@@ -71,9 +73,9 @@ export function PbnstMngForm({
name: `items.${indexMng}.fcOpers`,
});
const watchedItem = useWatch({
const { fields: mngRegForm } = useFieldArray({
control: form.control,
name: `items.${indexMng}`,
name: `items`,
});
const plusHist = () => {
@@ -88,6 +90,8 @@ export function PbnstMngForm({
bgngDt: new Date(),
endDt: new Date(),
});
//trigger(`items.${indexMng}.fcOpers`);
};
const removeSelected = () => {
@@ -171,68 +175,69 @@ export function PbnstMngForm({
};
useEffect(() => {
if (indexMng >= 0) {
const defaultFiles = watchedItem?.fcFiles;
if (defaultFiles && defaultFiles.length > 0) {
const relationFileList = defaultFiles.filter(
(item) => item.fileKnd === "계통도"
);
const currentItem = form.getValues(`items.${indexMng}`);
const currentKey = JSON.stringify(currentItem);
const isNewItem =
!fileInitRef.current ||
fileInitRef.current.index !== indexMng ||
fileInitRef.current.key !== currentKey;
const planFileList = defaultFiles.filter(
(item) => item.fileKnd === "평면도"
);
if (relationFileList.length > 0)
setRelationFiles(
relationFileList.map((item) => ({
atflCd: item.fileTkn,
file: new File([] as BlobPart[], item.filePath),
}))
);
else {
setRelationFiles(null);
}
if (!isNewItem) return; //
if (planFileList.length > 0)
setPlanFiles(
planFileList.map((item) => ({
atflCd: item.fileTkn,
file: new File([] as BlobPart[], item.filePath),
}))
);
else {
setPlanFiles(null);
}
const defaultFiles = currentItem?.fcFiles || [];
const relationFileList = defaultFiles.filter(
(item) => item.fileKnd === "계통도"
);
const planFileList = defaultFiles.filter(
(item) => item.fileKnd === "평면도"
);
setRelationFiles(
relationFileList.length > 0
? relationFileList.map((item) => ({
atflCd: item.fileTkn,
file: new File([], item.filePath),
}))
: null
);
setPlanFiles(
planFileList.length > 0
? planFileList.map((item) => ({
atflCd: item.fileTkn,
file: new File([], item.filePath),
}))
: null
);
// ✅ 다음 루프에선 다시 안 하도록 저장
fileInitRef.current = {
index: indexMng,
key: currentKey,
};
}, [indexMng, form.getValues(`items.${indexMng}`)]);
useEffect(
() => {
//폼이 들어오면 폼에 대한 이름 셀렉트박스를만들기 위해
if (mngRegForm && mngRegForm.length >= 0) {
const fcltNmList = mngRegForm?.map((item, index) => ({
text: item.ruseUtztnFcltNm,
val: String(index),
}));
if (fcltNmList) setFcltNm(fcltNmList);
} else {
setRelationFiles(null);
setPlanFiles(null);
setFcltNm(null);
}
}
}, [watchedItem, indexMng]);
}, //pbnst.pbnstRes
[mngRegForm]
);
useEffect(() => {
// pbnstMngData(pbnst.pbnstMngRegData);
}, [pbnst.pbnstMngRegData]);
useEffect(() => {
if (pbnst.pbnstRes && pbnst.pbnstRes?.length >= 0) {
const fcltNmList = pbnst.pbnstRes?.map((item, index) => ({
text: item.ruseUtztnFcltNm,
val: String(index),
}));
console.log(" fcltNmList ", fcltNmList);
if (fcltNmList) setFcltNm(fcltNmList);
} else {
setFcltNm(null);
if (regFileList && regFileList?.length > 0) {
form.setValue(`items.${indexMng}.fcFiles`, regFileList);
}
}, [pbnst.pbnstRes]);
// 2. Define a submit handler.
function onSubmit(values: z.infer<typeof pbnstRegZod>) {
values.fcOpers = [];
values.fcFiles = regFileList || [];
pbnstInsert(values);
}
}, [regFileList, indexMng]);
useEffect(() => {
if (relationfiles) {
@@ -251,14 +256,6 @@ export function PbnstMngForm({
}
}, [code]);
useEffect(() => {
// console.log(' fcltNm ', watchedItem?.ruseUtztnFcltNm)
}, [watchedItem]);
useEffect(() => {
console.log(" form indexMng ", indexMng);
}, [indexMng]);
return (
<div className=" !mx-[1.6rem] !p-0r">
<div>
@@ -338,26 +335,25 @@ export function PbnstMngForm({
</div>
<div className="h-[200px] overflow-y-auto">
<RuseMngTableForm
tableData={fcOpersField}
key={`ruse-table-${indexMng}-${fcOpersField.length}`} // 🔥 length까지 넣어야 동기화됨
tableData={form.getValues(`items.${indexMng}.fcOpers`) ||[]}
headList={
formType === "sttn"
? pbnst.pbnstMngUpHeadList.map((item) => {
return {
...item,
readonly: true,
};
})
return {
...item,
readonly: true,
};
})
: pbnst.pbnstMngUpHeadList
}
upHeadList={pbnst.pbnstMngNm}
code={mngMtdCode || []}
onTableSet={(val) => {
//setFcOpresData(val);
}}
indexMng={indexMng}
form={form}
formNm={"fcOpers"}
// ref={ref}
// ref={ref}
></RuseMngTableForm>
</div>
</div>
@@ -374,6 +370,7 @@ export function PbnstMngForm({
<Input
key={`items.${indexMng}.fcltCpct`}
placeholder=""
maxLength={10} //입력제한
type="text"
onChange={(e) => {
if (formType !== "sttn")
@@ -397,6 +394,7 @@ export function PbnstMngForm({
<Input
key={`items.${indexMng}.ruseCpct`}
placeholder=""
maxLength={10} //입력제한
type="text"
onChange={(e) => {
if (formType !== "sttn")
@@ -419,6 +417,7 @@ export function PbnstMngForm({
<Input
key={`items.${indexMng}.splyExtraCpct`}
placeholder=""
maxLength={10} //입력제한
type="text"
onChange={(e) => {
if (formType !== "sttn")
@@ -518,3 +517,7 @@ export function PbnstMngForm({
</div>
);
}
function trigger(arg0: string) {
throw new Error("Function not implemented.");
}
@@ -110,6 +110,9 @@ export default function MngRegFormDetail({
<Input
placeholder=""
type="text"
value={field.value ?? ""}
onChange={field.onChange}
readOnly={formHead.option === "readOnly" ? true : false}
@@ -35,9 +35,7 @@ export function PbnstRegModal({
setPbnstInsert: (data: customPbnst) => void;
onInvalid:(errors: FieldErrors<{ items: z.infer<typeof pbnstRegZod>[] }>) => void
}) {
const { pbnstInsert } = useWrStore((state) => {
return state;
});
const [pbnstBdstForm, setPbnstBdstForm] = useState<customPbnst>(
{} as customPbnst
);
@@ -126,6 +124,7 @@ export function PbnstRegModal({
}, [form.formState.errors]);
useEffect(() => {
const firstForm = form.getValues("items");
if (firstForm) {
setIndexMng(firstForm.length - 1);
@@ -1,3 +1,4 @@
import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead";
import { useWrStore } from "@/app/store";
import type { TableUpperProps } from "@/app/store/common/type/header";
import {
@@ -14,8 +15,10 @@ import {
type fcBizType,
} from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import { formH1Class } from "@/components/lib/class/comClass";
import { InputTableBody } from "@/components/lib/func/TableData";
import { PbnstMngForm } from "@/components/ui/form/fcltReg/pbnstReg/mngReg/mngRegForm";
import { ScrollArea, Title, UiTable } from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import {
Tabs,
@@ -23,6 +26,9 @@ import {
TabsTrigger,
Button,
TabsContent,
TableHeader,
TableBody,
Table,
} from "@common/components/ui";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect, useState } from "react";
@@ -30,7 +36,7 @@ import { set, useForm } from "react-hook-form";
import { z } from "zod";
export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titleVisible?: boolean }) {
const { code, pbnstSttn, prfmnc } = useWrStore((state) => state);
const { code, pbnstSttn, prfmnc , pbnstPrfmncSttn} = useWrStore((state) => state);
const [fcltTab, setFcltTab] = useState<string>("fclt");
const [ruseTab, setRuseTab] = useState<string>("totalPrf");
const [ruseBizData, setRuseBizData] = useState<{
@@ -180,6 +186,7 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
const usageKey = inData.usage;
const value = (prfItem as any)[usageKey] ?? 0;
inData[monthKey] = value;
inData.total += value;
@@ -231,7 +238,6 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
)?.prfList;
if (prfList) {
console.log("prfList", prfList);
getTablePrfData(prfList);
}
@@ -324,17 +330,23 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
</TabsList>
<TabsContent className="max-h-full" value={ruseTab}>
{prfData && (
<UiTable
headName={undefined}
tableData={prfData[ruseTab as keyof typeof 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 ">
<ScrollArea className="h-[60vh]">
<div className="card-header">
<h3 className="text-2xl font-medium text-label">
{"하수처리수재이용 실적(m3) 등록결과"}
</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>
@@ -155,4 +155,6 @@ const RuseMngTable = React.forwardRef<any, RuseMngTableProps>(
);
}
);
RuseMngTable.displayName = "RuseMngTable";
export default RuseMngTable;
@@ -1,7 +1,6 @@
import { headMakeprfmnc } from "@/app/ruseFcltMng/prfmncReg/chkgdnReg/TableHead";
import type { TableUpperProps } from "@/app/store/common/type/header";
import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn/headList";
import type { customPbnst as OriginalCustomPbnst } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import { selectClass } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import {
formatCommaNumber,
@@ -32,7 +31,6 @@ type RuseMngTableProps = {
headList: TableUpperProps[];
upHeadList: chHeadType[];
code?: { name: string; val: SelectDataType[] }[];
onTableSet?: (item: any) => void;
indexMng?: number;
indexBiz?: number;
form?: any;
@@ -46,7 +44,6 @@ const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
headList,
upHeadList,
code,
onTableSet,
indexMng,
form,
formNm,
@@ -56,7 +53,8 @@ const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
) => {
return (
<>
<Table key={`table-${indexMng}-${indexBiz}`} variant="secondary">
<Table key={`${formNm}-table-${indexMng}-${indexBiz}`} variant="secondary"
ref={ref}>
<TableHeader className="font-bold">
{upHeadList ? (
headMakeprfmnc(headList, upHeadList)
@@ -114,6 +112,7 @@ const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
: field.value || ""
}
readOnly={head.readonly ? true : false}
maxLength={head.maxLength?head.maxLength:15}
/>
) : head.type === "select" ? (
<SelectBox
@@ -183,4 +182,7 @@ const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
);
}
);
RuseMngTableForm.displayName = "RuseMngTableForm";
export default RuseMngTableForm;