물재이용사례관리 페이지 수정

This commit is contained in:
jyha00
2025-07-29 20:40:05 +09:00
parent 75d14782f4
commit e5f2cb2182
5 changed files with 245 additions and 187 deletions
+138 -100
View File
@@ -17,35 +17,45 @@ import {
UiModal,
UiTable,
type SelectDataType,
type SheetParameter,
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components/ui";
import { Button, Label } from "@common/components/ui";
import { useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
import toast, { Toaster } from "react-hot-toast";
import { useTranslation } from "react-i18next";
export default function RuseCaseMng() {
const { code, ruseCaseMng, selectRuseCaseMng } = useWrStore((state) => state);
const { ruseCaseMngList, status, count } = ruseCaseMng;
const { code, ruseCaseMng, selectRuseCaseMng, ruseCaseMngInit } = useWrStore((state) => state);
const { ruseCaseMngList, status, count, excelList } = ruseCaseMng;
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>([]);
const [objSearch, setObjSearch] = useState<objSearchType>({ sgg: "", city: "" });
const [sidoCd, setSidoCd] = useState<string>("");
const [sigunguCd, setSigunguCd] = useState<string>("");
const [selectUtz, setSelectUtz] = useState<string[] | []>(["조경용수"]);
// const [selectUtz, setSelectUtz] = useState<string[] | []>(["조경용수"]);
const [selectUtz, setSelectUtz] = useState<string>("");
const [name, setName] = useState<string>("");
const [resetPage, isResetPage] = useState(false);
const { t } = useTranslation('base');
// 물재이용사례 조회
const searchRuseCaseMng = async (pageNo: number, pageSize: number) => {
const searchRuseCaseMng = async (isExcel: boolean, pageNo: number, pageSize: number) => {
await selectRuseCaseMng(
isExcel,
pageNo,
pageSize,
sidoCd ?? "",
sigunguCd ?? "",
selectUtz[0] ?? "",
sidoCd ?? "",
sigunguCd ?? "",
selectUtz ?? "",
name ?? ""
);
}
useEffect(() => {
ruseCaseMngInit();
}, [])
// 시도 선택
const getSelCity = (val: string | number) => {
const cityValue = String(val);
@@ -69,91 +79,97 @@ export default function RuseCaseMng() {
isModal: boolean;
}>({ isModal: false });
// 다운로드
const download = () => {
searchRuseCaseMng(1, 10000);;
useEffect(() => {
if (excelList !== undefined && excelList.length === 0) {
toast.error(t('excelDownErrMsg'));
return;
}
fetch(`/sample_ruseCaseMng.xlsx`, {}).then(async (response) => {
if (!response.ok) {
throw Error(response.statusText);
}
// 받은 파일 바인너리 처리
const blobRet = await response.arrayBuffer();
const excelData1 = ruseCaseMngList.map((item) => {
return [
item.ruseBizNm,
item.bizBgngDate,
item.bizEndDate,
item.splyFcltKnd,
item.splyFcltNm,
item.splyFcltCpct,
item.dmdFcltNm,
item.dmdFcltAddr,
item.ruseFcltCpct,
item.ruseFcltPplLen,
item.ruseFcltUsg,
item.ruseFcltSplyCpct,
item.ruseFcltPrcsMsrc,
item.grnteWqUsg,
item.grnteWqGrssClfg,
item.grnteWqCombResdch,
item.grnteWqTrbt,
item.grnteWqBod,
item.grnteWqSmll,
item.grnteWqCrmty,
item.grnteWqTn,
item.grnteWqTp,
item.grnteWqPh,
item.grnteWqClIonQnt,
item.grnteWqCndctStat,
item.grnteWqRmrk,
item.reqBizGrssCst,
item.reqBizReuseFcltCst,
item.reqBizPplCst,
item.reqBizArchCst,
item.reqBizMchnCst,
item.reqBizMtrngCst,
item.reqBizGisCst,
item.reqBizCctvCst,
item.reqBizCmcnCst,
item.reqBizWstCst,
item.reqBizDesignCst,
item.reqBizSpvsCst,
item.reqBizSbsdCst,
item.reqBizEtc,
item.prcmPlanGrssCst,
item.prcmPlanNlep,
item.prcmPlanLcep,
item.prcmPlanBrdnCst,
item.prcmPlanEcqrRt,
item.clclnGrssCst,
item.clclnNlep,
item.clclnLcep,
item.clclnBrdnCst,
item.clclnEcqrRt,
];
});
const sheetParameter = [
{
data: excelData1,
headerNum: 2,
headerRange: 'A1:AX1',
sheetName: '물재이용사례',
startCol: 'A'
if (!response.ok) {
throw Error(response.statusText);
}
// 받은 파일 바인너리 처리
const blobRet = await response.arrayBuffer();
if(excelList){
const excelData1 = excelList.map((item) => {
return [
item.ruseBizNm,
item.bizBgngDate,
item.bizEndDate,
item.splyFcltKnd,
item.splyFcltNm,
item.splyFcltCpct,
item.dmdFcltNm,
item.dmdFcltAddr,
item.ruseFcltCpct,
item.ruseFcltPplLen,
item.ruseFcltUsg,
item.ruseFcltSplyCpct,
item.ruseFcltPrcsMsrc,
item.grnteWqUsg,
item.grnteWqGrssClfg,
item.grnteWqCombResdch,
item.grnteWqTrbt,
item.grnteWqBod,
item.grnteWqSmll,
item.grnteWqCrmty,
item.grnteWqTn,
item.grnteWqTp,
item.grnteWqPh,
item.grnteWqClIonQnt,
item.grnteWqCndctStat,
item.grnteWqRmrk,
item.reqBizGrssCst,
item.reqBizReuseFcltCst,
item.reqBizPplCst,
item.reqBizArchCst,
item.reqBizMchnCst,
item.reqBizMtrngCst,
item.reqBizGisCst,
item.reqBizCctvCst,
item.reqBizCmcnCst,
item.reqBizWstCst,
item.reqBizDesignCst,
item.reqBizSpvsCst,
item.reqBizSbsdCst,
item.reqBizEtc,
item.prcmPlanGrssCst,
item.prcmPlanNlep,
item.prcmPlanLcep,
item.prcmPlanBrdnCst,
item.prcmPlanEcqrRt,
item.clclnGrssCst,
item.clclnNlep,
item.clclnLcep,
item.clclnBrdnCst,
item.clclnEcqrRt,
];
});
const sheetParameter: SheetParameter[] = [
{
data: excelData1,
headerNum: 2,
headerRange: 'A1:AX1',
sheetName: '물재이용사례',
startCol: 'A'
}
];
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
await filePickedBlobArray(blobRet, '물재이용사례현황', sheetParameter);
}
];
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
await filePickedBlobArray(blobRet, '물재이용사례현황', sheetParameter);
});
}
}, [excelList])
// 양식받기
const sampleDownLoad = () => {
excelDownload(
[[]],
"물재이용사례 관리",
"물재이용사례 관리 등록양식",
"sample_ruseCaseMng.xlsx",
"A1:AX1",
2
@@ -161,7 +177,7 @@ export default function RuseCaseMng() {
}
useEffect(() => {
if(status === 200){
if (status === 200) {
setIsExcelOpen({ isModal: false });
}
}, [status]);
@@ -174,7 +190,7 @@ export default function RuseCaseMng() {
<Title title={"물재이용사례 관리"} />
<SearchDiv>
<SearchFormLeft>
<div className="col-span-8 flex flex-row">
<div className="col-span-8 flex flex-row items-center">
<SelectBox
className="col-span-2 w-1/3 h-full text-2xl"
label="시도"
@@ -183,24 +199,28 @@ export default function RuseCaseMng() {
onSelectValue={getSelCity}
/>
<SelectBox
className="col-span-2 w-1/3 h-full text-2xl"
className="col-span-2 w-1/3 h-full text-2xl ml-4"
label="시군구"
selectClass={""}
selectArray={selectSgg || []}
onSelectValue={getSgg}
/>
<SelectBox
className="col-span-2 w-1/3 h-full text-2xl"
className="col-span-2 w-1/3 h-full text-2xl ml-4"
label="용도"
selectClass={""}
selectArray={ruseUtzType}
onSelectValue={(val) => {
if (val) setSelectUtz([String(val)]);
if (val) setSelectUtz(String(val));
}}
value={selectUtz || ruseUtzType[0]?.val}
/>
<Label className="w-28 text-xl ml-4 mr-6">
{"수요처명"}
</Label>
<SearchInput
className={"text-2xl"}
label="수요처명"
className={"col-span-2 w-1/3 text-2xl"}
label=""
textValue={name}
setText={(e) => {
setName(e);
@@ -211,13 +231,29 @@ export default function RuseCaseMng() {
<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={() => { searchRuseCaseMng(1, 20) }}>
<Button size={"sm"} onClick={() => {
searchRuseCaseMng(false, 1, 10);
isResetPage(true);
}}>
조회
</Button>
<Button size={"sm"} onClick={() => { setIsExcelOpen({ isModal: true }); }}>
엑셀등록
</Button>
<Button size={"sm"} onClick={() => { download() }}>
<Button size={"sm"} onClick={() => {
selectRuseCaseMng(
true,
1,
count,
sidoCd ?? "",
sigunguCd ?? "",
selectUtz ?? "",
name ?? ""
);
// download()
}} className={"green"}>
다운로드
</Button>
<Button size={"sm"} onClick={() => { sampleDownLoad() }}>
@@ -239,10 +275,12 @@ export default function RuseCaseMng() {
headlist={ruseCaseMng.ruseHeadList}
pageSize={20}
total={count}
cellClick={() => {}}
cellClick={undefined}
onPageChange={(pageNo: number) => {
searchRuseCaseMng(pageNo, 10);
searchRuseCaseMng(false, pageNo, 10);
isResetPage(false)
}}
resetPageNo={resetPage}
/>
</div>
</ListDiv>
@@ -254,9 +292,9 @@ export default function RuseCaseMng() {
<UiModal
open={isExcelOpen.isModal}
onOpenChange={() => {
setIsExcelOpen({ isModal: !isExcelOpen.isModal })
setIsExcelOpen({ isModal: !isExcelOpen.isModal })
}}
bodyClass={"w-[40vw] max-w-none"}
bodyClass={"w-[35vw] max-w-none"}
body={<RuseCaseMngExcel />}
/>
</>
@@ -1,7 +1,6 @@
import type { SelectDataType } from "@common/business_components/ui";
import type { TableUpperProps } from "../../common/type/header";
//★☆★☆ 여기서부터 수정하기 ★☆★☆
export const ruseCaseHeadListExport: TableUpperProps[] = [
{
id: "ruseBizNm",
@@ -358,6 +357,7 @@ export const ruseCaseHeadListExport: TableUpperProps[] = [
];
export const ruseUtzType: SelectDataType[] = [
{ text: "전체", val: "0" },
{ text: "조경용수", val: "조경용수" },
{ text: "청소화장실용수", val: "청소화장실용수" },
{ text: "세척살수용수", val: "세척살수용수" },
+90 -64
View File
@@ -4,90 +4,93 @@ import type { TableUpperProps } from "../../common/type/header";
import { ruseCaseHeadListExport } from "./headList";
export type ruseCaseState = {
ruseCaseMng: {
ruseHeadList:TableUpperProps[];
ruseCaseMngList:ruseCaseMngExcelProps[];
ruseHeadList: TableUpperProps[];
ruseCaseMngList: ruseCaseMngExcelProps[];
status: number;
count: number;
excelList?: ruseCaseMngExcelProps[];
};
};
export interface ruseCaseMngExcelProps {
ruseBizNm: string,
bizBgngDate: string,
bizEndDate: string,
splyFcltKnd: string,
splyFcltNm: string,
splyFcltCpct: number | 0 |'',
dmdFcltNm: string,
dmdFcltAddr: string,
ruseFcltCpct: number | 0 |'',
ruseFcltPplLen: string,
ruseFcltUsg: string,
ruseFcltSplyCpct: number | 0 |'',
ruseFcltPrcsMsrc: string,
grnteWqUsg: string,
grnteWqGrssClfg: number | 0 |'',
grnteWqCombResdch: number | 0 |'',
grnteWqTrbt: string,
grnteWqBod: string,
grnteWqSmll: string,
grnteWqCrmty: string,
grnteWqTn: string,
grnteWqTp: string,
grnteWqPh: string,
grnteWqClIonQnt: string,
grnteWqCndctStat: string,
grnteWqRmrk: string,
reqBizReuseFcltCst: number | 0 |'',
reqBizPplCst: number | 0 |'',
reqBizArchCst: number | 0 |'',
reqBizMchnCst: number | 0 |'',
reqBizMtrngCst: number | 0 |'',
reqBizGisCst: number | 0 |'',
reqBizCctvCst: number | 0 |'',
reqBizCmcnCst: number | 0 |'',
reqBizWstCst: number | 0 |'',
reqBizDesignCst: number | 0 |'',
reqBizSpvsCst: number | 0 |'',
reqBizSbsdCst: number | 0 |'',
reqBizEtc: string,
reqBizGrssCst: number | 0 |'',
prcmPlanNlep: number | 0 |'',
prcmPlanLcep: number | 0 |'',
prcmPlanBrdnCst: number | 0 |'',
prcmPlanEcqrRt: number | 0 |'',
prcmPlanGrssCst: number | 0 |'',
clclnNlep: number | 0 |'',
clclnLcep: number | 0 |'',
clclnBrdnCst: number | 0 |'',
clclnEcqrRt: number | 0 |'',
clclnGrssCst: number | 0 |'',
ruseBizNm: string,
bizBgngDate: string,
bizEndDate: string,
splyFcltKnd: string,
splyFcltNm: string,
splyFcltCpct: number | 0 | '',
dmdFcltNm: string,
dmdFcltAddr: string,
ruseFcltCpct: number | 0 | '',
ruseFcltPplLen: string,
ruseFcltUsg: string,
ruseFcltSplyCpct: number | 0 | '',
ruseFcltPrcsMsrc: string,
grnteWqUsg: string,
grnteWqGrssClfg: number | 0 | '',
grnteWqCombResdch: number | 0 | '',
grnteWqTrbt: string,
grnteWqBod: string,
grnteWqSmll: string,
grnteWqCrmty: string,
grnteWqTn: string,
grnteWqTp: string,
grnteWqPh: string,
grnteWqClIonQnt: string,
grnteWqCndctStat: string,
grnteWqRmrk: string,
reqBizReuseFcltCst: number | 0 | '',
reqBizPplCst: number | 0 | '',
reqBizArchCst: number | 0 | '',
reqBizMchnCst: number | 0 | '',
reqBizMtrngCst: number | 0 | '',
reqBizGisCst: number | 0 | '',
reqBizCctvCst: number | 0 | '',
reqBizCmcnCst: number | 0 | '',
reqBizWstCst: number | 0 | '',
reqBizDesignCst: number | 0 | '',
reqBizSpvsCst: number | 0 | '',
reqBizSbsdCst: number | 0 | '',
reqBizEtc: string,
reqBizGrssCst: number | 0 | '',
prcmPlanNlep: number | 0 | '',
prcmPlanLcep: number | 0 | '',
prcmPlanBrdnCst: number | 0 | '',
prcmPlanEcqrRt: number | 0 | '',
prcmPlanGrssCst: number | 0 | '',
clclnNlep: number | 0 | '',
clclnLcep: number | 0 | '',
clclnBrdnCst: number | 0 | '',
clclnEcqrRt: number | 0 | '',
clclnGrssCst: number | 0 | '',
}
type ruseCaseActions = {
selectRuseCaseMng: (pageNo: number, pageSize: number, sidoCd: string, sigunguCd: string, usageCd : string, name: string) => Promise<void>;
ruseCaseMngInit: () => void;
selectRuseCaseMng: (isExcel: boolean, pageNo: number, pageSize: number, sidoCd: string, sigunguCd: string, usageCd: string, name: string) => Promise<void>;
insertRuseCaseMng: (data: any) => Promise<void>;
};
export const fetchSearchRuseCaseMng = async (pageNo: number, pageSize: number, sidoCd: string, sigunguCd: string, usageCd : string, name: string) => {
const tailUrl = '/'+pageNo+'/'+pageSize+ ((sigunguCd !== '전체' && sigunguCd !=='') ? `/${sigunguCd}` : (sidoCd != '전체' && sidoCd != '') ? `/${sidoCd}` : `/0`) + (usageCd? `/${usageCd}` : '/0') + (name? `/${name}` : '');
const resp = await getFetchWithCount(fetchType.WR,`/reuseFc/pubFcRuseCase${tailUrl}`);
return {data:resp.data, count:resp.count};
export const fetchSearchRuseCaseMng = async (pageNo: number, pageSize: number, sidoCd: string, sigunguCd: string, usageCd: string, name: string) => {
const tailUrl = '/' + pageNo + '/' + pageSize + ((sigunguCd !== '전체' && sigunguCd !== '') ? `/${sigunguCd}` : (sidoCd != '전체' && sidoCd != '') ? `/${sidoCd}` : `/0`) + (usageCd ? `/${usageCd}` : '/0') + (name ? `/${name}` : '');
const resp = await getFetchWithCount(fetchType.WR, `/reuseFc/pubFcRuseCase${tailUrl}`);
return { data: resp.data, count: resp.count };
};
export const fetchInsertRuseCaseMng = async (data: any) => {
const response = await postFectch('/reuseFc/pubFcRuseCase', data, fetchType.WR);
return {data:response.data, status:response.status};
return { data: response.data, status: response.status };
};
export type ruseCaseType = ruseCaseState & ruseCaseActions;
export const ruseCaseStateExport: ruseCaseState = {
ruseCaseMng: {
ruseHeadList:ruseCaseHeadListExport,
ruseCaseMngList:[],
ruseHeadList: ruseCaseHeadListExport,
ruseCaseMngList: [],
status: 0,
count: 0,
excelList: undefined,
},
};
@@ -95,8 +98,8 @@ export const ruseCaseActionsExport: (set: any) => ruseCaseActions = (
set: any
) => {
return {
selectRuseCaseMng: async (pageNo: number, pageSize: number, sidoCd: string, sigunguCd: string, usageCd : string, name: string) => {
const res = await fetchSearchRuseCaseMng(pageNo, pageSize, sidoCd, sigunguCd, usageCd, name);
ruseCaseMngInit: async () => {
const res = await getFetchWithCount(fetchType.WR, `/reuseFc/pubFcRuseCase/1/10/0/0`);
set((state: ruseCaseState) => ({
ruseCaseMng: {
...state.ruseCaseMng,
@@ -105,12 +108,35 @@ export const ruseCaseActionsExport: (set: any) => ruseCaseActions = (
},
}));
},
selectRuseCaseMng: async (isExcel: boolean, pageNo: number, pageSize: number, sidoCd: string, sigunguCd: string, usageCd: string, name: string) => {
const res = await fetchSearchRuseCaseMng(pageNo, pageSize, sidoCd, sigunguCd, usageCd, name);
if (isExcel) {
set((state: ruseCaseState) => {
return {
...state,
ruseCaseMng: {
...state.ruseCaseMng,
count: res.count,
excelList: res.data
},
};
});
} else {
set((state: ruseCaseState) => ({
ruseCaseMng: {
...state.ruseCaseMng,
ruseCaseMngList: res.data,
count: res.count,
},
}));
}
},
insertRuseCaseMng: async (data: any) => {
const response = await fetchInsertRuseCaseMng(data);
if(response.status === 200){
if (response.status === 200) {
toast.success("물재이용사례 등록이 완료되었습니다. ");
}else{
} else {
toast.error("물재이용사례 등록에 실패하였습니다. ");
}
set((state: ruseCaseState) => ({
@@ -1,14 +1,14 @@
import { useWrStore } from "@/app/store";
import { coRegExcel } from "@/app/store/matDmd/coSttn/headList";
import type { ruseCaseMngExcelProps } from "@/app/store/matDmd/ruseCaseMng/index";
import { reUseCaseNames } from "@/app/store/matDmd/ruseCaseMng/excel";
import { filePicked, FileUpload, FormUi, Title } from "@common/business_components/ui";
import { Form, FormField } from "@common/business_components/ui/form";
import { Button } from "@common/components/ui";
import type { ruseCaseMngExcelProps } from "@/app/store/matDmd/ruseCaseMng/index";
import { filePicked, Title } from "@common/business_components/ui";
import { Form } from "@common/business_components/ui/form";
import { Button, Input } from "@common/components/ui";
import { zodResolver } from "@hookform/resolvers/zod";
import { useState } from "react";
import { useForm } from "react-hook-form";
import type { z } from "zod";
import { useWrStore } from "@/app/store";
export default function RuseCaseMngExcel() {
const { insertRuseCaseMng } = useWrStore((state) => state);
@@ -79,6 +79,7 @@ export default function RuseCaseMngExcel() {
};
Object.keys(reUseCaseNames).forEach((key: string) => {
console.log("reUseCaseNames", reUseCaseNames)
if (item && reUseCaseNames[key] !== undefined) {
const mappedKey = reUseCaseNames[key];
if (mappedKey && object.hasOwnProperty(mappedKey)) {
@@ -146,23 +147,16 @@ export default function RuseCaseMngExcel() {
</div>
<div>
<FormField
control={form.control}
name="file"
render={() => (
<FormUi label="">
<FileUpload
files={file ? [file] : []}
setFiles={(files: File[] | null) => {
console.log("files", files)
if (files && files?.length === 1) setFiles(files[0]);
}}
fileTypes=""
maxFiles={1}
></FileUpload>
</FormUi>
)}
/>
<div className="space-y-4 p-4">
<Input
type="file"
onChange={(e) => {
const selectedFile = e.target.files?.[0];
if (selectedFile) setFiles(selectedFile);
}}
accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
/>
</div>
</div>
</form>
</Form>
Binary file not shown.