This commit is contained in:
2025-06-26 17:28:26 +09:00
195 changed files with 25795 additions and 2558 deletions
@@ -0,0 +1,27 @@
import { client } from "@/shared/api";
import { ENDPOINT } from "@/shared/config";
import type {
LoginlogInfo,
LoginlogList,
LoginlogParams,
LoginlogService,
} from "../model/loginlog-interface";
export class LoginlogApiService implements LoginlogService {
public async getLoginlogList(params: LoginlogParams): Promise<LoginlogList> {
const response = await client.get<LoginlogList>(
`${ENDPOINT.USER_SERVICE.LOGINLOG}`,
{ params },
);
return response.data;
}
public async getLoginlogInfo(lgnSn: string): Promise<LoginlogInfo> {
const response = await client.get<LoginlogInfo>(
`${ENDPOINT.USER_SERVICE.LOGINLOG}/${lgnSn}`,
);
return response.data;
}
}
export const LoginlogApi = new LoginlogApiService();
+5
View File
@@ -0,0 +1,5 @@
export { LoginlogApiService } from "./api/loginlog-service";
export type {
Loginlog,
LoginlogParams,
} from "./model/loginlog-interface";
@@ -0,0 +1,37 @@
import type { PageableList, PageableParams } from "@/shared/model";
export interface LoginlogParams extends PageableParams {
lgnSn?: string;
userId?: string;
siteId?: string;
}
export interface Loginlog {
lgnSn: string;
lgnDt: string;
userId: string;
lgnIp: string;
lgnMethodCd: string;
errOcrnYn: string;
lgnErrCd: string;
siteId: string;
}
export interface LoginlogInfo {
lgnSn: string;
lgnDt: string;
userId: string;
lgnIp: string;
lgnMethodCd: string;
errOcrnYn: string;
lgnErrCd: string;
siteId: string;
}
export type LoginlogList = PageableList<Loginlog>;
export interface LoginlogService {
getLoginlogList: (params: LoginlogParams) => Promise<LoginlogList>;
getLoginlogInfo: (lgnSn: string) => Promise<LoginlogInfo>;
}
@@ -0,0 +1,49 @@
import dayjs from "dayjs";
import type { ColumnDef } from "@tanstack/react-table";
import type { Loginlog } from "@/entities/loginlog";
export const columns: ColumnDef<Loginlog>[] = [
{
id: "no",
header: "NO",
cell: ({ row, table }) => {
const totalRows = table.getRowCount();
const { pageIndex, pageSize } = table.getState().pagination;
return totalRows - (pageIndex * pageSize + row.index);
},
},
{
accessorKey: "lgnDt",
header: "등록일",
cell: ({ row }) => {
const date = dayjs(row.original.lgnDt);
return date.format("YYYY-MM-DD HH24:mi:ss");
},
},
{
accessorKey: "userId",
header: "사용자ID",
},
{
accessorKey: "로그인IP",
header: "remoteIp",
},
{
accessorKey: "lgnMthd",
header: "접속방식",
},
{
accessorKey: "오류여부",
header: "errOcrnYn",
},
{
accessorKey: "오류코드",
header: "lgnErrCd",
},
{
accessorKey: "사이트ID",
header: "siteId",
}
];
@@ -0,0 +1,92 @@
"use client";
import { useState } from "react";
import { keepPreviousData, useQuery } from "@tanstack/react-query";
import {
getCoreRowModel,
useReactTable,
type PaginationState,
} from "@tanstack/react-table";
import { Button, DataTable, Input, Label } from "@common/components";
import { LoginlogApi} from "../../../entities/loginlog/api/loginlog-service";
import { type LoginlogParams} from "../../../entities/loginlog/model/loginlog-interface";
import { ENDPOINT } from "@/shared/config";
import { columns } from "../model/table-columns";
type LoginlogPageProps = {
lgnSn?: string;
};
function LoginlogPage({ }: LoginlogPageProps) {
const [loginlogQuery, setLoginlogQuery] = useState<LoginlogParams>({
userId: "",
siteId: "",
});
const [pagination, setPagination] = useState<PaginationState>({
pageIndex: 0,
pageSize: 10,
});
const { data: loginlogList, refetch } = useQuery({
queryKey: [ENDPOINT.USER_SERVICE.LOGINLOG, , pagination],
queryFn: () =>
LoginlogApi.getLoginlogList({
...loginlogQuery,
page: pagination.pageIndex,
size: pagination.pageSize,
}),
placeholderData: keepPreviousData,
});
const table = useReactTable({
data: loginlogList?.content ?? [],
columns,
rowCount: loginlogList?.totalElements ?? 0,
state: { pagination },
manualPagination: true,
enableMultiRowSelection: false,
getCoreRowModel: getCoreRowModel(),
onPaginationChange: setPagination,
});
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
refetch();
};
return (
<div className="flex-1">
<div className="card card-border">
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
<Label htmlFor="" className="mr-2 text-label">
로그인로그
</Label>
<Input
className="h-[3.2rem] w-[20rem] rounded-sm !text-[1.3rem]"
value={loginlogQuery.userId}
onChange={(e) =>
setLoginlogQuery({
...loginlogQuery,
userId: e.target.value,
})
}
/>
<Button className="h-[3.2rem]" type="submit">
조회
</Button>
</form>
</div>
<div className="card card-border">
<div className="card-header">
<h3 className="text-2xl font-medium text-label">로그인로그 목록</h3>
</div>
<div className="card !m-4 h-[calc(100vh-35rem)] overflow-auto !p-0">
<DataTable table={table} viewPagination />
</div>
</div>
</div>
);
}
export { LoginlogPage };
+1 -1
View File
@@ -19,6 +19,7 @@ export const ENDPOINT = {
AUTHORIZATIONS: "/user-service/api/v1/authorizations",
ROLE_AUTHORIZATIONS: "/user-service/api/v1/role-authorizations",
ROLES: "/user-service/api/v1/roles",
LOGINLOG: "/user-service//api/v1/login-logs",
},
CMS_SERVICE: {
SITES: "/cms-service/api/v1/sites",
@@ -45,7 +46,6 @@ export const ENDPOINT = {
SURVEY_QUESTION: "/cms-service/api/v1/srvy-qitem",
SURVEY_ARTICLE: "/cms-service/api/v1/srvy-artcl",
ZIPS: "/cms-service/api/v1/zips",
LOGINLOG: "/cms-service/api/v1/loginlog",
GROUPS: "/cms-service/api/v1/groups",
GROUP_USERS: "/cms-service/api/v1/group-users",
MANAGER_IP: "/cms-service/api/v1/mgrip",
-5
View File
@@ -1,5 +0,0 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
+7 -67
View File
@@ -1,70 +1,10 @@
@import "../../../packages/common/components/src/base.css";
@import "@common/assets/styles/base.css";
@import "@common/assets/styles/diveicon.css";
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
html,
body {
font-family: "Noto Sans KR", sans-serif;
font-size: 10px;
}
+4
View File
@@ -1,6 +1,8 @@
'use client'
import { BaseLayout } from "@common/components";
import "./globals.css";
import { StoreProvider } from "./store";
import { MainDiv } from "@common/business_components";
export default function RootLayout({
children,
@@ -12,7 +14,9 @@ export default function RootLayout({
<body>
<StoreProvider>
<BaseLayout>
<MainDiv>
{children}
</MainDiv>
</BaseLayout>
</StoreProvider>
</body>
+4
View File
@@ -0,0 +1,4 @@
export default function Loading() {
return <div>페이지 불러오는 중입니다...</div>;
}
+672
View File
@@ -0,0 +1,672 @@
"use client";
import { useWrStore } from "@/app/store";
import {
DmdCoReqSchema,
type DedMatUpdateType,
type DmdCoReqType,
type DmdMatTableType,
} from "@/app/store/matDmd/coMatRvw/type";
import { formH1Class, formTableName } from "@/components/lib/class/comClass";
import {
getCity,
getdmdMatFlag,
tableData,
yearOptions,
} from "@/components/lib/func/commom";
import {
ContentsDiv,
Form,
FormField,
FormUi,
ScrollArea,
SearchDiv,
SearchFormLeft,
SearchFormRight,
SearchInput,
SelectBox,
Title,
UiModal,
UiTable,
type SelectDataType,
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button, Input, Label } from "@common/components/ui";
import { useEffect, useRef, useState } from "react";
import { useForm } from "react-hook-form";
import toast, { Toaster } from "react-hot-toast";
import { z } from "zod";
import moment from "moment";
import { usageProcData } from "@/app/store/matDmd/coMatRvw/headList";
import { zodResolver } from "@hookform/resolvers/zod";
import ConCostForm from "@/components/ui/form/coMat/conCostForm/conCostForm";
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
export default function CoMatRvw() {
const { code, coRvw, coMatRvwInit, coMatRvwSearch, coMatRvwInqua } =
useWrStore((state) => state);
const { coMatRvwRes } = coRvw;
//init, sub, match
const initRef = useRef<boolean>(false);
const { coRvwHeadList } = coRvw;
const [pageNation, setPageNatiion] = useState<number>(1);
const [dmdCoNm, setDmdCoNm] = useState<string>("");
const [dmdMatData, setDmdMtaData] = useState<DmdMatTableType[]>([]);
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>();
const [objSearch, setObjSearch] = useState<objSearchType>({
sgg: "",
city: "",
});
const [fromDate, setFromDate] = useState<string>(
String(new Date().getFullYear())
);
const [toDate, setToDate] = useState<string>(
String(new Date().getFullYear())
);
const [selectData, setSelectData] = useState<DmdCoReqType>(
{} as DmdCoReqType
);
const getSearch = (
startYear: number,
endYear: number,
sggCd: string,
dmdCoNm: string
) => {
if (dmdCoNm.length > 0) {
coMatRvwSearch(
pageNation,
13,
String(startYear),
String(endYear),
sggCd,
dmdCoNm
);
} else {
coMatRvwInqua(pageNation, 13, String(startYear), String(endYear), sggCd);
}
};
const form = useForm<z.infer<typeof DmdCoReqSchema>>({
resolver: zodResolver(DmdCoReqSchema),
});
const TableCellClick = (index: number) => {
console.log(coMatRvwRes);
if (coMatRvwRes && coMatRvwRes[index]) {
setSelectData(coMatRvwRes[index]);
}
};
useEffect(() => {
if (form?.getValues("useUsgCd")) {
form.setValue(
"demandCst.usgPrcsProcs",
usageProcData?.find(
(item) => item.usage === (form?.getValues("useUsgCd") as string)
)?.process ?? ""
);
}
}, [form.watch("useUsgCd")]);
useEffect(() => {
if (coMatRvwRes.length > 0) {
const data = coMatRvwRes?.map((item, index) => {
let flag = "";
flag = getdmdMatFlag(item?.demandMatching?.splyFcltFlg ??"");
return {
...item,
ctpvCd: item.demandCo?.ctpvCd,
sggCd: item.demandCo?.sggCd,
dmdCoNm: item.demandCo?.dmdCoNm,
daddr: item.demandCo?.daddr,
telno: item.demandCo?.telno,
regDt: moment(item?.demandCo?.regDt).format("YYYY-MM-DD"),
splyFcltFlg: flag,
};
});
setDmdMtaData(tableData(data, { code }));
}
}, [coMatRvwRes]);
const getSelCity = (val: string | number) => {
const cityValue = String(val); // Ensure val is treated as a string
const data = getCity(cityValue, code.sggCd);
setSelectSgg(data);
setObjSearch({ city: cityValue, sgg: "" });
};
const getSgg = (val: string | number) => {
setObjSearch({ ...objSearch, sgg: String(val) });
};
useEffect(() => {
if (!initRef.current) {
coMatRvwInit(1, 13, fromDate, toDate);
initRef.current = true;
}
}, [coMatRvwInit, initRef, fromDate, toDate]);
useEffect(() => {
if (selectData) {
console.log(selectData);
form.reset(selectData);
}
}, [selectData, form]);
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<Title title={"수요매칭검토"} />
<SearchDiv>
<SearchFormLeft>
<div className="col-span-10 flex flex-row">
<SelectBox
className="col-span-2 w-1/3 h-full text-2xl"
label="시도"
selectClass={""}
selectArray={code.cityCd || []}
onSelectValue={getSelCity}
/>
<SelectBox
className="col-span-2 w-1/3 h-full text-2xl ml-4"
label="시군구"
selectClass={""}
selectArray={selectSgg || []}
onSelectValue={getSgg}
/>
<div className="col-span-7 w-full">
<div className="flex flex-row items-center">
<Label className="text-xl text-gray-600 mx-6">
하수 재이용년도
</Label>
<SelectBox
className="h-full w-32 text-2xl"
label=""
selectClass={""}
selectArray={yearOptions}
value={fromDate}
onSelectValue={(val: string | number) =>
setFromDate(String(val))
}
/>
<span className="mx-6">~</span>
<SelectBox
className="h-full w-32 text-2xl"
label=""
selectClass={""}
selectArray={yearOptions}
value={toDate}
onSelectValue={(val: string | number) =>
setToDate(String(val))
}
/>
<div className="col-span-2 ml-6">
<SearchInput
className={"text-2xl"}
label="회사명"
textValue={dmdCoNm}
setText={setDmdCoNm}
/>
</div>
</div>
</div>
</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={(e) => {
if (fromDate && toDate) {
const fromNum = Number(fromDate);
const toNum = Number(toDate);
if (fromNum > toNum) {
toast.error(
"시작년도가 종료년도 이후로 설정할 수 없습니다."
);
} else {
let con: string | number = "";
if (String(objSearch.city).length > 0) {
con = String(objSearch.city);
}
if (String(objSearch.sgg).length > 0 && String(objSearch.sgg) !== "0") {
con = String(objSearch.sgg);
}
getSearch(fromNum, toNum, con, dmdCoNm);
}
}
}}
>
조회
</Button>
</div>
</div>
</SearchFormRight>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 g ap-4">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={"수요매칭검토현황"}
tableData={dmdMatData || []}
headlist={coRvwHeadList}
pageSize={20}
total={100000}
cellClick={(index: number | undefined, headId: string) => {
if (index !== undefined && index >= 0) {
TableCellClick(index);
}
}}
onPageChange={() => {}}
></UiTable>
</ListDiv>
<hr />
<ScrollArea className="h-[49vh]">
<ListDiv>
<h3 className="mt-4 ml-2 text-2xl font-medium text-label">
수요신청 상세현황
</h3>
<Form {...form}>
<div className="grid grid-cols-12 gap-4 ml-4 mr-4">
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="demandCo.regDt"
render={({ field }) => (
<FormUi label="요구시기">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(String(e.target.value));
}}
value={
moment(field.value).format("YYYY-MM-DD") ?? ""
}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="dmndQty"
render={({ field }) => (
<FormUi label="요구수량(M3/d)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="useUsgCd"
render={({ field }) => (
<FormUi label="사용용도">
<Input
placeholder=""
type="text"
step="0.1"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="wntUntprc"
render={({ field }) => (
<FormUi label="희망단가(원/m3)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-12 w-full">
<h1 className={formH1Class}>요구수질</h1>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="grssClfg"
render={({ field }) => (
<FormUi label="총대장균군수 (개/100ml)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="combResdch"
render={({ field }) => (
<FormUi label="결합잔류염소(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="trbt"
render={({ field }) => (
<FormUi label="탁도(NTU)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="blgcOxygDmndQnt"
render={({ field }) => (
<FormUi label="생물학적 산소요구량(BOD)(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="smll"
render={({ field }) => (
<FormUi label="냄새">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="crmty"
render={({ field }) => (
<FormUi label="색도(도)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="tn"
render={({ field }) => (
<FormUi label="총질소 (T-N)(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="tph"
render={({ field }) => (
<FormUi label="총인(T-P)(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="ph"
render={({ field }) => (
<FormUi label="수소이온농도(pH)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="clIonQnt"
render={({ field }) => (
<FormUi label="염화물(mgCL/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="cdtnv"
render={({ field }) => (
<FormUi label="전기전도도(㎲/cm)">
<Input
placeholder=""
type="number"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="rmrk"
render={({ field }) => (
<FormUi label="비고">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-12 w-full">
<h1 className={formH1Class}>공급처 후보지</h1>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${0}`}
render={({ field }) => (
<FormUi label="후보지1">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(String(e.target.value));
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${1}`}
render={({ field }) => (
<FormUi label="후보지2">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${2}`}
render={({ field }) => (
<FormUi label="후보지3">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
</div>
</Form>
<ConCostForm form={form} type={"mat"} />
</ListDiv>
</ScrollArea>
</div>
</div>
</ContentsDiv>
<Toaster position="top-center" />
</>
);
}
@@ -0,0 +1,126 @@
"use client";
import { useWrStore } from "@/app/store";
import { ruseUtzType } from "@/app/store/matDmd/ruseCaseMng/headList";
import { getCity } from "@/components/lib/func/commom";
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import { ContentsDiv, SearchDiv, SearchFormLeft, SearchFormRight, SearchInput, SelectBox, Title, UiTable, type SelectDataType } from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components/ui";
import { useState } from "react";
export default function RuseCaseMng() {
const { code,ruseCase} = useWrStore((state) => state);
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>()
const [objSearch, setObjSearch] = useState<objSearchType>({ sgg: "", city: "" });
const [selectUtz, setSelectUtz] = useState<string[] | []>()
const [searchTxt, setSearchTxt] = useState<string>()
const getSelCity = (val: string | number) => {
const cityValue = String(val);
const data = getCity(cityValue, code.sggCd);
setSelectSgg(data);
setObjSearch({ city: cityValue, sgg: '' });
};
const getSgg = (val: string | number) => {
setObjSearch({ ...objSearch, sgg: String(val) })
};
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<Title title={"물재이용사례 관리"} />
<SearchDiv>
<SearchFormLeft>
<div className="col-span-8 flex flex-row">
<SelectBox
className="col-span-2 w-1/3 h-full text-2xl"
label="시도"
selectClass={""}
selectArray={code.cityCd || []}
onSelectValue={getSelCity}
/>
<SelectBox
className="col-span-2 w-1/3 h-full text-2xl"
label="시군구"
selectClass={""}
selectArray={selectSgg || []}
onSelectValue={getSgg}
/>
<SelectBox
className="col-span-2 w-1/3 h-full text-2xl"
label="용도"
selectClass={""}
selectArray={ruseUtzType}
onSelectValue={(val) => {
if(val)
setSelectUtz([String(val)])}}
/>
<SearchInput
className={"text-2xl"}
label="수요처명"
textValue={""}
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={(e) => { }}
>
조회
</Button>
<Button
size={"sm"}
onClick={(e) => { }}
>
엑셀등록
</Button>
<Button
size={"sm"}
onClick={(e) => { }}
>
다운로드
</Button>
<Button
size={"sm"}
onClick={(e) => { }}
>
양식받기
</Button>
</div>
</div>
</SearchFormRight>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv className="overflow-x-auto">
<UiTable
headName={"물재이용사례 현황"}
tableData={[]}
children={undefined}
headlist={ruseCase.ruseHeadList}
pageSize={20}
total={100000}
cellClick={(index: number | undefined, headId: string) => {
}}
onPageChange={() => { }}
></UiTable>
</ListDiv>
</div>
</div>
</ContentsDiv>
</>
)
}
@@ -0,0 +1,338 @@
"use client";
import { useWrStore } from "@/app/store";
import {
DmdCoReqSchema,
type DmdCoReqType,
type RvwHistTableType,
} from "@/app/store/matDmd/coMatRvw/type";
import {
getCity,
getdmdMatFlag,
yearOptions,
} from "@/components/lib/func/commom";
import ConCostForm from "@/components/ui/form/coMat/conCostForm/conCostForm";
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import {
ContentsDiv,
SearchDiv,
SearchFormLeft,
SearchFormRight,
SearchInput,
SelectBox,
Title,
UiTable,
type SelectDataType,
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button, DatePicker, Input, Label } from "@common/components/ui";
import { zodResolver } from "@hookform/resolvers/zod";
import moment from "moment";
import { useCallback, useEffect, useState } from "react";
import { set, useFieldArray, useForm } from "react-hook-form";
import { z } from "zod";
import { tableData } from "@/components/lib/func/commom";
import toast, { Toaster } from "react-hot-toast";
import { ToastFormUi } from "@/components/ui/toast/toastFromUi";
export default function RuseRvwHstry() {
const {
code,
ruseHist,
ruseRvwHistInit,
ruseRvwSearch,
ruseRvwInqua,
ruseRvwComplete,
} = useWrStore((state) => state);
const { rvwHistRes, ruseHistHeadList } = ruseHist;
const [pageNation, setPageNatiion] = useState<number>(1);
const [dmdCoNm, setDmdCoNm] = useState<string>("");
const [ruseUtztnFcltNm, setRuseUtztnFcltNm] = useState<string>("");
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>();
const [objSearch, setObjSearch] = useState<objSearchType>({
sgg: "",
city: "",
});
const [fromDate, setFromDate] = useState<string>(
String(new Date().getFullYear())
);
const [toDate, setToDate] = useState<string>(
String(new Date().getFullYear())
);
const [rvwHistData, setRvwHistData] = useState<RvwHistTableType[]>();
const getSelCity = (val: string | number) => {
const cityValue = String(val); // Ensure val is treated as a string
const data = getCity(cityValue, code.sggCd);
setSelectSgg(data);
setObjSearch({ city: cityValue, sgg: "0" });
};
const getSgg = (val: string | number) => {
console.log(val);
setObjSearch({ ...objSearch, sgg: String(val) });
};
const getSearch = (
startYear: number,
endYear: number,
sggCd: string,
dmdCoNm: string,
ruseUtztnFcltNm: string
) => {
if (dmdCoNm || ruseUtztnFcltNm) {
ruseRvwSearch(
pageNation,
13,
String(startYear),
String(endYear),
sggCd,
dmdCoNm,
ruseUtztnFcltNm
);
} else {
ruseRvwInqua(pageNation, 13, String(startYear), String(endYear), sggCd);
}
};
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]);
}
},
[rvwHistRes, form]
);
const confrirmToast = () => {
const completeData = rvwHistData
?.map((item) => {
form.clearErrors;
if (item?.completeYn) {
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>
));
} else {
ruseRvwComplete(completeData as Number[]);
}
};
useEffect(() => {
if (!ruseHist.isInit) {
ruseRvwHistInit(
1,
13,
new Date().getFullYear().toString(),
new Date().getFullYear().toString()
);
}
}, [ruseHist.isInit]);
useEffect(() => {
if (rvwHistRes) {
const data = rvwHistRes?.map((item, index) => {
let flag = "";
flag = getdmdMatFlag(item.demandMatching?.splyFcltFlg ?? "");
return {
...item,
ctpvCd: item.demandCo?.ctpvCd,
sggCd: item.demandCo?.sggCd,
dmdCoNm: item.demandCo?.dmdCoNm,
daddr: item.demandCo?.daddr,
telno: item.demandCo?.telno,
regDt: item?.demandCo?.regDt
? moment(item?.demandCo?.regDt).format("YYYY-MM-DD")
: "없음",
rvwCmptnYmd: item?.rvwCmptnYmd
? moment(item?.rvwCmptnYmd).format("YYYY-MM-DD")
: "없음",
mtchnCmptnYmd: item?.mtchnCmptnYmd
? moment(item?.mtchnCmptnYmd).format("YYYY-MM-DD")
: "없음",
ruseUtztnFcltNm: item.ruseUtztnFcltNm,
dmndQty: item.dmndQty,
splyFcltFlg: flag,
completeYn: false,
} as unknown as RvwHistTableType;
});
setRvwHistData(tableData(data, { code }));
}
}, [rvwHistRes]);
useEffect(() => {
console.log("변경여부 ", form.formState.isDirty);
}, [form.formState]);
return (
<ContentsDiv>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<Title title={"재이용검토이력"} />
<SearchDiv>
<SearchFormLeft>
<div className="col-span-10 flex flex-row">
<SelectBox
className="w-80 h-full text-2xl"
label="시도"
selectClass={""}
selectArray={code.cityCd || []}
onSelectValue={getSelCity}
>
{""}
</SelectBox>
<SelectBox
className="w-80 h-full text-2xl ml-4"
label="시군구"
selectClass={""}
selectArray={selectSgg || []}
onSelectValue={getSgg}
>
{""}
</SelectBox>
<div className="col-span-4 w-full">
<div className="flex flex-row items-center">
<Label className="text-xl text-gray-600 ml-4 mr-4">
수요신청년도
</Label>
<div className="flex flex-row mt-2">
<SelectBox
className="h-full w-32 text-2xl"
label=""
selectClass={""}
selectArray={yearOptions}
value={fromDate}
onSelectValue={(val: string | number) =>
setFromDate(String(val))
}
/>
<span className="mx-6">~</span>
<SelectBox
className="h-full w-32 text-2xl"
label=""
selectClass={""}
selectArray={yearOptions}
value={toDate}
onSelectValue={(val: string | number) =>
setToDate(String(val))
}
/>
<SearchInput
className={"text-2xl w-60 ml-4 "}
label="시설명"
textValue={ruseUtztnFcltNm}
setText={setRuseUtztnFcltNm}
/>
<SearchInput
className={"text-2xl w-60 ml-4 "}
label="회사명"
textValue={dmdCoNm}
setText={setDmdCoNm}
/>
</div>
</div>
</div>
</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={(e) => {
if (fromDate && toDate) {
const fromNum = Number(fromDate);
const toNum = Number(toDate);
if (fromNum > toNum) {
toast.error(
"시작년도가 종료년도 이후로 설정할 수 없습니다."
);
} else {
let con: string | number = "";
if (String(objSearch.city).length > 0) {
con = String(objSearch.city);
}
if (String(objSearch.sgg).length > 0 && objSearch.sgg !== "0") {
con = String(objSearch.sgg);
}
getSearch(
fromNum,
toNum,
con,
dmdCoNm,
ruseUtztnFcltNm
);
}
}
}}
>
조회
</Button>
<Button size={"sm"} onClick={confrirmToast}>
검토완료
</Button>
</div>
</div>
</SearchFormRight>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={"재이용검토현황"}
tableData={rvwHistData || []}
headlist={ruseHistHeadList}
pageSize={20}
total={100000}
cellClick={(index: number | undefined, headId: string) => {
TableCellClick(index);
}}
onPageChange={setPageNatiion}
></UiTable>
<hr />
<h3 className="mt-4 ml-2 text-2xl font-medium text-label">
수요신청 상세현황
</h3>
<ConCostForm form={form} type={"hist"} />
</ListDiv>
</div>
</div>
<Toaster position="top-center" />
</ContentsDiv>
);
}
+263
View File
@@ -0,0 +1,263 @@
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import { fetchType, getFetch } from "@/components/lib/api";
import {
excelDownload,
getCity,
tableData
} from "@/components/lib/func/commom";
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import { ToastFormUi } from "@/components/ui/toast/toastFromUi";
import {
ContentsDiv,
SearchDiv,
SearchFormLeft,
SearchFormRight,
SearchInput,
SelectBox,
Title,
UiModal,
UiTable,
type SelectDataType,
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import SdmInsertForm from "@common/business_components/ui/sdmInsertForm";
import type { DemandCompType } from "@common/business_components/ui/sdmInsertForm/form";
import { Button } from "@common/components/ui";
import { useCallback, useEffect, useState } from "react";
import toast, { Toaster } from "react-hot-toast";
export default function CoSttn() {
const {
code,
coSttn,
coSttnInit,
coSttnSearch,
getDemandCompList,
regDemandCompany,
updateDemandCompany,
coSttnTxtSearch,
demandCompList,
dmdIsSucees
} = useWrStore((state) => state);
const [bdstTable, setBdstTable] = useState<DemandCompType[]>();
const [pageNation, setPageNation] = useState(1);
const { coSttnRes, coSttnResCount } = coSttn;
const [isDmdModal, setIsDmdModal] = useState<{
isMoal: boolean;
data: DemandCompType;
}>({ isMoal: false, data: {} as DemandCompType });
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>();
const [objSearch, setObjSearch] = useState<objSearchType>({
sgg: "",
city: "",
});
const [seartchTxt, setSearchTxt] = useState<string>();
const [upadateData, setUpdateData] = useState<DemandCompType>();
const getSelCity = (val: string | number) => {
const cityValue = String(val); // Ensure val is treated as a string
const data = getCity(cityValue, code.sggCd);
setSelectSgg(data);
setObjSearch({ city: cityValue, sgg: "" });
};
const getSgg = (val: string | number) => {
setObjSearch({ ...objSearch, sgg: String(val) });
};
useEffect(() => {
if (!coSttn.isInit) {
coSttnInit("1", "13", "0");
}
}, [coSttn.isInit, coSttnInit]);
useEffect(() => {
if (coSttnRes?.length > 0 && code.cityCd.length > 0) {
const data = tableData(coSttnRes, { code });
const chData = data.map((item: any) => ({
...item,
}));
// .filter((item: any) => item !== undefined);
setBdstTable(chData);
} else if (coSttnRes.length == 0) {
setBdstTable([]);
}
}, [coSttnRes, code]);
useEffect(() => {
if (coSttn.excelList.length > 0) {
if (coSttn.excelList.length === 0) return;
excelDownload(
coSttn.excelList,
"수요처 관리",
"sample_coSttn.xlsx",
"A1:F1",
2
);
}
}, [coSttn.excelList]);
useEffect(() => {
const con = (objSearch.sgg && objSearch.sgg !== "0") ? objSearch.sgg : objSearch.city ? objSearch.city : "0";
if(con){
coSttnSearch(String(pageNation), "13", String(con));
}
}, [coSttnSearch, objSearch.city, objSearch.sgg, pageNation]);
const excelClick = useCallback(() => {
const con = objSearch.sgg ? objSearch.sgg : objSearch.city;
if (con) coSttnSearch("1", "10000", String(con));
}, [coSttnSearch, objSearch.city, objSearch.sgg]);
const searchClick = () => {
const con = (objSearch.sgg && objSearch.sgg !== "0") ? objSearch.sgg : objSearch.city;
if (con) {
if (seartchTxt && seartchTxt?.length > 0) {
coSttnTxtSearch("1", "13", String(con), seartchTxt ?? "");
} else {
coSttnSearch("1", "13", String(con));
}
}
};
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4 ">
<div className="col-span-4">
<Title title={"수요처 관리"} />
<SearchDiv>
<SearchFormLeft>
<div className="col-span-10 flex flex-row">
<SelectBox
className="col-span-2 w-1/6 h-full text-2xl"
label="시도"
selectClass={""}
selectArray={code.cityCd || []}
onSelectValue={getSelCity}
/>
<SelectBox
className="col-span-2 w-1/6 h-full text-2xl"
label="시군구"
selectClass={""}
selectArray={selectSgg?selectSgg : [{text:"전체",val:"0"}]}
onSelectValue={getSgg}
/>
<SearchInput
className={"!text-3xl"}
label="회사명"
textValue={seartchTxt ?? ""}
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="flex flex-row space-x-2">
<Button size={"sm"} onClick={searchClick}>
조회
</Button>
<Button
size={"sm"}
className={btnClass}
onClick={() => {
setUpdateData(undefined);
setIsDmdModal({ ...isDmdModal, isMoal: true });
}}
>
등록
</Button>
<Button
size={"sm"}
className={btnClass}
onClick={() => {
/* 저장 로직 */
if (!upadateData) {
<ToastFormUi body={"수요처 변경을 원하는 행을 선택해주세요"} title={"수요처관리"}></ToastFormUi>;
}else{
setIsDmdModal({
...isDmdModal,
isMoal: true})
}
}}
>
저장
</Button>
<Button
size={"sm"}
className={`${btnClass} green`}
onClick={excelClick}
>
다운로드
</Button>
</div>
</SearchFormRight>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={[]}
tableData={bdstTable || []}
headlist={coSttn.coSttHeadList}
pageSize={bdstTable?.length ? Math.ceil(bdstTable.length / 13) : 0}
total={ coSttnResCount || 0 }
cellClick={(index: number | undefined, headId: string) => {
setUpdateData(coSttnRes[index as number]);
}}
onPageChange={setPageNation}
></UiTable>
</ListDiv>
</div>
</div>
<UiModal
bodyClass={"w-[40vw] max-w-none h-[90vh]"}
open={isDmdModal.isMoal}
onOpenChange={() => {
setIsDmdModal({ isMoal: false, data: {} as DemandCompType });
}}
body={
<SdmInsertForm
selectSidoData={code.cityCd}
selectSigunData={code.sggCd}
dataList={demandCompList}
rtnValue={(searchText: string, pageCnt: number) => {
getDemandCompList(searchText, pageCnt);
}}
rtnInputData={ async(data) => {
if(upadateData?.dmdInfoPk){
updateDemandCompany(data as DemandCompType)
}else{
const dmd= await getFetch(fetchType.WR,`/reuseFc/request/${data.dmdInfoPk}`)
if(dmd) {
toast.error(`사업자번호 ${dmd.dmdInfoPk}는 이미 등록되었습니다. 다시등록해주세요`)
return
}
regDemandCompany(data as DemandCompType);
}
if(dmdIsSucees ==='success'){
toast.success(`수요처 등록 및 수정 완료되었습니다..`)
setIsDmdModal({ isMoal: false, data: data as DemandCompType });
}else{
toast.error(`수요처 등록 및 수정 에러입니다.`)
}
}}
bodyClassNm={"w-full mx-auto bg-white rounded-lg shadow-md p-6"}
updateList={upadateData}
></SdmInsertForm>
}
></UiModal>
</ContentsDiv>
<Toaster position="top-center" />
</>
);
}
+132
View File
@@ -0,0 +1,132 @@
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import type { customCoSttnBdst } from "@/app/store/matDmd/coSttn";
import { drgtHeadListExport } from "@/app/store/matDmd/drgtSttn/headList";
import { excelDownload, getCity } from "@/components/lib/func/commom";
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import { ContentsDiv, SearchDiv, SearchFormLeft, SearchFormRight, SelectBox, Title, UiTable, type SelectDataType } from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button, DatePicker, Label } from "@common/components/ui";
import { useCallback, useState } from "react";
export default function DrgtSttn() {
const { code, } = useWrStore((state) => state);
const [fromDate, setFromDate] = useState<Date>(new Date());
const [toDate, setToDate] = useState<Date>(new Date());
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>();
const [objSearch, setObjSearch] = useState<objSearchType>({ sgg: "", city: "" });
const getSelCity = (val: string | number) => {
const cityValue = String(val); // Ensure val is treated as a string
const data = getCity(cityValue, code.sggCd);
setSelectSgg(data);
setObjSearch({ city: cityValue, sgg: '' });
};
const getSgg = (val: string | number) => {
console.log(val);
setObjSearch({ ...objSearch, sgg: String(val) })
};
const excelClick = useCallback(() => {
excelDownload(
[[]],
"우리동네가뭄",
"sample_drgtSttn.xlsx",
"A1:H1"
);
}, []);
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4 ">
<div className="col-span-4">
<Title title={"우리동네가뭄"} />
<SearchDiv>
<SearchFormLeft>
<div className="col-span-10 flex flex-row">
<SelectBox
className="col-span-2 w-1/6 h-full text-2xl"
label="시도"
selectClass={""}
selectArray={code.cityCd || []}
onSelectValue={getSelCity}
/>
<SelectBox
className="col-span-2 w-1/6 h-full text-2xl"
label="시군구"
selectClass={""}
selectArray={selectSgg || []}
onSelectValue={getSgg}
/>
<div className="col-span-5 w-auto">
<div className="flex flex-row items-center">
<Label className="text-xl text-gray-600">조회기간</Label>
<div className="flex flex-row w-1/4">
<DatePicker mode={'single'}
selected={fromDate}
onSelect={(date: Date | undefined) => { if (date) setFromDate(date) }} />
<span>~</span>
<DatePicker mode={'single'}
selected={toDate}
onSelect={(date: Date | undefined) => { if (date) setToDate(date) }} />
</div>
</div>
</div>
</div>
</SearchFormLeft>
<SearchFormRight
className="w-2/12 mx-5 flex flex-col items-center justify-center space-x-2 ">
<div className="flex flex-row space-x-2">
<Button
size={"sm"}
onClick={(e) => { }}
>
조회
</Button>
<Button
size={"sm"}
className={btnClass}
onClick={() => { }}
>
상세보기
</Button>
<Button
size={"sm"}
className={`${btnClass} green`}
onClick={excelClick}
>
다운로드
</Button>
<Button
size={"sm"}
className={btnClass}
onClick={() => { }}
>
지도보기
</Button>
</div>
</SearchFormRight>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={[]}
tableData={[]}
headlist={drgtHeadListExport}
pageSize={20}
total={10000}
cellClick={(index: number | undefined, headId: string) => { }}
onPageChange={() => { }}
></UiTable>
</ListDiv>
</div>
</div>
</ContentsDiv>
</>
)
}
@@ -0,0 +1,293 @@
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import { type customLdrmnt } from "@/app/store/matDmd/ldrmntCoSttn";
import { ldrmntHeadListExport, ldrmntNodeListExport } from "@/app/store/matDmd/ldrmntCoSttn/headList";
import {
excelDownload,
getCity,
getCityOrSgg,
tableData
} from "@/components/lib/func/commom";
import CoRegExcel from "@/components/ui/modal/coReg/coRegExcel/coRegExcelModal";
import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import CoDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/coDatailModal";
import {
ContentsDiv,
downloadExcel,
SearchDiv,
SearchFormLeft,
SearchFormRight,
SearchInput,
SelectBox,
Title,
UiModal,
UiTable,
type ReturnType,
type SelectDataType
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components/ui";
import { useCallback, useEffect, useRef, useState } from "react";
export default function LdrmntCoSttn() {
const { code, ldrmnt, ldrmntInit, ldrmntSearch, } = useWrStore(
(state) => state
);
const { ldrmntRes, excelList } = ldrmnt;
const [detailModal, setDetailModal] = useState<{ isOpen: boolean, data: customLdrmnt | undefined }>({ data: undefined, isOpen: false })
const [pageNation, setPageNation] = useState(1);
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>()
const [objSearch, setObjSearch] = useState<objSearchType>({ sgg: "", city: "" });
const [bdstTable, setBdstTable] = useState<customLdrmnt[]>();
const [searchTxt, setSearchTxt] = useState<string>();
const ref = useRef<ReturnType>({} as ReturnType);
const [excelData, setExcelData] = useState<any[]>();
const excelClick = useCallback(() => {
excelDownload(
[[]],
"잠재수요처 관리",
"sample_ldrmntCoSttn.xlsx",
"A1:AL1",
2
);
}, []);
const excelDownloadClick = () => {
downloadExcel({
data: excelData ?? [],
fileName: "잠재수요처 관리",
sheetNameArray: ["Sheet1"],
headerRange: "A1:F1"
})
}
const [isExcelOpen, setIsExcelOpen] = useState<{
isModal: boolean;
}>({ isModal: false });
const cellClick = (index: number | undefined, headId: string) => {
if (index !== undefined) {
setDetailModal({ isOpen: true, data: ldrmntRes[index] });
}
}
const getSelCity = (val: string | number) => {
const cityValue = String(val); // Ensure val is treated as a string
const data = getCity(cityValue, code.sggCd);
setSelectSgg(data);
setObjSearch({ city: cityValue, sgg: '' });
};
const getSgg = (val: string | number) => {
setObjSearch({ ...objSearch, sgg: String(val) })
};
useEffect(() => {
if (!ldrmnt.isInit) {
ldrmntInit("0");
}
}, [ldrmnt.isInit, ldrmntInit]);
useEffect(() => {
const transData = Array.isArray(ldrmntRes) ? ldrmntRes : [ldrmntRes];
const data = tableData(transData, { code });
const tbData = Array.isArray(data)
? data.map((item: customLdrmnt) => ({
...item,
ctpvCd: item.fctryAddr.split(" ")[0] || "",
sggCd: item.fctryAddr.split(" ")[1] || ""
}))
: [];
setBdstTable(tbData);
}, [ldrmntRes, code]);
useEffect(() => {
const transData = Array.isArray(excelList) ? excelList : [excelList];
const exData = tableData(transData, { code });
const data = Array.isArray(exData)
? exData.map((item: customLdrmnt) => {
return {
"시도": item.fctryAddr.split(" ")[0] || "",
"시군구": item.fctryAddr.split(" ")[1] || "",
"회사명": item.dmdCoNm,
"공장주소": item.fctryAddr,
"공장관리번호": item.fctryMngNo,
"전화번호": item.telno
}
}) : [];
setExcelData(data)
}, [excelList])
useEffect(() => {
let cityTxt = '';
let sggTxt = '';
if (objSearch?.city.toString().length > 0) {
cityTxt = code.cityCd.find((item) => item.val === objSearch?.city)?.text ?? '';
}
if (objSearch?.sgg.toString().length > 1) {
sggTxt = code.sggCd.find((item) => item.val === objSearch?.sgg)?.text ?? '';
}
let cityNm = "";
if (sggTxt !== "0") {
cityNm = cityTxt + " " + sggTxt;
} else {
cityNm = cityTxt;
}
if (cityNm) {
if (cityTxt === '') cityNm = "0";
ldrmntSearch(pageNation, cityNm, searchTxt || "");
} else {
ldrmntSearch(pageNation, "", searchTxt || "");
}
}, [pageNation, objSearch, code, searchTxt, ldrmntSearch])
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4 ">
<div className="col-span-4">
<Title title={"잠재수요처 관리"} />
<SearchDiv>
<SearchFormLeft>
<div className="col-span-10 flex flex-row">
<SelectBox
className="col-span-2 w-1/6 h-full text-2xl"
label="시도"
selectClass={""}
selectArray={code.cityCd}
onSelectValue={getSelCity}
/>
<SelectBox
className="col-span-2 w-1/6 h-full text-2xl ml-4"
label="시군구"
selectClass={""}
selectArray={selectSgg || []}
onSelectValue={getSgg}
/>
<SearchInput
className={"text-2xl ml-4"}
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="flex flex-row space-x-2">
<Button
size={"sm"}
onClick={(e) => {
let cityTxt = ''
let sggTxt = ''
if (objSearch?.city.toString().length > 0) {
cityTxt = code.cityCd.find((item) => item.val === objSearch?.city)?.text ?? '';
}
if (objSearch?.sgg.toString().length > 1) {
sggTxt = code.sggCd.find((item) => item.val === objSearch?.sgg)?.text ?? '';
}
let cityNm = ""
if (sggTxt !== "0") {
cityNm = cityTxt + " " + sggTxt
} else {
cityNm = cityTxt
}
if (cityNm) {
if (cityTxt === '') cityNm = "0";
ldrmntSearch(pageNation, cityNm, searchTxt || "");
}
}}
>
조회
</Button>
<Button
size={"sm"}
className={btnClass}
onClick={() => {
setIsExcelOpen({ isModal: true });
}}
>
엑셀등록
</Button>
<Button
size={"sm"}
className={btnClass}
onClick={() => excelDownloadClick()}
>
다운로드
</Button>
<Button
size={"sm"}
className={`${btnClass} green`}
onClick={excelClick}
>
양식받기
</Button>
</div>
</SearchFormRight>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<div className="overflow-x-auto">
<ListDiv className="min-w-max">
<UiTable
headName={[]}
tableData={bdstTable || []}
headlist={ldrmntHeadListExport}
pageSize={20}
total={10000}
cellClick={(index: number | undefined, headId: string) => { cellClick(index ?? undefined, headId) }}
onPageChange={setPageNation}
/>
</ListDiv>
</div>
</div>
<UiModal
open={detailModal.isOpen}
onOpenChange={() => {
setDetailModal({ ...detailModal, isOpen: !detailModal.isOpen })
}}
bodyClass={"w-[40vw] max-w-none max-h-[calc(100%-70px)]"}
body={<CoDetailModal formObj={detailModal.data} />}
/>
<UiModal
open={isExcelOpen.isModal}
onOpenChange={() => {
setIsExcelOpen({ isModal: !isExcelOpen.isModal })
}}
bodyClass={"w-[40vw] max-w-none"}
body={<CoRegExcel />}
/>
</div>
</ContentsDiv>
</>
)
}
-84
View File
@@ -1,84 +0,0 @@
"use client";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import {
Form,
FormField,
FormUi,
ScrollArea,
SelectBox,
} from "@common/business_components/ui";
import { Button } from "@common/components/ui";
import { CoRegForm } from "@/components/ui/matDmd/coRegForm/component";
import toast, { Toaster } from "react-hot-toast";
import { ToastFormUi } from "@/components/toastFromUi";
const formSchema = z.object({
ctpv: z.string(),
sgg: z.string(),
coNm: z.string().min(1).max(20),
bznmNo: z.string().min(1).min(9).max(12),
addr: z.string().min(1).min(6).max(20),
telNo: z.string().min(8).max(12),
});
export default function MyForm() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
coNm:'',
bznmNo:'',
addr:'',
telNo:'',
},
});
function onSubmit(values: z.infer<typeof formSchema>) {
try {
toast.dismiss();
ToastFormUi("수요신청 화면으로 이동하시겠습니까?", "수요처 등록 완료", "./dmdReg", "이동")
} catch (error) {
console.error("Form submission error", error);
toast.error("수요처 등록이 실패하였습니다.");
}
}
return (
<>
<div className="grid h-40 grid-cols-3 place-content-center">
<h1 className=" col-start-2 col-span-1 text-4xl underline">
수요처 정보입력
</h1>
</div>
<div className="grid grid-cols-5 gap-4 overflow-hidden">
<div className="col-span-1 "/>
<div className="col-span-3 ">
<div>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8 max-w-3xl mx-auto"
>
<CoRegForm>{form}</CoRegForm>
<Button type="submit">수요처등록</Button>
</form>
</Form>
</div>
</div>
<div className="col-span-1 " >
<Toaster position="top-center" />
</div>
</div>
</>
);
}
-106
View File
@@ -1,106 +0,0 @@
"use client";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import { Form } from "@common/business_components/ui";
import { Button } from "@common/components/ui";
import { DmdRegForm } from "@/components/ui/matDmd/dmdRegform/component";
import toast, { Toaster } from "react-hot-toast";
import { useRouter } from "next/navigation";
const formSchema = z.object({
dmdSel: z.string().min(1),
dmdTmng: z.coerce.date(),
dmdWq: z.string().min(1).optional(),
useUsgCd: z.string(),
wntUntprc: z.string().min(1),
grssClfg: z.string().min(1),
tn: z.string().min(1).optional(),
combResdch: z.string().min(1).optional(),
tp: z.string().min(1).optional(),
trbt: z.string().min(1).optional(),
ph: z.string().min(1).optional(),
bod: z.string().min(1).optional(),
clIonQnt: z.string().min(1).optional(),
smll: z.string().min(1).optional(),
cdtnv: z.string().min(1).optional(),
crmty: z.string().min(1).optional(),
rmrk: z.string().min(1).optional(),
sply1: z.string().min(1).optional(),
sply2: z.string().min(1).optional(),
sply3: z.string().min(1).optional(),
password: z.string().min(1),
});
export default function MyForm() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
dmdSel:'',
dmdTmng: new Date(),
dmdWq: "",
useUsgCd: "",
wntUntprc: "",
grssClfg: "",
tn: "",
combResdch: "",
tp: "",
trbt: "",
ph: "",
bod: "",
clIonQnt: "",
smll: "",
cdtnv: "",
crmty: "",
rmrk: "",
sply1: "",
sply2: "",
sply3: "",
password: "",
},
});
const router = useRouter();
async function onSubmit(values: z.infer<typeof formSchema>) {
try {
toast.success("✅ 수요신청이 완료되었습니다.");
await new Promise((resolve) => setTimeout(resolve, 3000));
router.push("../../")
} catch (error) {
toast.error("수요신청을 다시입력해주시길 바랍니다.");
}
}
return (
<>
<div className="grid h-40 grid-cols-3 place-content-center">
<h1 className=" col-start-2 col-span-1 text-4xl underline">
수요 신청정보입력
</h1>
</div>
<div className="grid grid-cols-5 gap-4 overflow-hidden">
<div className="col-span-1 " />
<div className="col-span-3 max-h-[78vh] overflow-y-scroll ">
<div>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8 max-w-3xl mx-auto"
>
<DmdRegForm> {form}</DmdRegForm>
<Button type="submit"> 수요신청</Button>
</form>
</Form>
</div>
</div>
<div className="col-span-1 ">
<Toaster position="top-center" />
</div>
</div>
</>
);
}
+151 -18
View File
@@ -1,26 +1,159 @@
import Link from 'next/link';
import { Button } from '@common/components/ui';
"use client";
import { Button } from "@common/components/ui";
import { useRouter } from "next/navigation";
export default function Home() {
const router = useRouter();
return (
<>
<div className='flex'>
<Button className='place-self-auto'>
<Link href="reuseFaciltyManage/reuseFacilityInsert/publicReuseFaciltyInsert"> 하수재이용 시설 등록</Link>
</Button>
<Button className='place-self-auto'>
<Link href="reuseFaciltyManage/reuseFacilityInsert/rainReuseFaciltyInsert"> 빗물재이용 시설 등록</Link>
</Button>
<Button className='place-self-auto'>
<Link href="reuseFaciltyManage/reuseFacilityInsert/rswtReuseFacilityInsert"> 중수도시설 등록</Link>
</Button>
<div className="flex flex-col gap-8 p-6">
{/* 시설 등록 */}
<div>
<h2 className="text-xl font-semibold mb-4">시설 등록</h2>
<div className="grid grid-cols-12 gap-4">
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/ruseFcltMng/fcltReg/pbnstReg')}}>
하수재이용 시설 등록
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/ruseFcltMng/fcltReg/rainReg')}}>
빗물재이용 시설 등록
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/ruseFcltMng/fcltReg/rswtReg')}}>
중수도시설 등록
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/ruseFcltMng/fcltReg/htdflReg')}}>
온배수시설 등록
</Button>
</div>
</div>
</div>
<Button className='place-self-auto'>
<Link href="matMng/matDmd/coReg">수요처 등록</Link>
</Button>
{/* 지도점검 결과 */}
<div>
<h2 className="text-xl font-semibold mb-4">지도점검 결과</h2>
<div className="grid grid-cols-12 gap-4">
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/ruseFcltMng/prfmncReg/pbnstPrfmncReg')}}>
하수재이용실적 등록
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/ruseFcltMng/prfmncSttn/pbnstPrfmncSttn')}}>
하수재이용실적 현황
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/ruseFcltMng/prfmncReg/chkgdnReg')}}>
지도점검 결과 등록
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/ruseFcltMng/prfmncSttn/chkgdnSttn')}}>
지도점검 결과 현황
</Button>
</div>
</div>
</div>
{/* 시설 현황 */}
<div>
<h2 className="text-xl font-semibold mb-4">시설 현황</h2>
<div className="grid grid-cols-12 gap-4">
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/ruseFcltMng/fcltSttn/pbnstSttn')}}>
하수재이용시설현황
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/ruseFcltMng/fcltSttn/rainSttn')}}>
빗물재이용시설현황
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/ruseFcltMng/fcltSttn/rswtSttn')}}>
중수도이용시설현황
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/ruseFcltMng/fcltSttn/htdflSttn')}}>
온배수현황
</Button>
</div>
</div>
</div>
{/* 수요처 관리 */}
<div>
<h2 className="text-xl font-semibold mb-4">수요처 관리</h2>
<div className="grid grid-cols-12 gap-4">
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/matMng/coMng/coSttn')}}>
수요처 관리
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/matMng/coMng/ldrmntCoSttn')}}>
잠재수요처 관리
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/matMng/coMng/drgtSttn')}}>
우리동네가뭄
</Button>
</div>
</div>
</div>
{/* 수요처 매칭 */}
<div>
<h2 className="text-xl font-semibold mb-4">수요처 매칭</h2>
<div className="grid grid-cols-12 gap-4">
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/matMng/coMat/coMatRvw')}}>
수요처 매칭 검토
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/matMng/coMat/ruseRvwHstry')}}>
재이용검토이력
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/matMng/coMat/ruseCaseMng')}}>
물재이용사례 관리
</Button>
</div>
</div>
</div>
{/* 통계*/}
<div>
<h2 className="text-xl font-semibold mb-4">통계 매칭</h2>
<div className="grid grid-cols-12 gap-4">
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/stats/rainStat')}}>
빗물재이용시설통계
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/stats/rswtStat')}}>
중수도시설통계
</Button>
</div>
<div className="col-span-2">
<Button className="w-full" onClick={() => {router.push('/stats/matStat')}}>
물재이용사례 관리
</Button>
</div>
</div>
</div>
</div>
</>
</>
);
}
@@ -1,52 +0,0 @@
'use client'
import { ScrollArea, SearchDiv, SelectBox, UiTable } from '@common/business_components';
import { Button } from '@common/components';
import { PublicReuseFaciltyFormInsert } from '../../../../components/ui/publicReuseInsertForm';
import { useWrStore } from '../../../store';
export default function PublicReuseFaciltyInsert() {
const {pubFac} = useWrStore((state) => state);
const { pubFacHeadList, publicReuseFacilityData} = pubFac;
const searchDiv = '하수재이용시설 '
const selectBox = [{ text: '서울하수처리시설', val: "1_hasu" }, { text: '서울1하수처리시설', val: "2_hasu" }, { text: '서울2하수처리시설', val: "3_hasu" }]
const headName = () => {
return (
<h1 className="pl-3 text-xl">○공공 하수처리시설 등록</h1>
)
}
const onSelectValue = (val: string) => {
console.log(val)
}
return (
<>
<div className="grid grid-cols-2 gap-4 h-full">
<div className='col-span-4'>
<h1 className="pl-3 text-xl" > 하수재이용시설 등록</h1>
<div className="m-8">
<SearchDiv>
<div className='w-4/5 grid grid-cols-12 gap-1 mx-4'>
<SelectBox className='col-span-4' label={searchDiv} selectArray={selectBox} onSelectValue={onSelectValue} />
</div>
<div className='w-1/5 flex items-center justify-end'>
<Button className='mr-4 rounded-lg'>조회</Button>
<Button className='mr-4 rounded-lg'>신규추가</Button>
</div>
</SearchDiv>
</div>
</div>
<div className="col-span-1 pl-11">
<UiTable tableData={publicReuseFacilityData} headlist={pubFacHeadList} pageSize={100} total={10} headName={headName()} children={undefined}/>
</div>
<div className="col-span-1 pr-6 max-h-full overflow-y-scroll">
<ScrollArea>
<PublicReuseFaciltyFormInsert />
{/* <ScrollBar orientation="vertical"></ScrollBar> */}
</ScrollArea>
</div>
</div>
</>
)
}
@@ -1,67 +0,0 @@
'use client'
import { useWrStore } from "@/app/store";
import type { TableUpperProps } from "@/app/store/rainReuseFacilityInsert"
import { RainReuseFaciltyInsertForm } from "@/components/ui/rainReuseInsertForm";
import { ScrollArea, SearchDiv, SearchInput, UiTable } from "@common/business_components";
import { Button, TableHead, TableRow } from "@common/components";
export const headMakeColSpan = (upHeadList: TableUpperProps[]) => {
return (<>
<TableRow>{
upHeadList.map((head: TableUpperProps) =>
(!head.upSequnce ? <TableHead rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead key={head.id} rowSpan={1} colSpan={3}>{'중축 개축 증축 '}</TableHead> : null))}
</TableRow>
<TableRow>
{upHeadList.map((head: TableUpperProps) =>
(head.upName === 'upChangeRe' ? <TableHead key={head.id}>{head.title}</TableHead> : null))}
</TableRow>
</>)
}
export default function Home() {
const { rain } = useWrStore((state) => state);
const nodeList = headMakeColSpan(rain.upHeadList);
const headName = () => {
return (
<h1 className="pl-3 text-xl">○건축물 목록</h1>
)
}
return (
<>
<div className="grid grid-cols-2 gap-4 ">
<div className='col-span-2'>
<h1 className="pl-3 text-2xl" >빗물이용시설 등록 </h1>
<div className="m-8">
<SearchDiv >
<div className='w-4/5 grid grid-cols-12 gap-1 mx-4'>
<SearchInput className='col-span-3 my-7' label="건물명" />
</div>
<div className='w-1/5 flex items-center justify-end'>
<Button className='mr-4 rounded-lg'>조회</Button>
<Button className='mr-4 rounded-lg'>저장</Button>
<Button className='mr-4 rounded-lg'>신규등록</Button>
</div>
</SearchDiv>
</div>
</div>
<div className="colsapn-1 pl-11">
<UiTable tableData={rain.rainOfObject} headlist={rain.upHeadList} pageSize={100} total={10} headName={headName()}>
{nodeList}
</UiTable>
</div>
<div className="colsapn-1 pr-11 max-h-full ovreflow-y-scroll">
<ScrollArea>
<RainReuseFaciltyInsertForm></RainReuseFaciltyInsertForm>
</ScrollArea>
</div>
</div>
</>
);
}
@@ -1,69 +0,0 @@
'use client'
import { useWrStore } from "@/app/store";
import type { TableUpperProps } from "@/app/store/rainReuseFacilityInsert";
import { RswtrReuseFaciltyInsertForm } from "@/components/ui/rswtrReuseInsetForm";
import { ScrollArea, SearchDiv, SearchInput, UiTable } from "@common/business_components";
import { Button, TableHead, TableRow } from "@common/components";
const headMakeColSpan = (upHeadList: TableUpperProps[]) => {
return (<>
<TableRow>{
upHeadList.map((head: TableUpperProps) =>
(!head.upSequnce ? <TableHead rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead key={head.id} rowSpan={1} colSpan={3}>{'중축 개축 증축 '}</TableHead> : null))}
</TableRow>
<TableRow>
{upHeadList.map((head: TableUpperProps) =>
(head.upName === 'upChangeRe' ? <TableHead key={head.id}>{head.title}</TableHead> : null))}
</TableRow>
</>)
}
export default function Home() {
const {rswt} = useWrStore((state) => state);
const nodeList = headMakeColSpan(rswt.upHeadList);
const total = 100;
const headName = () => {
return (
<h1 className="pl-3 text-xl">○건축물 목록</h1>
)
}
return (
<>
<div className="grid grid-cols-2 gap-4 ">
<div className='col-span-2'>
<h1 className="pl-3 text-2xl" >중수도시설 등록 </h1>
<div className="m-8">
<SearchDiv >
<div className='w-4/5 grid grid-cols-6 gap-1 mx-4'>
<SearchInput className='col-span-1 my-7 text-2xl' label="건물명:" />
</div>
<div className='w-1/5 flex items-center justify-end'>
<Button className='mr-4 rounded-lg'>조회</Button>
<Button className='mr-4 rounded-lg'>저장</Button>
<Button className='mr-4 rounded-lg'>신규등록</Button>
</div>
</SearchDiv>
</div>
</div>
<div className="colsapn-1 pl-11">
<UiTable tableData={rswt.rswtOfObject} headlist={rswt.upHeadList} pageSize={100} total={10} headName={headName()}>
{nodeList}
</UiTable>
</div>
<div className="colsapn-1 pr-11 max-h-full ovreflow-y-scroll">
<ScrollArea>
<RswtrReuseFaciltyInsertForm></RswtrReuseFaciltyInsertForm>
</ScrollArea>
</div>
</div>
</>
);
}
@@ -0,0 +1,167 @@
"use client";
import { useWrStore } from "@/app/store";
import {
ContentsDiv,
ScrollArea,
SearchDiv,
SearchFormLeft,
SearchFormRight,
SearchInput,
Title,
UiModal,
UiTable,
} from "@common/business_components";
import { Button } from "@common/components";
import ListDiv from "@common/business_components/ui/list_div";
import { useEffect, useState } from "react";
import { tableData } from "@/components/lib/func/commom";
import HtdflRegForm from "@/components/ui/form/fcltReg/htdflReg/htdflRegForm";
import type { chgBuilding } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import BdstChgModal from "@/components/ui/modal/fcltReg/bdstChgModal/bdstChgModal";
import type { customHtdflBdst } from "@/app/store/ruseFcltMng/fcltReg/htdflReg";
import { BdstReg } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
export default function Home() {
const { code, htdfl, initHtdfl,getHtdflBdstData } = useWrStore((state) => state);
const [searchTxt, setSearchTxt] = useState("");
const [pageNation, setPageNation] = useState(1);
const [htdflForm, setHtdflForm] = useState<customHtdflBdst>();
const [bdstTable, setbdstTable] = useState<customHtdflBdst[]>();
const [issNewReg,setIsNewReg] = useState<boolean>( false);
const [bdstChgProps, setBdstChgProps] = useState<{
isOpen: boolean;
chgBuilding: chgBuilding[];
}>({ isOpen: false, chgBuilding: [] });
const { htdflRes } = htdfl;
useEffect(() => {
if (!htdfl.isInit) {
initHtdfl('0');
}
}, [htdfl.isInit, initHtdfl]);
useEffect(() => {
if (code.sggCd.length > 0) {
const htdflData = tableData(htdflRes, { code }).map(
(item: customHtdflBdst) => {
return {
...item,
bdstChgYn: item?.chgBuilding && item.chgBuilding.length > 0 && item.chgBuilding[0]?.bdstChgNm !== null ? 'Y' : 'N',
bdstUsgCd: item.reuseBuilding[0]?.bdstUsgCd
};
}
);
setbdstTable(htdflData);
}
}, [code, htdflRes]);
const cellClick: (val: number|undefined ,headId: string) => void = (
val
,headId) => {
if ((bdstTable ?? []).length > 0 && val !== undefined) {
{
setHtdflForm(htdflRes[val]);
}
}
if (headId === "bdstChgYn" && val !== undefined) {
if (
htdflRes[val]?.bdstInfoPk != null &&
htdflRes[val]?.chgBuilding?.length > 0
) {
bdstChgModal(htdflRes[val]?.chgBuilding as chgBuilding[]);
}
}
};
const bdstChgModal = (chgBuilding: chgBuilding[]) => {
setBdstChgProps({ isOpen: true, chgBuilding: chgBuilding });
};
useEffect(() => {
getHtdflBdstData(pageNation, "0");
}, [pageNation]);
return (
<>
<ContentsDiv>
<div className="grid grid-cols-2 gap-4 ">
<div className="col-span-2">
<Title title={"온배수시설 등록"} />
<SearchDiv>
<SearchFormLeft>
<SearchInput
className="col-span-3 my-7 !text-3xl"
label="건물명"
textValue={searchTxt || ""}
setText={(e) => {
setSearchTxt(e);
}}
/>
</SearchFormLeft>
<SearchFormRight>
<div className="flex flex-row space-x-2 items-center">
<Button size={"sm"} onClick={()=>{initHtdfl(searchTxt||"")}}>조회</Button>
<Button
size={"sm"}
onClick={() => setIsNewReg(!issNewReg)}
>
신규등록
</Button>
</div>
</SearchFormRight>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-4 h-full min-h-0">
<ListDiv className="min-h-0">
<UiTable
tableData={bdstTable || []}
headlist={htdfl.upHeadList}
pageSize={100}
total={10}
headName={"건축물 목록"}
cellClick={(val, headId) => { cellClick(val || undefined, headId); } }
onPageChange={setPageNation}
>
</UiTable>
</ListDiv>
</div>
<div className="col-span-2 max-h-full">
<ListDiv>
<ScrollArea className="h-[60vh]">
<HtdflRegForm
htdflForm={htdflForm ?? ({} as customHtdflBdst)}
isModal={false}
/>
</ScrollArea>
</ListDiv>
</div>
</div>
<UiModal
body={<BdstReg moType="HTB"></BdstReg>}
bodyClass="w-[68vw] max-w-none h-[90vh]"
open={issNewReg}
onOpenChange={(open) => {
setIsNewReg(open);
}}
/>
<UiModal
bodyClass={""}
open={bdstChgProps.isOpen}
body={<BdstChgModal chgBuilding={bdstChgProps.chgBuilding}></BdstChgModal>}
onOpenChange={(open) => {
setBdstChgProps({ ...bdstChgProps, isOpen: open });
}
}
/>
</ContentsDiv>
</>
);
}
@@ -0,0 +1,329 @@
"use client";
import {
ContentsDiv,
ScrollArea,
SearchDiv,
SearchFormLeft,
SearchInput,
Title,
UiModal,
UiTable,
} from "@common/business_components";
import { Button } from "@common/components";
import { useWrStore } from "../../../store";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@common/components";
import { useCallback, useEffect, useState } from "react";
import ListDiv from "@common/business_components/ui/list_div";
import { tableData } from "@/components/lib/func/commom";
import type {
customPbnst,
fcBizType,
PbnstRegArrrayType,
pubHasuType,
} from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/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";
import { PbnstRegModal } from "@/components/ui/modal/fcltReg/pbnstRegModal/pbnstRegModal";
import toast, { Toaster } from "react-hot-toast";
import { writeRgtrAndMdfr } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg";
import { useFieldArray, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
export default function PublicReuseFaciltyInsert() {
const {
code,
pbnst,
searchFclts,
pubHasuInit,
pbnstRegClick,
pbnstRuseFcltUpdate,
pubHasuSearch,
pbnstRuseBizUpdate,
} = useWrStore((state) => state);
const { pubFacHeadList, pbnstHasuRes, pbnstRes } = pbnst;
const [currentTab, setCurrentTab] = useState<string>("mng");
const [isRuseReg, setIsRuseReg] = useState<{
isModal: boolean;
data: pubHasuType;
}>({ isModal: false, data: {} as pubHasuType });
const [indexMng, setIndexMng] = useState<number>(0);
const [indexBiz, setIndexBiz] = useState<number>(0);
const [searchTxt, setSearchTxt] = useState<string>();
const [bdstTable, setbdstTable] = useState<pubHasuType[]>();
const [selectRow, setSelectRow] = useState<pubHasuType>();
const [pageNation, setPageNation] = useState<number>(1);
const form = useForm<{
items: z.infer<typeof pbnstRegZod>[];
}>({
resolver: zodResolver(z.object({ items: pbnstRegArrayZod })),
// defaultValues: { items: pbnstRegArrayZod.parse([]) },
mode: "onChange",
});
const {
fields: items,
append,
remove,
} = useFieldArray({
control: form.control,
name: `items`,
});
useEffect(() => {
if (!pbnst.isInit) {
pubHasuInit("1", "41");
}
}, [pbnst.isInit, pubHasuInit]);
const onSubmit = async (valuse: { items: PbnstRegArrrayType }) => {
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,
fcltCpct: fclt.fcltCpct,
ruseCpct: fclt.ruseCpct,
splyExtraCpct: fclt.splyExtraCpct,
rgtr: fclt.rgtr,
mdfr: fclt.mdfr,
fcFiles: fclt.fcFiles,
fcOpers: fclt.fcOpers,
})
})
await pbnstRuseFcltUpdate(pbnst as customPbnst[]);
await pbnstRuseBizUpdate(bizs);
};
useEffect(() => {
if (code.sggCd.length) {
if (searchFclts) {
setbdstTable(tableData(searchFclts, { code }));
} else if (code.sggCd.length > 0 && pbnstHasuRes.length > 0) {
setbdstTable(tableData(pbnstHasuRes, { code }));
}
}
}, [code, pbnstHasuRes, searchFclts]);
const cellClick = (val: number | undefined) => {
if (val === undefined) return;
const selectRow = pbnstHasuRes?.[val];
setSelectRow(pbnstHasuRes?.[val]);
if (selectRow) {
pbnstRegClick(selectRow);
}
};
const handleTabChange = (value: string) => {
setCurrentTab(value);
};
useEffect(() => {
if (pbnst.pbnstRes&& pbnst.pbnstRes?.length>0) {
console.log("pbnst.pbnstRes", pbnstRes);
form.reset({ items: pbnstRegArrayZod.parse(pbnst.pbnstRes) });
}else{
console.log("pbnst.pbnstRes is null", pbnstRes);
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: "",
fcBizs: [
fcBizSchema.parse({
pbnstRuseFcltFk:
String(lastPbnst.pbnstRuseFcltPk) +
String(pbnstRes.length + 1),
cycl: 1,
}),
] as fcBizType[],
})
);
setIsRuseReg({ ...isRuseReg, isModal: true });
}
} else {
if (selecTableRow) {
append(
pbnstRegZod.parse({
pbnstRuseFcltPk: String(selecTableRow.bscFctCd)+'1',
ruseUtztnFcltNm: "",
regDt: null,
mdfcnDt: null,
fcBizs: [fcBizSchema.parse({pbnstRuseFcltFk:String(selecTableRow.bscFctCd)+'1',cycl:1})] as fcBizType[],
})
)
setIsRuseReg({ ...isRuseReg, isModal: true });
}
}
}, [pbnstRegZod, pbnstRes, append, selectRow, form]);
useEffect(() => {
// console.log(" page getgetvaslue ", form.getValues());
}, [form.getValues()]);
useEffect(() =>{
pubHasuInit(String(pageNation), "41");
},[pageNation,pubHasuInit])
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<Title title={"하수재이용 시설 등록"} />
<SearchDiv>
<SearchFormLeft>
<SearchInput
className={"col-span-3 my-7 !text-3xl"}
label="건물명"
textValue={searchTxt || ""}
setText={(e) => {
setSearchTxt(e);
}}
/>
<div className="flex flex-row space-x-2 items-center">
<Button
className=""
size={"sm"}
onClick={(e) => {
searchTxt && searchTxt?.length > 0
? pubHasuSearch(String(pageNation), "41", searchTxt)
: pubHasuInit(String(pageNation), "41");
}}
>
조회
</Button>
<Button
size={"sm"}
className=""
onClick={() => {
// pbnstMngData([] as customPbnst[]);
if (!selectRow) {
toast.error(
"하수리시시설을 테이블을 선택하고 등록버튼을 눌러주세요"
);
return;
} else {
appendPbnstRuseFclt();
}
}}
>
신규등록
</Button>
</div>
</SearchFormLeft>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4 h-full">
<div className="col-span-4 h-full min-h-0">
<ListDiv className="min-h-0">
<ScrollArea className="h-[60vh]">
<UiTable
tableData={bdstTable || []}
headlist={pubFacHeadList}
pageSize={10}
total={100000}
headName={"공공 하수처리시설 등록"}
cellClick={cellClick}
onPageChange={setPageNation}
children={undefined}
/>
</ScrollArea>
</ListDiv>
</div>
<ListDiv className="col-span-2 pr-6 ">
<ScrollArea className="h-[60vh]">
<Tabs defaultValue="mng" onValueChange={handleTabChange}>
<TabsList className="">
<TabsTrigger className="!text-xl" value="mng">
시설정보
</TabsTrigger>
<TabsTrigger className="!text-xl" value="buse">
차수별정보
</TabsTrigger>
<Button
size={"sm"}
onClick={form.handleSubmit(onSubmit)}
className="!justify-end"
>
저장
</Button>
</TabsList>
<TabsContent className="max-h-full" value="mng">
<PbnstMngForm
formType="update"
form={form}
setIndexMng={(index: number) => {
console.log("setIndexMng", index);
setIndexMng(index);
}}
indexMng={indexMng}
/>
</TabsContent>
<TabsContent className="max-h-full" value="buse">
<PbnstBuseForm
formType="update"
form={form}
setIndexBiz={(index: number) => {
setIndexBiz(index);
}}
indexMng={indexMng}
indexBiz={indexBiz}
/>
</TabsContent>
</Tabs>
</ScrollArea>
</ListDiv>
<UiModal
body={
<PbnstRegModal
form={form}
data={isRuseReg.data || ({} as customPbnst)}
></PbnstRegModal>
}
bodyClass="w-[68vw] max-w-none h-[90vh]"
open={isRuseReg.isModal}
onOpenChange={(open) => {
remove(form.getValues("items").length - 1);
setIsRuseReg({ data: {} as pubHasuType, isModal: open });
}}
/>
</div>
<Toaster position="top-center" />
</ContentsDiv>
</>
);
}
@@ -0,0 +1,30 @@
import type { TableUpperProps } from "@/app/store/common/type/header";
import { TableRow, TableHead } from "@common/components/ui";
export const makeFcltRegHead = (upHeadList: TableUpperProps[]) => {
return (
<>
<TableRow>
{upHeadList.map((head: TableUpperProps) =>
!head.upSequnce ? (
<TableHead rowSpan={2} key={head.id}>
{head.title}
</TableHead>
) : head.upName === "upChangeRe" && head.upSequnce === 1 ? (
<TableHead key={head.id} rowSpan={1} colSpan={3}>
{"중축 개축 재축 "}
</TableHead>
) : null
)}
</TableRow>
<TableRow>
{upHeadList.map((head: TableUpperProps) =>
head.upName === "upChangeRe" ? (
<TableHead key={head.id}>{head.title}</TableHead>
) : null
)}
</TableRow>
</>
);
};
@@ -0,0 +1,181 @@
"use client";
import { useWrStore } from "@/app/store";
import {
type chgBuilding,
type customRainBdst,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { tableData } from "@/components/lib/func/commom";
import RainRegForm from "@/components/ui/form/fcltReg/rainReg/rainRegForm";
import BdstChgModal from "@/components/ui/modal/fcltReg/bdstChgModal/bdstChgModal";
import { BdstReg } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import {
ContentsDiv,
ScrollArea,
SearchDiv,
SearchFormLeft,
SearchInput,
Title,
UiModal,
UiTable,
} from "@common/business_components";
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components";
import { useEffect, useState } from "react";
export default function Home() {
const { rain, code, initRain, rainSearch, getRainData } = useWrStore((state) => {
return state;
});
const { rainRes } = rain;
const [rainForm, setRainForm] = useState<customRainBdst>();
const [issNewReg, setIsNewReg] = useState<boolean>(false);
const [pageNation, setPageNation] = useState(1);
const [bdstTable, setbdstTable] = useState<customRainBdst[]>();
const [searchTxt, setSearchTxt] = useState<string>();
const [bdstChgProps, setBdstChgProps] = useState<{
isOpen: boolean;
chgBuilding: chgBuilding[];
}>({ isOpen: false, chgBuilding: [] });
useEffect(() => {
if (!rain.isInit) {
initRain('41');
}
}, [rain.isInit, initRain]);
useEffect(() => {
if (code.sggCd.length > 0) {
const rainData = tableData(rainRes, { code }).map(
(item: customRainBdst) => {
return {
...item,
bdstChgYn: item.chgBuilding.length > 0 ? "Y" : "N",
};
}
);
setbdstTable(rainData);
}
}, [code, rainRes]);
const cellClick: (val: number | undefined, headId: string) => void = (
val,
headId
) => {
if (val !== undefined) {
setRainForm(rainRes[val]);
}
if (headId === "bdstChgYn" && val !== undefined) {
if (
rainRes[val]?.bdstInfoPk != null &&
rainRes[val]?.chgBuilding.length > 0
) {
bdstChgModal(rainRes[val].chgBuilding);
}
}
};
const bdstChgModal = (chgBuilding: chgBuilding[]) => {
setBdstChgProps({ isOpen: true, chgBuilding: chgBuilding });
};
useEffect(() => {
console.log("getPageNation", pageNation);
getRainData(pageNation, "41");
}, [pageNation]);
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<Title title={"빗물이용시설 등록"} />
<SearchDiv>
<SearchFormLeft>
<SearchInput
className={"col-span-3 my-7 !text-3xl"}
label="건물명"
textValue={searchTxt || ""}
setText={(e) => {
setSearchTxt(e);
}}
/>
<div className="flex flex-row space-x-2 items-center">
<Button
className=""
size={"sm"}
onClick={(e) => {
rainSearch(searchTxt || "", pageNation, "41");
}}
>
조회
</Button>
<Button
size={"sm"}
className=""
onClick={() => setIsNewReg(!issNewReg)}
>
신규등록
</Button>
</div>
</SearchFormLeft>
{/* <SearchFormRight>
</SearchFormRight> */}
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4">
<div className="col-span-4 h-full min-h-0">
<ListDiv className="min-h-0">
{/* <ScrollArea className="h-[60vh]"> */}
<UiTable
tableData={bdstTable || []}
headlist={rain.upHeadList}
pageSize={20}
total={10000}
headName={"건축물 목록"}
cellClick={(val, headId) => {
cellClick(val, headId);
}}
onPageChange={setPageNation}
>
</UiTable>
{/* </ScrollArea> */}
</ListDiv>
</div>
<div className="col-span-2 max-h-full">
<ListDiv className="">
<ScrollArea className="h-[60vh]">
<RainRegForm
rainForm={rainForm ?? ({} as customRainBdst)}
isModal={false}
></RainRegForm>
</ScrollArea>
</ListDiv>
</div>
</div>
<UiModal
body={<BdstReg moType="RNB"></BdstReg>}
bodyClass="w-[68vw] max-w-none h-[90vh]"
open={issNewReg}
onOpenChange={(open) => {
setIsNewReg(open);
}}
/>
<UiModal
bodyClass={""}
open={bdstChgProps.isOpen}
body={
<BdstChgModal chgBuilding={bdstChgProps.chgBuilding}></BdstChgModal>
}
onOpenChange={(open) => {
setBdstChgProps({ ...bdstChgProps, isOpen: open });
}}
/>
</ContentsDiv>
</>
);
}
@@ -0,0 +1,174 @@
"use client";
import { useWrStore } from "@/app/store";
import type { chgBuilding } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import type { customRswtBdst } from "@/app/store/ruseFcltMng/fcltReg/rswtReg";
import { tableData } from "@/components/lib/func/commom";
import RswtrRegForm from "@/components/ui/form/fcltReg/rswtrReg/rswtrRegForm";
import BdstChgModal from "@/components/ui/modal/fcltReg/bdstChgModal/bdstChgModal";
import { BdstReg } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import {
ContentsDiv,
ScrollArea,
SearchDiv,
SearchFormLeft,
SearchFormRight,
SearchInput,
Title,
UiModal,
UiTable,
} from "@common/business_components";
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components";
import { useEffect, useState } from "react";
export default function Home() {
const { code, rswt, initRswt, rswtBdstSearch, getRswtBdstData } = useWrStore(
(state) => state
);
const [rswtForm, setRswtForm] = useState<customRswtBdst>();
const [searchTxt, setSearchTxt] = useState<string>();
const [issNewReg, setIsNewReg] = useState<boolean>(false);
const [pageNation, setPageNation] = useState(1);
const [selectVal, setSelect] = useState<number>();
const [bdstTable, setbdstTable] = useState<customRswtBdst[]>();
const [bdstChgProps, setBdstChgProps] = useState<{
isOpen: boolean;
chgBuilding: chgBuilding[];
}>({ isOpen: false, chgBuilding: [] });
const { rswtRes } = rswt;
useEffect(() => {
if (!rswt.isInit) {
initRswt("41");
}
}, [rswt.isInit, initRswt]);
useEffect(() => {
if (code.sggCd.length > 0) {
const rswtData = tableData(rswtRes, { code }).map(
(item: customRswtBdst) => {
return {
...item,
bdstChgYn: item.chgBuilding[0]?.bdstChgNm != null ? "Y" : "N",
bdstUsgCd: item.reuseBuilding[0]?.bdstUsgCd,
};
}
);
setbdstTable(rswtData);
setRswtForm(rswtRes[selectVal ?? 0]);
}
}, [code, rswtRes, selectVal]);
const cellClick: (val: number | undefined, headId: string) => void = (
val,
headId
) => {
if ((bdstTable ?? []).length > 0 && val !== undefined) {
{
setSelect(val);
setRswtForm(rswtRes[val]);
}
}
if (headId === "bdstChgYn" && val !== undefined) {
if (
rswtRes[val]?.bdstInfoPk != null &&
rswtRes[val]?.chgBuilding?.length > 0
) {
bdstChgModal(rswtRes[val].chgBuilding);
}
}
};
const bdstChgModal = (chgBuilding: chgBuilding[]) => {
setBdstChgProps({ isOpen: true, chgBuilding: chgBuilding });
};
useEffect(() => {
getRswtBdstData(pageNation, "41");
}, [pageNation]);
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<Title title={"중수도시설 등록"} />
<SearchDiv>
<SearchFormLeft>
<SearchInput
className="col-span-3 my-7"
label="건물명"
textValue={searchTxt || ""}
setText={(e) => {
setSearchTxt(e);
}}
/>
</SearchFormLeft>
<SearchFormRight>
<div className="flex flex-row space-x-2">
<Button
size={"sm"}
className="mr-4 "
onClick={(e) => {
rswtBdstSearch(searchTxt || "", pageNation, "41");
}}
>
조회
</Button>
<Button
size={"sm"}
className="mr-4"
onClick={() => setIsNewReg(!issNewReg)}
>
신규등록
</Button>
</div>
</SearchFormRight>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4">
<div className="col-span-4 h-full min-h-0">
<ListDiv className="min-h-0">
<UiTable
tableData={bdstTable || []}
headlist={rswt.upHeadList}
pageSize={20}
total={10000}
headName={"건축물 목록"}
cellClick={cellClick}
onPageChange={setPageNation}
></UiTable>
</ListDiv>
</div>
<div className="col-span-2 max-h-full">
<ListDiv>
<ScrollArea className="h-[60vh]">
<RswtrRegForm
rswtForm={rswtForm ?? ({} as customRswtBdst)}
isModal={false}
/>
</ScrollArea>
</ListDiv>
</div>
</div>
<UiModal
body={<BdstReg moType="RST"></BdstReg>}
bodyClass="w-[68vw] max-w-none h-[90vh]"
open={issNewReg}
onOpenChange={(open) => {
setIsNewReg(open);
}}
/>
<UiModal
bodyClass={""}
open={bdstChgProps.isOpen}
body={
<BdstChgModal chgBuilding={bdstChgProps.chgBuilding}></BdstChgModal>
}
onOpenChange={(open) => {
setBdstChgProps({ ...bdstChgProps, isOpen: open });
}}
/>
</ContentsDiv>
</>
);
}
@@ -0,0 +1,193 @@
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import type {
chgBuilding,
customRainBdst,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import {
excelDownload,
getCityOrSgg,
tableData,
} from "@/components/lib/func/commom";
import HeadChModal from "@/components/ui/modal/sttn/headChModal/headChModal";
import SttnDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/sttnDetailModal";
import {
ContentsDiv,
SearchBaseForm,
Title,
UiModal,
UiTable,
type ReturnType,
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components/ui";
import { useCallback, useEffect, useRef, useState } from "react";
import { excelHtdflSttnParsing } from "@/app/store/ruseFcltMng/fcltSttn/htdflSttn/excel";
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
export default function HtdflSttn() {
const { code, htdflSttn, htdflSttnSearch, initHtdfl } = useWrStore(
(state) => state
);
const { htdflSttnRes } = htdflSttn;
const ref = useRef<ReturnType>({} as ReturnType);
const [pageNation, setPageNation] = useState(1);
const [isChHead, setIsChHead] = useState(false);
const [bdstTable, setBdstTable] = useState<customRainBdst[]>();
const [detailModal, setDetailModal] = useState<{
isOpen: boolean;
data: customRainBdst | undefined;
}>({ data: undefined, isOpen: false });
const [bdstChgProps, setBdstChgProps] = useState<{
isOpen: boolean;
chBuilding: chgBuilding[];
}>({ isOpen: false, chBuilding: [] });
const codeData = getCityOrSgg(ref);
const excelClick = useCallback(() => {
if (codeData) htdflSttnSearch(1, "10000", codeData);
}, [htdflSttnSearch, codeData]);
useEffect(() => {
if (codeData != null) htdflSttnSearch(pageNation, "20", codeData);
}, [pageNation]);
const cellClick = (index: number | undefined, headId: string) => {
if (
headId !== "chBuildingYn" &&
index !== undefined &&
bdstTable !== undefined
) {
setDetailModal({ isOpen: true, data: bdstTable[index] });
}
};
useEffect(() => {
const excelDown = async () => {
if (htdflSttn.excelList.length > 0) {
if (htdflSttn.excelList.length === 0) return;
const excelData = await tableData(htdflSttn.excelList, { code });
const htdflExcel = excelHtdflSttnParsing(excelData, code.cityCd, code.sggCd);
excelDownload(
htdflExcel as [[]],
"온배수시설 현황",
"sample_htdflSttn.xlsx",
"A1:S3"
);
}
};
excelDown();
}, [htdflSttn.excelList, code]);
useEffect(() => {
if (!htdflSttn.isInit) {
initHtdfl(codeData ?? "0");
}
}, [htdflSttn.isInit, initHtdfl]);
useEffect(() => {
if (htdflSttnRes.length > 0 && code.cityCd.length > 0) {
const data = tableData(htdflSttnRes, { code });
const chData = data
.map((item: any) => ({
...item,
...item.reuseBuilding[0],
...item.reuseBuilding[0].htdflObj,
chBuildingYn: item.chgBuilding[0]?.bdstChgNm !== null ? "Y" : "N",
}))
.filter((item: any) => item.htdflObj !== undefined);
setBdstTable(chData);
}
}, [code, htdflSttnRes, htdflSttn.htdflSttHeadList]);
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4 ">
<div className="col-span-4">
<Title title={"온배수 시설 현황"} />
<SearchBaseForm
selectSidoData={code.cityCd}
selectSigunData={code.sggCd}
selectRegionData={code.rvbsnCd}
selectUnitWaterShedData={code.lgbsnCd}
selectMiddleRegionData={code.mdmbsnCd}
selectEnvPartData={code.lclgvrnmntCd}
rightChildren={<Button
className={btnClass}
onClick={() => {
setIsChHead(true);
} }
>
조회항목설정
</Button>}
leftChildren={undefined}
queryClick={function (returnType: ReturnType): void {
// '{partValue: 'A', sidoValue: '0', sigunValue: '0', regionValue: '0', unitWaterShedValue: '0', …}'
let con;
if (returnType.sigunValue != "0") {
con = returnType.sigunValue;
} else {
con = returnType.sidoValue;
}
htdflSttnSearch(pageNation, "20", con);
} }
excelClick={excelClick}
initClick={function (): void { } }
btnClass={btnClass}
ref={ref} isAdmin={false} />
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={[]}
tableData={bdstTable || []}
children={
<HeadMakeColSpan upHeadList={htdflSttn.htdflSttNodeList} />
}
headlist={htdflSttn.htdflSttHeadList}
pageSize={20}
total={100000}
cellClick={(index: number | undefined, headId: string) => {
cellClick(index ?? undefined, headId);
}}
onPageChange={setPageNation}
></UiTable>
</ListDiv>
</div>
</div>
<UiModal
open={isChHead}
onOpenChange={() => {
setIsChHead(!isChHead);
}}
bodyClass={""}
body={
<HeadChModal
type={"HTB"}
headList={htdflSttn.htdflSttHeadList.map((item) => ({
...item,
visible: item.visible ?? false,
}))}
/>
}
/>
<UiModal
open={detailModal.isOpen}
onOpenChange={() => {
setDetailModal({ ...detailModal, isOpen: !detailModal.isOpen });
}}
bodyClass={"w-[40vw] max-w-none max-h-[calc(100%-70px)]"}
body={<SttnDetailModal type={"HTB"} formObj={detailModal.data} />}
/>
</ContentsDiv>
</>
);
}
@@ -0,0 +1,223 @@
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import {
ContentsDiv,
SearchBaseForm,
SearchInput,
SelectBox,
Title,
UiModal,
UiTable,
type ReturnType,
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button, Label } from "@common/components/ui";
import HeadChModal from "@/components/ui/modal/sttn/headChModal/headChModal";
import { useCallback, useEffect, useRef, useState } from "react";
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import type { customPbnst } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import { excelDownload, yearOptions } from "@/components/lib/func/commom";
import SearchInputText from "@/components/ui/searchInput/searchInput";
import type { WaterReuseFacility } from "@/app/store/ruseFcltMng/fcltSttn/pbnstSttn/type";
import { PbnstSttnModal } from "@/components/ui/modal/sttn/pbnstSttnModal/pbnstSttnModal";
export default function PbnstSttn() {
const {
code,
pbnstSttn,
pbnstSttnSearch,
pbnSttnInit,
getPbnStnDetail,
pbnNmSearch,
} = useWrStore((state) => state);
const ref = useRef<ReturnType>({} as ReturnType);
const [searchYear, setSearchYear] = useState<string>(
String(new Date().getFullYear())
);
const [isChHead, setIsChHead] = useState(false);
const [bdstTable, setBdstTable] = useState<WaterReuseFacility[]>();
const [pbnDetaileData, setPbnDetaileData] = useState<{
isModal: boolean;
data: customPbnst;
}>({ isModal: false, data: {} as customPbnst });
const [pbnRuseNm, setPbnRuseNm] = useState<string>("");
const excelClick = useCallback(() => {
pbnstSttnSearch("1", "10000", ref.current, "", searchYear);
}, [pbnstSttnSearch, searchYear, ref.current]);
const cellCLick = useCallback(
(index: number | undefined) => {
if (
index !== undefined &&
pbnstSttn.pbnstSttnRes &&
pbnstSttn.pbnstSttnRes[index]
) {
const pbnstRuseFcltPk = pbnstSttn.pbnstSttnRes[index].pbnstRuseFcltPk;
getPbnStnDetail(pbnstRuseFcltPk);
}
},
[getPbnStnDetail, pbnstSttn.pbnstSttnRes]
);
useEffect(() => {
if (pbnstSttn.excelList.length >= 0) {
excelDownload(
pbnstSttn.excelList,
"하수재이용시설 현황",
"sample_pbnstSttn.xlsx",
"A1:U2"
);
}
}, [pbnstSttn.excelList]);
useEffect(() => {
if (!pbnstSttn.isInit) {
pbnSttnInit("1", "13", ref.current, searchYear);
}
}, [pbnstSttn.isInit, pbnSttnInit, ref.current]);
useEffect(() => {
setBdstTable(pbnstSttn.pbnstSttnRes);
}, [pbnstSttn.pbnstSttnRes]);
// useEffect(() => {
// pbnstSttnSearch("1", "20", ref.current, pbnRuseNm, searchYear);
// }, [pageNation, ref.current, pbnRuseNm, searchYear, pbnstSttnSearch]);
// useEffect(() => {
// if (pbnRuseNm.length > 1)
// pbnNmSearch(String(pageNation), "23", ref.current, pbnRuseNm, searchYear);
// }, [pbnRuseNm,pageNation]);
useEffect(() => {
if (pbnstSttn.pbnstDetail.pbnstRuseFcltPk)
setPbnDetaileData({
isModal: true,
data: pbnstSttn.pbnstDetail,
});
}, [pbnstSttn.pbnstDetail]);
useEffect(() => {
console.log("pbnDetaileData.isModal ", pbnDetaileData.isModal);
}, [pbnDetaileData.isModal]);
return (
<>
<ContentsDiv>
<div className="grid grid-cols-2 gap-4 ">
<div className="col-span-2">
<Title title={"하수재이용 시설 현황"} />
<SearchBaseForm
selectSidoData={code.cityCd}
selectSigunData={code.sggCd}
selectRegionData={code.rvbsnCd}
selectUnitWaterShedData={code.lgbsnCd}
selectMiddleRegionData={code.mdmbsnCd}
selectEnvPartData={code.lclgvrnmntCd}
rightChildren={
<Button
className={btnClass}
onClick={() => {
setIsChHead(true);
}}
>
조회항목설정
</Button>
}
leftChildren={
<div className="col-span-3 flex items-center">
<SelectBox
className="w-48 h-full text-2xl"
label="연도"
selectClass={"w-full "}
selectArray={yearOptions}
value={searchYear}
onSelectValue={(val: string | number) =>
setSearchYear(String(val))
}
/>
<Label className="w-64 mt-2 mx-4 text-xl text-gray-600">
{"하수처리시설명 "}
</Label>
<SearchInput
className={"text-2xl w-full ㅍ"}
label=""
textValue={pbnRuseNm || ""}
setText={(e) => {
setPbnRuseNm(e || "");
}}
/>
</div>
}
queryClick={function (returnType: ReturnType): void {
pbnstSttnSearch("1", "20", returnType, pbnRuseNm, searchYear);
}}
excelClick={excelClick}
initClick={function (): void {}}
btnClass={btnClass}
ref={ref}
isAdmin={false}
/>
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={[]}
tableData={bdstTable || []}
children={
<HeadMakeColSpan upHeadList={pbnstSttn.pbnstSttNodeList} />
}
headlist={pbnstSttn.pbnstSttHeadList}
pageSize={20}
total={100000}
cellClick={(index: number | undefined, headId: string) => {
cellCLick(index);
}}
onPageChange={(page: number) => {
pbnstSttnSearch(
String(page),
String(13),
ref.current,
pbnRuseNm,
searchYear
);
}}
></UiTable>
</ListDiv>
</div>
</div>
<UiModal
open={isChHead}
onOpenChange={() => {
setIsChHead(!isChHead);
}}
bodyClass={""}
body={
<HeadChModal
type={"PBN"}
headList={pbnstSttn.pbnstSttHeadList.map((item) => ({
...item,
visible: item.visible ?? false,
}))}
/>
}
/>
<UiModal
body={
<PbnstSttnModal
data={pbnDetaileData.data || ({} as customPbnst)}
></PbnstSttnModal>
}
bodyClass="w-[68vw] max-w-none h-[90vh]"
open={pbnDetaileData.isModal}
onOpenChange={(open) => {
setPbnDetaileData({ data: {} as customPbnst, isModal: false });
}}
/>
</ContentsDiv>
</>
);
}
@@ -0,0 +1,216 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import {
excelDownload,
getCityOrSgg,
tableData,
} from "@/components/lib/func/commom";
import HeadChModal from "@/components/ui/modal/sttn/headChModal/headChModal";
import {
ContentsDiv,
SearchBaseForm,
Title,
UiModal,
UiTable,
type ReturnType,
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components/ui";
import { useCallback, useEffect, useRef, useState } from "react";
import type {
chgBuilding,
customRainBdst,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import SttnDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/sttnDetailModal";
import BdstChgModal from "@/components/ui/modal/fcltReg/bdstChgModal/bdstChgModal";
export default function RainSttn() {
const { code, rainSttn, rainSttnSearch, rainSttnInit } = useWrStore(
(state) => state
);
const { rainSttnRes } = rainSttn;
const ref = useRef<ReturnType>({} as ReturnType);
const [pageNation, setPageNation] = useState(1);
const [isChHead, setIsChHead] = useState(false);
const [bdstTable, setBdstTable] = useState<customRainBdst[]>();
const [detailModal, setDetailModal] = useState<{
isOpen: boolean;
data: customRainBdst | undefined;
}>({ data: undefined, isOpen: false });
const [bdstChgProps, setBdstChgProps] = useState<{
isOpen: boolean;
chBuilding: chgBuilding[];
}>({ isOpen: false, chBuilding: [] });
const codeData = getCityOrSgg(ref);
const cellClick = (index: number | undefined, headId: string) => {
if (
headId !== "chBuildingYn" &&
index !== undefined &&
bdstTable !== undefined
) {
setDetailModal({ isOpen: true, data: bdstTable[index] });
} else if (
headId === "chBuildingYn" &&
index !== undefined &&
bdstTable !== undefined
) {
if (
bdstTable[index] &&
bdstTable[index]?.chgBuilding[0]?.bdstChgNm !== null
) {
setBdstChgProps({
isOpen: true,
chBuilding: bdstTable[index].chgBuilding,
});
}
}
};
useEffect(() => {
if (!rainSttn.isInit) {
rainSttnInit(codeData ?? "0");
}
}, [rainSttn.isInit, rainSttnInit]);
useEffect(() => {
if (rainSttnRes.length > 0 && code.cityCd.length > 0) {
const data = tableData(rainSttnRes, { code });
const chData = data
.map((item: any) => ({
...item,
...item.reuseBuilding[0],
...item.reuseBuilding[0].rainyObj,
chBuildingYn: item.chgBuilding[0]?.bdstChgNm !== null ? "Y" : "N",
}))
.filter((item: any) => item.rainyObj !== undefined);
setBdstTable(chData);
}
}, [code, rainSttnRes, rainSttn.rainSttHeadList]);
useEffect(() => {
if (codeData != null) rainSttnSearch(pageNation, "20", codeData, code.cityCd, code.sggCd);
}, [pageNation]);
useEffect(() => {
if (rainSttn.excelList.length > 0) {
if (rainSttn.excelList.length === 0) return;
excelDownload(
rainSttn.excelList,
"빗물재이용시설 현황",
"sample_rainSttn.xlsx",
"A1:W3"
);
}
}, [rainSttn.excelList]);
const excelClick = useCallback(() => {
if (codeData) rainSttnSearch(1, "10000", codeData, code.cityCd, code.sggCd);
}, [rainSttnSearch, codeData, code.cityCd, code.sggCd]);
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4 ">
<div className="col-span-4">
<Title title={"빗물재이용 시설 현황"} />
<SearchBaseForm
selectSidoData={code.cityCd}
selectSigunData={code.sggCd}
selectRegionData={code.rvbsnCd}
selectUnitWaterShedData={code.lgbsnCd}
selectMiddleRegionData={code.mdmbsnCd}
selectEnvPartData={code.lclgvrnmntCd}
rightChildren={
<Button
className={btnClass}
onClick={() => {
setIsChHead(true);
}}
>
조회항목설정
</Button>
}
leftChildren={undefined}
queryClick={function (returnType: ReturnType): void {
// '{partValue: 'A', sidoValue: '0', sigunValue: '0', regionValue: '0', unitWaterShedValue: '0', …}'
let con;
if (returnType.sigunValue != "0") {
con = returnType.sigunValue;
} else {
con = returnType.sidoValue;
}
rainSttnSearch(1, "20", con, code.cityCd, code.sggCd);
}}
excelClick={excelClick}
initClick={function (): void { }}
btnClass={btnClass}
ref={ref}
isAdmin={false}
/>
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={[]}
tableData={bdstTable || []}
children={
<HeadMakeColSpan upHeadList={rainSttn.rainSttNodeList} />
}
headlist={rainSttn.rainSttHeadList}
pageSize={20}
total={100000}
cellClick={(index: number | undefined, headId: string) => {
cellClick(index ?? undefined, headId);
}}
onPageChange={setPageNation}
></UiTable>
</ListDiv>
</div>
</div>
<UiModal
open={isChHead}
onOpenChange={() => {
setIsChHead(!isChHead);
}}
bodyClass={""}
body={
<HeadChModal
type={"RNB"}
headList={rainSttn.rainSttHeadList.map((item) => ({
...item,
visible: item.visible ?? false,
}))}
/>
}
/>
<UiModal
open={detailModal.isOpen}
onOpenChange={() => {
setDetailModal({ ...detailModal, isOpen: !detailModal.isOpen });
}}
bodyClass={"w-[40vw] max-w-none max-h-[calc(100%-70px)]"}
body={<SttnDetailModal type={"RNB"} formObj={detailModal.data} />}
/>
<UiModal
bodyClass={""}
open={bdstChgProps.isOpen}
body={
<BdstChgModal chgBuilding={bdstChgProps.chBuilding}></BdstChgModal>
}
onOpenChange={(open) => {
setBdstChgProps({ ...bdstChgProps, isOpen: open });
}}
/>
</ContentsDiv>
</>
);
}
@@ -0,0 +1,199 @@
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import type { chgBuilding } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import type { customRswtBdst } from "@/app/store/ruseFcltMng/fcltReg/rswtReg";
import {
excelDownload,
getCityOrSgg,
tableData,
} from "@/components/lib/func/commom";
import BdstChgModal from "@/components/ui/modal/fcltReg/bdstChgModal/bdstChgModal";
import HeadChModal from "@/components/ui/modal/sttn/headChModal/headChModal";
import SttnDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/sttnDetailModal";
import {
ContentsDiv,
SearchBaseForm,
Title,
UiModal,
UiTable,
type ReturnType,
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import { Button } from "@common/components/ui";
import { useCallback, useEffect, useRef, useState } from "react";
export default function RswtSttn() {
const { code, rswtSttn, rswtSttnSearch, rswtSttnInit } = useWrStore(
(state) => state
);
const [pageNation, setPageNation] = useState(1);
const { rswtSttnRes } = rswtSttn;
const [isChHead, setIsChHead] = useState(false);
const ref = useRef<ReturnType>({} as ReturnType);
const [bdstTable, setBdstTable] = useState<customRswtBdst[]>();
const [detailModal, setDetailModal] = useState<{ isOpen: boolean, data: customRswtBdst | undefined }>({ data: undefined, isOpen: false })
const [bdstChgProps, setBdstChgProps] = useState<{
isOpen: boolean;
chBuilding: chgBuilding[];
}>({ isOpen: false, chBuilding: [] });
const codeCityOrSgg = getCityOrSgg(ref);
const cellClick = (index: number | undefined, headId: string) => {
if (headId !== 'chBuildingYn' && index !== undefined && bdstTable !== undefined) {
setDetailModal({ isOpen: true, data: bdstTable[index] })
} else if (headId === 'chBuildingYn' && index !== undefined && bdstTable !== undefined) {
if (
bdstTable[index] &&
bdstTable[index]?.chBuildingYn === 'Y'
) {
setBdstChgProps({ isOpen: true, chBuilding: bdstTable[index].chgBuilding });
}
}
}
useEffect(() => {
if (!rswtSttn.isInit) {
rswtSttnInit("0");
}
}, [rswtSttn.isInit, rswtSttnInit]);
useEffect(() => {
if (rswtSttnRes.length > 0 && code.cityCd.length > 0) {
const data = tableData(rswtSttnRes, { code });
const chData = data
.map((item: customRswtBdst) => ({
...item,
...item.reuseBuilding[0],
...item.reuseBuilding[0]?.rswtrObj,
chBuildingYn: item?.chgBuilding[0]?.bdstChgNm !== null && item?.chgBuilding.length > 0 ? 'Y' : 'N'
}))
.filter(
(item: customRswtBdst) =>
item.reuseBuilding[0]?.rswtrObj !== undefined
);
setBdstTable(chData);
}
}, [code, rswtSttnRes]);
useEffect(() => {
if (rswtSttn.excelList.length > 0) {
if (rswtSttn.excelList.length === 0) return;
excelDownload(
rswtSttn.excelList,
"중수도시설 현황",
"sample_rswtSttn.xlsx",
"A1:W3",
);
}
}, [rswtSttn.excelList]);
const excelClick = useCallback(
(returnType: ReturnType) => {
if (codeCityOrSgg)
rswtSttnSearch(1, "10000", codeCityOrSgg, code.cityCd, code.sggCd);
},
[rswtSttnSearch, code.cityCd, code.sggCd, codeCityOrSgg]
);
useEffect(() => {
if (codeCityOrSgg != null) rswtSttnSearch(pageNation, "20", codeCityOrSgg, code.cityCd, code.sggCd);
}, [pageNation]);
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4 ">
<div className="col-span-4">
<Title title={"중수도시설 현황"} />
<SearchBaseForm
selectSidoData={code.cityCd}
selectSigunData={code.sggCd}
selectRegionData={code.rvbsnCd}
selectUnitWaterShedData={code.lgbsnCd}
selectMiddleRegionData={code.mdmbsnCd}
selectEnvPartData={code.lclgvrnmntCd}
rightChildren={<Button
className={btnClass}
onClick={() => {
setIsChHead(true);
} }
>
조회항목설정
</Button>}
leftChildren={undefined}
queryClick={function (returnType: ReturnType): void {
// '{partValue: 'A', sidoValue: '0', sigunValue: '0', regionValue: '0', unitWaterShedValue: '0', …}'
if (codeCityOrSgg)
rswtSttnSearch(1, "20", codeCityOrSgg, code.cityCd, code.sggCd);
} }
excelClick={excelClick}
initClick={function (): void { } }
btnClass={btnClass}
ref={ref} isAdmin={false} />
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={[]}
tableData={bdstTable || []}
children={
<HeadMakeColSpan upHeadList={rswtSttn.rswtSttNodeList} />
}
headlist={rswtSttn.rswtSttHeadList}
pageSize={20}
total={10000}
cellClick={(index: number | undefined, headId: string) => { cellClick(index ?? undefined, headId) }}
onPageChange={setPageNation}
></UiTable>
</ListDiv>
</div>
</div>
<UiModal
open={isChHead}
onOpenChange={() => {
setIsChHead(!isChHead);
}}
bodyClass={""}
body={
<HeadChModal
headList={(rswtSttn.rswtSttHeadList || []).map((item) => ({
...item,
visible: item.visible ?? false,
}))}
type={"RST"}
/>
}
/>
<UiModal
open={detailModal.isOpen}
onOpenChange={() => {
setDetailModal({ ...detailModal, isOpen: !detailModal.isOpen });
}}
bodyClass={"w-[40vw] max-w-none max-h-[calc(100%-70px)]"}
body={<SttnDetailModal type={"RST"} formObj={detailModal.data} />}
/>
<UiModal
bodyClass={""}
open={bdstChgProps.isOpen}
body={
<BdstChgModal chgBuilding={bdstChgProps.chBuilding}></BdstChgModal>
}
onOpenChange={(open) => {
setBdstChgProps({ ...bdstChgProps, isOpen: open });
}}
/>
</ContentsDiv>
</>
);
}
@@ -0,0 +1,54 @@
import type { TableUpperProps } from "@/app/store/common/type/header";
import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn/headList";
import { TableHead, TableRow } from "@common/components/ui";
export const headMakeprfmnc = (
upHeadList: TableUpperProps[],
makeHeadNm: chHeadType[]
) => {
return (
<>
<TableRow>
{upHeadList
.filter((data) => data.visible != false)
.map((head: TableUpperProps) =>
!head.upSequnce ? (
<TableHead
className={`border border-gray-600 px-2 py-1 `}
rowSpan={2}
key={head.id}
>
{head.title}
</TableHead>
) : head.upSequnce === 1 ? (
<TableHead
className={`border border-gray-600 px-2 py-1 `}
key={head.id}
rowSpan={1}
colSpan={
makeHeadNm.find((ch) => ch.headNm === head.upName)?.length
}
>
{makeHeadNm.find((ch) => ch.headNm === head.upName)?.text}
</TableHead>
) : null
)}
</TableRow>
<TableRow>
{upHeadList
.filter((data) => data.visible != false)
.map((head: TableUpperProps) =>
makeHeadNm.find((ch) => ch.headNm === head.upName) ? (
<TableHead
className={`border border-gray-600 px-2 py-1 `}
key={head.id}
>
{head.title}
</TableHead>
) : null
)}
</TableRow>
</>
);
};
@@ -0,0 +1,283 @@
"use client";
import { useWrStore } from "@/app/store";
import { type rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn";
import type {
rswtChkZodType,
rswtrChkDetailsZodType,
} from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn";
import {
excelArrayDownload,
excelDownload,
yearOptions,
} from "@/components/lib/func/commom";
import ChkgdExcel from "@/components/ui/modal/chkgd/chkgdExcel/chkgdExcel";
import ChkgdModal from "@/components/ui/modal/chkgd/chkgdModal/chkgdModal";
import RainChkgdTable from "@/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable";
import RswtChkgdTable from "@/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable";
import {
ContentsDiv,
SearchDiv,
SearchFormLeft,
SearchFormRight,
SearchInput,
SelectBox,
Title,
UiModal,
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button, Label } from "@common/components/ui";
import { useCallback, useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
import { shallow } from "zustand/shallow";
//-----------------------
export default function Page() {
const {
code,
rainChkgdn,
rswtChkgdn,
rainChkInit,
rainChkDetilUpdate,
rainChkDelete,
rainChkExcelDownload,
rainChkHeadChange,
isRainSttn,
rswtChkgdnInit,
rswtChkPolInit,
rswtChkDetilsUpdate,
rswtChkDelete,
rswtrChkExcelDownload,
rswtChkHeadChange,
} = useWrStore((state) => {
return state;
});
const [isRegExcel, setIsRegExcel] = useState(false);
const [updateRainDetail, setUpdateRainDetail] = useState<rainChkZodType[]>(
[]
);
const [updateRswtDetail, setUpdateRSwtDetail] = useState<
rswtrChkDetailsZodType[]
>([]);
const [deleteIdx, setDeleteIdx] = useState<number[]>([]);
const [selFcltDiv, setSelFcltDiv] = useState("RNB");
const [isModal, setIsModal] = useState({
open: false,
data: {},
});
const cellClick = () => {
if (searchYear) rainChkInit(searchYear, "0");
};
const [searchYear, setSearchYear] = useState<string>(
String(new Date().getFullYear())
);
useEffect(() => {
if (!rainChkgdn.isInit) {
rainChkInit(new Date().getFullYear().toString(), "0");
isRainSttn(false);
setIsModal({ data: {}, open: false });
setIsRegExcel(false);
}
if (!rswtChkgdn.isInit) {
rswtChkgdnInit(new Date().getFullYear().toString(), "0");
setIsModal({ data: {}, open: false });
setIsRegExcel(false);
}
}, [rainChkgdn.isInit, rainChkInit]);
useEffect(() => {
if (rswtChkgdn.excelList[0]&&rswtChkgdn.excelList[0]?.data.length > 1) {
excelArrayDownload(
"중수도시설 지도점검",
"sample_rs_chk.xlsx",
rswtChkgdn.excelList
);
}
}, [rswtChkgdn.excelList]);
useEffect(() => {
excelDownload(
rainChkgdn.excelList,
"빗물이용시설 지도점검",
"sample_rainy.xlsx",
"A1:AN1",
2
);
}, [rainChkgdn.excelList]);
const excelClick = useCallback(() => {
if (selFcltDiv === "RNB") {
rainChkExcelDownload(code.cityCd, code.sggCd);
} else {
rswtrChkExcelDownload(code.cityCd, code.sggCd);
}
}, [
rainChkExcelDownload,
rswtrChkExcelDownload,
code.cityCd,
code.sggCd,
selFcltDiv,
]);
const handleClick = useCallback(
(data: any) => {
if (data) setIsModal({ open: !isModal.open, data: data });
},
[isModal]
);
useEffect(() => {
rainChkgdn.isSttn = false;
rswtChkgdn.isSttn = false;
if (!rainChkgdn.isSttn && !rswtChkgdn.isSttn) {
rainChkHeadChange({ rainChkgdn }, true);
rswtChkHeadChange({ rswtChkgdn }, true);
}
}, [rainChkgdn.isSttn, rswtChkgdn.isSttn]);
const clickDelete = (data: number[], selFcltDiv: string) => {
if (data.length > 0) {
if (selFcltDiv === "RNB") {
rainChkDelete(data);
} else {
rswtChkDelete(data);
}
}
};
const chkUpdateTable = (selFcltDiv: string) => {
if (selFcltDiv === "RNB") {
rainChkDetilUpdate(updateRainDetail);
} else {
rswtChkDetilsUpdate(updateRswtDetail);
}
};
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>
<SelectBox
className={"w-full h-full text-2xl"}
label={""}
selectClass={""}
selectArray={rainChkgdn.fcltDiv}
onSelectValue={(val: string | number) =>{
if(val === "RST") rswtChkPolInit();
setSelFcltDiv(String(val))
}
}
value={selFcltDiv ?? rainChkgdn.fcltDiv[0]?.val}
/>
</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={(e) => {
cellClick();
}}
>
조회
</Button>
<Button
size={"sm"}
onClick={() => {
clickDelete(deleteIdx, selFcltDiv);
}}
>
삭제
</Button>
<Button
size={"sm"}
onClick={() => {
chkUpdateTable(selFcltDiv);
}}
>
저장
</Button>
<Button
size={"sm"}
onClick={() => {
setIsRegExcel(!isRegExcel);
}}
>
결과등록
</Button>
<Button color="green" size={"sm"} onClick={excelClick}>
양식받기
</Button>
</div>
</div>
</SearchFormRight>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
{selFcltDiv === "RNB" ? (
<RainChkgdTable
deleteData={setDeleteIdx}
detailUp={setUpdateRainDetail}
handleClick={handleClick}
rainChkData={rainChkgdn.rainChk}
/>
) : (
<RswtChkgdTable
detaiRswtlUpdate={setUpdateRSwtDetail}
deleteRswtData={setDeleteIdx}
handleRswtClick={handleClick}
rswtChkData={rswtChkgdn.rswtChkRes}
/>
)}
</ListDiv>
</div>
</div>
<UiModal
open={isModal.open}
onOpenChange={() => {
setIsModal({ open: !open, data: {} });
}}
bodyClass={"w-[80vw] max-w-none"}
body={<ChkgdModal type={selFcltDiv} obj={isModal.data} />}
></UiModal>
<UiModal
open={isRegExcel}
onOpenChange={setIsRegExcel}
bodyClass={"w-[30vw] max-w-none"}
body={<ChkgdExcel type={selFcltDiv}></ChkgdExcel>}
/>
<Toaster position="top-center" />
</ContentsDiv>
);
}
@@ -0,0 +1,279 @@
"use client";
import { useWrStore } from "@/app/store";
import type { pubHasuType } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import { excelDownload, yearOptions } from "@/components/lib/func/commom";
import PbnPrfExcelModal from "@/components/ui/modal/chkgd/pbnPrfExcelModal/pbnPrfExcelModal";
import {
ContentsDiv,
Title,
SearchDiv,
SearchFormLeft,
SelectBox,
SearchInput,
SearchFormRight,
ScrollArea,
UiTable,
UiModal,
} 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 { useState, useEffect, useCallback } from "react";
import { set } from "react-hook-form";
import { Toaster } from "react-hot-toast";
import { headMakeprfmnc } from "../chkgdnReg/TableHead";
import { InputTableBody } from "@/components/lib/func/TableData";
import {
initValInUsage,
initValOutUsage,
subTotalObj,
totalObj,
type FcPrfType,
type PrfType,
} from "@/app/store/prfmncReg/pbnstPrfmncReg/type";
import { excelToPbnPrfData } from "@/app/store/prfmncReg/pbnstPrfmncReg/excel";
export default function prfmncPrfmncReg() {
const { code, prfmnc, prfmncHasuInit, prfmnRegData } = useWrStore(
(state) => state
);
const { pbnstPrfmncHeadList, monthHeadList, prfmncRes } = 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 [pbnstRuseFcltPk, setPbnstRuseFcltPk] = useState<string>();
const [pageNation , setPageNation] = 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(() => {
if (pbnstRuseFcltPk) {
prfmnRegData(
excelToPbnPrfData(
inputData as unknown as JSON[],
searchYear,
pbnstRuseFcltPk
) as unknown as PrfType
);
prfmncHasuInit(String(pageNation), "41");
}
}, [inputData, searchYear, pbnstRuseFcltPk,prfmncHasuInit,pageNation]);
const cellClick = useCallback(
(index: number | undefined, headId: string) => {
if (index !== undefined) {
setIsExcelOPen({
isModal: false,
data: prfmncRes[index] || ({} as FcPrfType),
});
const inUsageData = structuredClone(initValInUsage);
const outUsageData = structuredClone(initValOutUsage);
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];
setPbnstRuseFcltPk(prfmncRes[index].pbnstRuseFcltPk);
setInputData(tableData);
} else {
setInputData([]);
}
}
},
[prfmncRes]
);
useEffect(() => {
if (!prfmnc.isInit) {
prfmncHasuInit('1', "41");
}
}, [prfmnc.isInit, prfmncHasuInit]);
useEffect(() => {
setbdstTable(prfmncRes);
}, [prfmncRes]);
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={(e) => {}}>
조회
</Button>
<Button
size={"sm"}
onClick={() => {
onSave();
}}
>
저장
</Button>
<Button
size={"sm"}
onClick={() => {
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
tableData={bdstTable || []}
headlist={pbnstPrfmncHeadList}
pageSize={10}
total={10000}
headName={"하수재이용시설 목록"}
cellClick={(index: number | undefined, headId: string) => {
cellClick(index, headId);
}}
onPageChange={setPageNation}
children={undefined}
/>
</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">
{"하수처리수재이용 실적(m3) 등록결과"}
</h3>
</div>
<Table variant="secondary">
<TableHeader className="font-bold">
{headMakeprfmnc(monthHeadList, [])}
</TableHeader>
<TableBody>
{InputTableBody(inputData ?? [], monthHeadList, setInputData)}
</TableBody>
</Table>
</ScrollArea>
</ListDiv>
</div>
</ContentsDiv>
<UiModal
bodyClass={""}
body={<PbnPrfExcelModal data={isExcelOpen.data}></PbnPrfExcelModal>}
open={isExcelOpen.isModal}
onOpenChange={() => {
setIsExcelOPen({ isModal: false, data: {} as FcPrfType });
}}
></UiModal>
<Toaster position="top-center" />
</>
);
}
@@ -0,0 +1,187 @@
"use client";
import { useWrStore } from "@/app/store";
import { type rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn";
import type { rswtChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn";
import {
excelArrayDownload,
excelDownload,
yearOptions,
} from "@/components/lib/func/commom";
import ChkgdExcel from "@/components/ui/modal/chkgd/chkgdExcel/chkgdExcel";
import ChkgdModal from "@/components/ui/modal/chkgd/chkgdModal/chkgdModal";
import RainChkgdTable from "@/components/ui/table/chkgdTable/rainChkgd/rainChkgdTable";
import RswtChkgdTable from "@/components/ui/table/chkgdTable/rswtChkgd/rswtChkgdTable";
import {
ContentsDiv,
SearchDiv,
SearchFormLeft,
SearchFormRight,
SearchInput,
SelectBox,
Title,
UiModal,
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button, Label } from "@common/components/ui";
import { useCallback, useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
//-----------------------
export default function Page() {
const {
code,
rainChkSttn,
rswtChkSttn,
rainChkSttnInit,
rainChkSttnSearch,
rswtChkSttnInit,
isRainSttn,
isRswtSttn
} = useWrStore((state) => {
return state;
});
const [selFcltDiv, setSelFcltDiv] = useState("RNB");
const [isModal, setIsModal] = useState({
open: false,
data: {},
});
const [searchYear, setSearchYear] = useState<string>(String(new Date().getFullYear()));
const cellClick = () => {
if (searchYear) rainChkSttnSearch(searchYear, "0");
};
useEffect(() => {
if (!rainChkSttn.isInit) {
isRainSttn(true)
rainChkSttnInit( "0");
setIsModal({ data: {}, open: false });
}
}, [rainChkSttn.isInit, rainChkSttnInit]);
useEffect(() => {
if (!rswtChkSttn.isInit) {
setIsModal({ data: {}, open: false });
rswtChkSttnInit( "0");
isRswtSttn(true)
}
},[rswtChkSttn.isInit, rswtChkSttnInit])
const handleClick = useCallback(
(data: any) => {
if (data) setIsModal({ open: !isModal.open, data: data });
},
[isModal]
);
const excelDown=() =>{
if(rainChkSttn.sttnExcelList && selFcltDiv === "RNB"){
excelDownload(
rainChkSttn.sttnExcelList,
"빗물이용시설 지도점검 현황",
"sample_rainChkSttn.xlsx",
"A1:Q2",
3
);
}else if(rswtChkSttn.sttnExcelList && selFcltDiv === "RST"){
excelDownload(
rswtChkSttn.sttnExcelList,
"중수도시설 지도점검 현황",
"sample_rswtChkSttn.xlsx",
"A1:X2",
3
);
}
}
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>
<SelectBox
className={"w-full h-full text-2xl"}
label={""}
selectClass={""}
selectArray={rainChkSttn.fcltDiv}
onSelectValue={(val: string | number) =>
setSelFcltDiv(String(val))
}
value={selFcltDiv ?? rainChkSttn.fcltDiv[0]?.val}
/>
</div>
</SearchFormLeft>
<SearchFormRight>
<div className="space-y">
<div className="flex flex-row space-x-2">
<Button
size={"sm"}
onClick={(e) => {
cellClick();
}}
>
조회
</Button>
<Button color="green" size={"sm"} onClick={(e) =>{excelDown()}}>
다운로드
</Button>
</div>
</div>
</SearchFormRight>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
{selFcltDiv === "RNB" ? (
<RainChkgdTable
deleteData={() => {}}
detailUp={() => {}}
handleClick={handleClick}
rainChkData={rainChkSttn.rainChkRes}
/>
) : (
<RswtChkgdTable
detaiRswtlUpdate={() => {}}
deleteRswtData={() => {}}
handleRswtClick={handleClick}
rswtChkData={rswtChkSttn.rswtChkRes}
/>
)}
</ListDiv>
</div>
</div>
<UiModal
open={isModal.open}
onOpenChange={() => {
setIsModal({ open: !open, data: {} });
}}
bodyClass={"w-[80vw] max-w-none"}
body={<ChkgdModal type={selFcltDiv} obj={isModal.data} />}
></UiModal>
<Toaster position="top-center" />
</ContentsDiv>
);
}
@@ -0,0 +1,650 @@
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import { initValInUsage, initValOutUsage, subTotalObj, totalObj, type FcPrfType, type PrfType } from "@/app/store/prfmncReg/pbnstPrfmncReg/type";
import { excelPrfmncSttnParsing } from "@/app/store/prfmncSttn/pbnstPrfmncSttn/excel";
import { excelDownload, yearOptions } from "@/components/lib/func/commom";
import SearchInputText from "@/components/ui/searchInput/searchInput";
import { CHART_FORM, ContentsDiv, MainChart, ScrollArea, SearchBaseForm, SearchInput, SelectBox, Title, UiTable, type ChartConfig, type ReturnType } from "@common/business_components";
import ListDiv from "@common/business_components/ui/list_div";
import { Button, Label } from "@common/components/ui";
import { useCallback, useEffect, useRef, useState } from "react";
import toast, { Toaster } from "react-hot-toast";
export default function PbnstPrfmncSttn() {
const {
code,
tableHeadMaker,
pbnstPrfmncSttn,
pbnstPrfmncInit,
pbnstPrfmncSearch,
prfmnc,
pbnstSttn,
pbnNmSearch
} = useWrStore((state) => state);
const { monthHeadList } = prfmnc
const { pbnstPrfHeadList, prfmncRes, rawData, selectYearList } = pbnstPrfmncSttn;
const [isChHead, setIsChHead] = useState(false);
const [fromDate, setFromDate] = useState<string>(String(new Date().getFullYear()));
const [toDate, setToDate] = useState<string>(String(new Date().getFullYear()));
const [year, setYear] = useState<string>(String(new Date().getFullYear()));
const [bdstTable, setbdstTable] = useState<FcPrfType[]>();
const ref = useRef<ReturnType>({} as ReturnType);
const [swtrmtFcltNm, setSwtrmtFcltNm] = useState<string>();
const [pbnRuseNm, setPbnRuseNm] = useState<string>("");
const [searchYear, setSearchYear] = useState<string>(
String(new Date().getFullYear())
);
const [excelData, setExcelData] = useState<any[]>([]);
const excelClick = useCallback(() => {
excelDownload(
excelData,
"하수재이용실적 현황",
"sample_pbnstPrfmncSttn.xlsx",
"A1:N1",
2
);
}, [excelData]);
const [chartConfig, setChartConfig] = useState<ChartConfig>({});
const [chartData, setChartData] = useState<dnChartForm[]>([]);
const [dnInUsage, setDnInUsage] = useState<dnChartForm[]>([]);
const [dnInChartConfig, setDnInChartConfig] = useState<ChartConfig>({});
const [dnOutUsage, setDnOutUsage] = useState<dnChartForm[]>([]);
const [dnOutChartConfig, setDnOutChartConfig] = useState<ChartConfig>({});
const [barData, setBarData] = useState<barChartForm[]>([]);
const [barChartConfig, setBarChartConfig] = useState<ChartConfig>({});
const [prfData, setPrfData] = useState<any[]>();
const [lnInChartConfig, setLnInChartConfig] = useState<ChartConfig>({});
const [lnOutChartConfig, setLnOutChartConfig] = useState<ChartConfig>({});
const [inLineData, setInLineData] = useState<{
chartData1: lineChartDataProps[];
chartData2: lineChartDataProps[];
chartData3: lineChartDataProps[];
chartData4: lineChartDataProps[];
chartData5: lineChartDataProps[];
chartData6: lineChartDataProps[];
chartData7: lineChartDataProps[];
chartData8: lineChartDataProps[];
chartData9: lineChartDataProps[];
}>();
const [outLineData, setOutLineData] = useState<{
chartData1: lineChartDataProps[];
chartData2: lineChartDataProps[];
chartData3: lineChartDataProps[];
chartData4: lineChartDataProps[];
chartData5: lineChartDataProps[];
chartData6: lineChartDataProps[];
}>();
type dnChartForm = { label: string, val: number, fill?: string };
type barChartForm = { label: string, "장내용수": number, "장외용수": number };
type lineChartDataProps = { label: string, val: number, color: string };
const prfTableData = (prfList: PrfType[], year: string) => {
const inUsageData = structuredClone(initValInUsage);
const outUsageData = structuredClone(initValOutUsage);
const inSubtotal = structuredClone(subTotalObj);
const outSubtotal = structuredClone(subTotalObj);
const prfFilter = prfList?.filter((e) => e.ym.slice(0, 4) === year)
if (prfList && prfFilter.length > 0) {
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];
setPrfData(tableData);
setExcelData(excelPrfmncSttnParsing(prfData ?? []))
} else {
setPrfData([]);
}
}
const [chartId, setChartId] = useState<string>();
useEffect(() => {
// 누적 변수 초기화
let wshwtr = 0,
coolUswtr = 0,
cleanUswtr = 0,
drwtUswtr = 0,
dltnUswtr = 0,
ithlRswtr = 0,
ithlEtcUswtr = 0,
cleanToilUswtr = 0,
resn = 0;
let lndwtr = 0,
hydUswtr = 0,
ugwtChr = 0,
farmUswtr = 0,
rvrKeepUswtr = 0,
indstUswtr = 0;
let inUsageSum = 0,
outUsageSum = 0;
let inUsageArr: number[] = [],
outUsageArr: number[] = [];
// 라인차트용 데이터
const wshwtrData: lineChartDataProps[] = [],
coolUswtrData: lineChartDataProps[] = [],
cleanUswtrData: lineChartDataProps[] = [],
drwtUswtrData: lineChartDataProps[] = [],
dltnUswtrData: lineChartDataProps[] = [],
ithlRswtrData: lineChartDataProps[] = [],
ithlEtcUswtrData: lineChartDataProps[] = [],
cleanToilUswtrData: lineChartDataProps[] = [],
resnData: lineChartDataProps[] = [];
const lndwtrData: lineChartDataProps[] = [],
hydUswtrData: lineChartDataProps[] = [],
ugwtChrData: lineChartDataProps[] = [],
farmUswtrData: lineChartDataProps[] = [],
rvrKeepUswtrData: lineChartDataProps[] = [],
indstUswtrData: lineChartDataProps[] = [];
// 막대차트 데이터
const barData: barChartForm[] = [];
// 도넛차트 데이터
const dnData: dnChartForm[] = [];
const dnInData: dnChartForm[] = [];
const dnOutData: dnChartForm[] = [];
if (rawData) {
prfTableData([], year)
rawData.forEach((item) => {
// 실적 테이블 데이터
if (chartId){
if(item.prfList?.[0]?.ym.slice(0, 4) === year && item.prfList?.[0]?.pbnstRuseFcltFk === chartId){
prfTableData(item.prfList, year);
}
item.prfList.filter((e) => e.ym.slice(0, 4) === year && e.pbnstRuseFcltFk === chartId).forEach((element) => {
// 누적
wshwtr += element.wshwtr;
coolUswtr += element.coolUswtr;
cleanUswtr += element.cleanUswtr;
drwtUswtr += element.drwtUswtr;
dltnUswtr += element.dltnUswtr;
ithlRswtr += element.ithlRswtr;
ithlEtcUswtr += element.ithlEtcUswtr;
cleanToilUswtr += element.cleanToilUswtr;
resn += element.resn;
lndwtr += element.lndwtr;
hydUswtr += element.hydUswtr;
ugwtChr += element.ugwtChr;
farmUswtr += element.farmUswtr;
rvrKeepUswtr += element.rvrKeepUswtr;
indstUswtr += element.indstUswtr;
// 월별 합계
inUsageSum = element.wshwtr
+ element.coolUswtr
+ element.cleanUswtr
+ element.drwtUswtr
+ element.dltnUswtr
+ element.ithlRswtr
+ element.ithlEtcUswtr
+ element.cleanToilUswtr
+ element.resn;
outUsageSum = element.lndwtr
+ element.hydUswtr
+ element.ugwtChr
+ element.farmUswtr
+ element.rvrKeepUswtr
+ element.indstUswtr;
inUsageArr.push(inUsageSum);
outUsageArr.push(outUsageSum);
// 막대차트
const month = Number(element.ym.slice(4, 6));
barData.push({ label: `${month}월`, "장내용수": inUsageSum, "장외용수": outUsageSum });
// 라인차트
wshwtrData.push({ label: `${month}월`, val: element.wshwtr, color: "red" });
coolUswtrData.push({ label: `${month}월`, val: element.coolUswtr, color: "orange" });
cleanUswtrData.push({ label: `${month}월`, val: element.cleanUswtr, color: "yellow" });
drwtUswtrData.push({ label: `${month}월`, val: element.drwtUswtr, color: "pink" });
dltnUswtrData.push({ label: `${month}월`, val: element.dltnUswtr, color: "purple" });
ithlRswtrData.push({ label: `${month}월`, val: element.ithlRswtr, color: "green" });
ithlEtcUswtrData.push({ label: `${month}월`, val: element.ithlEtcUswtr, color: "blue" });
cleanToilUswtrData.push({ label: `${month}월`, val: element.cleanToilUswtr, color: "magenta" });
resnData.push({ label: `${month}월`, val: element.resn, color: "skyblue" });
lndwtrData.push({ label: `${month}월`, val: element.lndwtr, color: "red" });
hydUswtrData.push({ label: `${month}월`, val: element.hydUswtr, color: "orange" });
ugwtChrData.push({ label: `${month}월`, val: element.ugwtChr, color: "yellow" });
farmUswtrData.push({ label: `${month}월`, val: element.farmUswtr, color: "green" });
rvrKeepUswtrData.push({ label: `${month}월`, val: element.rvrKeepUswtr, color: "blue" });
indstUswtrData.push({ label: `${month}월`, val: element.indstUswtr, color: "purple" });
});
}
});
// 도넛차트 데이터
dnData.push({ label: "세척수", val: wshwtr, fill: "red" });
dnData.push({ label: "냉각수", val: coolUswtr, fill: "orange" });
dnData.push({ label: "청소수", val: cleanUswtr, fill: "yellow" });
dnData.push({ label: "식수대", val: drwtUswtr, fill: "green" });
dnData.push({ label: "희석용수", val: dltnUswtr, fill: "skyblue" });
dnData.push({ label: "중수도", val: ithlRswtr, fill: "blue" });
dnData.push({ label: "기타", val: ithlEtcUswtr, fill: "purple" });
dnData.push({ label: "청소화장실용수", val: cleanToilUswtr, fill: "red" });
dnData.push({ label: "세척살수용수", val: resn, fill: "orange" });
dnData.push({ label: "조경용수", val: lndwtr, fill: "yellow" });
dnData.push({ label: "친수용수", val: hydUswtr, fill: "green" });
dnData.push({ label: "지하수충전", val: ugwtChr, fill: "skyblue" });
dnData.push({ label: "농업용수", val: farmUswtr, fill: "blue" });
dnData.push({ label: "하천등유지용수", val: rvrKeepUswtr, fill: "purple" });
dnData.push({ label: "공업용수", val: indstUswtr, fill: "black" });
// 장내용수 도넛
dnInData.push({ label: "세척수", val: wshwtr, fill: "yellow" });
dnInData.push({ label: "냉각수", val: coolUswtr, fill: "green" });
dnInData.push({ label: "청소수", val: cleanUswtr, fill: "yellow" });
dnInData.push({ label: "식수대", val: drwtUswtr, fill: "green" });
dnInData.push({ label: "희석용수", val: dltnUswtr, fill: "yellow" });
dnInData.push({ label: "중수도", val: ithlRswtr, fill: "green" });
dnInData.push({ label: "기타", val: ithlEtcUswtr, fill: "yellow" });
dnInData.push({ label: "청소화장실용수", val: cleanToilUswtr, fill: "green" });
dnInData.push({ label: "세척살수용수", val: resn, fill: "yellow" });
// 장외용수 도넛
dnOutData.push({ label: "조경용수", val: lndwtr, fill: "yellow" });
dnOutData.push({ label: "친수용수", val: hydUswtr, fill: "black" });
dnOutData.push({ label: "지하수충전", val: ugwtChr, fill: "yellow" });
dnOutData.push({ label: "농업용수", val: farmUswtr, fill: "black" });
dnOutData.push({ label: "하천등유지용수", val: rvrKeepUswtr, fill: "yellow" });
dnOutData.push({ label: "공업용수", val: indstUswtr, fill: "black" });
// 라인차트 데이터
setInLineData({
chartData1: wshwtrData,
chartData2: coolUswtrData,
chartData3: cleanUswtrData,
chartData4: drwtUswtrData,
chartData5: dltnUswtrData,
chartData6: ithlRswtrData,
chartData7: ithlEtcUswtrData,
chartData8: cleanToilUswtrData,
chartData9: resnData
});
setOutLineData({
chartData1: lndwtrData,
chartData2: hydUswtrData,
chartData3: ugwtChrData,
chartData4: farmUswtrData,
chartData5: rvrKeepUswtrData,
chartData6: indstUswtrData,
});
setBarData(barData);
setChartData(dnData);
setDnInUsage(dnInData);
setDnOutUsage(dnOutData);
}
}, [rawData, year, chartId]);
useEffect(() => {
const newChartConfig = chartData.reduce((config, element) => {
config[element.label] = {
label: element.label,
fill: element.fill
};
return config;
}, {} as Record<string, { label: string; fill?: string }>) satisfies ChartConfig;
setChartConfig(newChartConfig);
}, [chartData]);
useEffect(() => {
const newChartConfig = dnInUsage.reduce((config, element) => {
config[element.label] = {
label: element.label,
fill: element.fill
};
return config;
}, {} as Record<string, { label: string; color: string; }>) satisfies ChartConfig;
setDnInChartConfig(newChartConfig);
}, [dnInUsage]);
useEffect(() => {
const newChartConfig = dnOutUsage.reduce((config, element) => {
config[element.label] = {
label: element.label,
fill: element.fill
};
return config;
}, {} as Record<string, { label: string; color: string; }>) satisfies ChartConfig;
setDnOutChartConfig(newChartConfig);
}, [dnOutUsage]);
useEffect(() => {
const newChartConfig = barData.reduce((config, element) => {
config[element.label] = {
label: element.label,
};
return config;
}, {} as Record<string, { label: string }>) satisfies ChartConfig;
setBarChartConfig(newChartConfig);
}, [barData]);
useEffect(() => {
if (inLineData?.chartData1) {
const newChartConfig = {
chartData1: {
label: '세척수',
color: "red",
},
chartData2: {
label: '냉각수',
color: "orange",
},
chartData3: {
label: '청소수',
color: "yellow",
},
chartData4: {
label: '식수대',
color: "pink",
},
chartData5: {
label: '희석용수',
color: "purple",
},
chartData6: {
label: '중수도',
color: "green",
},
chartData7: {
label: '기타',
color: "blue",
},
chartData8: {
label: '청소화장실용수',
color: "magenta",
},
chartData9: {
label: '세척살수용수',
color: "skyblue",
},
} satisfies ChartConfig;
setLnInChartConfig(newChartConfig);
}
}, [inLineData]);
useEffect(() => {
if (outLineData?.chartData1) {
const newChartConfig = {
chartData1: {
label: '조경용수',
color: "red",
},
chartData2: {
label: '친수용수',
color: "orange",
},
chartData3: {
label: '지하수충전',
color: "yellow",
},
chartData4: {
label: '농업용수',
color: "green",
},
chartData5: {
label: '하천등유지용수',
color: "blue",
},
chartData6: {
label: '공업용수',
color: "purple",
},
} satisfies ChartConfig;
setLnOutChartConfig(newChartConfig);
}
}, [outLineData]);
useEffect(() => {
const returnType: ReturnType = {
sidoValue: "0",
sigunValue: "0",
partValue: "A",
regionValue: "0",
unitWaterShedValue: "",
middleRegionValue: "",
envPartValue: "",
sidoText: "",
sigunText: ""
}
tableHeadMaker(Number(searchYear), Number(searchYear));
pbnstPrfmncSearch(returnType, "", searchYear, searchYear)
}, []);
useEffect(() => {
setbdstTable(prfmncRes);
if(prfmncRes?.[0]?.pbnstRuseFcltPk) setChartId(prfmncRes[0].pbnstRuseFcltPk)
}, [prfmncRes]);
useEffect(() => {
if (pbnRuseNm.length > 1)
pbnNmSearch("1", "23", ref.current, pbnRuseNm, searchYear);
}, [pbnRuseNm]);
const cellClick = (index: number | undefined, headId: string) => {
if (index !== undefined && headId !== undefined) {
setChartId(prfmncRes[index].pbnstRuseFcltPk)
}
}
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4 ">
<div className="col-span-4">
<Title title={"하수재이용실적 현황"} />
<SearchBaseForm
selectSidoData={code.cityCd}
selectSigunData={code.sggCd}
selectRegionData={code.rvbsnCd}
selectUnitWaterShedData={code.lgbsnCd}
selectMiddleRegionData={code.mdmbsnCd}
selectEnvPartData={code.lclgvrnmntCd}
rightChildren={<Button
className={btnClass}
onClick={() => {
setIsChHead(true);
}}
>
조회항목설정
</Button>}
leftChildren={<div className="col-span-5">
<div className="flex flex-row">
<div className="flex flex-row items-center">
<Label className="text-xl text-gray-600">하수 재이용년도</Label>
<SelectBox
className="h-full text-2xl"
label=""
selectClass={""}
selectArray={yearOptions}
value={fromDate}
onSelectValue={(val: string | number) => setFromDate(String(val))} />
<SelectBox
className="h-full text-2xl"
label=""
selectClass={""}
selectArray={yearOptions}
value={toDate}
onSelectValue={(val: string | number) => setToDate(String(val))} />
</div>
<SearchInputText
label={"하수처리시설"}
initValue={pbnRuseNm ?? ""}
setValue={(searchNm?: string) => {
setPbnRuseNm(searchNm || "");
}}
setRtnData={function (rtnData: any[]): void {
// setbdstTable(rtnData);
}}
searchList={pbnstSttn.pbnstSearchData || []}
></SearchInputText>
{/* <SelectBox
className="h-full text-2xl"
label="재이용시설명"
selectClass={""}
selectArray={[]}
value={""}
onSelectValue={() => { }} /> */}
</div>
</div>}
queryClick={function (returnType: ReturnType): void {
pbnstPrfmncSearch(returnType, pbnRuseNm ?? "", fromDate, toDate);
if (fromDate && toDate) {
const fromNum = Number(fromDate);
const toNum = Number(toDate);
if (fromNum > toNum) {
toast.error("시작년도가 종료년도 이후로 설정할 수 없습니다.");
} else {
if (toNum - fromNum > 5) {
toast.error("최대 5년까지 선택 가능합니다.");
} else {
tableHeadMaker(fromNum, toNum);
}
}
}
}}
excelClick={excelClick}
initClick={function (): void { }}
btnClass={btnClass}
ref={ref} isAdmin={false} />
</div>
</div>
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-6">
<ListDiv>
<UiTable
headName={[]}
tableData={bdstTable || []}
headlist={pbnstPrfHeadList}
pageSize={20}
total={10000}
cellClick={(index: number | undefined, headId: string) => {
cellClick(index ?? undefined, headId);
}}
onPageChange={() => { }
}
index={0}
/>
<hr />
<h3 className="mt-4 ml-2 text-2xl font-medium text-label">하수재이용실적 상세현황</h3>
<SelectBox
className="h-full w-1/12 text-2xl"
label=""
selectClass={""}
selectArray={selectYearList}
value={year}
onSelectValue={(val: string | number) => setYear(String(val))} />
<h1 className="">장내·외 용도별 하수재이용실적 현황(계)</h1>
<div className="flex">
<div className="w-1/3">
<MainChart chartConfig={chartConfig} chartData={chartData} chartTitle={"장내·외 용수 총 실적"} chartForm={CHART_FORM.DN} />
</div>
<div className="w-1/3">
<MainChart chartConfig={dnInChartConfig} chartData={dnInUsage} chartTitle={"장내용수 실적"} chartForm={CHART_FORM.DN} />
</div>
<div className="w-1/3">
<MainChart chartConfig={dnOutChartConfig} chartData={dnOutUsage} chartTitle={"장외용수 실적"} chartForm={CHART_FORM.DN} />
</div>
</div>
<h1 className="">장내·외 월별 하수재이용실적 현황</h1>
<div className="flex">
<div className="w-1/3">
<MainChart chartConfig={barChartConfig} chartData={barData} chartTitle={"월별 장내·외 용수 총 실적"} chartForm={CHART_FORM.DOUBLEBAR} />
</div>
<div className="w-1/3">
<MainChart chartConfig={lnInChartConfig} chartData={inLineData} chartTitle={"월별 장내 용수 실적"} chartForm={CHART_FORM.LINE} />
</div>
<div className="w-1/3">
<MainChart chartConfig={lnOutChartConfig} chartData={outLineData} chartTitle={"월별 장외 용수 총 실적"} chartForm={CHART_FORM.LINE} />
</div>
</div>
<h1 className="">하수재이용실적 현황</h1>
<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>
<UiTable
headName={undefined}
tableData={prfData || []}
headlist={monthHeadList}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={function (page: number): void {
throw new Error("Function not implemented.");
}}>
</UiTable>
</ScrollArea>
</ListDiv>
</ListDiv>
</div>
</div>
</ContentsDiv>
<Toaster position="top-center" />
</>
)
}
+74
View File
@@ -0,0 +1,74 @@
'use client'
import { useWrStore } from "@/app/store";
import { yearOptions } from "@/components/lib/func/commom";
import { ContentsDiv, Title, SearchDiv, SearchFormLeft, SelectBox, UiTable } from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components/ui";
import { useState } from "react";
export default function MatStat(){
const { code, matStat } = useWrStore((state) => {
return state;
});
const [pageNation, setPageNation] = useState(1);
const [searchYear, setSearchYear] = useState<string>(
String(new Date().getFullYear())
);
return(
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<Title title={"재이용 통계"} />
<SearchDiv>
<SearchFormLeft>
<SelectBox
className="w-full h-full text-2xl"
label="통계년도"
selectClass={""}
selectArray={yearOptions}
value={searchYear}
onSelectValue={(val: string | number) =>
setSearchYear(String(val))
}
/>
<div className="flex flex-row space-x-2 items-center">
<Button className="" size={"sm"} onClick={(e) => {}}>
조회
</Button>
<Button className="" size={"sm"} onClick={(e) => {}}>
다운로드
</Button>
<Button className="" size={"sm"} onClick={(e) => {}}>
전체통계다운로드
</Button>
</div>
</SearchFormLeft>
{/* <SearchFormRight>
</SearchFormRight> */}
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4">
<div className="col-span-6 h-full min-h-0">
<ListDiv className="min-h-0">
{/* <ScrollArea className="h-[60vh]"> */}
<UiTable
tableData={[]}
headlist={matStat.matStatHeadList}
pageSize={20}
total={10000}
headName={"건축물 목록"}
cellClick={(val, headId) => {}}
onPageChange={setPageNation}
></UiTable>
{/* </ScrollArea> */}
</ListDiv>
</div>
</div>
</ContentsDiv>
</>
)
}
+275
View File
@@ -0,0 +1,275 @@
"use client";
import { useWrStore } from "@/app/store";
import type { RainStatProps } from "@/app/store/stats/rainStat";
import { excelDownload, tableData, yearOptions } from "@/components/lib/func/commom";
import { downloadExcel } from "@common/business_components";
import {
ContentsDiv,
ScrollArea,
SearchDiv,
SelectBox,
Title,
UiTable
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components/ui";
import { useEffect, useState } from "react";
export default function RainStat() {
const { code, rainStat, searchRainStatList } = useWrStore((state) => state);
const { rainStatList, excelList, rainDetailList } = rainStat;
const [searchYear, setSearchYear] = useState<string>(
String(new Date().getFullYear())
);
const [exData, setExData] = useState<Array<Record<string, string | number>>>();
const [bdstTable, setBdstTable] = useState<RainStatProps[]>();
useEffect(() => {
searchRainStatList(searchYear);
}, [code.cityCd, code.sggCd, searchRainStatList, searchYear])
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 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;
}
// 시도별 상세 데이터 수집
if (sidoText) {
if (!sidoDetailMap.has(sidoText)) {
sidoDetailMap.set(sidoText, []);
}
sidoDetailMap.get(sidoText)!.push(item as unknown as (string | number)[]);
}
// 시도별 합계 데이터 수집
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);
}
});
// 시도별 합계 계산
rainDetailList.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){
sidoData[i] = '합계';
} else if(i == 3){
// 해당 시도의 데이터 개수를 계산
const sidoDataCount = rainDetailList.filter((data: unknown[]) =>
Array.isArray(data) && data.length > 0 && String(data[0]) === sidoText
).length;
sidoData[i] = sidoDataCount;
} else if( i == 4){
sidoData[i] = '';
} else if(i == 6){
// 법정 대상 건축물 개수 (인덱스 6이 'Y'인 경우)
const bumCnt = rainDetailList.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;
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 {
sidoData[i] = '';
}
}
}
});
// 시도별로 합계와 상세 데이터를 순서대로 배치
const summaryExcelData: (string | number)[][] = [];
// 시도별로 순회하면서 합계와 상세 데이터를 추가
Array.from(sidoList).forEach((sidoText) => {
const sidoSummary = sidoDataMap.get(sidoText);
const sidoDetails = sidoDetailMap.get(sidoText) || [];
if (sidoSummary) {
// 시도 합계 데이터 추가
summaryExcelData.push(sidoSummary);
// 해당 시도의 상세 데이터들 추가
sidoDetails.forEach(detail => {
summaryExcelData.push(detail);
});
}
});
const sidoSummaryList = Array.from(sidoDataMap.values());
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 (sidoTotalSummary[0] && index < sidoTotalSummary[0].length) {
sidoTotalSummary[0][index] = Number(sidoTotalSummary[0][index]) + Number(value);
}
}
});
});
// sidoSummaryList와 rainDetailList를 합쳐서 엑셀 데이터 생성
const excelData = [...sidoTotalSummary, ...sidoSummaryList, ...summaryExcelData];
excelDownload(
excelData as unknown as [][],
"빗물이용시설 통계",
"sample_rainStats.xlsx",
"A1:V3",
4
);
}
const excelClick = () => {
downloadExcel({
data: (exData as unknown as JSON[]) ?? [],
fileName: "재이용통계",
sheetNameArray: ["Sheet1"],
headerRange: "A1:M1"
})
}
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(() => {
const transData = Array.isArray(rainStatList) ? rainStatList : [rainStatList];
const data = tableData(transData, { code });
const tbData = Array.isArray(data)
? data.map((item: RainStatProps) => {
return {
...item,
ctpvCd: item.cityText
};
})
: [];
setBdstTable(tbData);
}, [code, rainStatList]);
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<Title title={"빗물이용시설 통계"} />
<SearchDiv>
<div className="grid grid-cols-12 gap-5 m-4">
<div className="col-span-2">
<SelectBox
className="w-full h-full text-2xl"
label="통계년도"
selectClass={""}
selectArray={yearOptions}
value={searchYear}
onSelectValue={(val: string | number) =>
setSearchYear(String(val))
}
/>
</div>
<div className="flex flex-row space-x-2 items-center">
<Button className="" size={"sm"} onClick={() => { }}>
조회
</Button>
<Button className="" size={"sm"} onClick={() => excelClick()}>
다운로드
</Button>
<Button className="" size={"sm"} onClick={() => excelDetailDownLoad()}>
전체통계다운로드
</Button>
</div>
</div>
</SearchDiv>
{/* <SearchFormRight>
</SearchFormRight> */}
</div>
</div>
<div className="grid grid-cols-6 gap-4">
<div className="col-span-6 h-full min-h-0">
<ListDiv className="">
<ScrollArea className="h-[67vh]">
<UiTable
tableData={bdstTable || []}
headlist={rainStat.rainStatHeadList}
pageSize={10}
total={0}
headName={""}
cellClick={undefined}
onPageChange={() => {}}
></UiTable>
</ScrollArea>
</ListDiv>
</div>
</div>
</ContentsDiv>
</>
);
}
+289
View File
@@ -0,0 +1,289 @@
"use client";
import { useWrStore } from "@/app/store";
import type { RswtStatProps } from "@/app/store/stats/rswtStat";
import { excelDownload, tableData, yearOptions } from "@/components/lib/func/commom";
import {
ContentsDiv,
downloadExcel,
ScrollArea,
SearchDiv,
SelectBox,
Title,
UiTable
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components/ui";
import { useEffect, useState } from "react";
export default function RswtStat() {
const { code, rswtStat, searchRswtStatList } = useWrStore((state) => state);
const { rswtStatList, excelList, rswtDetailList } = rswtStat;
const [rswtTable, setRswtTable] = useState<RswtStatProps[]>();
const [searchYear, setSearchYear] = useState<string>(
String(new Date().getFullYear())
);
const [excelData, setExceData] = useState<Record<string, string | number>[]>();
useEffect(() => {
searchRswtStatList(searchYear)
}, [searchRswtStatList, searchYear])
const excelClick = () => {
downloadExcel({
data: (excelData as unknown as JSON[]) ?? [],
fileName: "중수도재이용통계",
sheetNameArray: ["Sheet1"],
headerRange: "A1:O1"
})
}
useEffect(() => {
const transData = Array.isArray(rswtStatList) ? rswtStatList : [rswtStatList];
const data = tableData(transData, { code });
const tbData = Array.isArray(data)
? data.map((item: RswtStatProps) => {
return {
...item,
ctpvCd: item.cityText
};
})
: [];
setRswtTable(tbData);
}, [code, rswtStatList])
useEffect(() => {
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,
};
}) : [];
setExceData(tbData);
}, [code, excelList])
const excelDetailDownLoad=() =>{
const sidoList = new Set<string>();
const sidoDataMap = new Map<string, (string | number)[]>(); // 시도별 데이터를 저장할 Map
const sidoDetailMap = new Map<string, (string | number)[][]>(); // 시도별 상세 데이터를 저장할 Map
// 먼저 시도별 상세 데이터를 그룹화
rswtDetailList.forEach((item: RswtStatProps[]) => {
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 RswtStatProps;
}
if (item.length > 1) {
item[1] = sigunText as unknown as RswtStatProps;
}
if (item.length > 2) {
item[2] = sidoText+' '+sigunText as unknown as RswtStatProps;
}
// 시도별 상세 데이터 수집
if (sidoText) {
if (!sidoDetailMap.has(sidoText)) {
sidoDetailMap.set(sidoText, []);
}
sidoDetailMap.get(sidoText)!.push(item as unknown as (string | number)[]);
}
// 시도별 합계 데이터 수집
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);
}
});
// 시도별 합계 계산
rswtDetailList.forEach((item: RswtStatProps[]) => {
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){
sidoData[i] = '합계';
} else if(i == 3){
// 해당 시도의 데이터 개수를 계산
const sidoDataCount = rswtDetailList.filter((data: unknown[]) =>
Array.isArray(data) && data.length > 0 && String(data[0]) === sidoText
).length;
sidoData[i] = sidoDataCount;
} else if( i == 4){
sidoData[i] = '';
} else if(i == 6){
// 법정 대상 건축물 개수 (인덱스 6이 'Y'인 경우)
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){
const value = Number(item[9]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
} else if(i==10){
const value = Number(item[10]) || 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==13){
const value = Number(item[13]) || 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 if(i==16){
const value = Number(item[16]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
} else {
sidoData[i] = '';
}
}
}
});
// 시도별로 합계와 상세 데이터를 순서대로 배치
const summaryExcelData: (string | number)[][] = [];
// 시도별로 순회하면서 합계와 상세 데이터를 추가
Array.from(sidoList).forEach((sidoText) => {
const sidoSummary = sidoDataMap.get(sidoText);
const sidoDetails = sidoDetailMap.get(sidoText) || [];
if (sidoSummary) {
// 시도 합계 데이터 추가
summaryExcelData.push(sidoSummary);
// 해당 시도의 상세 데이터들 추가
sidoDetails.forEach(detail => {
summaryExcelData.push(detail);
});
}
});
const sidoSummaryList = Array.from(sidoDataMap.values());
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 (sidoTotalSummary[0] && index < sidoTotalSummary[0].length) {
sidoTotalSummary[0][index] = Number(sidoTotalSummary[0][index]) + Number(value);
}
}
});
});
// sidoSummaryList와 rainDetailList를 합쳐서 엑셀 데이터 생성
const excelData = [...sidoTotalSummary,...sidoSummaryList, ...summaryExcelData];
excelDownload(
excelData as unknown as [][],
"중수도시설 통계",
"sample_rswtStats.xlsx",
"A1:Q3",
4
);
}
return (<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<Title title="중수도시설 통계" />
<SearchDiv>
<div className="grid grid-cols-12 gap-5 m-4">
<div className="col-span-2">
<SelectBox
className="w-full h-full text-2xl"
label="통계년도"
selectClass=""
selectArray={yearOptions}
value={searchYear}
onSelectValue={(val: string | number) => setSearchYear(String(val))}
/>
</div>
<div className="flex flex-row space-x-2 items-center">
<Button
className=""
size="sm"
onClick={() => {
searchRswtStatList(searchYear)
}}
>
조회
</Button>
<Button
className=""
size="sm"
onClick={() => excelClick()}
>
다운로드
</Button>
<Button
className=""
size="sm"
onClick={() => { excelDetailDownLoad() }}
>
전체통계다운로드
</Button>
</div>
</div>
</SearchDiv>
</div>
</div>
<div className="grid grid-cols-6 gap-4">
<div className="col-span-6 h-full min-h-0">
<ListDiv className="">
<ScrollArea className="h-[67vh]">
<UiTable
tableData={rswtTable || []}
headlist={rswtStat.rswtStatHeadList}
pageSize={10}
total={0}
headName=""
cellClick={undefined}
onPageChange={() => { }}
/>
</ScrollArea>
</ListDiv>
</div>
</div>
</ContentsDiv>
</>
);
}
+370
View File
@@ -0,0 +1,370 @@
import { getFetch } from "@/components/lib/api";
import type { EnvPartSelectDataType, SelectDataType } from "@common/business_components/ui";
export const btnClass = "p-4 m-2 text-white rounded-sm text-lg font-medium "
const yn: SelectDataType[] = [
{ val: 'Y', text: 'Y' },
{ val: 'N', text: 'N' },
]
//공통 건축물 용도
const bdstUsgCd: SelectDataType[] = [
{ val: '-1', text: "확인불가" },
{ val: '1', text: "운동장" },
{ val: '2', text: "체육관" },
{ val: '3', text: "공공업무시설" },
{ val: '4', text: "공공기관의청사" },
{ val: '5', text: "아파트" },
{ val: '6', text: "연립주택" },
{ val: '7', text: "다세대주택" },
{ val: '8', text: "기숙사" },
{ val: '9', text: "초등학교" },
{ val: '10', text: "중학교" },
{ val: '11', text: "고등학교" },
{ val: '12', text: "전문대학" },
{ val: '13', text: "대학및대학교" },
{ val: '14', text: "골프장" },
{ val: '15', text: "대규모점포" },
{ val: '16', text: "기타" },
];
//빗물 집수면 종류 용도
// const rainFcltCd = [
// { val: "1", text: "지붕" },
// { val: "2", text: "건물옥상" },
// { val: "3", text: "골프장 연못" },
// { val: "4", text: "운동장 바닥" },
// { val: "5", text: "운동장 지붕" },
// { val: "6", text: "주차장" },
// { val: "7", text: "태양광패널" },
// { val: "8", text: "연못" },
// { val: "9", text: "기타" },
// { val: "10", text: "확인불가" },
// ];
// 중수도 필수 원수종류
const rswtBdstType: SelectDataType[] = [
{ text: "숙박업", val: "17" },
{ text: "목욕장업", val: "18" },
{ text: "공장", val: "19" },
{ text: "발전시설", val: "20" },
{ text: "관광단지개발사업", val: "21" },
{ text: "도시개발사업", val: "22" },
{ text: "산업단지개발사업", val: "23" },
{ text: "택지개발사업", val: "24" },
{ text: "대규모점포(대형마트)", val: "25" },
{ text: "대규모점포(전문점)", val: "26" },
{ text: "대규모점포(백화점)", val: "27" },
{ text: "대규모점포(쇼핑센터)", val: "28" },
{ text: "대규모점포(복합쇼핑몰)", val: "29" },
{ text: "물류시설", val: "30" },
{ text: "운수시설(여객자동차터미널)", val: "31" },
{ text: "운수시설(철도시설)", val: "32" },
{ text: "운수시설(공항시설)", val: "33" },
{ text: "운수시설(항만시설)", val: "34" },
{ text: "업무시설(공공업무시설)", val: "35" },
{ text: "업무시설(금융업소)", val: "36" },
{ text: "업무시설(사무소)", val: "37" },
{ text: "업무시설(결혼상담소 등 소개업소)", val: "38" },
{ text: "업무시설(출판사)", val: "39" },
{ text: "업무시설(신문사)", val: "40" },
{ text: "업무시설(오피스텔)", val: "41" },
{ text: "교정시설", val: "42" },
{ text: "방송국", val: "43" },
{ text: "전신전화국", val: "44" },
{ text: "기타", val: "45" }
];
const orgwtKndCd = [
{ text: "오수(변기 오수 제외)", val: "1" },
{ text: "오수", val: "2" },
{ text: "폐수", val: "3" },
{ text: "오수 및 폐수", val: "4" },
{ text: "기타", val: "5" },
];
const chBuCd = [
{ val: "증축", text: "증축" },
{ val: "개축", text: "개축" },
{ val: "재축", text: "재축" },
]
const dmdUszCd = [
{ val: "조경용수", text: "조경용수" },
{ val: "청소화장실용수", text: "청소화장실용수" },
{ val: "농업용수", text: "농업용수" },
{ val: "공업용수", text: "공업용수" },
{ val: "친수용수", text: "친수용수" },
{ val: "기타", text: "기타" },
]
const ruseMngMtd = [
{ val: "자체운영", text: "자체운영" },
{ val: "공기업", text: "공기업" },
{ val: "민간(대행)", text: "민간(대행)" },
]
const pplQulity = [
{ val: "도복장강관", text: "도복장강관" },
{ val: "PE관", text: "PE관" },
{ val: "스테인레스관", text: "스테인레스관" },
{ val: "덕타일주철관", text: "덕타일주철관" },
{ val: "유리섬유복합관", text: "유리섬유복합관" },
{ val: "기타", text: "기타" },
]
const pplLenght = [
{ val: "D100", text: "D100" },
{ val: "D200", text: "D200" },
{ val: "D250", text: "D250" },
{ val: "D300", text: "D300" },
{ val: "D350", text: "D350" },
{ val: "D400", text: "D400" },
{ val: "D450", text: "D450" },
{ val: "D500", text: "D500" },
{ val: "D700", text: "D700" },
{ val: "D900", text: "D900" },
{ val: "D1000​", text: "D1000​" },
]
export const buildingType = {
RST:"RST",
RNB:"RNB",
HTB:"HTB"
}
const rainFcltCd = [
{ val: "지붕", text: "지붕" },
{ val: "건물옥상", text: "건물옥상" },
{ val: "골프장 연못", text: "골프장 연못" },
{ val: "운동장 바닥", text: "운동장 바닥" },
{ val: "운동장 지붕", text: "운동장 지붕" },
{ val: "주차장", text: "주차장" },
{ val: "태양광패널", text: "태양광패널" },
{ val: "연못", text: "연못" },
{ val: "기타", text: "기타" },
{ val: "확인불가", text: "확인불가" },
];
export type comCodeState = {
code: {
isInit: boolean;
chBuCd: SelectDataType[]
rainFcltCd: SelectDataType[];
bdstUsgCd: SelectDataType[];
cityCd: SelectDataType[];
sggCd: SelectDataType[];
rvbsnCd: SelectDataType[];
mdmbsnCd: SelectDataType[];
lgbsnCd: SelectDataType[];
lclgvrnmntCd: EnvPartSelectDataType[];
orgwtKndCd: SelectDataType[];
yn: SelectDataType[];
pplQulity: SelectDataType[];
pplLenght: SelectDataType[];
dmdUszCd:SelectDataType[]
buildingType: {
RST:string,
RNB:string,
HTB:string
}
ruseMngMtd:SelectDataType[]
};
};
export type comCodeType = comCodeState & comCodeActions;
export const getSggCd = async (set: any) => {
const sgg = await getFetch("common", "/addr/sgg");
/* const sggCd = sgg.map((item: any) => ({
val: item.adstDstrCd,
text: item.gugun,
})); */
const sggCd = [
{ text: "전체", val: '0' },
...sgg
.map((item: any) => ({
text: item.gugun || '',
val: String(item.adstDstrCd) || ''
}))
];
set((state: comCodeState) => ({
code: {
...state.code,
sggCd: sggCd,
},
}));
};
export const getCityCd = async (set: any) => {
const city = await getFetch("common", "/addr/city");
const cityCd = city.map((item: any) => ({
val: item.adstDstrCd,
text: item.sido,
}));
cityCd.unshift({ val: '0', text: '전체' })
set((state: comCodeState) => ({
code: {
...state.code,
cityCd: cityCd,
},
}));
};
// 권역 API 호출 함수 추가
export const getRegionCd = async (set: any) => {
try {
const rvbsn = await getFetch("common", "/addr/sarea");
const rvbsnCd = rvbsn.map((item: any) => ({
val: item.rvbsnCd,
text: item.rvbsn,
}));
rvbsnCd.unshift({ val: '0', text: '전체' })
set((state: comCodeState) => ({
code: {
...state.code,
rvbsnCd: rvbsnCd,
},
}));
} catch (error) {
console.error('권역 데이터를 가져오는데 실패했습니다:', error);
}
};
// 중권역 API 호출 함수 추가
export const getMiddleRegionCd = async (set: any) => {
try {
const mdmbsn = await getFetch("common", "/addr/midArea");
const mdmbsnCd = mdmbsn.map((item: any) => ({
val: item.rvbsnCd,
text: item.mdmbsn,
}));
mdmbsnCd.unshift({ val: '0', text: '전체' })
set((state: comCodeState) => ({
code: {
...state.code,
mdmbsnCd: mdmbsnCd,
},
}));
} catch (error) {
console.error('중권역 데이터를 가져오는데 실패했습니다:', error);
}
};
// 단위유역 API 호출 함수 추가
export const getUnitWaterShedCd = async (set: any) => {
try {
const lgbsn = await getFetch("common", "/addr/largeArea");
const lgbsnCd = lgbsn.map((item: any) => ({
val: item.rvbsnCd,
text: item.lgbsn,
}));
lgbsnCd.unshift({ val: '0', text: '전체' })
set((state: comCodeState) => ({
code: {
...state.code,
lgbsnCd: lgbsnCd,
},
}));
} catch (error) {
console.error('대영역 데이터를 가져오는데 실패했습니다:', error);
}
};
// 환경청 데이터
export const getEnvPartCd = async (set: any) => {
try {
const lclgvrnmnt = await getFetch('common', '/addr/govArea');
const lclgvrnmntCd = lclgvrnmnt.map((item: any) => ({
val: item.lclgvrnmntCd,
text: item.lclgvrnmntNm,
adstDliStrCd: item.adstDliStrCd || ''
}));
lclgvrnmntCd.unshift({ val: '0', text: '전체', adstDliStrCd: '' })
set((state: comCodeState) => ({
code: {
...state.code,
lclgvrnmntCd: lclgvrnmntCd,
},
}));
} catch (error) {
console.error('환경청 데이터를 가져오는데 실패했습니다:', error);
}
};
export const comCodeStateExport: comCodeState = {
code: {
isInit: false,
rainFcltCd: rainFcltCd,
bdstUsgCd: bdstUsgCd,
chBuCd: chBuCd,
orgwtKndCd: orgwtKndCd,
cityCd: [],
sggCd: [],
rvbsnCd: [],
mdmbsnCd: [],
lgbsnCd: [],
lclgvrnmntCd: [],
pplQulity:pplQulity,
pplLenght:pplLenght,
yn: yn,
dmdUszCd:dmdUszCd,
buildingType:buildingType,
ruseMngMtd:ruseMngMtd,
},
};
export type comCodeActions = {
codeInit: () => void;
};
export const codeActionExport: (set: any) => comCodeActions = (set: any) => {
return {
codeInit: async () => {
const sgg = await getFetch("common", "/addr/sgg");
const sggCd = sgg.map((item: any) => ({
val: item.adstDstrCd,
text: item.gugun,
}));
const city = await getFetch("common", "/addr/city");
const cityCd = city.map((item: any) => ({
val: item.adstDstrCd,
text: item.sido,
}));
return set((state: comCodeState) => ({
code: {
...state.code,
sggCd: sggCd,
cityCd: cityCd,
},
}));
},
divCityCd: async (cd: string) => {
set((state: comCodeState) => ({
code: {
...state.code,
sggCd: state.code.sggCd.filter((item) => { return item.val.toString().slice(0, 2) === cd }),
},
}));
},
};
};
@@ -0,0 +1,122 @@
import {
fetchType,
getFetch,
postFectch,
putFectch,
} from "@/components/lib/api";
import type { pubHasuType } from "../../ruseFcltMng/fcltReg/pbnstReg/type";
import type { DemandCompType } from "@common/business_components/ui/sdmInsertForm/form";
import type { conCostFeeType, rateFeeType } from "./type";
export type comFcltState = {
searchFclts: pubHasuType;
demandCompList: DemandCompType[];
dmdIsSucees: string;
checkDemand: DemandCompType;
constCostRes:conCostFeeType[],
rateFeeRes:rateFeeType[],
};
export type comFcltActions = {
getSwtrmtFcltNm: (searchNm: string) => void;
getDemandCompList: (searchNm: string, cnt: number) => void;
regDemandCompany: (data: DemandCompType) => void;
updateDemandCompany: (data: DemandCompType) => void;
getConstCostFee: (year: string) => void;
getRateFee: (year: string) => void;
};
export const searchActions: (set: any) => comFcltActions = (set: any) => {
return {
getSwtrmtFcltNm: async (searchNm: string) => {
const fcltNm = await getFetch(
"common",
`/prcsFclt/info/1/11/${searchNm}`
);
const searchFclts: pubHasuType[] = fcltNm.map((item: any) => ({
bscFctCd: item.bscFctCd,
sido: item.sido,
gugun: item.gugun,
bscFctNm: item.bscFctNm,
addr: item.addr,
fctCpc: item.fctCpc,
}));
set((state: comFcltState) => ({
...state,
searchFclts: searchFclts,
}));
},
getDemandCompList: async (searchNm: string, cnt: number) => {
const coList = await getFetch(
fetchType.WR,
`/reuseFc/request/${searchNm}/${cnt}`
);
console.log(coList);
set((state: comFcltState) => {
return (state.demandCompList = [...coList]);
});
},
regDemandCompany: async (data: DemandCompType) => {
try {
const response = await postFectch(
"/reuseFc/request",
data,
fetchType.WR
);
let message = "";
if (response.status === 200) {
message = "success";
} else {
message = "fail";
}
set((state: comFcltState) => {
state.dmdIsSucees = message;
return state;
});
} catch (err) {
console.log(err);
}
},
updateDemandCompany: async (data: DemandCompType) => {
try {
const response = await putFectch("/reuseFc/request", data);
let message = "";
if (response.status === 200) {
message = "success";
} else {
message = "fail";
}
set((state: comFcltState) => {
state.dmdIsSucees = message;
return state;
});
} catch (err) {
console.log(err);
}
},
getRateFee: async (year: string) => {
try {
const url = `/prcsFclt/CstRt/${year}`;
const rateFeeRes = await getFetch(fetchType.COMMON, url);
set((state: comFcltState) => {
return state.rateFeeRes = rateFeeRes;;
});
} catch (e) {
console.log(" error ", e);
}
},getConstCostFee: async (year: string) => {
try {
const url = `/prcsFclt/CstRuse/${year}`;
const constCost = await getFetch(fetchType.COMMON, url);
set((state: comFcltState) => {
return state.constCostRes = constCost;;
});
}catch (e) {
}
}
};
};
@@ -0,0 +1,32 @@
export type conCostFeeType= {
yr: string,
fctCpc: string,
fctCd: string,
stdCost: string
}
export type rateFeeType = {
yr: string,
incExpCd: string,
stdCost: number,
rt: number
}
export type ContCostMap = {
gubun: string;
"500": number;
"1000": number;
"2000": number;
"3000": number;
"5000": number;
"10000": number;
"20000": number;
"30000": number;
"50000": number;
"100000": number;
[key: string]: any;
};
+27
View File
@@ -0,0 +1,27 @@
export type CommonTableProps = {
id: string;
title: string;
upName?: string;
upSequnce?: number;
row?: number;
rowSpan?: number;
colSpan?: number;
visible?: boolean;
};
export type TableUpperProps = {
id: string;
title: string;
upName?: string;
upSequnce?: number;
edit?:boolean;
visible?:boolean;
rowSpan?: number;
colSpan?: number;
type?: string;
selectData ?:string; // type 이 seelct 일경우 selectarray 정하기 위해
row?:number;
mergeCell?:boolean // 셀을 합칠경우
readonly?:boolean
};
+3 -6
View File
@@ -1,4 +1,3 @@
'use client'
import { type ReactNode, createContext, useContext, useRef } from 'react'
import { useStore } from 'zustand'
@@ -15,13 +14,11 @@ export interface StoreProviderProps {
children: ReactNode
}
export const StoreProvider = ({
export const StoreProvider = ({
children,
}: StoreProviderProps) => {
const storeRef = useRef<StoreApi>(null)
if (!storeRef.current) {
storeRef.current = StoreZus()
}
const storeRef = useRef<StoreApi>(StoreZus())
return (
<StoreContext.Provider value={storeRef.current}>
{children}
@@ -0,0 +1,199 @@
import type { CommonTableProps, TableUpperProps } from "../../common/type/header";
export const coRvwHeadListExport: CommonTableProps[]= [
{
id: "cityText",
title: "시도",
visible: true,
},
{
id: "sggText",
title: "시군구",
visible: true,
},
{
id: "dmdCoNm",
title: "회사명",
visible: true,
},
{
id: "daddr",
title: "공장주소",
visible: true,
},
{
id: "telno",
title: "전화번호",
visible: true,
},
{
id: "regDt", //바꾸기
title: "신청일자",
visible: true,
},
{
id: "state", //바꾸기
title: "진행상태",
visible: true,
},
];
// id는 다확인해야함
export const coRvwNodeListExport: CommonTableProps[] = [
{
id: "ctpv",
title: "시도",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "sgg",
title: "시군구",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "coNm",
title: "회사명",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "addr",
title: "공장주소",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "telNo",
title: "전화번호",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "regDt", //바꾸기
title: "신청일자",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "state", //바꾸기
title: "진행상태",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
];
export const constCostHeadListExport: CommonTableProps[] = [
{
id: "gubun",
title: "구분",
visible: true,
},
{
id: "500",
title: "500",
visible: true,
},
{
id: "1000",
title: "1,000",
visible: true,
},
{
id: "2000",
title: "2,000",
visible: true,
},
{
id: "3000", //바꾸기
title: "3,000",
visible: true,
},
{
id: "5000", //바꾸기
title: "5,000",
visible: true,
},
{
id: "10000", //
title: "10,000",
visible: true,
},
{
id: "20000", //
title: "20,000",
visible: true,
},
{
id: "30000", //
title: "30,000",
visible: true,
},
{
id: "50000", //
title: "50,000",
visible: true,
},
{
id: "100000", //바꾸기
title: "100,000",
visible: true,
},
];
export const rateFeeHeadListExport: CommonTableProps[] = [
{
id: "gubun",
title: "공사비/구분",
visible: true,
},
{
id: "BD",
title: "기본조사설계비",
visible: true,
},
{
id: "WD",
title: "실시설계비",
visible: true,
},
{
id: "SE",
title: "공사감리비",
visible: true,
},
{
id: "CE",
title: "시설부대비",
visible: true,
},
];
export const usageProcData = [
{ usage: "청소", process: "총인처리시설+염소소독" },
{ usage: "화장실용수", process: "총인처리시설+염소소독" },
{ usage: "세척", process: "총인처리시설+UV소독" },
{ usage: "살수", process: "총인처리시설+UV소독" },
{ usage: "조경", process: "총인처리시설+UV소독" },
{ usage: "농업", process: "총인처리시설+UV소독" },
{ usage: "하천", process: "총인처리시설+UV소독" },
{ usage: "지하수", process: "전처리시설+RO" },
{ usage: "공업", process: "전처리시설+RO" },
];
+183
View File
@@ -0,0 +1,183 @@
import { constCostHeadListExport, coRvwHeadListExport, coRvwNodeListExport, rateFeeHeadListExport } from "./headList";
import type { CommonTableProps } from "../../common/type/header";
import type { DedMatUpdateType, DmdCoReqType } from "./type";
import { fetchType, getFetch, putFectch } from "@/components/lib/api";
import toast from "react-hot-toast/headless";
const coRvwHeadList = coRvwHeadListExport;
const coRvwNodeList = coRvwNodeListExport;
const rateFeeHeadList =rateFeeHeadListExport;
const constCostHeadList=constCostHeadListExport
export type coRvwState = {
coRvw: {
isInit: boolean;
coMatRvwRes: DmdCoReqType[];
coRvwHeadList: CommonTableProps[];
coRvwNodeList: CommonTableProps[];
rateFeeHeadList: CommonTableProps[];
constCostHeadList: CommonTableProps[];
};
};
export const coRvwStateExport: coRvwState = {
coRvw: {
isInit: false,
coMatRvwRes: [],
coRvwHeadList: coRvwHeadList,
coRvwNodeList: coRvwNodeList,
rateFeeHeadList:rateFeeHeadList,
constCostHeadList:constCostHeadList
},
};
export type coRvwType = coRvwState & coRvwActions;
type coRvwActions = {
coMatRvwInit: (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
) => void;
coMatRvwUpdate: (
splyCd: string,
dmdCd: string,
data: DedMatUpdateType
) => void;
coMatRvwSearch: (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
sggCd: string,
dmdCoNm: string,
) => void;
coMatRvwInqua: (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
sggCd: string
) => void;
};
const coMatInit = async (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
) => {
const url = `/reuseFc/request/infoList/sub/${pageNo}/${pageCnt}/${startYear}/${endYear}`;
const coMatRvwRes = await getFetch(fetchType.WR, url);
return coMatRvwRes;
};
export const coRvwActionsExport: (set: any) => coRvwActions = (set: any) => {
return {
coMatRvwInit: async (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
) => {
const coMatRvwRes = await coMatInit(pageNo, pageCnt, startYear, endYear);
return set((state: coRvwState) => ({
...state,
coRvw: {
...state.coRvw,
init: false,
coMatRvwRes: coMatRvwRes,
},
}));
},
coMatRvwUpdate: async (
splyCd: string,
dmdCd: string,
data: DedMatUpdateType
) => {
try {
const isUpdate = await putFectch(
`/reuseFc/request/cst/${splyCd}/${dmdCd}`,
data
);
const coMatRvwRes = coMatInit(
1,
10,
new Date().getFullYear().toString(),
new Date().getFullYear().toString(),
);
return set((state: coRvwState) => ({
...state,
coRvw: {
...state.coRvw,
init: false,
coMatRvwRes: coMatRvwRes,
},
}));
} catch (e) {
toast.error("매칭 검토 저장 오류입니다.");
}
},
coMatRvwSearch: async (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
sggCd: string,
dmdCoNm: string,
) => {
let url = `/reuseFc/request/infoList/sub/${pageNo}/${pageCnt}/${startYear}/${endYear}`;
if (sggCd.length > 0) {
url += `/${sggCd}`;
} else {
url += `/0`;
}
if (dmdCoNm?.length > 0) {
url += `/${dmdCoNm}`;
} else {
url += `/0`;
}
console.log(' url ', url)
const coMatRvwRes = await getFetch(fetchType.WR, url);
return set((state: coRvwState) => ({
...state,
coRvw: {
...state.coRvw,
coMatRvwRes: coMatRvwRes,
},
}));
},
coMatRvwInqua: async (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
sggCd: string
) => {
try {
let url = `/reuseFc/request/infoList/sub/${pageNo}/${pageCnt}/${startYear}/${endYear}`;
if (sggCd.length > 0) {
url += `/${sggCd}/0`;
}else if(sggCd ==='0'){
url += `/0/0`;
}
const coMatRvwRes = await getFetch(fetchType.WR, url);
return set((state: coRvwState) => ({
...state,
coRvw: {
...state.coRvw,
coMatRvwRes: coMatRvwRes,
},
}));
} catch (e) {
console.log(" error ", e);
}
}
};
};
+173
View File
@@ -0,0 +1,173 @@
import { z } from "zod";
const DemandInfoSchema = z.object({
dmdInfoSn: z.number(),
dmdInfoFk: z.string(),
dmndTmng: z.coerce.date(),
dmndQty: z.number(),
wntUntprc: z.number(),
grssClfg: z.number(),
combResdch: z.number(),
trbt: z.number(),
blgcOxygDmndQnt: z.number(),
smll: z.number(),
crmty: z.number().nullish(),
tn: z.number(),
tph: z.number(),
ph: z.number(),
clIonQnt: z.number(),
cdtnv: z.number(),
rmrk: z.string(),
useUsgCd: z.string(),
mtchnCmptnYmd: z.string().nullish(),
rvwCmptnYmd: z.string().nullish()
});
const DemandMatchingSchema = z.object({
dmdInfoFk: z.string().nullish(),
splyFcltFk: z.string().nullish(),
splyFcltFlg: z.string().nullish(),
pbnstRuseFcltBizFk: z.number().nullish(),
splyBgngDay: z.coerce.date().nullish(),
splyEndDay: z.coerce.date().nullish(),
splyCpct: z.number().nullish(),
splyFmYn: z.string().nullish(),
useUsgCd: z.string().nullish(),
dmdInfoSn: z.number().nullish(),
splyCndtList:z.array(z.string().nullish() ).nullish()
});
const DemandCoSchema = z.object({
dmdInfoPk: z.string(),
dmdCoNm: z.string(),
ctpvCd: z.string(),
sggCd: z.string(),
daddr: z.string(),
splyBgngDay: z.coerce.date(),
splyEndDay: z.coerce.date(),
splyCpct: z.number(),
splyFmYn: z.string().nullish(),
telno: z.string(),
useUsgCd: z.string().nullish(),
regDt: z.coerce.date().nullish(),
rgtr: z.string().nullish(),
mdfcnDt: z.coerce.date().nullish(),
mdfr: z.string().nullish(),
dmdAplyPswd: z.string(),
demandInfo: z.array(DemandInfoSchema.nullish()).nullish(), // 안쓰는 거임
demandMatchings: z.array(DemandMatchingSchema.nullish()).nullish()// 안쓰는 거임
});
const DemandCstSchema = z.object({
dmdInfoSn: z.number(),
usgPrcsProcs: z.string().nullish(),
cstrnCst: z.number(),
fcltSbsdCstrnCst: z.number(),
prcsFcltCpctCstrnCst: z.number()
});
export const DmdCoReqSchema = z.object({
cityText:z.string().nullish(),
sggText:z.string().nullish(),
dmdInfoSn: z.number(),
dmdInfoFk: z.string(),
dmndTmng: z.coerce.date(),
dmndQty: z.number(),
wntUntprc: z.number().nullish(),
grssClfg: z.number().nullish(),
combResdch: z.number().nullish(),
trbt: z.number().nullish(),
blgcOxygDmndQnt: z.number(),
smll: z.number().nullish(),
crmty: z.number().nullish(),
tn: z.number().nullish(),
tph: z.number().nullish(),
ph: z.number().nullish(),
clIonQnt: z.number().nullish(),
cdtnv: z.number(),
rmrk: z.string().nullish(),
useUsgCd: z.string().nullish(),
mtchnCmptnYmd: z.string().nullish(),
rvwCmptnYmd: z.string().nullish(),
demandCo: DemandCoSchema.nullish(),
demandMatching: DemandMatchingSchema.nullish(),
demandCst: DemandCstSchema,
ruseUtztnFcltNm:z.string().nullish(),
totalConstCost:z.number().nullish(),
});
export type DmdCoReqType = z.infer<typeof DmdCoReqSchema>;
export type DmdMatTableType = {
cityText:string,
sggText:string,
dmdCoNm:string,
daddr:string,
telno:string,
regDt:string,
splyFcltFlg:string
}
export type DedMatUpdateType =
{
dmdInfoSn: number;
usgPrcsProcs: string;
cstrnCst: number;
fcltSbsdCstrnCst: number;
prcsFcltCpctCstrnCst: number;
rgtr: string;
}
export type RvwHistTableType = {
cityText:string,
sggText:string,
dmdCoNm:string,
daddr:string,
telno:string,
regDt:string,
rvwCmptnYmd:string,
mtchnCmptnYmd:string,
ruseUtztnFcltNm:string,
dmndQty:string,
useUsgCd:string,
splyFcltFlg:string
completeYn:boolean
dmdInfoSn :string
}
export type RvwHistTableType = {
cityText:string,
sggText:string,
dmdCoNm:string,
daddr:string,
telno:string,
regDt:string,
rvwCmptnYmd:string,
mtchnCmptnYmd:string,
ruseUtztnFcltNm:string,
dmndQty:string,
useUsgCd:string,
splyFcltFlg:string
completeYn:boolean
dmdInfoSn :string
}
export type conCostFeeType= {
yr: string,
fctCpc: string,
fctCd: string,
stdCost: string
}
export type rateFeeType = {
yr: string,
incExpCd: string,
stdCost: number,
rt: number
}
+17
View File
@@ -0,0 +1,17 @@
import type { customCoSttnBdst } from ".";
export const excelCoSttnParsing = (data: customCoSttnBdst[]): string[][] => {
const excelExportData: string[][] = [];
data.forEach((item) => {
excelExportData.push([
String(item.ctpvCd),
String(item.sggCd),
item.dmdCoNm ?? "",
item.daddr ?? "",
String(item.dmdInfoPk ?? ""),
item.telno ?? ""
]);
});
return excelExportData;
};
@@ -0,0 +1,98 @@
import type { CommonTableProps } from "@/app/store/common/type/header";
import { z } from "zod";
export const sttnHeadListType = z.array(
z.object({
id: z.string(),
title: z.string(),
visible: z.boolean(),
})
);
export const coRegExcel = z.object({
file: z.any()
});
export const coSttHeadListExport: z.infer<typeof sttnHeadListType> = [
{
id: "cityText",
title: "시도",
visible: true,
},
{
id: "sggText",
title: "시군구",
visible: true,
},
{
id: "dmdCoNm",
title: "회사명",
visible: true,
},
{
id: "daddr",
title: "주소",
visible: true,
},
{
id: "dmdInfoPk",
title: "사업자번호",
visible: true,
},
{
id: "telno",
title: "전화번호",
visible: true,
},
];
export const coSttNodeListExport: CommonTableProps[] = [
{
id: "cityText",
title: "시도",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "sggText",
title: "시군구",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "dmdCoNm",
title: "회사명",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "daddr",
title: "주소",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "dmdInfoPk",
title: "사업자번호",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "telno",
title: "전화번호",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
];
+123
View File
@@ -0,0 +1,123 @@
import type { CommonTableProps } from "@/app/store/common/type/header";
import { fetchType, getFetch, getFetchWithCount } from "@/components/lib/api";
import { coSttHeadListExport, coSttNodeListExport } from "./headList";
import { excelCoSttnParsing } from "./excel";
import type { DemandCompType } from "@common/business_components/ui";
// 테이블 헤드 리스트
const coSttNodeList = coSttNodeListExport;
const coSttHeadList = coSttHeadListExport;
const coSttnRes: DemandCompType[] = [];
export type coSttnState = {
coSttn: {
coSttnRes: DemandCompType[];
coSttHeadList: CommonTableProps[];
coSttNodeList: CommonTableProps[];
excelList: [];
isInit: boolean;
coSttnResCount: number;
};
};
type coSttnActions = {
coSttnInit:(pageNo:string, pageCnt:string, con: string) => void;
coSttnSearch: (pageNo:string, pageCnt:string, con: string) => void;
coSttnTxtSearch:(pageNo:string, pageCnt:string, con: string,txt:string) => void;
};
export type coSttnType = coSttnState & coSttnActions;
export const coSttnStateExport: coSttnState = {
coSttn: {
coSttHeadList: coSttHeadList,
coSttNodeList: coSttNodeList,
coSttnRes: coSttnRes,
excelList: [],
isInit: false,
coSttnResCount: 0,
},
};
export const coSttnActionsExport: (set: any) => coSttnActions = (
set: any
) => {
return {
coSttnInit: async (pageNo:string, pageCnt:string, con: string) => {
try {
const coSttnRes = await getFetchWithCount(
fetchType.WR,
`/reuseFc/request/${pageNo}/${pageCnt}/${con}`
);
set((state: coSttnState) => {
return {
...state,
coSttn: {
...state.coSttn,
coSttnRes: coSttnRes.data,
isInit: false,
coSttnResCount: coSttnRes.count,
},
};
});
} catch (e) {
console.log(e)
}
},
coSttnSearch: async (pageNo:string, pageCnt:string, con: string) => {
try {
const coSttnRes = await getFetchWithCount(
fetchType.WR,
`/reuseFc/request/${pageNo}/${pageCnt}/${con}`
);
if (Number(pageCnt) >= 10000) {
const coExcel = excelCoSttnParsing(coSttnRes.data);
set((state: coSttnState) => {
return {
...state,
coSttn: {
...state.coSttn,
excelList: coExcel,
isInit: false,
},
};
});
} else
set((state: coSttnState) => {
return {
...state,
coSttn: {
...state.coSttn,
coSttnRes: coSttnRes.data,
isInit: false,
coSttnResCount : coSttnRes.count,
},
};
});
} catch (erTxt) {
console.log("error", erTxt);
}
},
coSttnTxtSearch: async (pageNo:string, pageCnt:string, con: string, txt: string) => {
try {
const coSttnRes = await getFetch(
fetchType.WR,
`/reuseFc/request/${pageNo}/${pageCnt}/${con}/${txt}`)
set((state: coSttnState) => {
return {
...state,
coSttn: {
...state.coSttn,
coSttnRes: coSttnRes,
isInit: false,
}}})
} catch (erTxt) {
console.log("error", erTxt);
}
}
}
}
@@ -0,0 +1,102 @@
import type { CommonTableProps } from "../../common/type/header";
export const drgtHeadListExport: CommonTableProps[] = [
{
id: "ctpvCd",
title: "시도",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "sggCd",
title: "시군구",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "haengjung",
title: "행정동",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "normal",
title: "정상(횟수)",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "attention",
title: "관심(횟수)",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "caution",
title: "주의(횟수)",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "warning",
title: "관심+주의(횟수)",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "ranking",
title: "가뭄순위",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
];
export const drgtDetailHeadListExport: CommonTableProps[] = [
{
id: "year",
title: "년",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "month",
title: "월",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},{
id: "day",
title: "일",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "state",
title: "가뭄상태",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
]
@@ -0,0 +1,27 @@
import type { CommonTableProps } from "../../common/type/header";
import { drgtHeadListExport } from "./headList";
const drgtHeadList = drgtHeadListExport;
export type drgtState = {
drgt:{
drgtHeadList: CommonTableProps[];
}
}
type drgtActions = {
};
export type drgtType = drgtState & drgtActions;
export const drgtStateExport: drgtState = {
drgt: {
drgtHeadList: drgtHeadList,
}
}
export const drgtActionsExport: (set: any) => drgtActions = (
set: any
) => {
return {};
};
+5 -5
View File
@@ -1,4 +1,4 @@
import type { selectArray } from "../rainReuseFacilityInsert";
import type { SelectDataType } from "@common/business_components/ui";
@@ -23,10 +23,10 @@ const selectSgg = [
export type matDmdState ={ dmd:{
isInit: boolean;
selectSido:selectArray[];
selectSgg:selectArray[];
selectUsg:selectArray[];
selectYN:selectArray[];
selectSido:SelectDataType[];
selectSgg:SelectDataType[];
selectUsg:SelectDataType[];
selectYN:SelectDataType[];
}}
type matDmdActions = {
decrementList: () => void
@@ -0,0 +1,75 @@
import { TEST_UUID } from "../../ruseFcltMng/fcltReg/rainReg";
type nameMap = {
[key: string]: string;
}
export const names: nameMap = {
"시도": "ctpvCd",
"시군구명": "sggCd",
"관리기관": "mngInst",
"회사명": "dmdCoNm",
"공장구분": "fctrySe",
"단지명": "cmpxNm",
"설립구분": "fndnSe",
"입주형태": "mvnShp",
"보유구분": "hldSe",
"최초승인일": "frstAprvYmd",
"최초등록일": "frstRegYmd",
"등록구분": "regSe",
"등록일": "regYmd",
"전화번호": "telno",
"남자종업원": "maleEmpCnt",
"여자종업원": "fmaleEmpCnt",
"외국인남자종업원": "frgnrMaleEmpCnt",
"외국인여자종업원": "frgnrFmaleEmpCnt",
"종업원합계": "totalEmpCnt",
"생산품": "prdctnItem",
"원자재": "splyMtrl",
"공장규모": "fctryScl",
"용도지역": "usgRgn",
"지목": "ldcg",
"용지면적": "usgRgnArea",
"제조시설면적": "mnftrFcltArea",
"부대시설면적": "sbsdFcltArea",
"건축면적": "archArea",
"지식산업센터명": "knwlIndstCntrNm",
"대표업종": "rprsTpbiz",
"업종명": "tpbizNm",
"업종코드": "tpbizCd",
"차수": "cycl",
"법인주소": "corpAddr",
"필지수": "esntlIdx",
"공장주소": "fctryAddr",
"공장주소_지번": "fctryLotnoAddr",
"공장관리번호": "fctryMngNo",
}
export const excelPbnstSttnParsing = (data: any[]): string[][] => {
const excelExportData: string[][] = [];
data.forEach((item) => {
excelExportData.push([
item.rvbsn,
String(item.lgbsn),
item.mdmbsn ?? "",
item.rgnNm ?? "",
String(item.sido ?? ""),
String(item.gugun ?? ""),
String(item.bscFctNm ?? ""),
String(item.efflWqltStndrdNm ?? ""),
String(item.fctCpc ?? ""),
String(item.tel ?? ""),
String(item.ruseUtztnFcltNm ?? ""),
String(item.fcltCpct ?? ""),
String(item.splyExtraCpct ?? ""),
String(item.ruseCpct ?? ""),
String(item.usageTotal ?? ""),
String(item.inUsage ?? ""),
String(item.outUsage ?? ""),
])
})
return excelExportData;
};
@@ -0,0 +1,404 @@
import { z } from "zod";
import type { CommonTableProps } from "../../common/type/header";
import { TEST_UUID } from "../../ruseFcltMng/fcltReg/rainReg";
export const ldrmntZod = z.object({
fctryMngSn: z.string().default(''),
ctpvCd: z.string().default(''),
sggCd: z.string().default(''),
mngInstNm: z.string().default('').nullish(),
dmdCoNm: z.string().default(''),
fctrySe: z.string().default(''),
cmpxNm: z.string().default(''),
fndnSe: z.string().default(''),
mvnShp: z.string().default(''),
hldSe: z.string().default(''),
frstAprvYmd: z.string().default(''),
frstRegYmd: z.string().default(''),
regSe: z.string().default(''),
regYmd: z.string().default(''),
telno: z.string().default(''),
maleEmpCnt: z.number().default(0),
fmaleEmpCnt: z.number().default(0),
frgnrMaleEmpCnt: z.number().default(0),
frgnrFmaleEmpCnt: z.number().default(0),
totalEmpCnt: z.number().default(0),
prdctnItem: z.string().default(''),
splyMtrl: z.string().default(''),
fctryScl: z.string().default(''),
usgRgn: z.string().default(''),
ldcg: z.string().default(''),
usgRgnArea: z.number().default(0),
mnftrFcltArea: z.number().default(0),
sbsdFcltArea: z.number().default(0),
archArea: z.number().default(0),
knwlIndstCntrNm: z.string().default(''),
rprsTpbiz: z.string().default(''),
tpbizNm: z.string().default(''),
tpbizCd: z.string().default(''),
cycl: z.number().default(0),
corpAddr: z.string().default(''),
esntlIdx: z.number().default(0),
fctryAddr: z.string().default(''),
fctryLotnoAddr: z.string().default(''),
fctryMngNo: z.string().default(''),
rgtr:z.string().default(TEST_UUID).nullish()
})
export const ldrmntHeadListExport: CommonTableProps[] = [
{
id: "ctpvCd",
title: "시도",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "sggCd",
title: "시군구",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "dmdCoNm",
title: "회사명",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "fctryAddr",
title: "공장주소",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "fctryMngNo",
title: "공장관리번호",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "telno",
title: "전화번호",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
]
export const ldrmntNodeListExport: CommonTableProps[] = [
{
id: "ctpvCd",
title: "시도",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "sggCd",
title: "시군구",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "mngInstNm",
title: "관리기관",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "dmdCoNm",
title: "회사명",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "fctrySe",
title: "공장구분",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "cmpxNm",
title: "단지명",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "fndnSe",
title: "설립구분",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "mvnShp",
title: "입주형태",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "hldSe",
title: "보유구분",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "frstAprvYmd",
title: "최초승인일",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "frstRegYmd",
title: "최초등록일",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "regSe",
title: "등록구분",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "regYmd",
title: "등록일",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "telno",
title: "전화번호",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "maleEmpCnt",
title: "남자종업원",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "fmaleEmpCnt",
title: "여자종업원",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "frgnrMaleEmpCnt",
title: "외국인남자종업원",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "frgnrFmaleEmpCnt",
title: "외국인여자종업원",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "totalEmpCnt",
title: "종업원합계",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "prdctnItem",
title: "생산품",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "splyMtrl",
title: "원자재",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "fctryScl",
title: "공장규모",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "usgRgn",
title: "용도지역",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "ldcg",
title: "지목",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "usgRgnArea",
title: "용지면적",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "mnftrFcltArea",
title: "제조시설면적",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "sbsdFcltArea",
title: "부대시설면적",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "archArea",
title: "건축면적",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "knwlIndstCntrNm",
title: "지식산업센터명",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "rprsTpbiz",
title: "대표업종",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "tpbizNm",
title: "업종명",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "tpbizCd",
title: "업종코드",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "cycl",
title: "차수",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "corpAddr",
title: "법인주소",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "esntlIdx",
title: "필지수",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "fctryAddr",
title: "공장주소",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "fctryLotnoAddr",
title: "공장주소_지번",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{
id: "fctryMngNo",
title: "공장관리번호",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
];
@@ -0,0 +1,177 @@
import type { CommonTableProps } from "@/app/store/common/type/header";
import { deleteFectch, fetchType, getFetch, postFectch, putFectch } from "@/components/lib/api";
import { ToastFormUi } from "@/components/ui/toast/toastFromUi";
import { z } from "zod";
import { ldrmntHeadListExport, ldrmntNodeListExport, ldrmntZod } from "./headList";
import { TEST_UUID } from "../../ruseFcltMng/fcltReg/rainReg";
// 테이블 헤드 리스트
const ldrmntHeadList = ldrmntHeadListExport;
const ldrmntNodeList = ldrmntNodeListExport;
export type customLdrmnt = z.infer<typeof ldrmntZod>;
const ldrmntRes: customLdrmnt[] = [];
export type ldrmntState = {
ldrmnt: {
ldrmntHeadList: CommonTableProps[];
ldrmntNodeList: CommonTableProps[];
excelList: ExcelType[];
isInit: boolean;
ldrmntRes: customLdrmnt[];
};
};
type ExcelType = {
[key: string]: string | number | undefined;
};
const excelDownList: ExcelType[] = [];
type ldrmntActions = {
ldrmntRegData: (data: any[]) => void,
ldrmntInit: (con: string) => void
ldrmntSearch: (page: number, sggCd: string, coNm: string) => void;
ldrmntUpdate: (ldrmntRes: customLdrmnt) => void;
ldrmntDelete: () => void;
};
export type ldrmntType = ldrmntState & ldrmntActions;
export const ldrmntStateExport: ldrmntState = {
ldrmnt: {
ldrmntHeadList: ldrmntHeadList,
ldrmntNodeList: ldrmntNodeList,
excelList: [],
isInit: false,
ldrmntRes: ldrmntRes,
},
};
export const ldrmntActionsExport: (set: any) => ldrmntActions = (
set: any
) => {
return {
ldrmntInit: async (con: string) => {
try {
const ldrmntRes = await getFetch(
fetchType.WR,
`/reuseFc/request/temp/1/20/${con}`
);
set((state: ldrmntState) => {
return {
...state,
ldrmnt: {
...state.ldrmnt,
ldrmntRes: ldrmntRes,
isInit: false,
},
}
});
} catch (e) {
console.log(e)
}
},
ldrmntRegData: async (data) => {
try {
const response = await postFectch(
"/reuseFc/request/temp",
data,
fetchType.WR
);
console.log('response ', response)
if (response.status === 200) {
ToastFormUi({
body: "잠재수요처 등록이 완료되었습니다. ",
title: "잠재수요처 등록",
});
}
} catch (e) {
console.log(e)
ToastFormUi({
body: "잠재수요처 등록이 실패하였습니다. ",
title: "잠재수요처 등록",
});
}
},
ldrmntSearch: async (page: number, sggCd: string, coNm: string) => {
let searchUrl = "";
if (sggCd !== "") {
if (coNm !== "") {
searchUrl = `/reuseFc/request/temp/${page}/20/${sggCd}/${coNm}`;
} else {
searchUrl = `/reuseFc/request/temp/${page}/20/${sggCd}`;
}
}
try {
const ldrmntRes = await getFetch(
fetchType.WR,
searchUrl
);
ldrmntRes.forEach((item: customLdrmnt) => {
excelDownList.push({
ctpvCd: item.ctpvCd,
sggCd: item.sggCd,
dmdCoNm: item.dmdCoNm,
fctryAddr: item.fctryAddr,
fctryMngNo: item.fctryMngNo,
telno: item.telno,
})
})
set((state: ldrmntState) => {
return {
...state,
ldrmnt: {
...state.ldrmnt,
ldrmntRes: ldrmntRes,
excelList: excelDownList,
},
}
})
} catch (e) {
console.log(e)
}
},
ldrmntUpdate: async (ldrmntRes: customLdrmnt) => {
try {
ldrmntRes.rgtr = TEST_UUID;
const response = await putFectch(
`/reuseFc/request/temp`,
ldrmntRes
);
return set((state: ldrmntState) => ({
...state,
ldrmnt: {
...state.ldrmnt,
ldrmntRes: ldrmntRes,
},
}));
} catch (error) {
console.error("Error ldrmntUpdate:", error);
}
},
ldrmntDelete: async () => {
try {
const response = await deleteFectch(
`/reuseFc/request/temp`,
);
} catch (error) {
console.error("Error ldrmntDelete:", error);
}
},
}
}
@@ -0,0 +1,355 @@
import type { SelectDataType } from "@common/business_components/ui";
import type { TableUpperProps } from "../../common/type/header";
//★☆★☆ 여기서부터 수정하기 ★☆★☆
export const ruseCaseHeadListExport: TableUpperProps[] = [
{
id: "a",
title: "사업명",
visible: true,
row: 0,
rowSpan: 2,
},
{
id: "b",
title: "사업기간",
visible: true,
row: 0,
rowSpan: 2,
},
{
id: "c",
title: "공급처",
visible: true,
row: 0,
colSpan: 3,
},
{
id: "d",
title: "시설종류",
visible: true,
row: 1,
},
{
id: "e",
title: "공급처명",
visible: true,
row: 1,
},
{
id: "f",
title: "시설용량(m³/일)",
visible: true,
row: 1,
},
{
id: "g",
title: "수요처",
visible: true,
row: 0,
colSpan: 2,
},
{
id: "h",
title: "수요처명",
visible: true,
row: 1,
},
{
id: "i",
title: "주소",
visible: true,
row: 1,
},
{
id: "q",
title: "재이용시설",
visible: true,
row: 0,
colSpan: 5,
},
{
id: "q2",
title: "시설용량(m³/일)",
visible: true,
row: 1,
},
{
id: "q3",
title: "관로(km)",
visible: true,
row: 1,
},
{
id: "q4",
title: "용도",
visible: true,
row: 1,
},
{
id: "q5",
title: "공급량(m³/일)",
visible: true,
row: 1,
},
{
id: "q6",
title: "처리공법",
visible: true,
row: 1,
},
{
id: "k",
title: "보증수질",
visible: true,
row: 0,
colSpan: 13,
},
{
id: "k1",
title: "용도별",
visible: true,
row: 1,
},
{
id: "k2",
title: "총대장균군수​(개/100ml)",
visible: true,
row: 1,
},
{
id: "k3",
title: "결합잔류염소(mg/L)",
visible: true,
row: 1,
},
{
id: "k4",
title: "탁도(NTU)",
visible: true,
row: 1,
},
{
id: "k5",
title: "생물학적​산소요구량(BOD)(mg/L)​",
visible: true,
row: 1,
},
{
id: "k6",
title: "냄새​",
visible: true,
row: 1,
},
{
id: "k7",
title: "색도​",
visible: true,
row: 1,
},
{
id: "k8",
title: "총질소(T-N)(mg/L)​",
visible: true,
row: 1,
},
{
id: "k9",
title: "총인(T-P)(mg/L)",
visible: true,
row: 1,
},
{
id: "k10",
title: "수소이온농도(PH)​",
visible: true,
row: 1,
},
{
id: "k11",
title: "수소이온농도(PH)​",
visible: true,
row: 1,
},
{
id: "k12",
title: "전기전도도​(㎲/cm",
visible: true,
row: 1,
},
{
id: "k13",
title: "비고​",
visible: true,
row: 1,
},
{
id: "h",
title: "소요사업비(백만원)",
visible: true,
row: 0,
colSpan: 14,
},
{
id: "h1",
title: "총",
visible: true,
row: 1,
},
{
id: "h2",
title: "토목재이용시설",
visible: true,
row: 1,
},
{
id: "h3",
title: "토목관로",
visible: true,
row: 1,
},
{
id: "h4",
title: "건축",
visible: true,
row: 1,
},
{
id: "h5",
title: "기계",
visible: true,
row: 1,
},
{
id: "h6",
title: "전기・계측",
visible: true,
row: 1,
},
{
id: "h7",
title: "GIS・DB",
visible: true,
row: 1,
},
{
id: "h8",
title: "CCTV",
visible: true,
row: 1,
},
{
id: "h9",
title: "시공및준공",
visible: true,
row: 1,
},
{
id: "h10",
title: "페기물",
visible: true,
row: 1,
},
{
id: "h11",
title: "설계비",
visible: true,
row: 1,
},
{
id: "h12",
title: "감리비",
visible: true,
row: 1,
},
{
id: "h13",
title: "시설부대비",
visible: true,
row: 1,
},
{
id: "h14",
title: "기타",
visible: true,
row: 1,
},
{
id: "i",
title: "자원조달계획(백만원)",
visible: true,
row: 0,
colSpan: 4,
},
{
id: "i1",
title: "총",
visible: true,
row: 1,
},
{
id: "i2",
title: "국비",
visible: true,
row: 1,
},
{
id: "i3",
title: "지방비",
visible: true,
row: 1,
},
{
id: "i4",
title: "원인자부담",
visible: true,
row: 1,
},
{
id: "j",
title: "사업비정산(백만원)",
visible: true,
row: 0,
colSpan: 5,
},
{
id: "j1",
title: "총",
visible: true,
row: 1,
},
{
id: "j2",
title: "국비",
visible: true,
row: 1,
},
{
id: "j3",
title: "지방비",
visible: true,
row: 1,
},
{
id: "j4",
title: "원인자부담",
visible: true,
row: 1,
},
{
id: "j5",
title: "국고비율",
visible: true,
row: 1,
},
];
export const ruseUtzType: SelectDataType[] = [
{ text: "조경용수", val: "조경용수" },
{ text: "청소화장실용수", val: "청소화장실용수" },
{ text: "세척살수용수", val: "세척살수용수" },
{ text: "농업용수", val: "농업용수" },
{ text: "공업용수", val: "공업용수" },
{ text: "친수용수", val: "친수용수" },
{ text: "기타", val: "기타" },
];
@@ -0,0 +1,24 @@
import type { TableUpperProps } from "../../common/type/header";
import { ruseCaseHeadListExport } from "./headList";
export type ruseCaseState = {
ruseCase: {
ruseHeadList:TableUpperProps[];
};
};
type ruseCaseActions = {
};
export type ruseCaseType = ruseCaseState & ruseCaseActions;
export const ruseCaseStateExport: ruseCaseState = {
ruseCase: {
ruseHeadList:ruseCaseHeadListExport,
},
};
export const ruseCaseActionsExport: (set: any) => ruseCaseActions = (
set: any
) => {
return {
};
};
@@ -0,0 +1,71 @@
import type { TableUpperProps } from "../../common/type/header";
export const ruseHstryHeadListExport:TableUpperProps[]= [
{
id: "cityText",
title: "시도",
visible: true,
},
{
id: "sggText",
title: "시군구",
visible: true,
},
{
id: "dmdCoNm",
title: "회사명",
visible: true,
},
{
id: "daddr",
title: "공장주소",
visible: true,
},
{
id: "telno",
title: "전화번호",
visible: true,
},
{
id: "regDt", //바꾸기
title: "신청일자",
visible: true,
},
{
id: "rvwCmptnYmd", //바꾸기
title: "검토일자",
visible: true,
},
{
id: "mtchnCmptnYmd", //바꾸기
title: "매칭 완료일자",
visible: true,
},
{
id: "ruseUtztnFcltNm", //바꾸기
title: "공급처",
visible: true,
},
{
id: "dmndQty", //바꾸기
title: "요구수량(M3/d)",
visible: true,
},
{
id: "useUsgCd", //바꾸기
title: "사용용도",
visible: true,
},
{
id: "splyFcltFlg", //바꾸기
title: "진행상태",
visible: true,
},
{
id: "completeYn", //바꾸기
title: "매칭완료 여부",
visible: true,
},
];
@@ -0,0 +1,237 @@
import type { z } from "zod";
import type { sttnHeadListType } from "../coSttn/headList";
import type {
CommonTableProps,
TableUpperProps,
} from "../../common/type/header";
import { ruseHstryHeadListExport } from "./headList";
import { fetchType, getFetch, postFectch, putFectch } from "@/components/lib/api";
import type { DmdCoReqType } from "../coMatRvw/type";
import toast from "react-hot-toast";
import { TEST_UUID } from "../../ruseFcltMng/fcltReg/rainReg";
const ruseHistHeadList = ruseHstryHeadListExport;
export type ruseHstryState = {
ruseHist: {
isInit: boolean;
rvwHistRes: DmdCoReqType[];
ruseHistHeadList: TableUpperProps[];
};
};
export const ruseHstryStateExport: ruseHstryState = {
ruseHist: {
isInit: false,
rvwHistRes: [],
ruseHistHeadList: ruseHistHeadList,
},
};
export type ruseHstryType = ruseHstryState & ruseHstryActions;
//
export const addRgtrAndMdfrToDemandObj = (data: DmdCoReqType) => {
// 최상위 demand 객체
// demandCo가 있을 경우
if (data.demandCo) {
data.demandCo.rgtr = TEST_UUID;
data.demandCo.mdfr = TEST_UUID;
}
return data;
};
type ruseHstryActions = {
ruseRvwHistInit: (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
sggCd?: string
) => void;
ruseRvwCalUpdate: (data: DmdCoReqType) => void;
ruseRvwSearch: (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
sggCd: string,
dmdCoNm: string,
ruseUtztnFcltNm: string
) => void;
ruseRvwInqua: (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
sggCd: string
) => void;
ruseRvwComplete:( data: Number[]) => void;
};
const irvwHistInit = async (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
) => {
let url = `/reuseFc/request/infoList/matched/${pageNo}/${pageCnt}/${startYear}/${endYear}`;
// console.log("sggCd ", sggCd);
// if (sggCd) {
// url += `/${sggCd}`;
// }
const rvwHistRes = await getFetch(fetchType.WR, url);
return rvwHistRes;
};
export const ruseHstryActionsExport: (set: any) => ruseHstryActions = (
set: any
) => {
return {
ruseRvwHistInit: async (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
sggCd?: string
) => {
const rvwHistRes = await irvwHistInit(
pageNo,
pageCnt,
startYear,
endYear,
// sggCd
);
return set((state: ruseHstryState) => ({
...state,
ruseHist: {
...state.ruseHist,
init: false,
rvwHistRes: rvwHistRes,
},
}));
},
ruseRvwCalUpdate: async (data: DmdCoReqType) => {
try {
const updatedData = addRgtrAndMdfrToDemandObj(data);
const update = await putFectch(
`/reuseFc/request/cst`,
updatedData
);
if (update.status === 200) {
toast.success("매칭 계산 저장이 완료입니다.");
const rvwHistRes = await irvwHistInit(
1,
10,
new Date().getFullYear().toString(),
new Date().getFullYear().toString(),
);
return set((state: ruseHstryState) => ({
...state,
ruseHist: {
...state.ruseHist,
init: false,
rvwHistRes: rvwHistRes,
},
}));
}
} catch (e) {
toast.error("매칭 계산 저장이 오류입니다.");
console.log(e);
}
},
ruseRvwSearch: async (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
sggCd: string,
dmdCoNm: string,
ruseUtztnFcltNm: string
) => {
let url = `/reuseFc/request/infoList/matched/${pageNo}/${pageCnt}/${startYear}/${endYear}`;
if (sggCd.length > 0) {
url += `/${sggCd}`;
} else {
url += `/0`;
}
if (dmdCoNm?.length > 0) {
url += `/${dmdCoNm}`;
} else {
url += `/0`;
}
if (ruseUtztnFcltNm?.length > 0) {
url += `/${ruseUtztnFcltNm}`;
} else {
url += `/0`;
}
const rvwHistRes = await getFetch(fetchType.WR, url);
return set((state: ruseHstryState) => ({
...state,
ruseHist: {
...state.ruseHist,
rvwHistRes: rvwHistRes,
},
}));
},
ruseRvwInqua: async (
pageNo: number,
pageCnt: number,
startYear: string,
endYear: string,
sggCd: string
) => {
try {
let url = `/reuseFc/request/infoList/matched/${pageNo}/${pageCnt}/${startYear}/${endYear}`;
if (sggCd.length > 0) {
url += `/${sggCd}/0`;
}
const rvwHistRes = await getFetch(fetchType.WR, url);
return set((state: ruseHstryState) => ({
...state,
ruseHist: {
...state.ruseHist,
rvwHistRes: rvwHistRes,
},
}));
} catch (e) {
console.log(" error ", e);
}
},
ruseRvwComplete: async (data: Number[]) => {
try {
const complet = await postFectch(
`/reuseFc/request/completeCheck`,
data,
fetchType.WR
);
if (complet.status === 200) {
toast.success("완료 처리가 완료되었습니다.");
const rvwHistRes = await irvwHistInit(
1,
10,
new Date().getFullYear().toString(),
new Date().getFullYear().toString(),
);
}
} catch (e) {
console.log(" error ", e);
toast.error("완료 처리 중 오류가 발생했습니다.");
}
},
};
};
@@ -0,0 +1,137 @@
import type { SelectDataType } from "@common/business_components";
import type { rainChkZodType } from ".";
import { TEST_UUID } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { buildingType } from "../../../common/code/index";
export const useTypes = [
"조경용수",
"청소화장실용수",
"세척살수용수",
"농업용수",
"공업용수",
"친수용수",
"기타",
];
export type Buildingtype = {
bdstInfoPk: number;
ctpvCd: 1;
sggCd: 1001;
daddr: "string3";
bdstNm: "string";
frstArchPrmsnDt: "2025-03-25";
archArea: 0;
regDt: "2025-04-16";
rgtr: null;
mdfcnDt: "2025-04-16";
mdfr: null;
};
export const buildingToExcelType = (
buildings: Buildingtype[],
sidoCode: SelectDataType[],
sggCdoe: SelectDataType[],
) => {
const excelData: string[][] = [];
buildings.forEach((building) => {
useTypes.forEach((useType) => {
excelData.push([
building.bdstInfoPk.toString(),
sidoCode.find((sido) => sido.val === building.ctpvCd.toString())
?.text || "",
sggCdoe.find((sido) => sido.val === building.sggCd.toString())
?.text || "",
building.daddr,
building.bdstNm,
"",
"",
"",
"",
useType,
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
]);
});
});
return excelData;
};
export const excelToRainChkData = (excelData: any, year: string) => {
const rainChkgdData: rainChkZodType[] = excelData.map((item: any) => {
if (item["점검일"] !== undefined) {
const checkYmd = item["점검일"].replace(/\./g, "")
let vltnDt = item["과태료 부과일(위반일)"]
if (vltnDt !== undefined) {
vltnDt = vltnDt ? vltnDt.replace(/\./g, "") : "";
}
const makeGuidDetail = Array.from({ length: 12 }, (_, i) => {
let month = `${i + 1}`;
const splyData = item[`보급_${month}월`];
const ruseData = item[`빗물_${month}월`];
if (month.length < 2) month = "0" + month;
return {
utztnUsgCd: item["이용용도"],
ym: year + month,
chckYmd: checkYmd,
splyUswtrUtztnQnt: Number(splyData ?? 0),
ruseFcltUtztnQnt: Number(ruseData ?? 0),
flg: "RNB",
};
});
return {
bdstRuseFcltFk: Number(item["NO"]),
chckYmd: checkYmd,
spwtPositn: item["유량측정방법"] ?? "",
rgtr: TEST_UUID,
oilqMeasMthd: item["운영관리형태"] ?? "",
anlOperCst: Number(item["연간운영비(원/년)"]) ?? 0,
operMngCd: item["유량측정방법"] ?? "",
guideDetails: makeGuidDetail,
rainyDetails: [
{
utztnUsgCd: item["이용용도"] ?? "",
ph: Number(item["PH"] ?? 0),
trbt: Number(item["탁도"] ?? 0),
grssClfg: Number(item["총대장균군수"] ?? 0),
etc: item["기타"] ?? "", // 필드 누락 방지
vltnDt: vltnDt ?? "",
vltnMttr: item["위반사항"] ?? "",
levyAmt: Number(item["과태료부과금액(천원)"] ?? 0),
rgtr: TEST_UUID,
},
],
};
}
}).filter((el: any) => el !== undefined);
return rainChkgdData;
};
@@ -0,0 +1,223 @@
import type { TableUpperProps } from "@/app/store/common/type/header";
import { z } from "zod";
export const chkgdRegExcel = z.object({
bdstInfoPk: z.number().default(111111111),
chckYr: z
.string()
.default("")
.refine((year) => year.length === 0 || /^\d{4}$/.test(year), {
message: "4자리 연도만 입력하세요",
})
.refine(
(year) => {
if (year.length === 0) return true; // 빈 문자열은 통과
const numYear = Number(year);
return !isNaN(numYear) && numYear <= new Date().getFullYear();
},
{ message: "현재 년도보다 높은 수를 입력할 수 없습니다." }
),
file: z.instanceof(File).optional(),
});
export const guideDetail = z.object({
chkgdnFk: z.number().nullable(),
utztnUsgCd: z.string(),
chckYmd: z.string(),
ym: z.string(),
splyUswtrUtztnQnt: z.number(),
ruseFcltUtztnQnt: z.number(),
flg: z.string(),
});
export const rainChkZod = z.object({
chkgdnPk: z.number().nullable(),
bdstRuseFcltFk: z.number(),
chckYmd: z.string(),
cityText:z.string().nullish(),
sggText:z.string().nullish(),
prcsCpct: z.number().nullable(),
spwtPositn: z.string().nullable(),
regDt: z.string().nullable(),
rgtr: z.string().nullable(),
mdfcnDt: z.string().nullable(),
mdfr: z.string().nullable(),
flg: z.string().nullable(),
guideDetails: z.array(guideDetail),
building: z
.object({
bdstInfoPk: z.number(),
ctpvCd: z.number(),
sggCd: z.number(),
daddr: z.string().nullable(),
bdstNm: z.string(),
frstArchPrmsnDt: z.string().nullable(),
archArea: z.number(),
regDt: z.string().nullable(),
rgtr: z.string().nullable(),
mdfcnDt: z.string().nullable(),
mdfr: z.string().nullable(),
})
.nullable(),
rainyDetails: z.array(
z.object({
chkgdnFk: z.number().nullable(),
utztnUsgCd: z.string(),
ph: z.number().nullable(),
trbt: z.number().nullable(),
grssClfg: z.number().nullable(),
etc: z.string().nullable(),
vltnDt: z.string().nullable(),
vltnMttr: z.string().nullable(),
levyAmt: z.number().nullable(),
regDt: z.string().nullable(),
rgtr: z.string().nullable(),
mdfcnDt: z.string().nullable(),
mdfr: z.string().nullable(),
})
),
});
export type chHeadType = {
headNm: string;
text: string;
length: number;
rows?: number;
};
export type splRuseWaterType = {
utztnUsgCd: string;
splTotal: number;
spl01: number;
spl02: number;
spl03: number;
spl04: number;
spl05: number;
spl06: number;
spl07: number;
spl08: number;
spl09: number;
spl10: number;
spl11: number;
spl12: number;
ruseTotal: number;
ruse01: number;
ruse02: number;
ruse03: number;
ruse04: number;
ruse05: number;
ruse06: number;
ruse07: number;
ruse08: number;
ruse09: number;
ruse10: number;
ruse11: number;
ruse12: number;
};
export const rainHeadNmExport: chHeadType[] = [
{ headNm: "useQuilty", text: "이용수질(필요시)", length: 3 },
{ headNm: "feeHist", text: "과태료 부과내역", length: 3 },
{ headNm: "ruseWater", text: "연간보급수 이용량(m³)", length: 13 },
{ headNm: "detailQulity", text: "분기", length: 11 },
{ headNm: "splWater", text: "연간빗물 이용량(m³)", length: 13 },
];
export const rainChkgdnHeadListExport: TableUpperProps[] = [
{ id: "order", title: "순번", mergeCell: true },
{ id: "checkBox", title: "선택", mergeCell: true },
{ id: "cityText", title: "시도", mergeCell: true },
{ id: "sggText", title: "시군구", mergeCell: true },
{ id: "bdstNm", title: "시설명", mergeCell: true },
{ id: "operMngCd", title: "운영관리형태", mergeCell: true },
{ id: "oilqMeasMthd", title: "유량측정방법", mergeCell: true },
{ id: "anlOperCst", title: "연간운영비(원/년)", mergeCell: true },
{ id: "dtfcltCpct", title: "빗물저류조용량(m³)", mergeCell: true },
{ id: "chckYmd", title: "점검일", mergeCell: true },
{ id: "utztnUsgCd", title: "이용용도" },
{ id: "totalSplyUswtrUtztnQnt", title: "연간보급수이용량(m³)" },
{ id: "totalRuseFcltUtztnQnt", title: "연간빗물이용량(m³)" },
{
id: "ph",
title: "PH",
upName: "useQuilty",
upSequnce: 1,
type: "number",
edit: true,
},
{
id: "trbt",
title: "탁도",
upName: "useQuilty",
upSequnce: 2,
type: "number",
edit: true,
},
{
id: "grssClfg",
title: "총대장균군수",
upName: "useQuilty",
upSequnce: 3,
type: "number",
edit: true,
},
{
id: "vltnDt",
title: "부과일(위반일)",
upName: "feeHist",
upSequnce: 1,
type: "text",
edit: true,
},
{
id: "vltnMttr",
title: "위반사항",
upName: "feeHist",
upSequnce: 2,
type: "text",
edit: true,
},
{
id: "levyAmt",
title: "부과금액(천원)",
upName: "feeHist",
upSequnce: 3,
type: "number",
edit: true,
},
];
export const ruseHeadListExport: TableUpperProps[] = [
{ id: "utztnUsgCd", title: "이용용도" },
{ id: "ruseTotal", title: "계", upName: "ruseWater", upSequnce: 1 },
{ id: "ruse01", title: "1월", upName: "ruseWater", upSequnce: 2 , edit: true },
{ id: "ruse02", title: "2월", upName: "ruseWater", upSequnce: 3 , edit: true },
{ id: "ruse03", title: "3월", upName: "ruseWater", upSequnce: 4 , edit: true },
{ id: "ruse04", title: "4월", upName: "ruseWater", upSequnce: 5 , edit: true },
{ id: "ruse05", title: "5월", upName: "ruseWater", upSequnce: 6 , edit: true },
{ id: "ruse06", title: "6월", upName: "ruseWater", upSequnce: 7 , edit: true },
{ id: "ruse07", title: "7월", upName: "ruseWater", upSequnce: 8 , edit: true },
{ id: "ruse08", title: "8월", upName: "ruseWater", upSequnce: 9 , edit: true },
{ id: "ruse09", title: "9월", upName: "ruseWater", upSequnce: 10, edit: true },
{ id: "ruse10", title: "10월", upName: "ruseWater", upSequnce: 11 , edit: true },
{ id: "ruse11", title: "11월", upName: "ruseWater", upSequnce: 12 , edit: true },
{ id: "ruse12", title: "12월", upName: "ruseWater", upSequnce: 13 , edit: true },
];
export const splHeadListExport: TableUpperProps[] = [
{ id: "utztnUsgCd", title: "이용용도" },
{ id: "splTotal", title: "계", upName: "splWater", upSequnce: 1},
{ id: "spl01", title: "1월", upName: "splWater", upSequnce: 2, edit: true },
{ id: "spl02", title: "2월", upName: "splWater", upSequnce: 3, edit: true },
{ id: "spl03", title: "3월", upName: "splWater", upSequnce: 4, edit: true },
{ id: "spl04", title: "4월", upName: "splWater", upSequnce: 5, edit: true },
{ id: "spl05", title: "5월", upName: "splWater", upSequnce: 6, edit: true },
{ id: "spl06", title: "6월", upName: "splWater", upSequnce: 7, edit: true },
{ id: "spl07", title: "7월", upName: "splWater", upSequnce: 8, edit: true },
{ id: "spl08", title: "8월", upName: "splWater", upSequnce: 9, edit: true },
{ id: "spl09", title: "9월", upName: "splWater", upSequnce: 10, edit: true },
{ id: "spl10", title: "10월", upName: "splWater", upSequnce: 11, edit: true },
{ id: "spl11", title: "11월", upName: "splWater", upSequnce: 12, edit: true },
{ id: "spl12", title: "12월", upName: "splWater", upSequnce: 13, edit: true },
];
@@ -0,0 +1,271 @@
import { buildingType } from "@/app/store/common/code";
import {
TEST_UUID,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import {
deleteFectch,
fetchType,
getFetch,
postFectch,
putFectch,
} from "@/components/lib/api";
import { ToastFormUi } from "@/components/ui/toast/toastFromUi";
import type { SelectDataType } from "@common/business_components/ui";
import { z } from "zod";
import { buildingToExcelType } from "./excel";
import {
rainChkgdnHeadListExport,
rainChkZod,
rainHeadNmExport,
ruseHeadListExport,
splHeadListExport,
type chHeadType,
} from "./headList";
import type { TableUpperProps } from "@/app/store/common/type/header";
export type rainChkZodType = z.infer<typeof rainChkZod>;
const fcltDiv = [
{ val: "RST", text: "중수도시설" },
{ val: "RNB", text: "빗물이용시설" },
];
const rainHeadNm = rainHeadNmExport;
const rainChkgdnHeadList = rainChkgdnHeadListExport;
const ruseHeadList = ruseHeadListExport;
const splHeadList = splHeadListExport;
const rainChk: rainChkZodType[] = [];
export type rainChkgdnState = {
rainChkgdn: {
rainChkgdnHeadList: TableUpperProps[];
rainChk: rainChkZodType[];
rainHeadNm: chHeadType[];
ruseHeadList: TableUpperProps[];
splHeadList: TableUpperProps[];
isInit: boolean;
isModalClose: boolean;
fcltDiv: SelectDataType[];
excelList: [];
isSttn: boolean;
};
};
type rainChkgdnActions = {
rainChkInit: (sggCd: string, searchTxt: string) => void;
rainChkDetilUpdate(rainChk: rainChkZodType[]): Promise<void>;
rainChkGuidUpdate(rainChk: rainChkZodType): Promise<void>;
rainChkExcelDownload(
sidoCode: SelectDataType[],
sggCode: SelectDataType[]
): Promise<void>;
rainChkExcelDataUPload(excelData: rainChkZodType[]): Promise<void>;
rainChkDelete(chkgdnPks: number[]): Promise<void>;
rainChkHeadChange: (rainChkgdn: rainChkgdnState, isEdit :boolean) => void;
};
export type rainChkgdnType = rainChkgdnState & rainChkgdnActions;
export const rainChkgdnStateExport: rainChkgdnState = {
rainChkgdn: {
rainChkgdnHeadList: rainChkgdnHeadList,
rainHeadNm: rainHeadNm,
rainChk: rainChk,
splHeadList: splHeadList,
ruseHeadList: ruseHeadList,
isInit: false,
isModalClose: false,
excelList: [],
fcltDiv: fcltDiv,
isSttn: false,
},
};
const makeMdfrChk = (data: rainChkZodType[], type: string, toDo: string) => {
const chData = data.map((item) => {
item.mdfr = TEST_UUID;
item.rgtr = TEST_UUID;
if (type === "rainyDetails") {
item.rainyDetails.forEach((item) => {
item.mdfr = TEST_UUID;
item.rgtr = TEST_UUID;
});
} else {
}
return item;
});
return chData;
};
const initFetch = async (txt: string | undefined, sgg: string | undefined) => {
const rainRes = await getFetch(
"wr",
`/reuseChk/rainy` + (txt ? `/${txt}` : "2024") + (sgg ? `/${sgg}` : "/0")
);
return rainRes;
};
export const rainChkgdnActionsExport: (set: any) => rainChkgdnActions = (
set: any
) => {
return {
rainChkExcelDownload: async (
sidoCode: SelectDataType[],
sggCode: SelectDataType[]
) => {
// 로그인한 아이디의 시도 or 시군구로 들어가야하는데 현재는 그냥 0으로 하드코딩
const data = await getFetch(
fetchType.WR,
`/reuseFc/buildingFlg/${buildingType.RNB}/41`
);
const excelList = buildingToExcelType(data, sidoCode, sggCode);
set((state: rainChkgdnState) => ({
rainChkgdn: {
...state.rainChkgdn,
excelList: excelList,
},
}));
},
rainChkExcelDataUPload: async (excelData: rainChkZodType[]) => {
try {
const res = await postFectch("/reuseChk/rainy", excelData);
if (res.ok) {
ToastFormUi({
body: "지도점검 등록이 완료되었습니다. ",
title: "지도점검 등록",
});
}
const rainChkRes = await initFetch("2024", "0");
return set((state: rainChkgdnState) => ({
...state,
rainChkgdn: {
...state.rainChkgdn,
rainChk: rainChkRes,
},
}));
} catch (error) {
console.log(error);
ToastFormUi({
body: "지도점검 등록이 실패되었습니다.",
title: "지도점검 등록",
});
}
},
rainChkInit: async (searchTxt: string, sggCd: string) => {
try {
const rainChkRes = await initFetch(searchTxt, sggCd);
return set((state: rainChkgdnState) => ({
...state,
rainChkgdn: {
...state.rainChkgdn,
rainChk: rainChkRes,
},
}));
} catch (error) {
console.log(error);
}
},
rainChkDetilUpdate: async (rainChk: rainChkZodType[]) => {
try {
const chData = await makeMdfrChk(rainChk, "rain", "rainDetil");
const res = await postFectch("/reuseChk/rainy", chData);
if (res.ok) {
ToastFormUi({
body: "지도점검 보급수 및 밋물이용량 수정이 완료되었습니다. ",
title: "지도점검 수정",
});
}
const rainChkRes = await initFetch("2024", "0");
return set((state: rainChkgdnState) => ({
...state,
rainChkgdn: {
...state.rainChkgdn,
rainChk: rainChkRes,
},
}));
} catch (error) {
console.log(error);
alert("수정에 실패하였습니다.");
}
},
rainChkGuidUpdate: async (rainChk: rainChkZodType) => {
try {
//const chData = await makeMdfrChk(rainChk, "guideDetails", "rainDetil");
const res = await putFectch("/reuseChk/rainy", rainChk);
if (res.ok) {
ToastFormUi({
body: "지도점검 수질 및 과태료 수정이 완료되었습니다. ",
title: "지도점검 수정",
});
}
const rainChkRes = await initFetch("2024", "0");
return set((state: rainChkgdnState) => ({
...state,
rainChkgdn: {
...state.rainChkgdn,
rainChk: rainChkRes,
},
}));
} catch (error) {
console.log(error);
}
},
rainChkDelete: async (chkgdnPks: number[]) => {
try {
const res = await deleteFectch(`/reuseChk/rainy`, chkgdnPks);
if (res) {
ToastFormUi({
body: "삭제가 완료되었습니다. ",
title: "지도점검 삭제",
});
}
const rainChkRes = await initFetch("2024", "0");
return set((state: rainChkgdnState) => ({
...state,
rainChkgdn: {
...state.rainChkgdn,
rainChk: rainChkRes,
},
}));
} catch (error) {
ToastFormUi({ body: "삭제를 실패했습니다.. ", title: "지도점검 삭제" });
}
},
rainChkHeadChange: async (rainChkgdn: rainChkgdnState , isEdit :boolean) => {
try {
const rainChkgdnHeadList = rainChkgdn.rainChkgdn.rainChkgdnHeadList;
const splHeadList = rainChkgdn.rainChkgdn.splHeadList;
const ruseHeadList = rainChkgdn.rainChkgdn.ruseHeadList;
rainChkgdnHeadList.forEach(( head) => {
if(head.edit!== undefined)
head.edit=isEdit;
});
splHeadList.forEach((head) => {
if(head.edit!== undefined)
head.edit=isEdit;
});
ruseHeadList.forEach((head) => {
if(head.edit!== undefined)
head.edit=isEdit;
});
return set((state: rainChkgdnState) => ({
...state,
rainChkgdn: {
...state.rainChkgdn,
rainChkgdnHeadList: rainChkgdnHeadList,
splHeadList:splHeadList,
ruseHeadList:ruseHeadList
},
}));
} catch (error) {
console.log(error);
}
},
};
};
@@ -0,0 +1,237 @@
import type { SelectDataType } from "@common/business_components/ui";
import { useTypes, type Buildingtype } from "../rainChkgdn/excel";
import { TEST_UUID } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import type { rswtChkZodType } from ".";
export const rswtMakeExcelSample = (
buildings: Buildingtype[],
sidoCode: SelectDataType[],
sggCdoe: SelectDataType[]
) => {
const excelSite = {
guideDetail: [] as string[][],
polutions: [] as string[][],
};
//첫번째 시트 데이터 이용량 현황 양식만들기
buildings.forEach((building) => {
useTypes.forEach((useType) => {
excelSite.guideDetail.push([
building.bdstInfoPk.toString(),
sidoCode.find((sido) => sido.val === building.ctpvCd.toString())
?.text || "",
sggCdoe.find((sido) => sido.val === building.sggCd.toString())?.text ||
"",
building.bdstNm,
building.daddr,
"",
"",
"",
"",
"",
"",
useType,
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
]);
});
});
//두번째 시트 양식 만들기 오염도
buildings.forEach((building) => {
useTypes.forEach((useType) => {
excelSite.polutions.push([
building.bdstInfoPk.toString(),
sidoCode.find((sido) => sido.val === building.ctpvCd.toString())
?.text || "",
sggCdoe.find((sido) => sido.val === building.sggCd.toString())?.text ||
"",
building.bdstNm,
building.daddr,
"",
"",
"",
"",
"",
useType,
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
]);
});
});
return excelSite;
};
export const excelToRswtGuideData = (excelData: any, year: string) => {
const rainChkgdData: rswtChkZodType[] = excelData
.map((item: any) => {
if (item["점검일"] !== undefined) {
const checkYmd = item["점검일"].replace(/\./g, "")
const makeGuidDetail = Array.from({ length: 12 }, (_, i) => {
let month = `${i + 1}`;
const splyData = item[`대체수_${month}월`];
const rswtData = item[`중수_${month}월`];
if (month.length < 2) month = "0" + month;
return {
ym: year + month,
chckYmd: checkYmd,
splyUswtrUtztnQnt: splyData !== "" ? splyData : 0,
ruseFcltUtztnQnt: rswtData !== "" ? rswtData : 0,
};
});
return {
bdstRuseFcltFk: Number(item["NO"]),
operMngCd: item["운영관리형태"],
anlOperCst: Number(item["연간운영비(원/년)"]) ?? 0,
prcsCpct: item["처리용량(m³)"],
spwtPositn: item["채수지점"],
chckYmd:checkYmd,
utztnUsgCd: item["이용용도"],
guideDetails: makeGuidDetail,
rgtr: TEST_UUID,
mdfr: TEST_UUID,
};
}
})
.filter((el: any) => el !== undefined);
return rainChkgdData;
};
export const excelToRswtPolution = (excelData: any, year: string) => {
const rainChkgdData: rswtChkZodType[] = excelData
.map((item: any) => {
if (item["점검일"] !== undefined) {
const checkYmd = item["점검일"].replace(/\./g, "")
let vltnDt = item["과태료 부과일(위반일)"]
if (vltnDt !== undefined) {
vltnDt = vltnDt .replace(/\./g, "")
}
const makePoluttion = Array.from({ length: 4 }, (_, i) => {
let quarter = `${i+1}`;
const grssClfgUswtr = item[`${quarter}분기_총대장균군수`];
const combResdch = item[`${quarter}분기_결합잔류염소`];
const trbt = item[`${quarter}분기_탁도`];
const bod = item[`${quarter}분기_BOD`];
const smll = item[`${quarter}분기_냄새`];
const crmty = item[`${quarter}분기_색도`];
const tph = item[`${quarter}분기_T-P`];
const tn = item[`${quarter}분기_T-N`];
const ph = item[`${quarter}분기_PH`];
const clIonQnt = item[`${quarter}분기_염화물`];
return {
node: quarter,
chckYmd: checkYmd,
grssClfgUswtr: grssClfgUswtr !== "" ? grssClfgUswtr : 0,
combResdch: combResdch !== "" ? combResdch : 0,
trbt: trbt !== "" ? trbt : 0,
bod: bod !== "" ? bod : 0,
smll: smll !== "" ? smll : 0,
crmty: crmty !== "" ? crmty : 0,
tph: tph !== "" ? tph : 0,
tn: tn !== "" ? tn : 0,
ph: ph !== "" ? ph : 0,
clIonQnt: clIonQnt !== "" ? clIonQnt : 0,
rgtr: TEST_UUID,
mdfr: TEST_UUID,
};
});
return {
bdstRuseFcltFk: Number(item["NO"]),
chckYmd: checkYmd,
utztnUsgCd: item["이용용도"],
operMngCd: item["운영관리형태"],
anlOperCst: Number(item["연간운영비(원/년)"]) ?? 0,
prcsCpct: item["처리용량(m³)"],
spwtPositn: item["채수지점"],
rswtrPollutions: makePoluttion,
rgtr: TEST_UUID,
mdfr: TEST_UUID,
rswtrDetails: [
{
utztnUsgCd: item["이용용도"],
vltnDt:vltnDt,
vltnMttr: item["위반사항"],
levyAmt: Number(item["과태료 부과금액(천원)"]) ?? 0,
rgtr: TEST_UUID,
mdfr: TEST_UUID,
},
],
};
}
})
.filter((el: any) => el !== undefined);
return rainChkgdData;
};
@@ -0,0 +1,231 @@
import { z } from "zod";
import { guideDetail, type chHeadType } from "../rainChkgdn/headList";
import type { TableUpperProps } from "@/app/store/common/type/header";
export type polutionType = {
chkgdnDtlFk: number;
utztnUsgCd: string;
node: number;
grssClfgUswtr: number;
combResdch: number;
trbt: number;
bod: number;
smll: number;
crmty: number;
tph: number;
tn: number;
ph: number;
clIonQnt: number;
edit?:boolean
};
const reuseBuildingZod = z.object({
bdstRuseFcltPk: z.number().nullish(),
bdstInfoFk: z.number().nullish(),
instlCmptnDt: z.string().nullable(), // Assuming it's a date string or null
instlCst: z.number(),
operMngCd: z.string().nullable(),
instlCstSprtYn: z.string().nullable(), // Assuming 'Y'/'N' or similar, or null
instlCstSprtAmt: z.number(),
grntchBdstCertYn: z.string().nullable(),
grntchBdstCertYr: z.string().nullable(), // Could be z.number().nullable() if it's strictly a year number
grntchBdstCertNo: z.string().nullable(),
grntchBdstCertGrd: z.string().nullable(),
crgRdctYn: z.string().nullable(),
crgRdctBss: z.string().nullable(),
crgRdctAmt: z.number(),
ruseFcltFlg: z.string().nullable(),
bdstUsgCd: z.number(),
lawTrgtYn: z.string().nullable(), // Assuming 'Y'/'N' or similar, or null
rgtr: z.string(), // Assuming this is a UUID
mdfr: z.string(), // Assuming this is a UUID
});
const buildingZod = z.object({
bdstInfoPk: z.number().nullable(),
ctpvCd: z.number(),
sggCd: z.number(),
daddr: z.string().nullable(),
bdstNm: z.string(),
frstArchPrmsnDt: z.string().nullable(), // Assuming it's a date string or null
archArea: z.number(),
rgtr: z.string(), // Assuming this is a UUID
mdfr: z.string(), // Assuming this is a UUID
});
export const rswtrPolutionsZode = z.object({
chkgdnDtlFk: z.string().nullish(),
utztnUsgCd: z.string().nullish(),
node: z.string().nullish(),
grssClfgUswtr: z.number(),
combResdch: z.number(),
trbt: z.number(),
bod: z.number(),
smll: z.number(),
crmty: z.number(),
tph: z.number(),
tn: z.number(),
ph: z.number(),
clIonQnt: z.number(),
regDt: z.string().nullish(),
rgtr: z.string().nullish(),
mdfcnDt: z.string().nullish(),
mdfr: z.string().nullish(),
edit:z.boolean().nullish()
});
export const rswtrDetailsZod = z.object({
chkgdnDtlPk: z.string().nullish(),
chkgdnFk: z.string().nullish(),
utztnUsgCd: z.string(),
vltnDt: z.string(),
vltnMttr: z.string(),
levyAmt: z.number(),
regDt: z.string().nullish(),
rgtr: z.string().nullish(),
mdfcnDt: z.string().nullish(),
mdfr: z.string().nullish(),
})
export const rswtChkgdZod = z.object({
chkgdnPk: z.number().nullish(),
bdstRuseFcltFk: z.number().nullish(),
chckYmd: z.string(),
prcsCpct: z.number(),
dtfcltCpct: z.number(),
spwtPositn: z.string(),
regDt: z.string().nullish(),
rgtr: z.string().nullish(),
mdfcnDt: z.string().nullish(),
mdfr: z.string().nullish(),
anlOperCst:z.number(),
oilqMeasMthd: z.string().nullish(),
utztnUsgCd: z.string(),
building: buildingZod,
guideDetails: z.array(guideDetail),
reuseBuilding: reuseBuildingZod,
rswtrDetails: z.array(
rswtrDetailsZod
),
rswtrPollutions: z.array(rswtrPolutionsZode),
});
export const rswtHeadNmExport: chHeadType[] = [
{ headNm: "useQuilty", text: "연간 평균 이용수질", length: 10 },
{ headNm: "feeHist", text: "과태료 부과내역", length: 3 },
];
export const rswtChkHeadListExport: TableUpperProps[] = [
{ id: "order", title: "순번", mergeCell: true },
{ id: "checkBox", title: "선택", mergeCell: true },
{ id: "cityText", title: "시도" ,mergeCell: true },
{ id: "sggText", title: "시군구",mergeCell: true },
{ id: "bdstNm", title: "시설명" ,mergeCell: true},
{ id: "operMngCd", title: "운영관리형태" ,mergeCell: true},
{ id: "anlOperCst", title: "연간운영비(원/년)" ,mergeCell: true},
{ id: "prcsCpct", title: "처리용량(m³)" ,mergeCell: true},
{ id: "spwtPositn", title: "채수지점" ,mergeCell: true},
{ id: "chckYmd", title: "점검일" ,mergeCell: true},
{ id: "utztnUsgCd", title: "이용용도" },
{ id: "splyUswtrUtztnQnt", title: "연간보급수이용량(m³)" ,type: "number"},
{ id: "ruseFcltUtztnQnt", title: "연간중수도이용량(m³)",type: "number"},
{
id: "grssClfgUswtr",
title: "총대장균군수",
upName: "useQuilty",
upSequnce: 1,
type: "number"
},
{
id: "combResdch",
title: "결합잔류염소",
upName: "useQuilty",
upSequnce: 2,
type: "number"
},
{ id: "trbt", title: "탁도", upName: "useQuilty", upSequnce: 3 ,type: "number"},
{ id: "bod", title: "BOD", upName: "useQuilty", upSequnce: 4 ,type: "number"},
{ id: "smll", title: "냄새", upName: "useQuilty", upSequnce: 5 ,type: "number"},
{ id: "crmty", title: "색도", upName: "useQuilty", upSequnce: 6 ,type: "number"},
{ id: "tn", title: "T-N", upName: "useQuilty", upSequnce: 7 ,type: "number"},
{ id: "tph", title: "T-P", upName: "useQuilty", upSequnce: 8 ,type: "number"},
{ id: "ph", title: "PH", upName: "useQuilty", upSequnce: 9,type: "number" },
{ id: "clIonQnt", title: "염화물", upName: "useQuilty", upSequnce: 10 ,type: "number"},
{
id: "vltnDt",
title: "부과일(위반일)",
upName: "feeHist",
upSequnce: 1,
type: "text",
edit:true
},
{
id: "vltnMttr",
title: "위반사항",
upName: "feeHist",
upSequnce: 2,
type: "text",
edit:true
},
{
id: "levyAmt",
title: "부과금액(천원)",
upName: "feeHist",
upSequnce: 3,
type: "number",
edit:true
}];
export const rswtDetailHeadListExport: TableUpperProps[] = [
{ id: "utztnUsgCd", title: "이용용도" },
{
id: "grssClfgUswtr",
title: "총대장균군수",
upName: "detailQulity",
upSequnce: 2,
edit: true,
},
{
id: "combResdch",
title: "결합잔류염소",
upName: "detailQulity",
upSequnce: 3,
edit: true,
},
{
id: "trbt",
title: "탁도",
upName: "detailQulity",
upSequnce: 4,
edit: true,
},
{ id: "bod", title: "BOD", upName: "detailQulity", upSequnce: 5, edit: true },
{
id: "smll",
title: "냄새",
upName: "detailQulity",
upSequnce: 6,
edit: true,
},
{
id: "crmty",
title: "색도",
upName: "detailQulity",
upSequnce: 7,
edit: true,
},
{ id: "tn", title: "T-N", upName: "detailQulity", upSequnce: 8, edit: true },
{ id: "tph", title: "T-P", upName: "detailQulity", upSequnce: 9, edit: true },
{ id: "ph", title: "PH", upName: "detailQulity", upSequnce: 10, edit: true },
{
id: "clIonQnt",
title: "염화물",
upName: "detailQulity",
upSequnce: 11,
edit: true,
},
];
@@ -0,0 +1,299 @@
import {
TEST_UUID,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import type {
SelectDataType,
SheetParameter,
} from "@common/business_components";
import {
deleteFectch,
fetchType,
getFetch,
postFectch,
putFectch,
} from "@/components/lib/api";
import { buildingType } from "@/app/store/common/code";
import { rswtMakeExcelSample } from "./excel";
import {
rswtChkgdZod,
rswtChkHeadListExport,
rswtDetailHeadListExport,
rswtHeadNmExport,
rswtrDetailsZod,
} from "./headList";
import { z } from "zod";
import { ToastFormUi } from "@/components/ui/toast/toastFromUi";
import { type chHeadType } from "../rainChkgdn/headList";
import type { TableUpperProps } from "@/app/store/common/type/header";
const rswtChkHeadList = rswtChkHeadListExport;
const rswtDetailHeadList = rswtDetailHeadListExport;
const rswtHeadNm = rswtHeadNmExport;
export type rswtChkZodType = z.infer<typeof rswtChkgdZod>;
export type rswtrChkDetailsZodType = z.infer<typeof rswtrDetailsZod>;
export type rswtChkgdnState = {
rswtChkgdn: {
rswtChkHeadList: TableUpperProps[];
rswtDetailHeadList: TableUpperProps[];
rswtHeadNm: chHeadType[];
excelList: SheetParameter[];
rswtChkRes: rswtChkZodType[];
rswtChkPolGuide: rswtChkZodType[];
isInit: boolean;
isSttn:boolean
};
};
type rswtChkgdnActions = {
rswtChkgdnInit: (year: string, sggCd: string) => void;
rswtrChkExcelDownload(
sidoCode: SelectDataType[],
sggCode: SelectDataType[]
): Promise<void>;
rswtChkExceDataUpload: (excelData: rswtChkZodType[]) => void;
rswtChkDelete: (chkgdnPks: number[]) => void;
rswtChkDetilsUpdate: (rswtChkDetails: rswtrChkDetailsZodType[]) => void;
rswtChkPolAndGuide: (chkGdnPk: number) => void;
rswtChkPolInit: () => void;
rwstPolAndGuideUpdate: (rswtChk: rswtChkZodType[]) => void;
rswtChkHeadChange: (rswtChkgdn: rswtChkgdnState, isEdit: boolean) => void;
};
export type rswtChkgdnType = rswtChkgdnState & rswtChkgdnActions;
export const rswtChkgdnStateExport: rswtChkgdnState = {
rswtChkgdn: {
rswtChkHeadList: rswtChkHeadList,
rswtDetailHeadList: rswtDetailHeadList,
rswtHeadNm: rswtHeadNm,
excelList: [{
data: [[]], headerNum: 0, headerRange: "A1:V3",
sheetName: "",
startCol: '1'
}],
rswtChkRes: [],
rswtChkPolGuide: [],
isInit: false,
isSttn:false,
},
};
const initFetch = async (year: string | undefined, sgg: string | undefined) => {
const rswtChkRes = await getFetch(
"wr",
`/reuseChk/reuseWater/` +
(year ? `${year}` : "2024") +
(sgg ? `/${sgg}` : "/0")
);
return rswtChkRes;
};
const makeMdfrChk = (data: rswtChkZodType[] | rswtrChkDetailsZodType[]) => {
const chData = data.map((item) => {
item.mdfr = TEST_UUID;
item.rgtr = TEST_UUID;
if ("rswtrPollutions" in item) {
item?.rswtrPollutions.forEach((pollution) => {
pollution.mdfr = TEST_UUID;
pollution.rgtr = TEST_UUID;
});
}
return item;
});
return chData;
};
export const rswtChkgdnActionsExport: (set: any) => rswtChkgdnActions = (
set: any
) => {
return {
rswtrChkExcelDownload: async (
sidoCode: SelectDataType[],
sggCode: SelectDataType[]
) => {
const data = await getFetch(
fetchType.WR,
`/reuseFc/buildingFlg/${buildingType.RST}/41`
);
const excelList: any = [];
const exceldata = rswtMakeExcelSample(data, sidoCode, sggCode);
excelList.push({
data: exceldata.guideDetail,
headerNum: 0,
headerRange: "A1:AI1",
});
excelList.push({
data: exceldata.polutions,
headerNum: 0,
headerRange: "A1:AZ1",
});
return set((state: rswtChkgdnState) => ({
rswtChkgdn: {
...state.rswtChkgdn,
excelList: excelList,
},
}));
},
rswtChkgdnInit: async (year: string, sggCd: string) => {
try {
const rswtChkRes = await initFetch("2024", sggCd);
return set((state: rswtChkgdnState) => ({
...state,
rswtChkgdn: {
...state.rswtChkgdn,
rswtChkRes: rswtChkRes,
isInit: false,
},
}));
} catch (error) {
console.log(error);
}
},
rswtChkExceDataUpload: async (excelData: rswtChkZodType[]) => {
try {
const res = await postFectch("/reuseChk/reuseWater", excelData);
if (res.ok) {
ToastFormUi({
body: "지도점검 등록이 완료되었습니다.",
title: "지도점검 등록",
});
}
// const rainChkRes = await initFetch('2024', '0');
return set((state: rswtChkgdnState) => ({
...state,
rswtChkgdn: {
...state.rswtChkgdn,
},
}));
} catch (error) {
console.log(error);
}
},
rswtChkDetilsUpdate: async (rswtChk: rswtrChkDetailsZodType[]) => {
try {
const chData = await makeMdfrChk(rswtChk);
const res = await putFectch("/reuseChk/reuseWater", chData);
if (res.ok) {
ToastFormUi({
body: "지도점검 과태료 수정 수정이 완료되었습니다. ",
title: "지도점검 수정",
});
}
const rswtChkRes = await initFetch("2024", "0");
return set((state: rswtChkgdnState) => ({
...state,
rswtChkgdn: {
...state.rswtChkgdn,
rswtChkRes: rswtChkRes,
},
}));
} catch (error) {
console.log(error);
alert("수정에 실패하였습니다.");
}
},
rswtChkDelete: async (chkgdnPks: number[]) => {
try {
const res = await deleteFectch(`/reuseChk/reuseWater`, chkgdnPks);
if (res.ok) {
ToastFormUi({
body: "삭제가 완료되었습니다. ",
title: "지도점검 삭제",
});
}
const rswtChkRes = await initFetch("2024", "0");
return set((state: rswtChkgdnState) => ({
...state,
rswtChkgdn: {
...state.rswtChkgdn,
rswtChkRes: rswtChkRes,
},
}));
} catch (error) {
ToastFormUi({ body: "삭제를 실패했습니다.. ", title: "지도점검 삭제" });
}
},
rswtChkPolAndGuide: async (chkGdnPk: number) => {
try {
const rswtChkPolGuide = await getFetch(
"wr",
`/reuseChk/reuseWater/${chkGdnPk}`
);
return set((state: rswtChkgdnState) => ({
...state,
rswtChkgdn: {
...state.rswtChkgdn,
rswtChkPolGuide: rswtChkPolGuide,
},
}));
} catch (error) {}
},
rswtChkPolInit: () => {
try {
return set((state: rswtChkgdnState) => ({
...state,
rswtChkgdn: {
...state.rswtChkgdn,
rswtChkPolGuide: undefined,
},
}));
} catch (error) {}
},
rwstPolAndGuideUpdate: async (rswtChk: rswtChkZodType[]) => {
try {
const chData = await makeMdfrChk(rswtChk);
const res = await putFectch(
`/reuseChk/reuseWater/${rswtChk[0]?.chkgdnPk}`,
chData[0]
);
if (res.ok) {
ToastFormUi({
body: "지도점검 연간 수질 및 보급수/중수도 수정이 완료되었습니다. ",
title: "지도점검 수정",
});
}
const rswtChkRes = await initFetch("2024", "0");
return set((state: rswtChkgdnState) => ({
...state,
rswtChkgdn: {
...state.rswtChkgdn,
rswtChkRes: rswtChkRes,
},
}));
} catch (error) {
console.log(error);
ToastFormUi({
body: "지도점검 연간 수질 및 보급수/중수도 수정이 실패하였습니다.. ",
title: "지도점검 수정",
});
}
},
rswtChkHeadChange: async (rswtChkgdn: rswtChkgdnState, isEdit: boolean) => {
try {
const rswtChkHeadList = rswtChkgdn.rswtChkgdn.rswtChkHeadList;
const rswtDetailHeadList = rswtChkgdn.rswtChkgdn.rswtDetailHeadList;
rswtChkHeadList.forEach((head) => {
if (head.edit !== undefined) head.edit = isEdit;
});
rswtDetailHeadList.forEach((head) => {
if (head.edit !== undefined) head.edit = isEdit;
});
return set((state: rswtChkgdnState) => ({
...state,
rswtChkgdn: {
...state.rswtChkgdn,
rswtChkHeadList: rswtChkHeadList,
rswtDetailHeadList: rswtDetailHeadList,
},
}));
} catch (e) {}
},
};
};
@@ -0,0 +1,55 @@
import { TEST_UUID } from "../../ruseFcltMng/fcltReg/rainReg";
type NameMap = {
[key: string]: string;
};
const nameMap:NameMap = {
"세척수": "wshwtr",
"냉각수": "coolUswtr",
"청소수": "cleanUswtr",
"식수대": "drwtUswtr",
"희석용수": "dltnUswtr",
"중수도": "ithlRswtr",
"기타": "ithlEtcUswtr",
"청소화장실용수": "cleanToilUswtr",
"세척살수용수": "resn",
"조경용수": "lndwtr",
"친수용수": "hydUswtr",
"지하수충전": "ugwtChr",
"농업용수": "farmUswtr",
"하천등유지용수": "rvrKeepUswtr",
"공업용수": "indstUswtr"
};
export const excelToPbnPrfData = (excelData: JSON[], year: string,pbnstRuseFcltFk:string) => {
// 월별 데이터 하나로 병합
const merged = {} as any;
excelData.forEach((item: any) => {
const usageNm = item["용수명"]
const key = nameMap[usageNm as any];
if (!key) return;
for (let i = 1; i <= 12; i++) {
const month = i.toString().padStart(2, "0");
const ym = year + month;
if (!merged[ym]) merged[ym] = { ym };
merged[ym][key] = Number(item[`${i}월`] ?? 0);
}
});
const pbnPrfData = Object.values(merged);
const data = pbnPrfData.map((item) => {
return({
...(item as object),
pbnstRuseFcltFk:pbnstRuseFcltFk,
rgtr: TEST_UUID,
mdfr: TEST_UUID,
})
})
return data;
};
@@ -0,0 +1,38 @@
import { z } from "zod";
import type { TableUpperProps } from "../../common/type/header";
export const pbnPrfRegExcelZod = z.object({
ym: z.string().default(""),
bscFctNm: z.string().default(""),
pbnstRuseFcltFk:z.string(),
pbnstRuseFcltNm: z.string().default(""),
file: z.instanceof(File).optional(),
});
export const pbnstPrfmncHeadListExport: TableUpperProps[] = [
{ id: "sido", title: "시도" },
{ id: "gugun", title: "시군구" },
{ id: "bscFctNm", title: "시설명" },
{ id: "ruseUtztnFcltNm", title: "재이용시설명" },
{ id: "pbnstRuseFcltPk", title: "재이용시설코드" },
];
export const monthHeadListExport: TableUpperProps[] = [
{ id: "용수명", title: "용수명" },
{ id: "total", title: "계" },
{ id: "1월", title: "1월" ,edit: true },
{ id: "2월", title: "2월" ,edit: true },
{ id: "3월", title: "3월" ,edit: true },
{ id: "4월", title: "4월" ,edit: true },
{ id: "5월", title: "5월" ,edit: true },
{ id: "6월", title: "6월" ,edit: true },
{ id: "7월", title: "7월" ,edit: true },
{ id: "8월", title: "8월" ,edit: true },
{ id: "9월", title: "9월" ,edit: true },
{ id: "10월", title: "10월" ,edit: true },
{ id: "11월", title: "11월" ,edit: true },
{ id: "12월", title: "12월" ,edit: true },
];
@@ -0,0 +1,111 @@
import { fetchType, getFetch, postFectch } from "@/components/lib/api";
import { pbnstPrfmncHeadListExport, monthHeadListExport } from "./headList";
import type { pubHasuType } from "../../ruseFcltMng/fcltReg/pbnstReg/type";
import type { FcPrfType, PrfType } from "./type";
import type { TableUpperProps } from "../../common/type/header";
import { ToastFormUi } from "@/components/ui/toast/toastFromUi";
import toast from "react-hot-toast";
const pbnstPrfmncHeadList = pbnstPrfmncHeadListExport;
const monthHeadList = monthHeadListExport;
export type pbnstPrfmncState = {
prfmnc: {
isInit: boolean;
pbnstPrfmncHeadList: TableUpperProps[];
monthHeadList: TableUpperProps[];
prfmncRes: FcPrfType[];
excelList: Number[];
};
};
export const pbnstPrfmncStateExport: pbnstPrfmncState = {
prfmnc: {
isInit: false,
pbnstPrfmncHeadList: pbnstPrfmncHeadList,
monthHeadList: monthHeadList,
prfmncRes: [],
excelList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
},
};
export type pbnstPrfmncType = pbnstPrfmncState & pbnstPrfmncActions;
type pbnstPrfmncActions = {
prfmncHasuInit: (page: string, sggOrCity: string) => void;
prfmnRegData: (data: PrfType) => void;
};
const checkWrRegList = async () => {
const wrRegList = await getFetch("wr", `/reuseFc/pubDetailList`);
return wrRegList;
};
const hasuListFetch = async (page: string, sggOrCity: string) => {
const checkWrRegListRes = await checkWrRegList();
const rainRes = await postFectch(
`/prcsFclt/ruseInfo/${page ? page : 1}/10/A/${sggOrCity ? sggOrCity : "11"}/0/1/SW`,
checkWrRegListRes?.fcltCds,
fetchType.COMMON
);
const findData = rainRes.data.map((item: pubHasuType) => {
const data = checkWrRegListRes?.fcPrfList.find(
(fclt: FcPrfType) =>
fclt.pbnstRuseFcltPk.substring(0, 11) === item?.bscFctCd
);
if(data !==undefined){
return( {
sido: item.sido,
gugun: item.gugun,
bscFctNm: item.bscFctNm,
bscFctCd: item.bscFctCd,
ruseUtztnFcltNm: data.ruseUtztnFcltNm,
pbnstRuseFcltPk: data.pbnstRuseFcltPk,
prfList: data.prfList,
});
}
});
return findData;
};
export const pbnstPrfmncActionsExport: (set: any) => pbnstPrfmncActions = (
set: any
) => {
return {
prfmncHasuInit: async (page: string, sggOrCity: string) => {
try {
const prfmncRes = await hasuListFetch(page, sggOrCity);
console.log("prfmncRes", prfmncRes);
return set((state: pbnstPrfmncState) => ({
...state,
prfmnc: {
...state.prfmnc,
prfmncRes: prfmncRes,
isInit: false,
},
}));
} catch (errorHasu) {
console.log(errorHasu);
}
},
prfmnRegData: async (data: PrfType) => {
try {
const ressponse = await postFectch(
"/reuseFc/pubFcPrf",
data,
fetchType.WR
);
if (ressponse.status === 200) {
toast.success("하수재이용 시설 실적 등록이 완료되었습니다.");
}
} catch (e) {
console.log(e);
toast.error("하수재이용 시설 실적 등록이 실패하였습니다.");
}
},
};
};
@@ -0,0 +1,346 @@
import { z } from "zod";
import type { TableUpperProps } from "../../common/type/header";
import { fcOperSchema } from "../../ruseFcltMng/fcltReg/pbnstReg/type";
export const PrfSchema = z.object({
pbnstRuseFcltFk: z.string(),
ym: z.string(), // 예: "202310"
wshwtr: z.number(),
coolUswtr: z.number(),
cleanUswtr: z.number(),
drwtUswtr: z.number(),
dltnUswtr: z.number(),
ithlRswtr: z.number(),
ithlEtcUswtr: z.number(),
cleanToilUswtr: z.number(),
resn: z.number(),
lndwtr: z.number(),
hydUswtr: z.number(),
rvrKeepUswtr: z.number(),
farmUswtr: z.number(),
ugwtChr: z.number(),
indstUswtr: z.number(),
regDt: z.date().default(new Date()).nullish(),
rgtr: z.string().nullish(),
mdfcnDt: z.date().default(new Date()).nullish(),
mdfr: z.string().nullish(),
});
export const FcPrfSchema = z.object({
pbnstRuseFcltPk: z.string(),
ruseUtztnFcltNm: z.string(),
fcltCpct: z.number(),
ruseCpct: z.number(),
splyExtraCpct: z.number(),
regDt: z.date().default(new Date()),
rgtr: z.string(),
mdfcnDt: z.date().default(new Date()),
mdfr: z.string(),
prfList: z.array(PrfSchema),
operList:z.array(fcOperSchema),
bscFctNm: z.string().nullish(),
});
export type FcPrfType = z.infer<typeof FcPrfSchema>;
export type PrfType = z.infer<typeof PrfSchema>;
export const initValInUsage = [
{
usage: "wshwtr",
용수명: "세척수",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "coolUswtr",
용수명: "냉각수",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "cleanUswtr",
용수명: "청소수",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "drwtUswtr",
용수명: "식수대",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "dltnUswtr",
용수명: "희석용수",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "ithlRswtr",
용수명: "중수도",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "ithlEtcUswtr",
용수명: "기타",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
];
export const initValOutUsage = [
{
usage: "resn",
용수명: "세척살수용수",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "cleanToilUswtr",
용수명: "청소화장실용수",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "lndwtr",
용수명: "조경용수",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "hydUswtr",
용수명: "친수용수",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "ugwtChr",
용수명: "지하수충전",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "farmUswtr",
용수명: "농업용수",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "rvrKeepUswtr",
용수명: "하천등유지용수",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
{
usage: "indstUswtr",
용수명: "공업용수",
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
},
];
export const subTotalObj = {
usage: "subtotal",
용수명: "소계",
edit: false,
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
};
export const totalObj = {
usage: "total",
용수명: "총합계",
edit: false,
total: 0,
"1월": 0,
"2월": 0,
"3월": 0,
"4월": 0,
"5월": 0,
"6월": 0,
"7월": 0,
"8월": 0,
"9월": 0,
"10월": 0,
"11월": 0,
"12월": 0,
};
@@ -0,0 +1,41 @@
import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn";
type rainSttnExcelType = {
bdstInfoPk: number;
ctpvCd: 1;
sggCd: 1001;
daddr: "string3";
bdstNm: "string";
frstArchPrmsnDt: "2025-03-25";
archArea: 0;
regDt: "2025-04-16";
rgtr: null;
mdfcnDt: "2025-04-16";
mdfr: null;
};
export const buildingExcelRainSttn = (excelList: any[]) => {
const excelData: string[][] = [];
excelList.forEach((item, index) => {
excelData.push([
String(item.cityText) ?? "",
String(item.sggText) ?? "",
String(item.bdstNm) ?? "",
item.operMngCd || String(item.operMngCd)===null? String(item.operMngCd) : "",
String(item.oilqMeasMthd) ?? "",
String(item.anlOperCst) ?? "",
String(item.dtfcltCpct) ?? "",
String(item.chckYmd) ?? "",
String(item.utztnUsgCd) ?? "",
String(item.totalSplyUswtrUtztnQnt) ?? "",
String(item.totalRuseFcltUtztnQnt) ?? "",
String(item.ph) ?? "",
String(item.trbt) ?? "",
String(item.grssClfg) ?? "",
String(item.vltnDt) ?? "",
String(item.vltnMttr) ?? "",
String(item.levyAmt) ?? "",
]);
});
return excelData;
};
@@ -0,0 +1,163 @@
import type { TableUpperProps } from "@/app/store/common/type/header";
export const rainChkgdnHeadSttnExport: TableUpperProps[] = [
{ id: 'order', title: "순번", mergeCell: true },
{ id: "cityText", title: "시도", mergeCell: true },
{ id: "sggText", title: "시군구", mergeCell: true },
{ id: "bdstNm", title: "시설명", mergeCell: true },
{ id: "operMngCd", title: "운영관리형태", mergeCell: true },
{ id: "oilqMeasMthd", title: "유량측정방법", mergeCell: true },
{ id: "anlOperCst", title: "연간운영비(원/년)", mergeCell: true },
{ id: "dtfcltCpct", title: "빗물저류조용량(m³)", mergeCell: true },
{ id: "chckYmd", title: "점검일", mergeCell: true },
{ id: "utztnUsgCd", title: "이용용도" },
{ id: "totalSplyUswtrUtztnQnt", title: "연간보급수이용량(m³)" },
{ id: "totalRuseFcltUtztnQnt", title: "연간빗물이용량(m³)" },
{
id: "ph",
title: "PH",
upName: "useQuilty",
upSequnce: 1,
type: "number",
},
{
id: "trbt",
title: "탁도",
upName: "useQuilty",
upSequnce: 2,
type: "number",
},
{
id: "grssClfg",
title: "총대장균군수",
upName: "useQuilty",
upSequnce: 3,
type: "number",
},
{
id: "vltnDt",
title: "부과일(위반일)",
upName: "feeHist",
upSequnce: 1,
type: "text",
},
{
id: "vltnMttr",
title: "위반사항",
upName: "feeHist",
upSequnce: 2,
type: "text",
},
{
id: "levyAmt",
title: "부과금액(천원)",
upName: "feeHist",
upSequnce: 3,
type: "number",
},
];
export const ruseSttnHeadListExport: TableUpperProps[] = [
{ id: "utztnUsgCd", title: "이용용도" },
{ id: "ruseTotal", title: "계", upName: "ruseWater", upSequnce: 1 },
{ id: "ruse01", title: "1월", upName: "ruseWater", upSequnce: 2 },
{ id: "ruse02", title: "2월", upName: "ruseWater", upSequnce: 3 },
{ id: "ruse03", title: "3월", upName: "ruseWater", upSequnce: 4 },
{ id: "ruse04", title: "4월", upName: "ruseWater", upSequnce: 5 },
{ id: "ruse05", title: "5월", upName: "ruseWater", upSequnce: 6 },
{ id: "ruse06", title: "6월", upName: "ruseWater", upSequnce: 7 },
{ id: "ruse07", title: "7월", upName: "ruseWater", upSequnce: 8 },
{ id: "ruse08", title: "8월", upName: "ruseWater", upSequnce: 9 },
{ id: "ruse09", title: "9월", upName: "ruseWater", upSequnce: 10 },
{ id: "ruse10", title: "10월", upName: "ruseWater", upSequnce: 11 },
{ id: "ruse11", title: "11월", upName: "ruseWater", upSequnce: 12 },
{ id: "ruse12", title: "12월", upName: "ruseWater", upSequnce: 13 },
];
export const splSttnHeadListExport: TableUpperProps[] = [
{ id: "utztnUsgCd", title: "이용용도" },
{ id: "splTotal", title: "계", upName: "splWater", upSequnce: 1 },
{ id: "spl01", title: "1월", upName: "splWater", upSequnce: 2 },
{ id: "spl02", title: "2월", upName: "splWater", upSequnce: 3 },
{ id: "spl03", title: "3월", upName: "splWater", upSequnce: 4 },
{ id: "spl04", title: "4월", upName: "splWater", upSequnce: 5 },
{ id: "spl05", title: "5월", upName: "splWater", upSequnce: 6 },
{ id: "spl06", title: "6월", upName: "splWater", upSequnce: 7 },
{ id: "spl07", title: "7월", upName: "splWater", upSequnce: 8 },
{ id: "spl08", title: "8월", upName: "splWater", upSequnce: 9 },
{ id: "spl09", title: "9월", upName: "splWater", upSequnce: 10 },
{
id: "spl10",
title: "10월",
upName: "splWater",
upSequnce: 11,
},
{
id: "spl11",
title: "11월",
upName: "splWater",
upSequnce: 12,
},
{
id: "spl12",
title: "12월",
upName: "splWater",
upSequnce: 13,
},
];
export const rswtDetailHeadListExport: TableUpperProps[] = [
{ id: "utztnUsgCd", title: "이용용도" },
{
id: "grssClfgUswtr",
title: "총대장균군수",
upName: "detailQulity",
upSequnce: 2,
},
{
id: "combResdch",
title: "결합잔류염소",
upName: "detailQulity",
upSequnce: 3,
},
{
id: "trbt",
title: "탁도",
upName: "detailQulity",
upSequnce: 4,
},
{
id: "bod",
title: "BOD",
upName: "detailQulity",
upSequnce: 5,
},
{
id: "smll",
title: "냄새",
upName: "detailQulity",
upSequnce: 6,
},
{
id: "crmty",
title: "색도",
upName: "detailQulity",
upSequnce: 7,
},
{ id: "tn", title: "T-N", upName: "detailQulity", upSequnce: 8},
{
id: "tph",
title: "T-P",
upName: "detailQulity",
upSequnce: 9,
},
{ id: "ph", title: "PH", upName: "detailQulity", upSequnce: 10 },
{
id: "clIonQnt",
title: "염화물",
upName: "detailQulity",
upSequnce: 11,
},
];
@@ -0,0 +1,129 @@
import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn";
import { type TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { getFetch } from "@/components/lib/api";
import { ToastFormUi } from "@/components/ui/toast/toastFromUi";
import type { SelectDataType } from "@common/business_components/ui";
import { rainChkgdnHeadSttnExport, ruseSttnHeadListExport, splSttnHeadListExport } from "./headList";
import { rainHeadNmExport, type chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn/headList";
import { buildingExcelRainSttn } from "./excel";
const fcltDiv = [
{ val: "RST", text: "중수도시설" },
{ val: "RNB", text: "빗물이용시설" },
];
const rainChkgdnHeadList = rainChkgdnHeadSttnExport;
const ruseHeadList = ruseSttnHeadListExport;
const splHeadList = splSttnHeadListExport;
const rainHeadNm = rainHeadNmExport
const rainChk: rainChkZodType[] = [];
export type rainChkSttnState = {
rainChkSttn: {
rainChkRes: rainChkZodType[];
fcltDiv: SelectDataType[];
rainChkgdnHeadList: TableUpperProps[];
rainHeadNm:chHeadType[];
ruseHeadList: TableUpperProps[];
splHeadList: TableUpperProps[];
sttnExcelList:[]
isInit: boolean;
isSttn:boolean;
};
};
type rainChkSttnActions = {
rainChkSttnInit: ( sggCd: string) => void;
rainChkSttnSearch: (searchTxt: string, sggCd: string) => void;
isRainSttn:(isSttn:boolean) => void;
getRainSttnExcel:(excelList:rainChkZodType[]) => void;
};
export type rainChkSttnType = rainChkSttnState & rainChkSttnActions;
export const rainChkSttnStateExport: rainChkSttnState = {
rainChkSttn: {
rainChkRes: [],
fcltDiv: fcltDiv,
rainChkgdnHeadList: rainChkgdnHeadList,
ruseHeadList: ruseHeadList,
splHeadList: splHeadList,
rainHeadNm:rainHeadNm,
isInit: false,
sttnExcelList:[],
isSttn:false,
},
};
const initFetch = async (txt: string | undefined, sgg: string | undefined) => {
const rainRes = await getFetch(
"wr",
`/reuseChk/rainy/` + (txt ? `${txt}` : "2024") + (sgg ? `/${sgg}` : "/0")
);
return rainRes;
};
export const rainChkSttnActionsExport: (set: any) => rainChkSttnActions = (
set: any
) => {
return {
rainChkSttnInit: async ( sggCd: string) => {
try {
const rainChkRes = await initFetch(undefined, sggCd);
return set((state: rainChkSttnState) => ({
...state,
rainChkSttn: {
...state.rainChkSttn,
rainChkRes:rainChkRes
},
}));
} catch (error) {
console.log(error);
}
},
rainChkSttnSearch: async (searchTxt: string, sggCd: string) => {
try {
const rainChkRes = await initFetch(searchTxt, sggCd);
return set((state: rainChkSttnState) => ({
...state,
rainChkSttn: {
...state.rainChkSttn,
rainChkRes:rainChkRes
},
}));
} catch (error) {
console.log(error);
}
},isRainSttn :(isSttn:boolean) =>{
try {
return set((state: rainChkSttnState) => ({
...state,
rainChkSttn: {
...state.rainChkSttn,
isSttn:isSttn
},
}));
} catch (error) {
console.log(error);
}
},getRainSttnExcel: async (excelList:rainChkZodType[]) => {
try {
const excelData = buildingExcelRainSttn(excelList)
return set((state: rainChkSttnState) => ({
...state,
rainChkSttn: {
...state.rainChkSttn,
sttnExcelList:excelData
},
}));
} catch (error) {
console.log(error);
}
}
};
};
@@ -0,0 +1,34 @@
export const buildingExcelRswtSttn = (excelList: any[]) => {
const excelData: string[][] = [];
excelList.forEach((item, index) => {
excelData.push([
String(item.cityText) ?? "",
String(item.sggText) ?? "",
String(item.bdstNm) ?? "",
item.operMngCd===null ? "":item.operMngCd,
String(item.anlOperCst) ?? "",
String(item.prcsCpct) ?? "",
item.spwtPositn===null ? "":item.spwtPositn,
item.chckYmd ?? "",
String(item.utztnUsgCd) ?? "",
String(item.splyUswtrUtztnQnt) ?? "",
String(item.ruseFcltUtztnQnt) ?? "",
String(item.grssClfgUswtr) ?? "",
String(item.combResdch) ?? "",
String(item.trbt) ?? "",
String(item.bod) ?? "",
String(item.smll) ?? "",
String(item.tn) ?? "",
String(item.tph) ?? "",
String(item.ph) ?? "",
String(item.clIonQnt) ?? "",
String(item.vltnDt) ?? "",
String(item.vltnMttr) ?? "",
String(item.levyAmt) ?? "",
]);
});
return excelData;
};
@@ -0,0 +1,142 @@
import type { TableUpperProps } from "@/app/store/common/type/header";
export const rswtChkSttnHeadListExport: TableUpperProps[] = [
{ id: "order", title: "순번", rowSpan: true },
{ id: "cityText", title: "시도", rowSpan: true },
{ id: "sggText", title: "시군구", rowSpan: true },
{ id: "bdstNm", title: "시설명", rowSpan: true },
{ id: "operMngCd", title: "운영관리형태", rowSpan: true },
{ id: "anlOperCst", title: "연간운영비(원/년)", rowSpan: true },
{ id: "prcsCpct", title: "처리용량(m³)", rowSpan: true },
{ id: "spwtPositn", title: "채수지점", rowSpan: true },
{ id: "chckYmd", title: "점검일", rowSpan: true },
{ id: "utztnUsgCd", title: "이용용도" },
{ id: "splyUswtrUtztnQnt", title: "연간보급수이용량(m³)", type: "number" },
{ id: "ruseFcltUtztnQnt", title: "연간중수도이용량(m³)", type: "number" },
{
id: "grssClfgUswtr",
title: "총대장균군수",
upName: "useQuilty",
upSequnce: 1,
type: "number",
},
{
id: "combResdch",
title: "결합잔류염소",
upName: "useQuilty",
upSequnce: 2,
type: "number",
},
{
id: "trbt",
title: "탁도",
upName: "useQuilty",
upSequnce: 3,
type: "number",
},
{
id: "bod",
title: "BOD",
upName: "useQuilty",
upSequnce: 4,
type: "number",
},
{
id: "smll",
title: "냄새",
upName: "useQuilty",
upSequnce: 5,
type: "number",
},
{
id: "crmty",
title: "색도",
upName: "useQuilty",
upSequnce: 6,
type: "number",
},
{ id: "tn", title: "T-N", upName: "useQuilty", upSequnce: 7, type: "number" },
{
id: "tph",
title: "T-P",
upName: "useQuilty",
upSequnce: 8,
type: "number",
},
{ id: "ph", title: "PH", upName: "useQuilty", upSequnce: 9, type: "number" },
{
id: "clIonQnt",
title: "염화물",
upName: "useQuilty",
upSequnce: 10,
type: "number",
},
{
id: "vltnDt",
title: "부과일(위반일)",
upName: "feeHist",
upSequnce: 1,
type: "text",
},
{
id: "vltnMttr",
title: "위반사항",
upName: "feeHist",
upSequnce: 2,
type: "text",
},
{
id: "levyAmt",
title: "부과금액(천원)",
upName: "feeHist",
upSequnce: 3,
type: "number",
},
];
export const rswtDetailSttnHeadListExport: TableUpperProps[] = [
{ id: "utztnUsgCd", title: "이용용도" },
{
id: "grssClfgUswtr",
title: "총대장균군수",
upName: "detailQulity",
upSequnce: 2,
},
{
id: "combResdch",
title: "결합잔류염소",
upName: "detailQulity",
upSequnce: 3,
},
{
id: "trbt",
title: "탁도",
upName: "detailQulity",
upSequnce: 4,
},
{ id: "bod", title: "BOD", upName: "detailQulity", upSequnce: 5 },
{
id: "smll",
title: "냄새",
upName: "detailQulity",
upSequnce: 6,
},
{
id: "crmty",
title: "색도",
upName: "detailQulity",
upSequnce: 7,
},
{ id: "tn", title: "T-N", upName: "detailQulity", upSequnce: 8},
{ id: "tph", title: "T-P", upName: "detailQulity", upSequnce: 9 },
{ id: "ph", title: "PH", upName: "detailQulity", upSequnce: 10 },
{
id: "clIonQnt",
title: "염화물",
upName: "detailQulity",
upSequnce: 11,
},
];
@@ -0,0 +1,107 @@
import { rswtHeadNmExport } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn/headList";
import { rswtChkSttnHeadListExport, rswtDetailSttnHeadListExport } from "./headList";
import type { TableUpperProps } from "@/app/store/common/type/header";
import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn/headList";
import type { rswtChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn";
import { getFetch } from "@/components/lib/api";
import { buildingExcelRswtSttn } from "./excel";
const rswtChkHeadList = rswtChkSttnHeadListExport;
const rswtDetailHeadList = rswtDetailSttnHeadListExport;
const rswtHeadNm = rswtHeadNmExport;
export type rswtChkSttnState = {
rswtChkSttn: {
rswtChkSttnHeadList: TableUpperProps[];
rswtDetailSttnHeadList: TableUpperProps[];
rswtSttnHeadNm: chHeadType[];
sttnExcelList: [];
rswtChkRes: rswtChkZodType[];
isInit: boolean;
isSttn: boolean;
};
};
type rswtChkSttnActions = {
rswtChkSttnInit: ( sggCd: string) => void;
isRswtSttn: (isSttn:boolean) => void;
getRswtSttnExcel:(excelList:rswtChkZodType[]) => void;
};
export type rswtChkSttnType = rswtChkSttnState & rswtChkSttnActions;
export const rswtChkStateExport: rswtChkSttnState = {
rswtChkSttn: {
rswtChkSttnHeadList: rswtChkHeadList,
rswtDetailSttnHeadList: rswtDetailHeadList,
rswtSttnHeadNm: rswtHeadNm,
sttnExcelList: [],
rswtChkRes: [],
isInit: false,
isSttn:false,
},
};
const initFetch = async (year: string | undefined, sgg: string | undefined) => {
const rswtChkRes = await getFetch(
"wr",
`/reuseChk/reuseWater/` +
(year ? `${year}` : "2024") +
(sgg ? `/${sgg}` : "/0")
);
return rswtChkRes;
};
export const rswtChkSttnActionsExport: (set: any) => rswtChkSttnActions = (
set: any
) => {
return {
rswtChkSttnInit: async ( sggCd: string) => {
try {
const rswtChkRes = await initFetch("2024", sggCd);
return set((state: rswtChkSttnState) => ({
...state,
rswtChkSttn: {
...state.rswtChkSttn,
rswtChkRes: rswtChkRes,
isInit: false,
},
}));
} catch (error) {
console.log(error);
}
},isRswtSttn :(isSttn:boolean) =>{
try {
return set((state: rswtChkSttnState) => ({
...state,
rswtChkSttn: {
...state.rswtChkSttn,
isSttn:isSttn
},
}));
} catch (error) {
console.log(error);
}
},getRswtSttnExcel: async (excelList:rswtChkZodType []) => {
try {
const excelData = buildingExcelRswtSttn(excelList)
return set((state: rswtChkSttnState) => ({
...state,
rswtChkSttn: {
...state.rswtChkSttn,
sttnExcelList:excelData
},
}));
} catch (error) {
console.log(error);
}
}
};
};
@@ -0,0 +1,24 @@
export const excelPrfmncSttnParsing = (
data: any[]
): string[][] => {
const excelExportData: string[][] = [];
data.forEach((item) => {
excelExportData.push([
item.용수명,
item.total,
item["1월"],
item["2월"],
item["3월"],
item["4월"],
item["5월"],
item["6월"],
item["7월"],
item["8월"],
item["9월"],
item["10월"],
item["11월"],
item["12월"],
]);
});
return excelExportData;
};
@@ -0,0 +1,59 @@
import { z } from "zod";
import type { TableUpperProps } from "../../ruseFcltMng/fcltReg/rainReg";
export const pbnstPrfmncSttnHeadListExport: TableUpperProps[] = [
{
id: "number",
title: "No",
rowSpan: 2,
row: 0
},
{
id: "sido",
title: "시도",
rowSpan: 2,
row: 0
},
{
id: "gugun",
title: "시군구",
rowSpan: 2,
row: 0
},
{
id: "bscFctNm",
title: "시설명",
rowSpan: 2,
row: 0
},
{
id: "ruseUtztnFcltNm",
title: "재이용시설명",
rowSpan: 2,
row: 0
},
]
export const pbnstYearHeadListExport: TableUpperProps[] = [
{
title: "년도",
colSpan: 3,
row: 0
},
{
id: "total",
title: "계",
row: 1
},
{
id: "inUsage",
title: "장내용수",
row: 1
},
{
id: "outUsage",
title: "장외용수",
row: 1
},
]
@@ -0,0 +1,216 @@
import { fetchType, getFetch, postFectch } from "@/components/lib/api";
import type { TableUpperProps } from "../../common/type/header";
import { 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";
type pbnstPrfmncSttnActions = {
tableHeadMaker: (startYear: number, endYear: number) => void;
pbnstPrfmncInit: (page: string, sggOrCity: string) => void;
pbnstPrfmncSearch: (returnType: ReturnType, swtrmtFcltNm: string, fromDate: string, toDate: string) => void;
}
const pbnstPrfmncRes: PrfType[] = [];
const prfmncRes: FcPrfType[] = [];
export type pbnstPrfmncSttnState = {
pbnstPrfmncSttn: {
pbnstPrfHeadList: TableUpperProps[];
pbnstPrfmncRes: PrfType[];
prfmncRes: any[];
isInit: boolean;
rawData: any[];
selectYearList: selectLabel[]
}
}
export type pbnstPrfmncSttnType = pbnstPrfmncSttnState & pbnstPrfmncSttnActions;
export const pbnstPrfmncSttnExport: pbnstPrfmncSttnState = {
pbnstPrfmncSttn: {
pbnstPrfHeadList: [...pbnstPrfmncSttnHeadListExport],
pbnstPrfmncRes: pbnstPrfmncRes,
prfmncRes: prfmncRes,
isInit: false,
rawData: [],
selectYearList: []
}
}
const checkWrRegList = async () => {
const wrRegList = await getFetch("wr", `/reuseFc/pubDetailList`);
return wrRegList;
};
const hasuListFetch = async (page: string, sggOrCity: string) => {
const checkWrRegListRes = await checkWrRegList();
const rainRes = await postFectch(
`/prcsFclt/ruseInfo/${page ? page : 1}/10/A/${sggOrCity ? sggOrCity : "11"}/0/1/SW`,
checkWrRegListRes?.fcltCds,
fetchType.COMMON
);
const data = checkWrRegListRes.fcPrfList.map((item: FcPrfType) => {
const findData = rainRes.data.find(
(fclt: pubHasuType) =>
fclt.bscFctCd === item.pbnstRuseFcltPk.substring(0, 11)
);
return {
sido: findData?.sido,
gugun: findData?.gugun,
bscFctNm: findData?.bscFctNm,
ruseUtztnFcltNm: item.ruseUtztnFcltNm,
pbnstRuseFcltPk: item.pbnstRuseFcltPk,
};
});
return data;
}
export const pbnstPrfmncSttnActionsExport: (set: any) => pbnstPrfmncSttnActions = (
set: any
) => {
return {
tableHeadMaker: (startYear: number, endYear: number) => {
let yearHeader: TableUpperProps[] = [...pbnstPrfmncSttnHeadListExport];
const selectList = [] as unknown as selectLabel[]
for (let i = startYear; i <= endYear; i++) {
const yearHead = JSON.parse(JSON.stringify(pbnstYearHeadListExport));
if (yearHead) {
yearHead.forEach((item: { id?: string; }) => {
if (item.id) {
item.id = i + item.id;
}
})
if (yearHead[0])
yearHead[0].title = i + "년도"
}
yearHeader = [...yearHeader, ...yearHead]
selectList.push({ text: i + "년도", val: String(i) })
}
set((state: pbnstPrfmncSttnState) => {
return {
...state,
pbnstPrfmncSttn: {
...state.pbnstPrfmncSttn,
pbnstPrfHeadList: [...yearHeader],
selectYearList: selectList
},
};
});
},
pbnstPrfmncInit: async (page: string, sggOrCity: string) => {
try {
const prfmncRes = await hasuListFetch(page, sggOrCity);
return set((state: pbnstPrfmncSttnState) => ({
...state,
pbnstPrfmncSttn: {
...state.pbnstPrfmncSttn,
prfmncRes: prfmncRes,
isInit: true,
},
}));
} catch (e) {
console.log(e)
}
},
pbnstPrfmncSearch: async (returnType: ReturnType, swtrmtFcltNm: string, fromDate: string, toDate: string) => {
let searchUrl = "";
if (returnType.sigunValue !== "0") {
if (swtrmtFcltNm !== "") {
searchUrl = `/prcsFclt/info/1/20/${returnType.partValue}/${returnType.sigunValue}/0/1/SW${'/' + swtrmtFcltNm}`;
} else {
searchUrl = `/prcsFclt/info/1/20/${returnType.partValue}/${returnType.sigunValue}/0/1/SW`;
}
} else {
if (swtrmtFcltNm !== "") {
searchUrl = `/prcsFclt/info/1/20/${returnType.partValue}/${returnType.sidoValue}/0/1/SW${'/' + swtrmtFcltNm}`;
} else {
searchUrl = `/prcsFclt/info/1/20/${returnType.partValue}/${returnType.sidoValue}/0/1/SW`;
}
}
const pbnstRes = await getFetch(
fetchType.COMMON,
searchUrl
);
const bscFctCdList = pbnstRes.map((item: any) => {
return item.bscFctCd;
})
const res = await postFectch(
`/reuseFc/pubDetailList/${fromDate}/${toDate}`,
bscFctCdList,
`wr`,
)
let inUsageSum = 0;
let outUsageSum = 0;
let usageSum = 0;
let year = "";
const yearsData = []
res.data.forEach((item) => {
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;
yearsData.push(yearVal);
}
item.prfList.forEach((acc) => {
year = acc.ym?.substring(0, 4) ?? "";
inUsageSum =
(acc.wshwtr ?? 0) +
(acc.coolUswtr ?? 0) +
(acc.cleanUswtr ?? 0) +
(acc.drwtUswtr ?? 0) +
(acc.dltnUswtr ?? 0) +
(acc.ithlRswtr ?? 0) +
(acc.ithlEtcUswtr ?? 0) +
(acc.cleanToilUswtr ?? 0) +
(acc.resn ?? 0);
outUsageSum =
(acc.lndwtr ?? 0) +
(acc.hydUswtr ?? 0) +
(acc.ugwtChr ?? 0) +
(acc.farmUswtr ?? 0) +
(acc.rvrKeepUswtr ?? 0) +
(acc.indstUswtr ?? 0);
const yearData = yearsData.find(
(yearItem) =>
yearItem.year === year &&
yearItem.pbnstRuseFcltPk == acc.pbnstRuseFcltPk
);
if (yearData) {
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;
yearsData.push(yearVal);
}
});
});
const resData: any[] = []
pbnstRes.forEach((acc) => {
let data = yearsData.find((item) => item.pbnstRuseFcltPk.substring(0, 11) === acc.bscFctCd)
if (data) {
resData.push({ ...acc, ...data })
}
})
return set((state: pbnstPrfmncSttnState) => ({
...state,
pbnstPrfmncSttn: {
...state.pbnstPrfmncSttn,
prfmncRes: resData,
rawData: res.data
},
}));
}
}
}
@@ -1,178 +0,0 @@
import type { TableUpperProps } from "../rainReuseFacilityInsert";
export type TableProps = {
id: string;
title: string;
}
export type selectLabel={
text:string,
val:string
}
type publicReuseFacilityData = {
sido: string,
sigungo: string,
facilityName: string,
location: string,
locationgubun: string,
facilityCapacity: string,
yn?: string,
authoDay?: string,
area?: string,
reuse?: string,
register?: string
}
type pubMngFacData = {
mng: string,
subCo: string,
startDay: string,
endDay: string,
}
const selectLabel:selectLabel[]=[
{text:'test',val:'1'}
]
const pubFacHeadList:TableProps[] = [
{ id: "sido", title: "시도"},
{ id: "sigungo", title: "시군구"},
{ id: "facilityName", title: "시설명"},
{ id: "location", title: "위치"},
{ id: "locationgubun", title: "지역구분"},
{ id: "facilityCapacity", title: "시설용량"},
{ id: "yn", title: '재이용여부' },
{ id: "authoDay", title: '등록여부'}];
const pubMngUpHeadList:TableUpperProps[] = [
{ id: "mng", title: "운영방식"},
{ id: "subCo", title: "대행업체"},
{ id: "startDay", title: "시작일", upName:'upChangeRe' , upSequnce:1 },
{ id: "endDay", title: "종료일", upName:'upChangeRe' , upSequnce:2 },
];
const date = new Date()
const pubMngFacData:pubMngFacData[] = [
{ mng:"자체운영", subCo:"-",startDay: '2024-11-11' ,endDay:'2024-11-20'},
{ mng:"자체운영", subCo:"한국수자원공사",startDay: '2022-11-11' ,endDay:'2024-09-13'},
{ mng:"자체운영", subCo:"스타벅스",startDay: '2023-11-11' ,endDay:'2024-02-19'},
];
const publicReuseFacilityData:publicReuseFacilityData[] = [
{
sido: "서울",
sigungo: "강남구",
facilityName: "난지",
location: "경기도 고양시 덕양구 대차로 4가",
locationgubun: "500",
facilityCapacity: "800,000",
reuse: "Y",
register: "Y"
},
{
sido: "서울",
sigungo: "강남구",
facilityName: "난지",
location: "경기도 고양시 덕양구 대차로 4가",
locationgubun: "500",
facilityCapacity: "800,000",
reuse: "Y",
register: "Y"
},
{
sido: "서울",
sigungo: "강남구",
facilityName: "난지",
location: "경기도 고양시 덕양구 대차로 4가",
locationgubun: "500",
facilityCapacity: "800,000",
yn: "Y",
authoDay: "2012",
area:"123"
},
]
const erctUswtrCd:selectLabel[]=[
{text:'처리장연계',val:'1_erct'},
{text:'자체/연계',val:'2_erct'},
{text:'자체처리',val:'3_erct'},
]
const cyclCd :selectLabel[]= [
{ text: "1차", val: "1_cyc" },
{ text: "2차", val: "2_cyc" },
];
const seCd :selectLabel[] = [
{ text: "신규", val: "1_Se" },
{ text: "진행", val: "2_Se" },
];
const buseCd :selectLabel[]= [
{ text: "재정", val: "1_bus" },
{ text: "만루", val: "2_bus" },
];
const rprcsCd :selectLabel[] = [
{ text: "물리적처리", val: "1_rprc" },
{ text: "생물학적처리", val: "2_rprc" },
];
const buseMet :selectLabel[] = [
{ text: "재정", val: "1_busemet" },
{ text: "민간투자", val: "2_busemet" },
{ text: "자체", val: "3_busemet" },
];
const rprcLoCd :selectLabel[] = [
{ text: "내부", val: "1_rprc" },
{ text: "외부", val: "2_rprc" },
];
export type pubFacState = {pubFac:{
isInit: boolean;
pubFacHeadList: TableProps[];
pubMngUpHeadList:TableUpperProps[]
publicReuseFacilityData: publicReuseFacilityData[];
selectLabel:selectLabel[];
pubMngFacData:pubMngFacData[];
erctUswtrCd:selectLabel[];
cyclCd:selectLabel[];
seCd:selectLabel[];
buseCd :selectLabel[]
rprcsCd :selectLabel[]
buseMet :selectLabel[]
rprcLoCd:selectLabel[]
}}
type pubFacActions = {
decrementList: () => void
}
export type pubFacType = pubFacState & pubFacActions;
export const pubFacStateExport:pubFacState= {pubFac:{
isInit:false,
pubFacHeadList: pubFacHeadList,
pubMngUpHeadList:pubMngUpHeadList,
publicReuseFacilityData: publicReuseFacilityData,
selectLabel:selectLabel,
pubMngFacData:pubMngFacData,
erctUswtrCd:erctUswtrCd,
cyclCd:cyclCd,
seCd:seCd,
buseCd:buseCd,
rprcsCd:rprcsCd,
buseMet:buseMet,
rprcLoCd:rprcLoCd
}}
export const pubFacActionsExport:(set:any)=>pubFacActions=(set: any) => {
return {
decrementList:()=>set(
(state:pubFacState) => {
return (
{pubFac:{
pubFacheadList: state.pubFac.pubFacHeadList,
publicReuseFacilityUper:
state.pubFac.publicReuseFacilityData.slice(0, state.pubFac.publicReuseFacilityData.length - 1)
}})}
)
}
}
@@ -1,134 +0,0 @@
export type TableUpperProps = {
id: string;
title: string;
upName?: string;
upSequnce?: number;
}
export type rainFacOfType = {
sido: string,
sigungo: string,
facilityName: string,
location: string,
locationgubun: string,
firstConstructionPermission:string,
facilityCapacity: string,
buildingArea:string,
yn?: string,
permissionDay:string;
authoDay?: string,
area?: string,
reuse?: string,
register?: string,
legalTargetYn:string,
}
export const upHeadList:TableUpperProps[] = [
{ id: "sido", title: "시도"},
{ id: "sigungo", title: "시군구"},
{ id: "facilityName", title: "시설명"},
{ id: "location", title: "위치"},
{ id: "locationgubun", title: "지역구분"},
{ id: "facilityCapacity", title: "시설용량"},
{ id: "yn", title: '여부', upName:'upChangeRe' , upSequnce:1 },
{ id: "authoDay", title: '허가일',upName:'upChangeRe', upSequnce:2 },
{ id: "area", title: '면적' ,upName:'upChangeRe',upSequnce:3 }];
const rainOfObject:rainFacOfType[] = [
{
sido: "서울",
sigungo: "종로구",
facilityName: "그랑서울",
location: "종로 33",
locationgubun: "업무시설",
firstConstructionPermission : '2024-10-10',
buildingArea: "50",
facilityCapacity: "800,000",
reuse: "Y",
permissionDay:'2024-10-10',
register: "Y",
legalTargetYn:"Y"
},
{
sido: "서울",
sigungo: "종로구",
facilityName: "그랑서울",
location: "종로 33",
locationgubun: "업무시설",
firstConstructionPermission : '2024-10-10',
buildingArea: "50",
facilityCapacity: "800,000",
reuse: "Y",
permissionDay:'2024-10-10',
register: "Y",
legalTargetYn:"Y"
},
{
sido: "서울",
sigungo: "종로구",
facilityName: "그랑서울",
location: "종로 33",
locationgubun: "업무시설",
firstConstructionPermission : '2024-10-10',
buildingArea: "50",
facilityCapacity: "800,000",
reuse: "Y",
permissionDay:'2024-10-10',
register: "Y",
legalTargetYn:"Y"
},
]
export type selectArray ={
text:string,
val:string
}
export const selectClass ="w-full h-full text-2xl";
const selectHomeWater = [
{ text: '집수면', val: "1" },
{ text: "종류", val: "2" },
];
const selectYN= [
{ text: 'Y', val: "1" },
{ text: 'N', val: "2" },
];
export type rainFacState ={ rain:{
isInit: boolean;
upHeadList: TableUpperProps[];
rainOfObject: rainFacOfType[];
selectHomeWater:selectArray[];
selectYN:selectArray[];
}}
type rainFacSActions = {
decrementList: () => void
}
export type rainFacType = rainFacState & rainFacSActions;
export const rainFacStateExport:rainFacState= {rain:{
isInit:false,
upHeadList: upHeadList,
rainOfObject: rainOfObject,
selectHomeWater:selectHomeWater,
selectYN:selectYN
}}
export const rainFacActionsExport:(set:any)=>rainFacSActions=(set: any) => {
return {
decrementList:()=>set(
(state:rainFacState) => {
return (
{rain:{
upHeadList: state.rain.upHeadList,
rainOfObject:
state.rain.rainOfObject.slice(0, state.rain.rainOfObject.length - 1)
}})}
)
}
}
@@ -1,94 +0,0 @@
import { upHeadList, type rainFacOfType, type selectArray, type TableUpperProps } from "../rainReuseFacilityInsert";
const rswtOfObject:rainFacOfType[] = [
{
sido: "서울",
sigungo: "종로구",
facilityName: "그랑서울",
location: "종로 33",
locationgubun: "업무시설",
firstConstructionPermission : '2024-10-10',
buildingArea: "50",
facilityCapacity: "800,000",
reuse: "Y",
permissionDay:'2024-10-10',
register: "Y",
legalTargetYn:"Y"
},
{
sido: "서울",
sigungo: "종로구",
facilityName: "그랑서울",
location: "종로 33",
locationgubun: "업무시설",
firstConstructionPermission : '2024-10-10',
buildingArea: "50",
facilityCapacity: "800,000",
reuse: "Y",
permissionDay:'2024-10-10',
register: "Y",
legalTargetYn:"Y"
},
{
sido: "서울",
sigungo: "종로구",
facilityName: "그랑서울",
location: "종로 33",
locationgubun: "업무시설",
firstConstructionPermission : '2024-10-10',
buildingArea: "50",
facilityCapacity: "800,000",
reuse: "Y",
permissionDay:'2024-10-10',
register: "Y",
legalTargetYn:"Y"
},
]
const selectHomeWater = [
{ text: '집수면', val: "1" },
{ text: "종류", val: "2" },
];
const selectYN= [
{ text: 'Y', val: "1" },
{ text: 'N', val: "2" },
];
export type rswtFacState ={ rswt:{
isInit: boolean;
upHeadList: TableUpperProps[];
rswtOfObject: rainFacOfType[];
selectHomeWater:selectArray[];
selectYN:selectArray[];
}}
type rswtFacSActions = {
decrementList: () => void
}
export type rswtFacType = rswtFacState & rswtFacSActions;
export const rswtFacStateExport:rswtFacState= {rswt:{
isInit:false,
upHeadList: upHeadList,
rswtOfObject: rswtOfObject,
selectHomeWater:selectHomeWater,
selectYN:selectYN
}}
export const rswtFacActionsExport:(set:any)=>rswtFacSActions=(set: any) => {
return {
decrementList:()=>set(
(state:rswtFacState) => {
return (
{rain:{
upHeadList: state.rswt.upHeadList,
rainOfObject:
state.rswt.rswtOfObject.slice(0, state.rswt.rswtOfObject.length - 1)
}})}
)
}
}
@@ -0,0 +1,200 @@
import { getFetch } from "@/components/lib/api";
import { TEST_UUID, type customRainBdst } from "../rainReg";
import type { customHtdflBdst } from "../htdflReg";
import type { customRswtBdst } from "../rswtReg";
import type { TableUpperProps } from "@/app/store/common/type/header";
const moUpHeadList: TableUpperProps[] = [
{ id: "cityText", title: "시도" },
{ id: "sggText", title: "시군구" },
{ id: "bdstNm", title: "시설명" },
{ id: "daddr", title: "위치" },
{ id: "frstArchPrmsnDt", title: "최초건축허가일" },
{ id: "archArea", title: "건축면적", },
];
const bdstChgHeadList: TableUpperProps[] = [
{ id: "bdstChgNm", title: "구분" },
{ id: "archChgPrmsnDt", title: "허가일" },
{ id: "archChgArea", title: "변경면적" },
];
const bdstBase:any[] = [];
const isRainBdst = (data: any): data is customRainBdst=> {
return data.reuseBuilding?.[0]?.rainyObj !== undefined;
}
const isHtdflBdst = (data: any): data is customHtdflBdst=> {
return data.reuseBuilding?.[0]?.htdflObj !== undefined;
}
const isRswtBdst = (data: any): data is customRswtBdst =>{
return data.reuseBuilding?.[0]?.rswtrObj !== undefined;
}
export const makeRstr =(data:customRainBdst|customHtdflBdst|customRswtBdst) =>{
data.rgtr = TEST_UUID;
let chData
if(isRainBdst(data)){
chData = data.reuseBuilding.map((item) => ({
...item,
rgtr : TEST_UUID,
rainyObj:{
...item.rainyObj,
rgtr:TEST_UUID
}
}));
data.reuseBuilding=chData;
}else if(isHtdflBdst(data)){
chData = data.reuseBuilding.map((item) => ({
...item,
rgtr : TEST_UUID,
htdflObj:{
...item.htdflObj,
rgtr:TEST_UUID
}
}));
data.reuseBuilding=chData;
}else if (isRswtBdst(data)){
chData = data.reuseBuilding.map((item) => ({
...item,
rgtr : TEST_UUID,
rswtrObj:{
...item.rswtrObj,
rgtr:TEST_UUID
}
}));
data.reuseBuilding=chData;
}
if(data?.chgBuilding.length>0){
const chRgtr = data.chgBuilding.map((item) =>({...item, rgtr:TEST_UUID, mdfr: item.mdfr ?? null }))
data.chgBuilding =chRgtr;
}
return data;
}
export const makeMdfr =(data:customRainBdst|customHtdflBdst|customRswtBdst) =>{
data.mdfr = TEST_UUID;
let chData
if(isRainBdst(data)){
chData = data.reuseBuilding.map((item) => ({
...item,
mdfr : TEST_UUID,
rainyObj:{
...item.rainyObj,
mdfr:TEST_UUID
}
}));
if(data?.chgBuilding.length>0){
const chRgtr = data.chgBuilding.map((item) =>({...item, rgtr:TEST_UUID, mdfr: item.mdfr ?? null }))
data.chgBuilding =chRgtr;
}
data.reuseBuilding=chData
}else if(isHtdflBdst(data)){
chData = data.reuseBuilding.map((item) => ({
...item,
mdfr : TEST_UUID,
htdflObj:{
...item.htdflObj,
mdfr:TEST_UUID
}
}));
data.reuseBuilding=chData;
}else if (isRswtBdst(data)){
chData = data.reuseBuilding.map((item) => ({
...item,
mdfr : TEST_UUID,
rswtrObj:{
...item.rswtrObj,
mdfr:TEST_UUID
}
}));
data.reuseBuilding=chData;
}
if(data?.chgBuilding.length>0){
const chMdfr = data.chgBuilding.map((item) =>({...item, mdfr:TEST_UUID, archChgArea: item.archChgArea ?? '' }))
data.chgBuilding =chMdfr;
}
return data;
}
export type bdstFulType = bdstState & bdstActions;
export type bdstState = {
bdst: {
bdstBase: any[];
moUpHeadList:TableUpperProps[]
bdstChgHeadList:TableUpperProps[]
};
};
type bdstActions = {
findBdst: (sggCd:string, searchTxt:string, flag:string) => void ;
};
const findBdstInfo = async(sggCd:string, searchTxt:string ,flg:string)=>{
return await getFetch('wr', `/reuseFc/building/${flg}/${sggCd}`+(searchTxt?`/${searchTxt}`:'' ))
}
export const bdstStateExport: bdstState = {
bdst: {
bdstBase: bdstBase, // Updated to match the array type
moUpHeadList:moUpHeadList,
bdstChgHeadList:bdstChgHeadList,
},
};
export const bdstActionsExport: (set: any) => bdstActions = (
set: any
) => {
return {
findBdst: async(sggCd:string, searchTxt:string ,flg:string ) =>{
try{
const bdst = await findBdstInfo(sggCd, searchTxt, flg);
const makeBdst = bdst.map((item:any) => {
return {
...item,
reuseBuilding:[]
};
})
return set((state:bdstState) =>({
...state,
bdst:{
...state.bdst,
bdstBase:makeBdst
}
}))
}catch(error1){
console.log("error ", error1)
}finally{
}
},
};
};
@@ -0,0 +1,244 @@
import { getFetch, postFectch, putFectch } from "@/components/lib/api";
import { upHeadList, type chgBuilding} from "../rainReg";
import { z } from "zod";
import { makeMdfr, makeRstr } from "../bdstReg";
import type { TableUpperProps } from "@/app/store/common/type/header";
export const hdtflZod = z.object({
bdstInfoPk: z.number().nullish(),
ctpvCd: z.number().default(0),
sggCd: z.number().default(0),
cityText: z.string().nullish(),
sggText: z.string().nullish(),
daddr: z.string().default(" "),
bdstNm: z.string().default(" "),
frstArchPrmsnDt: z.date().default(() => new Date()),
archChgPrmsnDt: z.date().default(() => new Date()).nullish() ,
archArea: z.number().default(0),
archChgArea: z.number().nullish().default(0),
rgtr:z.string().nullish().default(null),
mdfr:z.string().nullish().default(null),
reuseBuilding: z
.array(
z.object({
bdstRuseFcltPk: z.number().nullish(),
bdstInfoFk: z.number().nullish(),
instlCmptnDt: z.coerce.date().default(() => new Date()),
instlCst: z.number().nullish().default(0),
operMngCd: z.string().nullish().default(""),
anlOperCst: z.number().default(0),
instlCstSprtYn: z.enum(["Y", "N"]).nullish(),
instlCstSprtAmt: z.number().nullish().default(0),
grntchBdstCertNo: z.string().nullish().default(""),
grntchBdstCertGrd: z.string().nullish().default(""),
ruseFcltFlg: z.string().nullish().default(""),
bdstUsgCd: z.number().default(0),
lawTrgtYn: z.enum(["Y", "N"]).nullish(),
rgtr:z.string().nullish().default(null),
mdfr:z.string().nullish().default(null),
// htdflObj 매핑
htdflObj: z
.object({
htdflFcltPk: z.number().nullish(),
bdstRuseFcltFk: z.number().nullish(),
etgtType: z.string().default(""),
fclCpct: z.number().default(0),
plwtYn: z.enum(["Y", "N"]),
orgwtWtritSpt: z.number().default(0),
orgwtOcrnProcs: z.string().default(""),
wtritEntrcTp: z.number().max(4, "온도는 100이상이 될 수 없습니다.")
.default(0),
amtgnr: z.number().default(0),
prcsProcsYn: z.enum(["Y", "N"]),
prcsFcltCpct: z.number().default(0),
fmYn: z.string().default(""),
utztnCpct: z.number().default(0),
utztnUsg: z.string().default(""),
grssClfg: z.number().default(0),
combResdch: z.number().default(0),
trbt: z.number().default(0),
bod: z.number().default(0),
smll: z.number().default(0),
crmty: z.number().default(0),
tn: z.number().default(0),
tph: z.number().default(0),
ph: z.number().default(0),
clIonQnt: z.number().default(0),
cdtnv: z.number().default(0),
emsnExitTp: z.number().default(0),
rgtr:z.string().nullish().default(null),
mdfr:z.string().nullish().default(null),
})
.default({
plwtYn: "N",
prcsProcsYn: "N",
}),
})
)
.default([]),
chgBuilding: z
.array(
z.object({
bdstInfoFk: z.number().nullish(),
archChgPrmsnDt: z.coerce.date() ,
archChgArea: z.string().default("-").nullish(),
bdstChgNm: z.string().default(""),
rgtr:z.string().nullish().default(null),
mdfr:z.string().nullish().default(null),
})
)
.default([]),
});
export type customHtdflBdst = z.infer<typeof hdtflZod>
export type htdflFacState = {
htdfl: {
isInit: boolean;
upHeadList: TableUpperProps[];
htdflRes: customHtdflBdst[];
};
};
type htdflFacSActions = {
initHtdfl: (code: string ) => void;
htdflBdstUpdate:(data: customHtdflBdst, code:string|number) => void;
htdflBdstReg:(data: customHtdflBdst, code:string|number) => void;
getHtdflBdstData:(pageNation:number, code:string|number) =>void;
};
const htdflRes: customHtdflBdst[] = [];
export type htdflFacType = htdflFacState & htdflFacSActions;
export const htdflFacStateExport: htdflFacState = {
htdfl: {
isInit: false,
upHeadList: upHeadList,
htdflRes: htdflRes,
},
};
const initFetch = async (code:string|number) => {
const rswtRes = await getFetch(
"wr",
`/facilityList/1/20/${code}`)
return rswtRes;
};
export const htdflFacActionsExport: (set: any) => htdflFacSActions = (
set: any
) => {
return {
getHtdflBdstData: async (pageNation: number, code: string | number) => {
try {
const rswtRes = await getFetch(
"wr",
`/drain/facilityList/${pageNation}/20/${code}`
);
console.log(pageNation)
// 여기서 상태 업데이트
return set((state: htdflFacState) => ({
...state,
htdfl: {
...state.htdfl,
htdflRes: rswtRes,
isInit: false,
},
}));
} catch (e) {
console.log(e);
}
},
initHtdfl: async (code: string ) => {
try {
const htdflRes = await initFetch(code);
set((state: htdflFacState) => {
return {
...state,
htdfl: {
...state.htdfl,
htdflRes: htdflRes,
isInit: false,
},
};
});
} catch (error) {
console.log(error);
}
},
htdflBdstUpdate: async (data: customHtdflBdst, code:string|number) => {
try {
const chData=await makeMdfr(data)
const res = await putFectch("/drain/facility", data);
if (res.ok) {
alert(" 수정이 완료되었습니다.");
}
const htdflRes = await initFetch(code);
set((state: htdflFacState) => ({
...state,
htdfl: {
...state.htdfl,
htdflRes: htdflRes,
isInit: false,
},
}));
} catch (errorUpdate) {
alert(
"업데이트 오류입니다. " +
(errorUpdate instanceof Error ? errorUpdate.message : "")
);
}
},
htdflBdstReg: async (data: customHtdflBdst , code:string|number) => {
try {
const chData=await makeRstr(data)
const res = await postFectch("/drain/facility", data);
if (res.ok) {
if(data.chgBuilding.length > 0){
await res
.json()
.then((resData: any) => {
const chPK = resData?.data?.bdstInfoPk;
const makeCh = resData.data.chgBuilding.map(
(item: chgBuilding) => ({
...item,
bdstInfoFk: chPK,
})
);
const chch = postFectch("/reuseFc/chgBuilding", makeCh);
return chch;
})
.then((chch: any) => {
if (chch.ok) {
alert("등록이 완료되었습니다.");
}
});
}else{
alert("등록이 완료되었습니다.");
}
}
const htdflRes = await initFetch(code);
set((state: htdflFacState) => ({
...state,
htdfl: {
...state.htdfl,
htdflRes: htdflRes,
isInit: false,
},
}));
} catch (errorReg) {
alert("등록 오류입니다.");
}
},
};
};
@@ -0,0 +1,132 @@
import type { TableUpperProps } from "@/app/store/common/type/header";
import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn/headList";
export const pubFacHeadListExport: TableUpperProps[] = [
{ id: "sido", title: "시도" },
{ id: "gugun", title: "시군구" },
{ id: "bscFctNm", title: "시설명" },
{ id: "addr", title: "위치" },
{ id: "efflWqltStndrdNm", title: "지역구분" },
{ id: "fctCpc", title: "시설용량" },
{ id: "ruse", title: "재이용여부" },
{ id: "rswtrYn", title: "등록여부" },
];
export const pbnstMngUpHeadListExport: TableUpperProps[] = [
{ id: "choose", title: "선택", type: "checkbox" },
{ id: "operMthd", title: "운영방식",type: "select", selectData: "ruseMngMtd" },
{ id: "rprtvBzenty", title: "대행업체", edit: true },
{
id: "bgngDt",
title: "시작일",
type: "date",
},
{
id: "endDt",
title: "종료일",
type: "date",
},
];
export const pplInstlsHeadListExport: TableUpperProps[] = [
{ id: "choose", title: "선택", type: "checkbox" },
{ id: "ppMqlt", title: "관재질", type: "select", selectData: "pplQulity" },
{ id: "pdmt", title: "관경", type: "select", selectData: "pplLenght" },
{ id: "cpct", title: "연장", edit: true, type: "number" },
];
export const pbnstDemandHeadListExport: TableUpperProps[] = [
{ id: "dmdCoNm", title: "수요처명" },
{ id: "daddr", title: "위치(주소)" },
{ id: "useUsgCd", title: "사용용도" },
{ id: "splyBgngDay", title: "공급시작일" },
{ id: "splyEndDay", title: "공급종료일" },
{ id: "splyCpct", title: "공급량(m³/일)" },
{ id: "splyFmYon", title: "공급유량계 유무" },
];
export const pbnstOrgwtHeadListRxport: TableUpperProps[] = [
{ id: "ruseUtztnFcltNm", title: "하수처리장명" },
{ id: "orgwtWtritQnt", title: "원수취수량" },
{ id: "tmsYn", title: "하수처리량TMS 전후" },
{ id: "dschgFmYn", title: "하수처리장 방류 유량계 전·후​" },
{ id: "dtlPstnExpln", title: "상세위치 설명" },
];
export const fcOrgwtsHeadListExport: TableUpperProps[] = [
{ id: "choose", title: "선택", type: "checkbox" },
{ id: "sido", title: "시도" },
{ id: "gugun", title: "시군구" },
{ id: "bscFctNm", title: "시설명" },
{ id: "addr", title: "위치" },
];
export const pbnstMngNmExport: chHeadType[] = [
{ headNm: "upChangeRe", text: "운영대행기간", length: 2 },
];
export type formDetailType = {
id: string;
lable: string;
type?: string;
option?:string
};
export const wasteWaterFcltINfo: formDetailType[] = [
{ id: "wwtEmsnFcltPrmsnYn", lable: "폐수배출물신고 허가여부", type: "selectYn" },
{ id: "tmsInstlYn", lable: "Tms설치여부", type: "selectYn" },
{ id: "pbnstDrngInflwExclYn", lable: "공공하수도유입제외 허가여부", type: "selectYn" },
];
export const concentratedWaterInfo: formDetailType[] = [
{ id: "erctWtrOcrnCpct", lable: "눙축수 발생량(m³/일)", type: "number" },
{ id: "erctUswtrLinkSpt", lable: "눙축수연계지점" },
{ id: "erctUswtrFcltCpct", lable: "시설용량(m³/일)", type: "number" },
{ id: "erctUswtrPrcsMeth", lable: "눙축수처리방식" },
{ id: "erctUswtrPrcsMsrcCd", lable: "눙축수처리공법" },
];
export const ruseFcltinfo: formDetailType[] = [
{ id: "rprcsFcltCpct", lable: "시설용량(m³/일)", type: "number" },
{ id: "majorPrcsMsrcCd", lable: "주처리공법" },
{ id: "addr", lable: "위치(주소)" },
{ id: "rprcsMthdCd", lable: "재처리방식" },
{ id: "inoutYn", lable: "위치(처리장 내외)" ,type: "selectYn" }, // 머가 내? 외?,
{ id: "mainSplyPumpCpct", lable: "메인공급펌프 용량", type: "number" },
];
export const businessMoneyInfo: formDetailType[] = [
{ id: "gvsbs", lable: "국고", type: "number" },
{ id: "lcep", lable: "지방비", type: "number" },
{ id: "cusrAlotm", lable: "민간투자비", type: "number" },
{ id: "etc", lable: "기타" },
{ id: "totalMoney", lable: "합계", type: "number" ,option:"readOnly" },
];
export const businessSttnInfo: formDetailType[] = [
{ id: "seCd", lable: "구분" },
{ id: "bizMthdCd", lable: "사업방식" },
{ id: "bizCmcnDay", lable: "사업준공일", type: "date" },
{ id: "instlAprvSncnDt", lable: "설치승인인가일", type: "date" },
];
export const ruseFcltIntakeList: formDetailType[] = [
{ id: "seCd", lable: "구분" },
{ id: "bizMthdCd", lable: "사업방식" },
{ id: "bizCmcnDay", lable: "사업준공일", type: "date" },
{ id: "instlAprvSncnDt", lable: "설치승인인가일", type: "date" },
];
export const ruseWaterQulityList: formDetailType[] = [
{ id: "bod", lable: "BOD(mg/L)", type: "number" },
{ id: "grssClfg", lable: "총대장균군수(개/mg)", type: "number" },
{ id: "combResdch", lable: "결합잔류염소(mh/L)", type: "number" },
{ id: "trbt", lable: "탁도(NTU)", type: "number" },
{ id: "smll", lable: "냄새", type: "number" },
{ id: "crmty", lable: "색도", type: "number" },
{ id: "tn", lable: "총질소(mg/L)", type: "number" },
{ id: "tph", lable: "총인(mg/L)", type: "number" },
{ id: "ph", lable: "수소이온농도", type: "number" },
{ id: "clIonQnt", lable: "염화물(mg/L)", type: "number" },
{ id: "cdtnv", lable: "전기전도도(μs/cm)​", type: "number" },
];
@@ -0,0 +1,404 @@
import { TEST_UUID } from "../rainReg";
import {
deleteFectch,
fetchType,
getFetch,
postFectch,
putFectch,
} from "@/components/lib/api";
import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn/headList";
import {
type customPbnst,
type fcBizType,
type pbnstInsertIndex,
type pubHasuType,
} from "./type";
import type { SelectDataType } from "@common/business_components/ui";
import {
pbnstMngUpHeadListExport,
pbnstOrgwtHeadListRxport,
pbnstMngNmExport,
pubFacHeadListExport,
pplInstlsHeadListExport,
pbnstDemandHeadListExport,
fcOrgwtsHeadListExport,
} from "./headList";
import type { TableUpperProps } from "@/app/store/common/type/header";
import toast from "react-hot-toast";
const selectLabel: SelectDataType[] = [{ text: "test", val: "1" }];
const pubFacHeadList = pubFacHeadListExport;
const pbnstMngUpHeadList = pbnstMngUpHeadListExport;
const pbnstOrgwtHeadList = pbnstOrgwtHeadListRxport;
const pbnstMngNm = pbnstMngNmExport;
const pplInstlsHeadLisat = pplInstlsHeadListExport;
const pbnstDemandHeadList = pbnstDemandHeadListExport;
const fcOrgwtsHeadList = fcOrgwtsHeadListExport;
export type pubFacState = {
pbnst: {
isInit: boolean;
pubFacHeadList: TableUpperProps[];
pbnstMngUpHeadList: TableUpperProps[];
pbnstMngNm: chHeadType[];
pbnstHasuRes: pubHasuType[];
pbnstRes: customPbnst[] | null; // 배열에서 단일 객체 또는 null로 변경
pbnstResObj: customPbnst | null; // 배열에서 단일 객체 또는 null로 변경
pbnstBizCycle: SelectDataType[];
selectLabel: SelectDataType[];
pbnstOrgwtHeadList: TableUpperProps[];
pplInstlsHeadLisat: TableUpperProps[];
pbnstDemandHeadList: TableUpperProps[];
fcOrgwtsHeadList: TableUpperProps[];
pbnstMngRegData: customPbnst[];
pbnsUpdateIndex: pbnstInsertIndex;
dmdComList: any[];
};
};
type pubFacActions = {
pubHasuInit: (page: string, sggOrCity: string) => void;
pbnstRegClick: (pubHasuRes: pubHasuType) => void;
pbnstReg: (txt: string | undefined) => void;
pbnstInsert(pbnstRes: customPbnst): Promise<void>;
appendRuseFclt(array: customPbnst[]): void;
fileDelete: (atflCd: string) => void;
fileDownLoad: (atflCd: string) => void;
//pbnstMngData: (data: customPbnst[]) => void;
//pbnstBizData(data: fcBizType): void;
// getBizCycle: (pbnstObj: customPbnst) => void;
getpbnstInsertIndex: (data: pbnstInsertIndex) => void;
pbnstRuseFcltUpdate: (ruseRes: customPbnst[]) => void;
pbnstRuseBizUpdate: (ruseRes: fcBizType[]) => void;
pubHasuSearch :(page: string, sggOrCity: string , searchTxt:string) => void
};
export type pubFacType = pubFacState & pubFacActions;
export const pubFacStateExport: pubFacState = {
pbnst: {
isInit: false,
pubFacHeadList: pubFacHeadList,
pbnstMngUpHeadList: pbnstMngUpHeadList,
pbnstMngNm: pbnstMngNm,
pbnstOrgwtHeadList: pbnstOrgwtHeadList,
pplInstlsHeadLisat: pplInstlsHeadLisat,
pbnstDemandHeadList: pbnstDemandHeadList,
fcOrgwtsHeadList: fcOrgwtsHeadList,
selectLabel: selectLabel,
pbnstResObj: null, // 초기값을 null로 변경
pbnstHasuRes: [],
pbnstRes: [], // 초기값을 null로 변경
pbnstBizCycle: [{ text: "없음", val: "1" }],
pbnstMngRegData: [],
pbnsUpdateIndex: {} as pbnstInsertIndex,
dmdComList: [],
},
};
const checkWrRegList = async () => {
const wrRegList = await getFetch("wr", `/reuseFc/pubFc`);
return wrRegList;
};
const hasuListFetch = async (page: string, sggOrCity: string, searchTxt?:string) => {
const checkWrRegListRes = await checkWrRegList();
console.log(' checkWrRegListRes ', checkWrRegListRes)
let url = `/prcsFclt/ruseInfo/${page ? page : 1}/10/A/${sggOrCity? sggOrCity : "11"}/0/1/SW`;
const data = checkWrRegListRes.filter((item:string) => item !== "")
console.log(' checkWrRegListRes ' )
if(searchTxt){
url= url +`/${searchTxt}`
}
const rainRes = await postFectch(
url,
data,
fetchType.COMMON
);
const hasuList = rainRes.data.map((item: any) => {
return {
...item,
ruse: item.ruse === false ? "N" : "Y",
};
});
return hasuList;
};
const initFetch = async (ruseFcltPk: string | undefined) => {
const pbnstRes = await getFetch("wr", `/reuseFc/pubFc/${ruseFcltPk}`);
return pbnstRes;
};
export const writeRgtrAndMdfr = (data: customPbnst[]) => {
data.forEach((pbnst) => {
pbnst.rgtr = TEST_UUID;
pbnst.mdfr = TEST_UUID;
pbnst.fcBizs = pbnst.fcBizs?.map((item) => {
item.rgtr = TEST_UUID;
item.mdfr = TEST_UUID;
item.fcOrgwts = item.fcOrgwts?.map((orgwt) => {
orgwt.mdfr = TEST_UUID;
orgwt.rgtr = TEST_UUID;
return orgwt;
});
item.fcDemands = item.fcDemands?.map((dmd) => {
dmd.mdfr = TEST_UUID;
dmd.rgtr = TEST_UUID;
return dmd;
});
return item;
});
pbnst.fcOpers = pbnst?.fcOpers?.map((oper) => {
oper.rgtr = TEST_UUID;
oper.mdfr = TEST_UUID;
return oper;
});
pbnst.fcFiles = pbnst.fcFiles?.map((file) => {
file.rgtr = TEST_UUID;
file.mdfr = TEST_UUID;
return file;
});
});
return data;
};
export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
return {
pubHasuInit: async (page: string, sggOrCity: string) => {
try {
const pbnstHasuRes = await hasuListFetch(page, sggOrCity);
return set((state: pubFacState) => ({
...state,
pbnst: {
...state.pbnst,
pbnstHasuRes: pbnstHasuRes,
isInit: false,
},
}));
} catch (errorHasu) {
console.log(errorHasu);
}
},pubHasuSearch : async(page: string, sggOrCity: string , searchTxt:string)=> {
try{
const pbnstHasuRes = await hasuListFetch(page, sggOrCity,searchTxt);
return set((state: pubFacState) => ({
...state,
pbnst: {
...state.pbnst,
pbnstHasuRes: pbnstHasuRes,
isInit: false,
},
}));
} catch (errorHasu) {
console.log(errorHasu);
}
},
pbnstRegClick: async (pubHasuRes: pubHasuType) => {
try {
const pbnstRes = await initFetch(pubHasuRes.bscFctCd);
return set((state: pubFacState) => ({
...state,
pbnst: {
...state.pbnst,
pbnstRes: pbnstRes,
isInit: false,
},
}));
} catch (errorHasu) {
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 {
const response = await postFectch(
`/reuseFc/pubFc`,
pbnstRes
);
if( response.status === 200) {
toast.success(`${pbnstRes.ruseUtztnFcltNm} 하수재이용 시설이 등록되었습니다.`);
}
const pbnstHasuRes = await hasuListFetch('1', '0');
return set((state: pubFacState) => ({
...state,
pbnst: {
...state.pbnst,
pbnstRes: pbnstHasuRes,
isInit: false,
},
}));
} catch (error) {
console.error("Error updating pbnst:", error);
}
},pbnstRuseFcltUpdate : async(ruseRes:customPbnst[])=>{
try {
const response = await putFectch(
`/reuseFc/pubFc`,
ruseRes
);
} catch (error) {
console.error("Error pbnstRuseFcltUpdate:", error);
}
} ,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);
}
} ,
getBizCycle: async (pbnstObj: customPbnst) => {
const pbnstBizCycle = pbnstObj.fcBizs.map((item) => {
return {
text: `${item.cycl}차`,
val: item.cycl,
};
});
return set((state: pubFacState) => ({
...state,
pbnst: {
...state.pbnst,
pbnstBizCycle: pbnstBizCycle,
pbnstResObj: pbnstObj,
isInit: false,
},
}));
},
fileDelete: async (atflCd: string) => {
try {
const response = await deleteFectch(
`/attach-service/api/v1/atfl/attachments/atflCd//${atflCd}`,
undefined,
fetchType.CS
);
console.log("File deleted successfully:", response);
return set((state: pubFacState) => ({
...state,
pbnst: {
...state.pbnst,
isInit: false,
},
}));
} catch (error) {
console.error("Error deleting file:", error);
}
},
fileDownLoad: async (atflCd: string) => {
try {
const response = await getFetch(
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);
}
},
// 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) => ({
...state,
pbnst: {
...state.pbnst,
pbnstRes: array,
isInit: false,
},
}));
} catch (e) {
console.log(e);
}
}
};
};
@@ -0,0 +1,244 @@
import { z } from "zod";
import { TEST_UUID } from "../rainReg";
export type customPbnst = z.infer<typeof pbnstRegZod>;
export const pbnstReg = [] as customPbnst[];
export type TableProps = {
id: string;
title: string;
};
export type selectLabel = {
text: string;
val: string;
};
export type pbnstInsertIndex ={
mng:number,
biz:number
}
export type publicReuseFacilityType = {
sido: string;
sigungo: string;
facilityName: string;
location: string;
locationgubun: string;
facilityCapacity: string;
yn?: string;
authoDay?: string;
area?: string;
reuse?: string;
register?: string;
swtrmtFcltFk: string;
};
export type ruseFcltType = {
swtrmtFcltFk: string;
pbnstRuseFcltPk: string;
fcltNm: string;
fcltCpct: number;
swtrmtCpct: number;
ruseCpct: number;
splyExtraCpct: number;
};
export type PbnstDemandComType = {
dmdInfoPk : string | '';
bzmnNo : string | '';
dmdCoNm : string | '';
daddr : string | '';
telno : string | '';
rgtr : string | '';
useUsgCd : string | '';
ctpvCd : string | '';
sggCd : string | '';
dmdAplyPswd: string | '';
splyCpct: number | 0;
splyFmYn:string|'Y'
// dmdInfoFk:string|''
}
const pubHasuZod = z.object({
choose: z.boolean().default(false),
bscFctCd: z.string(),
sido: z.string().default(""),
gugun: z.string().default(""),
bscFctNm: z.string().default(""),
efflWqltStndrdNm: z.string().default(""),
fctCpc: z.number().default(0),
addr:z.string().nullish()
});
export type pubHasuType = z.infer<typeof pubHasuZod>;
const zDate = z.preprocess((v) => (v ? new Date(v as string) : undefined), z.date()).nullish() ;
const zDateNullish = zDate.nullish();
const zDateDefaultNow = zDate.default(new Date());
const zNum = z.preprocess((v) => (v !== null && v !== undefined ? Number(v) : v), z.number());
const zNumNullish = zNum.nullish();
const zNumDefaultZero = zNum.default(0).nullish();
const pplInstlSchema = z.object({
ruseFcltBizFk: zNumNullish,
choose: z.boolean().default(false),
pdmt: z.string().default(''),
ppMqlt: z.string().default(""),
cpct: zNumDefaultZero,
});
const fcFileSchema = z.object({
ruseFcltFk: z.string().nullish(),
fileTkn: z.string(),
filePath: z.string(),
fileKnd: z.string(),
regDt: zDateDefaultNow.nullish(),
rgtr: z.string().nullish(),
mdfcnDt: zDateDefaultNow.nullish(),
mdfr: z.string().nullish(),
});
export const fcOperSchema = z.object({
pbnstRuseFcltOperInfoPk: zNumNullish,
pbnstRuseFcltFk: z.string().nullish(),
operMthd: z.string(),
rprtvBzenty: z.string(),
bgngDt: zDateDefaultNow,
endDt: zDateDefaultNow,
regDt: zDateNullish,
rgtr: z.string().default(""),
mdfcnDt: zDateNullish,
mdfr: z.string().default(""),
choose: z.boolean().default(false),
});
const fcOrgwtSchema = z.object({
pbnstRuseFcltBizFk:zNumNullish,
swtrmtFcltFk: z.string().nullish(),
orgwtWtritQnt: zNum,
tmsYn: z.enum(["Y", "N"]).default("N"),
dschgFmYn: z.enum(["Y", "N"]).default("N"),
dtlPstnExpln: z.string().default(''),
regDt: zDateNullish,
rgtr: z.string().default(''),
mdfcnDt: zDateNullish,
mdfr: z.string().default(''),
choose: z.boolean().default(false),
});
const dmdColist = z.object({
dmdInfoPk: z.string().default(''),
dmdCoNm: z.string().default(''),
daddr: z.string(),
useUsgCd: z.string().nullish(),
splyBgngDay: zDateDefaultNow,
splyEndDay: zDateDefaultNow,
splyCpct: zNumDefaultZero,
splyFmYn: z.string().nullish(),
rgtr: z.string().nullish(),
mdfr: z.string().nullish(),
pbnstRuseFcltBizPk: zNumDefaultZero,
pbnstRuseFcltFk: z.string().nullish(),
});
export const fcBizSchema = z.object({
pbnstRuseFcltBizPk: zNumNullish,
pbnstRuseFcltFk: z.string().nullish(),
superkey: z.string().default("").nullish(),
cycl: zNum.default(1),
seCd: z.string().default(""),
bizMthdCd: z.string().default(""),
instlAprvSncnDt: zDateDefaultNow,
bizCmcnDay: zDateDefaultNow,
gvsbs: zNumDefaultZero,
lcep: zNumDefaultZero,
cusrAlotm: zNumDefaultZero,
etc: z.string().default(''),
totalMoney: zNumNullish.default(0),
rprcsFcltCpct: zNumDefaultZero,
majorPrcsMsrcCd: z.string().default(""),
addr: z.string().default(''),
rprcsMthdCd: z.string().default(""),
inoutYn: z.enum(["Y", "N"]).default("Y"),
mainSplyPumpCpct: zNumNullish,
erctWtrOcrnCpct: zNumNullish,
erctUswtrLinkSpt: z.string().nullish(),
erctUswtrFcltCpct: zNumNullish,
erctUswtrPrcsMeth: z.string().nullish(),
erctUswtrPrcsMsrcCd: z.string().nullish(),
wwtEmsnFcltPrmsnYn: z.string().default("Y"),
tmsInstlYn: z.string().default("Y"),
pbnstDrngInflwExclYn: z.string().default("Y"),
bod: zNumDefaultZero,
grssClfg: zNumDefaultZero,
combResdch: zNumDefaultZero,
trbt: zNumDefaultZero,
clIonQnt: zNumDefaultZero,
smll: zNumDefaultZero,
crmty: zNumDefaultZero,
tph: zNumDefaultZero,
tn: zNumDefaultZero,
ph: zNumDefaultZero,
cdtnv: zNumDefaultZero,
designCst: zNumNullish,
cstrnSpvsCst: zNumNullish,
fcltSbsdCst: zNumNullish,
wstCst: zNumNullish,
cnstCmcnCst: zNumNullish,
mntrgEqpmntInstlCst: zNumNullish,
gisDbCst: zNumNullish,
elpwrMtrngCst: zNumNullish,
mchnCst: zNumNullish,
archCst: zNumNullish,
pplCst: zNumNullish,
ruseFcltCst: zNumNullish,
designCstClcln: zNumNullish,
cstrnSpvsCstClcln: zNumNullish,
fcltSbsdCstClcln: zNumNullish,
wstCstClcln: zNumNullish,
cnstCmcnCstClcln: zNumNullish,
mntrgEqpmntInstlCstClcln: zNumDefaultZero,
gisDbCstClcln: zNumNullish,
elpwrMtrngCstClcln: zNumNullish,
mchnCstClcln: zNumNullish,
archCstClcln: zNumNullish,
pplCstClcln: zNumNullish,
ruseFcltCstClcln: zNumNullish,
fcOrgwts: z.array(fcOrgwtSchema).nullish(),
pplInstls: z.array(pplInstlSchema).nullish(),
fcDemands: z.array(dmdColist).nullish(),
flg: z.string().nullish(),
regDt: z.string().nullish(),
rgtr: z.string().nullish(),
mdfcnDt: z.string().nullish(),
mdfr: z.string().nullish(),
});
export const pbnstRegZod = z.object({
pbnstRuseFcltPk: z.string().default(''),
swtrmtFcltFk: z.string().default(""),
ruseUtztnFcltNm: z.string().default(""),
fcltCpct: zNumDefaultZero,
ruseCpct: zNumDefaultZero,
splyExtraCpct: zNumDefaultZero,
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).default([]).nullish(),
});
export const pbnstRegArrayZod = z.array(pbnstRegZod)
export type PbnstRegArrrayType = z.infer<typeof pbnstRegArrayZod>
export type fcBizType = z.infer<typeof fcBizSchema>;
export type fcOrgwtType = z.infer<typeof fcOrgwtSchema>;
export type ppInstlType = z.infer<typeof pplInstlSchema>;
export type operType = z.infer<typeof fcOperSchema>;
export type fcFileType = z.infer<typeof fcFileSchema>;
@@ -0,0 +1,272 @@
import type { TableUpperProps } from "@/app/store/common/type/header";
import { getFetch, postFectch, putFectch } from "@/components/lib/api";
import { z } from "zod";
import { makeMdfr, makeRstr } from "../bdstReg";
const validationMessages = {
required: (field: string) => `${field}을(를) 입력해주세요.`,
requiredSelect: (field: string) => `${field}을(를) 선택해주세요.`,
yearFormat: '4자리 연도만 입력하세요',
};
export const TEST_UUID= '2d4b151d-1828-41e0-91d9-4cd28ea1cc7e'
const rainyObjSchema = z.object({
bdstReuseFcltFk: z.number().nullish(),
pntfColKnd: z.string().default(""),
pntfColArea: z.number().default(0),
dtfcltCpct: z.number().default(0),
filtrTrtmfctYn: z.string().default("Y").nullish(),
filtrTrtmfctCpct: z.number().nullish().default(0),
filtrTrtmfctPrs: z.string().default(""),
annRnwtQty: z.number().default(0),
oilqMeasMthd: z.string().default("").nullish(),
rgtr:z.string().nullish(),
mdfr:z.string().nullish(),
}).refine((data) => data.pntfColKnd.length > 0, {
message: validationMessages.requiredSelect("종류"),
path: ["pntfColKnd"],
}).refine((data) => data.pntfColArea > 0, {
message: validationMessages.required("면적(m³)"),
path: ["pntfColArea"],
});
const reuseBuildingSchema = z.object({
bdstRuseFcltPk: z.number().nullish(),
bdstInfoFk:z.number().nullish(),
instlCmptnDt: z.coerce.date().default(() => new Date()),
instlCst: z.number().nullish(),
operMngCd: z.string().optional().default(""),
anlOperCst: z.number().default(0),
instlCstSprtYn: z.string().default("Y"),
instlCstSprtAmt: z.number().nullish(),
grntchBdstCertYn: z.string().default("Y"),
grntchBdstCertYr: z.string().default("")
.refine((year)=> year.length===0 || /^\d{4}$/.test(year),{
message: validationMessages.yearFormat
}),
grntchBdstCertNo: z.string().default(""),
grntchBdstCertGrd: z.string().default(""),
crgRdctYn: z.string().default("N").nullish(), /// 안쓰는 값
crgRdctBss: z.string().default("").nullish(), /// 안쓰는 값
crgRdctAmt: z.number().default(0), // 안쓰는 값
ruseFcltFlg: z.string().default(""),
bdstUsgCd: z.number().default(0),
lawTrgtYn: z.string().default("Y"),
rgtr:z.string().nullish(),
mdfr:z.string().nullish(),
rainyObj: rainyObjSchema.default({})
}).refine((data) => data.bdstUsgCd > 0, {
message: validationMessages.requiredSelect("건축물용도"),
path: ["bdstUsgCd"],
});
const chgBuildingSchema = z.object({
bdstInfoFk: z.number().nullish(),
archChgPrmsnDt: z.coerce.date({required_error: validationMessages.required("허가일")}),
archChgArea: z.string().default("-"),
bdstChgNm: z.string().default(""),
rgtr:z.string().nullish(),
mdfr:z.string().nullish(),
}).refine(data => data.bdstChgNm.length > 0, {
message: validationMessages.requiredSelect("구분"),
path: ["bdstChgNm"]
});
export const rainZod = z.object({
bdstInfoPk: z.number().optional(),
ctpvCd: z.number().default(0),
sggCd: z.number().default(0),
daddr: z.string().default(""),
bdstNm: z.string().default(""),
frstArchPrmsnDt: z.date().default(() => new Date()),
archChgPrmsnDt: z.coerce.date().nullish().default(null),
archArea: z.number().default(0),
archChgArea: z.number().default(0),
rgtr:z.string().nullish(),
mdfr:z.string().nullish(),
reuseBuilding: z.array(reuseBuildingSchema).default([]),
chgBuilding: z.array(chgBuildingSchema).default([])
})
export type chgBuilding={
bdstInfoFk?: number|null,
archChgPrmsnDt?: Date,
archChgArea?: string,
bdstChgNm?: string
rgtr?:string|null;
mdfr?:string|null;
}
export type customRainBdst = z.infer<typeof rainZod>
export const upHeadList: TableUpperProps[] = [
{ id: "cityText", title: "시도" },
{ id: "sggText", title: "시군구" },
{ id: "bdstNm", title: "시설명" },
{ id: "daddr", title: "위치" },
{ id: "bdsgUsgText", title: "건축물용도" },
{ id: "frstArchPrmsnDt", title: "최초건축허가일" },
{ id: "archArea", title: "건축면적" },
{ id: "lawTrgtYn", title: "법적의무대상여부" },
{ id: "bdstChgYn", title: "건축물변경여부" },
];
const rainRes: customRainBdst[] = [];
export const selectClass = "w-full h-full !text-xl";
export type rainFacState = {
rain: {
isInit: boolean;
upHeadList: TableUpperProps[];
rainRes: customRainBdst[];
};
};
type rainFacSActions = {
initRain: (code:string|number) => void;
getRainData:(pageNation:number, code:string|number) =>void;
rainSearch: (txt:string,pageNation:number,code:string|number) => void;
rainBdstReg: (data: customRainBdst, code:string|number) => void;
rainBdstUpdate: (data: customRainBdst, code:string|number) => void;
};
export type rainFacType = rainFacState & rainFacSActions;
export const rainFacStateExport: rainFacState = {
rain: {
isInit: false,
rainRes: rainRes,
upHeadList: upHeadList,
},
};
const initFetch = async (code:string|number) => {
const rainRes =await getFetch("wr", `/reuseFc/rainyInfoList/1/10/${code}`);
return rainRes;
};
export const rainFacActionsExport: (set: any) => rainFacSActions = (
set: any
) => {
return {
getRainData: async(pageNation:number, code:string|number) =>{
try{
const rainRes =await getFetch("wr", `/reuseFc/rainyInfoList/${pageNation}/10/${code}`);
// 여기서 상태 업데이트
return set((state: rainFacState) => ({
...state,
rain: {
...state.rain,
rainRes: rainRes,
isInit: false,
},
}));
}catch(e){
console.log(e)
}
},
initRain: async (code:string|number) => {
try {
// 파라이터 수정 통합관리자 =0, 시관리자=시코드, 시군구 관리자= 시군구 코드 를 세번째 파라미터로 지정 / 건축물 서치가 있을경우 4번째 파라미터로 던지기 즉 1/20/42(서울시)/영현빌딩 이런식으로)
const rainRes = await initFetch(code);
// 여기서 상태 업데이트
return set((state: rainFacState) => ({
...state,
rain: {
...state.rain,
rainRes: rainRes,
isInit: false,
},
}));
} catch (error) {
console.log("error", error);
}
},
rainSearch: async(txt:string,pageNation:number) =>{
try{
const rainRes = await getFetch('wr' , `/reuseFc/rainyInfoList/${pageNation}/20/41` +(txt? `/${txt}`:''))
set((state: rainFacState) => {
return {
rain: {
...state.rain,
rainRes: rainRes,
isInit: false,
},
};
})}
catch(erTxt){
console.log("error", erTxt)
}
},
rainBdstReg: async (data: customRainBdst,code:string|number) => {
try {
const test =await makeRstr(data);
const res = await postFectch("/reuseFc/rainyInfo", test);
if(res.ok){
if(data.chgBuilding.length > 0){
await res.json().then((resData: any) => {
const chPK = resData?.data?.bdstInfoPk
const makeCh= resData.data.chgBuilding.map((item: chgBuilding) =>
( {
...item,
bdstInfoFk: chPK,
})
);
const chch= postFectch("/reuseFc/chgBuilding", makeCh);
return chch;
}).then((chch: any) => {
if(chch.ok) {
alert("등록이 완료되었습니다.");
}
})
}else{
alert("등록이 완료되었습니다.");
}
}
const rainRes = await initFetch(code);
set((state: rainFacState) => ({
...state,
rain: {
...state.rain,
rainRes: rainRes,
isInit: false,
},
}));
} catch (e) {
console.log("e", e);
alert("등록 오류입니다.");
} finally {
}
},
rainBdstUpdate: async (data: customRainBdst,code:string|number) => {
try {
const chData =await makeMdfr(data);
const res = await putFectch("/reuseFc/rainyInfo", chData);
console.log('rainUpdate', res);
if(res.ok){
alert(" 수정이 완료되었습니다.")
}
const rainRes = await initFetch(code);
set((state: rainFacState) => ({
...state,
rain: {
...state.rain,
rainRes: rainRes,
isInit: false,
},
}));
} catch (e) {
console.log("e", e);
alert("업데이트 오류입니다.");
} finally {
}
}
}}
@@ -0,0 +1,262 @@
import { getFetch, postFectch, putFectch } from "@/components/lib/api";
import { upHeadList, type chgBuilding } from "../rainReg";
import type { TableUpperProps } from "@/app/store/common/type/header";
import { z } from "zod";
import { makeMdfr, makeRstr } from "../bdstReg";
export const rswtZod = z.object({
bdstInfoPk: z.number().nullish(),
ctpvCd: z.number().default(0),
sggCd: z.number().default(0),
daddr: z.string().default(""),
bdstNm: z.string().default(""),
frstArchPrmsnDt: z.date().default(() => new Date()),
archChgPrmsnDt: z.coerce.date().nullish().default(null),
chBuildingYn: z.string().nullish(),
archArea: z.number().default(0),
archChgArea: z.number().default(0),
rgtr: z.string().nullish().default(null),
mdfr: z.string().nullish().default(null),
bdstUsgText: z.string().default(""),
cityText: z.string().default(""),
sggText: z.string().default(""),
reuseBuilding: z
.array(
z.object({
bdstRuseFcltPk: z.number().nullish(),
bdstInfoFk: z.number().nullish(),
instlCmptnDt: z.coerce.date().default(() => new Date()),
instlCst: z.number().default(0),
operMngCd: z.string().nullish().default(""),
anlOperCst: z.number().default(0),
instlCstSprtYn: z.enum(["Y", "N"]),
instlCstSprtAmt: z.number().default(0),
grntchBdstCertYn: z.enum(["Y", "N"]),
grntchBdstCertYr: z
.string()
.default("")
.refine((year) => year.length === 0 || /^\d{4}$/.test(year), {
message: "4자리 연도만 입력하세요",
}),
grntchBdstCertNo: z.string().default(""),
grntchBdstCertGrd: z.string().default(""),
crgRdctYn: z.string().default("N").nullish(), // 안쓰는 값
crgRdctBss: z.string().default("").nullish(), /// 안쓰는 값
crgRdctAmt: z.number().default(0), // 안쓰는 값
ruseFcltFlg: z.string().default(""),
bdstUsgCd: z.number().default(0),
lawTrgtYn: z.string().default(""),
rgtr: z.string().nullish().default(null),
mdfr: z.string().nullish().default(null),
rswtrObj: z
.object({
bdstRuseFcltFk: z.number().nullish(),
wtrUsqty: z.number().default(0),
oblgTrgtWtrUsqty: z.number().nullish().default(0),
orgwtKndCd: z.string().default(""),
filtrTrtmfctCpct: z.number().default(0),
filtrTrtmfctProcs: z.string().default(""),
filtrTrtmfctUsgCd: z.string().default("").nullish(),
rswtrUsqty: z.number().default(0),
altUswtrUtztnYn: z.enum(["Y", "N"]).nullish(), //안쓰는값
altUswtrKndCd: z.string().default("").nullish(), //안쓰는값
altUswtrUtztnQnt: z.number().default(0), //안쓰는값
altUswtrIdntyMthdCd: z.string().default("").nullish(), //안쓰는값
rgtr: z.string().nullish().default(null),
mdfr: z.string().nullish().default(null),
})
.default({}),
})
)
.default([]),
chgBuilding: z
.array(
z.object({
bdstInfoFk: z.number().nullish(),
archChgPrmsnDt: z.coerce.date(),
archChgArea: z.string().default("-"),
bdstChgNm: z.string().default(""),
rgtr: z.string().nullish().default(null),
mdfr: z.string().nullish().default(null),
})
)
.default([]),
});
export type customRswtBdst = z.infer<typeof rswtZod>;
const rswtRes: customRswtBdst[] = [];
export type rswtFacState = {
rswt: {
isInit: boolean;
upHeadList: TableUpperProps[];
rswtRes: customRswtBdst[];
};
};
type rswtFacSActions = {
initRswt: (code: string | number) => void;
rswtBdstUpdate: (data: customRswtBdst, code: string | number) => void;
getRswtBdstData: (pageNation: number, code: string | number) => void;
rswtBdstSearch: (
txt: string,
pageNation: number,
code: string | number
) => void;
rswtBdstReg: (data: customRswtBdst, code: string | number) => void;
};
export type rswtFacType = rswtFacState & rswtFacSActions;
export const rswtFacStateExport: rswtFacState = {
rswt: {
isInit: false,
upHeadList: upHeadList,
rswtRes: rswtRes,
},
};
const initFetch = async (code: string | number) => {
const rswtRes = await getFetch("wr", `/reuseFc/waterreuseFc/1/10/${code}`);
return rswtRes;
};
export const rswtFacActionsExport: (set: any) => rswtFacSActions = (
set: any
) => {
return {
rswtBdstSearch: async (
txt: string,
pageNation: number,
code: string | number
) => {
try {
const rswtRes = await getFetch(
"wr",
`/reuseFc/waterreuseFc/${pageNation}/20/${code}` +
(txt ? `/${txt}` : "")
);
set((state: rswtFacState) => {
return {
...state,
rswt: {
...state.rswt,
rswtRes: rswtRes,
isInit: false,
},
};
});
} catch (erTxt) {
console.log("error", erTxt);
}
},
getRswtBdstData: async (pageNation: number, code: string | number) => {
try {
const rswtRes = await getFetch(
"wr",
`/reuseFc/waterreuseFc/${pageNation}/10/${code}`
);
console.log(pageNation);
// 여기서 상태 업데이트
return set((state: rswtFacState) => ({
...state,
rswt: {
...state.rswt,
rswtRes: rswtRes,
isInit: false,
},
}));
} catch (e) {
console.log(e);
}
},
initRswt: async (code: string | number) => {
try {
const rswtRes = await initFetch(code);
return set((state: rswtFacState) => ({
...state,
rswt: {
...state.rswt,
rswtRes: rswtRes,
isInit: false,
},
}));
} catch (error) {
console.log(error);
}
},
rswtBdstUpdate: async (data: customRswtBdst, code: string | number) => {
try {
const chData = await makeMdfr(data);
const res = await putFectch("/reuseFc/waterreuseFc", chData);
if (res.ok) {
alert("등록이 완료되었습니다.");
const rswtRes = await initFetch(code);
set((state: rswtFacState) => ({
...state,
rswt: {
...state.rswt,
rswtRes: rswtRes,
isInit: false,
},
}));
}
} catch (errorUpdate) {
alert(
"업데이트 오류입니다. " +
(errorUpdate instanceof Error ? errorUpdate.message : "")
);
} finally {
}
},
rswtBdstReg: async (data: customRswtBdst, code: string | number) => {
try {
const chData = await makeRstr(data);
const res = await postFectch("/reuseFc/waterreuseFc", chData);
if (res.ok) {
if (data.chgBuilding.length > 0) {
await res
.json()
.then((resData: any) => {
const chPK = resData?.data?.bdstInfoPk;
const makeCh = resData.data.chgBuilding.map(
(item: chgBuilding) => ({
...item,
bdstInfoFk: chPK,
})
);
const chch = postFectch("/reuseFc/chgBuilding", makeCh);
return chch;
})
.then((chch: any) => {
if (chch.ok) {
alert("등록이 완료되었습니다.");
}
});
} else {
alert("등록이 완료되었습니다.");
}
}
const rainRes = await initFetch(code);
set((state: rswtFacState) => ({
...state,
rain: {
...state.rswt,
rswtRes: rswtRes,
isInit: false,
},
}));
} catch (e) {
console.log("e", e);
alert("등록 오류입니다.");
} finally {
}
},
};
};
@@ -0,0 +1,34 @@
import type { SelectDataType } from "@common/business_components/ui";
import type { customHtdflBdst } from "../../fcltReg/htdflReg";
export const excelHtdflSttnParsing = (
data: customHtdflBdst[],
sidoCode: SelectDataType[],
sggCode: SelectDataType[]
): string[][] => {
const excelExportData: string[][] = [];
data.forEach((item) => {
excelExportData.push([
sidoCode.find((sido) => sido.val === item.ctpvCd.toString())?.text ?? "",
sggCode.find((sgg) => sgg.val === item.sggCd.toString())?.text ?? "",
item.bdstNm ?? "",
item.daddr ?? "",
String(item.frstArchPrmsnDt ?? ""),
String(item.reuseBuilding?.[0]?.htdflObj.etgtType ?? ""),
String(item.reuseBuilding?.[0]?.htdflObj.fclCpct ?? ""), // fix: added missing parenthesis
String(item.reuseBuilding?.[0]?.htdflObj.plwtYn ? "Y" : "N"), // fix: added missing parenthesis
String(item.reuseBuilding?.[0]?.htdflObj.orgwtWtritSpt ?? ""), // fix: added missing parenthesis
String(item.reuseBuilding?.[0]?.htdflObj.wtritEntrcTp ?? ""), // fix: removed as it doesn't exist in the provided context
String(item.reuseBuilding?.[0]?.htdflObj.orgwtOcrnProcs ?? ""), // fix: removed as it doesn't exist in the provided context
String(item.reuseBuilding?.[0]?.htdflObj?.amtgnr ?? ""), // fix: removed as it doesn't exist in the provided context
String(item.reuseBuilding?.[0]?.htdflObj?.prcsProcsYn ?? ""), // fix: removed as it doesn't exist in the provided context
String(item.reuseBuilding?.[0]?.htdflObj?.prcsFcltCpct ?? ""), // fix: removed as it doesn't exist in the provided context
String(item.reuseBuilding?.[0]?.htdflObj?.fmYn ?? ""), // fix: removed as it doesn't exist in the provided context
String(item.reuseBuilding?.[0]?.htdflObj?.utztnCpct ?? ""), // fix: removed as it doesn't exist in the provided context
String(item.reuseBuilding?.[0]?.htdflObj?.utztnUsg ?? ""), // fix: removed as it doesn't exist in the provided context
String(item.reuseBuilding?.[0]?.htdflObj?.emsnExitTp ?? ""), // fix: removed as it doesn't exist in the provided context
]);
});
return excelExportData;
};
@@ -0,0 +1,312 @@
import type { z } from "zod";
import type { sttnHeadListType } from "../rainSttn/headList";
import type { CommonTableProps } from "@/app/store/common/type/header";
export const htdflSttHeadListExport: z.infer<typeof sttnHeadListType> = [
{
id: "cityText",
title: "시도",
visible: true,
},
{
id: "sggText",
title: "시군구",
visible: true,
},
{
id: "bdstNm",
title: "발전소명",
visible: true,
},
{
id: "daddr",
title: "주소",
visible: true,
},
{
id: "frstArchPrmsnDt",
title: "준공년월",
visible: true,
},
{
id: "etgtType",
title: "발전유형",
visible: true,
},
{
id: "fclCpct",
title: "설비용량(KW)",
visible: true,
},
{
id: "plwtYn",
title: "담수화여부",
visible: true,
},
{
id: "orgwtWtritSpt",
title: "원수취수지점",
visible: true,
},
{
id: "wtritEntrcTp",
title: "취수구온도(℃)",
visible: true,
},
{
id: "orgwtOcrnProcs",
title: "원수발생공정",
visible: true,
},
{
id: "amtgnr",
title: "발생량",
visible: true,
},
{
id: "prcsProcsYn",
title: "처리공정여부",
visible: true,
},
{
id: "prcsFcltCpct",
title: "처리시설용량(m³)",
visible: true,
},
{
id: "fmYn",
title: "유량계여부",
visible: true,
},
{
id: "utztnCpct",
title: "이용량(m³)",
visible: true,
},
{
id: "utztnUsg",
title: "이용용도",
visible: true,
},
{
id: "emsnExitTp",
title: "배출구온도(℃)",
visible: true,
},
];
// id는 다확인해야함
export const htdflSttNodeListExport: CommonTableProps[] = [
{
id: "bdnstInfo",
title: "1.건축물정보",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 5,
},
{
id: "htdflFcltInfo",
title: "2.온배수 시설현황",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 3,
},
{
id: "htdflMngInfo",
title: "3.온배수운영현황",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 11,
},
{
id: "adminDiv",
title: "행정구역",
visible: true,
row: 2,
upName: "bdnstInfo",
rowSpan: 1,
colSpan: 2,
},
// 3번째줄 시작
{
id: "cityText",
title: "시도",
visible: true,
upName: "adminDiv",
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "sggText",
title: "시군구",
visible: true,
upName: "adminDiv",
row: 3,
rowSpan: 1,
colSpan: 1,
},
// 2번째 줄
// 1번째 줄 건축물정보 아래의 행으로 만들 헤더
{
id: "bdstNm",
title: "발전소명",
visible: true,
upName: "bdnstInfo",
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "daddr",
title: "주소",
visible: true,
upName: "bdnstInfo",
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "frstArchPrmsnDt",
title: "준공년월",
upName: "bdnstInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "etgtType",
title: "발전유형",
upName: "htdflFcltInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "fclCpct",
title: "설비용량(KW)",
upName: "htdflFcltInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "plwtYn",
title: "담수화여부",
upName: "htdflFcltInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "orgwtWtritSpt",
title: "원수취수지점",
upName: "htdflMngInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "wtritEntrcTp",
title: "취수구온도(℃)",
upName: "htdflMngInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "orgwtOcrnProcs",
title: "원수발생공정",
upName: "htdflMngInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "amtgnr",
title: "발생량",
upName: "htdflMngInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "prcsProcsYn",
title: "처리공정여부",
upName: "prcsProcs",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "prcsFcltCpct",
title: "처리시설용량(m³)",
upName: "htdflMngInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "fmYn",
title: "유량계여부",
upName: "htdflMngInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "utztnCpct",
title: "이용량(m³)",
upName: "htdflMngInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "utztnUsg",
title: "이용용도",
upName: "htdflMngInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "emsnExitTp",
title: "배출구온도(℃)",
visible: true,
upName: "htdflMngInfo",
row: 2,
rowSpan: 2,
colSpan: 1,
},
];
@@ -0,0 +1,121 @@
import type { CommonTableProps } from "@/app/store/common/type/header";
import { htdflSttHeadListExport, htdflSttNodeListExport } from "./headList";
import type { sttnHeadListType } from "../rainSttn/headList";
import type { z } from "zod";
import { controlHeadView } from "../rainSttn";
import type { customHtdflBdst } from "../../fcltReg/htdflReg";
import { fetchType, getFetch } from "@/components/lib/api";
const htdflSttHeadList = htdflSttHeadListExport;
const htdflSttNodeList = htdflSttNodeListExport;
export type htdflSttnState = {
htdflSttn: {
isInit: boolean;
htdflSttHeadList: z.infer<typeof sttnHeadListType>;
htdflSttNodeList: CommonTableProps[];
htdflSttnRes: customHtdflBdst[]
excelList: [];
};
};
type htdflSttnActions = {
initHtdfl: (con: string) => void;
htdflSttnSearch: (page: number, total: string, con: string) => void;
htdflChSttnHead: (
headList: z.infer<typeof sttnHeadListType>,
) => void;
};
export type htdflSttnType = htdflSttnState & htdflSttnActions;
export const htdflSttnStateExport: htdflSttnState = {
htdflSttn: {
htdflSttHeadList: htdflSttHeadList,
htdflSttNodeList: htdflSttNodeList,
htdflSttnRes: [],
excelList: [],
isInit: false,
},
};
const initFetch = async (code: string | number) => {
const htdflRes = await getFetch(
"wr",
`/drain/facilityList/1/20/${code}`)
return htdflRes;
};
export const htdflSttnActionsExport: (set: any) => htdflSttnActions = (
set: any
) => {
return {
initHtdfl: async (code: string | number) => {
try {
const htdflSttnRes = await initFetch(code);
set((state: htdflSttnState) => {
return {
...state,
htdflSttn: {
...state.htdflSttn,
htdflSttnRes: htdflSttnRes,
isInit: false,
},
};
});
} catch (error) {
console.log(error);
}
},
htdflSttnSearch: async (page: number, total: string, con: string) => {
try {
const htdflSttnRes = await getFetch(
fetchType.WR,
`/drain/facilityList/${page}/${total}/${con}`
);
if (Number(total) > 9000) {
set((state: htdflSttnState) => {
return {
...state,
htdflSttn: {
...state.htdflSttn,
excelList: htdflSttnRes,
},
};
});
} else
set((state: htdflSttnState) => {
return {
...state,
htdflSttn: {
...state.htdflSttn,
htdflSttnRes: htdflSttnRes,
isInit: false,
},
};
});
} catch (erTxt) {
console.log("error", erTxt);
}
},
htdflChSttnHead: async (
headList: z.infer<typeof sttnHeadListType>
): Promise<void> => {
const changeNodeList = controlHeadView(headList, htdflSttNodeList)
return set((state: htdflSttnState) => ({
htdflSttn: {
...state.htdflSttn,
htdflSttHeadList: headList,
htdflSttNodeList: changeNodeList,
},
}));
},
}
}
@@ -0,0 +1,28 @@
import type { customPbnst } from "../../fcltReg/pbnstReg/type";
export const excelPbnstSttnParsing = (data: any[]): string[][] => {
const excelExportData: string[][] = [];
data.forEach((item) => {
excelExportData.push([
item.rvbsn,
String(item.lgbsn),
item.mdmbsn ?? "",
item.rgnNm ?? "",
String(item.sido ?? ""),
String(item.gugun ?? ""),
String(item.bscFctNm ?? ""),
String(item.efflWqltStndrdNm ?? ""),
String(item.fctCpc ?? ""),
String(item.tel ?? ""),
String(item.ruseUtztnFcltNm ?? ""),
String(item.fcltCpct ?? ""),
String(item.splyExtraCpct ?? ""),
String(item.ruseCpct ?? ""),
String(item.usageTotal ?? ""),
String(item.inUsage ?? ""),
String(item.outUsage ?? ""),
])
})
return excelExportData;
}
@@ -0,0 +1,541 @@
import type { sttnHeadListType } from "../rainSttn/headList";
import type {
CommonTableProps,
TableUpperProps,
} from "@/app/store/common/type/header";
import { z } from "zod";
export const pbnSttHeadListExport: z.infer<typeof sttnHeadListType> = [
{ id: "rvbsn", title: "권역", visible: true },
{
id: "lgbsn",
title: "단위유역",
visible: true,
},
{
id: "mdmbsn",
title: "중권역",
visible: true,
},
{ id: "rgnNm", title: "환경청", visible: true },
{
id: "sido",
title: "시도",
visible: true,
},
{
id: "gugun",
title: "시군구",
visible: true,
},
{ id: "bscFctNm", title: "시설명", visible: true },
{ id: "efflWqltStndrdNm", title: "지역구분", visible: true },
{ id: "tel", title: "전화번호", visible: true },
{ id: "fctCpc", title: "시설용량(톤/일)", visible: true },
{ id: "ruseUtztnFcltNm", title: "재이용시설명", visible: true },
{
id: "fcltCpct",
title: "시설용량(m³/일)",
visible: true,
},
{
id: "splyExtraCpct",
title: "하수처리량(m³/일)",
visible: true,
},
{
id: "ruseCpct",
title: "재이용량(m³/일)",
visible: true,
},
{
id: "usageTotal",
title: "합계",
visible: true,
},
{
id: "inUsage",
title: "장내용수",
visible: true,
},
{
id: "outUsage",
title: "장외용수",
visible: true,
},
{
id: "operMthd",
title: "운영방식",
visible: true,
},
{
id: "rprtvBzenty",
title: "대행업체",
visible: true,
},
{
id: "bgngDt",
title: "시작일",
visible: true,
},
{
id: "endDt",
title: "종료일",
visible: true,
},
];
// id는 다확인해야함
export const pbnstSttNodeListExport: CommonTableProps[] = [
{
id: "catchment",
title: "유역",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 3,
},
{
id: "operMngCd",
title: "환경청",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{
id: "adminDiv",
title: "행정구역",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 2,
},
{
id: "bdnstNm",
title: "시설명",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{
id: "locDiv",
title: "지역구분",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{
id: "tel",
title: "전화번호",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{
id: "fctCpc",
title: "시설용량(톤/일)",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{
id: "rusNm",
title: "재이용시설명",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{
id: "rusSup",
title: "재이용수공급가능량",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 3,
},
{
id: "yearResult",
title: "연간실적정보(m³)",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 3,
},
{
id: "mngInfo",
title: "운영정보",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 4,
},
{
id: "a",
title: "권역",
upName: "catchment",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "aaa",
title: "단위유역",
upName: "catchment",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "aaaa",
title: "중권역",
upName: "catchment",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "cityText",
title: "시도",
upName: "adminDiv",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "sggText",
title: "시군구",
upName: "adminDiv",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "fcltCpct",
title: "시설용량(m³/일)",
upName: "rusSup",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "trbt",
title: "하수처리량(m³/일)",
upName: "rusSup",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "ruseCpct",
title: "재이용량(m³/일)",
upName: "rusSup",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "total",
title: "합계",
upName: "yearResult",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "ithlWtr",
title: "장내용수",
upName: "yearResult",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "othlWtr",
title: "장외용수",
upName: "yearResult",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "mngMeth",
title: "운영방식",
upName: "mngInfo",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "rprtvBzenty",
title: "대행업체",
upName: "mngInfo",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "firstDay",
title: "시작일",
upName: "mngInfo",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
{
id: "LastDay",
title: "종료일",
upName: "mngInfo",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1,
},
];
export const ruseFcltNodeListExport: TableUpperProps[] = [
{ id: "cycl", title: "차수", visible: true, row: 1, rowSpan: 3, colSpan: 1 },
{ id: "seCd", title: "구분", visible: true, row: 1, rowSpan: 3, colSpan: 1 },
{
id: "busiTotal",
title: "사업개요",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 9,
},
{
id: "ruseFclt",
title: "재처리시설",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 3,
},
{
id: "mainSplyPumpCpct",
title: "메인공급펌프용량",
visible: true,
row: 1,
rowSpan: 3,
colSpan: 1,
},
{
id: "buziFee",
title: "사업비(백만원)",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 5,
},
{
id: "instlAprvSncnDt",
title: "설치승인・인가일",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "bizCmcnDay",
title: "사업준공일",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "rprcsFcltCpct",
title: "시설용량(m³/일)",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "rprcsMthdCd",
title: "재처리방식",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "majorPrcsMsrcCd",
title: "주처리공법",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "inoutYn",
title: "위치처리장(내・외)",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "addr",
title: "위치(주소)",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{ id: "gvsbs", title: "국고", visible: true, row: 3, rowSpan: 1, colSpan: 1 },
{
id: "lcep",
title: "지방비",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "cusrAlotm",
title: "민간투자비",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{ id: "etc", title: "기타", visible: true, row: 3, rowSpan: 1, colSpan: 1 },
{
id: "totalMoney",
title: "합계",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
];
export const ruseSplyHeadListExport: TableUpperProps[] = [
{ id: "cycl", title: "차수", visible: true },
{ id: "orgwtWtritQnt", title: "원수취수량", visible: true },
{ id: "tmsYn", title: "하수처리량TMS 전후", visible: true },
{ id: "dschgFmYn", title: "하수처리장 방류 유량계 전·후​", visible: true },
{ id: "dtlPstnExpln", title: "상세위치 설명", visible: true },
];
export const rusePplHeadListExport: TableUpperProps[] = [
{ id: "cycl", title: "차수", visible: true },
{ id: "ppMqlt", title: "관재질", type: "select", visible: true },
{ id: "pdmt", title: "관경", type: "select", visible: true },
{ id: "cpct", title: "연장", edit: true, visible: true },
];
export const ruseGuranteeHeadListExport: TableUpperProps[] = [
{ id: "cycl", title: "차수", visible: true },
{ id: "bod", title: "BOD(mg/L)", visible: true },
{ id: "grssClfg", title: "총대장균군수(개/mg)", visible: true },
{ id: "combResdch", title: "결합잔류염소(mh/L)", visible: true },
{ id: "trbt", title: "탁도(NTU)", visible: true },
{ id: "smll", title: "냄새", visible: true },
{ id: "crmty", title: "색도", visible: true },
{ id: "tn", title: "총질소(mg/L)", visible: true },
{ id: "tph", title: "총인(mg/L)", visible: true },
{ id: "ph", title: "수소이온농도", visible: true },
{ id: "clIonQnt", title: "염화물(mg/L)", visible: true },
{ id: "cdtnv", title: "전기전도도(μs/cm)​", visible: true },
];
export const ruseDmdHeadListExport: TableUpperProps[] = [
{ id: "cycl", title: "차수", visible: true },
{ id: "dmdCoNm", title: "수요처명", visible: true },
{ id: "daddr", title: "위치(주소)", visible: true },
{ id: "useUsgCd", title: "사용용도", visible: true },
{ id: "splyBgngDay", title: "공급시작일", visible: true },
{ id: "splyEndDay", title: "공급종료일", visible: true },
{ id: "splyCpct", title: "공급량(m³/일)", visible: true },
{ id: "splyFmYon", title: "공급유량계 유무", visible: true },
];
export const ruseFcltHeadListExport: CommonTableProps[] = [
{ id: "cycl", title: "차수", visible: true},
{ id: "seCd", title: "구분", visible: true},
{ id: "gvsbs", title: "국고", visible: true },
{
id: "lcep",
title: "지방비",
visible: true,
},
{
id: "cusrAlotm",
title: "민간투자비",
visible: true,
},
{ id: "etc", title: "기타", visible: true },
{
id: "totalMoney",
title: "합계",
visible: true,
},
{
id: "instlAprvSncnDt",
title: "설치승인・인가일",
visible: true,
},
{
id: "bizCmcnDay",
title: "사업준공일",
visible: true,
},
{
id: "rprcsFcltCpct",
title: "시설용량(m³/일)",
visible: true,
},
{
id: "rprcsMthdCd",
title: "재처리방식",
visible: true,
},
{
id: "majorPrcsMsrcCd",
title: "주처리공법",
visible: true,
},
{
id: "inoutYn",
title: "위치처리장(내・외)",
visible: true,
},
{
id: "addr",
title: "위치(주소)",
visible: true,
},
{
id: "mainSplyPumpCpct",
title: "메인공급펌프용량",
visible: true,
},
];
@@ -0,0 +1,322 @@
import type { CommonTableProps, TableUpperProps } from "@/app/store/common/type/header";
import type { z } from "zod";
import { pbnSttHeadListExport, pbnstSttNodeListExport, ruseDmdHeadListExport, ruseFcltHeadListExport, ruseFcltNodeListExport, ruseGuranteeHeadListExport, rusePplHeadListExport, ruseSplyHeadListExport } from "./headList";
import { fetchType, getFetch, postFectch } from "@/components/lib/api";
import { controlHeadView } from "../rainSttn";
import type { sttnHeadListType } from "../rainSttn/headList";
import type { customPbnst, pubHasuType } from "../../fcltReg/pbnstReg/type";
import { excelPbnstSttnParsing } from "./excel";
import type { FcPrfType } from "@/app/store/prfmncReg/pbnstPrfmncReg/type";
import type { ReturnType } from "@common/business_components/ui";
import type { WaterReuseFacility } from "./type";
import moment from "moment";
const pbnstSttHeadList = pbnSttHeadListExport;
const pbnstSttNodeList = pbnstSttNodeListExport;
export type pbnstSttnState = {
pbnstSttn: {
pbnstSttnRes: WaterReuseFacility[];
pbnstSearchData: WaterReuseFacility[];
pbnstSttHeadList: CommonTableProps[];
pbnstSttNodeList: CommonTableProps[];
pbnstDetail: customPbnst;
ruseFcltNodeList:TableUpperProps[]
ruseSplyHeadList:TableUpperProps[]
rusePplHeadList:TableUpperProps[]
ruseGuranteeHeadList:TableUpperProps[]
ruseDmdHeadList:TableUpperProps[]
ruseFcltHeadList:TableUpperProps[]
excelList: [];
isInit: boolean;
};
};
type pbnstSttnActions = {
pbnstChSttnHead: (headList: z.infer<typeof sttnHeadListType>) => void;
pbnstSttnSearch: (
page: string,
total: string,
reurnValue: ReturnType,
searchNm: string | undefined,
year: string
) => void;
pbnSttnInit: (
page: string,
total: string,
reurnValue: ReturnType,
year: string
) => void;
getPbnStnDetail: (pbnstRuseFcltPk: string) => void;
pbnNmSearch: (
page: string,
total: string,
reurnValue: ReturnType,
searchNm: string | undefined,
year: string
) => void;
};
export type pbnstSttnType = pbnstSttnState & pbnstSttnActions;
export const pbnstSttnStateExport: pbnstSttnState = {
pbnstSttn: {
pbnstSttHeadList: pbnstSttHeadList,
pbnstSttNodeList: pbnstSttNodeList,
ruseFcltNodeList:ruseFcltNodeListExport,
ruseSplyHeadList:ruseSplyHeadListExport,
rusePplHeadList:rusePplHeadListExport,
ruseGuranteeHeadList:ruseGuranteeHeadListExport,
ruseDmdHeadList:ruseDmdHeadListExport,
ruseFcltHeadList:ruseFcltHeadListExport,
pbnstSttnRes: [],
pbnstDetail: {} as customPbnst,
pbnstSearchData: [],
excelList: [],
isInit: false,
},
};
const hasuListFetch = async (
page: string,
total: string,
reurnValue: ReturnType,
searchNm: string | undefined,
year: string
) => {
let url = "";
if (reurnValue.partValue === "A") {
url = `/prcsFclt/info/${page}/${total}/${reurnValue.partValue}/${
reurnValue.sidoValue ? reurnValue.sidoValue : reurnValue.sigunValue
}/0/1/SW`
} else if (reurnValue.partValue === "R") {
url = `/prcsFclt/info/${page}/${total}/${reurnValue.partValue}/${
reurnValue.regionValue
? reurnValue.regionValue
: reurnValue.unitWaterShedValue
? reurnValue.unitWaterShedValue
: reurnValue.middleRegionValue
}/0/1/SW`
} else {
url = `/prcsFclt/info/${page}/${total}/${reurnValue.envPartValue}/${reurnValue.sidoValue ? reurnValue.sidoValue : reurnValue.sigunValue}/0/1/SW`
}
if( searchNm&& searchNm?.length>0){
url+="/"+searchNm
}
const pbnList = await getFetch(fetchType.COMMON, url);
const arrayList = pbnList.map((item: pubHasuType) => item.bscFctCd);
const getRuseList = await postFectch(
`/reuseFc/pubDetailList/${year}`,
arrayList,
fetchType.WR
);
const checkWrRegListRes = getRuseList.data;
const data: WaterReuseFacility[] = checkWrRegListRes.map(
(item: FcPrfType) => {
const findData = pbnList.find(
(fclt: pubHasuType) =>
fclt.bscFctCd === item.pbnstRuseFcltPk.substring(0, 11)
);
const usage = item.prfList.reduce(
(acc, cur) => {
acc.inUsage +=
cur.wshwtr +
cur.coolUswtr +
cur.cleanUswtr +
cur.drwtUswtr +
cur.dltnUswtr +
cur.ithlRswtr +
cur.ithlEtcUswtr +
cur.cleanToilUswtr +
cur.resn;
acc.outUsage +=
cur.lndwtr +
cur.hydUswtr +
cur.ugwtChr +
cur.farmUswtr +
cur.rvrKeepUswtr +
cur.indstUswtr;
acc.total = acc.inUsage + acc.outUsage;
return acc;
},
{ total: 0, inUsage: 0, outUsage: 0 }
);
return {
rvbsn: findData?.rvbsn,
lgbsn: findData?.lgbsn,
mdmbsn: findData?.mdmbsn,
rgnNm: findData?.rgnNm,
sido: findData?.sido,
gugun: findData?.gugun,
bscFctNm: findData?.bscFctNm,
efflWqltStndrdNm: findData?.efflWqltStndrdNm,
fctCpc: findData.fctCpc,
tel: findData?.tel ?? "-",
ruseUtztnFcltNm: item.ruseUtztnFcltNm,
fcltCpct: item.fcltCpct,
splyExtraCpct: item.splyExtraCpct,
ruseCpct: item.ruseCpct,
pbnstRuseFcltPk: item.pbnstRuseFcltPk,
usageTotal: usage.total,
inUsage: usage.inUsage,
outUsage: usage.outUsage,
operMthd: item.operList[0]?.operMthd,
rprtvBzenty: item.operList[0]?.rprtvBzenty,
bgngDt: moment(item.operList[0]?.bgngDt).format("YYYY-MM-DD") ?? "",
endDt: moment(item.operList[0]?.endDt).format("YYYY-MM-DD") ?? "",
searchNm: findData.bscFctNm,
searchPk: findData.bscFctCd,
prfList:item?.prfList??[]
};
}
);
return data;
};
export const pbnstSttnActionsExport: (set: any) => pbnstSttnActions = (
set: any
) => {
return {
pbnstChSttnHead: async (
headList: z.infer<typeof sttnHeadListType>
): Promise<void> => {
const changeNodeList = controlHeadView(headList, pbnstSttNodeList);
return set((state: pbnstSttnState) => ({
pbnstSttn: {
...state.pbnstSttn,
pbnstSttHeadList: headList,
pbnstSttNodeList: changeNodeList,
},
}));
},
pbnstSttnSearch: async (
page: string,
total: string,
reurnValue: ReturnType,
searchNm: string | undefined,
year: string
) => {
try {
const pbnstSttnRes = await hasuListFetch(
page,
total,
reurnValue,
searchNm,
year
);
console.log("pbnstSttnRes", pbnstSttnRes);
if (Number(total) > 9000) {
const pbnstExcel = excelPbnstSttnParsing(pbnstSttnRes);
set((state: pbnstSttnState) => {
return {
...state,
pbnstSttn: {
...state.pbnstSttn,
excelList: pbnstExcel,
},
};
});
} else
set((state: pbnstSttnState) => {
return {
...state,
pbnstSttn: {
...state.pbnstSttn,
pbnstSttnRes: pbnstSttnRes,
isInit: false,
},
};
});
} catch (erTxt) {
console.log("error", erTxt);
}
},
pbnSttnInit: async (
page: string,
total: string,
reurnValue: ReturnType,
year: string
) => {
try {
const pbnstSttnRes = await hasuListFetch(
page,
total,
reurnValue,
undefined,
year
);
console.log('pbnstSttnRes ', pbnstSttnRes)
set((state: pbnstSttnState) => {
return {
...state,
pbnstSttn: {
...state.pbnstSttn,
pbnstSttnRes: pbnstSttnRes,
isInit: false,
},
};
});
} catch (erTxt) {
console.log("error", erTxt);
}
},
getPbnStnDetail: async (pbnstRuseFcltPk: string) => {
try {
let pbnstDetail = await getFetch("wr", `/reuseFc/pubFc/${pbnstRuseFcltPk}`);
if(pbnstDetail.length>=0){
pbnstDetail= pbnstDetail.find((item: customPbnst) =>item.pbnstRuseFcltPk === pbnstRuseFcltPk)
}
console.log( 'pbnstDetail ', pbnstDetail)
set((state: pbnstSttnState) => {
return {
...state,
pbnstSttn: {
...state.pbnstSttn,
pbnstDetail: pbnstDetail,
},
};
});
} catch (errorHasu) {
console.log(errorHasu);
}
},
pbnNmSearch: async (
page: string,
total: string,
reurnValue: ReturnType,
searchNm: string | undefined,
year: string
) => {
try {
const pbnstSttnRes = await hasuListFetch(
page,
total,
reurnValue,
searchNm,
year
);
set((state: pbnstSttnState) => {
return {
...state,
pbnstSttn: {
...state.pbnstSttn,
pbnstSearchData: pbnstSttnRes,
},
};
});
} catch (e) {
console.log(e);
}
},
};
};
@@ -0,0 +1,27 @@
import type { PrfType } from "@/app/store/prfmncReg/pbnstPrfmncReg/type";
export type WaterReuseFacility = {
bscFctNm: string; // 기본시설명 (예: "난지")
efflWqltStndrdNm: string; // 방류수 수질 기준명 (예: "500톤 이상(Ⅲ지역)")
fcltCpct: number; // 시설 용량 (숫자형, 예: 1)
fctCpc: string; // 시설 처리 능력 (예: "2360000")
gugun: string; // 구군 정보 (예: " ")
inUsage: number; // 유입량 (예: 1387)
lgbsn: string; // 대수계 (예: "한강본류")
mdmbsn: string; // 중권역 (예: "한강서울")
outUsage: number; // 유출량 (예: 900)
pbnstRuseFcltPk: string; // 공공하수 재이용 시설 PK (예: "11000SW001R1")
rgnNm: string; // 관할 기관명 (예: "한강유역환경청")
ruseCpct: number; // 재이용 가능 용량 (예: 123)
ruseUtztnFcltNm: string; // 재사용 활용 시설명 (예: "난지 재사용")
rvbsn: string; // 소수계 (예: "한강")
sido: string; // 시도 정보 (예: "서울특별시")
splyExtraCpct: number; // 추가 공급 용량 (예: 123)
tel: string; // 전화번호 (예: "-")
usageTotal: number; // 총 사용량 (예: 2287)
operMthd: string;
rprtvBzenty: string;
bgngDt: string;
endDt: string;
prfList:PrfType[];
};
@@ -0,0 +1,40 @@
import type { SelectDataType } from "@common/business_components/ui";
import type { customRainBdst } from "../../fcltReg/rainReg";
export const excelRainSttnParsing = (
data: customRainBdst[],
sidoCode: SelectDataType[],
sggCode: SelectDataType[]
): string[][] => {
const excelExportData: string[][] = [];
data.forEach((item) => {
excelExportData.push([
sidoCode.find((sido) => sido.val === item.ctpvCd.toString())?.text ?? "",
sggCode.find((sgg) => sgg.val === item.sggCd.toString())?.text ?? "",
item.bdstNm ?? "",
item.daddr ?? "",
String(item.bdstInfoPk ?? ""),
String(item.frstArchPrmsnDt ?? ""),
String(item.archArea ?? ""),
String(item.chgBuilding.length > 0 ? "Y" : "N"),
String(item.reuseBuilding?.[0]?.lawTrgtYn ?? ""),
String(item.reuseBuilding?.[0]?.instlCmptnDt ?? ""),
String(item.reuseBuilding?.[0]?.instlCst ?? ""),
item.reuseBuilding?.[0]?.rainyObj?.pntfColKnd ?? "",
String(item.reuseBuilding?.[0]?.rainyObj?.pntfColArea ?? ""),
String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctYn ?? ""),
String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctCpct ?? ""),
String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctPrs ?? ""),
String(item.reuseBuilding?.[0]?.rainyObj?.dtfcltCpct ?? ""),
String(item.reuseBuilding?.[0]?.instlCstSprtYn ?? ""),
String(item.reuseBuilding?.[0]?.instlCstSprtAmt ?? ""),
String(item.reuseBuilding?.[0]?.grntchBdstCertYn ?? ""),
String(item.reuseBuilding?.[0]?.grntchBdstCertYr ?? ""),
String(item.reuseBuilding?.[0]?.grntchBdstCertNo ?? ""),
String(item.reuseBuilding?.[0]?.grntchBdstCertGrd ?? "")
]);
});
return excelExportData;
};
@@ -0,0 +1,583 @@
import type { CommonTableProps } from "@/app/store/common/type/header";
import { z } from "zod";
export const sttnHeadListType = z.array(
z.object({
id: z.string(),
title: z.string(),
visible: z.boolean(),
})
);
export const rainSttHeadListExport: z.infer<typeof sttnHeadListType> = [
{
id: "cityText",
title: "시도",
visible: true,
},
{
id: "sggText",
title: "시군구",
visible: true,
},
{
id: "bdstNm",
title: "건축물명",
visible: true,
},
{
id: "daddr",
title: "주소",
visible: true,
},
{
id: "bdstUsgCd",
title: "건축물용도코드",
visible: true,
},
{
id: "frstArchPrmsnDt",
title: "최초건축허가일시",
visible: true,
},
{
id: "archArea",
title: "건축면적",
visible: true,
},
{
id: "chBuildingYn",
title: "중축・개축・재축여부",
visible: true,
},
{
id: "lawTrgtYn",
title: "법적의무대상여부",
visible: true,
},
{
id: "instlCmptnDt",
title: "설치완료일시",
visible: true,
},
{
id: "instlCst",
title: "설치비용",
visible: true,
},
{
id: "pntfColKnd",
title: "집수지점종류",
visible: true,
},
{
id: "pntfColArea",
title: "집수지점면적",
visible: true,
},
{
id: "dtfcltCpct",
title: "저류조용량",
visible: true,
},
{
id: "filtrTrtmfctYn",
title: "여과처리시설유무",
visible: true,
},
{
id: "filtrTrtmfctCpct",
title: "여과처리시설용량",
visible: true,
},
{
id: "filtrTrtmfctPrs",
title: "여과처리시설처리공정",
visible: true,
},
{
id: "instlCstSprtYn",
title: "설치지원비용여부",
visible: true,
},
{
id: "instlCstSprtAmt",
title: "설치지원비용",
visible: true,
},
{
id: "grntchBdstCertYn",
title: "녹색건축물인증여부",
visible: true,
},
{
id: "grntchBdstCertYr",
title: "녹색건축물인증년도",
visible: true,
},
{
id: "grntchBdstCertNo",
title: "녹색건축물인증번호",
visible: true,
},
{
id: "grntchBdstCertGrd",
title: "녹색건축물인증등급",
visible: true,
},
];
// id는 다확인해야함
export const rainSttNodeListExport: CommonTableProps[] = [
{
id: "bdnstInfo",
title: "1.건축물정보",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 10,
},
{
id: "rainFcltInfo",
title: "2.빗물이용시설정보",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 7,
},
{
id: "insenInfo",
title: "3.인센티브 정보",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 6,
},
{
id: "adminDiv",
title: "행정구역",
visible: true,
row: 2,
upName: "bdnstInfo",
rowSpan: 1,
colSpan: 2,
},
// 3번째줄 시작
{
id: "cityText",
title: "시도",
visible: true,
upName: "adminDiv",
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "sggText",
title: "시군구",
visible: true,
upName: "adminDiv",
row: 3,
rowSpan: 1,
colSpan: 1,
},
// 2번째 줄
// 1번째 줄 건축물정보 아래의 행으로 만들 헤더
{
id: "bdstNm",
title: "건축물명",
visible: true,
upName: "bdnstInfo",
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "daddr",
title: "주소",
visible: true,
upName: "bdnstInfo",
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "bdstUsgCd",
title: "건축물용도코드",
upName: "bdnstInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "frstArchPrmsnDt",
title: "최초건축허가일시",
upName: "bdnstInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "archArea",
title: "건축면적",
upName: "bdnstInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "chBuildingYn",
title: "중축・개축・재축여부",
upName: "bdnstInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "lawTrgtYn",
title: "법적의무대상여부",
upName: "bdnstInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "instlCmptnDt",
title: "설치완료일시",
upName: "bdnstInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "instlCst",
title: "설치비용",
upName: "rainFcltInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "pntfCol",
title: "집수면",
upName: "rainFcltInfo",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 2,
},
{
id: "pntfColKnd",
title: "집수지점종류",
upName: "pntfCol",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "pntfColArea",
title: "집수지점면적",
upName: "pntfCol",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "dtfcltCpct",
title: "저류조용량",
upName: "rainFcltInfo",
visible: true,
row: 2,
rowSpan: 2,
colSpan: 1,
},
{
id: "filtrTrtmfctYn",
title: "여과처리시설유무",
upName: "filtrTrtmfct",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "filtrTrtmfctCpct",
title: "여과처리시설용량",
upName: "filtrTrtmfct",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "filtrTrtmfctPrs",
title: "여과처리시설처리공정",
upName: "filtrTrtmfct",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "filtrTrtmfct",
title: "여과등 처리시설",
visible: true,
upName: "insenInfo",
row: 2,
rowSpan: 1,
colSpan: 3,
},
{
id: "instlCstSprtYn",
title: "설치지원비용여부",
upName: "instlCstSprt",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "instlCstSprtAmt",
title: "설치지원비용",
upName: "instlCstSprt",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "instlCstSprt",
title: "설치비지원",
upName: "insenInfo",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 2,
},
{
id: "grntchBdstCertYn",
title: "녹색건축물인증여부",
upName: "grntchBdstCert",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "grntchBdstCertYr",
title: "녹색건축물인증년도",
upName: "grntchBdstCert",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "grntchBdstCertNo",
title: "녹색건축물인증번호",
upName: "grntchBdstCert",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "grntchBdstCertGrd",
title: "녹색건축물인증등급",
upName: "grntchBdstCert",
visible: true,
row: 3,
rowSpan: 1,
colSpan: 1,
},
{
id: "grntchBdstCert",
title: "녹색건축물인증",
upName: "insenInfo",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 4,
},
];
export const rainSttnDetailNodeListExport:CommonTableProps[] = [
{ id: "totalSplyUswtrUtztnQnt",
title: "연간보급수이용량(m³)",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1,
},
{ id: "totalRuseFcltUtztnQnt", title: "연간빗물이용량(m³)",
visible: true,
row: 1,
rowSpan: 2,
colSpan: 1
},
{ id: "useQulity",
title: "이용수질(필요시)",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 4
},
{ id: "ph", title: "PH",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1
},
{
id: "trbt",
title: "탁도",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1
},
{
id: "grssClfg",
title: "총대장균군수",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1
},
{
id: "etc",
title: "기타",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1
},
{ id: "feeHistory",
title: "과태료부과내역",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 3
},
{
id: "vltnDt",
title: "부과일(위반일)",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1
},
{
id: "vltnMttr",
title: "위반사항",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1
},
{
id: "levyAmt",
title: "부과금액(천원)",
visible: true,
row: 2,
rowSpan: 1,
colSpan: 1
},
];
export const rainSttnDetailHeadListExport:CommonTableProps[] = [
{ id: "totalSplyUswtrUtztnQnt",
title: "연간보급수이용량(m³)",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1,
},
{ id: "totalRuseFcltUtztnQnt", title: "연간빗물이용량(m³)",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1
},
{ id: "ph", title: "PH",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1
},
{
id: "trbt",
title: "탁도",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1
},
{
id: "grssClfg",
title: "총대장균군수",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1
},
{
id: "etc",
title: "기타",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1
},
{
id: "vltnDt",
title: "부과일(위반일)",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1
},
{
id: "vltnMttr",
title: "위반사항",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1
},
{
id: "levyAmt",
title: "부과금액(천원)",
visible: true,
row: 1,
rowSpan: 1,
colSpan: 1
},
];
@@ -0,0 +1,217 @@
import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn";
import { fetchType, getFetch } from "@/components/lib/api";
import {
type customRainBdst,
} from "../../fcltReg/rainReg";
import { excelRainSttnParsing } from "./excel";
import {
rainSttHeadListExport,
sttnHeadListType,
rainSttNodeListExport,
rainSttnDetailHeadListExport,
rainSttnDetailNodeListExport,
} from "./headList";
import type { z } from "zod";
import type { CommonTableProps } from "@/app/store/common/type/header";
import type { SelectDataType } from "@common/business_components/ui";
// 테이블 헤드 리스트
const rainSttHeadList = rainSttHeadListExport;
const rainSttNodeList = rainSttNodeListExport;
const rainSttnDetailNodeList = rainSttnDetailNodeListExport;
const rainSttnDetailHeadList = rainSttnDetailHeadListExport;
const rainSttnRes: customRainBdst[] = [];
const rainChkRes : rainChkZodType ={} as rainChkZodType
const visibleHeadList = (falseHeads:CommonTableProps[], orgNodeList:CommonTableProps[])=>{
const visibleHeads = orgNodeList.map((node) => {
const copyNode = {...node}
falseHeads.forEach((head)=>{
if(copyNode.id ===head.id)
copyNode.visible = head.visible
})
return copyNode;
})
return visibleHeads
}
const getColspanReductionMap = (falseHeads:CommonTableProps[], orgList:CommonTableProps[]):Record<string, number> => {
const reduceMap:Record<string, number> = {};
falseHeads.forEach(head => {
const node = orgList.find(n => n.id === head.id);
if (node?.upName) {
reduceMap[node.upName] = (reduceMap[node.upName] || 0) + 1;
if (node.row&& node.row >= 3) {
const upperUpName = orgList.find(n => n.id === node.upName)?.upName;
if (upperUpName) {
reduceMap[upperUpName] = (reduceMap[upperUpName] || 0) + 1;
}
}
}
});
return reduceMap;
};
// colSpan 반영 및 visible 처리
const applyColspanReduction = (
orgList: CommonTableProps[],
reduceMap: Record<string, number>
): CommonTableProps[] => {
return orgList.map(node => {
const newNode: CommonTableProps = { ...node };
const reduceCount = reduceMap[node.id];
if (
newNode.colSpan !== undefined &&
reduceCount !== undefined &&
typeof newNode.colSpan === "number"
) {
newNode.colSpan -= reduceCount;
if (newNode.colSpan <= 0) {
newNode.visible = false;
}
}
return newNode;
});
};
// 일단 헤더가 3개 이상인경우 visible 처리를 위해서 공통함수로 작업
export const controlHeadView = (headList:CommonTableProps[], orgNodeList:CommonTableProps[] ) =>{
const falseHeads = headList.filter((item) => item.visible == false);
const viewHeadList = visibleHeadList(falseHeads, orgNodeList)
const reduceMap= getColspanReductionMap( falseHeads,viewHeadList)
return applyColspanReduction(viewHeadList,reduceMap);
}
export type rainSttnState = {
rainSttn: {
rainSttnRes: customRainBdst[];
rainSttHeadList: CommonTableProps[];
rainSttNodeList: CommonTableProps[];
rainSttnDetailHeadList:CommonTableProps[]
rainSttnDetailNodeList:CommonTableProps[]
rainChkRes:rainChkZodType
excelList: [];
isInit: boolean;
};
};
type rainSttnActions = {
rainSttnInit:(con:string) => void
rainSttnSearch: (page: number, total: string, con: string, sidoCode: SelectDataType[], sggCode: SelectDataType[]) => void;
rainChSttnHead: (
headList: z.infer<typeof sttnHeadListType>,
) => void;
rainSttnChkSearch:(rusePk:string) => void;
};
export type rainSttnType = rainSttnState & rainSttnActions;
export const rainSttnStateExport: rainSttnState = {
rainSttn: {
rainSttHeadList: rainSttHeadList,
rainSttNodeList: rainSttNodeList,
rainSttnDetailHeadList:rainSttnDetailHeadList,
rainSttnDetailNodeList:rainSttnDetailNodeList,
rainSttnRes: rainSttnRes,
rainChkRes:rainChkRes,
excelList: [],
isInit: false,
},
};
export const rainSttnActionsExport: (set: any) => rainSttnActions = (
set: any
) => {
return {
rainSttnInit: async( con:string)=>{
try{
const rainSttnRes = await getFetch(
fetchType.WR,
`/reuseFc/rainyInfoList/1/20/${con}`
);
set((state: rainSttnState) => {
return {
...state,
rainSttn: {
...state.rainSttn,
rainSttnRes: rainSttnRes,
isInit: false,
},
};
});
}catch(e){
console.log(e)
}
},
rainSttnSearch: async (page: number, total: string, con: string,
sidoCode: SelectDataType[],
sggCode: SelectDataType[]) => {
try {
const rainSttnRes = await getFetch(
fetchType.WR,
`/reuseFc/rainyInfoList/${page}/${total}/${con}`
);
if (Number(total) > 9000) {
const rainExcel = excelRainSttnParsing(rainSttnRes, sidoCode, sggCode);
set((state: rainSttnState) => {
return {
...state,
rainSttn: {
...state.rainSttn,
excelList: rainExcel,
},
};
});
} else
set((state: rainSttnState) => {
return {
...state,
rainSttn: {
...state.rainSttn,
rainSttnRes: rainSttnRes,
isInit: false,
},
};
});
} catch (erTxt) {
console.log("error", erTxt);
}
},
rainChSttnHead: async (
headList: z.infer<typeof sttnHeadListType>
) => {
const changeNodeList= controlHeadView(headList,rainSttNodeList)
return set((state: rainSttnState) => ({
rainSttn: {
...state.rainSttn,
rainSttHeadList: headList,
rainSttNodeList: changeNodeList,
},
}));
},
rainSttnChkSearch: async(
rusePk:string
)=>{
const rainChkRes = await getFetch(
fetchType.WR,
`/reuseChk/rainy/${rusePk}`
);
return set((state: rainSttnState) =>({
rainSttn: {
...state.rainSttn,
rainChkRes:rainChkRes
},
}) )
}
};
};
@@ -0,0 +1,40 @@
import type { SelectDataType } from "@common/business_components/ui";
import type { customRswtBdst } from "../../fcltReg/rswtReg";
import { useWrStore } from "@/app/store";
export const excelRSwtSttnParsing = (
data: customRswtBdst[],
sidoCode: SelectDataType[],
sggCode: SelectDataType[]
): string[][] => {
const excelExportData: string[][] = [];
data.forEach((item) => {
excelExportData.push([
sidoCode.find((sido) => sido.val === item.ctpvCd.toString())?.text ?? "",
sggCode.find((sgg) => sgg.val === item.sggCd.toString())?.text ?? "",
item.bdstNm ?? "",
item.daddr ?? "",
String(item.bdstUsgText ?? ""),
String(item.frstArchPrmsnDt ?? ""),
String(item.archArea ?? ""),
String(item.reuseBuilding?.[0]?.rswtrObj.wtrUsqty ?? "0"), //물사용량
String(item.chgBuilding.length > 0 ? "Y" : "N"), //중축・개축・재축여부
String(item.reuseBuilding?.[0]?.lawTrgtYn ?? ""), //법적의무대상여부
String(item.reuseBuilding?.[0]?.rswtrObj.oblgTrgtWtrUsqty ?? ""), //의무대상물사용량
String(item.reuseBuilding?.[0]?.instlCmptnDt ?? ""), //설치완료일시
String(item.reuseBuilding?.[0]?.instlCst ?? ""), //설치비용
item.reuseBuilding?.[0]?.rswtrObj?.orgwtKndCd ?? "", //원수종류
String(item.reuseBuilding?.[0]?.rswtrObj.filtrTrtmfctCpct ?? ""), //처리시설용량
String(item.reuseBuilding?.[0]?.rswtrObj?.filtrTrtmfctProcs ?? ""), //주요처리공정
String(item.reuseBuilding?.[0]?.rswtrObj?.filtrTrtmfctUsgCd ?? ""), //이용용도
String(item.reuseBuilding?.[0]?.instlCstSprtYn ?? ""), //설치지원비용여부
String(item.reuseBuilding?.[0]?.instlCstSprtAmt ?? ""), //설치지원비용
String(item.reuseBuilding?.[0]?.grntchBdstCertYn ?? ""),
String(item.reuseBuilding?.[0]?.grntchBdstCertYr ?? ""),
String(item.reuseBuilding?.[0]?.grntchBdstCertNo ?? ""),
String(item.reuseBuilding?.[0]?.grntchBdstCertGrd ?? "")
]);
});
return excelExportData;
};

Some files were not shown because too many files have changed in this diff Show More