Compare commits
71
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c72fa450bc | ||
|
|
400d6cf732 | ||
|
|
39e2734a49 | ||
|
|
d92d4d3949 | ||
|
|
b93efa5503 | ||
|
|
0b8559891a | ||
|
|
ffa1781005 | ||
|
|
b47c0dff2b | ||
|
|
83f5d878e7 | ||
|
|
e815b9662f | ||
|
|
2e6cbad49c | ||
|
|
ede5ef6a21 | ||
|
|
621d222799 | ||
|
|
01df37d0b3 | ||
|
|
072a5337a3 | ||
|
|
2a0f5dce25 | ||
|
|
26f2c60f4c | ||
|
|
28d0e21815 | ||
|
|
49c475709f | ||
|
|
31b8152d37 | ||
|
|
b9f5eb50e5 | ||
|
|
c7772a0a23 | ||
|
|
392ccefb16 | ||
|
|
aeaf507c47 | ||
|
|
2f4cfa0d78 | ||
|
|
ebfc520d67 | ||
|
|
4df286b086 | ||
|
|
262cf21546 | ||
|
|
056b7bae3c | ||
|
|
428f617802 | ||
|
|
e797bdbdf7 | ||
|
|
cb11ec839e | ||
|
|
772dd1c1aa | ||
|
|
579e599eb1 | ||
|
|
3cc8fcb2eb | ||
|
|
f644bd6b7e | ||
|
|
f685884ed7 | ||
|
|
a2af60d52e | ||
|
|
395590bbe4 | ||
|
|
6c0d65a69a | ||
|
|
a6b34780ae | ||
|
|
a83ea455fb | ||
|
|
ab63cbe992 | ||
|
|
b2a6285475 | ||
|
|
6808430c9a | ||
|
|
dad8b9925e | ||
|
|
07c7947da1 | ||
|
|
35e1203168 | ||
|
|
bec3132417 | ||
|
|
e7a46ac3a2 | ||
|
|
6fb39d6384 | ||
|
|
0ad7d6a2c4 | ||
|
|
8fbecc41a5 | ||
|
|
711adc2e17 | ||
|
|
4920b4c1a2 | ||
|
|
c4f2af0bfe | ||
|
|
190adb6bc1 | ||
|
|
59bccfe1d6 | ||
|
|
84ff24c5b5 | ||
|
|
e1b48ab7c8 | ||
|
|
4c3be448f0 | ||
|
|
8ede32f4c4 | ||
|
|
2862fdc9fd | ||
|
|
a446739432 | ||
|
|
ea125605d1 | ||
|
|
8353800dac | ||
|
|
6492ad5500 | ||
|
|
523925459c | ||
|
|
d5c967e9ad | ||
|
|
804688b3c1 | ||
|
|
8435096e5a |
@@ -185,15 +185,6 @@ function PostingDialog({ postingType, postingTargets }: PostingDialogProps) {
|
||||
...prev,
|
||||
[siteId]: value,
|
||||
}));
|
||||
|
||||
// 상시 선택 시 게시 기간 미설정
|
||||
if (value === "99") {
|
||||
handleUpdateFields(siteId)({
|
||||
pstgPrdSeCd: value,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setRememberPeriodDate((prev) => ({
|
||||
...prev,
|
||||
[siteId]: { from, to },
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
Skeleton,
|
||||
} from "@common/components";
|
||||
import { AttachmentApi } from "@/entities/attachment";
|
||||
import { PostApi, PostPageGuard, type PostParams } from "@/entities/post";
|
||||
import { PostApi, type PostParams } from "@/entities/post";
|
||||
import { useAlertStore, useMenuStore, useUserStore } from "@/shared/lib";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import dayjs from "dayjs";
|
||||
@@ -103,147 +103,143 @@ function FaqPage({ bbsId }: { bbsId: string }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<PostPageGuard bbsId={bbsId}>
|
||||
<div className="card card-border !mt-6">
|
||||
<div className="card card-border">
|
||||
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
|
||||
<Label className="mr-2 text-label">검색</Label>
|
||||
<Select
|
||||
value={postParams.keywordType}
|
||||
onValueChange={(keywordType) => {
|
||||
setPostParams({ ...postParams, keywordType });
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-[3.2rem] w-[10rem]">
|
||||
<SelectValue placeholder="선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="title">제목</SelectItem>
|
||||
<SelectItem value="all">제목+내용</SelectItem>
|
||||
<SelectItem value="writer">작성자</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Input
|
||||
value={postParams.keyword}
|
||||
onChange={(e) =>
|
||||
setPostParams({ ...postParams, keyword: e.target.value })
|
||||
}
|
||||
className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]"
|
||||
/>
|
||||
<Button className="h-[3.2rem]" type="submit">
|
||||
조회
|
||||
</Button>
|
||||
</form>
|
||||
<div className="card card-border !mt-6">
|
||||
<div className="card card-border">
|
||||
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
|
||||
<Label className="mr-2 text-label">검색</Label>
|
||||
<Select
|
||||
value={postParams.keywordType}
|
||||
onValueChange={(keywordType) => {
|
||||
setPostParams({ ...postParams, keywordType });
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-[3.2rem] w-[10rem]">
|
||||
<SelectValue placeholder="선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="title">제목</SelectItem>
|
||||
<SelectItem value="all">제목+내용</SelectItem>
|
||||
<SelectItem value="writer">작성자</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Input
|
||||
value={postParams.keyword}
|
||||
onChange={(e) =>
|
||||
setPostParams({ ...postParams, keyword: e.target.value })
|
||||
}
|
||||
className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]"
|
||||
/>
|
||||
<Button className="h-[3.2rem]" type="submit">
|
||||
조회
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
<div className="card card-border">
|
||||
<div className="card-header">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<h3 className="text-2xl font-medium text-label">콘텐츠 목록</h3>
|
||||
<div className="flex gap-2">
|
||||
{pageMenuAuthority?.regAuthrtYn === "Y" && (
|
||||
<Button onClick={() => router.push(`${pathname}/register`)}>
|
||||
등록
|
||||
</Button>
|
||||
)}
|
||||
{pageMenuAuthority?.delAuthrtYn === "Y" && (
|
||||
<Button
|
||||
color="red"
|
||||
onClick={onSelectedPostDelete}
|
||||
disabled={!selectedPostNumbers.length}
|
||||
>
|
||||
선택삭제
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card card-border">
|
||||
<div className="card-header">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<h3 className="text-2xl font-medium text-label">콘텐츠 목록</h3>
|
||||
<div className="flex gap-2">
|
||||
{pageMenuAuthority?.regAuthrtYn === "Y" && (
|
||||
<Button onClick={() => router.push(`${pathname}/register`)}>
|
||||
등록
|
||||
</Button>
|
||||
)}
|
||||
{pageMenuAuthority?.delAuthrtYn === "Y" && (
|
||||
<Button
|
||||
color="red"
|
||||
onClick={onSelectedPostDelete}
|
||||
disabled={!selectedPostNumbers.length}
|
||||
<div className="card !m-[1.2rem] h-full overflow-auto !p-0">
|
||||
<div className="mb-4 flex items-center gap-2 rounded-sm border border-border bg-background p-4">
|
||||
<Checkbox
|
||||
id="all-select"
|
||||
checked={selectedPostNumbers.length === postList?.content.length}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onCheckedChange={handleAllCheckboxChange}
|
||||
/>
|
||||
<Label htmlFor="all-select" className="text-2xl">
|
||||
전체선택
|
||||
</Label>
|
||||
</div>
|
||||
{isFetched ? (
|
||||
<Accordion
|
||||
type="multiple"
|
||||
className="secondary flex flex-col gap-4"
|
||||
>
|
||||
{postList?.content.map((item) => (
|
||||
<div key={item.pstNo} className="flex items-start gap-2">
|
||||
<Checkbox
|
||||
id={item.pstNo.toString()}
|
||||
checked={selectedPostNumbers.includes(item.pstNo)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onCheckedChange={(checked) =>
|
||||
handleCheckboxChange(item.pstNo, checked)
|
||||
}
|
||||
className="mx-2 my-6"
|
||||
/>
|
||||
<AccordionItem
|
||||
value={item.pstNo.toString()}
|
||||
className="w-full"
|
||||
>
|
||||
선택삭제
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !m-[1.2rem] h-full overflow-auto !p-0">
|
||||
<div className="mb-4 flex items-center gap-2 rounded-sm border border-border bg-background p-4">
|
||||
<Checkbox
|
||||
id="all-select"
|
||||
checked={
|
||||
selectedPostNumbers.length === postList?.content.length
|
||||
}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onCheckedChange={handleAllCheckboxChange}
|
||||
/>
|
||||
<Label htmlFor="all-select" className="text-2xl">
|
||||
전체선택
|
||||
</Label>
|
||||
</div>
|
||||
{isFetched ? (
|
||||
<Accordion
|
||||
type="multiple"
|
||||
className="secondary flex flex-col gap-4"
|
||||
>
|
||||
{postList?.content.map((item) => (
|
||||
<div key={item.pstNo} className="flex items-start gap-2">
|
||||
<Checkbox
|
||||
id={item.pstNo.toString()}
|
||||
checked={selectedPostNumbers.includes(item.pstNo)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onCheckedChange={(checked) =>
|
||||
handleCheckboxChange(item.pstNo, checked)
|
||||
}
|
||||
className="mx-2 my-6"
|
||||
/>
|
||||
<AccordionItem
|
||||
value={item.pstNo.toString()}
|
||||
className="w-full"
|
||||
>
|
||||
<AccordionTrigger>
|
||||
<div className="flex flex-1 items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-primary">Q</span>
|
||||
<span>{item.pstTtl}</span>
|
||||
</div>
|
||||
<span className="px-4 text-[1.2rem] font-normal text-label">
|
||||
등록일: {dayjs(item.regDt).format("YYYY-MM-DD")}
|
||||
</span>
|
||||
<AccordionTrigger>
|
||||
<div className="flex flex-1 items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-primary">Q</span>
|
||||
<span>{item.pstTtl}</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className="flex items-start gap-4">
|
||||
<span className="text-[1.4rem] font-bold text-label">
|
||||
A
|
||||
</span>
|
||||
<div className="flex-1">
|
||||
<pre className="whitespace-pre-wrap font-noto text-[1.4rem] tracking-tighter text-foreground">
|
||||
{item.pstCn}
|
||||
</pre>
|
||||
<Attachment atflCd={item.atflCd} />
|
||||
</div>
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button
|
||||
size="icon"
|
||||
color="white"
|
||||
onClick={() =>
|
||||
router.push(`${pathname}/${item.pstNo}`)
|
||||
}
|
||||
>
|
||||
<i className="diveicon di-pencil" />
|
||||
</Button>
|
||||
<Button
|
||||
size="icon"
|
||||
color="white"
|
||||
onClick={() => handleDeletePost(item.pstNo)}
|
||||
>
|
||||
<i className="diveicon di-trash" />
|
||||
</Button>
|
||||
</div>
|
||||
<span className="px-4 text-[1.2rem] font-normal text-label">
|
||||
등록일: {dayjs(item.regDt).format("YYYY-MM-DD")}
|
||||
</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className="flex items-start gap-4">
|
||||
<span className="text-[1.4rem] font-bold text-label">
|
||||
A
|
||||
</span>
|
||||
<div className="flex-1">
|
||||
<pre className="whitespace-pre-wrap font-noto text-[1.4rem] tracking-tighter text-foreground">
|
||||
{item.pstCn}
|
||||
</pre>
|
||||
<Attachment atflCd={item.atflCd} />
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</div>
|
||||
))}
|
||||
</Accordion>
|
||||
) : (
|
||||
<Skeleton className="h-[36rem] w-full" />
|
||||
)}
|
||||
</div>
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button
|
||||
size="icon"
|
||||
color="white"
|
||||
onClick={() =>
|
||||
router.push(`${pathname}/${item.pstNo}`)
|
||||
}
|
||||
>
|
||||
<i className="diveicon di-pencil" />
|
||||
</Button>
|
||||
<Button
|
||||
size="icon"
|
||||
color="white"
|
||||
onClick={() => handleDeletePost(item.pstNo)}
|
||||
>
|
||||
<i className="diveicon di-trash" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</div>
|
||||
))}
|
||||
</Accordion>
|
||||
) : (
|
||||
<Skeleton className="h-[36rem] w-full" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</PostPageGuard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+8
-27
@@ -1,12 +1,5 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import {
|
||||
CLAIM_NAME,
|
||||
AUTH_USER_ID,
|
||||
PORT,
|
||||
PROXY_HOST,
|
||||
SERVER_API_URL,
|
||||
SITE_ID,
|
||||
} from "./src/shared/config";
|
||||
import { CLAIM_NAME, AUTH_USER_ID } from "./src/shared/config";
|
||||
|
||||
const serverApiUrl =
|
||||
process.env.NEXT_PUBLIC_SERVER_API_URL ?? "http://localhost:3000";
|
||||
@@ -14,23 +7,17 @@ const serverApiUrl =
|
||||
export function middleware(req: NextRequest) {
|
||||
const pathname = req.nextUrl.pathname;
|
||||
const searchParams = req.nextUrl.searchParams;
|
||||
|
||||
const logMessages: string[] = [
|
||||
`[Middleware Request] ${new Date().toISOString()}`,
|
||||
`[Environment]\n Mode: ${process.env.NODE_ENV}\n Port: ${PORT}\n Proxy Host: ${PROXY_HOST}\n Server API URL: ${SERVER_API_URL}\n Site ID: ${SITE_ID}`,
|
||||
`[Request]\n Original Pathname: ${pathname}`,
|
||||
];
|
||||
|
||||
|
||||
if (pathname.startsWith("/server")) {
|
||||
const queryParams = searchParams.toString();
|
||||
|
||||
const decodedParams = Array.from(searchParams.entries())
|
||||
.map(([key, value]) => `${key}=${decodeURIComponent(value)}`)
|
||||
.join("&");
|
||||
|
||||
const newUrl = `${serverApiUrl}${pathname.replace("/server", "")}${
|
||||
queryParams ? `?${queryParams}` : ""
|
||||
decodedParams ? `?${decodedParams}` : ""
|
||||
}`;
|
||||
|
||||
logMessages.push(` Rewritten URL: ${newUrl}`);
|
||||
logMessages.push("\n--------------------------------\n");
|
||||
console.log(logMessages.join("\n"));
|
||||
|
||||
return NextResponse.rewrite(new URL(newUrl));
|
||||
}
|
||||
|
||||
@@ -43,10 +30,6 @@ export function middleware(req: NextRequest) {
|
||||
if (token) requestHeaders.set(CLAIM_NAME, token);
|
||||
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
|
||||
|
||||
logMessages.push(` Rewritten URL: ${newUrl}`);
|
||||
logMessages.push("\n--------------------------------\n");
|
||||
console.log(logMessages.join("\n"));
|
||||
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders,
|
||||
});
|
||||
@@ -56,8 +39,6 @@ export function middleware(req: NextRequest) {
|
||||
return NextResponse.redirect(new URL("/dashboard", req.url));
|
||||
}
|
||||
|
||||
logMessages.push("\n--------------------------------\n");
|
||||
console.log(logMessages.join("\n"));
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
|
||||
@@ -67,22 +67,11 @@ export const contentsDetailSchema = z.object({
|
||||
useYn: z.string(),
|
||||
});
|
||||
|
||||
export const contentsFormSchema = contentsDetailSchema
|
||||
.omit({
|
||||
contsVer: true,
|
||||
aprvDt: true,
|
||||
autzr: true,
|
||||
})
|
||||
.extend({
|
||||
contsSn: z.number().optional(),
|
||||
aprvCd: z
|
||||
.enum([
|
||||
CONTENTS_APPROVE_STATUS.DRAFT,
|
||||
CONTENTS_APPROVE_STATUS.REQUESTED,
|
||||
CONTENTS_APPROVE_STATUS.APPROVED,
|
||||
])
|
||||
.optional(),
|
||||
});
|
||||
export const contentsFormSchema = contentsDetailSchema.omit({
|
||||
contsVer: true,
|
||||
aprvDt: true,
|
||||
autzr: true,
|
||||
});
|
||||
|
||||
export type Contents = z.infer<typeof contentsSchema>;
|
||||
export type ContentsDetail = z.infer<typeof contentsDetailSchema>;
|
||||
|
||||
@@ -6,7 +6,6 @@ import type {
|
||||
MenuItem,
|
||||
MenuFormData,
|
||||
MenuTemporarilyStoredData,
|
||||
SiteMapFormData,
|
||||
} from "../model/menu-interface";
|
||||
|
||||
export class MenuApiService implements MenuService {
|
||||
@@ -66,14 +65,6 @@ export class MenuApiService implements MenuService {
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async publishSiteMap(data: SiteMapFormData["siteMap"]): Promise<void> {
|
||||
const response = await client.post<void>(
|
||||
`${ENDPOINT.CMS_SERVICE.MENUS}/sitemap/publish`,
|
||||
data,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
export const MenuApi = new MenuApiService();
|
||||
|
||||
@@ -2,11 +2,8 @@ export { MenuApi } from "./api/menu-service";
|
||||
export {
|
||||
MENU_TYPE,
|
||||
menuFormSchema,
|
||||
siteMapFormSchema,
|
||||
type MenuType,
|
||||
type MenuItem,
|
||||
type MenuFormData,
|
||||
type SiteMapFormData,
|
||||
type SiteMapPayloadData,
|
||||
} from "./model/menu-interface";
|
||||
export { MenuWrapper } from "./lib/menu-wrapper";
|
||||
|
||||
@@ -72,19 +72,8 @@ export const menuFormSchema = z.object({
|
||||
menuPicDsgnYmd: z.string().nullish(),
|
||||
});
|
||||
|
||||
export const siteMapPayloadSchema = z.object({
|
||||
menuCd: z.number(),
|
||||
menuSubKornNm: z.string(),
|
||||
otptYn: z.string(),
|
||||
});
|
||||
|
||||
export const siteMapFormSchema = z.object({
|
||||
siteMap: z.array(siteMapPayloadSchema),
|
||||
});
|
||||
|
||||
export type MenuFormData = z.infer<typeof menuFormSchema>;
|
||||
export type SiteMapFormData = z.infer<typeof siteMapFormSchema>;
|
||||
export type SiteMapPayloadData = z.infer<typeof siteMapPayloadSchema>;
|
||||
|
||||
export type Menu = Omit<MenuFormData, "iconNm"> & {
|
||||
menuCd: number;
|
||||
iconName?: string;
|
||||
@@ -103,5 +92,4 @@ export interface MenuService {
|
||||
getMenuTemporarilyStoredData: (
|
||||
menuCd: number,
|
||||
) => Promise<MenuTemporarilyStoredData[]>;
|
||||
publishSiteMap: (data: SiteMapFormData["siteMap"]) => Promise<void>;
|
||||
}
|
||||
|
||||
@@ -194,15 +194,6 @@ function PostingDialog({
|
||||
...prev,
|
||||
[siteId]: value,
|
||||
}));
|
||||
|
||||
// 상시 선택 시 게시 기간 미설정
|
||||
if (value === "99") {
|
||||
handleUpdateFields(siteId)({
|
||||
pstgPrdSeCd: value,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setRememberPeriodDate((prev) => ({
|
||||
...prev,
|
||||
[siteId]: { from, to },
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
export { TreeMenuApi } from "./api/tree-menu-service";
|
||||
export type { TreeMenu, TreeNode } from "./model/tree-menu-interface";
|
||||
@@ -4,7 +4,6 @@ export {
|
||||
userSaveSchema,
|
||||
userPasswordUpdateSchema,
|
||||
userUpdateSchema,
|
||||
type UserStateCode,
|
||||
type UserSearchParams,
|
||||
type UserListResponse,
|
||||
type UserSaveData,
|
||||
|
||||
@@ -9,8 +9,7 @@ export const USER_STATE_CODE = {
|
||||
삭제: "09",
|
||||
} as const;
|
||||
|
||||
export type UserStateCode =
|
||||
(typeof USER_STATE_CODE)[keyof typeof USER_STATE_CODE];
|
||||
type UserStateCode = (typeof USER_STATE_CODE)[keyof typeof USER_STATE_CODE];
|
||||
|
||||
// 사용자 검색 파라미터
|
||||
export interface UserSearchParams extends PageableParams {
|
||||
|
||||
@@ -23,7 +23,6 @@ import {
|
||||
import { AttachmentApi } from "@/entities/attachment";
|
||||
import {
|
||||
PostApi,
|
||||
PostPageGuard,
|
||||
deleteReasonMessages,
|
||||
type PostParams,
|
||||
} from "@/entities/post";
|
||||
@@ -121,147 +120,143 @@ function FaqPage({ bbsId }: { bbsId: string }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<PostPageGuard bbsId={bbsId}>
|
||||
<div className="card card-border !mt-6">
|
||||
<div className="card card-border">
|
||||
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
|
||||
<Label className="mr-2 text-label">검색</Label>
|
||||
<Select
|
||||
value={postParams.keywordType}
|
||||
onValueChange={(keywordType) => {
|
||||
setPostParams({ ...postParams, keywordType });
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-[3.2rem] w-[10rem]">
|
||||
<SelectValue placeholder="선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="title">제목</SelectItem>
|
||||
<SelectItem value="all">제목+내용</SelectItem>
|
||||
<SelectItem value="writer">작성자</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Input
|
||||
value={postParams.keyword}
|
||||
onChange={(e) =>
|
||||
setPostParams({ ...postParams, keyword: e.target.value })
|
||||
}
|
||||
className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]"
|
||||
/>
|
||||
<Button className="h-[3.2rem]" type="submit">
|
||||
조회
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
<div className="card card-border">
|
||||
<div className="card-header">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<h3 className="text-2xl font-medium text-label">콘텐츠 목록</h3>
|
||||
<div className="flex gap-2">
|
||||
<AuthorityButton
|
||||
authority="regAuthrtYn"
|
||||
onClick={() => router.push(`${pathname}/register`)}
|
||||
>
|
||||
등록
|
||||
</AuthorityButton>
|
||||
<AuthorityButton
|
||||
authority="delAuthrtYn"
|
||||
color="red"
|
||||
onClick={onSelectedPostDelete}
|
||||
disabled={!selectedPostNumbers.length}
|
||||
>
|
||||
선택삭제
|
||||
</AuthorityButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !m-[1.2rem] h-full overflow-auto !p-0">
|
||||
<div className="mb-4 flex items-center gap-2 rounded-sm border border-border bg-background p-4">
|
||||
<Checkbox
|
||||
id="all-select"
|
||||
checked={
|
||||
selectedPostNumbers.length === postList?.content.length
|
||||
}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onCheckedChange={handleAllCheckboxChange}
|
||||
/>
|
||||
<Label htmlFor="all-select" className="text-2xl">
|
||||
전체선택
|
||||
</Label>
|
||||
</div>
|
||||
{isFetched ? (
|
||||
<Accordion
|
||||
type="multiple"
|
||||
className="secondary flex flex-col gap-4"
|
||||
<div className="card card-border !mt-6">
|
||||
<div className="card card-border">
|
||||
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
|
||||
<Label className="mr-2 text-label">검색</Label>
|
||||
<Select
|
||||
value={postParams.keywordType}
|
||||
onValueChange={(keywordType) => {
|
||||
setPostParams({ ...postParams, keywordType });
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-[3.2rem] w-[10rem]">
|
||||
<SelectValue placeholder="선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="title">제목</SelectItem>
|
||||
<SelectItem value="all">제목+내용</SelectItem>
|
||||
<SelectItem value="writer">작성자</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Input
|
||||
value={postParams.keyword}
|
||||
onChange={(e) =>
|
||||
setPostParams({ ...postParams, keyword: e.target.value })
|
||||
}
|
||||
className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]"
|
||||
/>
|
||||
<Button className="h-[3.2rem]" type="submit">
|
||||
조회
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
<div className="card card-border">
|
||||
<div className="card-header">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<h3 className="text-2xl font-medium text-label">콘텐츠 목록</h3>
|
||||
<div className="flex gap-2">
|
||||
<AuthorityButton
|
||||
authority="regAuthrtYn"
|
||||
onClick={() => router.push(`${pathname}/register`)}
|
||||
>
|
||||
{postList?.content.map((item) => (
|
||||
<div key={item.pstNo} className="flex items-start gap-2">
|
||||
<Checkbox
|
||||
id={item.pstNo.toString()}
|
||||
checked={selectedPostNumbers.includes(item.pstNo)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onCheckedChange={(checked) =>
|
||||
handleCheckboxChange(item.pstNo, checked)
|
||||
}
|
||||
className="mx-2 my-6"
|
||||
/>
|
||||
<AccordionItem
|
||||
value={item.pstNo.toString()}
|
||||
className="w-full"
|
||||
>
|
||||
<AccordionTrigger>
|
||||
<div className="flex flex-1 items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-primary">Q</span>
|
||||
<span>{item.pstTtl}</span>
|
||||
</div>
|
||||
<span className="px-4 text-[1.2rem] font-normal text-label">
|
||||
등록일: {dayjs(item.regDt).format("YYYY-MM-DD")}
|
||||
</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className="flex items-start gap-4">
|
||||
<span className="text-[1.4rem] font-bold text-label">
|
||||
A
|
||||
</span>
|
||||
<div className="flex-1">
|
||||
<pre className="whitespace-pre-wrap font-noto text-[1.4rem] tracking-tighter text-foreground">
|
||||
{item.pstCn}
|
||||
</pre>
|
||||
<Attachment atflCd={item.atflCd} />
|
||||
</div>
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button
|
||||
size="icon"
|
||||
color="white"
|
||||
onClick={() =>
|
||||
router.push(`${pathname}/${item.pstNo}`)
|
||||
}
|
||||
>
|
||||
<i className="diveicon di-pencil" />
|
||||
</Button>
|
||||
<Button
|
||||
size="icon"
|
||||
color="white"
|
||||
onClick={() => handleDeletePost(item.pstNo)}
|
||||
>
|
||||
<i className="diveicon di-trash" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</div>
|
||||
))}
|
||||
</Accordion>
|
||||
) : (
|
||||
<Skeleton className="h-[36rem] w-full" />
|
||||
)}
|
||||
등록
|
||||
</AuthorityButton>
|
||||
<AuthorityButton
|
||||
authority="delAuthrtYn"
|
||||
color="red"
|
||||
onClick={onSelectedPostDelete}
|
||||
disabled={!selectedPostNumbers.length}
|
||||
>
|
||||
선택삭제
|
||||
</AuthorityButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !m-[1.2rem] h-full overflow-auto !p-0">
|
||||
<div className="mb-4 flex items-center gap-2 rounded-sm border border-border bg-background p-4">
|
||||
<Checkbox
|
||||
id="all-select"
|
||||
checked={selectedPostNumbers.length === postList?.content.length}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onCheckedChange={handleAllCheckboxChange}
|
||||
/>
|
||||
<Label htmlFor="all-select" className="text-2xl">
|
||||
전체선택
|
||||
</Label>
|
||||
</div>
|
||||
{isFetched ? (
|
||||
<Accordion
|
||||
type="multiple"
|
||||
className="secondary flex flex-col gap-4"
|
||||
>
|
||||
{postList?.content.map((item) => (
|
||||
<div key={item.pstNo} className="flex items-start gap-2">
|
||||
<Checkbox
|
||||
id={item.pstNo.toString()}
|
||||
checked={selectedPostNumbers.includes(item.pstNo)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onCheckedChange={(checked) =>
|
||||
handleCheckboxChange(item.pstNo, checked)
|
||||
}
|
||||
className="mx-2 my-6"
|
||||
/>
|
||||
<AccordionItem
|
||||
value={item.pstNo.toString()}
|
||||
className="w-full"
|
||||
>
|
||||
<AccordionTrigger>
|
||||
<div className="flex flex-1 items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-primary">Q</span>
|
||||
<span>{item.pstTtl}</span>
|
||||
</div>
|
||||
<span className="px-4 text-[1.2rem] font-normal text-label">
|
||||
등록일: {dayjs(item.regDt).format("YYYY-MM-DD")}
|
||||
</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className="flex items-start gap-4">
|
||||
<span className="text-[1.4rem] font-bold text-label">
|
||||
A
|
||||
</span>
|
||||
<div className="flex-1">
|
||||
<pre className="whitespace-pre-wrap font-noto text-[1.4rem] tracking-tighter text-foreground">
|
||||
{item.pstCn}
|
||||
</pre>
|
||||
<Attachment atflCd={item.atflCd} />
|
||||
</div>
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button
|
||||
size="icon"
|
||||
color="white"
|
||||
onClick={() =>
|
||||
router.push(`${pathname}/${item.pstNo}`)
|
||||
}
|
||||
>
|
||||
<i className="diveicon di-pencil" />
|
||||
</Button>
|
||||
<Button
|
||||
size="icon"
|
||||
color="white"
|
||||
onClick={() => handleDeletePost(item.pstNo)}
|
||||
>
|
||||
<i className="diveicon di-trash" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</div>
|
||||
))}
|
||||
</Accordion>
|
||||
) : (
|
||||
<Skeleton className="h-[36rem] w-full" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</PostPageGuard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ function AdminPage() {
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
const { confirm } = useConfirm();
|
||||
|
||||
const [keywordType, setKeywordType] = useState("userId");
|
||||
const [keywordType, setKeywordType] = useState("");
|
||||
const [keyword, setKeyword] = useState("");
|
||||
const [grpId, setGrpId] = useState("");
|
||||
const [searchParams, setSearchParams] = useState<UserSearchParams>({
|
||||
|
||||
@@ -15,7 +15,8 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@common/components";
|
||||
import { ApiLogApi, type ApiLogParams } from "@/entities/apilog";
|
||||
import { ApiLogApi } from "@/entities/apilog";
|
||||
import { type ApiLogParams } from "@/entities/apilog/model/apilog-interface";
|
||||
import { useDataTable } from "@/shared/lib";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { columns } from "@/pages/apilog/model/table-columns";
|
||||
|
||||
@@ -35,14 +35,9 @@ export const columns: ColumnDef<Post>[] = [
|
||||
accessorKey: "pstgPrdSeNm",
|
||||
header: "게시기간",
|
||||
cell: ({ row }) => {
|
||||
const pstgPrdSeCd = row.original.pstgPrdSeCd;
|
||||
const pstgPrdSeNm = row.original.pstgPrdSeNm;
|
||||
const pstgBgngDt = row.original.pstgBgngDt;
|
||||
const pstgEndDt = row.original.pstgEndDt;
|
||||
|
||||
if (pstgPrdSeCd === "99") {
|
||||
return pstgPrdSeNm;
|
||||
}
|
||||
return `${pstgPrdSeNm} (${dayjs(pstgBgngDt).format("YYYY-MM-DD")} ~ ${dayjs(pstgEndDt).format("YYYY-MM-DD")})`;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -34,7 +34,7 @@ function CreatePage() {
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">콘텐츠 등록</h3>
|
||||
</div>
|
||||
<ContentsForm isEditable form={form} handleSave={createContents} />
|
||||
<ContentsForm form={form} handleSave={createContents} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
@@ -25,7 +24,6 @@ import { useAlertStore, useMutationWrapper } from "@/shared/lib";
|
||||
import { ContentsForm } from "./contents-form";
|
||||
|
||||
function ModifyPage({ sequential }: { sequential: string }) {
|
||||
const router = useRouter();
|
||||
const { confirm } = useConfirm();
|
||||
const queryClient = useQueryClient();
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
@@ -53,11 +51,9 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
mutationFn: (data: ContentsFormData) => ContentsApi.createContents(data),
|
||||
onSuccess: () => {
|
||||
setContsVer(0);
|
||||
alert("수정되었습니다.", () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn],
|
||||
});
|
||||
router.back();
|
||||
alert("수정되었습니다.");
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn],
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -66,7 +62,7 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
mutationFn: (data: ContentsFormData) =>
|
||||
ContentsApi.updateContents(contsSn, contsVer, data),
|
||||
onSuccess: () => {
|
||||
alert("수정되었습니다.", router.back);
|
||||
alert("수정되었습니다.");
|
||||
},
|
||||
});
|
||||
|
||||
@@ -74,11 +70,9 @@ function ModifyPage({ sequential }: { sequential: string }) {
|
||||
mutationFn: () => ContentsApi.deleteContents(contsSn, contsVer),
|
||||
onSuccess: () => {
|
||||
setContsVer(0);
|
||||
alert("삭제되었습니다.", () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn],
|
||||
});
|
||||
router.back();
|
||||
alert("삭제되었습니다.");
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -39,7 +39,8 @@ function FilePage() {
|
||||
mutationFn: (atflId: string) =>
|
||||
AttachmentApi.deleteAttachmentByAtflId(atflId),
|
||||
onSuccess: () => {
|
||||
alert("삭제되었습니다.", query.refetch);
|
||||
query.refetch();
|
||||
alert("삭제되었습니다.");
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
keepPreviousData,
|
||||
useQuery,
|
||||
@@ -22,7 +22,6 @@ import {
|
||||
DialogFooter,
|
||||
Input,
|
||||
Checkbox,
|
||||
Label,
|
||||
} from "@common/components";
|
||||
import {
|
||||
UserApi,
|
||||
@@ -42,8 +41,7 @@ function AddUserDialog({ groupId }: AdditionalUserDialogProps) {
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [userName, setUserName] = useState("");
|
||||
const [searchParam, setSearchParam] = useState<UserSearchParams>({
|
||||
const [userSearchQuery, setUserSearchQuery] = useState<UserSearchParams>({
|
||||
userName: "",
|
||||
});
|
||||
const [pagination, setPagination] = useState<PaginationState>({
|
||||
@@ -55,10 +53,10 @@ function AddUserDialog({ groupId }: AdditionalUserDialogProps) {
|
||||
);
|
||||
|
||||
const query = useQuery({
|
||||
queryKey: [ENDPOINT.USER_SERVICE.USERS, searchParam, pagination],
|
||||
queryKey: [ENDPOINT.USER_SERVICE.USERS, userSearchQuery, pagination],
|
||||
queryFn: () =>
|
||||
UserApi.findPageUser({
|
||||
...searchParam,
|
||||
...userSearchQuery,
|
||||
page: pagination.pageIndex,
|
||||
size: pagination.pageSize,
|
||||
}),
|
||||
@@ -120,9 +118,6 @@ function AddUserDialog({ groupId }: AdditionalUserDialogProps) {
|
||||
onRowSelectionChange: setUserRowSelection,
|
||||
getRowId: (row) => row.userUnqId,
|
||||
},
|
||||
dataTableOptions: {
|
||||
viewPagination: true,
|
||||
},
|
||||
});
|
||||
|
||||
const handleAddUsers = async () => {
|
||||
@@ -149,30 +144,10 @@ function AddUserDialog({ groupId }: AdditionalUserDialogProps) {
|
||||
}
|
||||
};
|
||||
|
||||
const handleSearch = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setPagination({
|
||||
...pagination,
|
||||
pageIndex: 0,
|
||||
});
|
||||
setSearchParam({ userName });
|
||||
const handleSearch = () => {
|
||||
setPagination({ pageIndex: 0, pageSize: 10 });
|
||||
};
|
||||
|
||||
const resetSearch = () => {
|
||||
setPagination({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
setUserName("");
|
||||
setSearchParam({ userName: "" });
|
||||
setUserRowSelection({});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (open) resetSearch();
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
@@ -182,31 +157,20 @@ function AddUserDialog({ groupId }: AdditionalUserDialogProps) {
|
||||
<DialogHeader>
|
||||
<DialogTitle>사용자 추가</DialogTitle>
|
||||
</DialogHeader>
|
||||
<form onSubmit={handleSearch} className="mb-4 flex items-end gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<Label htmlFor="userName" className="mr-2 text-label">
|
||||
사용자 이름
|
||||
</Label>
|
||||
<Input
|
||||
id="userName"
|
||||
className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]"
|
||||
value={userName}
|
||||
onChange={(e) => setUserName(e.target.value)}
|
||||
placeholder="사용자 이름으로 검색"
|
||||
/>
|
||||
</div>
|
||||
<Button className="h-[3.2rem]" type="submit">
|
||||
조회
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
color="white"
|
||||
className="h-[3.2rem]"
|
||||
onClick={resetSearch}
|
||||
>
|
||||
초기화
|
||||
</Button>
|
||||
</form>
|
||||
<div className="mb-4 flex items-end gap-2">
|
||||
<Input
|
||||
value={userSearchQuery.userName}
|
||||
onChange={(e) =>
|
||||
setUserSearchQuery({
|
||||
...userSearchQuery,
|
||||
userName: e.target.value,
|
||||
})
|
||||
}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="사용자 이름으로 검색"
|
||||
/>
|
||||
<Button onClick={handleSearch}>검색</Button>
|
||||
</div>
|
||||
{tableComponent}
|
||||
<DialogFooter>
|
||||
<Button color="white" onClick={() => setOpen(false)}>
|
||||
|
||||
@@ -35,14 +35,9 @@ export const columns: ColumnDef<Post>[] = [
|
||||
accessorKey: "pstgPrdSeNm",
|
||||
header: "게시기간",
|
||||
cell: ({ row }) => {
|
||||
const pstgPrdSeCd = row.original.pstgPrdSeCd;
|
||||
const pstgPrdSeNm = row.original.pstgPrdSeNm;
|
||||
const pstgBgngDt = row.original.pstgBgngDt;
|
||||
const pstgEndDt = row.original.pstgEndDt;
|
||||
|
||||
if (pstgPrdSeCd === "99") {
|
||||
return pstgPrdSeNm;
|
||||
}
|
||||
return `${pstgPrdSeNm} (${dayjs(pstgBgngDt).format("YYYY-MM-DD")} ~ ${dayjs(pstgEndDt).format("YYYY-MM-DD")})`;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -16,7 +16,8 @@ import {
|
||||
SelectValue,
|
||||
LoadingWithImage,
|
||||
} from "@common/components";
|
||||
import { LoginlogApi, type LoginlogParams } from "@/entities/loginlog";
|
||||
import { LoginlogApi } from "@/entities/loginlog";
|
||||
import { type LoginlogParams } from "@/entities/loginlog/model/loginlog-interface";
|
||||
import { useDataTable } from "@/shared/lib";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { columns } from "@/pages/loginlog/model/table-columns";
|
||||
|
||||
@@ -3,7 +3,7 @@ import type {
|
||||
TreeUserOrganization,
|
||||
TreeUser,
|
||||
} from "@/entities/user-organization";
|
||||
import type { TreeMenu, TreeNode } from "@/entities/tree-menu";
|
||||
import type { TreeMenu, TreeNode } from "../model/tree-menu-interface";
|
||||
|
||||
export const generateMenuTreeData = (
|
||||
data: TreeMenu[],
|
||||
|
||||
-1
@@ -19,7 +19,6 @@ export interface TreeMenu extends Omit<TreeNode, "name" | "icon" | "children"> {
|
||||
qrcd?: string;
|
||||
useYn: string;
|
||||
otptYn: string;
|
||||
menuSubKornNm?: string;
|
||||
requiredUrlPath?: boolean;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Button, Input } from "@common/components";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/shared/ui/tooltip";
|
||||
|
||||
type EditableNodeProps = {
|
||||
depth?: number;
|
||||
@@ -21,34 +20,22 @@ function EditableNode({
|
||||
>
|
||||
<Input {...props} className="h-[2.5rem] !text-[1.3rem] text-foreground" />
|
||||
<div className="flex items-center gap-1">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="size-8 !bg-transparent"
|
||||
onClick={onSave}
|
||||
aria-label="저장"
|
||||
>
|
||||
<i className="diveicon di-check text-2xl" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>저장</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="size-8 !bg-transparent"
|
||||
onClick={onCancel}
|
||||
aria-label="취소"
|
||||
>
|
||||
<i className="diveicon di-x" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>취소</TooltipContent>
|
||||
</Tooltip>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="size-8 !bg-transparent"
|
||||
onClick={onSave}
|
||||
>
|
||||
<i className="diveicon di-check text-2xl" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="size-8 !bg-transparent"
|
||||
onClick={onCancel}
|
||||
>
|
||||
<i className="diveicon di-x" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,9 +2,10 @@ import { useEffect, useState } from "react";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import type { NodeModel, TreeMethods } from "@minoru/react-dnd-treeview";
|
||||
import { Button, cn } from "@common/components";
|
||||
import { TreeMenuApi, type TreeMenu } from "@/entities/tree-menu";
|
||||
import { useMutationWrapper } from "@/shared/lib";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { TreeMenuApi } from "../api/tree-menu-service";
|
||||
import type { TreeMenu } from "../model/tree-menu-interface";
|
||||
import { EditableNode } from "./editable-node";
|
||||
|
||||
type MenuNodeProps = {
|
||||
|
||||
@@ -21,10 +21,11 @@ import {
|
||||
type MenuFormData,
|
||||
} from "@/entities/menu";
|
||||
import { SiteApi } from "@/entities/site";
|
||||
import { TreeMenuApi, type TreeMenu } from "@/entities/tree-menu";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { useAlertStore, useMutationWrapper } from "@/shared/lib";
|
||||
import { generateMenuTreeData } from "../lib/utils";
|
||||
import { TreeMenuApi } from "../api/tree-menu-service";
|
||||
import type { TreeMenu } from "../model/tree-menu-interface";
|
||||
import { MenuTree } from "./menu-tree";
|
||||
import { MenuForm } from "./menu-form";
|
||||
|
||||
|
||||
@@ -12,11 +12,8 @@ import { Button } from "@common/components";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { useMutationWrapper } from "@/shared/lib";
|
||||
import type { MenuFormData } from "@/entities/menu";
|
||||
import {
|
||||
TreeMenuApi,
|
||||
type TreeMenu,
|
||||
type TreeNode,
|
||||
} from "@/entities/tree-menu";
|
||||
import { TreeMenuApi } from "../api/tree-menu-service";
|
||||
import type { TreeMenu, TreeNode } from "../model/tree-menu-interface";
|
||||
import { handleDropNode, handleSelectNode } from "../lib/utils";
|
||||
import { MenuNode } from "./menu-node";
|
||||
import { EditableNode } from "./editable-node";
|
||||
|
||||
@@ -72,7 +72,7 @@ function AddUserDialog({ onAddUsers, ...props }: AddUserDialogProps) {
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-[60rem]" aria-describedby={undefined}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>사용자 조회</DialogTitle>
|
||||
<DialogTitle>콘텐츠 조회</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="card card-border !m-0 flex w-full items-center gap-2">
|
||||
|
||||
@@ -242,16 +242,6 @@ function UserOrganizationSection({ ognzSn }: UserOrganizationSectionProps) {
|
||||
</div>
|
||||
<div className="card max-h-[calc(100vh-58rem)] overflow-auto !p-0">
|
||||
<Table>
|
||||
<colgroup>
|
||||
<col width="5%" />
|
||||
<col width="5%" />
|
||||
<col width="auto" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="15%" />
|
||||
<col width="15%" />
|
||||
</colgroup>
|
||||
<TableHeader className="sticky top-0">
|
||||
<TableRow>
|
||||
<TableHead>
|
||||
@@ -310,9 +300,6 @@ const UserCells = memo(
|
||||
jobPositionCodeData,
|
||||
jobGradeCodeData,
|
||||
}: UserCellsProps) => {
|
||||
const [jbpsSeCd, setJbpsSeCd] = useState(user.jbpsSeCd);
|
||||
const [jbgdSeCd, setJbgdSeCd] = useState(user.jbgdSeCd);
|
||||
|
||||
const updateMode = (index: number) => {
|
||||
const mode = form.watch(`userOrganization.${index}.mode`);
|
||||
if (mode === "R") {
|
||||
@@ -335,33 +322,17 @@ const UserCells = memo(
|
||||
<CodeSelect
|
||||
codeData={jobPositionCodeData}
|
||||
defaultValue={user.jbpsSeCd}
|
||||
onValueChange={(value) => {
|
||||
setJbpsSeCd(value);
|
||||
updateFormValue(index, "jbpsSeCd")(value);
|
||||
}}
|
||||
onValueChange={updateFormValue(index, "jbpsSeCd")}
|
||||
{...form.register(`userOrganization.${index}.jbpsSeCd`)}
|
||||
/>
|
||||
{!jbpsSeCd && (
|
||||
<p className="pt-1 text-base text-destructive">
|
||||
직위를 선택해주세요.
|
||||
</p>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
<CodeSelect
|
||||
codeData={jobGradeCodeData}
|
||||
defaultValue={user.jbgdSeCd}
|
||||
onValueChange={(value) => {
|
||||
setJbgdSeCd(value);
|
||||
updateFormValue(index, "jbgdSeCd")(value);
|
||||
}}
|
||||
onValueChange={updateFormValue(index, "jbgdSeCd")}
|
||||
{...form.register(`userOrganization.${index}.jbgdSeCd`)}
|
||||
/>
|
||||
{!jbgdSeCd && (
|
||||
<p className="pt-1 text-base text-destructive">
|
||||
직급을 선택해주세요.
|
||||
</p>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
<Input
|
||||
|
||||
@@ -33,14 +33,9 @@ export const columns: ColumnDef<Post>[] = [
|
||||
accessorKey: "pstgPrdSeNm",
|
||||
header: "게시기간",
|
||||
cell: ({ row }) => {
|
||||
const pstgPrdSeCd = row.original.pstgPrdSeCd;
|
||||
const pstgPrdSeNm = row.original.pstgPrdSeNm;
|
||||
const pstgBgngDt = row.original.pstgBgngDt;
|
||||
const pstgEndDt = row.original.pstgEndDt;
|
||||
|
||||
if (pstgPrdSeCd === "99") {
|
||||
return pstgPrdSeNm;
|
||||
}
|
||||
return `${pstgPrdSeNm} (${dayjs(pstgBgngDt).format("YYYY-MM-DD")} ~ ${dayjs(pstgEndDt).format("YYYY-MM-DD")})`;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -15,10 +15,8 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@common/components";
|
||||
import {
|
||||
PrivacyLogPrivacy,
|
||||
type PrivacyLogParams,
|
||||
} from "@/entities/privacylog";
|
||||
import { PrivacyLogPrivacy } from "@/entities/privacylog";
|
||||
import type { PrivacyLogParams } from "@/entities/privacylog/model/privacylog-interface";
|
||||
import { useDataTable } from "@/shared/lib";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { columns } from "@/pages/privacylog/model/table-columns";
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import { client } from "@/shared/api";
|
||||
import type {
|
||||
SiteAuthorityCreatePayload,
|
||||
SiteAuthorityList,
|
||||
SiteAuthoritySearchParams,
|
||||
SiteAuthorityService,
|
||||
} from "../model/site-authority-interface";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
|
||||
export class SiteAuthorityApiService implements SiteAuthorityService {
|
||||
public async getSiteAuthorityList(
|
||||
params: SiteAuthoritySearchParams,
|
||||
): Promise<SiteAuthorityList> {
|
||||
const response = await client.get<SiteAuthorityList>(
|
||||
ENDPOINT.CMS_SERVICE.SITE_AUTHORITY,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async createSiteAuthority(
|
||||
data: SiteAuthorityCreatePayload[],
|
||||
): Promise<void> {
|
||||
await client.post(ENDPOINT.CMS_SERVICE.SITE_AUTHORITY, data);
|
||||
}
|
||||
}
|
||||
|
||||
export const SiteAuthorityApi = new SiteAuthorityApiService();
|
||||
@@ -1,24 +0,0 @@
|
||||
import type { PageableList, PageableParams } from "@/shared/model";
|
||||
|
||||
export interface SiteAuthoritySearchParams extends PageableParams {
|
||||
siteId?: string;
|
||||
authrtId?: string;
|
||||
}
|
||||
|
||||
export interface SiteAuthority {
|
||||
siteId: string;
|
||||
authrtId: string;
|
||||
siteNm: string;
|
||||
mode: string;
|
||||
}
|
||||
|
||||
export type SiteAuthorityCreatePayload = Omit<SiteAuthority, "siteNm">;
|
||||
|
||||
export type SiteAuthorityList = PageableList<SiteAuthority>;
|
||||
|
||||
export interface SiteAuthorityService {
|
||||
getSiteAuthorityList: (
|
||||
params: SiteAuthoritySearchParams,
|
||||
) => Promise<SiteAuthorityList>;
|
||||
createSiteAuthority: (data: SiteAuthorityCreatePayload[]) => Promise<void>;
|
||||
}
|
||||
@@ -3,13 +3,8 @@ import { useState } from "react";
|
||||
import type { Role } from "@/entities/role";
|
||||
import type { ColumnDef } from "@tanstack/react-table";
|
||||
import { MappingRoleDialog } from "../ui/mapping-role-dialog";
|
||||
import { Button } from "@common/components";
|
||||
|
||||
export const createColumns = ({
|
||||
deleteRole,
|
||||
}: {
|
||||
deleteRole: (roleId: string) => void;
|
||||
}): ColumnDef<Role>[] => [
|
||||
export const columns: ColumnDef<Role>[] = [
|
||||
{
|
||||
id: "no",
|
||||
header: "NO",
|
||||
@@ -44,18 +39,7 @@ export const createColumns = ({
|
||||
{
|
||||
id: "action",
|
||||
header: "관리",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<MappingRoleButton roleId={row.original.roleId} />
|
||||
<Button
|
||||
size="sm"
|
||||
color="red"
|
||||
onClick={() => deleteRole(row.original.roleId)}
|
||||
>
|
||||
삭제
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
cell: ({ row }) => <MappingRoleButton roleId={row.original.roleId} />,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { getCoreRowModel, type ColumnDef } from "@tanstack/react-table";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
Dialog,
|
||||
DialogTrigger,
|
||||
@@ -9,7 +8,6 @@ import {
|
||||
DialogTitle,
|
||||
Button,
|
||||
Switch,
|
||||
Input,
|
||||
} from "@common/components";
|
||||
import {
|
||||
RoleAuthorizationsApi,
|
||||
@@ -33,18 +31,12 @@ function MappingRoleDialog({
|
||||
}: MappingRoleDialogProps) {
|
||||
const queryClient = useQueryClient();
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [searchParams, setSearchParams] = useState({
|
||||
keyword: "",
|
||||
keywordType: "authorizationName",
|
||||
});
|
||||
|
||||
const query = useQuery({
|
||||
queryKey: [ENDPOINT.USER_SERVICE.ROLE_AUTHORIZATIONS, searchParams],
|
||||
queryKey: [ENDPOINT.USER_SERVICE.AUTHORIZATIONS],
|
||||
queryFn: () =>
|
||||
RoleAuthorizationsApi.getRoleAuthorizationsListByRoleId({
|
||||
roleId,
|
||||
...searchParams,
|
||||
}),
|
||||
enabled: open,
|
||||
});
|
||||
@@ -54,7 +46,7 @@ function MappingRoleDialog({
|
||||
RoleAuthorizationsApi.createRoleAuthorizations(data),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.USER_SERVICE.ROLE_AUTHORIZATIONS],
|
||||
queryKey: [ENDPOINT.USER_SERVICE.AUTHORIZATIONS],
|
||||
});
|
||||
alert("권한 맵핑이 완료되었습니다.");
|
||||
},
|
||||
@@ -74,26 +66,6 @@ function MappingRoleDialog({
|
||||
);
|
||||
};
|
||||
|
||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(e.target as HTMLFormElement);
|
||||
const keyword = formData.get("keyword") as string;
|
||||
setSearchParams({
|
||||
...searchParams,
|
||||
keyword,
|
||||
});
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
if (inputRef.current) {
|
||||
inputRef.current.value = "";
|
||||
}
|
||||
setSearchParams({
|
||||
...searchParams,
|
||||
keyword: "",
|
||||
});
|
||||
};
|
||||
|
||||
const { tableComponent } = useDataTable({
|
||||
query,
|
||||
tableOptions: {
|
||||
@@ -107,31 +79,21 @@ function MappingRoleDialog({
|
||||
<DialogTrigger asChild>
|
||||
<Button size="sm">권한맵핑</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-[80rem]" aria-describedby={undefined}>
|
||||
<DialogContent className="max-w-[60rem]" aria-describedby={undefined}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>모듈 목록</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<form onSubmit={handleSubmit} className="flex items-center gap-2">
|
||||
<Input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
name="keyword"
|
||||
className="w-[32rem]"
|
||||
/>
|
||||
<Button type="submit">검색</Button>
|
||||
<Button type="button" color="white" onClick={handleReset}>
|
||||
초기화
|
||||
<div className="max-h-[40rem] overflow-y-auto">
|
||||
<div className="mb-4 flex justify-end gap-2">
|
||||
<Button size="sm" onClick={() => handleApplyAll("Y")}>
|
||||
일괄적용
|
||||
</Button>
|
||||
</form>
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<Button onClick={() => handleApplyAll("Y")}>일괄적용</Button>
|
||||
<Button color="gray" onClick={() => handleApplyAll("N")}>
|
||||
<Button size="sm" color="gray" onClick={() => handleApplyAll("N")}>
|
||||
일괄해제
|
||||
</Button>
|
||||
</div>
|
||||
{tableComponent}
|
||||
</div>
|
||||
<div className="max-h-[60rem] overflow-y-auto">{tableComponent}</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useState } from "react";
|
||||
import type { UseFormReturn } from "react-hook-form";
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Input,
|
||||
Label,
|
||||
RadioGroup,
|
||||
@@ -18,9 +16,6 @@ import { FormWrapper } from "@/widgets/form-wrapper";
|
||||
import { RoleApi, type RoleFormData } from "@/entities/role";
|
||||
import { FormField, FormItem, FormControl } from "@/shared/ui/form";
|
||||
import { useAlertStore, useMutationWrapper } from "@/shared/lib";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { SiteAuthorityApi } from "../api/site-authority-service";
|
||||
import type { SiteAuthorityCreatePayload } from "../model/site-authority-interface";
|
||||
|
||||
type RoleFormProps = {
|
||||
roleId?: string;
|
||||
@@ -29,24 +24,12 @@ type RoleFormProps = {
|
||||
handleDelete?: () => Promise<void>;
|
||||
};
|
||||
|
||||
function RoleForm({ roleId, form, handleSave, ...props }: RoleFormProps) {
|
||||
function RoleForm({ roleId, form, ...props }: RoleFormProps) {
|
||||
const isModifyMode = !!roleId;
|
||||
const queryClient = useQueryClient();
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
const [isValidRoleId, setIsValidRoleId] = useState(false);
|
||||
const [checkedSiteAuthority, setCheckedSiteAuthority] = useState<string[]>(
|
||||
[],
|
||||
);
|
||||
|
||||
const { data: siteAuthorityList } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.SITE_AUTHORITY, roleId],
|
||||
queryFn: () =>
|
||||
SiteAuthorityApi.getSiteAuthorityList({
|
||||
authrtId: roleId,
|
||||
page: 0,
|
||||
size: 100,
|
||||
}),
|
||||
});
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
|
||||
const [isValidRoleId, setIsValidRoleId] = useState(false);
|
||||
|
||||
const { mutateAsync: checkDuplicateRoleId } = useMutationWrapper({
|
||||
mutationFn: (roleId: string) => RoleApi.checkDuplicateRoleId(roleId),
|
||||
@@ -60,49 +43,8 @@ function RoleForm({ roleId, form, handleSave, ...props }: RoleFormProps) {
|
||||
},
|
||||
});
|
||||
|
||||
const handleSiteAuthorityChecked = (checked: boolean, siteId: string) => {
|
||||
if (checked) {
|
||||
setCheckedSiteAuthority((prev) => [...prev, siteId]);
|
||||
} else {
|
||||
setCheckedSiteAuthority((prev) => prev.filter((id) => id !== siteId));
|
||||
}
|
||||
};
|
||||
|
||||
const saveInterceptor = async (data: RoleFormData) => {
|
||||
const siteAuthorityPayload: SiteAuthorityCreatePayload[] =
|
||||
checkedSiteAuthority.map((siteId) => ({
|
||||
siteId,
|
||||
authrtId: data.roleId,
|
||||
mode: "C",
|
||||
}));
|
||||
|
||||
try {
|
||||
await handleSave(data);
|
||||
if (data.mngrYn === "N") return;
|
||||
await SiteAuthorityApi.createSiteAuthority(siteAuthorityPayload);
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.SITE_AUTHORITY],
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!siteAuthorityList?.content.length) return;
|
||||
const checkedSiteAuthority = siteAuthorityList.content.filter(
|
||||
(item) => item.mode === "R",
|
||||
);
|
||||
setCheckedSiteAuthority(checkedSiteAuthority.map((item) => item.siteId));
|
||||
}, [siteAuthorityList]);
|
||||
|
||||
return (
|
||||
<FormWrapper
|
||||
form={form}
|
||||
isModifyMode={isModifyMode}
|
||||
handleSave={saveInterceptor}
|
||||
{...props}
|
||||
>
|
||||
<FormWrapper form={form} isModifyMode={isModifyMode} {...props}>
|
||||
<div className="card">
|
||||
<Table variant="secondary">
|
||||
<colgroup>
|
||||
@@ -223,29 +165,6 @@ function RoleForm({ roleId, form, handleSave, ...props }: RoleFormProps) {
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{form.watch("mngrYn") === "Y" && (
|
||||
<TableRow>
|
||||
<TableHead data-required>관리사이트</TableHead>
|
||||
<TableCell className="border">
|
||||
<div className="flex flex-wrap items-center gap-4">
|
||||
{siteAuthorityList?.content.map((item) => (
|
||||
<div
|
||||
key={item.siteId}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<Checkbox
|
||||
defaultChecked={item.mode === "R"}
|
||||
onCheckedChange={(checked: boolean) => {
|
||||
handleSiteAuthorityChecked(checked, item.siteId);
|
||||
}}
|
||||
/>
|
||||
<span className="whitespace-nowrap">{item.siteNm}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
<TableRow>
|
||||
<TableHead data-required>사용여부</TableHead>
|
||||
<TableCell className="border">
|
||||
|
||||
@@ -7,12 +7,11 @@ import { getCoreRowModel, type PaginationState } from "@tanstack/react-table";
|
||||
import { Button, Input, Label } from "@common/components";
|
||||
import { RoleApi, type Role, type RoleParams } from "@/entities/role";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { useAlertStore, useDataTable, useMutationWrapper } from "@/shared/lib";
|
||||
import { createColumns } from "../model/table-columns";
|
||||
import { useDataTable } from "@/shared/lib";
|
||||
import { columns } from "../model/table-columns";
|
||||
|
||||
function RolePage() {
|
||||
const router = useRouter();
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
|
||||
const [keyword, setKeyword] = useState("");
|
||||
const [searchParams, setSearchParams] = useState<RoleParams>({
|
||||
@@ -34,13 +33,6 @@ function RolePage() {
|
||||
}),
|
||||
});
|
||||
|
||||
const { mutateAsync: deleteRole } = useMutationWrapper({
|
||||
mutationFn: (roleId: string) => RoleApi.deleteRole(roleId),
|
||||
onSuccess: () => {
|
||||
alert("삭제되었습니다.", query.refetch);
|
||||
},
|
||||
});
|
||||
|
||||
const handleRowClick = (row: Role) => {
|
||||
router.push(`/role/register/${row.roleId}`);
|
||||
};
|
||||
@@ -48,9 +40,7 @@ function RolePage() {
|
||||
const { tableComponent } = useDataTable({
|
||||
query,
|
||||
tableOptions: {
|
||||
columns: createColumns({
|
||||
deleteRole,
|
||||
}),
|
||||
columns,
|
||||
state: {
|
||||
pagination,
|
||||
},
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import type { NodeModel } from "@minoru/react-dnd-treeview";
|
||||
import type { TreeMenu } from "@/entities/tree-menu";
|
||||
|
||||
export const generateMenuTreeData = (
|
||||
data: TreeMenu[],
|
||||
): NodeModel<TreeMenu>[] => {
|
||||
return data.reduce<NodeModel<TreeMenu>[]>((acc, menu) => {
|
||||
const node: NodeModel<TreeMenu> = {
|
||||
id: menu.menuCd ?? 0,
|
||||
parent: menu.parentId ?? 0,
|
||||
text: menu.menuSubKornNm ?? "",
|
||||
droppable: true,
|
||||
data: menu,
|
||||
};
|
||||
|
||||
acc.push(node);
|
||||
|
||||
if (menu.children?.length) {
|
||||
acc.push(...generateMenuTreeData(menu.children));
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
};
|
||||
@@ -1,32 +1,6 @@
|
||||
import dayjs from "dayjs";
|
||||
import { memo, useState } from "react";
|
||||
import { useFieldArray, useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { type ColumnDef } from "@tanstack/react-table";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@common/components";
|
||||
import type { Site } from "@/entities/site";
|
||||
import { TreeMenuApi } from "@/entities/tree-menu";
|
||||
import {
|
||||
MenuApi,
|
||||
siteMapFormSchema,
|
||||
type SiteMapFormData,
|
||||
} from "@/entities/menu";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { useAlertStore, useMutationWrapper } from "@/shared/lib";
|
||||
import { MenuTree } from "../ui/menu-tree";
|
||||
import { generateMenuTreeData } from "../lib/utils";
|
||||
|
||||
export const columns: ColumnDef<Site>[] = [
|
||||
{
|
||||
@@ -71,81 +45,4 @@ export const columns: ColumnDef<Site>[] = [
|
||||
return date.format("YYYY-MM-DD");
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "action",
|
||||
header: "관리",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<ActionCell data={row.original} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const ActionCell = memo(({ data }: { data: Site }) => {
|
||||
const { confirm } = useConfirm();
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const { data: menuTreeData, refetch } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.MENUS, data.siteId],
|
||||
queryFn: () => TreeMenuApi.getTreeMenuList(data.siteId),
|
||||
select: (data) => generateMenuTreeData(data),
|
||||
enabled: !!data.siteId && open,
|
||||
});
|
||||
|
||||
const { mutate: publishSiteMap } = useMutationWrapper({
|
||||
mutationFn: (data: SiteMapFormData["siteMap"]) =>
|
||||
MenuApi.publishSiteMap(data),
|
||||
onSuccess: () => {
|
||||
alert("사이트맵이 저장되었습니다.", () => {
|
||||
setOpen(false);
|
||||
refetch();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm<SiteMapFormData>({
|
||||
resolver: zodResolver(siteMapFormSchema),
|
||||
});
|
||||
const fieldArray = useFieldArray({
|
||||
control: form.control,
|
||||
name: "siteMap",
|
||||
});
|
||||
|
||||
const handlePublishSiteMap = async () => {
|
||||
if (await confirm("저장하시겠습니까?")) {
|
||||
publishSiteMap(form.getValues("siteMap"));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button size="sm">사이트맵</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{data.siteNm} - 사이트맵 관리</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div>
|
||||
<div className="flex items-center justify-end gap-2 p-2">
|
||||
<span className="text-xl">표시여부</span>
|
||||
<Checkbox checked />
|
||||
</div>
|
||||
<MenuTree tree={menuTreeData ?? []} fieldArray={fieldArray} />
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button onClick={handlePublishSiteMap}>저장</Button>
|
||||
<DialogClose asChild>
|
||||
<Button color="white">취소</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
});
|
||||
|
||||
ActionCell.displayName = "ActionCell";
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import { Button, Input } from "@common/components";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/shared/ui/tooltip";
|
||||
|
||||
type EditableNodeProps = {
|
||||
depth?: number;
|
||||
onSave: () => void;
|
||||
onCancel: () => void;
|
||||
} & ComponentProps<typeof Input>;
|
||||
|
||||
function EditableNode({
|
||||
depth,
|
||||
onSave,
|
||||
onCancel,
|
||||
...props
|
||||
}: EditableNodeProps) {
|
||||
return (
|
||||
<div
|
||||
className="flex items-center gap-2 rounded-sm bg-accent p-2"
|
||||
style={{ marginInlineStart: !depth ? 0 : depth * 5 + 5 }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Input {...props} className="h-[2.5rem] !text-[1.3rem] text-foreground" />
|
||||
<div className="flex items-center gap-1">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="size-8 !bg-transparent"
|
||||
onClick={onSave}
|
||||
aria-label="저장"
|
||||
>
|
||||
<i className="diveicon di-check text-2xl" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>저장</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="size-8 !bg-transparent"
|
||||
onClick={onCancel}
|
||||
aria-label="취소"
|
||||
>
|
||||
<i className="diveicon di-x" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>취소</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { EditableNode };
|
||||
@@ -1,128 +0,0 @@
|
||||
import { useState } from "react";
|
||||
import type { NodeModel } from "@minoru/react-dnd-treeview";
|
||||
import type { UseFieldArrayReturn } from "react-hook-form";
|
||||
import { Button, Checkbox, cn } from "@common/components";
|
||||
import { type TreeMenu } from "@/entities/tree-menu";
|
||||
import type { SiteMapFormData, SiteMapPayloadData } from "@/entities/menu";
|
||||
import { EditableNode } from "./editable-node";
|
||||
|
||||
type MenuNodeProps = {
|
||||
node: NodeModel<TreeMenu>;
|
||||
depth: number;
|
||||
isOpen: boolean;
|
||||
fieldArray: UseFieldArrayReturn<SiteMapFormData>;
|
||||
onToggle: (id: NodeModel["id"]) => void;
|
||||
};
|
||||
|
||||
function MenuNode({
|
||||
node,
|
||||
depth,
|
||||
isOpen,
|
||||
fieldArray,
|
||||
onToggle,
|
||||
}: MenuNodeProps) {
|
||||
const { id, text, data } = node;
|
||||
const indent = depth * 10 + 5;
|
||||
|
||||
const [editMode, setEditMode] = useState(false);
|
||||
const [nodeName, setNodeName] = useState(text);
|
||||
const [otptYn, setOtptYn] = useState(data?.otptYn ?? "N");
|
||||
|
||||
const updateField = (id: number, newField: SiteMapPayloadData) => {
|
||||
const existingFieldIndex = fieldArray.fields.findIndex(
|
||||
(field) => field.menuCd === id,
|
||||
);
|
||||
if (existingFieldIndex !== -1) {
|
||||
fieldArray.update(existingFieldIndex, newField);
|
||||
} else {
|
||||
fieldArray.append(newField);
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggle = () => onToggle(id);
|
||||
|
||||
const handleSave = async () => {
|
||||
const newField = {
|
||||
menuCd: id as number,
|
||||
menuSubKornNm: nodeName,
|
||||
otptYn,
|
||||
};
|
||||
updateField(id as number, newField);
|
||||
setEditMode(false);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setEditMode(false);
|
||||
setNodeName(text);
|
||||
};
|
||||
|
||||
const handleOtptYnChange = (checked: boolean) => {
|
||||
const newField = {
|
||||
menuCd: id as number,
|
||||
menuSubKornNm: nodeName,
|
||||
otptYn: checked ? "Y" : "N",
|
||||
};
|
||||
updateField(id as number, newField);
|
||||
setOtptYn(checked ? "Y" : "N");
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{ paddingInlineStart: indent }}
|
||||
className={cn(
|
||||
"group flex cursor-pointer items-center gap-2 rounded-sm p-2 hover:bg-accent",
|
||||
editMode && "p-0 pr-2 hover:bg-transparent",
|
||||
)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleToggle();
|
||||
}}
|
||||
>
|
||||
{editMode ? (
|
||||
<EditableNode
|
||||
value={nodeName}
|
||||
onChange={(e) => setNodeName(e.target.value)}
|
||||
onSave={handleSave}
|
||||
onCancel={handleCancel}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<div className="flex items-center">
|
||||
{data?.children?.length && (
|
||||
<i
|
||||
className={cn(
|
||||
"diveicon di-arrow-forward mr-2 text-base text-label",
|
||||
isOpen && "rotate-90",
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
<span className="text-[1.4rem] font-medium text-label">
|
||||
{nodeName}
|
||||
</span>
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="invisible !bg-transparent group-hover:visible"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setEditMode(true);
|
||||
}}
|
||||
>
|
||||
<i className="diveicon di-pencil" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<Checkbox
|
||||
className="ml-auto"
|
||||
checked={otptYn === "Y"}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
onCheckedChange={handleOtptYnChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { MenuNode };
|
||||
@@ -1,70 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useRef } from "react";
|
||||
import type { UseFieldArrayReturn } from "react-hook-form";
|
||||
import {
|
||||
Tree,
|
||||
type NodeModel,
|
||||
type TreeMethods,
|
||||
} from "@minoru/react-dnd-treeview";
|
||||
import { Button } from "@common/components";
|
||||
import type { SiteMapFormData } from "@/entities/menu";
|
||||
import { type TreeMenu } from "@/entities/tree-menu";
|
||||
import { MenuNode } from "./menu-node";
|
||||
|
||||
type MenuTreeProps = {
|
||||
tree: NodeModel<TreeMenu>[];
|
||||
fieldArray: UseFieldArrayReturn<SiteMapFormData>;
|
||||
};
|
||||
|
||||
function MenuTree({ tree, fieldArray }: MenuTreeProps) {
|
||||
const treeMethods = useRef<TreeMethods>(null);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="max-h-[calc(100vh-33.5rem)] min-h-[40vh] overflow-auto">
|
||||
<Tree
|
||||
tree={tree}
|
||||
rootId={0}
|
||||
ref={treeMethods}
|
||||
render={(node: NodeModel<TreeMenu>, props) => {
|
||||
return <MenuNode node={node} fieldArray={fieldArray} {...props} />;
|
||||
}}
|
||||
onDrop={() => {}}
|
||||
canDrag={() => false}
|
||||
canDrop={() => false}
|
||||
classes={{
|
||||
container: "flex flex-col",
|
||||
dropTarget: "!bg-[rgba(32,148,250,0.5)] rounded-sm",
|
||||
placeholder: "relative",
|
||||
}}
|
||||
sort={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
color="lightGray"
|
||||
className="flex-1 items-center px-0"
|
||||
onClick={() => {
|
||||
treeMethods.current?.openAll();
|
||||
}}
|
||||
>
|
||||
<i className="diveicon di-arrows-angle-expand" />
|
||||
전체펼침
|
||||
</Button>
|
||||
<Button
|
||||
color="lightGray"
|
||||
className="flex-1 items-center px-0"
|
||||
onClick={() => {
|
||||
treeMethods.current?.closeAll();
|
||||
}}
|
||||
>
|
||||
<i className="diveicon di-arrows-angle-contract" />
|
||||
전체접기
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export { MenuTree };
|
||||
@@ -36,14 +36,9 @@ export const columns: ColumnDef<Post>[] = [
|
||||
accessorKey: "pstgPrdSeNm",
|
||||
header: "게시기간",
|
||||
cell: ({ row }) => {
|
||||
const pstgPrdSeCd = row.original.pstgPrdSeCd;
|
||||
const pstgPrdSeNm = row.original.pstgPrdSeNm;
|
||||
const pstgBgngDt = row.original.pstgBgngDt;
|
||||
const pstgEndDt = row.original.pstgEndDt;
|
||||
|
||||
if (pstgPrdSeCd === "99") {
|
||||
return pstgPrdSeNm;
|
||||
}
|
||||
return `${pstgPrdSeNm} (${dayjs(pstgBgngDt).format("YYYY-MM-DD")} ~ ${dayjs(pstgEndDt).format("YYYY-MM-DD")})`;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import dayjs from "dayjs";
|
||||
import type { ColumnDef } from "@tanstack/react-table";
|
||||
import {
|
||||
USER_STATE_CODE,
|
||||
type UserListResponse,
|
||||
type UserStateCode,
|
||||
} from "@/entities/user";
|
||||
import { Badge } from "@common/components";
|
||||
import type { UserListResponse } from "@/entities/user";
|
||||
|
||||
export const columns: ColumnDef<UserListResponse>[] = [
|
||||
{
|
||||
@@ -47,11 +42,8 @@ export const columns: ColumnDef<UserListResponse>[] = [
|
||||
header: "기관/부서",
|
||||
},
|
||||
{
|
||||
accessorKey: "userStateCode",
|
||||
accessorKey: "userStateCodeName",
|
||||
header: "회원상태",
|
||||
cell: ({ row }) => {
|
||||
return getUserStateBadge(row.original.userStateCode);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "aprvYmd",
|
||||
@@ -71,18 +63,3 @@ export const columns: ColumnDef<UserListResponse>[] = [
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const getUserStateBadge = (userStateCode: UserStateCode) => {
|
||||
switch (userStateCode) {
|
||||
case USER_STATE_CODE.대기:
|
||||
return <Badge color="gray">대기</Badge>;
|
||||
case USER_STATE_CODE.정상:
|
||||
return <Badge color="green">정상</Badge>;
|
||||
case USER_STATE_CODE.정지:
|
||||
return <Badge color="yellow">정지</Badge>;
|
||||
case USER_STATE_CODE.탈퇴:
|
||||
return <Badge color="purple">탈퇴</Badge>;
|
||||
case USER_STATE_CODE.삭제:
|
||||
return <Badge color="red">삭제</Badge>;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,11 +16,20 @@ function CreatePage() {
|
||||
defaultValues: {
|
||||
userId: "",
|
||||
userName: "",
|
||||
email: "",
|
||||
password: "",
|
||||
pswdHnt: "",
|
||||
pswdAns: "",
|
||||
mphn: "",
|
||||
telno: "",
|
||||
zip: "",
|
||||
addr: "",
|
||||
daddr: "",
|
||||
laeSeCd: "",
|
||||
ogdpSeCd: "",
|
||||
expryYmd: "",
|
||||
instSeCd: "",
|
||||
enoCd: "",
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ export const ENDPOINT = {
|
||||
GROUP_USERS: "/cms-service/api/v1/group-users",
|
||||
MANAGER_IP: "/cms-service/api/v1/mgrip",
|
||||
APILOG: "/cms-service/api/v1/api-logs",
|
||||
SITE_AUTHORITY: "/cms-service/api/v1/site-authrt",
|
||||
},
|
||||
BOARD_SERVICE: {
|
||||
BBS: "/board-service/api/v1/bbs",
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
NEXT_PUBLIC_SITE_ID = FO
|
||||
NEXT_PUBLIC_PORT = 11300
|
||||
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||
NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
|
||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
|
||||
NEXT_PUBLIC_CLAIM_NAME = Authorization
|
||||
NEXT_PUBLIC_AUTH_USER_ID = token-id
|
||||
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
|
||||
@@ -1,13 +0,0 @@
|
||||
NEXT_PUBLIC_SITE_ID = FO
|
||||
NEXT_PUBLIC_PORT = 3000
|
||||
NEXT_PUBLIC_PROXY_HOST = http://localhost:3000
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||
NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
|
||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
|
||||
NEXT_PUBLIC_CLAIM_NAME = Authorization
|
||||
NEXT_PUBLIC_AUTH_USER_ID = token-id
|
||||
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
|
||||
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성 PC 서버 API
|
||||
@@ -1,41 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/versions
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# env files (can opt-in for committing if needed)
|
||||
#.env*
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
@@ -1,12 +0,0 @@
|
||||
const DEV_PORT_COMMON = "11081";
|
||||
const DEV_PORT_FO = "11082";
|
||||
const DEV_PORT_WR = "11080";
|
||||
|
||||
export const LOCAL_URL_COMMON = `http://192.168.1.129:${DEV_PORT_COMMON}/api/v1`;
|
||||
export const DEV_URL_COMMON = `http://con.mind-one.co.kr:${DEV_PORT_COMMON}/api/v1`;
|
||||
|
||||
export const LOCAL_URL_FO = `http://192.168.1.129:${DEV_PORT_FO}/api/v1`;
|
||||
export const DEV_URL_FO = `http://con.mind-one.co.kr:${DEV_PORT_FO}/api/v1`;
|
||||
|
||||
export const LOCAL_URL_WR = `http://192.168.1.129:${DEV_PORT_WR}/api/v1`;
|
||||
export const DEV_URL_WR = `http://con.mind-one.co.kr:${DEV_PORT_WR}/api/v1`;
|
||||
@@ -1 +0,0 @@
|
||||
export * from './env';
|
||||
@@ -1,79 +0,0 @@
|
||||
import { DEV_URL_COMMON, DEV_URL_FO, DEV_URL_WR } from "./config/env";
|
||||
|
||||
export const getFetch = async (part : string, url: string) => {
|
||||
let reqUrl = "";
|
||||
reqUrl = part === "fo" ? DEV_URL_FO+url : part === "wr" ? DEV_URL_WR+url : DEV_URL_COMMON+url;
|
||||
const response = await fetch(reqUrl , {
|
||||
method: "GET",
|
||||
headers: {
|
||||
accept: "application/json",
|
||||
}
|
||||
});
|
||||
if(!response.ok) {
|
||||
throw new Error(`오류 발생: ${response.status}`);
|
||||
}
|
||||
const res = await response.json()
|
||||
return res;
|
||||
}
|
||||
|
||||
export const getFetchAreaList = async (url: string) => {
|
||||
const response = await fetch(url , {
|
||||
method: "GET",
|
||||
headers: {
|
||||
accept: "application/json",
|
||||
}
|
||||
});
|
||||
if(!response.ok) {
|
||||
throw new Error(`오류 발생: ${response.status}`);
|
||||
}
|
||||
const res = await response.json()
|
||||
return res;
|
||||
}
|
||||
|
||||
export const postFetch = async (part : string, url: string, params: unknown) => {
|
||||
let reqUrl = "";
|
||||
reqUrl = part === "fo" ? DEV_URL_FO+url : DEV_URL_COMMON+url;
|
||||
const response = await fetch(reqUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
if(!response.ok) {
|
||||
throw new Error(`오류 발생: ${response.status}`);
|
||||
}
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
export const putFetch = async (part : string, url: string, params: unknown) => {
|
||||
let reqUrl = "";
|
||||
reqUrl = part === "fo" ? DEV_URL_FO+url : DEV_URL_COMMON+url;
|
||||
const response = await fetch(reqUrl, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
if(!response.ok) {
|
||||
throw new Error(`오류 발생: ${response.status}`);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
export const deleteFetch = async (part : string, url: string, params: unknown) => {
|
||||
let reqUrl = "";
|
||||
reqUrl = part === "fo" ? DEV_URL_FO+url : DEV_URL_COMMON+url;
|
||||
const response = await fetch(reqUrl, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
if(!response.ok) {
|
||||
throw new Error(`오류 발생: ${response.status}`);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
type DataFormProps = {
|
||||
type: string;
|
||||
column: string;
|
||||
item: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export default function DataForm({ type, column, item }: DataFormProps) {
|
||||
if(item) {
|
||||
const value = item[column];
|
||||
switch(type){
|
||||
case 'date':
|
||||
if(value && typeof value === 'string' && value.length >= 8)
|
||||
item[column] = value.substring(0, 4) + "-" + value.substring(4, 6) + "-" + value.substring(6, 8);
|
||||
break;
|
||||
case 'number':
|
||||
if(value && value != '') {
|
||||
item[column] = value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
break;
|
||||
case 'float1':
|
||||
if(value) {
|
||||
item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 10) / 10).split('.').map((part, index) =>
|
||||
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
|
||||
).join('.')
|
||||
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
break;
|
||||
case 'float2':
|
||||
if(value) {
|
||||
item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 100) / 100).split('.').map((part, index) =>
|
||||
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
|
||||
).join('.')
|
||||
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
break;
|
||||
case 'float3':
|
||||
if(value) {
|
||||
item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 1000) / 1000).split('.').map((part, index) =>
|
||||
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
|
||||
).join('.')
|
||||
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,279 +0,0 @@
|
||||
import { useFoStore } from '@/app/store';
|
||||
import { DatePickerRange, SelectBox } from '@common/business_components/ui';
|
||||
import ListDiv from '@common/business_components/ui/list_div';
|
||||
import { Table, TableCell, TableHead, TableRow } from '@common/components/ui';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
type FacilityTermModalHeaderProps<T extends { msrDt: string }> = {
|
||||
fcltyCd : string;
|
||||
fcltyName: string;
|
||||
tabName: string;
|
||||
searchYear: string;
|
||||
searchList: T[];
|
||||
ref: React.RefObject<ReturnType<T>>;
|
||||
queryClick:(returnType:ReturnType<T>) => void;
|
||||
}
|
||||
|
||||
export type ReturnType<T> = {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
tabName: string;
|
||||
filteredList: T[];
|
||||
}
|
||||
|
||||
export default function FacilityTermModalHeader<T extends { msrDt: string }>({
|
||||
searchList,
|
||||
fcltyName,
|
||||
tabName,
|
||||
searchYear,
|
||||
queryClick,
|
||||
ref
|
||||
}: FacilityTermModalHeaderProps<T & { msrDt: string }>) {
|
||||
const {Common} = useFoStore((state) => state);
|
||||
const { selectFlowPanel } = Common;
|
||||
const [startDate, setStartDate] = useState<Date>(new Date(Number(searchYear), 0, 1));
|
||||
const [endDate, setEndDate] = useState<Date>(new Date(Number(searchYear), 11, 31));
|
||||
const startPickerRef = useRef<HTMLDivElement>(null);
|
||||
const endPickerRef = useRef<HTMLDivElement>(null);
|
||||
const [flowPanel, setFlowPanel] = useState<string>(selectFlowPanel[0]?.val ?? '00');
|
||||
const [copySearchList, setCopySearchList] = useState<T[]>(searchList);
|
||||
const [standSearchList, setStandSearchList] = useState<T[]>(searchList);
|
||||
|
||||
const isDateInRanges = (date: Date) => {
|
||||
const standYear = parseInt(searchYear);
|
||||
const dateRanges:{start:Date, end:Date}[] = [];
|
||||
|
||||
if (tabName.includes("_summer")) {
|
||||
dateRanges.push({
|
||||
start: new Date(standYear, 5, 1),
|
||||
end: new Date(standYear, 7, 31)
|
||||
});
|
||||
} else if (tabName.includes("_winter")) {
|
||||
dateRanges.push({
|
||||
start: new Date(standYear, 0, 1),
|
||||
end: new Date(standYear, 1, 28)
|
||||
});
|
||||
} else {
|
||||
dateRanges.push({
|
||||
start: new Date(standYear, 0, 1),
|
||||
end: new Date(standYear, 11, 31)
|
||||
});
|
||||
}
|
||||
|
||||
return dateRanges.some(range => {
|
||||
const start = new Date(range.start);
|
||||
const end = new Date(range.end);
|
||||
return date >= start && date <= end;
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let startDate = new Date(Number(searchYear), 0, 1);
|
||||
let endDate = new Date(Number(searchYear), 11, 31);
|
||||
|
||||
if(tabName.includes("_summer")) {
|
||||
startDate = new Date(Number(searchYear), 5, 1);
|
||||
endDate = new Date(Number(searchYear), 7, 31);
|
||||
setStartDate(startDate);
|
||||
setEndDate(endDate);
|
||||
} else if (tabName.includes("_winter")) {
|
||||
startDate = new Date(Number(searchYear), 0, 1);
|
||||
endDate = new Date(Number(searchYear), 1, 28);
|
||||
setStartDate(startDate);
|
||||
setEndDate(endDate);
|
||||
} else {
|
||||
startDate = new Date(Number(searchYear), 0, 1);
|
||||
endDate = new Date(Number(searchYear), 11, 31);
|
||||
setStartDate(startDate);
|
||||
setEndDate(endDate);
|
||||
}
|
||||
|
||||
let filteredData: T[] = [];
|
||||
|
||||
if(tabName.includes("_rain")) {
|
||||
filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
const rainEffectDay = (item as T & { rainEffectDay: number }).rainEffectDay;
|
||||
if(flowPanel === '1') {
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay>0 && infoRnDay < 3;
|
||||
} else if(flowPanel === '2'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 3 && infoRnDay < 10;
|
||||
} else if(flowPanel === '3'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 10 && infoRnDay < 20;
|
||||
} else if(flowPanel === '4'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 20 && infoRnDay < 30;
|
||||
} else if(flowPanel === '5'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 30 && infoRnDay < 40;
|
||||
} else if(flowPanel === '6'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 40 && infoRnDay < 50;
|
||||
} else if(flowPanel === '7'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 50 && infoRnDay < 60;
|
||||
} else if(flowPanel === '8'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 60;
|
||||
} else {
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && (infoRnDay>0 || rainEffectDay ===1);
|
||||
}
|
||||
});
|
||||
} else if(tabName.includes("_chuncheon")) {
|
||||
filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay==0;
|
||||
});
|
||||
} else {
|
||||
filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
|
||||
});
|
||||
}
|
||||
|
||||
setCopySearchList(filteredData);
|
||||
setStandSearchList(filteredData);
|
||||
}, [searchList, searchYear, tabName, flowPanel]);
|
||||
|
||||
const handleStartDateSelect = (day: Date | undefined) => {
|
||||
if(day && day > endDate) {
|
||||
alert('종료일은 시작일 이전일 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedDate = day ?? startDate;
|
||||
setStartDate(selectedDate);
|
||||
const button = startPickerRef.current?.querySelector('button');
|
||||
if (button) {
|
||||
setTimeout(() => button.click(), 0);
|
||||
}
|
||||
|
||||
const filteredData = standSearchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
|
||||
});
|
||||
setCopySearchList(filteredData);
|
||||
};
|
||||
|
||||
const handleEndDateSelect = (day: Date | undefined) => {
|
||||
if(day && day < startDate) {
|
||||
alert('종료일은 시작일 이후일 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedDate = day ?? endDate;
|
||||
setEndDate(selectedDate);
|
||||
const button = endPickerRef.current?.querySelector('button');
|
||||
if (button) {
|
||||
setTimeout(() => button.click(), 0);
|
||||
}
|
||||
|
||||
const filteredData = standSearchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate());
|
||||
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
|
||||
});
|
||||
setCopySearchList(filteredData);
|
||||
};
|
||||
|
||||
const fncSetFilteredList = useCallback(() => {
|
||||
queryClick({
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
tabName: tabName,
|
||||
filteredList: copySearchList
|
||||
});
|
||||
}, [queryClick, startDate, endDate, tabName, copySearchList]);
|
||||
|
||||
useEffect(() => {
|
||||
fncSetFilteredList();
|
||||
}, [fncSetFilteredList]);
|
||||
|
||||
useEffect(() => {
|
||||
if(ref && ref.current) {
|
||||
const customRef = ref.current;
|
||||
customRef.startDate = startDate;
|
||||
customRef.endDate = endDate;
|
||||
customRef.tabName = tabName;
|
||||
customRef.filteredList = copySearchList;
|
||||
}
|
||||
}, [startDate, endDate, tabName, copySearchList, ref]);
|
||||
|
||||
return (
|
||||
<ListDiv className="!h-[80px]">
|
||||
<div className="!m-[0.5rem] max-h-[40rem] overflow-auto">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow className="!h-[20px]">
|
||||
<TableHead className="w-[120px]">{'시설명'}</TableHead>
|
||||
{tabName === "tab_term_rain" ? <TableCell className="w-[300px]">{fcltyName}</TableCell> :
|
||||
<TableCell className="w-[380px]">{fcltyName}</TableCell>}
|
||||
{tabName === "tab_term_rain" && (
|
||||
<>
|
||||
<TableHead className="w-[120px]">{'강수구분'}</TableHead>
|
||||
<TableCell className="w-[250px]">
|
||||
<div className="justify-center">
|
||||
<SelectBox
|
||||
selectArray={selectFlowPanel}
|
||||
value={flowPanel}
|
||||
onSelectValue={(val) => setFlowPanel(val.toString())}
|
||||
className="mx-3 w-[150px]"
|
||||
label=""
|
||||
selectClass="w-full p-1 border rounded bg-white"
|
||||
/>
|
||||
</div>
|
||||
</TableCell>
|
||||
</>
|
||||
)}
|
||||
<TableHead className="w-[120px]">{'년/월'}</TableHead>
|
||||
<TableCell className="">
|
||||
<div className="flex">
|
||||
<div ref={startPickerRef} className="flex justify-center">
|
||||
<DatePickerRange
|
||||
mode="single"
|
||||
selected={startDate}
|
||||
onSelect={(date) => handleStartDateSelect(date as Date)}
|
||||
className="w-full p-1 border rounded bg-white"
|
||||
disabled={(date) => !isDateInRanges(date)}
|
||||
defaultMonth={startDate}
|
||||
/>
|
||||
</div>
|
||||
<h3 className="justify-center px-5">~</h3>
|
||||
<div ref={endPickerRef} className="flex justify-center">
|
||||
<DatePickerRange
|
||||
mode="single"
|
||||
selected={endDate}
|
||||
onSelect={(date) => handleEndDateSelect(date as Date)}
|
||||
className="w-full p-1 border rounded bg-white"
|
||||
disabled={(date) => !isDateInRanges(date)}
|
||||
defaultMonth={endDate}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
);
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
import { useFoStore } from '@/app/store';
|
||||
import { SelectBox } from '@common/business_components/ui';
|
||||
import ListDiv from '@common/business_components/ui/list_div';
|
||||
import { DatePicker, Table, TableCell, TableHead, TableRow } from '@common/components/ui';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
type FacilityTermModalHeaderProps<T extends { msrDt: string }> = {
|
||||
fcltyCd : string;
|
||||
fcltyName: string;
|
||||
tabName: string;
|
||||
searchYear: string;
|
||||
searchList: T[];
|
||||
ref: React.RefObject<ReturnType<T>>;
|
||||
queryClick:(returnType:ReturnType<T>) => void;
|
||||
}
|
||||
|
||||
export type ReturnType<T> = {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
tabName: string;
|
||||
filteredList: T[];
|
||||
}
|
||||
|
||||
export default function FacilityTermModalHeaderMonth<T extends { msrDt: string }>({
|
||||
searchList,
|
||||
fcltyName,
|
||||
tabName,
|
||||
searchYear,
|
||||
queryClick,
|
||||
ref
|
||||
}: FacilityTermModalHeaderProps<T & { msrDt: string }>) {
|
||||
const {Common} = useFoStore((state) => state);
|
||||
const { selectFlowPanel } = Common;
|
||||
const [startDate, setStartDate] = useState<Date>(new Date(Number(searchYear), 0, 1));
|
||||
const [endDate, setEndDate] = useState<Date>(new Date(Number(searchYear), 11, 31));
|
||||
const startPickerRef = useRef<HTMLDivElement>(null);
|
||||
const endPickerRef = useRef<HTMLDivElement>(null);
|
||||
const [flowPanel, setFlowPanel] = useState<string>(selectFlowPanel[0]?.val ?? '00');
|
||||
const [copySearchList, setCopySearchList] = useState<T[]>(searchList);
|
||||
|
||||
/* const isDateInRanges = (date: Date) => {
|
||||
const standYear = parseInt(searchYear);
|
||||
const dateRanges = [];
|
||||
|
||||
if (tabName.includes("_summer")) {
|
||||
dateRanges.push({
|
||||
start: new Date(standYear, 5, 1),
|
||||
end: new Date(standYear, 7, 31)
|
||||
});
|
||||
} else if (tabName.includes("_winter")) {
|
||||
dateRanges.push({
|
||||
start: new Date(standYear, 0, 1),
|
||||
end: new Date(standYear, 1, 28)
|
||||
});
|
||||
} else {
|
||||
dateRanges.push({
|
||||
start: new Date(standYear, 0, 1),
|
||||
end: new Date(standYear, 11, 31)
|
||||
});
|
||||
}
|
||||
|
||||
return dateRanges.some(range => {
|
||||
const start = new Date(range.start);
|
||||
const end = new Date(range.end);
|
||||
return date >= start && date <= end;
|
||||
});
|
||||
}; */
|
||||
|
||||
useEffect(() => {
|
||||
let startDate = new Date(Number(searchYear), 0, 1);
|
||||
let endDate = new Date(Number(searchYear), 11, 31);
|
||||
|
||||
if(tabName.includes("_summer")) {
|
||||
startDate = new Date(Number(searchYear), 5, 1);
|
||||
endDate = new Date(Number(searchYear), 7, 31);
|
||||
setStartDate(startDate);
|
||||
setEndDate(endDate);
|
||||
} else if (tabName.includes("_winter")) {
|
||||
startDate = new Date(Number(searchYear), 0, 1);
|
||||
endDate = new Date(Number(searchYear), 1, 28);
|
||||
setStartDate(startDate);
|
||||
setEndDate(endDate);
|
||||
} else {
|
||||
startDate = new Date(Number(searchYear), 0, 1);
|
||||
endDate = new Date(Number(searchYear), 11, 31);
|
||||
setStartDate(startDate);
|
||||
setEndDate(endDate);
|
||||
}
|
||||
|
||||
let filteredData: T[] = [];
|
||||
|
||||
if(tabName.includes("_rain")) {
|
||||
filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
const rainEffectDay = (item as T & { rainEffectDay: number }).rainEffectDay;
|
||||
|
||||
if(flowPanel === '1') {
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay>0 && infoRnDay < 3;
|
||||
} else if(flowPanel === '2'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 3 && infoRnDay < 10;
|
||||
} else if(flowPanel === '3'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 10 && infoRnDay < 20;
|
||||
} else if(flowPanel === '4'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 20 && infoRnDay < 30;
|
||||
} else if(flowPanel === '5'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 30 && infoRnDay < 40;
|
||||
} else if(flowPanel === '6'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 40 && infoRnDay < 50;
|
||||
} else if(flowPanel === '7'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 50 && infoRnDay < 60;
|
||||
} else if(flowPanel === '8'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 60;
|
||||
} else {
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && (infoRnDay>0 || rainEffectDay ===1);
|
||||
}
|
||||
});
|
||||
} else if(tabName.includes("_chuncheon")) {
|
||||
filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay==0;
|
||||
});
|
||||
} else {
|
||||
filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
|
||||
});
|
||||
}
|
||||
|
||||
setCopySearchList(filteredData);
|
||||
}, [searchList, searchYear, tabName, flowPanel]);
|
||||
|
||||
const handleStartDateSelect = (day: Date | undefined) => {
|
||||
if(day && day > endDate) {
|
||||
alert('종료일은 시작일 이전일 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedDate = day ?? startDate;
|
||||
setStartDate(selectedDate);
|
||||
const button = startPickerRef.current?.querySelector('button');
|
||||
if (button) {
|
||||
setTimeout(() => button.click(), 0);
|
||||
}
|
||||
|
||||
const filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
|
||||
});
|
||||
setCopySearchList(filteredData);
|
||||
};
|
||||
|
||||
const handleEndDateSelect = (day: Date | undefined) => {
|
||||
if(day && day < startDate) {
|
||||
alert('종료일은 시작일 이후일 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedDate = day ?? endDate;
|
||||
setEndDate(selectedDate);
|
||||
const button = endPickerRef.current?.querySelector('button');
|
||||
if (button) {
|
||||
setTimeout(() => button.click(), 0);
|
||||
}
|
||||
|
||||
const filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate());
|
||||
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
|
||||
});
|
||||
setCopySearchList(filteredData);
|
||||
};
|
||||
|
||||
const fncSetFilteredList = useCallback(() => {
|
||||
queryClick({
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
tabName: tabName,
|
||||
filteredList: copySearchList
|
||||
});
|
||||
}, [queryClick, startDate, endDate, tabName, copySearchList]);
|
||||
|
||||
useEffect(() => {
|
||||
fncSetFilteredList();
|
||||
}, [fncSetFilteredList]);
|
||||
|
||||
useEffect(() => {
|
||||
if(ref && ref.current) {
|
||||
const customRef = ref.current;
|
||||
customRef.startDate = startDate;
|
||||
customRef.endDate = endDate;
|
||||
customRef.tabName = tabName;
|
||||
customRef.filteredList = copySearchList;
|
||||
}
|
||||
}, [startDate, endDate, tabName, copySearchList, ref]);
|
||||
|
||||
return (
|
||||
<ListDiv className="!h-[100px]">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow>
|
||||
<TableHead className="w-[120px]">{'시설명'}</TableHead>
|
||||
{tabName === "tab_term_rain" ? <TableCell className="w-[300px]">{fcltyName}</TableCell> :
|
||||
<TableCell className="w-[380px]">{fcltyName}</TableCell>}
|
||||
{tabName === "tab_term_rain" && (
|
||||
<>
|
||||
<TableHead className="w-[120px]">{'강수구분'}</TableHead>
|
||||
<TableCell className="w-[250px]">
|
||||
<div className="justify-center">
|
||||
<SelectBox
|
||||
selectArray={selectFlowPanel}
|
||||
value={flowPanel}
|
||||
onSelectValue={(val) => setFlowPanel(val.toString())}
|
||||
className="mx-3 w-[150px]"
|
||||
label=""
|
||||
selectClass="w-full p-1 border rounded bg-white"
|
||||
/>
|
||||
</div>
|
||||
</TableCell>
|
||||
</>
|
||||
)}
|
||||
<TableHead className="w-[120px]">{'년/월'}</TableHead>
|
||||
<TableCell className="">
|
||||
<div className="flex">
|
||||
<div ref={startPickerRef} className="flex justify-center">
|
||||
<DatePicker
|
||||
mode="single"
|
||||
selected={startDate}
|
||||
onSelect={(date) => handleStartDateSelect(date as Date)}
|
||||
className="w-full p-1 border rounded bg-white"
|
||||
defaultMonth={startDate}
|
||||
/>
|
||||
</div>
|
||||
<h3 className="justify-center px-5">~</h3>
|
||||
<div ref={endPickerRef} className="flex justify-center">
|
||||
<DatePicker
|
||||
mode="single"
|
||||
selected={endDate}
|
||||
onSelect={(date) => handleEndDateSelect(date as Date)}
|
||||
className="w-full p-1 border rounded bg-white"
|
||||
defaultMonth={endDate}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
);
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import { TableHead, TableRow } from "@common/components/ui";
|
||||
import type { TableUpperProps } from "../../store/dashboard";
|
||||
|
||||
const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProps[], layoutNum: string }) => {
|
||||
return (
|
||||
layoutNum === 'A' ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={2} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={2}>{'행정구역'}</TableHead> :
|
||||
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 'R' ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={2} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={3}>{'유역'}</TableHead> :
|
||||
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={2} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.upName === 'upChangeRe1' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={3}>{'권역'}</TableHead> :
|
||||
head.upName === 'upChangeRe2' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={2}>{'행정구역'}</TableHead> :
|
||||
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export { HeadMakeColSpan };
|
||||
@@ -1,108 +0,0 @@
|
||||
import { useFoStore } from '@/app/store';
|
||||
import type { facilityListProps } from '@/app/store/processFacility';
|
||||
import { Label } from '@common/components/ui';
|
||||
import React, { useEffect, useState, useRef, useCallback } from 'react'
|
||||
|
||||
type thisProps = {
|
||||
label: string | undefined;
|
||||
setValue : (fcltyCd?: string, fcltyNm?: string, fcltyCpc?: number | '', trtFrfNm?: string | '', efflWqltStndrdNm?: string | '') => void;
|
||||
sidoSigun? : string | undefined;
|
||||
fcltyName? : string | undefined;
|
||||
}
|
||||
|
||||
export default function SearchInputText({label=undefined, setValue=()=>{}, sidoSigun=undefined, fcltyName=undefined} :thisProps) {
|
||||
|
||||
const { ProcessFacilityList, searchProcessFacilitySearching } = useFoStore((state) => state);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [textValue, setTextValue] = useState(fcltyName || '');
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
const processFacilityList = ProcessFacilityList?.processFacilityList || [];
|
||||
|
||||
const handleInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
setTextValue(value);
|
||||
if (value) {
|
||||
setIsOpen(true);
|
||||
if(sidoSigun) {
|
||||
searchProcessFacilitySearching(1, 4999, 'A', sidoSigun, '0', '0', '0', value);
|
||||
} else {
|
||||
searchProcessFacilitySearching(1, 4999, '0', '0', '0', '0', '0', value);
|
||||
}
|
||||
} else {
|
||||
setIsOpen(false);
|
||||
}
|
||||
}, [searchProcessFacilitySearching, sidoSigun]);
|
||||
|
||||
const onInputFocus = useCallback(() => {
|
||||
setIsOpen(true);
|
||||
if(sidoSigun) {
|
||||
searchProcessFacilitySearching(1, 4999, 'A', sidoSigun, '0', '0', '0');
|
||||
} else {
|
||||
searchProcessFacilitySearching(1, 4999, '0', '0', '0', '0', '0');
|
||||
}
|
||||
}, [searchProcessFacilitySearching, sidoSigun]);
|
||||
|
||||
useEffect(() => {
|
||||
setTextValue(fcltyName || '');
|
||||
}, [fcltyName]);
|
||||
|
||||
const handleSuggestionClick = useCallback((bscFctCd: string, bscFctNm: string, fctCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | '') => {
|
||||
console.log('bscFctNm : ', bscFctNm);
|
||||
console.log('bscFctCd : ', bscFctCd);
|
||||
console.log('fctCpc : ', fctCpc);
|
||||
console.log('trtFrfNm : ', trtFrfNm);
|
||||
console.log('efflWqltStndrdNm : ', efflWqltStndrdNm);
|
||||
setTextValue(bscFctNm);
|
||||
setValue(bscFctCd, bscFctNm, fctCpc, trtFrfNm, efflWqltStndrdNm);
|
||||
setIsOpen(false);
|
||||
}, [setValue]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={'relative'} ref={wrapperRef}>
|
||||
{label && <Label className="w-20 text-xl text-gray-600 justify-self-center">{label}</Label>}
|
||||
<input
|
||||
type="text"
|
||||
value={textValue}
|
||||
onChange={handleInputChange}
|
||||
onFocus={onInputFocus}
|
||||
className="w-[200px] ml-6 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder={`${label}을(를) 입력하세요`}
|
||||
/>
|
||||
{isOpen && processFacilityList.length > 0 && (
|
||||
<div className="absolute z-10 w-[300px] px-2 py-1 !mt-5 ml-20 bg-white border border-gray-300 rounded-md shadow-lg h-90 overflow-auto">
|
||||
<div className="max-h-72">
|
||||
{processFacilityList.map((item : facilityListProps, index : number) => (
|
||||
<div
|
||||
key={index}
|
||||
className="w-full text-left pl-1 pr-10 py-2 hover:bg-gray-100 cursor-pointer overflow-auto"
|
||||
onClick={() => handleSuggestionClick(item.bscFctCd, item.bscFctNm, Number(item.fctCpc), item.trtFrfNm, item.efflWqltStndrdNm)}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
handleSuggestionClick(item.bscFctCd, item.bscFctNm, Number(item.fctCpc), item.trtFrfNm, item.efflWqltStndrdNm);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{item.sido} {item.gugun} <span className="float-right">{item.bscFctNm}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
@@ -1,7 +0,0 @@
|
||||
@import "../../../packages/common/components/src/base.css";
|
||||
|
||||
html,
|
||||
body {
|
||||
font-family: "Noto Sans KR", sans-serif;
|
||||
font-size: 10px;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
"use client"
|
||||
import { BaseLayout } from "@common/components/ui";
|
||||
import "./globals.css";
|
||||
import { StoreProvider } from "./store";
|
||||
|
||||
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<StoreProvider>
|
||||
<BaseLayout>
|
||||
{children}
|
||||
</BaseLayout>
|
||||
</StoreProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import Link from "next/link";
|
||||
import { Button } from "@common/components/ui";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="grid grid-cols-12 gap-2">
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/processFacility"}><Button>처리시설 시설정보</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/flowRate"}><Button>시설별 유량현황</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/dashboard"}><Button>대시보드</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/processArea"}><Button>처리구역정보</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/facilityPrecipitation"}><Button>시설별 강수현황</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/facilityWaterQlty"}><Button>시설별 수질현황</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/planSewage"}><Button>계획하수량 산정지표 현황</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/sewageOccur"}><Button>오수발생량 추정</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/underWaterInput"}><Button>지하수 유입량 추정</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/rdi"}><Button>RDII 조회</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/map"}><Button>지도보기</Button></Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useFoStore } from '@/app/store';
|
||||
import type { DrainageEquipmentListProps, TableUpperProps } from '@/app/store/dashboard';
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@common/components';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export type DrainageEquipmentProps = {
|
||||
searchYear?: string;
|
||||
fcltyList?: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string, efflWqltStndrdNm: string }[];
|
||||
};
|
||||
|
||||
export default function DrainageEquipment({searchYear = '', fcltyList = []}: DrainageEquipmentProps) {
|
||||
|
||||
const {
|
||||
Common,
|
||||
DrainageEquipment,
|
||||
searchDrainageEquipment,
|
||||
} = useFoStore((state) => state);
|
||||
|
||||
const {
|
||||
isInit,
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
upHeadListDrainageEquipment,
|
||||
drainageEquipmentList,
|
||||
} = DrainageEquipment;
|
||||
|
||||
const [hasSearched, setHasSearched] = useState(false);
|
||||
// 이전 시설코드 저장
|
||||
const [prevFacilityCode, setPrevFacilityCode] = useState<string>('');
|
||||
|
||||
const tableData = fcltyList;
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit && tableData[0]?.bscFctCd && (tableData[0].bscFctCd !== prevFacilityCode || !hasSearched)) {
|
||||
searchDrainageEquipment(searchYear, tableData[0].bscFctCd, false);
|
||||
setHasSearched(true);
|
||||
setPrevFacilityCode(tableData[0].bscFctCd);
|
||||
}
|
||||
}, [fcltyList, isInit, searchDrainageEquipment, searchYear, tableData, hasSearched, prevFacilityCode]);
|
||||
|
||||
// 연도가 바뀌면 hasSearched를 false로 리셋
|
||||
useEffect(() => {
|
||||
setHasSearched(false);
|
||||
}, [searchYear]);
|
||||
|
||||
// 시설계획 table header 변경
|
||||
const HeadMakeColSpan = ({ upHeadList }: { upHeadList: TableUpperProps[] }) => {
|
||||
return (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'part1' ? <TableHead rowSpan={3} className='w-60' key={head.id}>구분</TableHead> :
|
||||
head.id === 'part2' ? <TableHead rowSpan={3} className='w-60' key={head.id}>구분</TableHead> :
|
||||
head.id == 'nowSum' ? <TableHead rowSpan={2} colSpan={3} key={head.id} style={{ whiteSpace: 'pre-line' }}>{'현재\n(기준년도)'}</TableHead> :
|
||||
head.id == 'stepOneSum' ? <TableHead rowSpan={1} colSpan={12} key={head.id} style={{ whiteSpace: 'pre-line' }}>{'변경(금회계획)'}</TableHead> :
|
||||
head.id == 'etc' ? <TableHead rowSpan={3} key={head.id}>비고</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'stepOneSum' ? <TableHead rowSpan={1} colSpan={3} key={head.id}>1단계</TableHead> :
|
||||
head.id === 'stepTwoSum' ? <TableHead rowSpan={1} colSpan={3} key={head.id}>2단계</TableHead> :
|
||||
head.id === 'stepThreeSum' ? <TableHead rowSpan={1} colSpan={3} key={head.id}>3단계</TableHead> :
|
||||
head.id === 'stepFourSum' ? <TableHead rowSpan={1} colSpan={3} key={head.id}>4단계</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe2' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4' || head.upName === 'upChangeRe5' || head.upName === 'upChangeRe6') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const upHeadList = HeadMakeColSpan({upHeadList:upHeadListDrainageEquipment});
|
||||
return (
|
||||
<div className="overflow-x-auto">
|
||||
<Table variant="secondary" className='w-[130%]'>
|
||||
<TableHeader>
|
||||
{upHeadList}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{drainageEquipmentList.map((el: DrainageEquipmentListProps, index) => (
|
||||
<TableRow key={index+"row"}>
|
||||
{upHeadListDrainageEquipment.map((head) => (
|
||||
(head.id==='nowSum')?
|
||||
<TableCell className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{333}</TableCell>
|
||||
:<TableCell className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id as keyof DrainageEquipmentListProps]}</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
"use client"
|
||||
import type { OperationalStatusListProps } from "@/app/store/dashboard";
|
||||
import { CHART_FORM, MainChart, type ChartConfig } from "@common/business_components";
|
||||
import { Button } from "@common/business_components/ui/table/lib/button";
|
||||
import html2canvas from "html2canvas";
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
|
||||
type yearProps = {
|
||||
label: string;
|
||||
평균 : number | string | '';
|
||||
최대 : number | string | '';
|
||||
최소 : number | string | '';
|
||||
}
|
||||
|
||||
type summerProps = {
|
||||
전기간 : number | string | '';
|
||||
강우일3mm이상 : number | string | '';
|
||||
비강우시 : number | string | '';
|
||||
}
|
||||
|
||||
type winterProps = {
|
||||
전기간 : number | string | '';
|
||||
청천시최대 : number | string | '';
|
||||
청천시평균 : number | string | '';
|
||||
청천시최소 : number | string | '';
|
||||
}
|
||||
|
||||
type dashBoardChartModalProps = {
|
||||
title : string;
|
||||
item : string;
|
||||
period : string;
|
||||
modalData : OperationalStatusListProps[];
|
||||
waterQlty : string;
|
||||
}
|
||||
|
||||
export default function DashBoardChartModal({item='', period='', title='',modalData=[], waterQlty=''} : dashBoardChartModalProps) {
|
||||
|
||||
const [chartData, setChartData] = useState<yearProps[] | summerProps[] | winterProps[]>([]);
|
||||
const [chartConfig, setChartConfig] = useState<ChartConfig>({});
|
||||
const chartRef = useRef<HTMLDivElement>(null);
|
||||
const chartOption = {
|
||||
chartForm : CHART_FORM.BAR,
|
||||
chartConfig : chartConfig,
|
||||
chartData : chartData,
|
||||
chartTitle : title,
|
||||
chartClassName : "h-[calc(100%-15%)] w-[90%] mt-5",
|
||||
graphSize : 40,
|
||||
yFieldText : item === 'flowRate' ? '유량(㎥/일)' : item === 'waterQlty' ? '수질(mg/L)' : item === 'chongin' ? '수질(mg/L)' : '',
|
||||
showLegend : true
|
||||
}
|
||||
|
||||
const handleDownload = () => {
|
||||
if (!chartRef.current) {
|
||||
return alert('결과 저장에 실패했습니다.');
|
||||
}
|
||||
html2canvas(chartRef.current).then((canvas) => {
|
||||
const link = document.createElement('a');
|
||||
document.body.appendChild(link);
|
||||
link.href = canvas.toDataURL('image/png');
|
||||
link.download = 'result.png';
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* useEffect
|
||||
*/
|
||||
useEffect(() => {
|
||||
if(period === 'year'){
|
||||
const filteredData: yearProps[] = modalData.map((item) => {
|
||||
if(waterQlty.trim().includes('T-N') || waterQlty.trim().includes('T-P')){
|
||||
return {
|
||||
label: item.waterQlty,
|
||||
평균: typeof item.yearAvg === 'string' ? Number(item.yearAvg.replace(/,/g, '')).toFixed(3) : (item.yearAvg || 0),
|
||||
최대: typeof item.yearMax === 'string' ? Number(item.yearMax.replace(/,/g, '')).toFixed(3) : (item.yearMax || 0),
|
||||
최소: typeof item.yearMin === 'string' ? Number(item.yearMin.replace(/,/g, '')).toFixed(3) : (item.yearMin || 0),
|
||||
}
|
||||
}
|
||||
else{
|
||||
return {
|
||||
label: item.waterQlty,
|
||||
평균: typeof item.yearAvg === 'string' ? Number(item.yearAvg.replace(/,/g, '')).toFixed(1) : (item.yearAvg || 0),
|
||||
최대: typeof item.yearMax === 'string' ? Number(item.yearMax.replace(/,/g, '')).toFixed(1) : (item.yearMax || 0),
|
||||
최소: typeof item.yearMin === 'string' ? Number(item.yearMin.replace(/,/g, '')).toFixed(1) : (item.yearMin || 0),
|
||||
}
|
||||
}
|
||||
})
|
||||
if (item === 'flowRate') {
|
||||
setChartData(filteredData.slice(0,5));
|
||||
} else if (item === 'waterQlty') {
|
||||
setChartData(filteredData.slice(5,11));
|
||||
} else {
|
||||
setChartData(filteredData.slice(11,13));
|
||||
}
|
||||
}
|
||||
else if (period === 'summer') {
|
||||
const filteredData: summerProps[] = modalData.map((item) => {
|
||||
if(waterQlty.trim().includes('T-N') || waterQlty.trim().includes('T-P')){
|
||||
return {
|
||||
label: item.waterQlty,
|
||||
전기간: typeof item.summerAll === 'string' ? Number(item.summerAll.replace(/,/g, '')).toFixed(3) : (item.summerAll || 0),
|
||||
강우일3mm이상: typeof item.summerThree === 'string' ? Number(item.summerThree.replace(/,/g, '')).toFixed(3) : (item.summerThree || 0),
|
||||
비강우시: typeof item.summerRain === 'string' ? Number(item.summerRain.replace(/,/g, '')).toFixed(3) : (item.summerRain || 0),
|
||||
}
|
||||
}else{
|
||||
return {
|
||||
label: item.waterQlty,
|
||||
전기간: typeof item.summerAll === 'string' ? Number(item.summerAll.replace(/,/g, '')).toFixed(1) : (item.summerAll || 0),
|
||||
강우일3mm이상: typeof item.summerThree === 'string' ? Number(item.summerThree.replace(/,/g, '')).toFixed(1) : (item.summerThree || 0),
|
||||
비강우시: typeof item.summerRain === 'string' ? Number(item.summerRain.replace(/,/g, '')).toFixed(1) : (item.summerRain || 0),
|
||||
}
|
||||
}
|
||||
})
|
||||
if (item === 'flowRate') {
|
||||
setChartData(filteredData.slice(0,5));
|
||||
} else if (item === 'waterQlty') {
|
||||
setChartData(filteredData.slice(5,11));
|
||||
} else {
|
||||
setChartData(filteredData.slice(11,13));
|
||||
}
|
||||
}
|
||||
else if (period === 'winter') {
|
||||
const filteredData: winterProps[] = modalData.map((item) => {
|
||||
return {
|
||||
label: item.waterQlty,
|
||||
전기간: typeof item.winterAll === 'string' ? Number(item.winterAll.replace(/,/g, '')).toFixed(3) : (item.winterAll || 0),
|
||||
청천시최대: typeof item.winterSunnyMax === 'string' ? Number(item.winterSunnyMax.replace(/,/g, '')).toFixed(3) : (item.winterSunnyMax || 0),
|
||||
청천시평균: typeof item.winterSunnyAvg === 'string' ? Number(item.winterSunnyAvg.replace(/,/g, '')).toFixed(3) : (item.winterSunnyAvg || 0),
|
||||
청천시최소: typeof item.winterSunnyMin === 'string' ? Number(item.winterSunnyMin.replace(/,/g, '')).toFixed(3) : (item.winterSunnyMin || 0),
|
||||
}
|
||||
})
|
||||
setChartData(filteredData);
|
||||
|
||||
if (item === 'flowRate') {
|
||||
setChartData(filteredData.slice(0,5));
|
||||
} else if (item === 'waterQlty') {
|
||||
setChartData(filteredData.slice(5,11));
|
||||
} else {
|
||||
setChartData(filteredData.slice(11,13));
|
||||
}
|
||||
} else {
|
||||
setChartData([]);
|
||||
}
|
||||
}, [item, modalData, period, waterQlty]);
|
||||
|
||||
useEffect(() => {
|
||||
const newChartConfig = chartData.reduce((config, element) => {
|
||||
const label = 'label' in element ? element.label : '';
|
||||
if (label) {
|
||||
config[label] = {
|
||||
label: label,
|
||||
color : "hsl(var(--chart-1))"
|
||||
};
|
||||
}
|
||||
return config;
|
||||
}, {} as Record<string, { label: string; color: string; }>) satisfies ChartConfig;
|
||||
setChartConfig(newChartConfig);
|
||||
}, [chartData]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex justify-end">
|
||||
<span className="text-[13px] font-bold mt-2 w-[260px] h-[30px] -mb-9">
|
||||
(하절기 : 6/1~8/31 동절기 : 1/1~2/28)
|
||||
</span>
|
||||
<Button className="text-[13px] w-[80px] h-[30px] -mb-9 mr-20" onClick={handleDownload}>캡처</Button>
|
||||
</div>
|
||||
<div ref={chartRef}>
|
||||
<MainChart
|
||||
chartForm={chartOption.chartForm}
|
||||
chartConfig={chartOption.chartConfig}
|
||||
chartData={chartOption.chartData}
|
||||
chartTitle={chartOption.chartTitle}
|
||||
chartClassName={chartOption.chartClassName}
|
||||
graphSize={chartOption.graphSize}
|
||||
yFieldText={chartOption.yFieldText}
|
||||
showLegend={chartOption.showLegend}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/processFacility";
|
||||
import { ContentsDiv, UiModal, UiTable } from "@common/business_components";
|
||||
import { cn, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components";
|
||||
import { useEffect, useState } from "react";
|
||||
import DashBoardChartModal from "./modal/page";
|
||||
|
||||
export type facilityInfoProps = {
|
||||
searchYear?: string;
|
||||
fcltyList?: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string, efflWqltStndrdNm: string }[];
|
||||
};
|
||||
|
||||
// 시설계획 table header 변경
|
||||
const headMakeColSpanPlanFclty = (upHeadList: TableUpperProps[], planYearList: string[]) => {
|
||||
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={7} style={{ whiteSpace: 'pre-line' }}>{'시설계획\n(금회)'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
{upHeadList.map((head: TableUpperProps, index: number) =>
|
||||
(head.upName === 'upChangeRe'?<TableHead key={head.id} style={{ whiteSpace: 'pre-line' }}>{index===0?head.title:head.title+'\n('+planYearList[index-1]+')'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
</> )
|
||||
}
|
||||
|
||||
// 시설계획 table header 변경
|
||||
const headMakeColSpanOperationStatus = (upHeadList: TableUpperProps[], searchYear: string) => {
|
||||
return ( <>
|
||||
<TableRow>
|
||||
<TableHead rowSpan={1} colSpan={16} style={{ whiteSpace: 'pre-line' }}>{searchYear+'년도 운영실태'}</TableHead>
|
||||
</TableRow>
|
||||
<TableRow>{
|
||||
upHeadList.map((head: TableUpperProps) =>
|
||||
(head.upName === 'upChangeRe1'&&head.upSequnce===1?<TableHead key={head.id} rowSpan={2}colSpan={2} style={{ whiteSpace: 'pre-line' }}>{head.title}</TableHead>:
|
||||
!head.upSequnce?<TableHead rowSpan={2}key={head.id}>{head.title}</TableHead>:
|
||||
head.upName === 'upChangeRe2'&&head.upSequnce===1?<TableHead key={head.id} colSpan={3} style={{ whiteSpace: 'pre-line' }}>{'연간 운영실태'}</TableHead>:
|
||||
head.upName === 'upChangeRe3'&&head.upSequnce===1?<TableHead key={head.id} colSpan={3} style={{ whiteSpace: 'pre-line' }}>{'하절기 운영실태\n(6~8월)'}</TableHead>:
|
||||
head.upName === 'upChangeRe4'&&head.upSequnce===1?<TableHead key={head.id} colSpan={4} style={{ whiteSpace: 'pre-line' }}>{'동절기 운영실태\n(1~2월)'}</TableHead>:
|
||||
head.upName === 'upChangeRe5'&&head.upSequnce===1?<TableHead key={head.id} colSpan={3} style={{ whiteSpace: 'pre-line' }}>{'지하수유입량'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.upName === 'upChangeRe2'||head.upName === 'upChangeRe3'||head.upName === 'upChangeRe4'||head.upName === 'upChangeRe5' ?<TableHead key={head.id}>{head.title}</TableHead>:null))}
|
||||
</TableRow>
|
||||
</> )
|
||||
}
|
||||
|
||||
export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}: facilityInfoProps & { onFacilityChange: (facility: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string, efflWqltStndrdNm: string }) => void }) {
|
||||
// 입력값 상태 관리
|
||||
const {
|
||||
Common,
|
||||
FcltyMain,
|
||||
PlanFclty,
|
||||
OperationStatus,
|
||||
searchOperationStatus,
|
||||
searchPlanInfo
|
||||
} = useFoStore((state) => state);
|
||||
|
||||
const [modalItem, setModalItem] = useState<{item: string, period: string, title: string, waterQlty: string} | null>(null);
|
||||
const [hasSearched, setHasSearched] = useState(false);
|
||||
const [prevFacilityCode, setPrevFacilityCode] = useState<string>('');
|
||||
|
||||
const {
|
||||
isInit,
|
||||
} = Common;
|
||||
|
||||
// Tab1
|
||||
// fclty 관련
|
||||
const {
|
||||
upHeadListFclty,
|
||||
} = FcltyMain;
|
||||
|
||||
// 시설계획 관련
|
||||
const {
|
||||
upHeadListPlanFclty,
|
||||
planFcltyList,
|
||||
planYearList
|
||||
} = PlanFclty;
|
||||
|
||||
// 그리드 관련
|
||||
const {
|
||||
upHeadListOperationStatus,
|
||||
operationalStatusList
|
||||
} = OperationStatus;
|
||||
|
||||
const closeModal = () => {
|
||||
setModalItem(null);
|
||||
};
|
||||
|
||||
// const fcltyListArr = useMemo(() => [fcltyList], [fcltyList]);
|
||||
|
||||
const tableData = fcltyList;
|
||||
|
||||
// key 변환
|
||||
const mappedTableData = tableData.map(item => ({
|
||||
fcltyNm: item.bscFctNm,
|
||||
facilityCapacity: item.fcltyCpc,
|
||||
publicMethod: item.trtFrfNm,
|
||||
location: item.efflWqltStndrdNm,
|
||||
}));
|
||||
|
||||
const fncLoadModal = (item: string, period: string, waterQlty: string) => {
|
||||
// 유량
|
||||
if(item === 'flowRate'){
|
||||
if(period === 'year'){
|
||||
setModalItem({item: 'flowRate', period: 'year', title: '연간 유량', waterQlty: waterQlty});
|
||||
}
|
||||
else if(period === 'summer'){
|
||||
setModalItem({item: 'flowRate', period: 'summer', title: '하절기 유량', waterQlty: waterQlty});
|
||||
}
|
||||
else if(period === 'winter'){
|
||||
setModalItem({item: 'flowRate', period: 'winter', title: '동절기 유량', waterQlty: waterQlty});
|
||||
}
|
||||
}
|
||||
// 수질
|
||||
else if (item == 'waterQlty'){
|
||||
if(period === 'year'){
|
||||
setModalItem({item: 'waterQlty', period: 'year', title: '연간 수질', waterQlty: waterQlty});
|
||||
}
|
||||
else if(period === 'summer'){
|
||||
setModalItem({item: 'waterQlty', period: 'summer', title: '하절기 수질', waterQlty: waterQlty});
|
||||
}
|
||||
else if(period === 'winter'){
|
||||
setModalItem({item: 'waterQlty', period: 'winter', title: '동절기 수질', waterQlty: waterQlty});
|
||||
}
|
||||
}
|
||||
// 총인
|
||||
else {
|
||||
if(period === 'year'){
|
||||
setModalItem({item: 'chongin', period: 'year', title: '총인설비 연간 수질', waterQlty: waterQlty});
|
||||
}
|
||||
else if(period === 'summer'){
|
||||
setModalItem({item: 'chongin', period: 'summer', title: '총인설비 하절기 수질', waterQlty: waterQlty});
|
||||
}
|
||||
else if(period === 'winter'){
|
||||
setModalItem({item: 'chongin', period: 'winter', title: '총인설비 동절기 수질', waterQlty: waterQlty});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit && fcltyList[0]?.bscFctCd && (fcltyList[0].bscFctCd !== prevFacilityCode || !hasSearched)) {
|
||||
searchOperationStatus(false, searchYear, fcltyList[0].bscFctCd);
|
||||
searchPlanInfo(searchYear, fcltyList[0].bscFctCd);
|
||||
setHasSearched(true);
|
||||
setPrevFacilityCode(fcltyList[0].bscFctCd);
|
||||
planFcltyList.forEach((el: { [key: string]: string | number | boolean }, index) => {
|
||||
if (index === 6) {
|
||||
el['item'] = (Number(searchYear)-2).toString();
|
||||
el['provisionalApproval'] = Number(fcltyList[0]?.fcltyCpc)* 0.6;
|
||||
} else if (index === 7) {
|
||||
el['item'] = (Number(searchYear)-1).toString();
|
||||
el['provisionalApproval'] = Number(fcltyList[0]?.fcltyCpc)* 0.6;
|
||||
} else if (index === 8) {
|
||||
el['item'] = (Number(searchYear)-0).toString();
|
||||
el['provisionalApproval'] = Number(fcltyList[0]?.fcltyCpc)* 0.6;
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [isInit, searchOperationStatus, searchYear, fcltyList, hasSearched, prevFacilityCode, searchPlanInfo, planFcltyList]);
|
||||
// 연도가 바뀌면 hasSearched를 false로 리셋
|
||||
useEffect(() => {
|
||||
setHasSearched(false);
|
||||
}, [searchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
operationalStatusList.map((item: { [key: string]: string | number | boolean },index) => {
|
||||
if(index===8 || index===9 || index===10 || index===11 || index===12 || index===13 || index===14 || index===15){
|
||||
item['yearAvg'] = Number(item['yearAvg']).toFixed(3);
|
||||
item['yearMax'] = item['yearMax']+'%';
|
||||
item['yearMin'] = item['yearMin']+'%';
|
||||
item['summerAll'] = item['summerAll']+'%';
|
||||
item['summerThree'] = item['summerThree']+'%';
|
||||
item['summerRain'] = item['summerRain']+'%';
|
||||
item['winterAll'] = item['winterAll']+'%';
|
||||
item['winterSunnyAvg'] = item['winterSunnyAvg']+'%';
|
||||
item['winterSunnyMax'] = item['winterSunnyMax']+'%';
|
||||
item['winterSunnyMin'] = item['winterSunnyMin']+'%';
|
||||
}
|
||||
|
||||
});
|
||||
}, [operationalStatusList]);
|
||||
|
||||
const upChangeRePlanFclty = headMakeColSpanPlanFclty(upHeadListPlanFclty, planYearList);
|
||||
const upChangeHeadListOperationStatus = headMakeColSpanOperationStatus(upHeadListOperationStatus, searchYear);
|
||||
return (
|
||||
<>
|
||||
<UiTable headName={""} tableData={mappedTableData} headlist={upHeadListFclty} pageSize={0} total={0} cellClick={ undefined } onPageChange={() => { } } />
|
||||
<ContentsDiv>
|
||||
<div className="grid grid-cols-12 gap-1">
|
||||
<div className="col-span-5">
|
||||
<Table variant="secondary">
|
||||
<TableHeader>
|
||||
{upChangeRePlanFclty}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{planFcltyList.map((el: { [key: string]: string | number | boolean },index) => (
|
||||
<TableRow key={index+"row"} >
|
||||
{upHeadListPlanFclty.map((head) => (
|
||||
((index === 6 || index === 7 || index === 8) && (head.id === 'provisionalApproval' || head.id === 'stepTwo'))?
|
||||
<TableCell className="text-right" colSpan={3} style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
|
||||
:((index === 6 || index === 7 || index === 8) && (head.id === 'now' || head.id === 'stepOne' || head.id === 'stepThree' || head.id === 'stepFour'))?
|
||||
null
|
||||
:((index === 5) && (head.id === 'provisionalApproval' || head.id === 'stepTwo'))?
|
||||
<TableCell colSpan={3} className="text-center border border-[var(--border)] bg-[rgb(234,243,251)] text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
|
||||
:((index === 5) && (head.id === 'now' || head.id === 'stepOne' || head.id === 'stepThree'|| head.id === 'stepFour'))?
|
||||
null
|
||||
:(index < 5 || index > 5)&& (index!= 4) && (head.id ==='provisionalApproval'||head.id ==='now'||head.id ==='stepOne'||head.id ==='stepTwo'||head.id ==='stepThree'||head.id ==='stepFour')
|
||||
?<TableCell className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
|
||||
:(head.id === "provisionalApproval" && index === 4)
|
||||
?<TableCell colSpan={6} className="text-right border border-[var(--border)] text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{(Number(fcltyList[0]?.fcltyCpc)* 0.6).toLocaleString('en-US', { minimumFractionDigits: 1, maximumFractionDigits: 1 })} </TableCell>
|
||||
:((head.id ==='now'||head.id ==='stepOne'||head.id ==='stepTwo'||head.id ==='stepThree'||head.id ==='stepFour') && index === 4)
|
||||
?null
|
||||
:(head.id === 'item' && index != 5)?
|
||||
<TableCell className="text-center text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
|
||||
:<TableCell className="text-center border border-[var(--border)] bg-[rgb(234,243,251)] text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<div className="col-span-7 h-[600px] overflow-x-auto">
|
||||
<div className="w-[200%]">
|
||||
<Table variant="secondary">
|
||||
<TableHeader>
|
||||
{upChangeHeadListOperationStatus}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{operationalStatusList.map((el: { [key: string]: string | number | boolean },index) => (
|
||||
<TableRow key={index+"row"} >
|
||||
{upHeadListOperationStatus.map((head) => (
|
||||
(head.id === 'flowRate' && index === 0)?<TableCell rowSpan={5} className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
(head.id === 'flowRate' && index === 5)?<TableCell rowSpan={6} className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
(head.id === 'flowRate' && index === 11)?<TableCell rowSpan={2} className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
(head.id === 'groundWaterAvg'||head.id === 'groundWaterSummer'||head.id === 'groundWaterWinter')&&(index === 0)?<TableCell rowSpan={7} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
(head.id === 'groundWaterAvg'||head.id === 'groundWaterSummer'||head.id === 'groundWaterWinter')&&(index === 7)?<TableCell rowSpan={6} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
(head.id === 'rdi'&&index === 0)?<TableCell rowSpan={2} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
(head.id === 'rdi'&&index === 2)?<TableCell rowSpan={3} className={cn("sticky top-0 bg-secondary [&_tr]:border-b", "text-center" )} style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{'RDII추정시\n일강수량(mm)'}</TableCell>:
|
||||
(head.id === 'rdi'&&index === 5)?<TableCell rowSpan={2} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el['rdiRain']}</TableCell>:
|
||||
(head.id === 'rdi'&&index === 7)?<TableCell rowSpan={6} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}></TableCell>:
|
||||
(head.id === 'waterQlty')?<TableCell className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=0 && index<=4))?<TableCell className="bg-yellow-50 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('flowRate', 'year', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=5 && index<=10))?<TableCell className="bg-green-50 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('waterQlty', 'year', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=11 && index<=12))?<TableCell className="bg-blue-50 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('chongin', 'year', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=0 && index<=4))?<TableCell className="bg-yellow-100 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('flowRate', 'summer', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=5 && index<=10))?<TableCell className="bg-green-100 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('waterQlty', 'summer', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=11 && index<=12))?<TableCell className="bg-blue-100 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('chongin', 'summer', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=0 && index<=4))?<TableCell className="bg-yellow-200 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('flowRate', 'winter', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=5 && index<=10))?<TableCell className="bg-green-200 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('waterQlty', 'winter', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=11 && index<=12))?<TableCell className="bg-blue-200 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('chongin', 'winter', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
null
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ContentsDiv>
|
||||
{modalItem && (modalItem.item === 'flowRate' || modalItem.item === 'waterQlty' || modalItem.item === 'chongin') && (
|
||||
<UiModal
|
||||
body={<DashBoardChartModal item={modalItem.item} period={modalItem.period} title={modalItem.title} modalData={operationalStatusList} waterQlty={modalItem.waterQlty}></DashBoardChartModal>}
|
||||
bodyClass="sm:max-w-[80%] h-[88%]"
|
||||
open={true}
|
||||
onOpenChange={(open) => !open && closeModal()}
|
||||
noHeaderYn="Y"
|
||||
noFooterYn="Y"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,243 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { lineChartDataProps } from "@/app/store/dashboard";
|
||||
import { CHART_FORM, type ChartConfig, ContentsDiv, MainChart } from "@common/business_components";
|
||||
import { Card, CardContent } from "@common/business_components/ui/chart/lib/card";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
type facilityInfoProps = {
|
||||
searchYear?: string;
|
||||
fcltyList?: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string, efflWqltStndrdNm: string }[];
|
||||
};
|
||||
|
||||
export default function DashBoardChart({searchYear = '', fcltyList = []}: facilityInfoProps) {
|
||||
const {MainGraph
|
||||
,searchMainGraph
|
||||
} = useFoStore((state) => state);
|
||||
|
||||
const [hasSearched, setHasSearched] = useState(false);
|
||||
const [prevFacilityCode, setPrevFacilityCode] = useState<string>('');
|
||||
const [chart_tpTp, setChart_tpTp] = useState<{
|
||||
chartData1: lineChartDataProps[];
|
||||
chartData2: lineChartDataProps[];
|
||||
}>();
|
||||
const [chart_tntn, setChart_tntn] = useState<{
|
||||
chartData1: lineChartDataProps[];
|
||||
chartData2: lineChartDataProps[];
|
||||
}>();
|
||||
const [chart_inflBodInflTn, setChart_inflBodInflTn] = useState<{
|
||||
chartData1: lineChartDataProps[];
|
||||
chartData2: lineChartDataProps[];
|
||||
}>();
|
||||
const [chart_inflBodInflTp, setChart_inflBodInflTp] = useState<{
|
||||
chartData1: lineChartDataProps[];
|
||||
chartData2: lineChartDataProps[];
|
||||
}>();
|
||||
|
||||
const {
|
||||
chart_inflowRain,
|
||||
chart_bodRain,
|
||||
chart_inflTp,
|
||||
chart_chongInTp,
|
||||
chart_efflTp,
|
||||
chart_inflTn,
|
||||
chart_efflTn,
|
||||
chart_inflBod,
|
||||
} = MainGraph;
|
||||
|
||||
/**
|
||||
* 차트 Config
|
||||
*/
|
||||
const colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#00b50c", "#D4A5A5"];
|
||||
|
||||
//유입하수량-강수량
|
||||
const chartConfig_inflowRain = {
|
||||
barVal0: {
|
||||
label: '강수량',
|
||||
color: colors[2],
|
||||
},
|
||||
lineVal0: {
|
||||
label: '시설용량',
|
||||
color: colors[1],
|
||||
},
|
||||
lineVal1: {
|
||||
label: '유입량',
|
||||
color: colors[4],
|
||||
}
|
||||
} satisfies ChartConfig;
|
||||
//강우량-유입BOD
|
||||
const chartConfig_rainBod = {
|
||||
barVal0: {
|
||||
label: '강수량',
|
||||
color: colors[2],
|
||||
},
|
||||
lineVal0: {
|
||||
label: '유입BOD',
|
||||
color: colors[0],
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
//총인유입T-P-방류T-P
|
||||
const chartConfig_tptp = {
|
||||
chartData1: {
|
||||
label: '총인유입T-P',
|
||||
color: colors[0],
|
||||
},
|
||||
chartData2: {
|
||||
label: '방류T-P',
|
||||
color: colors[1],
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
// 유입T-N-방류T-N
|
||||
const chartConfig_tntn = {
|
||||
chartData1: {
|
||||
label: '유입T-N',
|
||||
color: colors[0],
|
||||
},
|
||||
chartData2: {
|
||||
label: '방류T-N',
|
||||
color: colors[1],
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
// 유입BOD-유입T-N
|
||||
const chartConfig_inflBodInflTn = {
|
||||
chartData1: {
|
||||
label: '유입BOD',
|
||||
color: colors[0],
|
||||
},
|
||||
chartData2: {
|
||||
label: '유입T-N',
|
||||
color: colors[1],
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
// 유입BOD-유입T-P
|
||||
const chartConfig_inflBodInflTp = {
|
||||
chartData1: {
|
||||
label: '유입BOD',
|
||||
color: colors[0],
|
||||
},
|
||||
chartData2: {
|
||||
label: '유입T-P',
|
||||
color: colors[1],
|
||||
},
|
||||
|
||||
} satisfies ChartConfig;
|
||||
|
||||
useEffect(() => {
|
||||
if (fcltyList.length > 0 && fcltyList[0]?.bscFctCd && (fcltyList[0].bscFctCd !== prevFacilityCode || !hasSearched)) {
|
||||
searchMainGraph(searchYear, fcltyList[0].bscFctCd);
|
||||
setHasSearched(true);
|
||||
setPrevFacilityCode(fcltyList[0].bscFctCd);
|
||||
}
|
||||
}, [searchYear, fcltyList, searchMainGraph, hasSearched, chart_inflTp, chart_efflTp, prevFacilityCode]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chart_chongInTp || !chart_efflTp) return;
|
||||
const chartTpTpData = {
|
||||
chartData1: chart_chongInTp,
|
||||
chartData2: chart_efflTp
|
||||
};
|
||||
setChart_tpTp(chartTpTpData);
|
||||
}, [chart_chongInTp, chart_efflTp]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chart_inflTn || !chart_efflTn) return;
|
||||
const chartTntnData = {
|
||||
chartData1: chart_inflTn,
|
||||
chartData2: chart_efflTn
|
||||
};
|
||||
setChart_tntn(chartTntnData);
|
||||
}, [chart_inflTn, chart_efflTn]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chart_inflBod || !chart_inflTn) return;
|
||||
const chartInflBodInflTnData = {
|
||||
chartData1: chart_inflBod,
|
||||
chartData2: chart_inflTn
|
||||
};
|
||||
setChart_inflBodInflTn(chartInflBodInflTnData);
|
||||
}, [chart_inflBod, chart_inflTn]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chart_inflBod || !chart_inflTp) return;
|
||||
const chartInflBodInflTpData = {
|
||||
chartData1: chart_inflBod,
|
||||
chartData2: chart_inflTp
|
||||
};
|
||||
setChart_inflBodInflTp(chartInflBodInflTpData);
|
||||
}, [chart_inflBod, chart_inflTp]);
|
||||
|
||||
// 연도가 바뀌면 hasSearched를 false로 리셋
|
||||
useEffect(() => {
|
||||
setHasSearched(false);
|
||||
}, [searchYear]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ContentsDiv>
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINEBAR} chartConfig={chartConfig_inflowRain} chartData={chart_inflowRain} chartTitle="유입하수량-강수량" yFieldText="유입하수량(m³/일)" yFieldText2="강수량(mm)"></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINEBAR} chartConfig={chartConfig_rainBod} chartData={chart_bodRain} chartTitle="유입BOD-강수량" yFieldText="BOD(mg/L)" yFieldText2="강수량(mm)"></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_tptp} chartData={chart_tpTp} chartTitle="총인유입T-P-방류T-P" yFieldText="T-P(mg/L)"></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
{/* 유입T-N-방류T-N */}
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_tntn} chartData={chart_tntn} chartTitle="유입T-N-방류T-N" yFieldText="T-N(mg/L)"></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
{/* 유입BOD-유입T-N */}
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_inflBodInflTn} chartData={chart_inflBodInflTn} chartTitle="유입BOD-유입T-N" yFieldText="농도(mg/L)"></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
{/* 유입BOD-유입T-P */}
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_inflBodInflTp} chartData={chart_inflBodInflTp} chartTitle="유입BOD-유입T-P" yFieldText="농도(mg/L)"></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
</>
|
||||
);
|
||||
{/* <div>>
|
||||
<MainChart chartForm={CHART_FORM.DN} chartConfig={chartConfig} chartData={chartData} chartTitle="유입하수량-강수량"></MainChart>
|
||||
</div>
|
||||
<div className="col-span-6">
|
||||
<MainChart chartForm={CHART_FORM.LINEBAR} chartConfig={chartConfig} chartData={chart_inflowRain} chartTitle="유입BOD-강수량"></MainChart>
|
||||
</div>
|
||||
<div className="col-span-6">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig} chartData={chartData} chartTitle="총인유입T-P-방류T-P"></MainChart>
|
||||
</div>
|
||||
<div className="col-span-6">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig} chartData={chartData} chartTitle="유입T-N-방류T-N"></MainChart>
|
||||
</div>
|
||||
</div> */}
|
||||
}
|
||||
@@ -1,306 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { ContentsDiv, downloadExcel, downloadMultipleExcel, filePickedBlobArray, MainDiv, SelectBox, UITab, type SelectDataType } from "@common/business_components";
|
||||
import { Button, TabsContent } from "@common/components/ui";
|
||||
import { useEffect, useState } from "react";
|
||||
import DashBoardFclty from "../dashboardMain/page";
|
||||
/* import DrainageEquipment from "./drainageEquipment/page"; */
|
||||
import ProcessFacilitySearch from "./facilityInfo/page";
|
||||
import DashBoardChart from "./maingraph/page";
|
||||
import RainManageTab from "./rainManage/page";
|
||||
import DrainageEquipment from "./drainageEquipment/page";
|
||||
|
||||
const tabList = [
|
||||
{ value: 'facilityInfo', label: '시설정보 및 운영현황' },
|
||||
{ value: 'mainGraph', label: '주요그래프' },
|
||||
{ value: 'rainManage', label: '강우일 운영현황' },
|
||||
{ value: 'drainageEquipment', label: '배수설비 정비현황' }
|
||||
];
|
||||
|
||||
export default function DashBoard() {
|
||||
// 입력값 상태 관리
|
||||
const { Common, initializeCommonData,searchMainGraph, searchRainManage, searchOperationStatus, OperationStatus, RainManage, MainGraph, PlanFclty } = useFoStore((state) => state);
|
||||
const [activeTab, setActiveTab] = useState<string>('facilityInfo');
|
||||
|
||||
const [filteredSigunData, setFilteredSigunData] = useState<SelectDataType[]>([{ text: "전체", val: '0' }]);
|
||||
const [sidoValue, setSidoValue] = useState<string>('0');
|
||||
const [sigunValue, setSigunValue] = useState<string>('0');
|
||||
const {
|
||||
isInit,
|
||||
selectSearchYear,
|
||||
btnClass,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
planFcltyList
|
||||
} = PlanFclty;
|
||||
|
||||
const {
|
||||
operationalStatusList
|
||||
} = OperationStatus;
|
||||
|
||||
const {
|
||||
excelList
|
||||
} = RainManage;
|
||||
|
||||
const {
|
||||
chart_inflowRain,
|
||||
chart_bodRain,
|
||||
chart_inflTp,
|
||||
chart_chongInTp,
|
||||
chart_efflTp,
|
||||
chart_inflTn,
|
||||
chart_efflTn,
|
||||
} = MainGraph;
|
||||
|
||||
/******************선택된 데이터******************/
|
||||
// 연도
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || '0');
|
||||
// 시설명
|
||||
const [fcltyList, setFcltyList] = useState<{bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | ''}>({
|
||||
bscFctCd: '',
|
||||
bscFctNm: '',
|
||||
fcltyCpc: '',
|
||||
trtFrfNm: '',
|
||||
efflWqltStndrdNm: ''
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
setFcltyList({
|
||||
bscFctCd: '11000SW001R',
|
||||
bscFctNm: '난지',
|
||||
fcltyCpc: 860000,
|
||||
trtFrfNm: '표준활성슬러지법, MLE, A2O',
|
||||
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
|
||||
});
|
||||
}
|
||||
}, [isInit, initializeCommonData]);
|
||||
|
||||
const handleFacilityChange = (facility: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | '' }) => {
|
||||
setFcltyList(facility);
|
||||
};
|
||||
|
||||
const onSelectValue = (val: string, type: string) => {
|
||||
switch(type) {
|
||||
case 'sido':
|
||||
setSidoValue(val);
|
||||
initializeSigunData(val);
|
||||
onSelectValue('0', 'sigun');
|
||||
break;
|
||||
case 'sigun':
|
||||
setSigunValue(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 시군구 세팅
|
||||
const initializeSigunData = (sidoCd: string) => {
|
||||
if (sidoCd === '0') {
|
||||
setSigunValue('0');
|
||||
setFilteredSigunData([{ text: "전체", val: '0' }]);
|
||||
} else {
|
||||
const newFilteredData = [
|
||||
{ text: "전체", val: '0' },
|
||||
...selectSigunData.filter((item: SelectDataType) => item.val.substring(0, 2) === sidoCd)
|
||||
];
|
||||
setSigunValue('0');
|
||||
setFilteredSigunData(newFilteredData);
|
||||
}
|
||||
}
|
||||
|
||||
const excelDownload = () => {
|
||||
if (!fcltyList.bscFctCd) return;
|
||||
switch (activeTab) {
|
||||
case 'facilityInfo':
|
||||
searchOperationStatus(false, searchYear, fcltyList.bscFctCd);
|
||||
|
||||
fetch(`/mainDashBoard.xlsx`, {}).then(async (response) => {
|
||||
if (!response.ok) {
|
||||
throw Error(response.statusText);
|
||||
}
|
||||
// 받은 파일 바인너리 처리
|
||||
const blobRet = await response.arrayBuffer();
|
||||
|
||||
const excelData1 = planFcltyList.map((item) => {
|
||||
return [
|
||||
item.item,
|
||||
item.provisionalApproval,
|
||||
item.now,
|
||||
item.stepOne,
|
||||
item.stepTwo,
|
||||
item.stepThree,
|
||||
item.stepFour,
|
||||
];
|
||||
});
|
||||
|
||||
// operationalStatusList를 2차원 배열로 변환
|
||||
const excelData2 = operationalStatusList.map((item, index) => {
|
||||
const baseData = [
|
||||
item.yearAvg,
|
||||
item.yearMax,
|
||||
item.yearMin,
|
||||
item.summerAll,
|
||||
item.summerThree,
|
||||
item.summerRain,
|
||||
item.winterAll,
|
||||
item.winterSunnyAvg,
|
||||
item.winterSunnyMax,
|
||||
item.winterSunnyMin,
|
||||
item.groundWaterAvg,
|
||||
item.groundWaterSummer,
|
||||
item.groundWaterWinter
|
||||
];
|
||||
|
||||
// index가 0일 때만 rdi와 rdiRain 추가
|
||||
return index === 0 ? [...baseData, item.rdi, item.rdiRain] : baseData;
|
||||
});
|
||||
|
||||
const sheetParameter = [
|
||||
{
|
||||
data: excelData1,
|
||||
headerNum: 3,
|
||||
headerRange: 'A1:G2',
|
||||
sheetName: '운영실태',
|
||||
startCol: 'A'
|
||||
},
|
||||
{
|
||||
data: excelData2,
|
||||
headerNum: 4,
|
||||
headerRange: 'A1:Q3',
|
||||
sheetName: '운영실태',
|
||||
startCol: 'C'
|
||||
}
|
||||
];
|
||||
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
|
||||
await filePickedBlobArray(blobRet, '시설정보및운영현황황', sheetParameter);
|
||||
});
|
||||
break;
|
||||
|
||||
case 'mainGraph':
|
||||
searchMainGraph(searchYear, fcltyList.bscFctCd);
|
||||
|
||||
const sheetParameter = [
|
||||
{
|
||||
data: [['날짜', '강수량'],...chart_inflowRain.map((item) => [item.label, item.barVal0])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '강수량'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '유입하수량'],...chart_inflowRain.map((item) => [item.label, item.lineVal1])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '유입하수량'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '시설용량'],...chart_inflowRain.map((item) => [item.label, item.lineVal0])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '시설용량'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '유입BOD'],...chart_bodRain.map((item) => [item.label, item.lineVal0])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '유입BOD'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '유입T-P'],...chart_inflTp.map((item) => [item.label, item.val])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '유입T-P'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '총인유입T-P'],...chart_chongInTp.map((item) => [item.label, item.val])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '총인유입T-P'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '방류T-P'],...chart_efflTp.map((item) => [item.label, item.val])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '방류T-P'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '유입T-N'],...chart_inflTn.map((item) => [item.label, item.val])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '유입T-N'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '방류T-N'],...chart_efflTn.map((item) => [item.label, item.val])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '방류T-N'
|
||||
}
|
||||
];
|
||||
|
||||
downloadMultipleExcel('주요그래프', sheetParameter);
|
||||
break;
|
||||
|
||||
case 'rainManage':
|
||||
searchRainManage(searchYear, fcltyList.bscFctCd, true);
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({ data: excelList as unknown as JSON[], fileName: '강우일 운영현황', sheetNameArray: ['강우일 운영현황'], headerRange: 'A1:T1' });
|
||||
}
|
||||
break;
|
||||
// Add other cases for different tabs as needed
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const initVal = () => {
|
||||
setFcltyList({
|
||||
bscFctCd: '11000SW001R',
|
||||
bscFctNm: '난지',
|
||||
fcltyCpc: 860000,
|
||||
trtFrfNm: '표준활성슬러지법, MLE, A2O',
|
||||
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<ContentsDiv>
|
||||
<div className="flex card card-border !mt-6">
|
||||
<div className="grid grid-cols-12 gap-5 w-8/12 m-4">
|
||||
<SelectBox className="col-span-2" label={'연도'} selectArray={selectSearchYear} onSelectValue={ (val) => setSearchYear(val.toString()) } value={searchYear} selectClass={undefined}/>
|
||||
<SelectBox className="col-span-3" label={'시도'} selectArray={selectSidoData} onSelectValue={(val) => onSelectValue(val.toString(), 'sido')} value={sidoValue} selectClass={undefined}/>
|
||||
<SelectBox className="col-span-3" label={'시군구'} selectArray={filteredSigunData} onSelectValue={(val) => onSelectValue(val.toString(), 'sigun')} value={sigunValue} selectClass={undefined}/>
|
||||
<div className="col-span-4 flex">
|
||||
<DashBoardFclty onFacilityChange={handleFacilityChange} sidoSigun={sigunValue!='0'?sigunValue:sidoValue!='0'?sidoValue:''} facilityNm={fcltyList.bscFctNm}></DashBoardFclty>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-4/12 mx-5 flex items-center justify-end space-x-2">
|
||||
<Button className={btnClass} onClick={initVal}>
|
||||
초기화
|
||||
</Button>
|
||||
<Button className={btnClass} color="green" onClick={excelDownload}>
|
||||
엑셀다운로드
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<UITab tabList={tabList} defaultValue="facilityInfo" onValueChange={setActiveTab}>
|
||||
<TabsContent value="facilityInfo">
|
||||
<ProcessFacilitySearch searchYear={searchYear} fcltyList={[fcltyList]} onFacilityChange={handleFacilityChange} />
|
||||
</TabsContent>
|
||||
<TabsContent value="mainGraph">
|
||||
<DashBoardChart searchYear={searchYear} fcltyList={[fcltyList]}/>
|
||||
</TabsContent>
|
||||
<TabsContent value="rainManage">
|
||||
<RainManageTab searchYear={searchYear} fcltyList={[fcltyList]}/>
|
||||
</TabsContent>
|
||||
<TabsContent value="drainageEquipment">
|
||||
<DrainageEquipment searchYear={searchYear} fcltyList={[fcltyList]}/>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</ContentsDiv>
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { UiTable } from "@common/business_components/ui/table";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export type facilityInfoProps = {
|
||||
searchYear?: string;
|
||||
fcltyList?: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string, efflWqltStndrdNm: string }[];
|
||||
};
|
||||
|
||||
export default function RainManageTab({searchYear = '', fcltyList = []}: facilityInfoProps) {
|
||||
|
||||
const {
|
||||
Common,
|
||||
searchRainManage,
|
||||
RainManage
|
||||
} = useFoStore((state) => state);
|
||||
|
||||
const [hasSearched, setHasSearched] = useState(false);
|
||||
// 이전 시설코드 저장
|
||||
const [prevFacilityCode, setPrevFacilityCode] = useState<string>('');
|
||||
|
||||
const {
|
||||
isInit,
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
upHeadListRainManage,
|
||||
rainManageList,
|
||||
} = RainManage;
|
||||
|
||||
const tableData = fcltyList;
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit && tableData[0]?.bscFctCd && (tableData[0].bscFctCd !== prevFacilityCode || !hasSearched)) {
|
||||
searchRainManage(searchYear, tableData[0].bscFctCd, false);
|
||||
setHasSearched(true);
|
||||
setPrevFacilityCode(tableData[0].bscFctCd);
|
||||
}
|
||||
}, [fcltyList, isInit, searchRainManage, searchYear, tableData, hasSearched, prevFacilityCode]);
|
||||
|
||||
// 연도가 바뀌면 hasSearched를 false로 리셋
|
||||
useEffect(() => {
|
||||
setHasSearched(false);
|
||||
}, [searchYear]);
|
||||
|
||||
return (
|
||||
<UiTable
|
||||
headName=""
|
||||
tableData={rainManageList}
|
||||
headlist={upHeadListRainManage}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
>
|
||||
</UiTable>
|
||||
)
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { useEffect, useState } from "react";
|
||||
import SearchInput from "../../components/common/SearchInput";
|
||||
|
||||
export default function DashBoardFclty({ onFacilityChange, sidoSigun, facilityNm }: { onFacilityChange?: (facility: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | '' }) => void, sidoSigun?: string, facilityNm?: string }) {
|
||||
// 입력값 상태 관리
|
||||
const { Common, initializeCommonData } = useFoStore((state) => state);
|
||||
|
||||
const {
|
||||
isInit,
|
||||
} = Common;
|
||||
|
||||
// 시설명
|
||||
const [bscFctNm, setFcltyName] = useState<string>(facilityNm || '난지');
|
||||
const [bscFctCd, setbscFctCd] = useState<string>('11000SW001R');
|
||||
const [fcltyCpc, setFcltyCpc] = useState<number | ''>(860000);
|
||||
const [trtFrfNm, setTrtFrfNm] = useState<string | ''>('표준활성슬러지법, MLE, A2O');
|
||||
const [efflWqltStndrdNm, setEfflWqltStndrdNm] = useState<string | ''>('500톤 이상(Ⅲ지역)');
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
}
|
||||
}, [isInit, initializeCommonData ]);
|
||||
|
||||
useEffect(() => {
|
||||
if (facilityNm) {
|
||||
setFcltyName(facilityNm);
|
||||
}
|
||||
}, [facilityNm]);
|
||||
|
||||
const fncNextPage = (bscFctCd?: string, bscFctNm?: string, fcltyCpc?: number | '', trtFrfNm?: string | '', efflWqltStndrdNm?: string | '') => {
|
||||
setbscFctCd(bscFctCd || '');
|
||||
setFcltyName(bscFctNm || '');
|
||||
setFcltyCpc(fcltyCpc || '');
|
||||
setTrtFrfNm(trtFrfNm || '');
|
||||
setEfflWqltStndrdNm(efflWqltStndrdNm || '');
|
||||
|
||||
if (bscFctCd && onFacilityChange) {
|
||||
onFacilityChange({
|
||||
bscFctCd: bscFctCd || '',
|
||||
bscFctNm: bscFctNm || '',
|
||||
fcltyCpc: fcltyCpc || '',
|
||||
trtFrfNm: trtFrfNm || '',
|
||||
efflWqltStndrdNm: efflWqltStndrdNm || ''
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.log('bscFctNm : ', bscFctNm);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchInput label={'시설명'} setValue={fncNextPage} sidoSigun={sidoSigun} fcltyName={bscFctNm}/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { PrecipitationPropsDetailProps } from "@/app/store/facilityPrecipitation";
|
||||
import { DatePickerRange, UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Table, TableCell, TableHead, TableRow } from "@common/components/ui";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
type PrecipitationModalProps = {
|
||||
searchYear: string;
|
||||
fcltyName: string;
|
||||
facilityCd: string;
|
||||
detailList: PrecipitationPropsDetailProps[];
|
||||
}
|
||||
|
||||
type DateRange = {
|
||||
start: Date;
|
||||
end: Date;
|
||||
}
|
||||
|
||||
export default function PrecipitationModal(props: PrecipitationModalProps) {
|
||||
const { PrecipitationDetail } = useFoStore((state) => state);
|
||||
const { upHeadListPrecipitationDetail } = PrecipitationDetail;
|
||||
|
||||
// Refs
|
||||
const startPickerRef = useRef<HTMLDivElement>(null);
|
||||
const endPickerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// States
|
||||
const [startDate, setStartDate] = useState<Date | null>(null);
|
||||
const [endDate, setEndDate] = useState<Date | null>(null);
|
||||
const [filteredDetailList, setFilteredDetailList] = useState<PrecipitationPropsDetailProps[]>([]);
|
||||
const [copyDetailList, setCopyDetailList] = useState<PrecipitationPropsDetailProps[]>([]);
|
||||
|
||||
const getDateRanges = (): DateRange[] => {
|
||||
const standYear = parseInt(props.searchYear);
|
||||
return [{
|
||||
start: new Date(standYear, 0, 1),
|
||||
end: new Date(standYear, 11, 31)
|
||||
}];
|
||||
};
|
||||
|
||||
const isDateInRanges = (date: Date): boolean => {
|
||||
return getDateRanges().some(range => {
|
||||
const start = new Date(range.start);
|
||||
const end = new Date(range.end);
|
||||
return date >= start && date <= end;
|
||||
});
|
||||
};
|
||||
|
||||
const filterDataByDateRange = (start: Date | null, end: Date | null): PrecipitationPropsDetailProps[] => {
|
||||
if (!start || !end) return filteredDetailList;
|
||||
return filteredDetailList.filter((item) => {
|
||||
const itemDate = new Date(item.rainDt);
|
||||
return itemDate >= start && itemDate <= end;
|
||||
});
|
||||
};
|
||||
|
||||
const handleStartDateSelect = (date: Date | null) => {
|
||||
if (!date || !endDate) return;
|
||||
|
||||
if (date > endDate) {
|
||||
alert('시작일은 종료일 이후일 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const filteredData = filterDataByDateRange(date, endDate);
|
||||
setCopyDetailList(filteredData);
|
||||
setStartDate(date);
|
||||
|
||||
const button = startPickerRef.current?.querySelector('button');
|
||||
if (button) {
|
||||
setTimeout(() => button.click(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEndDateSelect = (date: Date | null) => {
|
||||
if (!date || !startDate) return;
|
||||
|
||||
if (date < startDate) {
|
||||
alert('종료일은 시작일 이전일 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const filteredData = filterDataByDateRange(startDate, date);
|
||||
setCopyDetailList(filteredData);
|
||||
setEndDate(date);
|
||||
|
||||
const button = endPickerRef.current?.querySelector('button');
|
||||
if (button) {
|
||||
setTimeout(() => button.click(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
const calculateTotals = () => {
|
||||
return copyDetailList.reduce((acc, item) => ({
|
||||
infoRnDay: acc.infoRnDay + Number(item.infoRnDay),
|
||||
rainDay: acc.rainDay + Number(item.rainDay),
|
||||
rainEffectDay: acc.rainEffectDay + Number(item.rainEffectDay)
|
||||
}), { infoRnDay: 0, rainDay: 0, rainEffectDay: 0 });
|
||||
};
|
||||
|
||||
const getTableData = () => {
|
||||
const totals = calculateTotals();
|
||||
return [
|
||||
{
|
||||
bscFctCd: "",
|
||||
rainDt: '합계',
|
||||
...totals
|
||||
},
|
||||
...copyDetailList
|
||||
];
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (props.detailList.length > 0) {
|
||||
const filteredList = props.detailList.filter((item) =>
|
||||
props.facilityCd === item.bscFctCd
|
||||
);
|
||||
|
||||
setFilteredDetailList(filteredList);
|
||||
setCopyDetailList(filteredList);
|
||||
|
||||
if (filteredList.length > 0) {
|
||||
const firstDateStr = filteredList[0]?.rainDt;
|
||||
const lastDateStr = filteredList[filteredList.length - 1]?.rainDt;
|
||||
|
||||
if (firstDateStr) {
|
||||
const firstDate = new Date(firstDateStr);
|
||||
if (!isNaN(firstDate.getTime())) {
|
||||
setStartDate(firstDate);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastDateStr) {
|
||||
const lastDate = new Date(lastDateStr);
|
||||
if (!isNaN(lastDate.getTime())) {
|
||||
setEndDate(lastDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [props.detailList, props.facilityCd]);
|
||||
|
||||
if (!startDate || !endDate) {
|
||||
return <div>로딩 중...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListDiv className="!h-[80px] !mt-10">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow>
|
||||
<TableHead className="w-1/6">{'시설명'}</TableHead>
|
||||
<TableCell className="w-1/3">{props.fcltyName}</TableCell>
|
||||
<TableHead className="w-1/6">{'년월'}</TableHead>
|
||||
<TableCell className="w-1/3">
|
||||
<div className="flex">
|
||||
<div ref={startPickerRef} className="flex justify-center">
|
||||
<DatePickerRange
|
||||
mode="single"
|
||||
selected={startDate}
|
||||
onSelect={(date) => handleStartDateSelect(date as Date)}
|
||||
className="w-full p-1 border rounded bg-white"
|
||||
disabled={(date) => !isDateInRanges(date)}
|
||||
defaultMonth={startDate}
|
||||
/>
|
||||
</div>
|
||||
<span className="mx-3">~</span>
|
||||
<div ref={endPickerRef} className="flex justify-center">
|
||||
<DatePickerRange
|
||||
mode="single"
|
||||
selected={endDate}
|
||||
onSelect={(date) => handleEndDateSelect(date as Date)}
|
||||
className="w-full p-1 border rounded bg-white"
|
||||
disabled={(date) => !isDateInRanges(date)}
|
||||
defaultMonth={endDate}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<ListDiv className="h-[450px] overflow-y-auto">
|
||||
<UiTable
|
||||
headName={"강수현황"}
|
||||
tableData={getTableData()}
|
||||
headlist={upHeadListPrecipitationDetail}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
boldArray={[0]}
|
||||
/>
|
||||
</ListDiv>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import PrecipitationModal from "./modal/page";
|
||||
|
||||
export default function FacilityPrecipitation() {
|
||||
const {Common
|
||||
,FacilityPrecipitation
|
||||
,FacilityPrecipitationSearch
|
||||
,PrecipitationDetail
|
||||
,initializeCommonData
|
||||
,searchFacilityPrecipitationList
|
||||
} = useFoStore((state) => state) || { processAreaList: { processAreaList: [] }};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectSearchYear,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
labelArray,
|
||||
} = FacilityPrecipitationSearch;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
excelList,
|
||||
facilityPrecipitation,
|
||||
facilityPrecipitationCount
|
||||
} = FacilityPrecipitation;
|
||||
|
||||
const {
|
||||
gridListPrecipitationDetail
|
||||
} = PrecipitationDetail;
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
const facilityPrecipitationList = FacilityPrecipitation?.facilityPrecipitation || [];
|
||||
|
||||
// 그리드 관련
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
// 모달 상태 추가
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [fcltyNm, setFcltyNm] = useState<string>("");
|
||||
const [fcltyCd, setFcltyCd] = useState<string>("");
|
||||
|
||||
// 초기화 변수
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
// 표 너비
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
// 구분별 그리드 헤더
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
// 용량별
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
// 시설명
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
// 시설상태
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
*/
|
||||
// 초기화
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
setUpheadList(upHeadList1)
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYear(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
searchFacilityPrecipitationList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
};
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
if (facilityPrecipitation[index]) {
|
||||
setFcltyNm(facilityPrecipitation[index].bscFctNm);
|
||||
setFcltyCd(facilityPrecipitation[index].bscFctCd);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* useEffect
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchFacilityPrecipitationList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchFacilityPrecipitationList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '시설별 강수현황',
|
||||
sheetNameArray: ['시설별 강수현황'],
|
||||
headerRange: 'A1:N1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
useEffect(() => {
|
||||
if (facilityPrecipitation.length > 0) {
|
||||
|
||||
}
|
||||
}, [facilityPrecipitation]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
*/
|
||||
// 조회
|
||||
const searchFacilityPrecipitation = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
console.log('partValue : ', partValue);
|
||||
console.log('regionValue : ', regionValue);
|
||||
console.log('unitWaterShedValue : ', unitWaterShedValue);
|
||||
console.log('middleRegionValue : ', middleRegionValue);
|
||||
console.log('envPartValue : ', envPartValue);
|
||||
console.log('sidoValue : ', sidoValue);
|
||||
console.log('sigunValue : ', sigunValue);
|
||||
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || operationValue!== '0' || fcltCpct !== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchFacilityPrecipitationList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchFacilityPrecipitationList(pageNo, pageCnt, searchYear);
|
||||
}
|
||||
}, [operationValue, fcltyName, searchFacilityPrecipitationList, searchYear, fcltCpct]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback((searchReturn: ReturnType) => {
|
||||
searchFacilityPrecipitation(searchReturn, 1, 10000);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
// 페이지 변경
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchFacilityPrecipitation(ref.current, page, 10);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
const mainList = facilityPrecipitationList || [];
|
||||
const total = facilityPrecipitationCount || 0;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="시설별 강수현황" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className={"col-span-3"} label={labelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={labelArray[6] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={labelArray[5] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref} isAdmin={false} />
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 강수현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
<span className="text-2xl font-bold text-gray-500">☞ 강우일은 3mm 이상만 해당 / 강우영향일은 강우일 및 강우일 후 연속 2일간으로 정의</span>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<PrecipitationModal searchYear={searchYear} fcltyName={fcltyNm} facilityCd={fcltyCd} detailList={gridListPrecipitationDetail}></PrecipitationModal>}
|
||||
bodyClass="sm:max-w-[90vw] w-[72vw] h-[40vw]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open) => !open && closeModal()}
|
||||
noHeaderYn="Y"
|
||||
noFooterYn="Y"
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
import { TableHead, TableRow } from "@common/components/ui";
|
||||
|
||||
interface TableUpperProps {
|
||||
id: string;
|
||||
title: string;
|
||||
upName?: string;
|
||||
upSequnce?: number;
|
||||
}
|
||||
|
||||
const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProps[], layoutNum: number }) => {
|
||||
return (
|
||||
layoutNum === 0 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if(!head.upName) {
|
||||
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
|
||||
}else if(head.upName==="upChangeRe1"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>행정구역</TableHead>
|
||||
}else if(head.upName==="upChangeRe3"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
|
||||
}else if(head.upName==="upChangeRe4"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유출</TableHead>
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps, idx: number) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4') {
|
||||
if (idx == 1 || idx == 2 || idx == 3) {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
else {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 1 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if(!head.upName) {
|
||||
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
|
||||
}else if(head.upName==="upChangeRe1"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={3} style={{ whiteSpace: 'pre-line' }} key={head.id}>권역</TableHead>
|
||||
}else if(head.upName==="upChangeRe3"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
|
||||
}else if(head.upName==="upChangeRe4"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유출</TableHead>
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps, idx: number) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4') {
|
||||
if (idx == 1 || idx == 2 || idx == 3) {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
else {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 2 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if(!head.upName) {
|
||||
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
|
||||
}else if(head.upName==="upChangeRe1"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={3} style={{ whiteSpace: 'pre-line' }} key={head.id}>권역</TableHead>
|
||||
}else if(head.upName==="upChangeRe2"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>행정구역</TableHead>
|
||||
}else if(head.upName==="upChangeRe3"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
|
||||
}else if(head.upName==="upChangeRe4"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유출</TableHead>
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps, idx: number) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4') {
|
||||
if (idx == 1 || idx == 2 || idx == 3) {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
else {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 3 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if(!head.upName) {
|
||||
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
|
||||
}else if(head.upName==="upChangeRe1"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
|
||||
}else if(head.upName==="upChangeRe2"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>방류</TableHead>
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps, idx: number) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2') {
|
||||
if (idx == 1 || idx == 2 || idx == 3) {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
else {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 4 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if(!head.upName) {
|
||||
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
|
||||
}else if(head.upName==="upChangeRe"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={4} style={{ whiteSpace: 'pre-line' }} key={head.id}>방류</TableHead>
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps, idx: number) => {
|
||||
if (head.upName === 'upChangeRe') {
|
||||
if (idx == 1 || idx == 2 || idx == 3) {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
else {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 5 ? ( // 총인설비 수질현황 헤더
|
||||
<>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if(!head.upName) {
|
||||
return <TableHead className="w-[180px] bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
|
||||
}else if(head.upName==="upChangeRe1" && head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
|
||||
}else if(head.upName==="upChangeRe2" && head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>방류</TableHead>
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
): (
|
||||
<>
|
||||
</>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export { HeadMakeColSpan };
|
||||
@@ -1,571 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { FacilityWaterQltyProps, modalExcelType } from "@/app/store/facilityWaterQlty";
|
||||
import { downloadExcel, UITab, UiTable } from "@common/business_components/ui";
|
||||
import { Button, TabsContent } from "@common/components/ui";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import type { ReturnType } from "../../../components/common/FacilityTermModalHeader";
|
||||
import FacilityTermModalHeader from "../../../components/common/FacilityTermModalHeader";
|
||||
import { HeadMakeColSpan } from "../HeadMakeColSpan";
|
||||
|
||||
type ModalProps ={
|
||||
fcltyName: string;
|
||||
facilityCd : string;
|
||||
searchYear : string;
|
||||
}
|
||||
|
||||
const tabList1 = [
|
||||
{ value: 'tab_num1', label: '처리시설 수질현황' },
|
||||
{ value: 'tab_num2', label: '총인설비 수질현황' },
|
||||
];
|
||||
|
||||
const tabList2 = [
|
||||
{ value: 'tab_term_year', label: '연간' },
|
||||
{ value: 'tab_term_summer', label: '하절기' },
|
||||
{ value: 'tab_term_winter', label: '동절기' },
|
||||
{ value: 'tab_term_chuncheon', label: '청천시' },
|
||||
{ value: 'tab_term_rain', label: '강우시' }
|
||||
];
|
||||
|
||||
const tabList3 = [
|
||||
{ value: 'tab_term_year_chongin', label: '연간' },
|
||||
{ value: 'tab_term_summer_chongin', label: '하절기' },
|
||||
{ value: 'tab_term_winter_chongin', label: '동절기' }
|
||||
];
|
||||
|
||||
export default function WaterQualityModal({fcltyName='', facilityCd='', searchYear=new Date().getFullYear().toString()} : ModalProps) {
|
||||
// 그리드 관련
|
||||
const {FacilityWaterQltyModal,
|
||||
searchFacilityWaterQltyListHist,
|
||||
Common
|
||||
} = useFoStore((state) => state);
|
||||
const {btnClass} = Common;
|
||||
const {
|
||||
upHeadListModalYear,
|
||||
facilityWaterQltyYearList,
|
||||
upHeadListModalTms,
|
||||
tmsList,
|
||||
msrmtDate,
|
||||
upHeadListModalChongIn,
|
||||
} = FacilityWaterQltyModal;
|
||||
|
||||
const prevExcelListRef = useRef<modalExcelType[] | null>(null);
|
||||
|
||||
// 필터링 된 후 최대, 최소, 평균 값 계산
|
||||
const setFilterAfterData = (filteredData: FacilityWaterQltyProps[]) => {
|
||||
// 쉼표가 포함된 문자열을 숫자로 변환하는 함수
|
||||
const parseNumber = (value: string | number | null | undefined): number => {
|
||||
if (value === null || value === undefined || value === '') return 0;
|
||||
if (typeof value === 'number') return value;
|
||||
return Number(value.replace(/,/g, ''));
|
||||
};
|
||||
|
||||
let maxEfflWqltBod = 0;
|
||||
let maxEfflWqltTn = 0;
|
||||
let maxEfflWqltTp = 0;
|
||||
let maxefflWqltCod = 0;
|
||||
let maxEfflWqltSs = 0;
|
||||
|
||||
let maxInflAssctAftWqltBod = 0;
|
||||
let maxInflAssctAftWqltTn = 0;
|
||||
let maxInflAssctBfrWqltTp = 0;
|
||||
let maxInflAssctAftWqltToc = 0;
|
||||
let maxInflAssctAftWqltSs = 0;
|
||||
|
||||
let maxTpInflWqltBod = 0;
|
||||
let maxTpInflWqltTp = 0;
|
||||
let maxInfoRnDay = 0;
|
||||
|
||||
// 초기값 설정
|
||||
let minEfflWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltBod) : 0;
|
||||
let minEfflWqltTn = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltTn) : 0;
|
||||
let minEfflWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltTp) : 0;
|
||||
let minefflWqltCod = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltCod) : 0;
|
||||
let minEfflWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltSs) : 0;
|
||||
|
||||
let minInflAssctAftWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctAftWqltBod) : 0;
|
||||
let minInflAssctAftWqltTn = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctAftWqltTn) : 0;
|
||||
let minInflAssctBfrWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltTp) : 0;
|
||||
let minInflAssctAftWqltToc = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctAftWqltToc) : 0;
|
||||
let minInflAssctAftWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctAftWqltSs) : 0;
|
||||
|
||||
let minTpInflWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.tpInflWqltBod) : 0;
|
||||
let minTpInflWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.tpInflWqltTp) : 0;
|
||||
|
||||
let minInfoRnDay = filteredData.length > 0 ? parseNumber(filteredData[0]?.infoRnDay) : 0;
|
||||
|
||||
let avgEfflWqltBod = 0;
|
||||
let avgEfflWqltTn = 0;
|
||||
let avgEfflWqltTp = 0;
|
||||
let avgefflWqltCod = 0;
|
||||
let avgEfflWqltSs = 0;
|
||||
|
||||
let avgInflAssctAftWqltBod = 0;
|
||||
let avgInflAssctAftWqltTn = 0;
|
||||
let avgInflAssctBfrWqltTp = 0;
|
||||
let avgInflAssctAftWqltToc = 0;
|
||||
let avgInflAssctAftWqltSs = 0;
|
||||
|
||||
let avgTpInflWqltBod = 0;
|
||||
let avgTpInflWqltTp = 0;
|
||||
|
||||
let avgInfoRnDay = 0;
|
||||
|
||||
filteredData.forEach((item: FacilityWaterQltyProps) => {
|
||||
const efflWqltBod = parseNumber(item.efflWqltBod);
|
||||
const efflWqltTn = parseNumber(item.efflWqltTn);
|
||||
const efflWqltTp = parseNumber(item.efflWqltTp);
|
||||
const efflWqltCod = parseNumber(item.efflWqltCod);
|
||||
const efflWqltSs = parseNumber(item.efflWqltSs);
|
||||
|
||||
const inflAssctAftWqltBod = parseNumber(item.inflAssctAftWqltBod);
|
||||
const inflAssctAftWqltTn = parseNumber(item.inflAssctAftWqltTn);
|
||||
const inflAssctBfrWqltTp = parseNumber(item.inflAssctBfrWqltTp);
|
||||
const inflAssctAftWqltToc = parseNumber(item.inflAssctAftWqltToc);
|
||||
const inflAssctAftWqltSs = parseNumber(item.inflAssctAftWqltSs);
|
||||
|
||||
|
||||
const tpInflWqltBod = parseNumber(item.tpInflWqltBod);
|
||||
const tpInflWqltTp = parseNumber(item.tpInflWqltTp);
|
||||
|
||||
const infoRnDay = parseNumber(item.infoRnDay);
|
||||
|
||||
maxEfflWqltBod = Math.max(maxEfflWqltBod, efflWqltBod);
|
||||
maxEfflWqltTn = Math.max(maxEfflWqltTn, efflWqltTn);
|
||||
maxEfflWqltTp = Math.max(maxEfflWqltTp, efflWqltTp);
|
||||
maxefflWqltCod = Math.max(maxefflWqltCod, efflWqltCod);
|
||||
maxEfflWqltSs = Math.max(maxEfflWqltSs, efflWqltSs);
|
||||
|
||||
maxInflAssctAftWqltBod = Math.max(maxInflAssctAftWqltBod, inflAssctAftWqltBod);
|
||||
maxInflAssctAftWqltTn = Math.max(maxInflAssctAftWqltTn, inflAssctAftWqltTn);
|
||||
maxInflAssctBfrWqltTp = Math.max(maxInflAssctBfrWqltTp, inflAssctBfrWqltTp);
|
||||
maxInflAssctAftWqltToc = Math.max(maxInflAssctAftWqltToc, inflAssctAftWqltToc);
|
||||
maxInflAssctAftWqltSs = Math.max(maxInflAssctAftWqltSs, inflAssctAftWqltSs);
|
||||
|
||||
maxTpInflWqltBod = Math.max(maxTpInflWqltBod, tpInflWqltBod);
|
||||
maxTpInflWqltTp = Math.max(maxTpInflWqltTp, tpInflWqltTp);
|
||||
|
||||
maxInfoRnDay = Math.max(maxInfoRnDay, infoRnDay);
|
||||
|
||||
minEfflWqltBod = Math.min(minEfflWqltBod, efflWqltBod);
|
||||
minEfflWqltTn = Math.min(minEfflWqltTn, efflWqltTn);
|
||||
minEfflWqltTp = Math.min(minEfflWqltTp, efflWqltTp);
|
||||
minefflWqltCod = Math.min(minefflWqltCod, efflWqltCod);
|
||||
minEfflWqltSs = Math.min(minEfflWqltSs, efflWqltSs);
|
||||
|
||||
minInflAssctAftWqltBod = Math.min(minInflAssctAftWqltBod, inflAssctAftWqltBod);
|
||||
minInflAssctAftWqltTn = Math.min(minInflAssctAftWqltTn, inflAssctAftWqltTn);
|
||||
minInflAssctBfrWqltTp = Math.min(minInflAssctBfrWqltTp, inflAssctBfrWqltTp);
|
||||
minInflAssctAftWqltToc = Math.min(minInflAssctAftWqltToc, inflAssctAftWqltToc);
|
||||
minInflAssctAftWqltSs = Math.min(minInflAssctAftWqltSs, inflAssctAftWqltSs);
|
||||
|
||||
minTpInflWqltBod = Math.min(minTpInflWqltBod, tpInflWqltBod);
|
||||
minTpInflWqltTp = Math.min(minTpInflWqltTp, tpInflWqltTp);
|
||||
|
||||
minInfoRnDay = Math.min(minInfoRnDay, infoRnDay);
|
||||
|
||||
avgEfflWqltBod += efflWqltBod;
|
||||
avgEfflWqltTn += efflWqltTn;
|
||||
avgEfflWqltTp += efflWqltTp;
|
||||
avgefflWqltCod += efflWqltCod;
|
||||
avgEfflWqltSs += efflWqltSs;
|
||||
|
||||
avgInflAssctAftWqltBod += inflAssctAftWqltBod;
|
||||
avgInflAssctAftWqltTn += inflAssctAftWqltTn;
|
||||
avgInflAssctBfrWqltTp += inflAssctBfrWqltTp;
|
||||
avgInflAssctAftWqltToc += inflAssctAftWqltToc;
|
||||
avgInflAssctAftWqltSs += inflAssctAftWqltSs;
|
||||
|
||||
avgTpInflWqltBod += tpInflWqltBod;
|
||||
avgTpInflWqltTp += tpInflWqltTp;
|
||||
|
||||
avgInfoRnDay += infoRnDay;
|
||||
});
|
||||
|
||||
const newFilteredData = [
|
||||
{
|
||||
msrDt: '평균',
|
||||
efflWqltBod: filteredData.length==0?'0.0':(Math.round(avgEfflWqltBod / filteredData.length * 10) / 10).toFixed(1),
|
||||
efflWqltCod: filteredData.length==0?'0.0':(Math.round(avgefflWqltCod / filteredData.length * 10) / 10).toFixed(1),
|
||||
efflWqltSs: filteredData.length==0?'0.0':(Math.round(avgEfflWqltSs / filteredData.length * 10) / 10).toFixed(1),
|
||||
efflWqltTn: filteredData.length==0?'0.000':(Math.round(avgEfflWqltTn / filteredData.length * 1000) / 1000).toFixed(3),
|
||||
efflWqltTp: filteredData.length==0?'0.000':(Math.round(avgEfflWqltTp / filteredData.length * 1000) / 1000).toFixed(3),
|
||||
inflAssctAftWqltBod: filteredData.length==0?'0.0':(Math.round(avgInflAssctAftWqltBod / filteredData.length * 10) / 10).toFixed(1),
|
||||
inflAssctAftWqltTn: filteredData.length==0?'0.000':(Math.round(avgInflAssctAftWqltTn / filteredData.length * 1000) / 1000).toFixed(3),
|
||||
inflAssctBfrWqltTp: filteredData.length==0?'0.000':(Math.round(avgInflAssctBfrWqltTp / filteredData.length * 1000) / 1000).toFixed(3),
|
||||
inflAssctAftWqltToc: filteredData.length==0?'0.0':(Math.round(avgInflAssctAftWqltToc / filteredData.length * 10) / 10).toFixed(1),
|
||||
inflAssctAftWqltSs: filteredData.length==0?'0.0':(Math.round(avgInflAssctAftWqltSs / filteredData.length * 10) / 10).toFixed(1),
|
||||
bscFctCd: "",
|
||||
bscFctNm: "",
|
||||
lclgvrnmntNm: "",
|
||||
sidoNm: "",
|
||||
sggNm: "",
|
||||
addr: "",
|
||||
fctCpc: 0,
|
||||
infoRnDay: filteredData.length==0?'0.0':(Math.round(avgInfoRnDay / filteredData.length * 10) / 10).toFixed(1),
|
||||
tpInflWqltBod: filteredData.length==0?'0.0':(Math.round(avgTpInflWqltBod / filteredData.length * 10) / 10).toFixed(1),
|
||||
tpInflWqltTp: filteredData.length==0?'0.000':(Math.round(avgTpInflWqltTp / filteredData.length * 1000) / 1000).toFixed(3)
|
||||
},
|
||||
{
|
||||
msrDt : '최대',
|
||||
efflWqltBod : Math.round(maxEfflWqltBod * 10) / 10?(Math.round(maxEfflWqltBod * 10) / 10).toFixed(1):'0.0',
|
||||
efflWqltCod : Math.round(maxefflWqltCod * 10) / 10?(Math.round(maxefflWqltCod * 10) / 10).toFixed(1):'0.0',
|
||||
efflWqltSs : Math.round(maxEfflWqltSs * 10) / 10?(Math.round(maxEfflWqltSs * 10) / 10).toFixed(1):'0.0',
|
||||
efflWqltTn : Math.round(maxEfflWqltTn * 1000) / 1000?(Math.round(maxEfflWqltTn * 1000) / 1000).toFixed(3):'0.000',
|
||||
efflWqltTp : Math.round(maxEfflWqltTp * 1000) / 1000?(Math.round(maxEfflWqltTp * 1000) / 1000).toFixed(3):'0.000',
|
||||
inflAssctAftWqltBod : Math.round(maxInflAssctAftWqltBod * 10) / 10?(Math.round(maxInflAssctAftWqltBod * 10) / 10).toFixed(1):'0.0',
|
||||
inflAssctAftWqltTn : Math.round(maxInflAssctAftWqltTn * 1000) / 1000?(Math.round(maxInflAssctAftWqltTn * 1000) / 1000).toFixed(3):'0.000',
|
||||
inflAssctBfrWqltTp : Math.round(maxInflAssctBfrWqltTp * 1000) / 1000?(Math.round(maxInflAssctBfrWqltTp * 1000) / 1000).toFixed(3):'0.000',
|
||||
inflAssctAftWqltToc : Math.round(maxInflAssctAftWqltToc * 10) / 10?(Math.round(maxInflAssctAftWqltToc * 10) / 10).toFixed(1):'0.0',
|
||||
inflAssctAftWqltSs : Math.round(maxInflAssctAftWqltSs * 10) / 10?(Math.round(maxInflAssctAftWqltSs * 10) / 10).toFixed(1):'0.0',
|
||||
bscFctCd: "",
|
||||
bscFctNm: "",
|
||||
lclgvrnmntNm: "",
|
||||
sidoNm: "",
|
||||
sggNm: "",
|
||||
addr: "",
|
||||
fctCpc: 0,
|
||||
infoRnDay: 0,
|
||||
tpInflWqltBod: Math.round(maxTpInflWqltBod * 10) / 10?(Math.round(maxTpInflWqltBod * 10) / 10).toFixed(1):'0.0',
|
||||
tpInflWqltTp: Math.round(maxTpInflWqltTp * 1000) / 1000?(Math.round(maxTpInflWqltTp * 1000) / 1000).toFixed(3):'0.000'
|
||||
},
|
||||
{
|
||||
msrDt : '최소',
|
||||
efflWqltBod : Math.round(minEfflWqltBod * 10) / 10?(Math.round(minEfflWqltBod?minEfflWqltBod:0 * 10) / 10).toFixed(1) : '0.0',
|
||||
efflWqltCod : Math.round(minefflWqltCod * 10) / 10?(Math.round(minefflWqltCod?minefflWqltCod:0 * 10) / 10).toFixed(1) : '0.0',
|
||||
efflWqltSs : Math.round(minEfflWqltSs * 10) / 10?(Math.round(minEfflWqltSs * 10) / 10).toFixed(1) : '0.0',
|
||||
efflWqltTn : Math.round(minEfflWqltTn * 1000) / 1000?(Math.round(minEfflWqltTn * 1000) / 1000).toFixed(3) : '0.000',
|
||||
efflWqltTp : Math.round(minEfflWqltTp * 1000) / 1000?(Math.round(minEfflWqltTp * 1000) / 1000).toFixed(3) : '0.000',
|
||||
inflAssctAftWqltBod : Math.round(minInflAssctAftWqltBod * 10) / 10?(Math.round(minInflAssctAftWqltBod * 10) / 10).toFixed(1) : '0.0',
|
||||
inflAssctAftWqltTn : Math.round(minInflAssctAftWqltTn * 1000) / 1000?(Math.round(minInflAssctAftWqltTn * 1000) / 1000).toFixed(3) : '0.000',
|
||||
inflAssctBfrWqltTp : Math.round(minInflAssctBfrWqltTp * 1000) / 1000?(Math.round(minInflAssctBfrWqltTp * 1000) / 1000).toFixed(3) : '0.000',
|
||||
inflAssctAftWqltToc : Math.round(minInflAssctAftWqltToc * 10) / 10?(Math.round(minInflAssctAftWqltToc * 10) / 10).toFixed(1) : '0.0',
|
||||
inflAssctAftWqltSs : Math.round(minInflAssctAftWqltSs * 10) / 10?(Math.round(minInflAssctAftWqltSs * 10) / 10).toFixed(1) : '0.0',
|
||||
bscFctCd: "",
|
||||
bscFctNm: "",
|
||||
lclgvrnmntNm: "",
|
||||
sidoNm: "",
|
||||
sggNm: "",
|
||||
addr: "",
|
||||
fctCpc: 0,
|
||||
infoRnDay: 0,
|
||||
tpInflWqltBod: Math.round(minTpInflWqltBod * 10) / 10?'0.0':(Math.round(minTpInflWqltBod * 10) / 10).toFixed(1),
|
||||
tpInflWqltTp: Math.round(minTpInflWqltTp * 1000) / 1000?'0.000':(Math.round(minTpInflWqltTp * 1000) / 1000).toFixed(3)
|
||||
},
|
||||
...filteredData
|
||||
];
|
||||
return newFilteredData;
|
||||
}
|
||||
|
||||
// 날짜 필터링 관련 상태
|
||||
const [copyYearList, setCopyYearList] = useState<FacilityWaterQltyProps[]>([]);
|
||||
const [chongInWaterQltyYearList, setChongInWaterQltyYearList] = useState<FacilityWaterQltyProps[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
searchFacilityWaterQltyListHist(searchYear, facilityCd);
|
||||
}, [searchYear, facilityCd, searchFacilityWaterQltyListHist]);
|
||||
|
||||
useEffect(() => {
|
||||
const filteredYearData = setFilterAfterData(facilityWaterQltyYearList);
|
||||
setCopyYearList(filteredYearData as FacilityWaterQltyProps[]);
|
||||
setChongInWaterQltyYearList(filteredYearData as FacilityWaterQltyProps[]);
|
||||
}, [facilityWaterQltyYearList]);
|
||||
|
||||
const yesterDay = new Date();
|
||||
yesterDay.setDate(yesterDay.getDate() - 1);
|
||||
const yesterDayStr = yesterDay.toISOString().split('T')[0];
|
||||
|
||||
const ref = useRef<ReturnType<FacilityWaterQltyProps>>({
|
||||
startDate: new Date(),
|
||||
endDate: new Date(),
|
||||
tabName: '',
|
||||
filteredList: [],
|
||||
});
|
||||
|
||||
const filterData = useCallback((returnType: ReturnType<FacilityWaterQltyProps>) => {
|
||||
const filteredData = setFilterAfterData(returnType.filteredList);
|
||||
setCopyYearList(filteredData as FacilityWaterQltyProps[]);
|
||||
}, []);
|
||||
|
||||
const excelDownload = () => {
|
||||
const excelDownList: modalExcelType[] = [];
|
||||
if(copyYearList.length > 0){
|
||||
copyYearList.forEach((item) => {
|
||||
excelDownList.push({
|
||||
날짜: item.msrDt,
|
||||
"유입BOD(mg/L)": item.inflAssctAftWqltBod,
|
||||
"유입TOC(COD)(mg/L)": item.inflAssctAftWqltToc,
|
||||
"유입SS(mg/L)": item.inflAssctAftWqltSs,
|
||||
"유입TN(mg/L)": item.inflAssctAftWqltTn,
|
||||
"유입TP(mg/L)": item.inflAssctBfrWqltTp,
|
||||
"유출BOD(mg/L)": item.efflWqltBod,
|
||||
"유출TOC(COD)(mg/L)": item.efflWqltCod,
|
||||
"유출SS(mg/L)": item.efflWqltSs,
|
||||
"유출TN(mg/L)": item.efflWqltTn,
|
||||
"유출TP(mg/L)": item.efflWqltTp,
|
||||
"강우량(일)": item.infoRnDay?item.infoRnDay.toString():"0.0",
|
||||
});
|
||||
});
|
||||
}
|
||||
if (excelDownList && excelDownList.length > 0) {
|
||||
downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: searchYear+'년 '+fcltyName + ' 수질현황', sheetNameArray: [fcltyName + ' 수질현황'], headerRange: 'A1:L1' });
|
||||
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
prevExcelListRef.current = excelDownList;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<UITab tabList={tabList1} defaultValue="tab_num1">
|
||||
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownload}>
|
||||
{"엑셀다운로드"}
|
||||
</Button>
|
||||
{/* 처리시설 수질현황 */}
|
||||
<TabsContent value="tab_num1">
|
||||
<UITab tabList={tabList2} defaultValue="tab_term_year">
|
||||
<TabsContent value="tab_term_year">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={facilityWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName={"tab_term_year"}
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[350px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[310px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
|
||||
</UiTable>
|
||||
</div>
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">수질 TMS</h3>
|
||||
<h3 className="text-2xl font-medium text-label text-right">({msrmtDate?msrmtDate.substring(0,4)+'-'+msrmtDate.substring(4,6)+'-'+msrmtDate.substring(6,8):yesterDayStr})</h3>
|
||||
</div>
|
||||
<div className="overflow-y-auto h-[250px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={tmsList}
|
||||
headlist={upHeadListModalTms}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalTms} layoutNum={4} />
|
||||
</UiTable>
|
||||
{msrmtDate != yesterDayStr?.replaceAll('-','')?<h3 className="text-2xl text-left text-gray-500">※전날 데이터 결측으로 인해 가장 최근 데이터 표출함</h3> : ''}
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_summer">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={facilityWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_summer"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { } }
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_winter">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={facilityWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_winter"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_chuncheon">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={facilityWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_chuncheon"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_rain">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={facilityWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_rain"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</TabsContent>
|
||||
|
||||
{/* 총인설비 수질현황 */}
|
||||
<TabsContent value="tab_num2">
|
||||
<UITab tabList={tabList3} defaultValue="tab_term_year_chongin">
|
||||
<TabsContent value="tab_term_year_chongin">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={chongInWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_year"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalChongIn}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalChongIn} layoutNum={5} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_summer_chongin">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={chongInWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_summer"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalChongIn}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalChongIn} layoutNum={5} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_winter_chongin">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={chongInWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_winter"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalChongIn}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalChongIn} layoutNum={5} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import WaterQualityModal from "./modal/page";
|
||||
import type { FacilityWaterQltyProps } from "@/app/store/facilityWaterQlty";
|
||||
|
||||
export default function ProcessFacilitySearch() {
|
||||
const { Common
|
||||
, FacilityWaterQltyMain
|
||||
, initializeCommonData
|
||||
, searchFacilityWaterQltyList
|
||||
} = useFoStore((state) => state) || { FacilityWaterQltyList: { facilityWaterQltyList: [], facilityWaterQltyCount: 0 } };
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectSearchYear,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
mainLabelArray,
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
facilityWaterQltyList,
|
||||
facilityWaterQltyCount,
|
||||
excelList
|
||||
} = FacilityWaterQltyMain;
|
||||
|
||||
const mainList: FacilityWaterQltyProps[] = facilityWaterQltyList || [];
|
||||
|
||||
// 그리드 관련
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
const [searchYearValue, setSearchYearValue] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
|
||||
// 모달 상태 추가
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [fcltyNm, setFcltyNm] = useState<string>("");
|
||||
const [fcltyCd, setFcltyCd] = useState<string>("");
|
||||
const [modalYear, setModalYear] = useState<string>("");
|
||||
|
||||
const searchFcltyQltyList = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
let nameCd, partStr;
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchFacilityWaterQltyList(pageNo, pageCnt, searchYearValue, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchFacilityWaterQltyList(pageNo, pageCnt, searchYearValue);
|
||||
}
|
||||
}, [operationValue, fcltyName, searchFacilityWaterQltyList, searchYearValue, fcltCpct]);
|
||||
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
setUpheadList(upHeadList1)
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYearValue(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
searchFacilityWaterQltyList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
const facility = facilityWaterQltyList[index];
|
||||
if (facility) {
|
||||
setFcltyNm(facility.bscFctNm);
|
||||
setFcltyCd(facility.bscFctCd);
|
||||
setModalYear(searchYearValue);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
}
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
}
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchFacilityWaterQltyList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchFacilityWaterQltyList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '시설별 수질현황',
|
||||
sheetNameArray: ['시설별 수질현황'],
|
||||
headerRange: 'A1:T1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
const excelDownload = useCallback(() => {
|
||||
searchFcltyQltyList(ref.current, 1, 10000);
|
||||
}, [searchFcltyQltyList]);
|
||||
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchFcltyQltyList(ref.current, page, 10);
|
||||
}, [searchFcltyQltyList]);
|
||||
|
||||
const total = facilityWaterQltyCount || 1;
|
||||
console.log('total : ', total);
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="시설별 수질현황" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={mainLabelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className="col-span-3" label={mainLabelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={mainLabelArray[5] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYearValue(val.toString())} value={searchYearValue} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={mainLabelArray[6] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref} isAdmin={false} />
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 수질현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total<10?facilityWaterQltyList.length:total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<WaterQualityModal fcltyName={fcltyNm} facilityCd={fcltyCd} searchYear={modalYear}></WaterQualityModal>}
|
||||
bodyClass="sm:max-w-[90vw] w-[1200px] h-[920px]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open) => !open && closeModal()}
|
||||
noHeaderYn="Y"
|
||||
noFooterYn="Y"
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -1,310 +0,0 @@
|
||||
"use client"
|
||||
import FacilityTermModalHeader from "@/app/components/common/FacilityTermModalHeader";
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { FlowRateModalInterface, modalExcelType } from "@/app/store/flowRate";
|
||||
import { downloadExcel, UITab, UiTable } from "@common/business_components/ui";
|
||||
import { Button, TabsContent } from "@common/components/ui";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import type { ReturnType } from "../../../components/common/FacilityTermModalHeader";
|
||||
|
||||
const tabList = [
|
||||
{ value: 'tab_term_year', label: '연간' },
|
||||
{ value: 'tab_term_summer', label: '하절기' },
|
||||
{ value: 'tab_term_winter', label: '동절기' },
|
||||
{ value: 'tab_term_chuncheon', label: '청천시' },
|
||||
{ value: 'tab_term_rain', label: '강우시' }
|
||||
];
|
||||
|
||||
export default function FlowRateModal(props: { fcltyName: string; facilityCd: string; searchYear: string }) {
|
||||
// 그리드 관련
|
||||
const { Common, FlowRateModal, searchFlowRateModalList } = useFoStore((state) => state);
|
||||
const { btnClass } = Common;
|
||||
const [copyYearList, setCopyYearList] = useState<FlowRateModalInterface[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const prevExcelListRef = useRef<modalExcelType[] | null>(null);
|
||||
const {
|
||||
modalFlowRateListYear,
|
||||
upHeadListFlowRateModalYear,
|
||||
} = FlowRateModal;
|
||||
|
||||
const ref = useRef<ReturnType<FlowRateModalInterface>>({
|
||||
startDate: new Date(),
|
||||
endDate: new Date(),
|
||||
tabName: '',
|
||||
filteredList: [],
|
||||
});
|
||||
|
||||
const filterData = useCallback((returnType: ReturnType<FlowRateModalInterface>) => {
|
||||
if (!returnType.filteredList) return;
|
||||
// 타입을 FlowRateModalInterface[]로 강제 변환하여 타입 오류 해결
|
||||
const filteredData = setFilterAfterData(returnType.filteredList as FlowRateModalInterface[]);
|
||||
setCopyYearList(filteredData);
|
||||
}, []);
|
||||
|
||||
// 필터링 된 후 최대, 최소, 평균 값 계산
|
||||
const setFilterAfterData = (filteredData: FlowRateModalInterface[]) => {
|
||||
if (!filteredData || filteredData.length === 0) return [];
|
||||
|
||||
// 쉼표가 포함된 문자열을 숫자로 변환하는 함수
|
||||
const parseNumber = (value: string | number | null | undefined): number => {
|
||||
if (value === null || value === undefined || value === '') return 0;
|
||||
if (typeof value === 'number') return value;
|
||||
return Number(value.replace(/,/g, ''));
|
||||
};
|
||||
|
||||
let maxtotInflAmnt = 0;
|
||||
let maxinflAmnt = 0;
|
||||
let maxsumFlow = 0;
|
||||
let maxreturnAmnt = 0;
|
||||
let maxefflAmnt = 0;
|
||||
let maxinfoRnDay = 0;
|
||||
|
||||
// 초기값 설정
|
||||
let mintotInflAmnt = parseNumber(filteredData[0]?.totInflAmnt);
|
||||
let mininflAmnt = parseNumber(filteredData[0]?.inflAmnt);
|
||||
let minsumFlow = parseNumber(filteredData[0]?.sumFlow);
|
||||
let minreturnAmnt = parseNumber(filteredData[0]?.returnAmnt);
|
||||
let minefflAmnt = parseNumber(filteredData[0]?.efflAmnt);
|
||||
let mininfoRnDay = parseNumber(filteredData[0]?.infoRnDay);
|
||||
|
||||
let avgtotInflAmnt = 0;
|
||||
let avginflAmnt = 0;
|
||||
let avgsumFlow = 0;
|
||||
let avgreturnAmnt = 0;
|
||||
let avgefflAmnt = 0;
|
||||
let avginfoRnDay = 0;
|
||||
|
||||
filteredData.forEach((item: FlowRateModalInterface) => {
|
||||
const totInflAmnt = parseNumber(item.totInflAmnt);
|
||||
const inflAmnt = parseNumber(item.inflAmnt);
|
||||
const sumFlow = parseNumber(item.sumFlow);
|
||||
const returnAmnt = parseNumber(item.returnAmnt);
|
||||
const efflAmnt = parseNumber(item.efflAmnt);
|
||||
const infoRnDay = parseNumber(item.infoRnDay);
|
||||
maxtotInflAmnt = Math.max(maxtotInflAmnt, totInflAmnt);
|
||||
maxinflAmnt = Math.max(maxinflAmnt, inflAmnt);
|
||||
maxsumFlow = Math.max(maxsumFlow, sumFlow);
|
||||
maxreturnAmnt = Math.max(maxreturnAmnt, returnAmnt);
|
||||
maxefflAmnt = Math.max(maxefflAmnt, efflAmnt);
|
||||
maxinfoRnDay = Math.max(maxinfoRnDay, infoRnDay);
|
||||
|
||||
mintotInflAmnt = Math.min(mintotInflAmnt, totInflAmnt);
|
||||
mininflAmnt = Math.min(mininflAmnt, inflAmnt);
|
||||
minsumFlow = Math.min(minsumFlow, sumFlow);
|
||||
minreturnAmnt = Math.min(minreturnAmnt, returnAmnt);
|
||||
minefflAmnt = Math.min(minefflAmnt, efflAmnt);
|
||||
mininfoRnDay = Math.min(mininfoRnDay, infoRnDay);
|
||||
|
||||
avgtotInflAmnt += totInflAmnt;
|
||||
avginflAmnt += inflAmnt;
|
||||
avgsumFlow += sumFlow;
|
||||
avgreturnAmnt += returnAmnt;
|
||||
avgefflAmnt += efflAmnt;
|
||||
avginfoRnDay += infoRnDay;
|
||||
});
|
||||
|
||||
const newFilteredData = [
|
||||
{
|
||||
msrDt: '평균',
|
||||
totInflAmnt: Math.round(avgtotInflAmnt / filteredData.length * 10) / 10,
|
||||
inflAmnt: Math.round(avginflAmnt / filteredData.length * 10) / 10,
|
||||
sumFlow: Math.round(avgsumFlow / filteredData.length * 10) / 10,
|
||||
returnAmnt: Math.round(avgreturnAmnt / filteredData.length * 10) / 10,
|
||||
efflAmnt: Math.round(avgefflAmnt / filteredData.length * 10) / 10,
|
||||
infoRnDay: avginfoRnDay > 0 ? Math.round(avginfoRnDay / filteredData.length * 10) / 10 : 0,
|
||||
rainEffectDay: 0,
|
||||
},
|
||||
{
|
||||
msrDt: '최대',
|
||||
totInflAmnt: Math.round(maxtotInflAmnt * 10) / 10,
|
||||
inflAmnt: Math.round(maxinflAmnt * 10) / 10,
|
||||
sumFlow: Math.round(maxsumFlow * 10) / 10,
|
||||
returnAmnt: Math.round(maxreturnAmnt * 10) / 10,
|
||||
efflAmnt: Math.round(maxefflAmnt * 10) / 10,
|
||||
infoRnDay: maxinfoRnDay > 0 ? (Math.round(maxinfoRnDay * 10) / 10).toFixed(1) : '0.0',
|
||||
rainEffectDay: 0,
|
||||
},
|
||||
{
|
||||
msrDt: '최소',
|
||||
totInflAmnt: Math.round(mintotInflAmnt * 10) / 10,
|
||||
inflAmnt: Math.round(mininflAmnt * 10) / 10,
|
||||
sumFlow: Math.round(minsumFlow * 10) / 10,
|
||||
returnAmnt: Math.round(minreturnAmnt * 10) / 10,
|
||||
efflAmnt: Math.round(minefflAmnt * 10) / 10,
|
||||
infoRnDay: mininfoRnDay > 0 ? (Math.round(mininfoRnDay * 10) / 10).toFixed(1) : '0.0',
|
||||
rainEffectDay: 0,
|
||||
},
|
||||
...filteredData
|
||||
];
|
||||
return newFilteredData;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
await searchFlowRateModalList(props.facilityCd, props.searchYear);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchData();
|
||||
}, [props.facilityCd, props.searchYear, searchFlowRateModalList]);
|
||||
|
||||
if (isLoading) {
|
||||
return <div>로딩 중...</div>;
|
||||
}
|
||||
|
||||
const excelDownload = () => {
|
||||
const excelDownList: modalExcelType[] = [];
|
||||
if(copyYearList.length > 0){
|
||||
copyYearList.forEach((item) => {
|
||||
excelDownList.push({
|
||||
"날짜": item.msrDt,
|
||||
"총유입량(m³/일)": item.totInflAmnt,
|
||||
"하수유입량(m³/일)": item.inflAmnt,
|
||||
"연계처리량(m³/일)": item.sumFlow,
|
||||
"총인반류수량(m³/일)": item.returnAmnt,
|
||||
"방류량(m³/일)": item.efflAmnt,
|
||||
"강우량": item.infoRnDay,
|
||||
});
|
||||
});
|
||||
}
|
||||
if (excelDownList && excelDownList.length > 0) {
|
||||
downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.searchYear+'년 '+props.fcltyName + ' 유량현황', sheetNameArray: [props.fcltyName + ' 유량현황'], headerRange: 'A1:G1' });
|
||||
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
prevExcelListRef.current = excelDownList;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<UITab tabList={tabList} defaultValue="tab_term_year">
|
||||
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownload}>
|
||||
{"엑셀다운로드"}
|
||||
</Button>
|
||||
<TabsContent value="tab_term_year">
|
||||
<FacilityTermModalHeader<FlowRateModalInterface>
|
||||
searchList={modalFlowRateListYear}
|
||||
fcltyCd={props.facilityCd}
|
||||
fcltyName={props.fcltyName}
|
||||
tabName={"tab_term_year"}
|
||||
searchYear={props.searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="h-[370px] overflow-y-auto overflow-x-auto">
|
||||
<div className="w-[120%]">
|
||||
<UiTable
|
||||
headName="유량현황"
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListFlowRateModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[370px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="tab_term_summer">
|
||||
<FacilityTermModalHeader<FlowRateModalInterface>
|
||||
searchList={modalFlowRateListYear}
|
||||
fcltyCd={props.facilityCd}
|
||||
fcltyName={props.fcltyName}
|
||||
tabName={"tab_term_summer"}
|
||||
searchYear={props.searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="h-[370px] overflow-y-auto overflow-x-auto">
|
||||
<div className="w-[120%]">
|
||||
<UiTable
|
||||
headName="유량현황"
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListFlowRateModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[370px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="tab_term_winter">
|
||||
<FacilityTermModalHeader<FlowRateModalInterface>
|
||||
searchList={modalFlowRateListYear}
|
||||
fcltyCd={props.facilityCd}
|
||||
fcltyName={props.fcltyName}
|
||||
tabName={"tab_term_winter"}
|
||||
searchYear={props.searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="h-[370px] overflow-y-auto overflow-x-auto">
|
||||
<div className="w-[120%]">
|
||||
<UiTable
|
||||
headName="유량현황"
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListFlowRateModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[370px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="tab_term_chuncheon">
|
||||
<FacilityTermModalHeader<FlowRateModalInterface>
|
||||
searchList={modalFlowRateListYear}
|
||||
fcltyCd={props.facilityCd}
|
||||
fcltyName={props.fcltyName}
|
||||
tabName={"tab_term_chuncheon"}
|
||||
searchYear={props.searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="h-[370px] overflow-y-auto overflow-x-auto">
|
||||
<div className="w-[120%]">
|
||||
<UiTable
|
||||
headName="유량현황"
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListFlowRateModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[370px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="tab_term_rain">
|
||||
<FacilityTermModalHeader<FlowRateModalInterface>
|
||||
searchList={modalFlowRateListYear}
|
||||
fcltyCd={props.facilityCd}
|
||||
fcltyName={props.fcltyName}
|
||||
tabName={"tab_term_rain"}
|
||||
searchYear={props.searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="h-[370px] overflow-y-auto overflow-x-auto">
|
||||
<div className="w-[120%]">
|
||||
<UiTable headName="유량현황" tableData={copyYearList} headlist={upHeadListFlowRateModalYear} pageSize={0} total={0} cellClick={undefined} onPageChange={() => {}} className="h-[370px]" boldArray={[0,1,2]}/>
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,207 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import FlowRateModal from "./modal/page";
|
||||
import type { ExcelType } from "@/app/store/flowRate";
|
||||
|
||||
export default function ProcessFacilitySearch() {
|
||||
const {Common
|
||||
,FlowRateSearch
|
||||
,FlowRateList
|
||||
,initializeCommonData
|
||||
,searchFlowRateList
|
||||
} = useFoStore((state) => state);
|
||||
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectSearchYear,
|
||||
selectOperationData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
flowRateSearchLabelArray
|
||||
} = FlowRateSearch;
|
||||
|
||||
// 그리드 관련
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
flowRateList,
|
||||
flowRateCount,
|
||||
excelList
|
||||
} = FlowRateList;
|
||||
|
||||
// 입력값 상태 관리
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
const [searchYearValue, setSearchYearValue] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
const prevExcelListRef = useRef<ExcelType[] | null>(null);
|
||||
|
||||
// 모달 상태 추가
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [fcltyNm, setFcltyNm] = useState<string>("");
|
||||
const [fcltyCd, setFcltyCd] = useState<string>("");
|
||||
|
||||
const searchFlowRate = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchFlowRateList(pageNo, pageCnt, searchYearValue, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchFlowRateList(pageNo, pageCnt, searchYearValue);
|
||||
}
|
||||
}, [operationValue, fcltyName, searchFlowRateList, searchYearValue, fcltCpct]);
|
||||
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
setUpheadList(upHeadList1)
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYearValue(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
searchFlowRateList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
if (flowRateList[index]) {
|
||||
setFcltyNm(flowRateList[index].bscFctNm);
|
||||
setFcltyCd(flowRateList[index].bscFctCd);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
};
|
||||
|
||||
// 페이지 네비게이션션
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchFlowRate(ref.current, page, 10);
|
||||
}, [searchFlowRate]);
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
};
|
||||
|
||||
// 시도 데이터 초기화
|
||||
useEffect(() => {
|
||||
if(!isInit) {
|
||||
initializeCommonData();
|
||||
searchFlowRateList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchFlowRateList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({ data: JSON.parse(JSON.stringify(excelList)), fileName: '시설별 유량현황', sheetNameArray: ['시설별 유량현황'], headerRange: 'A1:O1' });
|
||||
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
prevExcelListRef.current = excelList;
|
||||
}, [excelList]);
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
const excelDownload = useCallback(() => {
|
||||
searchFlowRate(ref.current, 1, 10000);
|
||||
}, [searchFlowRate]);
|
||||
|
||||
const total = flowRateCount;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="시설별 유량현황" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={flowRateSearchLabelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className="col-span-3" label={flowRateSearchLabelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={flowRateSearchLabelArray[5] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYearValue(val.toString())} value={searchYearValue} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={flowRateSearchLabelArray[6] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref} isAdmin={false} />
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 유량현황"} tableData={flowRateList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<FlowRateModal fcltyName={fcltyNm} facilityCd={fcltyCd} searchYear={searchYearValue}></FlowRateModal>}
|
||||
bodyClass="sm:max-w-[90vw] w-[1050px] h-[700px]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open: boolean) => !open && closeModal()}
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import Gis from "@common/business_components/ui/map/Gis";
|
||||
import GisApp from "@common/business_components/ui/map/lib/gis.core";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
interface FeatureData {
|
||||
fid?: string;
|
||||
ftrIdn?: string;
|
||||
id?: string;
|
||||
getGeometry?: () => { getExtent: () => number[] };
|
||||
setStyle?: () => void;
|
||||
}
|
||||
|
||||
interface MapInstance {
|
||||
getLayers: () => { getArray: () => Array<{ getSource?: () => { getFeatureById?: (id: string) => FeatureData | null } }> };
|
||||
getView: () => { fit: (extent: number[], options: object) => void };
|
||||
}
|
||||
|
||||
const Map = () => {
|
||||
const [treeData, setTreeData] = useState([]); // 초기값을 객체 또는 null로 설정
|
||||
const gisMaps = useRef<MapInstance | null>(null);
|
||||
const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태
|
||||
const [isSearchModalOpen, setIsSearchModalOpen] = useState(false); // SearchModal 열림 상태
|
||||
const [featureData, setFeatureData] = useState<FeatureData | null>(null); // 선택된 피쳐 데이터
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}/v1/map`
|
||||
const reqUrl = `${API_URL}/lyrStngs/FO_NETWORK`;
|
||||
const response = await fetch(reqUrl, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
accept: "application/json",
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP 오류! 상태: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json(); // 여기서 json 파싱
|
||||
setTreeData(data); // 데이터 설정
|
||||
} catch (error) {
|
||||
console.error("데이터 불러오기 실패:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// 컴포넌트 마운트 시 1회 실행
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
// SearchModal, GisContent 등에서 호출
|
||||
const onFeatureSelect = (data: FeatureData) => {
|
||||
const map = gisMaps.current;
|
||||
if (!map) {
|
||||
console.warn("지도가 초기화되지 않았습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 항상 같은 select 객체 사용
|
||||
const select = (GisApp.Module.select as unknown) as { resetSelectedFeature: () => void; selectFeature: (feature: FeatureData, selected: boolean) => void } | undefined;
|
||||
if (!select) return;
|
||||
|
||||
// 1. 기존 선택 초기화
|
||||
select.resetSelectedFeature();
|
||||
|
||||
// 2. data가 OpenLayers Feature 인스턴스인지 확인
|
||||
let foundFeature: FeatureData | null = null;
|
||||
if (
|
||||
data &&
|
||||
typeof data.getGeometry === "function" &&
|
||||
typeof data.setStyle === "function"
|
||||
) {
|
||||
// 이미 Feature 인스턴스라면 그대로 사용
|
||||
foundFeature = data;
|
||||
} else {
|
||||
// 아니면 featureId로 맵에서 Feature 인스턴스를 찾아서 사용
|
||||
const featureId = data.fid || data.ftrIdn || data.id;
|
||||
map
|
||||
.getLayers()
|
||||
.getArray()
|
||||
.forEach((layer) => {
|
||||
const source = layer.getSource?.();
|
||||
if (source?.getFeatureById) {
|
||||
const feature = source.getFeatureById(String(featureId).trim());
|
||||
if (feature) foundFeature = feature;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 3. 피처 선택
|
||||
if (foundFeature && foundFeature.getGeometry) {
|
||||
const geometry = foundFeature.getGeometry();
|
||||
if (geometry) {
|
||||
const extent = geometry.getExtent();
|
||||
|
||||
map.getView().fit(extent, {
|
||||
duration: 300,
|
||||
padding: [50, 50, 50, 50],
|
||||
maxZoom: 16,
|
||||
constrainResolution: true,
|
||||
nearest: true,
|
||||
});
|
||||
}
|
||||
select.selectFeature(foundFeature, true);
|
||||
} else {
|
||||
console.warn("OpenLayers Feature를 찾을 수 없습니다:", data);
|
||||
}
|
||||
|
||||
setFeatureData(data);
|
||||
setIsOpen(true);
|
||||
setIsSearchModalOpen(false);
|
||||
};
|
||||
|
||||
// onCheckedLayersChange handler
|
||||
const handleCheckedLayersChange = (checkedIds: string[], checkedNodesData: unknown[]) => {
|
||||
// Handle checked layers change if needed
|
||||
console.log('Checked layers changed:', checkedIds, checkedNodesData);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-container">
|
||||
<Gis
|
||||
treeData={treeData}
|
||||
isSearch={false}
|
||||
gisMaps={gisMaps}
|
||||
isMiniMap={true}
|
||||
searchView={null}
|
||||
detailView={null}
|
||||
onFeatureSelect={onFeatureSelect}
|
||||
setIsOpen={setIsOpen}
|
||||
setFeatureData={setFeatureData}
|
||||
featureData={featureData}
|
||||
setIsSearchModalOpen={setIsSearchModalOpen}
|
||||
isOpen={isOpen}
|
||||
isSearchModalOpen={isSearchModalOpen}
|
||||
onCheckedLayersChange={handleCheckedLayersChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Map;
|
||||
@@ -1,197 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
export default function PlanSewage() {
|
||||
const {Common
|
||||
,PlanSewage
|
||||
,PlanSewageSearch
|
||||
,initializeCommonData
|
||||
,searchPlanSewageList
|
||||
} = useFoStore((state) => state) || { processAreaList: { processAreaList: [] }};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectSearchYear,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
labelArray,
|
||||
} = PlanSewageSearch;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
planSewageList,
|
||||
planSewageCount,
|
||||
excelList
|
||||
} = PlanSewage;
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
// 그리드 관련
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
// 모달 상태 추가
|
||||
|
||||
// 초기화 변수
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
// 표 너비
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
// 구분별 그리드 헤더
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
// 용량별
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
// 시설명
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
// 시설상태
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
*/
|
||||
// 초기화
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
setUpheadList(upHeadList1);
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYear(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* useEffect
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchPlanSewageList(1, 10, searchYear, ref.current.partValue);
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchYear, searchPlanSewageList]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('excelList' , excelList);
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '계획하수량 산정지표 현황',
|
||||
sheetNameArray: ['계획하수량 산정지표 현황'],
|
||||
headerRange: 'A1:M1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
*/
|
||||
// 조회
|
||||
const searchPlanSewage = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchPlanSewageList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchPlanSewageList(pageNo, pageCnt, searchYear, partValue);
|
||||
}
|
||||
}, [operationValue, fcltyName, searchPlanSewageList, searchYear, fcltCpct]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback((searchReturn: ReturnType) => {
|
||||
searchPlanSewage(searchReturn, 1, 10000);
|
||||
}, [searchPlanSewage]);
|
||||
|
||||
// 페이지 변경
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchPlanSewage(ref.current, page, 10);
|
||||
}, [searchPlanSewage]);
|
||||
|
||||
const mainList = planSewageList || [];
|
||||
const total = planSewageCount || 0;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="계획하수량 산정지표 현황" />
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className={"col-span-3"} label={labelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={labelArray[5] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={labelArray[6] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref} isAdmin={false}/>
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={ undefined } headName={"계획하수량 산정지표 현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
import { TableHead, TableRow } from "@common/components/ui";
|
||||
import type { TableUpperProps } from "../../store/dashboard";
|
||||
|
||||
const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProps[], layoutNum: number }) => {
|
||||
return (
|
||||
layoutNum === 0 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={3} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={3} key={head.id}>{head.title}</TableHead> :
|
||||
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={3} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={3} key={head.id}>{head.title}</TableHead> :
|
||||
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={2}>{'행정구역'}</TableHead> :
|
||||
head.upName === 'upChangeRe3' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={6}>{'증설계획'}</TableHead> :
|
||||
head.upName === 'upChangeRe4' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={19}>{'시설계획'}</TableHead> :
|
||||
!head.upName ? <TableHead rowSpan={3} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => (
|
||||
head.upName === 'upChangeRe4' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'증설계획(m³/일)'}</TableHead> :
|
||||
head.upName === 'upChangeRe5' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'처리인구(인)'}</TableHead> :
|
||||
head.upName === 'upChangeRe6' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={7}>{'처리구역(k㎡)'}</TableHead> :
|
||||
null
|
||||
))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe' || head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4' || head.upName === 'upChangeRe5' || head.upName === 'upChangeRe6') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 1 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={3} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={3} key={head.id}>{head.title}</TableHead> :
|
||||
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={3} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={3} key={head.id}>{head.title}</TableHead> :
|
||||
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={3}>{'유역'}</TableHead> :
|
||||
head.upName === 'upChangeRe3' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={6}>{'증설계획'}</TableHead> :
|
||||
!head.upName ? <TableHead rowSpan={3} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => (
|
||||
head.upName === 'upChangeRe4' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'증설계획(m³/일)'}</TableHead> :
|
||||
head.upName === 'upChangeRe5' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'처리인구(인)'}</TableHead> :
|
||||
head.upName === 'upChangeRe6' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={7}>{'처리구역(k㎡)'}</TableHead> :
|
||||
null
|
||||
))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe' || head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4' || head.upName === 'upChangeRe5' || head.upName === 'upChangeRe6') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={2} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.upName === 'upChangeRe1' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={3}>{'권역'}</TableHead> :
|
||||
head.upName === 'upChangeRe2' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={2}>{'환경청'}</TableHead> :
|
||||
head.upName === 'upChangeRe3' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'증설계획(m³/일)'}</TableHead> :
|
||||
head.upName === 'upChangeRe5' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'처리인구(인)'}</TableHead> :
|
||||
head.upName === 'upChangeRe6' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={7}>{'처리구역(k㎡)'}</TableHead> :
|
||||
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2' ||head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4' || head.upName === 'upChangeRe5' || head.upName === 'upChangeRe6') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export { HeadMakeColSpan };
|
||||
@@ -1,55 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Table, TableCell, TableHead, TableHeader, TableRow } from "@common/components/ui";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export default function ProcessFacilityInfoModal(props: { fcltyName: string; facilityCd : string;}) {
|
||||
// 그리드 관련
|
||||
const {ProcessAreaDetail, initModalData} = useFoStore((state) => state);
|
||||
|
||||
useEffect(() => {
|
||||
initModalData(props.facilityCd);
|
||||
}, [initModalData, props.facilityCd]);
|
||||
|
||||
const {
|
||||
upHeadListFcltyImproveInfo,
|
||||
gridListFcltyImproveInfo,
|
||||
upHeadListProcessPopulation,
|
||||
gridListProcessPopulation,
|
||||
upHeadListProcessAreaPlan,
|
||||
gridListProcessAreaPlan,
|
||||
} = ProcessAreaDetail
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListDiv>
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-1/6">{'시설명'}</TableHead>
|
||||
<TableCell className="w-1/3">{props.fcltyName}</TableCell>
|
||||
<TableHead className="w-1/6">{'시설코드'}</TableHead>
|
||||
<TableCell className="w-1/3">{props.facilityCd}</TableCell>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<ListDiv>
|
||||
<UiTable headName={"시설증설 계획"} tableData={gridListFcltyImproveInfo} headlist={upHeadListFcltyImproveInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
</UiTable>
|
||||
</ListDiv>
|
||||
<ListDiv>
|
||||
<UiTable headName={"처리인구 계획"} tableData={gridListProcessPopulation} headlist={upHeadListProcessPopulation} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
</UiTable>
|
||||
</ListDiv>
|
||||
<ListDiv>
|
||||
<UiTable headName={"처리구역 계획"} tableData={gridListProcessAreaPlan} headlist={upHeadListProcessAreaPlan} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
</UiTable>
|
||||
</ListDiv>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import ProcessFacilityInfoModal from "./modal/page";
|
||||
|
||||
export default function ProcessArea() {
|
||||
const {Common,
|
||||
ProcessArea,
|
||||
ProcessAreaSearch,
|
||||
initializeCommonData,
|
||||
searchProcessAreaList
|
||||
} = useFoStore((state) => state) || {
|
||||
Common: { isInit: false, selectSidoData: [], selectSigunData: [], selectRegionData: [], selectUnitWaterShedData: [], selectMiddleRegionData: [], selectEnvPartData: [], selectSearchYear: [{ val: "0" }], btnClass: "" },
|
||||
ProcessArea: { processAreaList: [], processAreaCount: 0, excelList: [], upHeadList1: [] },
|
||||
ProcessAreaSearch: { processFacilityLabelArray: [] },
|
||||
initializeCommonData: () => {},
|
||||
searchProcessAreaList: () => {}
|
||||
};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectSearchYear,
|
||||
btnClass,
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
processFacilityLabelArray,
|
||||
} = ProcessAreaSearch;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
processAreaList,
|
||||
processAreaCount,
|
||||
excelList
|
||||
} = ProcessArea;
|
||||
|
||||
const mainList: Record<string, unknown>[] = processAreaList || [];
|
||||
// 그리드 관련
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
// 모달 상태 추가
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [fcltyNm, setFcltyNm] = useState<string>("");
|
||||
const [fcltyCd, setFcltyCd] = useState<string>("");
|
||||
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
const [searchYearValue, setSearchYearValue] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
const searchProcessArea = useCallback(({ sidoText, sigunText}: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
searchProcessAreaList(pageNo, pageCnt, sidoText, sigunText, searchYearValue);
|
||||
}, [searchProcessAreaList, searchYearValue]);
|
||||
|
||||
// 조회
|
||||
const chkVal = useCallback(() => {
|
||||
setResetPage(true);
|
||||
}, []);
|
||||
|
||||
// 초기화
|
||||
const resetVal = () => {
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
setSearchYearValue(selectSearchYear[0]?.val || "0");
|
||||
searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val);
|
||||
}
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
if (processAreaList[index]) {
|
||||
setFcltyNm(processAreaList[index].swtrmtFcltNm);
|
||||
setFcltyCd(processAreaList[index].swtrmtFcltCd);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
};
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val);
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchProcessAreaList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '처리구역정보',
|
||||
sheetNameArray: ['처리구역정보'],
|
||||
headerRange: 'A1:W1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
const excelDownload = useCallback(() => {
|
||||
searchProcessArea(ref.current, 1, 10000);
|
||||
}, [searchProcessArea]);
|
||||
|
||||
const handlePageChange = useCallback((pageNo: number) => {
|
||||
setResetPage(false);
|
||||
searchProcessArea(ref.current, pageNo, 10);
|
||||
}, [searchProcessArea]);
|
||||
|
||||
const total = processAreaCount;
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="처리구역정보" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={processFacilityLabelArray[6] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYearValue(val.toString())} value={searchYearValue} selectClass={undefined}/>
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref}
|
||||
isAdmin={true}
|
||||
/>
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className="w-[180%]">
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"처리구역정보"} tableData={mainList} headlist={upHeadList1} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<ProcessFacilityInfoModal fcltyName={fcltyNm} facilityCd={fcltyCd}></ProcessFacilityInfoModal>}
|
||||
bodyClass="sm:max-w-[90vw] w-[1200px] h-[900px]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open: boolean) => !open && closeModal()}
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -1,211 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/dashboard";
|
||||
import { UITab, UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import {
|
||||
TabsContent
|
||||
} from "@common/components";
|
||||
import { Table, TableCell, TableHead, TableRow } from "@common/components/ui";
|
||||
|
||||
type ModalType = {
|
||||
fcltyName: string;
|
||||
facilityCd : string;
|
||||
sido : string;
|
||||
gugun : string;
|
||||
daddr : string;
|
||||
fctCpc : number | '';
|
||||
trtFrfNm : string;
|
||||
rnDt : string;
|
||||
cmplDt : string;
|
||||
trstOprEtpNm : string;
|
||||
bscFctClsNm : string;
|
||||
mnstr : string;
|
||||
efflWtrrgn : string;
|
||||
lgbsn : string;
|
||||
efflWqltStndrdNm : string;
|
||||
rgnNm : string;
|
||||
rvbsn : string;
|
||||
}
|
||||
|
||||
// 시설계획 table header 변경
|
||||
const headMakeList = (upHeadList: TableUpperProps[], gridNum:number) => {
|
||||
if(gridNum===1){
|
||||
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={6} style={{ whiteSpace: 'pre-line' }}>{'증설계획(m³/일)'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.upName === 'upChangeRe'?<TableHead className="w-150" key={head.id}>{head.title}</TableHead>:null))}
|
||||
</TableRow>
|
||||
</> )
|
||||
} else if(gridNum===2){
|
||||
return ( <>
|
||||
<TableRow>{
|
||||
upHeadList.map((head: TableUpperProps) =>
|
||||
(!head.upSequnce?<TableHead rowSpan={2}key={head.id}>{head.title}</TableHead>:
|
||||
head.upName === 'upChangeRe1'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={6} style={{ whiteSpace: 'pre-line' }}>{'계획유입수질(mg/L)'}</TableHead>:
|
||||
head.upName === 'upChangeRe2'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={6} style={{ whiteSpace: 'pre-line' }}>{'설계유입수질(mg/L)'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.upName === 'upChangeRe1'||head.upName === 'upChangeRe2'?<TableHead style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>:null))}
|
||||
</TableRow>
|
||||
</> )
|
||||
} else if(gridNum===3){
|
||||
return ( <>
|
||||
<TableRow>{
|
||||
upHeadList.map((head: TableUpperProps) =>
|
||||
(!head.upSequnce?<TableHead key={head.id}>{head.title}</TableHead>:
|
||||
head.upName === 'upChangeRe1'&& head.upSequnce=== 1?<TableHead key={head.id} colSpan={2} style={{ whiteSpace: 'pre-line' }}>{'사업기간'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
</> )
|
||||
} else if(gridNum===4){
|
||||
return ( <>
|
||||
<TableRow>{
|
||||
upHeadList.map((head: TableUpperProps) =>
|
||||
(!head.upSequnce?<TableHead rowSpan={2}key={head.id}>{head.title}</TableHead>:
|
||||
head.upName === 'upChangeRe1'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={6} style={{ whiteSpace: 'pre-line' }}>{'계획유입수질(mg/L)'}</TableHead>:
|
||||
head.upName === 'upChangeRe2'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={6} style={{ whiteSpace: 'pre-line' }}>{'설계유입수질(mg/L)'}</TableHead>:
|
||||
head.upName === 'upChangeRe3'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={6} style={{ whiteSpace: 'pre-line' }}>{'계획방류수질(mg/L)'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.upName === 'upChangeRe1'||head.upName === 'upChangeRe2'||head.upName === 'upChangeRe3'?<TableHead style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>:null))}
|
||||
</TableRow>
|
||||
</> )
|
||||
}
|
||||
}
|
||||
|
||||
export default function ProcessFacilityInfoModal(props: ModalType) {
|
||||
// 그리드 관련
|
||||
const {ProcessFacilityDetail} = useFoStore((state) => state);
|
||||
|
||||
const {
|
||||
upHeadListPlanInfo,
|
||||
gridListPlanInfo,
|
||||
upHeadListFcltyAreaInfo,
|
||||
gridListFcltyAreaInfo,
|
||||
|
||||
upHeadListFcltyHistInfo,
|
||||
gridListFcltyHistInfo,
|
||||
upHeadListFcltyWaterQltyInfo,
|
||||
gridListFcltyWaterQltyInfo,
|
||||
|
||||
upHeadListLegalWaterQlty,
|
||||
gridListLegalWaterQlty,
|
||||
} = ProcessFacilityDetail;
|
||||
|
||||
gridListFcltyAreaInfo.map((item) => {
|
||||
item.efflWtrrgn = props.efflWtrrgn;
|
||||
item.lgbsn = props.lgbsn;
|
||||
item.efflWqltStndrdNm = props.efflWqltStndrdNm;
|
||||
item.rgnNm = props.rgnNm;
|
||||
item.rvbsn = props.rvbsn;
|
||||
})
|
||||
|
||||
const tabList = [
|
||||
{ value: 'common_info', label: '기본정보' },
|
||||
{ value: 'history_info', label: '이력정보' },
|
||||
];
|
||||
const fctCpc = props.fctCpc ? props.fctCpc.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : '';
|
||||
const upHeadListPlanInfoChange = headMakeList(upHeadListPlanInfo, 2);
|
||||
const upHeadListFcltyHistInfoChange = headMakeList(upHeadListFcltyHistInfo, 3);
|
||||
const upHeadListFcltyWaterQltyInfoChange = headMakeList(upHeadListFcltyWaterQltyInfo, 4);
|
||||
return (
|
||||
<>
|
||||
<ListDiv className="!h-[80px]">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'시설명'}</TableHead>
|
||||
<TableCell className="w-1/3">{props.fcltyName}</TableCell>
|
||||
<TableHead className="w-1/6">{'시설코드'}</TableHead>
|
||||
<TableCell className="w-1/3">{props.facilityCd}</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<div className="overflow-y-auto">
|
||||
<div className="!h-[600px]">
|
||||
<ListDiv className="">
|
||||
<UITab tabList={tabList} defaultValue="common_info">
|
||||
<TabsContent value="common_info">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">시설 기본정보</h3>
|
||||
</div>
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'시설명'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.fcltyName}</TableCell>
|
||||
<TableHead className="w-1/6">{'시설구분'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.bscFctClsNm}</TableCell>
|
||||
<TableHead className="w-1/6">{'시설용량(m³/일)'}</TableHead>
|
||||
<TableCell className="w-1/6">{fctCpc}</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'시도'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.sido}</TableCell>
|
||||
<TableHead className="w-1/6">{'시군구'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.gugun}</TableCell>
|
||||
<TableHead className="w-1/6">{'가동개시일'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.rnDt}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'주소'}</TableHead>
|
||||
<TableCell className="w-1/6" colSpan={3}>{props.daddr}</TableCell>
|
||||
<TableHead className="w-1/6">{'준공일'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.cmplDt}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'공법'}</TableHead>
|
||||
<TableCell className="w-1/6" colSpan={3}>{props.trtFrfNm}</TableCell>
|
||||
<TableHead className="w-1/6">{'관리대행업자'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.trstOprEtpNm}</TableCell>
|
||||
</TableRow>
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
<UiTable headName={"시설 계획정보"} tableData={gridListPlanInfo} headlist={upHeadListPlanInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
{upHeadListPlanInfoChange}
|
||||
</UiTable>
|
||||
<UiTable headName={"시설 법적방류수질"} tableData={gridListLegalWaterQlty} headlist={upHeadListLegalWaterQlty} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}} />
|
||||
<UiTable headName={"시설 수역 및 구역정보"} tableData={gridListFcltyAreaInfo} headlist={upHeadListFcltyAreaInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}} />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="history_info">
|
||||
<ListDiv>
|
||||
<div className="h-[270px] w-full overflow-y-auto overflow-x-hidden">
|
||||
<div className="h-[130%]">
|
||||
<UiTable headName={"시설 이력관리"} tableData={gridListFcltyHistInfo} headlist={upHeadListFcltyHistInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
{upHeadListFcltyHistInfoChange}
|
||||
</UiTable>
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<ListDiv>
|
||||
<div className="h-[270px] w-full overflow-y-auto overflow-x-hidden">
|
||||
<div className="h-[130%]">
|
||||
<UiTable headName={"시설 수질정보"} tableData={gridListFcltyWaterQltyInfo} headlist={upHeadListFcltyWaterQltyInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
{upHeadListFcltyWaterQltyInfoChange}
|
||||
</UiTable>
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</ListDiv>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,294 +0,0 @@
|
||||
"use client"
|
||||
import { HeadMakeColSpan } from "@/app/components/common/HeadMakeColSpan";
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import ProcessFacilityInfoModal from "./modal/page";
|
||||
|
||||
export default function ProcessFacilitySearch() {
|
||||
const {Common
|
||||
,ProcessFacility
|
||||
,ProcessFacilityList
|
||||
,initializeCommonData
|
||||
//시설데이터 조회
|
||||
,searchProcessFacility
|
||||
//시설데이터 이력정보 조회
|
||||
,searchProcessFacilityHist
|
||||
//시설데이터 수질정보 조회
|
||||
,searchProcessFacilityWaterQlty
|
||||
} = useFoStore((state) => state) || { ProcessFacilityList: { processFacilityList: [], processFacilityCount: 0 }};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectFacilityPartData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
btnClass,
|
||||
} = Common;
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if(!isInit) {
|
||||
initializeCommonData();
|
||||
searchProcessFacility(1, 10, 'A', '0', '0', '0', '0');
|
||||
}
|
||||
}, [isInit
|
||||
,initializeCommonData
|
||||
,searchProcessFacility
|
||||
]);
|
||||
|
||||
const {
|
||||
processFacilityLabelArray,
|
||||
} = ProcessFacility;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
excelList
|
||||
} = ProcessFacilityList;
|
||||
|
||||
const processFacilityList = ProcessFacilityList?.processFacilityList || [];
|
||||
|
||||
// 그리드 관련
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
const [facilityPartValue, setFacilityPartValue] = useState<string>("0");
|
||||
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
|
||||
const [partValue, setPartValue] = useState<string>("A");
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
const [upHeadList, setUpheadList] = useState(upHeadList1);
|
||||
|
||||
/**
|
||||
* 모달 상태 변수
|
||||
* selectedRow : 클릭한 행의 index
|
||||
* modalFcltyNm : 시설명
|
||||
* modalFcltyCd : 시설코드
|
||||
* modalSido : 시도
|
||||
* modalGugun : 시군구
|
||||
* modalLaeNm : 주소
|
||||
* modalFctCpc : 시설용량
|
||||
* modalTrtFrfNm : 공법
|
||||
* modalRnDt : 가동개시일
|
||||
* modalCmplDt : 준공일
|
||||
* modalTrstOprEtpNm : 관리대행업자
|
||||
* modalBscFctClsNm : 시설구분
|
||||
*/
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [modalFcltyNm, setModalFcltyNm] = useState<string>("");
|
||||
const [modalFcltyCd, setModalFcltyCd] = useState<string>("");
|
||||
const [modalSido, setModalSido] = useState<string>("");
|
||||
const [modalGugun, setModalGugun] = useState<string>("");
|
||||
const [modalAddr, setModalAddr] = useState<string>("");
|
||||
const [modalFctCpc, setModalFctCpc] = useState<number | ''>("");
|
||||
const [modalTrtFrfNm, setModalTrtFrfNm] = useState<string>("");
|
||||
const [modalRnDt, setModalRnDt] = useState<string>("");
|
||||
const [modalCmplDt, setModalCmplDt] = useState<string>("");
|
||||
const [modalTrstOprEtpNm, setModalTrstOprEtpNm] = useState<string>("");
|
||||
const [modalBscFctClsNm, setModalBscFctClsNm] = useState<string>("");
|
||||
const [modalMnstr, setModalMnstr] = useState<string>("");
|
||||
const [modalEfflWtrrgn, setModalEfflWtrrgn] = useState<string>("");
|
||||
const [modalLgbsn, setModalLgbsn] = useState<string>("");
|
||||
const [modalEfflWqltStndrdNm, setModalEfflWqltStndrdNm] = useState<string>("");
|
||||
const [modalRgnNm, setModalRgnNm] = useState<string>("");
|
||||
const [modalRvbsn, setModalRvbsn] = useState<string>("");
|
||||
const [isSearch, setIsSearch] = useState<boolean>(false);
|
||||
|
||||
// 표 레이아웃 상태
|
||||
const chkVal = useCallback((result:ReturnType) => {
|
||||
setPartValue(result.partValue);
|
||||
setResetPage(true);
|
||||
setIsSearch(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
switch (partValue) {
|
||||
case 'A':
|
||||
setWidthSize("w-[130%]");
|
||||
setUpheadList(upHeadList1);
|
||||
break;
|
||||
case 'R':
|
||||
setWidthSize("w-[140%]");
|
||||
setUpheadList(upHeadList2);
|
||||
break;
|
||||
case 'G':
|
||||
setWidthSize("w-[150%]");
|
||||
setUpheadList(upHeadList3);
|
||||
break;
|
||||
}
|
||||
}, [partValue, upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({ data: excelList as unknown as JSON[], fileName: '처리시설 시설정보', sheetNameArray: ['처리시설 시설정보'], headerRange: 'A1:P1' });
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
const searchFcltyList = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=10) => {
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
searchProcessFacility(pageNo, pageCnt, partStr, nameCd || '0', fcltCpct, operationValue, facilityPartValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
if(isSearch) {
|
||||
setIsSearch(false);
|
||||
}
|
||||
}, [facilityPartValue, fcltCpct, fcltyName, isSearch, operationValue, searchProcessFacility])
|
||||
|
||||
const changePage = useCallback((page: number) => {
|
||||
searchFcltyList(ref.current, page);
|
||||
},[searchFcltyList])
|
||||
|
||||
const resetVal = () => {
|
||||
// SelectBox 초기화 - 각 selectArray의 첫 번째 옵션 값 사용
|
||||
searchProcessFacility(1, 10, 'A', '0', '0', '0', '0', '');
|
||||
setFcltCpct("0");
|
||||
setOperationValue("0");
|
||||
setFacilityPartValue("0");
|
||||
setPartValue('A');
|
||||
setUpheadList(upHeadList1);
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
|
||||
// ref를 사용하여 input 값 초기화
|
||||
if (inputRef.current) {
|
||||
inputRef.current.value = "";
|
||||
}
|
||||
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
const facility = processFacilityList[index];
|
||||
if (facility) {
|
||||
setModalFcltyNm(facility.bscFctNm);
|
||||
setModalFcltyCd(facility.bscFctCd);
|
||||
setModalSido(facility.sido);
|
||||
setModalGugun(facility.gugun);
|
||||
setModalAddr(facility.daddr);
|
||||
setModalFctCpc(Number(facility.fctCpc));
|
||||
setModalTrtFrfNm(facility.trtFrfNm);
|
||||
setModalRnDt(facility.rnDt);
|
||||
setModalCmplDt(facility.cmplDt);
|
||||
setModalTrstOprEtpNm(facility.trstOprEtpNm);
|
||||
setModalBscFctClsNm(facility.bscFctClsNm);
|
||||
setModalMnstr(facility.mnstr);
|
||||
setModalEfflWtrrgn(facility.efflWtrrgn);
|
||||
setModalLgbsn(facility.lgbsn);
|
||||
setModalEfflWqltStndrdNm(facility.efflWqltStndrdNm);
|
||||
setModalRgnNm(facility.rgnNm);
|
||||
setModalRvbsn(facility.rvbsn);
|
||||
|
||||
searchProcessFacilityHist(facility.bscFctCd);
|
||||
searchProcessFacilityWaterQlty(facility.bscFctCd);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
}
|
||||
|
||||
const excelDownload = useCallback(() => {
|
||||
searchFcltyList(ref.current, 1, 10000);
|
||||
}, [searchFcltyList]);
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
}
|
||||
|
||||
const total = ProcessFacilityList?.processFacilityCount || 1;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="처리시설 시설정보" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={processFacilityLabelArray[3] as string} selectArray={selectUpdownData} onSelectValue={val => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className="col-span-3" label={processFacilityLabelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={processFacilityLabelArray[5] as string} selectArray={selectOperationData} onSelectValue={val => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={processFacilityLabelArray[6] as string} selectArray={selectFacilityPartData} onSelectValue={val => setFacilityPartValue(val.toString())} value={facilityPartValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref} isAdmin={false} />
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable
|
||||
cellClick={(index: number | undefined) => index !== undefined && cellClick(index)}
|
||||
headName={"처리시설 시설정보"}
|
||||
tableData={processFacilityList}
|
||||
headlist={upHeadList}
|
||||
pageSize={10}
|
||||
total={total}
|
||||
resetPageNo={resetPage}
|
||||
onPageChange={changePage}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadList} layoutNum={partValue}/>
|
||||
</UiTable>
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<span className="text-2xl text-gray-500">※계획유입수질 및 설계유입수질은 해당 BOD를 나타냄</span>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<ProcessFacilityInfoModal fcltyName={modalFcltyNm} facilityCd={modalFcltyCd} sido={modalSido} gugun={modalGugun} daddr={modalAddr} fctCpc={modalFctCpc} trtFrfNm={modalTrtFrfNm} rnDt={modalRnDt} cmplDt={modalCmplDt} trstOprEtpNm={modalTrstOprEtpNm} bscFctClsNm={modalBscFctClsNm} mnstr={modalMnstr} efflWtrrgn={modalEfflWtrrgn} lgbsn={modalLgbsn} efflWqltStndrdNm={modalEfflWqltStndrdNm} rgnNm={modalRgnNm} rvbsn={modalRvbsn}></ProcessFacilityInfoModal>}
|
||||
bodyClass="sm:max-w-[70vw] sm:max-h-[95vh]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open) => !open && closeModal()}
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
export default function Rdi() {
|
||||
const {Common
|
||||
,initializeCommonData
|
||||
,Rdi
|
||||
,RdiSearch
|
||||
,searchRdiList
|
||||
} = useFoStore((state) => state) || { processAreaList: { processAreaList: [] }};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectSearchYear,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
labelArray,
|
||||
} = RdiSearch;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
rdiList,
|
||||
rdiCount,
|
||||
excelList,
|
||||
} = Rdi;
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
// 그리드 관련
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
// 초기화 변수
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
// 표 너비
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
// 구분별 그리드 헤더
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
// 용량별
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
// 시설명
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
// 시설상태
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
*/
|
||||
// 초기화
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
|
||||
setUpheadList(upHeadList1)
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYear(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
searchRdiList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* useEffect
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchRdiList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchRdiList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: 'RDII추정',
|
||||
sheetNameArray: ['RDII추정'],
|
||||
headerRange: 'A1:O1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
*/
|
||||
// 조회
|
||||
const searchRdi = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchRdiList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchRdiList(pageNo, pageCnt, searchYear);
|
||||
}
|
||||
}, [operationValue, fcltyName, searchRdiList, searchYear, fcltCpct]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback(() => {
|
||||
searchRdi(ref.current, 1, 10000);
|
||||
}, [searchRdi]);
|
||||
|
||||
// 페이지 변경
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchRdi(ref.current, page, 10);
|
||||
}, [searchRdi]);
|
||||
|
||||
const mainList: Record<string, string | number | boolean>[] = rdiList || [];
|
||||
const total = rdiCount || 0;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="RDII추정" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput ref={searchInputRef} className={"col-span-3"} label={labelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={labelArray[5] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={labelArray[6] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref} isAdmin={false} />
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={ undefined } headName={"RDII추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
<span className="text-2xl text-gray-500">※주) 처리장 유입부에서 측정된 유량 및 수질조사 자료를 기준으로 산정된 결과임</span>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { SewageOccurDetailProps } from "@/app/store/sewageOccur";
|
||||
import { DateMonthPicker, UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Table, TableCell, TableHead, TableRow } from "@common/components/ui";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function SewageOccurModal(props: { fcltyName: string; facilityCd : string; searchYear : string}) {
|
||||
// 그리드 관련
|
||||
const {SewageOccurDetail} = useFoStore((state) => state);
|
||||
|
||||
// searchYear 유효성 검사 및 기본값 설정
|
||||
const validSearchYear = props.searchYear && /^\d{4}$/.test(props.searchYear) ? props.searchYear : new Date().getFullYear().toString();
|
||||
|
||||
const [startYearMonth, setStartYearMonth] = useState(validSearchYear+'01');
|
||||
const [endYearMonth, setEndYearMonth] = useState(validSearchYear+'12');
|
||||
const [detailList, setDetailList] = useState<SewageOccurDetailProps[]>([]);
|
||||
const {
|
||||
upHeadListSewageOccurDetail,
|
||||
gridListSewageOccurDetail
|
||||
} = SewageOccurDetail;
|
||||
|
||||
useEffect(() => {
|
||||
setDetailList(gridListSewageOccurDetail);
|
||||
}, [gridListSewageOccurDetail]);
|
||||
|
||||
useEffect(() => {
|
||||
const filteredList = gridListSewageOccurDetail.filter(item => item.msrDt.replace(/-/g, '') >= startYearMonth && item.msrDt.replace(/-/g, '') <= endYearMonth);
|
||||
let maxWaterUsage = 0;
|
||||
let maxSwageChangePercent = 0;
|
||||
let maxEstimationSewage = 0;
|
||||
|
||||
let minWaterUsage = filteredList[0]?.waterUsage || 0;
|
||||
let minSwageChangePercent = filteredList[0]?.swageChangePercent || 0;
|
||||
let minEstimationSewage = filteredList[0]?.estimationSewage || 0;
|
||||
|
||||
let totalWaterUsage = 0;
|
||||
let totalSwageChangePercent = 0;
|
||||
let totalEstimationSewage = 0;
|
||||
|
||||
let avgWaterUsage = 0;
|
||||
let avgSwageChangePercent = 0;
|
||||
let avgEstimationSewage = 0;
|
||||
|
||||
filteredList.forEach(item => {
|
||||
if (item.waterUsage > maxWaterUsage) {
|
||||
maxWaterUsage = item.waterUsage;
|
||||
}
|
||||
if (item.swageChangePercent > maxSwageChangePercent) {
|
||||
maxSwageChangePercent = item.swageChangePercent;
|
||||
}
|
||||
if (item.estimationSewage > maxEstimationSewage) {
|
||||
maxEstimationSewage = item.estimationSewage;
|
||||
}
|
||||
|
||||
if (item.waterUsage < minWaterUsage) {
|
||||
minWaterUsage = item.waterUsage;
|
||||
}
|
||||
if (item.swageChangePercent < minSwageChangePercent) {
|
||||
minSwageChangePercent = item.swageChangePercent;
|
||||
}
|
||||
if (item.estimationSewage < minEstimationSewage) {
|
||||
minEstimationSewage = item.estimationSewage;
|
||||
}
|
||||
|
||||
totalWaterUsage += item.waterUsage;
|
||||
totalSwageChangePercent += item.swageChangePercent;
|
||||
totalEstimationSewage += item.estimationSewage;
|
||||
});
|
||||
|
||||
avgWaterUsage = totalWaterUsage?totalWaterUsage / filteredList.length:0;
|
||||
avgSwageChangePercent = totalSwageChangePercent?totalSwageChangePercent / filteredList.length:0;
|
||||
avgEstimationSewage = totalEstimationSewage?totalEstimationSewage / filteredList.length:0;
|
||||
|
||||
const newData = [
|
||||
{
|
||||
msrDt: '평균',
|
||||
waterUsage: Math.round(avgWaterUsage * 100) / 100,
|
||||
swageChangePercent: Math.round(avgSwageChangePercent * 100) / 100,
|
||||
estimationSewage: Math.round(avgEstimationSewage * 100) / 100
|
||||
},
|
||||
{
|
||||
msrDt: '최대',
|
||||
waterUsage: maxWaterUsage,
|
||||
swageChangePercent: maxSwageChangePercent,
|
||||
estimationSewage: maxEstimationSewage
|
||||
},
|
||||
{
|
||||
msrDt: '최소',
|
||||
waterUsage: minWaterUsage,
|
||||
swageChangePercent: minSwageChangePercent,
|
||||
estimationSewage: minEstimationSewage
|
||||
},
|
||||
...filteredList
|
||||
]
|
||||
setDetailList(newData);
|
||||
|
||||
|
||||
}, [startYearMonth, endYearMonth, gridListSewageOccurDetail]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListDiv className="!h-[80px] !mt-10">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'시설명'}</TableHead>
|
||||
<TableCell className="w-1/3">{props.fcltyName}</TableCell>
|
||||
<TableHead className="w-1/6">{'년월'}</TableHead>
|
||||
<TableCell className="w-1/3">
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: startYearMonth || (() => {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
return `${year}${month}`;
|
||||
})(),
|
||||
onChange: (value: string) => {
|
||||
if (value && /^\d{6}$/.test(value)) {
|
||||
setStartYearMonth(value);
|
||||
}
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={1900}
|
||||
/>~
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: endYearMonth || (() => {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
return `${year}${month}`;
|
||||
})(),
|
||||
onChange: (value: string) => {
|
||||
if (value && /^\d{6}$/.test(value)) {
|
||||
setEndYearMonth(value);
|
||||
}
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={1900}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<ListDiv className="!h-[570px] overflow-y-auto">
|
||||
<div className="h-[120%]">
|
||||
<UiTable headName={"오수발생량 추정"} tableData={detailList} headlist={upHeadListSewageOccurDetail} pageSize={0} total={0} cellClick={undefined} onPageChange={() => {}} boldArray={[0, 1, 2]}>
|
||||
</UiTable>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import SewageOccurModal from "./modal/page";
|
||||
import type { SewageOccurProps } from "@/app/store/sewageOccur";
|
||||
|
||||
export default function PlanSewage() {
|
||||
const {Common
|
||||
,SewageOccur
|
||||
,SewageOccurSearch
|
||||
,initializeCommonData
|
||||
,searchSewageOccurList
|
||||
} = useFoStore((state) => state) || {
|
||||
Common: { isInit: false, selectUpdownData: [], selectOperationData: [], selectSidoData: [], selectSigunData: [], selectRegionData: [], selectUnitWaterShedData: [], selectMiddleRegionData: [], selectEnvPartData: [], selectSearchYear: [{ val: "0" }], btnClass: "" },
|
||||
SewageOccur: { sewageOccurList: [], sewageOccurCount: 0, excelList: [], upHeadList1: [], upHeadList2: [], upHeadList3: [] },
|
||||
SewageOccurSearch: { labelArray: [] },
|
||||
initializeCommonData: () => {},
|
||||
searchSewageOccurList: () => {}
|
||||
};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectSearchYear,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
labelArray,
|
||||
} = SewageOccurSearch;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
sewageOccurList,
|
||||
sewageOccurCount,
|
||||
excelList
|
||||
} = SewageOccur;
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
const sewageOccur = SewageOccur?.sewageOccurList || [];
|
||||
|
||||
// 모달 상태 추가
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [fcltyNm, setFcltyNm] = useState<string>("");
|
||||
const [fcltyCd, setFcltyCd] = useState<string>("");
|
||||
|
||||
// 그리드 관련
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
// 초기화 변수
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
// 표 너비
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
// 구분별 그리드 헤더
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
// 용량별
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
// 시설명
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
// 시설상태
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
*/
|
||||
// 초기화
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
setUpheadList(upHeadList1)
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYear(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
};
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
if (sewageOccur[index]) {
|
||||
setFcltyNm(sewageOccur[index].bscFctNm);
|
||||
setFcltyCd(sewageOccur[index].bscFctCd);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* useEffect
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchSewageOccurList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchSewageOccurList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '오수발생량 추정',
|
||||
sheetNameArray: ['오수발생량 추정'],
|
||||
headerRange: 'A1:O1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
*/
|
||||
// 조회
|
||||
const searchFacilityPrecipitation = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchSewageOccurList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchSewageOccurList(pageNo, pageCnt, searchYear);
|
||||
}
|
||||
}, [fcltCpct, operationValue, fcltyName, searchSewageOccurList, searchYear]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback(() => {
|
||||
searchFacilityPrecipitation(ref.current, 1, 10000);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
// 페이지 변경
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchFacilityPrecipitation(ref.current, page, 10);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
const mainList: SewageOccurProps[] = sewageOccurList || [];
|
||||
const total = sewageOccurCount || 0;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="오수발생량 추정" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className={"col-span-3"} label={labelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={labelArray[5] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={labelArray[6] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref}
|
||||
isAdmin={false}
|
||||
/>
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"오수발생량 추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<SewageOccurModal fcltyName={fcltyNm} facilityCd={fcltyCd} searchYear={searchYear}></SewageOccurModal>}
|
||||
bodyClass="sm:max-w-[90vw] w-[1000px] h-[770px]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open) => !open && closeModal()}
|
||||
noHeaderYn="Y"
|
||||
noFooterYn="Y"
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -1,317 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { UnderWaterInputModalProps } from "@/app/store/underWaterInput";
|
||||
import { DateMonthPicker, UITab, UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Table, TableCell, TableHead, TableRow, TabsContent } from "@common/components/ui";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
type ModalProps ={
|
||||
fcltyName: string;
|
||||
searchYear : string;
|
||||
}
|
||||
|
||||
const tabList1 = [
|
||||
{ value: 'tab_term_year', label: '연간' },
|
||||
{ value: 'tab_term_summer', label: '하절기' },
|
||||
{ value: 'tab_term_winter', label: '동절기' },
|
||||
];
|
||||
|
||||
export default function UnderWaterInputModal({fcltyName='', searchYear=new Date().getFullYear().toString()} : ModalProps) {
|
||||
// 그리드 관련
|
||||
const {UnderWaterDetail} = useFoStore((state) => state);
|
||||
|
||||
const [startYmDate, setStartYmDate] = useState<string>(searchYear+'01');
|
||||
const [endYmDate, setEndYmDate] = useState<string>(searchYear+'12');
|
||||
const [tabTerm, setTabTerm] = useState<string>('tab_term_year');
|
||||
|
||||
// 이전 값들을 저장하기 위한 상태
|
||||
const [prevStartYmDate, setPrevStartYmDate] = useState<string>(searchYear+'01');
|
||||
const [prevEndYmDate, setPrevEndYmDate] = useState<string>(searchYear+'12');
|
||||
|
||||
const {
|
||||
upHeadListUnderWaterDetail,
|
||||
gridListUnderWaterDetail,
|
||||
} = UnderWaterDetail;
|
||||
|
||||
// 필터링 된 후 최대, 최소, 평균 값 계산
|
||||
const setFilterAfterData = (filteredData: UnderWaterInputModalProps[]) => {
|
||||
let maxRealSewageInput = Number(filteredData[0]?.realSewageInput ?? 0);
|
||||
let maxSewageOccur = Number(filteredData[0]?.sewageOccur ?? 0);
|
||||
let maxUnderWaterInput = Number(filteredData[0]?.underWaterInput ?? 0);
|
||||
|
||||
let minRealSewageInput = Number(filteredData[0]?.realSewageInput ?? 0);
|
||||
let minSewageOccur = Number(filteredData[0]?.sewageOccur ?? 0);
|
||||
let minUnderWaterInput = Number(filteredData[0]?.underWaterInput ?? 0);
|
||||
|
||||
let avgRealSewageInput = 0;
|
||||
let avgSewageOccur = 0;
|
||||
let avgUnderWaterInput = 0;
|
||||
|
||||
filteredData.forEach((item: UnderWaterInputModalProps) => {
|
||||
maxRealSewageInput = Math.max(Number(maxRealSewageInput), Number(item.realSewageInput));
|
||||
maxSewageOccur = Math.max(Number(maxSewageOccur), Number(item.sewageOccur));
|
||||
maxUnderWaterInput = Math.max(Number(maxUnderWaterInput), Number(item.underWaterInput));
|
||||
|
||||
minRealSewageInput = Math.min(Number(minRealSewageInput) || 0, Number(item.realSewageInput));
|
||||
minSewageOccur = Math.min(Number(minSewageOccur) || 0, Number(item.sewageOccur));
|
||||
minUnderWaterInput = Math.min(Number(minUnderWaterInput) || 0, Number(item.underWaterInput));
|
||||
|
||||
avgRealSewageInput += Number(item.realSewageInput ?? 0);
|
||||
avgSewageOccur += Number(item.sewageOccur ?? 0);
|
||||
avgUnderWaterInput += Number(item.underWaterInput ?? 0);
|
||||
})
|
||||
|
||||
const newFilteredData = [
|
||||
{
|
||||
msrDt: '평균',
|
||||
realSewageInput: filteredData.length==0?0:Math.round(Number(avgRealSewageInput) / filteredData.length * 10) / 10,
|
||||
sewageOccur: filteredData.length==0?0:Math.round(Number(avgSewageOccur) / filteredData.length * 1000) / 1000 ,
|
||||
underWaterInput: filteredData.length==0?0:Math.round(Number(avgUnderWaterInput) / filteredData.length * 1000) / 1000,
|
||||
},
|
||||
{
|
||||
msrDt : '최대',
|
||||
realSewageInput : Math.round(maxRealSewageInput * 10) / 10,
|
||||
sewageOccur : Math.round(maxSewageOccur * 1000) / 1000 ,
|
||||
underWaterInput : Math.round(maxUnderWaterInput * 1000) / 1000,
|
||||
},
|
||||
{
|
||||
msrDt : '최소',
|
||||
realSewageInput : Math.round(minRealSewageInput * 10) / 10,
|
||||
sewageOccur : Math.round(minSewageOccur * 1000) / 1000 ,
|
||||
underWaterInput : Math.round(minUnderWaterInput * 1000) / 1000,
|
||||
},
|
||||
...filteredData
|
||||
];
|
||||
return newFilteredData;
|
||||
}
|
||||
|
||||
// 날짜 필터링 관련 상태
|
||||
const [copyYearList, setCopyYearList] = useState<UnderWaterInputModalProps[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const filteredYearData = setFilterAfterData(gridListUnderWaterDetail);
|
||||
setCopyYearList(filteredYearData as UnderWaterInputModalProps[]);
|
||||
}, [gridListUnderWaterDetail]);
|
||||
|
||||
useEffect(() => {
|
||||
switch (tabTerm) {
|
||||
case 'tab_term_summer':
|
||||
setStartYmDate(searchYear+'06');
|
||||
setEndYmDate(searchYear+'08');
|
||||
setPrevStartYmDate(searchYear+'06');
|
||||
setPrevEndYmDate(searchYear+'08');
|
||||
break;
|
||||
case 'tab_term_winter':
|
||||
setStartYmDate(searchYear+'01');
|
||||
setEndYmDate(searchYear+'02');
|
||||
setPrevStartYmDate(searchYear+'01');
|
||||
setPrevEndYmDate(searchYear+'02');
|
||||
break;
|
||||
default:
|
||||
setStartYmDate(searchYear+'01');
|
||||
setEndYmDate(searchYear+'12');
|
||||
setPrevStartYmDate(searchYear+'01');
|
||||
setPrevEndYmDate(searchYear+'12');
|
||||
}
|
||||
}, [searchYear, tabTerm]);
|
||||
|
||||
useEffect(() => {
|
||||
if(endYmDate < startYmDate) {
|
||||
alert('종료일이 시작일보다 작습니다.')
|
||||
// 이전 값으로 되돌리기
|
||||
setStartYmDate(prevStartYmDate);
|
||||
setEndYmDate(prevEndYmDate);
|
||||
return;
|
||||
}
|
||||
|
||||
// 유효한 경우 현재 값을 이전 값으로 저장
|
||||
setPrevStartYmDate(startYmDate);
|
||||
setPrevEndYmDate(endYmDate);
|
||||
|
||||
const filteredData = gridListUnderWaterDetail.filter((item: UnderWaterInputModalProps) => {
|
||||
// msrDt가 "2024-01" 형태이므로 "202401" 형태로 변환
|
||||
const itemDate = item.msrDt.replace('-', '');
|
||||
return itemDate >= startYmDate && itemDate <= endYmDate;
|
||||
});
|
||||
const filteredYearData = setFilterAfterData(filteredData);
|
||||
setCopyYearList(filteredYearData as UnderWaterInputModalProps[]);
|
||||
}, [startYmDate, endYmDate, gridListUnderWaterDetail, prevStartYmDate, prevEndYmDate]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<UITab tabList={tabList1} defaultValue="tab_term_year" onValueChange={(val) => {setTabTerm(val)}}>
|
||||
<TabsContent value="tab_term_year">
|
||||
<ListDiv className="!h-[100px]">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow>
|
||||
<TableHead className="w-[120px]">{'시설명'}</TableHead>
|
||||
<TableCell className="w-[300px]">{fcltyName}</TableCell>
|
||||
<TableHead className="w-[120px]">{'년/월'}</TableHead>
|
||||
<TableCell className="">
|
||||
<div className="flex">
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: startYmDate,
|
||||
onChange: (value: string) => {
|
||||
setStartYmDate(value);
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={Number(searchYear)} // 시작 연도 설정
|
||||
/>
|
||||
<h3 className="justify-center px-5">~</h3>
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: endYmDate,
|
||||
onChange: (value: string) => {
|
||||
setEndYmDate(value);
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={Number(searchYear)} // 시작 연도 설정
|
||||
/>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<div className="overflow-y-auto h-[500px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListUnderWaterDetail}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[200px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_summer">
|
||||
{/* <FacilityTermModalHeader<UnderWaterInputModalProps>
|
||||
searchList={gridListUnderWaterDetail}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_summer"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/> */}
|
||||
<ListDiv className="!h-[100px]">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow>
|
||||
<TableHead className="w-[120px]">{'시설명'}</TableHead>
|
||||
<TableCell className="w-[300px]">{fcltyName}</TableCell>
|
||||
<TableHead className="w-[120px]">{'년/월'}</TableHead>
|
||||
<TableCell className="">
|
||||
<div className="flex">
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: startYmDate,
|
||||
onChange: (value: string) => {
|
||||
setStartYmDate(value);
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={Number(searchYear)} // 시작 연도 설정
|
||||
/>
|
||||
<h3 className="justify-center px-5">~</h3>
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: endYmDate,
|
||||
onChange: (value: string) => {
|
||||
setEndYmDate(value);
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={Number(searchYear)} // 시작 연도 설정
|
||||
/>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<div className="overflow-y-auto h-[500px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListUnderWaterDetail}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { } }
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_winter">
|
||||
<ListDiv className="!h-[100px]">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow>
|
||||
<TableHead className="w-[120px]">{'시설명'}</TableHead>
|
||||
<TableCell className="w-[300px]">{fcltyName}</TableCell>
|
||||
<TableHead className="w-[120px]">{'년/월'}</TableHead>
|
||||
<TableCell className="">
|
||||
<div className="flex">
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: startYmDate,
|
||||
onChange: (value: string) => {
|
||||
setStartYmDate(value);
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={Number(searchYear)} // 시작 연도 설정
|
||||
/>
|
||||
<h3 className="justify-center px-5">~</h3>
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: endYmDate,
|
||||
onChange: (value: string) => {
|
||||
setEndYmDate(value);
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={Number(searchYear)} // 시작 연도 설정
|
||||
/>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<div className="overflow-y-auto h-[500px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListUnderWaterDetail}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import UnderWaterInputModal from "./modal/page";
|
||||
import type { UnderWaterProps } from "@/app/store/underWaterInput";
|
||||
|
||||
export default function UnderWaterInput() {
|
||||
const {Common
|
||||
,UnderWater
|
||||
,UnderWaterSearch
|
||||
,initializeCommonData
|
||||
,searchUnderWaterList
|
||||
} = useFoStore((state) => state) || {
|
||||
Common: { isInit: false, selectUpdownData: [], selectOperationData: [], selectSidoData: [], selectSigunData: [], selectRegionData: [], selectUnitWaterShedData: [], selectMiddleRegionData: [], selectEnvPartData: [], selectSearchYear: [{ val: "0" }], btnClass: "" },
|
||||
UnderWater: { underWaterList: [], underWaterCount: 0, excelList: [], upHeadList1: [], upHeadList2: [], upHeadList3: [] },
|
||||
UnderWaterSearch: { labelArray: [] },
|
||||
initializeCommonData: () => {},
|
||||
searchUnderWaterList: () => {}
|
||||
};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectSearchYear,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
labelArray,
|
||||
} = UnderWaterSearch;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
underWaterList,
|
||||
underWaterCount,
|
||||
excelList,
|
||||
} = UnderWater;
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
const underWater = UnderWater?.underWaterList || [];
|
||||
|
||||
// 모달 상태 추가
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [fcltyNm, setFcltyNm] = useState<string>("");
|
||||
|
||||
// 그리드 관련
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
// 초기화 변수
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
// 표 너비
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
// 구분별 그리드 헤더
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
// 용량별
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
// 시설명
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
// 시설상태
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
*/
|
||||
// 초기화
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
setUpheadList(upHeadList1)
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYear(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
searchUnderWaterList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
};
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
if (underWater[index]) {
|
||||
setFcltyNm(underWater[index].bscFctNm);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* useEffect
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchUnderWaterList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchUnderWaterList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '지하수유입량 추정',
|
||||
sheetNameArray: ['지하수유입량 추정'],
|
||||
headerRange: 'A1:V1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
*/
|
||||
// 조회
|
||||
const searchFacilityPrecipitation = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchUnderWaterList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchUnderWaterList(pageNo, pageCnt, searchYear);
|
||||
}
|
||||
}, [fcltCpct, operationValue, fcltyName, searchUnderWaterList, searchYear]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback(() => {
|
||||
searchFacilityPrecipitation(ref.current, 1, 10000);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
// 페이지 변경
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchFacilityPrecipitation(ref.current, page, 10);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
const mainList: UnderWaterProps[] = underWaterList || [];
|
||||
const total = underWaterCount || 0;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="지하수유입량 추정" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className={"col-span-3"} label={labelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={labelArray[5] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={labelArray[6] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref}
|
||||
isAdmin={false}
|
||||
/>
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"지하수유입량 추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-2xl text-gray-500">※지하수 유입량 = 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)</span>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<UnderWaterInputModal fcltyName={fcltyNm} searchYear={searchYear}></UnderWaterInputModal>}
|
||||
bodyClass="sm:max-w-[90vw] w-[1000px] h-[770px]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open) => !open && closeModal()}
|
||||
noHeaderYn="Y"
|
||||
noFooterYn="Y"
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -1,374 +0,0 @@
|
||||
/**====================================
|
||||
* 보편적으로 쓰는 store 공간
|
||||
====================================**/
|
||||
|
||||
import { getFetch } from "@/app/components/api";
|
||||
|
||||
/**
|
||||
* STORE - TYPE
|
||||
*/
|
||||
|
||||
// selectBox
|
||||
export type SelectDataType = {
|
||||
text: string;
|
||||
val: string;
|
||||
}
|
||||
// grid header
|
||||
export type TableUpperProps = {
|
||||
id: string;
|
||||
title: string;
|
||||
upName?: string;
|
||||
upSequnce?: number;
|
||||
}
|
||||
|
||||
// 시도 데이터
|
||||
export type sidoDataType = {
|
||||
adstDstrCd: number,
|
||||
sido: string,
|
||||
}
|
||||
|
||||
// 시군구 데이터
|
||||
export type sigunDataType = {
|
||||
adstDstrCd: number,
|
||||
gugun: string
|
||||
}
|
||||
|
||||
// 권역 데이터
|
||||
export type regionDataType = {
|
||||
rvbsnCd: string,
|
||||
rvbsn: string,
|
||||
}
|
||||
|
||||
// 단위유역 데이터
|
||||
export type unitWaterShedDataType = {
|
||||
rvbsnCd: string,
|
||||
lgbsn: string,
|
||||
}
|
||||
|
||||
// 중권역 데이터
|
||||
export type middleRegionDataType = {
|
||||
rvbsnCd: string,
|
||||
mdmbsn: string,
|
||||
}
|
||||
|
||||
// 환경청 데이터
|
||||
export type envPartDataType = {
|
||||
lclgvrnmntCd: string,
|
||||
lclgvrnmntNm: string,
|
||||
adstDliStrCd: string,
|
||||
adstDstrCd: string,
|
||||
}
|
||||
|
||||
export type envPartSelectDataType = SelectDataType & {
|
||||
adstDliStrCd: string,
|
||||
}
|
||||
|
||||
/**
|
||||
* STORE - DATA
|
||||
*/
|
||||
|
||||
// 시도 데이터
|
||||
let selectSidoData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
// 시군구 데이터
|
||||
let selectSigunData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
// 권역 데이터
|
||||
const selectRegionData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
// 단위유역 데이터
|
||||
const selectUnitWaterShedData: SelectDataType[] = [
|
||||
];
|
||||
|
||||
// 환경청 데이터
|
||||
let selectEnvPartData: envPartSelectDataType[] = [
|
||||
{ text: "전체", val: '0', adstDliStrCd: '' }
|
||||
];
|
||||
|
||||
// 환경청 내 시도 데이터
|
||||
const selectEnvPartSidoData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
// 환경청 내 시군구 데이터
|
||||
const selectEnvPartSigunData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
// 구분 데이터
|
||||
// const selectPartData:SelectDataType[] = [
|
||||
// { text: "행정별", val: '0' },
|
||||
// { text: "유역별", val: '01' },
|
||||
// { text: "환경청별", val: '02' },
|
||||
// ];
|
||||
|
||||
// 상향 하향 데이터
|
||||
const selectUpdownData:SelectDataType[] = [
|
||||
{ text: "전체", val: '0' },
|
||||
{ text: "500이하", val: '400' },
|
||||
{ text: "500이상", val: '500' },
|
||||
];
|
||||
|
||||
// 운영 상태 데이터
|
||||
const selectOperationData:SelectDataType[] = [
|
||||
{ text: "전체", val: '0' },
|
||||
{ text: "가동중", val: '1' },
|
||||
{ text: "재가동", val: '2' },
|
||||
{ text: "가동중지", val: '3' },
|
||||
{ text: "시설폐쇄", val: '4' },
|
||||
];
|
||||
|
||||
// 시설 구분 데이터
|
||||
const selectFacilityPartData:SelectDataType[] = [
|
||||
{ text: "전체", val: '0' },
|
||||
{ text: "공공하수처리시설", val: 'SW' },
|
||||
{ text: "오수처리장", val: 'SS' },
|
||||
{ text: "개인하수처리시설", val: 'PB' },
|
||||
{ text: "분뇨처리장", val: 'NS' },
|
||||
{ text: "폐수처리장", val: 'LW' },
|
||||
{ text: "침출수처리장", val: 'LC' },
|
||||
{ text: "기타기초시설", val: 'ET' },
|
||||
];
|
||||
|
||||
// 년도 데이터
|
||||
const getYearData = () => {
|
||||
const year = new Date().getFullYear();
|
||||
const year1 = year - 1;
|
||||
const year2 = year - 2;
|
||||
const year3 = year - 3;
|
||||
const year4 = year - 4;
|
||||
const year5 = year - 5;
|
||||
return [
|
||||
{ text: year1 + "년", val: year1.toString() },
|
||||
{ text: year2 + "년", val: year2.toString() },
|
||||
{ text: year3 + "년", val: year3.toString() },
|
||||
{ text: year4 + "년", val: year4.toString() },
|
||||
{ text: year5 + "년", val: year5.toString() },
|
||||
]
|
||||
}
|
||||
|
||||
const selectSearchYear:SelectDataType[] = getYearData();
|
||||
|
||||
// 유량 기간 구분
|
||||
const selectFlowTerm : SelectDataType[] = [
|
||||
{ text: "연간", val: '0' },
|
||||
{ text: "하절기", val: '01' },
|
||||
{ text: "동절기", val: '02' },
|
||||
{ text: "청천시", val: '03' },
|
||||
{ text: "강우시", val: '04' },
|
||||
];
|
||||
|
||||
// 유량 기간 구분
|
||||
const selectFlowPanel : SelectDataType[] = [
|
||||
{ text: "전체", val: '0'},
|
||||
{ text: "3~10mm미만", val: '2'},
|
||||
{ text: "10~20mm미만", val: '3'},
|
||||
{ text: "20~30mm미만", val: '4'},
|
||||
{ text: "30~40mm미만", val: '5'},
|
||||
{ text: "40~50mm미만", val: '6'},
|
||||
{ text: "50~60mm미만", val: '7'},
|
||||
{ text: "60mm이상", val: '8'},
|
||||
];
|
||||
|
||||
// 중권역 데이터
|
||||
const selectMiddleRegionData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
/**
|
||||
* STORE - API
|
||||
*/
|
||||
|
||||
// 시도 API 호출 함수 추가
|
||||
const fetchSidoData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/addr/city');
|
||||
const data = res.data;
|
||||
selectSidoData = [
|
||||
{ text: "전체", val: '0'},
|
||||
...data.map((item: sidoDataType) => ({
|
||||
text: item.sido || '',
|
||||
val: String(item.adstDstrCd) || ''
|
||||
}))
|
||||
];
|
||||
return selectSidoData;
|
||||
} catch (error) {
|
||||
console.error('시도 데이터를 가져오는데 실패했습니다:', error);
|
||||
return selectSidoData;
|
||||
}
|
||||
};
|
||||
|
||||
// 시군구 API 호출 함수 추가
|
||||
const fetchSigunData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/addr/sgg');
|
||||
const data = res.data;
|
||||
selectSigunData = [
|
||||
{ text: "전체", val: '0' },
|
||||
...data
|
||||
.map((item: sigunDataType) => ({
|
||||
text: item.gugun || '',
|
||||
val: String(item.adstDstrCd) || ''
|
||||
}))
|
||||
];
|
||||
return selectSigunData;
|
||||
} catch (error) {
|
||||
console.error('시군구 데이터를 가져오는데 실패했습니다:', error);
|
||||
return selectSigunData;
|
||||
}
|
||||
};
|
||||
|
||||
// 권역 API 호출 함수 추가
|
||||
const fetchRegionData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/addr/sarea');
|
||||
const data = res.data;
|
||||
return [
|
||||
{ text: "전체", val: '0'},
|
||||
...data.map((item: regionDataType) => ({
|
||||
text: item.rvbsn || '',
|
||||
val: String(item.rvbsnCd) || ''
|
||||
}))
|
||||
];
|
||||
} catch (error) {
|
||||
console.error('권역 데이터를 가져오는데 실패했습니다:', error);
|
||||
return selectRegionData;
|
||||
}
|
||||
};
|
||||
|
||||
// 중권역 API 호출 함수 추가
|
||||
const fetchMiddleRegionData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/addr/midArea');
|
||||
const data = res.data;
|
||||
return [
|
||||
{ text: "전체", val: '0' },
|
||||
...data
|
||||
.map((item: middleRegionDataType) => ({
|
||||
text: item.mdmbsn || '',
|
||||
val: String(item.rvbsnCd) || ''
|
||||
}))
|
||||
];
|
||||
} catch (error) {
|
||||
console.error('중권역 데이터를 가져오는데 실패했습니다:', error);
|
||||
return selectMiddleRegionData;
|
||||
}
|
||||
};
|
||||
|
||||
// 단위유역 API 호출 함수 추가
|
||||
const fetchUnitWaterShedData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/addr/largeArea');
|
||||
const data = res.data;
|
||||
return [
|
||||
{ text: "전체", val: '0' },
|
||||
...data
|
||||
.map((item: unitWaterShedDataType) => ({
|
||||
text: item.lgbsn || '',
|
||||
val: String(item.rvbsnCd) || ''
|
||||
}))
|
||||
];
|
||||
} catch (error) {
|
||||
console.error('단위유역 데이터를 가져오는데 실패했습니다:', error);
|
||||
return selectUnitWaterShedData;
|
||||
}
|
||||
};
|
||||
|
||||
// 환경청 데이터
|
||||
const fetchEnvPartData = async (): Promise<envPartSelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/addr/govArea');
|
||||
const data = res.data;
|
||||
selectEnvPartData = [
|
||||
{ text: "전체", val: '0', adstDliStrCd: '' },
|
||||
...data
|
||||
.map((item: envPartDataType) => ({
|
||||
text: item.lclgvrnmntNm || '',
|
||||
val: String(item.lclgvrnmntCd) || '',
|
||||
adstDliStrCd: item.adstDliStrCd || ''
|
||||
}))
|
||||
];
|
||||
return selectEnvPartData;
|
||||
} catch (error) {
|
||||
console.error('환경청 데이터를 가져오는데 실패했습니다:', error);
|
||||
return selectEnvPartData;
|
||||
}
|
||||
};
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type CommonAction = {
|
||||
initializeCommonData: () => Promise<void>;
|
||||
}
|
||||
|
||||
export type CommonType = {
|
||||
Common: {
|
||||
isInit: boolean;
|
||||
selectSidoData: SelectDataType[];
|
||||
selectSigunData: SelectDataType[];
|
||||
selectUpdownData: SelectDataType[];
|
||||
selectOperationData: SelectDataType[];
|
||||
selectFacilityPartData: SelectDataType[];
|
||||
selectSearchYear: SelectDataType[];
|
||||
selectUnitWaterShedData: SelectDataType[];
|
||||
selectRegionData: SelectDataType[];
|
||||
selectMiddleRegionData: SelectDataType[];
|
||||
selectEnvPartSidoData: SelectDataType[];
|
||||
selectEnvPartSigunData: SelectDataType[];
|
||||
selectFlowTerm: SelectDataType[];
|
||||
selectFlowPanel: SelectDataType[];
|
||||
selectEnvPartData: envPartSelectDataType[];
|
||||
btnClass: string;
|
||||
}
|
||||
}
|
||||
|
||||
export const commonState:CommonType = {
|
||||
Common: {
|
||||
isInit: false,
|
||||
selectSidoData: selectSidoData,
|
||||
selectSigunData: selectSigunData,
|
||||
selectUpdownData: selectUpdownData,
|
||||
selectOperationData: selectOperationData,
|
||||
selectFacilityPartData: selectFacilityPartData,
|
||||
selectSearchYear: selectSearchYear,
|
||||
selectRegionData: selectRegionData,
|
||||
selectUnitWaterShedData: selectUnitWaterShedData,
|
||||
selectMiddleRegionData: selectMiddleRegionData,
|
||||
selectEnvPartSidoData : selectEnvPartSidoData,
|
||||
selectEnvPartSigunData : selectEnvPartSigunData,
|
||||
selectFlowTerm: selectFlowTerm,
|
||||
selectFlowPanel: selectFlowPanel,
|
||||
selectEnvPartData : selectEnvPartData,
|
||||
btnClass: "p-4 m-2 text-white rounded-sm text-lg font-medium"
|
||||
}
|
||||
}
|
||||
|
||||
export const CommonReducer:(set:(fn: (state: CommonType) => CommonType) => void)=>CommonAction=(set: (fn: (state: CommonType) => CommonType) => void) => {
|
||||
return {
|
||||
// 시도 변경 이벤트
|
||||
initializeCommonData: async () => {
|
||||
const promiseSet = await Promise.all([fetchSidoData(), fetchSigunData(), fetchRegionData(), fetchUnitWaterShedData(), fetchMiddleRegionData(), fetchEnvPartData()]);
|
||||
const [sidoData, sggData, regionData, unitData, midData, envData] = promiseSet;
|
||||
set((state: CommonType) => ({
|
||||
Common: {
|
||||
...state.Common,
|
||||
selectSidoData: sidoData,
|
||||
selectSigunData: sggData,
|
||||
selectRegionData: regionData,
|
||||
selectMiddleRegionData: midData,
|
||||
selectUnitWaterShedData: unitData,
|
||||
selectEnvPartData: envData
|
||||
}
|
||||
}))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export type CommonStore = CommonType & CommonAction;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,307 +0,0 @@
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { getFetch } from "@/app/components/api";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 시설별 강수현황
|
||||
type FacilityPrecipitationProps = {
|
||||
bscFctCd : string,
|
||||
sido : string,
|
||||
gugun : string,
|
||||
bscFctNm : string,
|
||||
addr : string,
|
||||
fctCpc : number,
|
||||
stnKo : string,
|
||||
infoRnDay : number,
|
||||
rainEffectDay : number,
|
||||
totalYearRain : number,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
rgnNm : string,
|
||||
}
|
||||
|
||||
/*
|
||||
* (2) 강수현황 팝업
|
||||
*/
|
||||
// 강수현황
|
||||
export type PrecipitationPropsDetailProps = {
|
||||
bscFctCd : string,
|
||||
rainDt : string,
|
||||
infoRnDay : number,
|
||||
rainEffectDay : number,
|
||||
rainDay : number
|
||||
}
|
||||
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설이름: string,
|
||||
주소: string,
|
||||
시설용량: number,
|
||||
관측소정보 : string,
|
||||
강우일 : number,
|
||||
강우영향일 : number,
|
||||
연간총강수량 : number,
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 검색단
|
||||
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '시설상태', '조회기간', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row: 0, rowSpan: 2},
|
||||
{ id: "A", title: "행정구역", row: 0, colSpan: 2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row: 1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2, row: 1 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "addr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2},
|
||||
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2},
|
||||
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2},
|
||||
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2},
|
||||
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2}
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row: 0, rowSpan: 2},
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3} ,
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row: 1} ,
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row: 1},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row: 1},
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "addr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2},
|
||||
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2},
|
||||
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2},
|
||||
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2},
|
||||
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2}
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row: 0, rowSpan: 2},
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3} ,
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row: 1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row: 1},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row: 1},
|
||||
{ id: "rgnNm", title: "환경청", row: 0, rowSpan: 2},
|
||||
{ id: "B", title: "행정구역", upName:"upChangeRe2", row: 0, colSpan: 2},
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, row: 1},
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe2",upSequnce:2, row: 1},
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "addr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2},
|
||||
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2},
|
||||
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2},
|
||||
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2},
|
||||
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2}
|
||||
];
|
||||
|
||||
const facilityPrecipitation:FacilityPrecipitationProps[] = [
|
||||
]
|
||||
|
||||
/**
|
||||
* 강수현황 상세팝업
|
||||
*/
|
||||
// 강수현황 (헤더)
|
||||
const upHeadListPrecipitationDetail:TableUpperProps[] = [
|
||||
{ id: "rainDt", title: "날짜"},
|
||||
{ id: "infoRnDay", title: "강수량(mm/일)"},
|
||||
{ id: "rainDay", title: "강우일(일)"},
|
||||
{ id: "rainEffectDay", title: "강우영향일(일)"}
|
||||
]
|
||||
// 강수현황 (리스트)
|
||||
const gridListPrecipitationDetail:PrecipitationPropsDetailProps[] = [
|
||||
]
|
||||
|
||||
/**====================================
|
||||
* Store - api
|
||||
====================================*/
|
||||
|
||||
const fetchFacilityPrecipitationList = async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const tailStr = '/'+pageNo + '/' + pageSize + '/' + searchYear + (part?'/' + part:'' ) + (nameCd?'/' + nameCd:'' ) + (fcltCpct?'/' + fcltCpct:'' ) + (operationValue?'/' + operationValue:'' ) + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') ;
|
||||
console.log('tailStr', tailStr);
|
||||
const url = '/fclt/rain' + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
const tmpData:PrecipitationPropsDetailProps[] = [];
|
||||
if(res!= null && res.data.length > 0){
|
||||
for(let idx=0; idx<res.data.length; idx++){
|
||||
for(let idx2=0; idx2<res.data[idx].rainyDayObjList.length; idx2++){
|
||||
const bscFctCd = res.data[idx].rainyDayObjList[idx2].bscFctCd;
|
||||
const rainDt = res.data[idx].rainyDayObjList[idx2].rainDt;
|
||||
const infoRnDay = res.data[idx].rainyDayObjList[idx2].infoRnDay;
|
||||
const rainDay = res.data[idx].rainyDayObjList[idx2].infoRnDay>=3?1:0;
|
||||
let rainEffectDay = 0;
|
||||
if(idx2 < res.data[idx].rainyDayObjList.length-2){
|
||||
if(rainDay==1){
|
||||
rainEffectDay = 1;
|
||||
} else {
|
||||
if(idx2 >= 2){
|
||||
if(res.data[idx].rainyDayObjList[idx2-1].infoRnDay>=3 || res.data[idx].rainyDayObjList[idx2-2].infoRnDay>=3){
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(idx2 < res.data[idx].rainyDayObjList.length-1){
|
||||
if(rainDay==1 || res.data[idx].rainyDayObjList[idx2+1].infoRnDay>=3){
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
} else {
|
||||
rainEffectDay = rainDay;
|
||||
}
|
||||
|
||||
tmpData.push({
|
||||
bscFctCd : bscFctCd,
|
||||
rainDt : rainDt,
|
||||
infoRnDay : infoRnDay,
|
||||
rainDay : rainDay,
|
||||
rainEffectDay : rainEffectDay
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
res.data.map((item: FacilityPrecipitationProps) => {
|
||||
const filteredList = tmpData.filter((gridItem) => {
|
||||
return gridItem.bscFctCd === item.bscFctCd;
|
||||
});
|
||||
|
||||
item.rainEffectDay = filteredList.reduce((acc, curr) => acc + curr.rainEffectDay, 0);
|
||||
item.totalYearRain = filteredList.reduce((acc, curr) => acc + curr.infoRnDay, 0);
|
||||
item.infoRnDay = filteredList.reduce((acc, curr) => acc + curr.rainDay, 0);
|
||||
})
|
||||
}
|
||||
return { data: res.data, count: res.count, detailData: tmpData };
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type FacilityPrecipitationActions = {
|
||||
searchFacilityPrecipitationList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
|
||||
}
|
||||
|
||||
const dataFormSetting=(item : FacilityPrecipitationProps)=> {
|
||||
DataForm({ type: 'number', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'totalYearRain', item: item as unknown as Record<string, unknown>});
|
||||
};
|
||||
|
||||
export type FacilityPrecipitationType = {
|
||||
FacilityPrecipitationSearch: {
|
||||
isInit: boolean;
|
||||
labelArray:string[];
|
||||
},
|
||||
|
||||
FacilityPrecipitation : {
|
||||
isInit: boolean;
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
facilityPrecipitation: FacilityPrecipitationProps[];
|
||||
excelList: ExcelType[];
|
||||
facilityPrecipitationCount: number;
|
||||
},
|
||||
|
||||
PrecipitationDetail : {
|
||||
isInit : boolean;
|
||||
upHeadListPrecipitationDetail : TableUpperProps[];
|
||||
gridListPrecipitationDetail : PrecipitationPropsDetailProps[];
|
||||
}
|
||||
}
|
||||
|
||||
export const facilityPrecipitationInitState: FacilityPrecipitationType = {
|
||||
FacilityPrecipitationSearch: {
|
||||
isInit: false,
|
||||
labelArray: LabelArray,
|
||||
},
|
||||
|
||||
FacilityPrecipitation : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
upHeadList2 : upHeadList2,
|
||||
upHeadList3 : upHeadList3,
|
||||
facilityPrecipitation : facilityPrecipitation,
|
||||
excelList : [],
|
||||
facilityPrecipitationCount : 0
|
||||
},
|
||||
|
||||
PrecipitationDetail : {
|
||||
isInit : false,
|
||||
upHeadListPrecipitationDetail : upHeadListPrecipitationDetail,
|
||||
gridListPrecipitationDetail : gridListPrecipitationDetail
|
||||
}
|
||||
}
|
||||
|
||||
export type FacilityPrecipitationStore = FacilityPrecipitationType & FacilityPrecipitationActions;
|
||||
|
||||
export const facilityPrecipitationReducer:(set:(fn: (state: FacilityPrecipitationType) => FacilityPrecipitationType) => void)=>FacilityPrecipitationActions=(set: (fn: (state: FacilityPrecipitationType) => FacilityPrecipitationType) => void) => {
|
||||
return {
|
||||
searchFacilityPrecipitationList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const res = await fetchFacilityPrecipitationList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const data = res.data;
|
||||
const excelDownList: ExcelType[] = [];
|
||||
|
||||
if(pageSize>5000){
|
||||
data.forEach((item: FacilityPrecipitationProps) => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : 0;
|
||||
item.totalYearRain = item.totalYearRain ? parseFloat(item.totalYearRain.toString().replace(/,/g, '')) : 0;
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시도: item.sido,
|
||||
시군구: item.gugun,
|
||||
시설이름: item.bscFctNm,
|
||||
주소: item.addr,
|
||||
시설용량: item.fctCpc,
|
||||
관측소정보: item.stnKo,
|
||||
강우일: item.infoRnDay,
|
||||
강우영향일: item.rainEffectDay,
|
||||
연간총강수량: item.totalYearRain,
|
||||
})
|
||||
})
|
||||
}else{
|
||||
data.forEach((item: FacilityPrecipitationProps) => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : 0;
|
||||
item.totalYearRain = item.totalYearRain ? parseFloat(item.totalYearRain.toString().replace(/,/g, '')) : 0;
|
||||
})
|
||||
}
|
||||
set((state:FacilityPrecipitationType) => ({
|
||||
...state,
|
||||
FacilityPrecipitation: pageSize<5000?{
|
||||
...state.FacilityPrecipitation,
|
||||
facilityPrecipitation: res.data,
|
||||
facilityPrecipitationCount: res.count,
|
||||
}:{
|
||||
...state.FacilityPrecipitation,
|
||||
excelList: excelDownList,
|
||||
},
|
||||
PrecipitationDetail:{
|
||||
...state.PrecipitationDetail,
|
||||
gridListPrecipitationDetail: res.detailData
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,659 +0,0 @@
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
export type { TableUpperProps };
|
||||
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
*
|
||||
* tn, tp는 소수점 3자리까지, 나머지는 소수점 1자리까지
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 시설수질리스트 타입
|
||||
export interface FacilityWaterQltyProps {
|
||||
bscFctCd: string,
|
||||
bscFctNm: string,
|
||||
msrDt: string
|
||||
sidoNm: string,
|
||||
sggNm: string,
|
||||
addr: string,
|
||||
fctCpc: number,
|
||||
inflAssctAftWqltBod: string | '',
|
||||
inflAssctAftWqltToc: string | '',
|
||||
inflAssctAftWqltSs: string | '',
|
||||
inflAssctAftWqltTn: string | '',
|
||||
inflAssctAftWqltTp: string | '',
|
||||
inflAssctBfrWqltTp: string | '',
|
||||
efflWqltBod: string | '',
|
||||
efflWqltCod: string | '',
|
||||
efflWqltSs: string | '',
|
||||
efflWqltTn: string | '',
|
||||
efflWqltTp: string | '',
|
||||
rgnNm:string|'',
|
||||
rvbsn:string|'',
|
||||
lgbsn:string|'',
|
||||
mdmbsn:string|'',
|
||||
inflAmnt: number | '',
|
||||
lclgvrnmntNm: string,
|
||||
infoRnDay: number | '',
|
||||
rainEffectDay: number | '',
|
||||
tpInflWqltTmprtr: number | '',
|
||||
tpInflWqltPh: string | '',
|
||||
tpInflWqltBod: string | '',
|
||||
tpInflWqltCod: string | '',
|
||||
tpInflWqltSs: string | '',
|
||||
tpInflWqltTn: string | '',
|
||||
tpInflWqltTp: string | '',
|
||||
tpInflWqltEclgyTox: string | '',
|
||||
tpInflWqltClfgrpcnt: string | '',
|
||||
}
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설이름: string,
|
||||
주소: string,
|
||||
용량: number,
|
||||
유입BOD: string | '',
|
||||
유입TOC: string | '',
|
||||
유입SS: string | '',
|
||||
유입TN: string | '',
|
||||
유입TP: string | '',
|
||||
유출BOD: string | '',
|
||||
유출TOC: string | '',
|
||||
유출SS: string | '',
|
||||
유출TN: string | '',
|
||||
유출TP: string | '',
|
||||
}
|
||||
|
||||
/**
|
||||
* (2) 모달페이지
|
||||
*/
|
||||
// 시설수질리스트 타입
|
||||
export type FacilityWaterQltyTmsProps = {
|
||||
part: string,
|
||||
toc: number,
|
||||
ss: number,
|
||||
tn: number,
|
||||
tp: number,
|
||||
}
|
||||
|
||||
// API 응답 데이터 타입
|
||||
export interface WaterQualityHistoryResponse {
|
||||
data: {
|
||||
wqltObjs: FacilityWaterQltyProps[];
|
||||
};
|
||||
}
|
||||
|
||||
export type modalExcelType = {
|
||||
날짜: string;
|
||||
"유입BOD(mg/L)": string;
|
||||
"유입TOC(COD)(mg/L)": string;
|
||||
"유입SS(mg/L)": string;
|
||||
"유입TN(mg/L)": string;
|
||||
"유입TP(mg/L)": string;
|
||||
"유출BOD(mg/L)": string;
|
||||
"유출TOC(COD)(mg/L)": string;
|
||||
"유출SS(mg/L)": string;
|
||||
"유출TN(mg/L)": string;
|
||||
"유출TP(mg/L)": string;
|
||||
"강우량(일)": string;
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 메인 라벨 배열
|
||||
const mainLabelArray: string[] = ['구분', '시도', '시군구', '용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
// 시설수질리스트 헤더(행정별)
|
||||
const upHeadList1: TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", rowSpan: 2, row:0 },
|
||||
{ id: "C", title: "행정명", colSpan: 2, row: 0 },
|
||||
{ id: "sidoNm", title: "시도", row: 1 },
|
||||
{ id: "sggNm", title: "시군구", row: 1 },
|
||||
{ id: "bscFctNm", title: "시설명", rowSpan: 2, row: 0 },
|
||||
{ id: "addr", title: "주소", rowSpan: 2, row: 0 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align: "right", rowSpan: 2, row: 0 },
|
||||
{ id: "A", title: "유입", colSpan: 5, row: 0 },
|
||||
{ id: "B", title: "방류", colSpan: 5, row: 0 },
|
||||
{ id: "inflAssctAftWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row: 1 },
|
||||
{ id: "inflAssctAftWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1 },
|
||||
{ id: "inflAssctAftWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1 },
|
||||
{ id: "inflAssctAftWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 4, align: "right", row: 1 },
|
||||
{ id: "inflAssctAftWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1 },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row: 1 },
|
||||
{ id: "efflWqltCod", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row: 1 },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1 },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 4, align: "right", row: 1 },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1 },
|
||||
];
|
||||
|
||||
// 시설수질리스트 헤더(권역별)
|
||||
const upHeadList2: TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "C", title: "유역", colSpan: 3, row: 0 },
|
||||
{ id: "rvbsn", title: "권역", upName: "upChangeRe1", upSequnce: 1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName: "upChangeRe1", upSequnce: 2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName: "upChangeRe1", upSequnce: 3, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "addr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/L)", align: "right", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유입", colSpan: 5, row: 0 },
|
||||
{ id: "B", title: "방류", colSpan: 5, row: 0 },
|
||||
{ id: "inflAssctAftWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row:1 },
|
||||
{ id: "efflWqltCod", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1 },
|
||||
];
|
||||
|
||||
// 시설수질리스트 헤더(환경청별)
|
||||
const upHeadList3: TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "C", title: "유역", colSpan: 3, row: 0 },
|
||||
{ id: "rvbsn", title: "권역", row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "D", title: "행정명", colSpan: 2, row: 0 },
|
||||
{ id: "sidoNm", title: "시도", upName: "upChangeRe2", row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName: "upChangeRe2", row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "addr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/L)", align: "right", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유입", colSpan: 5, row: 0 },
|
||||
{ id: "B", title: "방류", colSpan: 5, row: 0 },
|
||||
{ id: "inflAssctAftWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row:1 },
|
||||
{ id: "efflWqltCod", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1 },
|
||||
];
|
||||
|
||||
/**
|
||||
* (2) 모달페이지
|
||||
*/
|
||||
// 처리시설 수질현황 헤더(모달-연간)
|
||||
const upHeadListModalYear: TableUpperProps[] = [
|
||||
{ id: "msrDt", title: "날짜" },
|
||||
{ id: "inflAssctAftWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe1", upSequnce: 1, align: "right" },
|
||||
{ id: "inflAssctAftWqltToc", title: "TOC(COD)\n(mg/L)", upName: "upChangeRe1", upSequnce: 2, align: "right" },
|
||||
{ id: "inflAssctAftWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe1", upSequnce: 3, align: "right" },
|
||||
{ id: "inflAssctAftWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe1", upSequnce: 2, align: "right" },
|
||||
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe1", upSequnce: 3, align: "right" },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe2", upSequnce: 1, align: "right" },
|
||||
{ id: "efflWqltCod", title: "TOC(COD)\n(mg/L)", upName: "upChangeRe2", upSequnce: 2, align: "right" },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe2", upSequnce: 3, align: "right" },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe2", upSequnce: 2, align: "right" },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe2", upSequnce: 3, align: "right" },
|
||||
{ id: "infoRnDay", title: "강우량", align: "right" },
|
||||
];
|
||||
|
||||
// 처리시설 수질현황 헤더(모달-수질TMS)
|
||||
const upHeadListModalTms: TableUpperProps[] = [
|
||||
{ id: "part", title: "구분" },
|
||||
{ id: "toc", title: "TOC(mg/L)", upName: "upChangeRe", upSequnce: 1, align: "right" },
|
||||
{ id: "ss", title: "SS(mg/L)", upName: "upChangeRe", upSequnce: 2, align: "right" },
|
||||
{ id: "tn", title: "T-N(mg/L)", upName: "upChangeRe", upSequnce: 3, align: "right" },
|
||||
{ id: "tp", title: "T-P(mg/L)", upName: "upChangeRe", upSequnce: 4, align: "right" },
|
||||
];
|
||||
|
||||
// 처리시설 수질현황 데이터(모달-연간)
|
||||
const facilityWaterQltyYearList: FacilityWaterQltyProps[] = [
|
||||
];
|
||||
|
||||
// 처리시설 수질현황 데이터(모달-수질TMS)
|
||||
const facilityWaterQltyTmsList: FacilityWaterQltyTmsProps[] = [
|
||||
];
|
||||
|
||||
// 총인설비 수질현황 헤더 데이터
|
||||
const upHeadListModalChongIn: TableUpperProps[] = [
|
||||
{ id: "msrDt", title: "날짜" },
|
||||
{ id: "tpInflWqltBod", title: "BOD(mg/L)", upName: "upChangeRe1", upSequnce: 1, align: "right" },
|
||||
{ id: "tpInflWqltTp", title: "T-P(mg/L)", upName: "upChangeRe1", upSequnce: 2, align: "right" },
|
||||
{ id: "efflWqltBod", title: "BOD(mg/L)", upName: "upChangeRe2", upSequnce: 1, align: "right" },
|
||||
{ id: "efflWqltTp", title: "T-P(mg/L)", upName: "upChangeRe2", upSequnce: 2, align: "right" },
|
||||
];
|
||||
|
||||
/**====================================
|
||||
* Store - api (데이터 호출)
|
||||
====================================*/
|
||||
// 메인페이지
|
||||
// 시설정보 수질 리스트 데이터 호출
|
||||
const fetchFacilityWaterQltyList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string|undefined, nameCd?: string|undefined, fcltCpct?: string|undefined, operationValue?: string|undefined, fcltyNm?: string | undefined): Promise<{ data: FacilityWaterQltyProps[], count: number }> => {
|
||||
try {
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/fclt/qlty/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count }
|
||||
} catch (error) {
|
||||
console.error('시설정보 수질현황 데이터를 가져오는데 실패했습니다:', error);
|
||||
return { data: [], count: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
// 시설정보 수질 리스트 데이터 호출(모달-수질TMS)
|
||||
const fetchFacilityWaterQltyTmsList = async (facilityCd: string|undefined) => {
|
||||
try {
|
||||
const res = await getFetch('wr', '/il/getTms/' + facilityCd);
|
||||
return { data: res.data, count: res.count };
|
||||
} catch (error) {
|
||||
console.error('시설정보 수질현황 TMS 데이터를 가져오는데 실패했습니다:', error);
|
||||
return { data: [], count: 0 };
|
||||
}
|
||||
};
|
||||
|
||||
// 시설정보 수질 리스트 데이터 호출(모달-이력)
|
||||
const fetchFacilityWaterQltyListHist = async (searchYear: string|undefined, facilityCd: string|undefined): Promise<WaterQualityHistoryResponse | null> => {
|
||||
try {//
|
||||
const res = await getFetch('fo', '/fclt/qlty/hist/' + searchYear + '/' + facilityCd);
|
||||
return res;
|
||||
} catch (error) {
|
||||
console.error('시설정보 수질현황 이력 데이터를 가져오는데 실패했습니다:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**====================================
|
||||
* Store - export
|
||||
====================================*/
|
||||
export type FacilityWaterQltyType = {
|
||||
FacilityWaterQltyMain: {
|
||||
facilityWaterQltyList: FacilityWaterQltyProps[];
|
||||
excelList: ExcelType[];
|
||||
facilityWaterQltyCount: number;
|
||||
isInit: boolean;
|
||||
mainLabelArray: string[];
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
},
|
||||
|
||||
FacilityWaterQltyModal: {
|
||||
// 처리시설 수질현황
|
||||
upHeadListModalYear: TableUpperProps[];
|
||||
facilityWaterQltyYearList: FacilityWaterQltyProps[];
|
||||
upHeadListModalTms: TableUpperProps[];
|
||||
facilityWaterQltyTmsList: FacilityWaterQltyTmsProps[];
|
||||
|
||||
// 수질tms
|
||||
tmsList: FacilityWaterQltyTmsProps[];
|
||||
msrmtDate: string;
|
||||
|
||||
// 총인시설 수질현황
|
||||
upHeadListModalChongIn: TableUpperProps[];
|
||||
}
|
||||
}
|
||||
|
||||
export const facilityWaterQltyInitState: FacilityWaterQltyType = {
|
||||
FacilityWaterQltyMain: {
|
||||
facilityWaterQltyCount: 0,
|
||||
facilityWaterQltyList: [],
|
||||
excelList: [],
|
||||
isInit: false,
|
||||
mainLabelArray: mainLabelArray,
|
||||
upHeadList1: upHeadList1,
|
||||
upHeadList2: upHeadList2,
|
||||
upHeadList3: upHeadList3,
|
||||
},
|
||||
|
||||
FacilityWaterQltyModal: {
|
||||
// 처리시설 수질현황
|
||||
upHeadListModalYear: upHeadListModalYear,
|
||||
facilityWaterQltyYearList: facilityWaterQltyYearList,
|
||||
upHeadListModalTms: upHeadListModalTms,
|
||||
facilityWaterQltyTmsList: facilityWaterQltyTmsList,
|
||||
|
||||
// 수질tms
|
||||
tmsList: [],
|
||||
msrmtDate: '',
|
||||
|
||||
// 총인시설 수질현황
|
||||
upHeadListModalChongIn: upHeadListModalChongIn,
|
||||
}
|
||||
}
|
||||
|
||||
export type FacilityWaterQltyActions = {
|
||||
/**
|
||||
* 시설정보 수질현황 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
* @param searchYear : 검색 년도
|
||||
* @param part : 구분
|
||||
* @param nameCd : 시설명
|
||||
* @param fcltCpct : 시설용량
|
||||
* @param operationValue : 운영상태코드
|
||||
* @param fcltyNm : 시설명
|
||||
*/
|
||||
searchFacilityWaterQltyList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => Promise<void>;
|
||||
|
||||
/**
|
||||
* 시설정보 수질현황 이력 데이터 호출
|
||||
* @param searchYear : 검색 년도
|
||||
* @param facilityCd : 시설코드
|
||||
*/
|
||||
searchFacilityWaterQltyListHist: (searchYear: string, facilityCd: string) => Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param item : 시설수질리스트 타입
|
||||
* @returns : 없음
|
||||
* @description : 시설수질리스트 타입의 데이터를 표현 방식으로 바꿔주는 함수
|
||||
* - msrDt : YYYY-MM-DD 형식으로 변환
|
||||
* - inflAssctAftWqltBod : 소수점 1자리까지 표현
|
||||
* - inflAssctAftWqltTn : 소수점 1자리까지 표현
|
||||
* - inflAssctBfrWqltTp : 소수점 1자리까지 표현
|
||||
* - efflWqltBod : 소수점 2자리까지 표현
|
||||
* - efflWqltTn : 소수점 2자리까지 표현
|
||||
* - efflWqltTp : 소수점 2자리까지 표현
|
||||
* @author : 박진우
|
||||
* @date : 2025-04-24
|
||||
*/
|
||||
const dataFormSetting = (item: FacilityWaterQltyProps) => {
|
||||
DataForm({ type: 'date', column: 'msrDt', item: item as unknown as Record<string, unknown> });
|
||||
}
|
||||
|
||||
export type FacilityWaterQltyStore = FacilityWaterQltyType & FacilityWaterQltyActions;
|
||||
|
||||
export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType) => FacilityWaterQltyType) => void): FacilityWaterQltyActions => {
|
||||
return {
|
||||
// 메인페이지
|
||||
/**
|
||||
* 시설정보 수질현황 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
* @param searchYear : 검색 년도
|
||||
* @param part : 구분
|
||||
* @param nameCd : 시설명
|
||||
* @param fcltCpct : 시설용량
|
||||
* @param operationValue : 운영상태코드
|
||||
* @param fcltyNm : 시설명
|
||||
*/
|
||||
searchFacilityWaterQltyList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const res = await fetchFacilityWaterQltyList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const rtnData = res.data.map(item => {
|
||||
dataFormSetting(item)
|
||||
if(item.inflAssctAftWqltTn) {
|
||||
item.inflAssctAftWqltTn = Number(Math.round(Number(item.inflAssctAftWqltTn) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.efflWqltTn){
|
||||
item.efflWqltTn = Number(Math.round(Number(item.efflWqltTn) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.inflAssctAftWqltTp){
|
||||
item.inflAssctAftWqltTp = Number(Math.round(Number(item.inflAssctAftWqltTp) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.efflWqltTp){
|
||||
item.efflWqltTp = Number(Math.round(Number(item.efflWqltTp) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.inflAssctAftWqltToc){
|
||||
item.inflAssctAftWqltToc = Number(Math.round(Number(item.inflAssctAftWqltToc) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltCod){
|
||||
item.efflWqltCod = Number(Math.round(Number(item.efflWqltCod) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctAftWqltBod){
|
||||
item.inflAssctAftWqltBod = Number(Math.round(Number(item.inflAssctAftWqltBod) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltBod){
|
||||
item.efflWqltBod = Number(Math.round(Number(item.efflWqltBod) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctAftWqltSs){
|
||||
item.inflAssctAftWqltSs = Number(Math.round(Number(item.inflAssctAftWqltSs) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltSs){
|
||||
item.efflWqltSs = Number(Math.round(Number(item.efflWqltSs) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctAftWqltToc){
|
||||
item.inflAssctAftWqltToc = Number(Math.round(Number(item.inflAssctAftWqltToc) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltCod){
|
||||
item.efflWqltCod = Number(Math.round(Number(item.efflWqltCod) * 10)/10).toFixed(1);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
const excelDownList: ExcelType[] = [];
|
||||
if(pageSize>5000){
|
||||
res.data.forEach(item => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시도: item.sidoNm,
|
||||
시군구: item.sggNm,
|
||||
시설이름: item.bscFctNm,
|
||||
주소: item.addr,
|
||||
용량: item.fctCpc,
|
||||
유입BOD: item.inflAssctAftWqltBod,
|
||||
유입TOC: item.inflAssctAftWqltToc,
|
||||
유입SS: item.inflAssctAftWqltSs,
|
||||
유입TN: item.inflAssctAftWqltTn,
|
||||
유입TP: item.inflAssctAftWqltTp,
|
||||
유출BOD: item.efflWqltBod,
|
||||
유출TOC: item.efflWqltCod,
|
||||
유출SS: item.efflWqltSs,
|
||||
유출TN: item.efflWqltTn,
|
||||
유출TP: item.efflWqltTp,
|
||||
});
|
||||
});
|
||||
}else{
|
||||
res.data.forEach((item: FacilityWaterQltyProps) => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
});
|
||||
}
|
||||
set((state: FacilityWaterQltyType) => ({
|
||||
...state,
|
||||
FacilityWaterQltyMain: pageSize<5000?{
|
||||
...state.FacilityWaterQltyMain,
|
||||
facilityWaterQltyList: rtnData,
|
||||
facilityWaterQltyCount: res.count,
|
||||
}:{
|
||||
...state.FacilityWaterQltyMain,
|
||||
excelList: excelDownList,
|
||||
}
|
||||
}))
|
||||
},
|
||||
|
||||
searchFacilityWaterQltyListHist: async (searchYear: string, facilityCd: string) => {
|
||||
const res = await fetchFacilityWaterQltyListHist(searchYear, facilityCd);
|
||||
const res1 = await fetchFacilityWaterQltyTmsList(facilityCd);
|
||||
|
||||
let rtnMsrmtDate = '';
|
||||
const rtnTmsList: FacilityWaterQltyTmsProps[] = [];
|
||||
if(res1.data){
|
||||
rtnTmsList.push({
|
||||
part: '평균',
|
||||
toc: res1.data.tocAvgVl,
|
||||
ss: res1.data.ssAvgVl,
|
||||
tn: res1.data.tnAvgVl,
|
||||
tp: res1.data.tpAvgVl,
|
||||
});
|
||||
|
||||
rtnTmsList.push({
|
||||
part: '최대',
|
||||
toc: res1.data.tocMaxVl,
|
||||
ss: res1.data.ssMaxVl,
|
||||
tn: res1.data.tnMaxVl,
|
||||
tp: res1.data.tpMaxVl,
|
||||
});
|
||||
|
||||
rtnTmsList.push({
|
||||
part: '최소',
|
||||
toc: res1.data.tocMinVl,
|
||||
ss: res1.data.ssMinVl,
|
||||
tn: res1.data.tnMinVl,
|
||||
tp: res1.data.tpMinVl,
|
||||
});
|
||||
|
||||
rtnMsrmtDate = res1.data.msrmtDate;
|
||||
}else{
|
||||
rtnTmsList.push({
|
||||
part: '평균',
|
||||
toc: 0,
|
||||
ss: 0,
|
||||
tn: 0,
|
||||
tp: 0,
|
||||
});
|
||||
|
||||
rtnTmsList.push({
|
||||
part: '최대',
|
||||
toc: 0,
|
||||
ss: 0,
|
||||
tn: 0,
|
||||
tp: 0,
|
||||
});
|
||||
|
||||
rtnTmsList.push({
|
||||
part: '최소',
|
||||
toc: 0,
|
||||
ss: 0,
|
||||
tn: 0,
|
||||
tp: 0,
|
||||
});
|
||||
|
||||
rtnMsrmtDate = '';
|
||||
}
|
||||
|
||||
if(Array.isArray(res) || !res || !('data' in res) || !res.data || !res.data.wqltObjs || res.data.wqltObjs.length === 0) {
|
||||
set((state: FacilityWaterQltyType) => ({
|
||||
...state,
|
||||
FacilityWaterQltyModal: {
|
||||
...state.FacilityWaterQltyModal,
|
||||
facilityWaterQltyYearList: [],
|
||||
tmsList : rtnTmsList,
|
||||
msrmtDate : rtnMsrmtDate
|
||||
}
|
||||
}))
|
||||
return;
|
||||
}
|
||||
|
||||
const tmpData:FacilityWaterQltyProps[] = [];
|
||||
|
||||
// facilityPrecipitation의 rainEffectDay 계산 로직을 적용
|
||||
for(let idx = 0; idx < res.data.wqltObjs.length; idx++) {
|
||||
const item = res.data.wqltObjs[idx];
|
||||
if (!item) continue;
|
||||
|
||||
const rainDay = Number(item.infoRnDay) >= 3 ? 1 : 0;
|
||||
let rainEffectDay = 0;
|
||||
|
||||
if(idx < res.data.wqltObjs.length - 2) {
|
||||
if(rainDay == 1) {
|
||||
rainEffectDay = 1;
|
||||
} else {
|
||||
if(idx >= 2) {
|
||||
const prevItem1 = res.data.wqltObjs[idx-1];
|
||||
const prevItem2 = res.data.wqltObjs[idx-2];
|
||||
if((prevItem1 && Number(prevItem1.infoRnDay) >= 3) || (prevItem2 && Number(prevItem2.infoRnDay) >= 3)) {
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(idx < res.data.wqltObjs.length - 1) {
|
||||
const nextItem = res.data.wqltObjs[idx+1];
|
||||
if(rainDay == 1 || (nextItem && Number(nextItem.infoRnDay) >= 3)) {
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
} else {
|
||||
rainEffectDay = rainDay;
|
||||
}
|
||||
|
||||
tmpData.push({
|
||||
...item,
|
||||
rainEffectDay: rainEffectDay,
|
||||
} as FacilityWaterQltyProps);
|
||||
}
|
||||
|
||||
const rtnData = tmpData.map((item: FacilityWaterQltyProps) => {
|
||||
dataFormSetting(item)
|
||||
if(item.inflAssctAftWqltTn) {
|
||||
item.inflAssctAftWqltTn = Number(Math.round(Number(item.inflAssctAftWqltTn) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.efflWqltTn){
|
||||
item.efflWqltTn = Number(Math.round(Number(item.efflWqltTn) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.inflAssctBfrWqltTp){
|
||||
item.inflAssctBfrWqltTp = Number(Math.round(Number(item.inflAssctBfrWqltTp) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.efflWqltTp){
|
||||
item.efflWqltTp = Number(Math.round(Number(item.efflWqltTp) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.inflAssctAftWqltToc){
|
||||
item.inflAssctAftWqltToc = Number(Math.round(Number(item.inflAssctAftWqltToc) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltCod){
|
||||
item.efflWqltCod = Number(Math.round(Number(item.efflWqltCod) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctAftWqltBod){
|
||||
item.inflAssctAftWqltBod = Number(Math.round(Number(item.inflAssctAftWqltBod) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltBod){
|
||||
item.efflWqltBod = Number(Math.round(Number(item.efflWqltBod) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctAftWqltSs){
|
||||
item.inflAssctAftWqltSs = Number(Math.round(Number(item.inflAssctAftWqltSs) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltSs){
|
||||
item.efflWqltSs = Number(Math.round(Number(item.efflWqltSs) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctAftWqltToc){
|
||||
item.inflAssctAftWqltToc = Number(Math.round(Number(item.inflAssctAftWqltToc) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltCod){
|
||||
item.efflWqltCod = Number(Math.round(Number(item.efflWqltCod) * 10)/10).toFixed(1);
|
||||
}
|
||||
|
||||
if(item.tpInflWqltBod){
|
||||
item.tpInflWqltBod = item.tpInflWqltBod?Number(Math.round(Number(item.tpInflWqltBod) * 10)/10).toFixed(1):Number(item.tpInflWqltBod)===0?'0.0':'';
|
||||
}else{
|
||||
item.tpInflWqltBod = '';
|
||||
}
|
||||
|
||||
if(item.tpInflWqltTp){
|
||||
item.tpInflWqltTp = item.tpInflWqltTp?Number(Math.round(Number(item.tpInflWqltTp) * 1000)/1000).toFixed(3): Number(item.tpInflWqltTp)===0?'0.000':'';
|
||||
}else{
|
||||
item.tpInflWqltTp = '';
|
||||
}
|
||||
return item;
|
||||
})
|
||||
set((state: FacilityWaterQltyType) => ({
|
||||
...state,
|
||||
FacilityWaterQltyModal: {
|
||||
...state.FacilityWaterQltyModal,
|
||||
facilityWaterQltyYearList: rtnData,
|
||||
tmsList : rtnTmsList,
|
||||
msrmtDate : rtnMsrmtDate
|
||||
}
|
||||
}))
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,366 +0,0 @@
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
const FlowRateSearchLabelArray:string[] = ['구분', '시도', '시군구', '용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
export type flowRateListProps = {
|
||||
bscFctCd : string,
|
||||
sidoNm : string,
|
||||
sggNm : string,
|
||||
bscFctNm : string,
|
||||
daddr : string,
|
||||
fctCpc : number,
|
||||
lclgvrnmntNm : string,
|
||||
totInflAmnt : number | '',
|
||||
inflAmnt : number | '',
|
||||
sumFlow : number | '',
|
||||
returnAmnt : number | '',
|
||||
efflAmnt : number | '',
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
infoRnDay : number | '',
|
||||
}
|
||||
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설이름: string,
|
||||
주소: string,
|
||||
용량: number,
|
||||
총유입량: number | '',
|
||||
하수유입량: number | '',
|
||||
연계처리량: number | '',
|
||||
총인반류수량: number | '',
|
||||
방류량: number | '',
|
||||
환경청:string|'',
|
||||
}
|
||||
|
||||
export type modalExcelType = {
|
||||
날짜: string,
|
||||
"총유입량(m³/일)": number | '',
|
||||
"하수유입량(m³/일)": number | '',
|
||||
"연계처리량(m³/일)": number | '',
|
||||
"총인반류수량(m³/일)": number | '',
|
||||
"방류량(m³/일)": number | '',
|
||||
"강우량": number | string | '',
|
||||
}
|
||||
/**
|
||||
* (2) 모달
|
||||
*/
|
||||
export interface FlowRateModalInterface {
|
||||
msrDt : string,
|
||||
totInflAmnt : number | '',
|
||||
inflAmnt : number | '',
|
||||
sumFlow : number | '',
|
||||
returnAmnt : number | '',
|
||||
efflAmnt : number | '',
|
||||
infoRnDay : number | string | '',
|
||||
rainEffectDay : number | string | '' ,
|
||||
}
|
||||
export type FlowRateModalProps = {
|
||||
msrDt : string,
|
||||
totInflAmnt : number,
|
||||
inflAmnt : number,
|
||||
sumFlow : number,
|
||||
returnAmnt : number,
|
||||
efflAmnt : number,
|
||||
infoRnDay : number | string | '',
|
||||
rainEffectDay : number | string | '',
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 리스트 (행정별)
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2},
|
||||
{ id: "A", title: "행정명", row: 0 ,colSpan: 2 },
|
||||
{ id: "sidoNm", title: "시도", upName:"upChangeRe", row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName:"upChangeRe", row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "totInflAmnt", title: "총 유입입량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2}
|
||||
];
|
||||
|
||||
// 리스트 (권역별)
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2},
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3},
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "totInflAmnt", title: "총 유입입량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2}
|
||||
];
|
||||
|
||||
// 리스트 (환경청별별)
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "행정명", row: 0 ,colSpan: 2 },
|
||||
{ id: "ctpvNm", title: "시도", upName:"upChangeRe2", row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName:"upChangeRe2", row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2 },
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "totInflAmnt", title: "총 유입입량\n(m³/일)", align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2 }
|
||||
];
|
||||
|
||||
const flowRateList:flowRateListProps[] = [
|
||||
]
|
||||
|
||||
/**
|
||||
* (2) 모달
|
||||
*/
|
||||
|
||||
const upHeadListFlowRateModal:TableUpperProps[] = [
|
||||
{ id: "msrDt", title: "날짜"},
|
||||
{ id: "totInflAmnt", title: "총 유입량(m³/일)", align:"right"},
|
||||
{ id: "inflAmnt", title: "하수유입량(m³/일)", align:"right"},
|
||||
{ id: "sumFlow", title: "연계처리량(m³/일)", align:"right"},
|
||||
{ id: "returnAmnt", title: "총인 반류수량(m³/일)", align:"right"},
|
||||
{ id: "efflAmnt", title: "방류량(m³/일)", align:"right"},
|
||||
{ id: "infoRnDay", title: "강우량", align:"right"}
|
||||
]
|
||||
|
||||
const modalFlowRateListYear:FlowRateModalProps[] = [
|
||||
]
|
||||
|
||||
/**====================================
|
||||
* Store - API
|
||||
====================================*/
|
||||
const fetchFlowRateList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
try {
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : ''; const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
console.log(url);
|
||||
return { data: res.data, count: res.count }
|
||||
} catch (error) {
|
||||
console.error('시설정보 유량현황 데이터를 가져오는데 실패했습니다:', error);
|
||||
return { data: [], count: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
const fetchFlowRateModalList = async (bscFctCd: string, searchYear: string) => {
|
||||
try {
|
||||
const url = '/fclt/flow/' + bscFctCd + '/' + searchYear;
|
||||
const res = await getFetch('fo', url);
|
||||
|
||||
// msrDt 오름차순으로 정렬
|
||||
const sortedData = res.data.sort((a: FlowRateModalInterface, b: FlowRateModalInterface) => {
|
||||
return new Date(a.msrDt).getTime() - new Date(b.msrDt).getTime();
|
||||
});
|
||||
|
||||
return { data: sortedData }
|
||||
} catch (error) {
|
||||
console.error('시설정보 유량현황 모달 데이터를 가져오는데 실패했습니다:', error);
|
||||
return { data: [] }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
|
||||
export type FlowRateSearchActions = {
|
||||
searchFlowRateList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
|
||||
|
||||
searchFlowRateModalList : (bscFctCd: string, searchYear: string) => void;
|
||||
}
|
||||
|
||||
export type FlowRateSearchType = {
|
||||
FlowRateSearch: {
|
||||
isInit: boolean;
|
||||
flowRateSearchLabelArray:string[];
|
||||
},
|
||||
|
||||
FlowRateList : {
|
||||
isInit : boolean;
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
flowRateList:flowRateListProps[];
|
||||
flowRateCount: number;
|
||||
excelList: ExcelType[];
|
||||
},
|
||||
|
||||
FlowRateModal : {
|
||||
isInit : boolean;
|
||||
modalFlowRateListYear : FlowRateModalProps[];
|
||||
upHeadListFlowRateModalYear : TableUpperProps[];
|
||||
}
|
||||
}
|
||||
|
||||
export type FlowRateSearchStore = FlowRateSearchType & FlowRateSearchActions;
|
||||
|
||||
const dataFormSetting=(item : flowRateListProps | FlowRateModalProps)=> {
|
||||
DataForm({ type: 'date', column: 'msrDt', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'totInflAmnt', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'inflAmnt', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'sumFlow', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'efflWqltBod', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'returnAmnt', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'efflAmnt', item: item as unknown as Record<string, unknown>});
|
||||
}
|
||||
|
||||
export const flowRateSearchInitState:FlowRateSearchType = {
|
||||
FlowRateSearch: {
|
||||
isInit: false,
|
||||
flowRateSearchLabelArray: FlowRateSearchLabelArray,
|
||||
},
|
||||
FlowRateList : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
upHeadList2 : upHeadList2,
|
||||
upHeadList3 : upHeadList3,
|
||||
flowRateList : flowRateList,
|
||||
flowRateCount : 0,
|
||||
excelList: []
|
||||
},
|
||||
FlowRateModal : {
|
||||
isInit : false,
|
||||
upHeadListFlowRateModalYear : upHeadListFlowRateModal,
|
||||
modalFlowRateListYear : modalFlowRateListYear,
|
||||
}
|
||||
}
|
||||
|
||||
export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => FlowRateSearchType) => void)=>FlowRateSearchActions=(set: (fn: (state: FlowRateSearchType) => FlowRateSearchType) => void) => {
|
||||
return {
|
||||
searchFlowRateList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const res = await fetchFlowRateList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const data = res.data;
|
||||
const excelDownList: ExcelType[] = [];
|
||||
|
||||
const rtnData = data.map((item: flowRateListProps) => {
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0)
|
||||
dataFormSetting(item);
|
||||
return item;
|
||||
});
|
||||
|
||||
if(pageSize>5000){
|
||||
rtnData.forEach((item: flowRateListProps) => {
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시도: item.sidoNm,
|
||||
시군구: item.sggNm,
|
||||
시설이름: item.bscFctNm,
|
||||
주소: item.daddr,
|
||||
용량: item.fctCpc,
|
||||
총유입량: item.totInflAmnt,
|
||||
하수유입량: item.inflAmnt,
|
||||
연계처리량: item.sumFlow,
|
||||
총인반류수량: item.returnAmnt,
|
||||
방류량: item.efflAmnt,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
console.log('excelDownList' , excelDownList);
|
||||
set((state: FlowRateSearchType) => ({
|
||||
...state,
|
||||
FlowRateList: pageSize<5000?{
|
||||
...state.FlowRateList,
|
||||
flowRateList: rtnData,
|
||||
flowRateCount: res.count,
|
||||
}:{
|
||||
...state.FlowRateList,
|
||||
excelList: excelDownList,
|
||||
}
|
||||
}))
|
||||
},
|
||||
searchFlowRateModalList: async (bscFctCd: string, searchYear: string) => {
|
||||
const res = await fetchFlowRateModalList(bscFctCd, searchYear);
|
||||
const data = res.data;
|
||||
|
||||
const tmpData:FlowRateModalProps[] = [];
|
||||
// facilityPrecipitation의 rainEffectDay 계산 로직을 적용
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
const item = data[idx];
|
||||
const rainDay = Number(item.infoRnDay) >= 3 ? 1 : 0;
|
||||
let rainEffectDay = 0;
|
||||
|
||||
if(idx < data.length - 2) {
|
||||
if(rainDay == 1) {
|
||||
rainEffectDay = 1;
|
||||
} else {
|
||||
if(idx >= 2) {
|
||||
if(Number(data[idx-1].infoRnDay) >= 3 || Number(data[idx-2].infoRnDay) >= 3) {
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(idx < data.length - 1) {
|
||||
if(rainDay == 1 || Number(data[idx+1].infoRnDay) >= 3) {
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
} else {
|
||||
rainEffectDay = rainDay;
|
||||
}
|
||||
|
||||
tmpData.push({
|
||||
...item,
|
||||
rainEffectDay: rainEffectDay,
|
||||
});
|
||||
}
|
||||
|
||||
const rtnData = tmpData.map((item: FlowRateModalProps) => {
|
||||
item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0)
|
||||
dataFormSetting(item);
|
||||
return item;
|
||||
});
|
||||
|
||||
set((state: FlowRateSearchType) => ({
|
||||
...state,
|
||||
FlowRateModal: {
|
||||
...state.FlowRateModal,
|
||||
modalFlowRateListYear: rtnData || [],
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import { type ReactNode, createContext, useContext, useRef } from 'react'
|
||||
import { useStore } from 'zustand'
|
||||
import { type FoStore, StoreZus } from './store'
|
||||
|
||||
|
||||
export type StoreApi = ReturnType<typeof StoreZus>
|
||||
|
||||
export const StoreContext = createContext<StoreApi | undefined>(
|
||||
undefined,
|
||||
)
|
||||
|
||||
export interface StoreProviderProps {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export const StoreProvider = ({
|
||||
children,
|
||||
}: StoreProviderProps) => {
|
||||
const storeRef = useRef<StoreApi>()
|
||||
|
||||
if (!storeRef.current) {
|
||||
const store = StoreZus()
|
||||
storeRef.current = store
|
||||
}
|
||||
|
||||
return (
|
||||
<StoreContext.Provider value={storeRef.current}>
|
||||
{children}
|
||||
</StoreContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useFoStore = <T,>(
|
||||
selector: (store: FoStore) => T,
|
||||
): T => {
|
||||
const storeContext = useContext(StoreContext)
|
||||
|
||||
if (!storeContext) {
|
||||
throw new Error(`useStore must be used within StoreProvider`)
|
||||
}
|
||||
|
||||
return useStore(storeContext, selector)
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { getFetch } from "@/app/components/api";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 시설별 강수현황
|
||||
type PlanSewageProps = {
|
||||
bscFctCd : string,
|
||||
sido : string,
|
||||
gugun : string,
|
||||
bscFctNm : string,
|
||||
daddr : string,
|
||||
fctCpc : number,
|
||||
spareCapacity : number,
|
||||
variableLoadPercent : number,
|
||||
classifiedSewerPercent : number,
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
sprtProcZoneAr : number,
|
||||
procZoneSm : number,
|
||||
avgInflAmnt : number,
|
||||
avgInflAmntSunny : number,
|
||||
maxInflAmntSunny : number,
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 검색단
|
||||
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "행정구역", upSequnce:1, row:0, colSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' },
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row:1},
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' },
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1},
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "행정구역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' },
|
||||
];
|
||||
|
||||
const planSewageList:PlanSewageProps[] = [
|
||||
]
|
||||
|
||||
/**====================================
|
||||
* Store - api
|
||||
====================================*/
|
||||
const fetchPlanSewageList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + (nameCd || '0') + '/' + (fcltCpct || '0') + '/' + (operationValue || '0') +'/0'+ (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/prcsFclt/info/plan/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
console.log(url);
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count }
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type ExcelType = {
|
||||
시설코드: string;
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string;
|
||||
시군구: string;
|
||||
시설이름: string;
|
||||
주소: string;
|
||||
시설용량: number;
|
||||
여유용량: number;
|
||||
변동부하율 : number;
|
||||
분류식화율 : number;
|
||||
}
|
||||
|
||||
const dataFormSetting=(item : PlanSewageProps)=> {
|
||||
DataForm({ type: 'float1', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'spareCapacity', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'variableLoadPercent', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'classifiedSewerPercent', item: item as unknown as Record<string, unknown>});
|
||||
};
|
||||
|
||||
export type PlanSewageActions = {
|
||||
searchPlanSewageList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
|
||||
}
|
||||
|
||||
export type PlanSewageType = {
|
||||
PlanSewageSearch: {
|
||||
isInit: boolean;
|
||||
labelArray:string[];
|
||||
},
|
||||
|
||||
PlanSewage : {
|
||||
isInit: boolean;
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
planSewageList: PlanSewageProps[];
|
||||
planSewageCount: number;
|
||||
excelList: ExcelType[];
|
||||
},
|
||||
}
|
||||
|
||||
export const planSewageInitState: PlanSewageType = {
|
||||
PlanSewageSearch: {
|
||||
isInit: false,
|
||||
labelArray: LabelArray,
|
||||
},
|
||||
|
||||
PlanSewage : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
upHeadList2 : upHeadList2,
|
||||
upHeadList3 : upHeadList3,
|
||||
planSewageList : planSewageList,
|
||||
planSewageCount : 0,
|
||||
excelList : []
|
||||
},
|
||||
}
|
||||
|
||||
export type PlanSewageStore = PlanSewageType & PlanSewageActions;
|
||||
|
||||
export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageType) => void)=>PlanSewageActions=(set: (fn: (state: PlanSewageType) => PlanSewageType) => void) => {
|
||||
return {
|
||||
searchPlanSewageList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const res = await fetchPlanSewageList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const excelDownList: ExcelType[] = [];
|
||||
console.log('res' , res.data);
|
||||
/**
|
||||
* 결과데이터 계산
|
||||
* (1) 여유용량 = 시설용량 - 건기시 평균유량
|
||||
* (2) 변동부하율 = 건기시 일최대 유량/일평균유량(기준 최근 3개년)
|
||||
* (3) 분류식화율 = 분류식지역 면적(㎢)/처리구역 면적합계(㎢) ×100
|
||||
*/
|
||||
const resultData = res.data.map((item:PlanSewageProps) => {
|
||||
item.spareCapacity = Number(item.fctCpc) - Number(item.avgInflAmntSunny);
|
||||
item.variableLoadPercent = item.maxInflAmntSunny && item.maxInflAmntSunny!==0 ? Number(item.maxInflAmntSunny) / Number(item.avgInflAmntSunny) : 0;
|
||||
item.classifiedSewerPercent = item.sprtProcZoneAr && item.sprtProcZoneAr!==0 ? Number(item.sprtProcZoneAr) / Number(item.procZoneSm) * 100 : 0;
|
||||
return item;
|
||||
});
|
||||
|
||||
resultData.forEach((item:PlanSewageProps) => {
|
||||
dataFormSetting(item)
|
||||
})
|
||||
|
||||
if(pageSize>5000){
|
||||
resultData.forEach((item:PlanSewageProps) => {
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.lgbsn,
|
||||
단위유역: item.rvbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시설이름: item.bscFctNm,
|
||||
시도: item.sido,
|
||||
시군구: item.gugun,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc,
|
||||
여유용량: item.spareCapacity,
|
||||
변동부하율: item.variableLoadPercent,
|
||||
분류식화율: item.classifiedSewerPercent,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
set((state:PlanSewageType) => ({
|
||||
...state,
|
||||
PlanSewage: pageSize<5000?{
|
||||
...state.PlanSewage,
|
||||
planSewageList: resultData,
|
||||
planSewageCount: res.count,
|
||||
}:{
|
||||
...state.PlanSewage,
|
||||
excelList: excelDownList,
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,507 +0,0 @@
|
||||
import { getFetchAreaList, postFetch } from "@/app/components/api";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 처리구역 리스트
|
||||
export type ProcessAreaProps = {
|
||||
swtrmtFcltCd : string,
|
||||
sido : string,
|
||||
gugun : string,
|
||||
swtrmtFcltNm : string,
|
||||
location : string,
|
||||
fctCpc : number | '',
|
||||
ruse : boolean,
|
||||
yrDt4 : string,
|
||||
yr : string,
|
||||
yrDc1 : string,
|
||||
yrDc2 : string,
|
||||
yrDc3 : string,
|
||||
yrDc4 : string,
|
||||
/**
|
||||
* 증설계획
|
||||
*/
|
||||
// 기승인(당초4단계), 현재, 변경1~4
|
||||
planSwageQntSumDt4 : number | '',
|
||||
planSwageQntSum : number | '',
|
||||
planSwageQntSumDc1 : number | '',
|
||||
planSwageQntSumDc2 : number | '',
|
||||
planSwageQntSumDc3 : number | '',
|
||||
planSwageQntSumDc4 : number | '',
|
||||
/**
|
||||
* 처리인구
|
||||
*/
|
||||
// 기승인(당초4단계), 변경1~4
|
||||
swtrmtPpltnCntDt4 : number | '',
|
||||
swtrmtPpltnCnt : number | '',
|
||||
swtrmtPpltnCntDc1 : number | '',
|
||||
swtrmtPpltnCntDc2 : number | '',
|
||||
swtrmtPpltnCntDc3 : number | '',
|
||||
swtrmtPpltnCntDc4 : number | '',
|
||||
/**
|
||||
* 처리구역면적
|
||||
*/
|
||||
// 기승인(당초4단계), 변경1~4
|
||||
swtrmtZoneAreaDt4 : number | '',
|
||||
swtrmtZoneArea : number | '',
|
||||
swtrmtZoneAreaDc1 : number | '',
|
||||
swtrmtZoneAreaDc2 : number | '',
|
||||
swtrmtZoneAreaDc3 : number | '',
|
||||
swtrmtZoneAreaDc4 : number | '',
|
||||
// 처리구역
|
||||
trtDstr : string | '',
|
||||
}
|
||||
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
시설명: string,
|
||||
주소: string,
|
||||
시설용량: number | '',
|
||||
증설계획기존: number | '',
|
||||
증설계획현재: number | '',
|
||||
증설계획1단계: number | '',
|
||||
증설계획2단계: number | '',
|
||||
증설계획3단계: number | '',
|
||||
증설계획4단계: number | '',
|
||||
처리인구기존: number | '',
|
||||
처리인구현재: number | '',
|
||||
처리인구1단계: number | '',
|
||||
처리인구2단계: number | '',
|
||||
처리인구3단계: number | '',
|
||||
처리인구4단계: number | '',
|
||||
처리구역기존: number | '',
|
||||
처리구역현재: number | '',
|
||||
처리구역1단계: number | '',
|
||||
처리구역2단계: number | '',
|
||||
처리구역3단계: number | '',
|
||||
처리구역4단계: number | '',
|
||||
처리구역: string | ''
|
||||
}
|
||||
|
||||
// (2) 처리구역 팝업
|
||||
// 시설증설 계획
|
||||
export type FcltyImproveInfoProps = {
|
||||
planSwageQntSumDt4 : number | '',
|
||||
planSwageQntSum : number | '',
|
||||
planSwageQntSumDc1 : number | '',
|
||||
planSwageQntSumDc2 : number | '',
|
||||
planSwageQntSumDc3 : number | '',
|
||||
planSwageQntSumDc4 : number | '',
|
||||
}
|
||||
|
||||
// 처리인구 계획
|
||||
export type ProcessPopulationProps = {
|
||||
swtrmtPpltnCntDt4 : number | '',
|
||||
swtrmtPpltnCnt : number | '',
|
||||
swtrmtPpltnCntDc1 : number | '',
|
||||
swtrmtPpltnCntDc2 : number | '',
|
||||
swtrmtPpltnCntDc3 : number | '',
|
||||
swtrmtPpltnCntDc4 : number | '',
|
||||
}
|
||||
// 처리구역 계획
|
||||
export type ProcessAreaPlanProps = {
|
||||
swtrmtZoneAreaDt4 : number | '',
|
||||
swtrmtZoneArea : number | '',
|
||||
swtrmtZoneAreaDc1 : number | '',
|
||||
swtrmtZoneAreaDc2 : number | '',
|
||||
swtrmtZoneAreaDc3 : number | '',
|
||||
swtrmtZoneAreaDc4 : number | '',
|
||||
trtDstr : string,
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 검색단
|
||||
const ProcessFacilityLabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '시설상태', '연도별', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
// 리스트 헤더(행정별)
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "swtrmtFcltCd", title: "시설코드", rowSpan:3, row:0},
|
||||
{ id: "A", title: "행정구역", colSpan:2, rowSpan:2, row:0},
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", row:2 },
|
||||
{ id: "sigungo", title: "시군구", upName:"upChangeRe", row:2 },
|
||||
{ id: "swtrmtFcltNm", title: "시설명", rowSpan:3, row:0},
|
||||
{ id: "location", title: "주소", rowSpan:3, row:0, },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", rowSpan:3, row:0},
|
||||
{ id: "B", title: "시설계획", colSpan:19, row:0},
|
||||
{ id: "C", title: "증설계획(m³/일)", colSpan:6, row:1},
|
||||
{ id: "planSwageQntSumDt4", title: "기승인\n4단계", row:2},
|
||||
{ id: "planSwageQntSum", title: "현재", row:2},
|
||||
{ id: "planSwageQntSumDc1", title: "1단계", row:2},
|
||||
{ id: "planSwageQntSumDc2", title: "2단계", row:2},
|
||||
{ id: "planSwageQntSumDc3", title: "3단계", row:2},
|
||||
{ id: "planSwageQntSumDc4", title: "4단계", row:2},
|
||||
{ id: "D", title: "처리인구(인)", colSpan:6, row:1},
|
||||
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계", row:2},
|
||||
{ id: "swtrmtPpltnCnt", title: "현재", row:2},
|
||||
{ id: "swtrmtPpltnCntDc1", title: "1단계", row:2},
|
||||
{ id: "swtrmtPpltnCntDc2", title: "2단계", row:2},
|
||||
{ id: "swtrmtPpltnCntDc3", title: "3단계", row:2},
|
||||
{ id: "swtrmtPpltnCntDc4", title: "4단계", row:2},
|
||||
{ id: "E", title: "처리구역(km²)", colSpan:7, row:1},
|
||||
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계", row:2},
|
||||
{ id: "swtrmtZoneArea", title: "현재", row:2},
|
||||
{ id: "swtrmtZoneAreaDc1", title: "1단계", row:2},
|
||||
{ id: "swtrmtZoneAreaDc2", title: "2단계", row:2},
|
||||
{ id: "swtrmtZoneAreaDc3", title: "3단계", row:2},
|
||||
{ id: "swtrmtZoneAreaDc4", title: "4단계", row:2},
|
||||
{ id: "trtDstr", title: "처리구역", row:2}
|
||||
];
|
||||
|
||||
const processAreaList:ProcessAreaProps[] = [
|
||||
]
|
||||
|
||||
/**
|
||||
* 처리구역정보 상세팝업
|
||||
*/
|
||||
// 시설증설 계획 (헤더)
|
||||
const upHeadListFcltyImproveInfo:TableUpperProps[] = [
|
||||
{ id: "planSwageQntSumDt4", title: "기승인\n4단계(m³/일)", rowSpan:2, row:0},
|
||||
{ id: "A", title: "증설계획(m³/일)", colSpan:5, row:0},
|
||||
{ id: "planSwageQntSum", title: "현재", row:1},
|
||||
{ id: "planSwageQntSumDc1", title: "1단계", row:1},
|
||||
{ id: "planSwageQntSumDc2", title: "2단계", row:1},
|
||||
{ id: "planSwageQntSumDc3", title: "3단계", row:1},
|
||||
{ id: "planSwageQntSumDc4", title: "4단계", row:1},
|
||||
];
|
||||
|
||||
// 시설증설 계획 (리스트)
|
||||
const gridListFcltyImproveInfo:FcltyImproveInfoProps[] = [
|
||||
];
|
||||
|
||||
// 처리인구 계획 (헤더)
|
||||
const upHeadListProcessPopulation:TableUpperProps[] = [
|
||||
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계(인)", rowSpan:2, row:0},
|
||||
{ id: "A", title: "처리인구(인)", colSpan:5, row:0},
|
||||
{ id: "swtrmtPpltnCnt", title: "현재", row:1},
|
||||
{ id: "swtrmtPpltnCntDc1", title: "1단계", row:1},
|
||||
{ id: "swtrmtPpltnCntDc2", title: "2단계", row:1},
|
||||
{ id: "swtrmtPpltnCntDc3", title: "3단계", row:1},
|
||||
{ id: "swtrmtPpltnCntDc4", title: "4단계", row:1},
|
||||
];
|
||||
|
||||
// 처리인구 계획 (리스트)
|
||||
const gridListProcessPopulation:ProcessPopulationProps[] = [
|
||||
];
|
||||
|
||||
// 처리구역 계획 (헤더)
|
||||
const upHeadListProcessAreaPlan:TableUpperProps[] = [
|
||||
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계(km²)", rowSpan:2, row:0},
|
||||
{ id: "A", title: "처리면적(km²)", colSpan:6, row:0},
|
||||
{ id: "swtrmtZoneArea", title: "현재", row:1},
|
||||
{ id: "swtrmtZoneAreaDc1", title: "1단계", row:1},
|
||||
{ id: "swtrmtZoneAreaDc2", title: "2단계", row:1},
|
||||
{ id: "swtrmtZoneAreaDc3", title: "3단계", row:1},
|
||||
{ id: "swtrmtZoneAreaDc4", title: "4단계", row:1},
|
||||
{ id: "trtDstr", title: "처리구역", row:1}
|
||||
];
|
||||
|
||||
// 시설증설 계획 (리스트)
|
||||
const gridListProcessAreaPlan:ProcessAreaPlanProps[] = [
|
||||
];
|
||||
|
||||
/**====================================
|
||||
* Store - API
|
||||
=====================================*/
|
||||
// 시설 상세 정보 조회 API
|
||||
const fetchFacilityDetailInfo = async (swtrmtFcltCd: string) => {
|
||||
try {
|
||||
const tailUrl = '/1/5/A/0/0/0/SW';
|
||||
const res = await postFetch('fo', '/prcsFclt/ruseInfo'+tailUrl, [swtrmtFcltCd]);
|
||||
return { data:res.data, count:res.count };
|
||||
} catch (error) {
|
||||
console.error('시설정보 데이터를 가져오는데 실패했습니다:', error);
|
||||
return {data: [], count: 0};
|
||||
}
|
||||
};
|
||||
|
||||
// 시설정보 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
|
||||
const fetchProcessAreaList = async (pageNo : number, pageSize : number, ctpvNm : string | undefined, sggNm : string | undefined, targetYear : string | undefined ): Promise<{data:ProcessAreaProps[], count:number}> => {
|
||||
try {
|
||||
targetYear = targetYear ? targetYear : "2024";
|
||||
const baseUrl = 'https://apigateway.rsonesoft.com/dc-service/api/v1/nowDmgMtncGnsvy';
|
||||
const queryParams = new URLSearchParams();
|
||||
|
||||
if (ctpvNm && ctpvNm !== '전체') queryParams.append('ctpvNm', ctpvNm);
|
||||
if (sggNm && sggNm !== '전체') queryParams.append('sggNm', sggNm);
|
||||
if (targetYear) queryParams.append('targetYear',targetYear);
|
||||
|
||||
const queryString = queryParams.toString();
|
||||
const url = queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
||||
const res = await getFetchAreaList(url);
|
||||
|
||||
if(res && res.length > 0){
|
||||
const enrichedData = await Promise.all(
|
||||
res.map(async (item: ProcessAreaProps) => {
|
||||
upHeadList1.forEach((head:TableUpperProps) => {
|
||||
if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
|
||||
head.title = '현재\n(' + item.yr + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
|
||||
head.title = '1단계\n(' + item.yrDc1 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
|
||||
head.title = '2단계\n(' + item.yrDc2 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
|
||||
head.title = '3단계\n(' + item.yrDc3 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
|
||||
head.title = '4단계\n(' + item.yrDc4 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
|
||||
head.title = '기승인\n4단계(' + item.yrDt4 + '년)';
|
||||
}
|
||||
});
|
||||
const res = await fetchFacilityDetailInfo(item.swtrmtFcltCd);
|
||||
const detailInfo = res.data.filter((item:ProcessAreaProps) => item.ruse === true);
|
||||
return {
|
||||
...item,
|
||||
sido: detailInfo.length > 0 ? detailInfo[0].sido||'' : '',
|
||||
sigungo: detailInfo.length > 0 ? detailInfo[0].gugun||'' : '',
|
||||
location: detailInfo.length > 0 ? detailInfo[0].addr||'' : '',
|
||||
fctCpc: detailInfo.length > 0 ? detailInfo[0].fctCpc||'' : 0,
|
||||
trtDstr: detailInfo.length > 0 ? detailInfo[0].trtDstr||'' : '',
|
||||
};
|
||||
})
|
||||
);
|
||||
const startIndex = (pageNo - 1) * pageSize;
|
||||
const endIndex = startIndex + pageSize;
|
||||
const paginatedData = enrichedData.slice(startIndex, endIndex);
|
||||
return {data: paginatedData, count: enrichedData.length};
|
||||
}else{
|
||||
return {data: [], count: 0};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('시설계획정보를 가져오는데 실패했습니다:', error);
|
||||
return {data: [], count: 0};
|
||||
}
|
||||
};
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
=====================================*/
|
||||
export type ProcessAreaActions = {
|
||||
searchProcessAreaList : (pageNo: number, pageSize: number, ctpvNm?:string, sggNm?:string, targetYear?:string) => void;
|
||||
initModalData : (swtrmtFcltCd:string) => void;
|
||||
}
|
||||
|
||||
export type ProcessAreaType = {
|
||||
ProcessAreaSearch: {
|
||||
isInit: boolean;
|
||||
processFacilityLabelArray:string[];
|
||||
},
|
||||
|
||||
ProcessArea : {
|
||||
isInit: boolean;
|
||||
upHeadList1: TableUpperProps[];
|
||||
processAreaList: ProcessAreaProps[];
|
||||
processAreaCount: number;
|
||||
excelList: ExcelType[];
|
||||
},
|
||||
|
||||
ProcessAreaDetail : {
|
||||
isInit: boolean;
|
||||
upHeadListFcltyImproveInfo: TableUpperProps[];
|
||||
gridListFcltyImproveInfo: FcltyImproveInfoProps[]; // Changed from facilityAreaProps to ProcessAreaProps
|
||||
upHeadListProcessPopulation: TableUpperProps[];
|
||||
gridListProcessPopulation: ProcessPopulationProps[]; // Changed from facilityAreaProps to ProcessAreaProps
|
||||
upHeadListProcessAreaPlan: TableUpperProps[];
|
||||
gridListProcessAreaPlan: ProcessAreaPlanProps[]; // Changed from facilityAreaProps to ProcessAreaProps
|
||||
},
|
||||
}
|
||||
|
||||
export const processAreaInitState: ProcessAreaType = {
|
||||
ProcessAreaSearch: {
|
||||
isInit: false,
|
||||
processFacilityLabelArray: ProcessFacilityLabelArray,
|
||||
},
|
||||
|
||||
ProcessArea : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
processAreaList : processAreaList,
|
||||
processAreaCount : 0,
|
||||
excelList : []
|
||||
},
|
||||
|
||||
ProcessAreaDetail : {
|
||||
isInit : false,
|
||||
upHeadListFcltyImproveInfo : upHeadListFcltyImproveInfo,
|
||||
gridListFcltyImproveInfo : gridListFcltyImproveInfo,
|
||||
upHeadListProcessPopulation : upHeadListProcessPopulation,
|
||||
gridListProcessPopulation : gridListProcessPopulation,
|
||||
upHeadListProcessAreaPlan : upHeadListProcessAreaPlan,
|
||||
gridListProcessAreaPlan : gridListProcessAreaPlan,
|
||||
},
|
||||
}
|
||||
|
||||
// 상태 설정 함수 타입 정의
|
||||
type SetStateFunction = (state: ProcessAreaType | ((state: ProcessAreaType) => ProcessAreaType)) => void;
|
||||
|
||||
export type ProcessAreaStore = ProcessAreaType & ProcessAreaActions;
|
||||
|
||||
export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set: SetStateFunction) => {
|
||||
return {
|
||||
/**
|
||||
* 시설정보 리스트 데이터 호출
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
*/
|
||||
searchProcessAreaList: async ( pageNo:number, pageSize:number, ctpvNm?:string, sggNm?:string, targetYear?:string) => {
|
||||
const res = await fetchProcessAreaList(pageNo, pageSize, ctpvNm, sggNm, targetYear);
|
||||
res.data.forEach((item:ProcessAreaProps) => {
|
||||
DataForm({ type: 'float1', column: 'fctCpc', item:item as unknown as Record<string, unknown>});
|
||||
})
|
||||
const excelDownList: ExcelType[] = [];
|
||||
if(pageSize>5000){
|
||||
res.data.forEach(item => {
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : '';
|
||||
excelDownList.push({
|
||||
시설코드: item.swtrmtFcltCd,
|
||||
시설명: item.swtrmtFcltNm,
|
||||
주소: item.location,
|
||||
시설용량: item.fctCpc,
|
||||
증설계획기존: item.planSwageQntSumDt4,
|
||||
증설계획현재: item.planSwageQntSum,
|
||||
증설계획1단계: item.planSwageQntSumDc1,
|
||||
증설계획2단계: item.planSwageQntSumDc2,
|
||||
증설계획3단계: item.planSwageQntSumDc3,
|
||||
증설계획4단계: item.planSwageQntSumDc4,
|
||||
처리인구기존: item.swtrmtPpltnCntDt4,
|
||||
처리인구현재: item.swtrmtPpltnCnt,
|
||||
처리인구1단계: item.swtrmtPpltnCntDc1,
|
||||
처리인구2단계: item.swtrmtPpltnCntDc2,
|
||||
처리인구3단계: item.swtrmtPpltnCntDc3,
|
||||
처리인구4단계: item.swtrmtPpltnCntDc4,
|
||||
처리구역기존: item.swtrmtZoneAreaDt4,
|
||||
처리구역현재: item.swtrmtZoneArea,
|
||||
처리구역1단계: item.swtrmtZoneAreaDc1,
|
||||
처리구역2단계: item.swtrmtZoneAreaDc2,
|
||||
처리구역3단계: item.swtrmtZoneAreaDc3,
|
||||
처리구역4단계: item.swtrmtZoneAreaDc4,
|
||||
처리구역: item.trtDstr
|
||||
});
|
||||
});
|
||||
}else{
|
||||
res.data.forEach(item => {
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : '';
|
||||
})
|
||||
}
|
||||
set((state:ProcessAreaType) => ({
|
||||
...state,
|
||||
ProcessArea: pageSize<5000?{
|
||||
...state.ProcessArea,
|
||||
processAreaList: res.data,
|
||||
processAreaCount: res.count,
|
||||
}:{
|
||||
...state.ProcessArea,
|
||||
excelList: excelDownList,
|
||||
},
|
||||
}))
|
||||
},
|
||||
|
||||
initModalData: async (swtrmtFcltCd:string) => {
|
||||
set((state: ProcessAreaType) => {
|
||||
const rtnData = state.ProcessArea.processAreaList.find((item: ProcessAreaProps) => item.swtrmtFcltCd === swtrmtFcltCd);
|
||||
if (rtnData) {
|
||||
upHeadListFcltyImproveInfo.forEach((head:TableUpperProps) => {
|
||||
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
|
||||
head.title = '현재\n(' + rtnData.yr + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
|
||||
head.title = '1단계\n(' + rtnData.yrDc1 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
|
||||
head.title = '2단계\n(' + rtnData.yrDc2 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
|
||||
head.title = '3단계\n(' + rtnData.yrDc3 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
|
||||
head.title = '4단계\n(' + rtnData.yrDc4 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
|
||||
head.title = '기승인\n4단계(' + rtnData.yrDt4 + '년)';
|
||||
}
|
||||
});
|
||||
|
||||
upHeadListProcessAreaPlan.forEach((head:TableUpperProps) => {
|
||||
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
|
||||
head.title = '현재\n(' + rtnData.yr + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
|
||||
head.title = '1단계\n(' + rtnData.yrDc1 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
|
||||
head.title = '2단계\n(' + rtnData.yrDc2 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
|
||||
head.title = '3단계\n(' + rtnData.yrDc3 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
|
||||
head.title = '4단계\n(' + rtnData.yrDc4 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
|
||||
head.title = '기승인\n4단계(' + rtnData.yrDt4 + '년)';
|
||||
}
|
||||
});
|
||||
|
||||
upHeadListProcessPopulation.forEach((head:TableUpperProps) => {
|
||||
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
|
||||
head.title = '현재\n(' + rtnData.yr + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
|
||||
head.title = '1단계\n(' + rtnData.yrDc1 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
|
||||
head.title = '2단계\n(' + rtnData.yrDc2 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
|
||||
head.title = '3단계\n(' + rtnData.yrDc3 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
|
||||
head.title = '4단계\n(' + rtnData.yrDc4 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
|
||||
head.title = '기승인\n4단계(' + rtnData.yrDt4 + '년)';
|
||||
}
|
||||
});
|
||||
|
||||
// 시설증설 계획 데이터 생성
|
||||
const fcltyImproveInfo: FcltyImproveInfoProps = {
|
||||
planSwageQntSumDt4: rtnData.planSwageQntSumDt4,
|
||||
planSwageQntSum: rtnData.planSwageQntSum,
|
||||
planSwageQntSumDc1: rtnData.planSwageQntSumDc1,
|
||||
planSwageQntSumDc2: rtnData.planSwageQntSumDc2,
|
||||
planSwageQntSumDc3: rtnData.planSwageQntSumDc3,
|
||||
planSwageQntSumDc4: rtnData.planSwageQntSumDc4
|
||||
};
|
||||
|
||||
// 처리인구 계획 데이터 생성
|
||||
const processPopulation: ProcessPopulationProps = {
|
||||
swtrmtPpltnCntDt4: rtnData.swtrmtPpltnCntDt4,
|
||||
swtrmtPpltnCnt: rtnData.swtrmtPpltnCnt,
|
||||
swtrmtPpltnCntDc1: rtnData.swtrmtPpltnCntDc1,
|
||||
swtrmtPpltnCntDc2: rtnData.swtrmtPpltnCntDc2,
|
||||
swtrmtPpltnCntDc3: rtnData.swtrmtPpltnCntDc3,
|
||||
swtrmtPpltnCntDc4: rtnData.swtrmtPpltnCntDc4
|
||||
};
|
||||
|
||||
// 처리구역 계획 데이터 생성
|
||||
const processAreaPlan: ProcessAreaPlanProps = {
|
||||
swtrmtZoneAreaDt4: rtnData.swtrmtZoneAreaDt4,
|
||||
swtrmtZoneArea: rtnData.swtrmtZoneArea,
|
||||
swtrmtZoneAreaDc1: rtnData.swtrmtZoneAreaDc1,
|
||||
swtrmtZoneAreaDc2: rtnData.swtrmtZoneAreaDc2,
|
||||
swtrmtZoneAreaDc3: rtnData.swtrmtZoneAreaDc3,
|
||||
swtrmtZoneAreaDc4: rtnData.swtrmtZoneAreaDc4,
|
||||
trtDstr: rtnData.trtDstr
|
||||
};
|
||||
|
||||
return {
|
||||
...state,
|
||||
ProcessAreaDetail: {
|
||||
...state.ProcessAreaDetail,
|
||||
gridListFcltyImproveInfo: [fcltyImproveInfo],
|
||||
gridListProcessPopulation: [processPopulation],
|
||||
gridListProcessAreaPlan: [processAreaPlan]
|
||||
}
|
||||
};
|
||||
}
|
||||
return state;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,832 +0,0 @@
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
export type { TableUpperProps };
|
||||
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 처리시설 리스트
|
||||
export type facilityListProps = {
|
||||
bscFctCd : string,
|
||||
bscFctNm : string,
|
||||
bscFctClsNm : string,
|
||||
sido : string,
|
||||
gugun : string,
|
||||
daddr : string,
|
||||
fctCpc : number | string | '',
|
||||
plInflWqltBod : number | string | '',
|
||||
dsInflWqltBod : number | string | '',
|
||||
trtFrfNm : string,
|
||||
rnDt : string,
|
||||
cmplDt : string,
|
||||
trstOprEtpNm : string,
|
||||
rvbsn : string,
|
||||
mdmbsn : string,
|
||||
lgbsn : string,
|
||||
rgnNm : string,
|
||||
mnstr : string,
|
||||
efflWtrrgn : string,
|
||||
efflWqltStndrdNm : string
|
||||
}
|
||||
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설이름: string,
|
||||
주소: string,
|
||||
시설용량: number | '',
|
||||
계획유입수질: number | '',
|
||||
설계유입수질: number | '',
|
||||
공법: string,
|
||||
가동개시일: string,
|
||||
준공일: string,
|
||||
관리대행업자: string,
|
||||
}
|
||||
|
||||
// (2) 처리시설 팝업
|
||||
// 시설 기본정보
|
||||
export type BasicInfoProps = {
|
||||
bscFctNm : string,
|
||||
fctCpc : number | '',
|
||||
sido : string,
|
||||
gugun : string,
|
||||
startDay : string,
|
||||
addr : string,
|
||||
cmplDt : string,
|
||||
trtFrfNm : string,
|
||||
trstOprEtpNm : string,
|
||||
}
|
||||
|
||||
// 시설 계획정보
|
||||
export type PlanInfoProps = {
|
||||
plInflWqltBod? : string,
|
||||
plInflWqltToc? : string,
|
||||
plInflWqltCod? : string,
|
||||
plInflWqltSs? : string,
|
||||
plInflWqltTn? : string,
|
||||
plInflWqltTp? : string,
|
||||
dsInflWqltBod? : string,
|
||||
dsInflWqltToc? : string,
|
||||
dsInflWqltCod? : string,
|
||||
dsInflWqltSs? : string,
|
||||
dsInflWqltTn? : string,
|
||||
dsInflWqltTp? : string,
|
||||
sitArea? : string | number,
|
||||
trtDstrArea? : string | number,
|
||||
swrTrtPopl? : string | number
|
||||
}
|
||||
|
||||
// 시설 계획정보
|
||||
export type LegalWaterQltyProps = {
|
||||
totClfgrpcnt : number,
|
||||
bod : number,
|
||||
cod : number,
|
||||
ss : number,
|
||||
tn : number,
|
||||
tp : number
|
||||
}
|
||||
|
||||
// 시설 수역 및 구역정보
|
||||
export type fcltyAreaInfoProps = {
|
||||
rvbsn : string,
|
||||
efflWtrrgn : string,
|
||||
lgbsn : string,
|
||||
efflWqltStndrdNm : string,
|
||||
rgnNm : string,
|
||||
}
|
||||
|
||||
// 시설 이력관리
|
||||
export type fcltyHistInfoProps = {
|
||||
extnsSeqno : string,
|
||||
extnsNm : string,
|
||||
bzStrtYrMnth : string,
|
||||
bzEdYrMnth : string,
|
||||
eqpPrmsDt : string,
|
||||
cmplDt : string,
|
||||
trlrnCmplDt : string,
|
||||
rnDt : string,
|
||||
sitArea : number,
|
||||
trtDstrArea : number,
|
||||
swrTrtPopl : number
|
||||
}
|
||||
|
||||
// 시설 수질정보
|
||||
export type fcltyWaterQltyInfoProps = {
|
||||
extnsSeqno : string,
|
||||
plInflWqltBod : string,
|
||||
plInflWqltToc : string,
|
||||
plInflWqltCod : string,
|
||||
plInflWqltSs : string,
|
||||
plInflWqltTn : string,
|
||||
plInflWqltTp : string,
|
||||
dsInflWqltBod : string,
|
||||
dsInflWqltToc : string,
|
||||
dsInflWqltCod : string,
|
||||
dsInflWqltSs : string,
|
||||
dsInflWqltTn : string,
|
||||
dsInflWqltTp : string,
|
||||
plEfflWqltBod : string,
|
||||
plEfflWqltToc : string,
|
||||
plEfflWqltCod : string,
|
||||
plEfflWqltSs : string,
|
||||
plEfflWqltTn : string,
|
||||
plEfflWqltTp : string,
|
||||
bod : number,
|
||||
cod : number,
|
||||
ss : number,
|
||||
tn : number,
|
||||
tp : number,
|
||||
totClfgrpcnt : number,
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 검색단
|
||||
const ProcessFacilityLabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '시설상태', '시설구분', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드"},
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2 },
|
||||
{ id: "bscFctNm", title: "시설명"},
|
||||
{ id: "daddr", title: "주소"},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align: 'right'},
|
||||
{ id: "plInflWqltBod", title: "계획유입수질\n(mg/L)", align:"right"},
|
||||
{ id: "dsInflWqltBod", title: "설계유입수질\n(mg/L)", align:"right"},
|
||||
{ id: "trtFrfNm", title: '공법'},
|
||||
{ id: "rnDt", title: '가동개시일'},
|
||||
{ id: "cmplDt", title: '준공일' },
|
||||
{ id: "trstOprEtpNm", title: '관리대행업자'}
|
||||
];
|
||||
|
||||
// 처리시설 리스트 (유역)
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드"},
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3},
|
||||
{ id: "bscFctNm", title: "시설명"},
|
||||
{ id: "daddr", title: "주소"},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align: 'right'},
|
||||
{ id: "plInflWqltBod", title: "계획유입수질\n(mg/L)", align:'right'},
|
||||
{ id: "dsInflWqltBod", title: "설계유입수질\n(mg/L)", align:'right'},
|
||||
{ id: "trtFrfNm", title: '공법'},
|
||||
{ id: "rnDt", title: '가동개시일'},
|
||||
{ id: "cmplDt", title: '준공일' },
|
||||
{ id: "trstOprEtpNm", title: '관리대행업자'}
|
||||
];
|
||||
|
||||
// 처리시설 리스트 (환경청청)
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드"},
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3},
|
||||
{ id: "rgnNm", title: "환경청"},
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe2",upSequnce:2 },
|
||||
{ id: "bscFctNm", title: "시설명"},
|
||||
{ id: "daddr", title: "주소"},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align: 'right'},
|
||||
{ id: "plInflWqltBod", title: "계획유입수질\n(mg/L)", align:'right'},
|
||||
{ id: "dsInflWqltBod", title: "설계유입수질\n(mg/L)", align:'right'},
|
||||
{ id: "trtFrfNm", title: '공법'},
|
||||
{ id: "rnDt", title: '가동개시일'},
|
||||
{ id: "cmplDt", title: '준공일' },
|
||||
{ id: "trstOprEtpNm", title: '관리대행업자'}
|
||||
];
|
||||
|
||||
const processFacilityList:facilityListProps[] = [
|
||||
]
|
||||
|
||||
/**
|
||||
* 처리시설 상세팝업
|
||||
*/
|
||||
// 시설 기본정보 (헤더)
|
||||
const upHeadListBasicInfo:TableUpperProps[] = [
|
||||
{ id: "bscFctNm", title: "시설명" },
|
||||
{ id: "fctCpc", title: "시설용량n(m³/일)", align: 'right'},
|
||||
{ id: "sido", title: "시도"},
|
||||
{ id: "gugun", title: "시군구"},
|
||||
{ id: "rnDt", title: "가동개시일"},
|
||||
{ id: "daddr", title: "주소"},
|
||||
{ id: "cmplDt", title: "준공일"},
|
||||
{ id: "trtFrfNm", title: "공법"},
|
||||
{ id: "trstOprEtpNm", title: "관리대행업자"},
|
||||
];
|
||||
|
||||
// 시설 기본정보 (리스트)
|
||||
const gridListBasicInfo:BasicInfoProps[] = [
|
||||
{
|
||||
bscFctNm : "난지",
|
||||
fctCpc : 860000,
|
||||
sido : "서울특별시",
|
||||
gugun : "",
|
||||
startDay : "1987-06-30",
|
||||
addr : "경기도 고양시 덕양구 대덕로 426 (현천동)",
|
||||
cmplDt : "2013-04-30",
|
||||
trtFrfNm : "MLE, A2O",
|
||||
trstOprEtpNm : "자체",
|
||||
}
|
||||
];
|
||||
|
||||
// 시설 법적방류수질 (헤더)
|
||||
const upHeadListLegalWaterQlty:TableUpperProps[] = [
|
||||
{ id: "bod", title: "BOD(mg/L)", align: 'right'},
|
||||
{ id: "cod", title: "TOC(COD)(mg/L)", align: 'right'},
|
||||
{ id: "ss", title: "SS(mg/L)", align: 'right'},
|
||||
{ id: "tn", title: "T-N(mg/L)", align: 'right'},
|
||||
{ id: "tp", title: "T-P(mg/L) ", align: 'right'},
|
||||
{ id: "totClfgrpcnt", title: "대장균군(개/100ml)"},
|
||||
]
|
||||
|
||||
// 시설 법적방류수질 (리스트)
|
||||
let gridListLegalWaterQlty:LegalWaterQltyProps[] = [
|
||||
]
|
||||
|
||||
// 시설 계획정보 (헤더)
|
||||
const upHeadListPlanInfo:TableUpperProps[] = [
|
||||
{ id: "plInflWqltBod", title: "BOD", upName:"upChangeRe1", upSequnce:1, align: 'right' },
|
||||
{ id: "plInflWqltToc", title: "TOC", upName:"upChangeRe1", upSequnce:2, align: 'right' },
|
||||
{ id: "plInflWqltCod", title: "COD", upName:"upChangeRe1", upSequnce:3, align: 'right' },
|
||||
{ id: "plInflWqltSs", title: "SS", upName:"upChangeRe1", upSequnce:4, align: 'right' },
|
||||
{ id: "plInflWqltTn", title: "T-N", upName:"upChangeRe1", upSequnce:5, align: 'right' },
|
||||
{ id: "plInflWqltTp", title: "T-P", upName:"upChangeRe1", upSequnce:6, align: 'right' },
|
||||
{ id: "dsInflWqltBod", title: "BOD", upName:"upChangeRe2", upSequnce:1, align: 'right' },
|
||||
{ id: "dsInflWqltToc", title: "TOC", upName:"upChangeRe2", upSequnce:2, align: 'right' },
|
||||
{ id: "dsInflWqltCod", title: "COD", upName:"upChangeRe2", upSequnce:3, align: 'right' },
|
||||
{ id: "dsInflWqltSs", title: "SS", upName:"upChangeRe2", upSequnce:4, align: 'right' },
|
||||
{ id: "dsInflWqltTn", title: "T-N", upName:"upChangeRe2", upSequnce:5, align: 'right' },
|
||||
{ id: "dsInflWqltTp", title: "T-P", upName:"upChangeRe2", upSequnce:6, align: 'right' },
|
||||
{ id: "sitArea", title: "부지면적\n(m²)", align: 'right'},
|
||||
{ id: "trtDstrArea", title: "처리구역면적\n(ha)", align: 'right'},
|
||||
{ id: "swrTrtPopl", title: "하수처리인구\n(인)", align: 'right'},
|
||||
];
|
||||
|
||||
// 시설 계획정보 (리스트)
|
||||
const gridListPlanInfo:PlanInfoProps[] = [
|
||||
{
|
||||
plInflWqltBod : "179.0",
|
||||
plInflWqltToc : "90.0",
|
||||
plInflWqltCod : "0.0",
|
||||
plInflWqltSs : "132.0",
|
||||
plInflWqltTn : "38.000",
|
||||
plInflWqltTp : "4.300",
|
||||
dsInflWqltBod : "178.0",
|
||||
dsInflWqltToc : "91.0",
|
||||
dsInflWqltCod : "0.0",
|
||||
dsInflWqltSs : "131.0",
|
||||
dsInflWqltTn : "40.200",
|
||||
dsInflWqltTp : "4.500",
|
||||
sitArea : "928,574",
|
||||
trtDstrArea : "7,994.0",
|
||||
swrTrtPopl : "1,573,277",
|
||||
}
|
||||
];
|
||||
|
||||
// 시설 수역 및 구역정보 (헤더)
|
||||
const upHeadListFcltyAreaInfo:TableUpperProps[] = [
|
||||
{ id: "rvbsn", title: "하천명" },
|
||||
{ id: "efflWtrrgn", title: "방류수역"},
|
||||
{ id: "lgbsn", title: "단위유역"},
|
||||
{ id: "efflWqltStndrdNm", title: "지역구분"},
|
||||
{ id: "rgnNm", title: "관할 유역(지방) 환경청"}
|
||||
];
|
||||
|
||||
// 시설 수역 및 구역정보 (리스트)
|
||||
const gridListFcltyAreaInfo:fcltyAreaInfoProps[] = [
|
||||
{
|
||||
rvbsn : "한강",
|
||||
efflWtrrgn : "한강수계",
|
||||
lgbsn : "한강본류",
|
||||
efflWqltStndrdNm : "500톤 이상\n(Ⅲ지역)",
|
||||
rgnNm : "한강유역환경청"
|
||||
}
|
||||
];
|
||||
|
||||
// 시설 이력관리 (헤더)
|
||||
const upHeadListFcltyHistInfo:TableUpperProps[] = [
|
||||
{ id: "extnsSeqno", title: "차수", align: 'center' },
|
||||
{ id: "extnsNm", title: "구분"},
|
||||
{ id: "bzStrtYrMnth", title: "사업기간", upName:"upChangeRe1", upSequnce:1},
|
||||
{ id: "bzEdYrMnth", title: "사업기간", upName:"upChangeRe1", upSequnce:2},
|
||||
{ id: "eqpPrmsDt", title: "설치인가일"},
|
||||
{ id: "cmplDt", title: "준공일"},
|
||||
{ id: "trlrnCmplDt", title: "시운전완료일"},
|
||||
{ id: "rnDt", title: "가동개시일"},
|
||||
];
|
||||
|
||||
// 시설 이력관리 (리스트)
|
||||
const gridListFcltyHistInfo:fcltyHistInfoProps[] = [
|
||||
{
|
||||
extnsSeqno : "최초",
|
||||
extnsNm : "최초",
|
||||
bzStrtYrMnth : "1984.12.01",
|
||||
bzEdYrMnth : "1987.06.01",
|
||||
eqpPrmsDt : "1985.09.13",
|
||||
cmplDt : "1987.06.30",
|
||||
trlrnCmplDt : "1987.06.30",
|
||||
rnDt : "1987.06.30",
|
||||
sitArea : 0,
|
||||
trtDstrArea : 0,
|
||||
swrTrtPopl : 0,
|
||||
}
|
||||
];
|
||||
|
||||
// 시설 수질정보 (헤더)
|
||||
const upHeadListFcltyWaterQltyInfo:TableUpperProps[] = [
|
||||
{ id: "extnsSeqno", title: "차수" },
|
||||
{ id: "plInflWqltBod", title: "BOD", upName:"upChangeRe1", upSequnce:1, align: 'right' },
|
||||
{ id: "plInflWqltToc", title: "TOC", upName:"upChangeRe1", upSequnce:2, align: 'right' },
|
||||
{ id: "plInflWqltCod", title: "COD", upName:"upChangeRe1", upSequnce:3, align: 'right' },
|
||||
{ id: "plInflWqltSs", title: "SS", upName:"upChangeRe1", upSequnce:4, align: 'right' },
|
||||
{ id: "plInflWqltTn", title: "T-N", upName:"upChangeRe1", upSequnce:5, align: 'right' },
|
||||
{ id: "plInflWqltTp", title: "T-P", upName:"upChangeRe1", upSequnce:6, align: 'right' },
|
||||
{ id: "dsInflWqltBod", title: "BOD", upName:"upChangeRe2", upSequnce:1, align: 'right' },
|
||||
{ id: "dsInflWqltToc", title: "TOC", upName:"upChangeRe2", upSequnce:2, align: 'right' },
|
||||
{ id: "dsInflWqltCod", title: "COD", upName:"upChangeRe2", upSequnce:3, align: 'right' },
|
||||
{ id: "dsInflWqltSs", title: "SS", upName:"upChangeRe2", upSequnce:4, align: 'right' },
|
||||
{ id: "dsInflWqltTn", title: "T-N", upName:"upChangeRe2", upSequnce:5, align: 'right' },
|
||||
{ id: "dsInflWqltTp", title: "T-P", upName:"upChangeRe2", upSequnce:6, align: 'right' },
|
||||
{ id: "plEfflWqltBod", title: "BOD", upName:"upChangeRe3", upSequnce:1, align: 'right' },
|
||||
{ id: "plEfflWqltToc", title: "TOC", upName:"upChangeRe3", upSequnce:2, align: 'right' },
|
||||
{ id: "plEfflWqltCod", title: "COD", upName:"upChangeRe3", upSequnce:3, align: 'right' },
|
||||
{ id: "plEfflWqltSs", title: "SS", upName:"upChangeRe3", upSequnce:4, align: 'right' },
|
||||
{ id: "plEfflWqltTn", title: "T-N", upName:"upChangeRe3", upSequnce:5, align: 'right' },
|
||||
{ id: "plEfflWqltTp", title: "T-P", upName:"upChangeRe3", upSequnce:6, align: 'right' },
|
||||
];
|
||||
|
||||
// 시설 수질정보 (리스트)
|
||||
const gridListFcltyWaterQltyInfo:fcltyWaterQltyInfoProps[] = [
|
||||
{
|
||||
extnsSeqno: "최초",
|
||||
plInflWqltBod: "111.0",
|
||||
plInflWqltToc: "(0.0)",
|
||||
plInflWqltCod: "(0.0)",
|
||||
plInflWqltSs: "122.0",
|
||||
plInflWqltTn: "0.000",
|
||||
plInflWqltTp: "0.000",
|
||||
dsInflWqltBod: "111.0",
|
||||
dsInflWqltToc: "(0.0)",
|
||||
dsInflWqltCod: "(0.0)",
|
||||
dsInflWqltSs: "122.0",
|
||||
dsInflWqltTn: "0.000",
|
||||
dsInflWqltTp: "0.000",
|
||||
plEfflWqltBod: "20.0",
|
||||
plEfflWqltCod: "(0.0)",
|
||||
plEfflWqltToc: "(0.0)",
|
||||
plEfflWqltSs: "12.0",
|
||||
plEfflWqltTn: "0.000",
|
||||
plEfflWqltTp: "0.000",
|
||||
bod: 0,
|
||||
cod: 0,
|
||||
ss: 0,
|
||||
tn: 0,
|
||||
tp: 0,
|
||||
totClfgrpcnt: 0
|
||||
}
|
||||
];
|
||||
|
||||
/**====================================
|
||||
* Store - api (데이터 호출)
|
||||
====================================*/
|
||||
|
||||
// 시설정보 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
|
||||
const fetchFacilityList = async (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string ): Promise<{data:facilityListProps[], count:number}> => {
|
||||
try {
|
||||
const tailStr = partValue ? '/'+ (partValue==='G' ? 'A' : partValue) + '/' + nameCd + '/' + fcltCpct + '/' + oprtngSttsCd + '/' + facilityPartValue + (facilityName && facilityName !== '' ? '/' + facilityName : '') : '';
|
||||
const url = '/prcsFclt/info/history/'+pageNo+'/'+pageSize+tailStr;
|
||||
//const res = await getFetch('fo', '/prcsFclt/info/'+pageNo+'/'+pageSize+tailUrl);
|
||||
const res = await getFetch('fo', url);
|
||||
return res;
|
||||
} catch (error) {
|
||||
console.error('시설정보 데이터를 가져오는데 실패했습니다:', error);
|
||||
return {data: [], count: 0};
|
||||
}
|
||||
};
|
||||
|
||||
// 시설정보 리스트 데이터 호출 (대시보드용)
|
||||
const fetchFacilityListSearching = async (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string ): Promise<{data:facilityListProps[], count:number}> => {
|
||||
try {
|
||||
const tailStr = partValue ? '/'+ (partValue==='G' ? 'A' : partValue) + '/' + nameCd + '/' + fcltCpct + '/' + oprtngSttsCd + '/' + facilityPartValue + (facilityName && facilityName !== '' ? '/' + facilityName : '') : '';
|
||||
const url = '/prcsFclt/searching/'+pageNo+'/'+pageSize+tailStr;
|
||||
//const res = await getFetch('fo', '/prcsFclt/info/'+pageNo+'/'+pageSize+tailUrl);
|
||||
const res = await getFetch('fo', url);
|
||||
return res;
|
||||
} catch (error) {
|
||||
console.error('시설정보 데이터를 가져오는데 실패했습니다:', error);
|
||||
return {data: [], count: 0};
|
||||
}
|
||||
};
|
||||
|
||||
// 모달
|
||||
// 시설정보 이력정보 데이터 호출
|
||||
const fetchFacilityHistInfo = async (facilityCd:string ): Promise<fcltyHistInfoProps[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/prcsFclt/hist/'+facilityCd);
|
||||
const data = res.data;
|
||||
DataForm({ type: 'date', column: 'trlrnCmplDt', item: data as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'date', column: 'eqpPrmsDt', item: data as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'date', column: 'cmplDt', item: data as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'date', column: 'rnDt', item: data as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'number', column: 'sitArea', item: data as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'number', column: 'trtDstrArea', item: data as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'number', column: 'swrTrtPopl', item: data as unknown as Record<string, unknown> });
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('시설정보 이력정보 데이터를 가져오는데 실패했습니다:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
// 시설정보 수질정보 데이터 호출
|
||||
const fetchFacilityWaterQltyInfo = async (facilityCd:string ): Promise<fcltyWaterQltyInfoProps[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/prcsFclt/info/history/'+facilityCd);
|
||||
const data = res.data;
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('시설정보 수질정보 데이터를 가져오는데 실패했습니다:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type ProcessFacilityActions = {
|
||||
/**
|
||||
* 시설정보 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
* @param partValue : 구분값(행정명, 대유역, 환경청)
|
||||
* @param nameCd : 행정코드(시도명, 시군구명, 단위유역)
|
||||
* @param fcltCpct : 시설용량
|
||||
* @param oprtngSttsCd : 운영 상태 코드
|
||||
* @param facilityName : 시설명
|
||||
*/
|
||||
searchProcessFacility : (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string) => void;
|
||||
|
||||
/**
|
||||
* 시설정보 이력정보 데이터 호출
|
||||
* @param facilityCd : 시설코드
|
||||
*/
|
||||
searchProcessFacilityHist : (facilityCd:string) => void;
|
||||
|
||||
/**
|
||||
* 시설정보 수질정보 데이터 호출
|
||||
* @param facilityCd : 시설코드
|
||||
*/
|
||||
searchProcessFacilityWaterQlty : (facilityCd:string) => void;
|
||||
|
||||
/**
|
||||
* 시설정보 리스트 데이터 호출 (대시보드용)
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
*/
|
||||
searchProcessFacilitySearching : (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string) => void;
|
||||
}
|
||||
|
||||
export type ProcessFacilityType = {
|
||||
ProcessFacility: {
|
||||
isInit: boolean;
|
||||
processFacilityLabelArray:string[];
|
||||
},
|
||||
|
||||
ProcessFacilityList : {
|
||||
isInit: boolean;
|
||||
upHeadList1:TableUpperProps[];
|
||||
upHeadList2:TableUpperProps[];
|
||||
upHeadList3:TableUpperProps[];
|
||||
processFacilityList:facilityListProps[];
|
||||
processFacilityCount:number;
|
||||
excelList : ExcelType[];
|
||||
},
|
||||
|
||||
ProcessFacilityDetail : {
|
||||
isInit : boolean;
|
||||
upHeadListBasicInfo : TableUpperProps[];
|
||||
gridListBasicInfo : BasicInfoProps[];
|
||||
upHeadListPlanInfo : TableUpperProps[];
|
||||
gridListPlanInfo : PlanInfoProps[];
|
||||
upHeadListFcltyAreaInfo : TableUpperProps[];
|
||||
gridListFcltyAreaInfo : fcltyAreaInfoProps[];
|
||||
|
||||
upHeadListFcltyHistInfo : TableUpperProps[];
|
||||
gridListFcltyHistInfo : fcltyHistInfoProps[];
|
||||
upHeadListFcltyWaterQltyInfo : TableUpperProps[];
|
||||
gridListFcltyWaterQltyInfo : fcltyWaterQltyInfoProps[];
|
||||
|
||||
upHeadListLegalWaterQlty : TableUpperProps[];
|
||||
gridListLegalWaterQlty : LegalWaterQltyProps[];
|
||||
},
|
||||
}
|
||||
|
||||
export const processFacilityInitState:ProcessFacilityType = {
|
||||
ProcessFacility: {
|
||||
isInit: false,
|
||||
processFacilityLabelArray: ProcessFacilityLabelArray,
|
||||
},
|
||||
|
||||
ProcessFacilityList : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
upHeadList2 : upHeadList2,
|
||||
upHeadList3 : upHeadList3,
|
||||
processFacilityList : processFacilityList,
|
||||
processFacilityCount:1,
|
||||
excelList : []
|
||||
},
|
||||
|
||||
ProcessFacilityDetail : {
|
||||
isInit : false,
|
||||
upHeadListBasicInfo : upHeadListBasicInfo,
|
||||
gridListBasicInfo : gridListBasicInfo,
|
||||
upHeadListPlanInfo : upHeadListPlanInfo,
|
||||
gridListPlanInfo : gridListPlanInfo,
|
||||
upHeadListFcltyAreaInfo : upHeadListFcltyAreaInfo,
|
||||
gridListFcltyAreaInfo : gridListFcltyAreaInfo,
|
||||
|
||||
upHeadListFcltyHistInfo : upHeadListFcltyHistInfo,
|
||||
gridListFcltyHistInfo : gridListFcltyHistInfo,
|
||||
upHeadListFcltyWaterQltyInfo : upHeadListFcltyWaterQltyInfo,
|
||||
gridListFcltyWaterQltyInfo : gridListFcltyWaterQltyInfo,
|
||||
|
||||
upHeadListLegalWaterQlty : upHeadListLegalWaterQlty,
|
||||
gridListLegalWaterQlty : gridListLegalWaterQlty,
|
||||
}
|
||||
}
|
||||
|
||||
// 상태 설정 함수 타입 정의
|
||||
type SetStateFunction = (state: ProcessFacilityType | ((state: ProcessFacilityType) => ProcessFacilityType)) => void;
|
||||
|
||||
export type ProcessFacilityStore = ProcessFacilityType & ProcessFacilityActions;
|
||||
|
||||
export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActions=(set: SetStateFunction) => {
|
||||
return{
|
||||
// 메인페이지
|
||||
|
||||
/**
|
||||
* 시설정보 리스트 데이터 호출
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
*/
|
||||
searchProcessFacility: async (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string) => {
|
||||
const res = await fetchFacilityList(pageNo, pageSize, partValue, nameCd, fcltCpct, oprtngSttsCd, facilityPartValue, facilityName);
|
||||
res.data.forEach((item:facilityListProps) => {
|
||||
DataForm({ type: 'date', column: 'cmplDt', item:item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'date', column: 'rnDt', item:item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'fctCpc', item:item as unknown as Record<string, unknown>});
|
||||
})
|
||||
|
||||
res.data.forEach(item => {
|
||||
item.plInflWqltBod = item.plInflWqltBod ? Number(item.plInflWqltBod).toFixed(1) : '';
|
||||
item.dsInflWqltBod = item.dsInflWqltBod ? Number(item.dsInflWqltBod).toFixed(1) : '';
|
||||
})
|
||||
|
||||
const excelDownList: ExcelType[] = [];
|
||||
|
||||
if(pageSize>5000){
|
||||
res.data.forEach(item => {
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : '';
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시도: item.sido,
|
||||
시군구: item.gugun,
|
||||
시설이름: item.bscFctNm,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc ? Number(item.fctCpc) : '',
|
||||
계획유입수질: item.plInflWqltBod ? Number(item.plInflWqltBod) : '',
|
||||
설계유입수질: item.dsInflWqltBod ? Number(item.dsInflWqltBod) : '',
|
||||
공법: item.trtFrfNm,
|
||||
가동개시일: item.rnDt,
|
||||
준공일: item.cmplDt,
|
||||
관리대행업자: item.mnstr,
|
||||
})
|
||||
})
|
||||
}else{
|
||||
res.data.forEach(item => {
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : '';
|
||||
})
|
||||
}
|
||||
set((state:ProcessFacilityType) => ({
|
||||
...state,
|
||||
ProcessFacilityList: pageSize<5000?{
|
||||
...state.ProcessFacilityList,
|
||||
processFacilityList: res.data,
|
||||
processFacilityCount: res.count,
|
||||
}:{
|
||||
...state.ProcessFacilityList,
|
||||
excelList: excelDownList,
|
||||
},
|
||||
}))
|
||||
},
|
||||
|
||||
/**
|
||||
* 시설정보 리스트 데이터 호출
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
*/
|
||||
searchProcessFacilitySearching: async (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string) => {
|
||||
const res = await fetchFacilityListSearching(pageNo, pageSize, partValue, nameCd, fcltCpct, oprtngSttsCd, facilityPartValue, facilityName);
|
||||
/* res.data.forEach((item:facilityListProps) => {
|
||||
DataForm({ type: 'date', column: 'cmplDt', item:item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'date', column: 'rnDt', item:item as unknown as Record<string, unknown>});
|
||||
})
|
||||
|
||||
res.data.forEach(item => {
|
||||
item.plInflWqltBod = item.plInflWqltBod ? Number(item.plInflWqltBod).toFixed(1) : '';
|
||||
item.dsInflWqltBod = item.dsInflWqltBod ? Number(item.dsInflWqltBod).toFixed(1) : '';
|
||||
}) */
|
||||
console.log(res.data);
|
||||
set((state:ProcessFacilityType) => ({
|
||||
...state,
|
||||
ProcessFacilityList: {
|
||||
...state.ProcessFacilityList,
|
||||
processFacilityList: res.data,
|
||||
processFacilityCount: res.count,
|
||||
},
|
||||
}))
|
||||
},
|
||||
|
||||
|
||||
// 모달 이력정보
|
||||
/**
|
||||
* 시설정보 이력정보 데이터 호출
|
||||
* @param facilityCd : 시설코드
|
||||
*/
|
||||
searchProcessFacilityHist: async (facilityCd:string) => {
|
||||
const promiseSet = await Promise.all([fetchFacilityHistInfo(facilityCd)]);
|
||||
const [facilityHistInfo] = promiseSet;
|
||||
// extnsSeqno를 기준으로 오름차순 정렬
|
||||
const sortedHistInfo = [...facilityHistInfo].sort((a, b) => {
|
||||
// 숫자로 변환하여 비교
|
||||
const numA = Number(a.extnsSeqno);
|
||||
const numB = Number(b.extnsSeqno);
|
||||
if (!isNaN(numA) && !isNaN(numB)) {
|
||||
return numA - numB;
|
||||
}
|
||||
// 숫자 변환이 실패하면 문자열로 비교
|
||||
return String(a.extnsSeqno).localeCompare(String(b.extnsSeqno));
|
||||
});
|
||||
|
||||
sortedHistInfo.forEach(item => {
|
||||
if(item.extnsSeqno == '0'){
|
||||
item.extnsSeqno = '최초';
|
||||
item.extnsNm = '신설';
|
||||
}
|
||||
});
|
||||
|
||||
// yyyy-MM-dd로 변환
|
||||
sortedHistInfo.forEach(item => {
|
||||
item.eqpPrmsDt = item.eqpPrmsDt ? item.eqpPrmsDt.substring(0,4) + '-' + item.eqpPrmsDt.substring(4,6) + '-' + item.eqpPrmsDt.substring(6,8) : '';
|
||||
item.trlrnCmplDt = item.trlrnCmplDt ? item.trlrnCmplDt.substring(0,4) + '-' + item.trlrnCmplDt.substring(4,6) + '-' + item.trlrnCmplDt.substring(6,8) : '';
|
||||
item.cmplDt = item.cmplDt ? item.cmplDt.substring(0,4) + '-' + item.cmplDt.substring(4,6) + '-' + item.cmplDt.substring(6,8) : '';
|
||||
item.rnDt = item.rnDt ? item.rnDt.substring(0,4) + '-' + item.rnDt.substring(4,6) + '-' + item.rnDt.substring(6,8) : '';
|
||||
});
|
||||
|
||||
// 마지막 이력 데이터의 값을 gridListPlanInfo에 업데이트
|
||||
if (sortedHistInfo.length > 0) {
|
||||
const lastHistInfo = sortedHistInfo[sortedHistInfo.length - 1];
|
||||
set((state: ProcessFacilityType) => ({
|
||||
...state,
|
||||
ProcessFacilityDetail: {
|
||||
...state.ProcessFacilityDetail,
|
||||
gridListFcltyHistInfo: sortedHistInfo,
|
||||
gridListPlanInfo: [{
|
||||
...state.ProcessFacilityDetail.gridListPlanInfo[0],
|
||||
swrTrtPopl: lastHistInfo?.swrTrtPopl ?? state.ProcessFacilityDetail.gridListPlanInfo[0]?.swrTrtPopl,
|
||||
trtDstrArea: lastHistInfo?.trtDstrArea ?? state.ProcessFacilityDetail.gridListPlanInfo[0]?.trtDstrArea,
|
||||
sitArea: lastHistInfo?.sitArea ?? state.ProcessFacilityDetail.gridListPlanInfo[0]?.sitArea
|
||||
}]
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
set((state: ProcessFacilityType) => ({
|
||||
...state,
|
||||
ProcessFacilityDetail: {
|
||||
...state.ProcessFacilityDetail,
|
||||
gridListFcltyHistInfo: sortedHistInfo,
|
||||
gridListPlanInfo: [{
|
||||
...state.ProcessFacilityDetail.gridListPlanInfo[0],
|
||||
swrTrtPopl: '',
|
||||
trtDstrArea: '',
|
||||
sitArea: ''
|
||||
}]
|
||||
}
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
// 모달 수질정보
|
||||
/**
|
||||
* 시설정보 수질정보 데이터 호출
|
||||
* @param facilityCd : 시설코드
|
||||
*/
|
||||
searchProcessFacilityWaterQlty: async (facilityCd:string) => {
|
||||
const promiseSet = await Promise.all([fetchFacilityWaterQltyInfo(facilityCd)]);
|
||||
const [facilityWaterQltyInfo] = promiseSet;
|
||||
// extnsSeqno를 기준으로 오름차순 정렬
|
||||
const sortedWaterQltyInfo = [...facilityWaterQltyInfo].sort((a, b) => {
|
||||
// 숫자로 변환하여 비교
|
||||
const numA = Number(a.extnsSeqno);
|
||||
const numB = Number(b.extnsSeqno);
|
||||
if (!isNaN(numA) && !isNaN(numB)) {
|
||||
return numA - numB;
|
||||
}
|
||||
// 숫자 변환이 실패하면 문자열로 비교
|
||||
return String(a.extnsSeqno).localeCompare(String(b.extnsSeqno));
|
||||
});
|
||||
|
||||
sortedWaterQltyInfo.forEach(item => {
|
||||
if(item.extnsSeqno == '0'){
|
||||
item.extnsSeqno = '최초';
|
||||
}
|
||||
});
|
||||
|
||||
// 법적수질정보 초기화 및 push
|
||||
gridListLegalWaterQlty = [];
|
||||
|
||||
gridListLegalWaterQlty.push({
|
||||
bod: facilityWaterQltyInfo[0]?.bod ?? 0,
|
||||
cod: Number(facilityWaterQltyInfo[0]?.cod ?? 0),
|
||||
ss: Number(facilityWaterQltyInfo[0]?.ss ?? 0),
|
||||
tn: Number(facilityWaterQltyInfo[0]?.tn ?? 0),
|
||||
tp: Number(facilityWaterQltyInfo[0]?.tp ?? 0),
|
||||
totClfgrpcnt : Number(facilityWaterQltyInfo[0]?.totClfgrpcnt ?? 0),
|
||||
});
|
||||
|
||||
// 마지막 수질 데이터의 값을 gridListPlanInfo에 업데이트
|
||||
if (sortedWaterQltyInfo.length > 0) {
|
||||
const lastWaterQltyInfo = sortedWaterQltyInfo[sortedWaterQltyInfo.length - 1];
|
||||
set((state: ProcessFacilityType) => ({
|
||||
...state,
|
||||
ProcessFacilityDetail: {
|
||||
...state.ProcessFacilityDetail,
|
||||
gridListFcltyWaterQltyInfo: sortedWaterQltyInfo,
|
||||
gridListLegalWaterQlty: gridListLegalWaterQlty,
|
||||
gridListPlanInfo: [{
|
||||
...state.ProcessFacilityDetail.gridListPlanInfo[0],
|
||||
dsInflWqltBod: lastWaterQltyInfo?.dsInflWqltBod === 'NULL' || lastWaterQltyInfo?.dsInflWqltBod === undefined ? '' : lastWaterQltyInfo.dsInflWqltBod,
|
||||
dsInflWqltToc: lastWaterQltyInfo?.dsInflWqltToc === 'NULL' || lastWaterQltyInfo?.dsInflWqltToc === undefined ? '' : lastWaterQltyInfo.dsInflWqltToc,
|
||||
dsInflWqltCod: lastWaterQltyInfo?.dsInflWqltCod === 'NULL' || lastWaterQltyInfo?.dsInflWqltCod === undefined ? '' : lastWaterQltyInfo.dsInflWqltCod,
|
||||
dsInflWqltSs: lastWaterQltyInfo?.dsInflWqltSs === 'NULL' || lastWaterQltyInfo?.dsInflWqltSs === undefined ? '' : lastWaterQltyInfo.dsInflWqltSs,
|
||||
dsInflWqltTn: lastWaterQltyInfo?.dsInflWqltTn === 'NULL' || lastWaterQltyInfo?.dsInflWqltTn === undefined ? '' : lastWaterQltyInfo.dsInflWqltTn,
|
||||
dsInflWqltTp: lastWaterQltyInfo?.dsInflWqltTp === 'NULL' || lastWaterQltyInfo?.dsInflWqltTp === undefined ? '' : lastWaterQltyInfo.dsInflWqltTp,
|
||||
plInflWqltBod: lastWaterQltyInfo?.plInflWqltBod === 'NULL' || lastWaterQltyInfo?.plInflWqltBod === undefined ? '' : lastWaterQltyInfo.plInflWqltBod,
|
||||
plInflWqltToc: lastWaterQltyInfo?.plInflWqltToc === 'NULL' || lastWaterQltyInfo?.plInflWqltToc === undefined ? '' : lastWaterQltyInfo.plInflWqltToc,
|
||||
plInflWqltCod: lastWaterQltyInfo?.plInflWqltCod === 'NULL' || lastWaterQltyInfo?.plInflWqltCod === undefined ? '' : lastWaterQltyInfo.plInflWqltCod,
|
||||
plInflWqltSs: lastWaterQltyInfo?.plInflWqltSs === 'NULL' || lastWaterQltyInfo?.plInflWqltSs === undefined ? '' : lastWaterQltyInfo.plInflWqltSs,
|
||||
plInflWqltTn: lastWaterQltyInfo?.plInflWqltTn === 'NULL' || lastWaterQltyInfo?.plInflWqltTn === undefined ? '' : lastWaterQltyInfo.plInflWqltTn,
|
||||
plInflWqltTp: lastWaterQltyInfo?.plInflWqltTp === 'NULL' || lastWaterQltyInfo?.plInflWqltTp === undefined ? '' : lastWaterQltyInfo.plInflWqltTp
|
||||
}]
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
set((state: ProcessFacilityType) => ({
|
||||
...state,
|
||||
ProcessFacilityDetail: {
|
||||
...state.ProcessFacilityDetail,
|
||||
gridListFcltyWaterQltyInfo: sortedWaterQltyInfo,
|
||||
gridListLegalWaterQlty: gridListLegalWaterQlty,
|
||||
gridListPlanInfo: [{
|
||||
...state.ProcessFacilityDetail.gridListPlanInfo[0],
|
||||
dsInflWqltBod: '',
|
||||
dsInflWqltToc: '',
|
||||
dsInflWqltCod: '',
|
||||
dsInflWqltSs: '',
|
||||
dsInflWqltTn: '',
|
||||
dsInflWqltTp: '',
|
||||
plEfflWqltBod: '',
|
||||
plEfflWqltToc: '',
|
||||
plEfflWqltCod: '',
|
||||
plEfflWqltSs: '',
|
||||
plEfflWqltTn: '',
|
||||
plEfflWqltTp: ''
|
||||
}]
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
export type TableUpperProps = {
|
||||
id: string;
|
||||
title: string;
|
||||
upName?: string;
|
||||
upSequnce?: number;
|
||||
}
|
||||
type PublicReuseFacility = {
|
||||
sido: string,
|
||||
sigungo: string,
|
||||
facilityName: string,
|
||||
location: string,
|
||||
locationgubun: string,
|
||||
facilityCapacity: string,
|
||||
yn?: string,
|
||||
authoDay?: string,
|
||||
area?: string,
|
||||
reuse?: string,
|
||||
register?: string
|
||||
}
|
||||
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 publicReuseFacilityUper:PublicReuseFacility[] = [
|
||||
{
|
||||
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"
|
||||
},
|
||||
]
|
||||
|
||||
export type tableState = {
|
||||
isInit: boolean;
|
||||
upHeadList: TableUpperProps[];
|
||||
publicReuseFacilityUper: PublicReuseFacility[];
|
||||
}
|
||||
type tableActions = {
|
||||
decrementList: () => void
|
||||
}
|
||||
|
||||
export type tableType = tableState & tableActions;
|
||||
|
||||
export const tableStateExport:tableState= {
|
||||
isInit:false,
|
||||
upHeadList: upHeadList,
|
||||
publicReuseFacilityUper: publicReuseFacilityUper,
|
||||
}
|
||||
|
||||
// 상태 설정 함수 타입 정의
|
||||
type SetStateFunction = (state: tableState | ((state: tableState) => tableState)) => void;
|
||||
|
||||
export const tableActionsExport:(set:SetStateFunction)=>tableActions=(set: SetStateFunction) => {
|
||||
|
||||
return {
|
||||
decrementList:()=>set(
|
||||
(state:tableState) => {
|
||||
return {
|
||||
...state,
|
||||
publicReuseFacilityUper:
|
||||
state.publicReuseFacilityUper.slice(0, state.publicReuseFacilityUper.length - 1)
|
||||
}}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { getFetch } from "@/app/components/api";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 시설별 강수현황
|
||||
export type RdiProps = {
|
||||
bscFctCd : string,
|
||||
sido : string,
|
||||
sigungo : string,
|
||||
bscFctNm : string,
|
||||
lclgvrnmntNm : string,
|
||||
daddr : string,
|
||||
fctCpc : number,
|
||||
summerMinBodValue : number,
|
||||
inflAmnt : number,
|
||||
winterAvgBodLowRainfall : number,
|
||||
rdiiValue : number,
|
||||
infoRnDay : number,
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
}
|
||||
|
||||
export interface RdiInterface {
|
||||
bscFctCd : string,
|
||||
sido : string,
|
||||
sigungo : string,
|
||||
bscFctNm : string,
|
||||
lclgvrnmntNm : string,
|
||||
daddr : string,
|
||||
fctCpc : number,
|
||||
summerMinBodValue : number,
|
||||
inflAmnt : number,
|
||||
winterAvgBodLowRainfall : number,
|
||||
rdiiValue : number,
|
||||
infoRnDay : number,
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
}
|
||||
|
||||
// 모달
|
||||
export interface RdiInputModalProps {
|
||||
msrDt : string,
|
||||
realSewageInput : number | '',
|
||||
sewageOccur : number | '',
|
||||
underWaterInput : number | '',
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 검색단
|
||||
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설명: string,
|
||||
주소: string,
|
||||
시설용량: number,
|
||||
하절기강우일최저유입BOD: number | '',
|
||||
하절기최저유입BOD유입유량: number | '',
|
||||
동절기청천시유입BOD: number | '',
|
||||
RDII추정 : number | '',
|
||||
RDII추정시일강수량 : number | '',
|
||||
}
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "sigungo", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 },
|
||||
{ id: "summerMinBodValue", title: "3mm 이상 강우일 중 최저 유입BOD\n(mg/L)", align:"right", row:1 },
|
||||
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량\n(m³/일)", row:1 },
|
||||
{ id: "C", title: "동절기 운영현황(1~2월)", row:0 },
|
||||
{ id: "winterAvgBodLowRainfall", title: "청천시 유입BOD\n(mg/L)", row:1 },
|
||||
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2 },
|
||||
{ id: "infoRnDay", title: "RDII추정시일강수량\n(mm)", row:0, rowSpan:2 },
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 },
|
||||
{ id: "summerMinBodValue", title: "하절기강우일최저유입BOD", align:"right", row:1 },
|
||||
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량", row:1 },
|
||||
{ id: "D", title: "동절기 운영현황(1~2월)", row:0 },
|
||||
{ id: "winterAvgBodLowRainfall", title: "동절기청천시유입BOD", row:1 },
|
||||
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2 },
|
||||
{ id: "infoRnDay", title: "RDII추정시일강수량", row:0, rowSpan:2 },
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1 },
|
||||
{ id: "sigungo", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "C", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 },
|
||||
{ id: "summerMinBodValue", title: "하절기강우일최저유입BOD", align:"right", row:1 },
|
||||
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량", row:1 },
|
||||
{ id: "D", title: "동절기 운영현황(1~2월)", row:0 },
|
||||
{ id: "winterAvgBodLowRainfall", title: "동절기청천시유입BOD", row:1 },
|
||||
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2 },
|
||||
{ id: "infoRnDay", title: "RDII추정시일강수량", row:0, rowSpan:2 },
|
||||
];
|
||||
|
||||
const rdiList:RdiProps[] = [
|
||||
]
|
||||
|
||||
/**====================================
|
||||
* Store - API
|
||||
====================================*/
|
||||
|
||||
const fetchRdiList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
try{
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/rdii/list/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
console.log(url);
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count }
|
||||
}catch(error){
|
||||
console.log(error);
|
||||
return { data: rdiList, count: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type RdiActions = {
|
||||
searchRdiList: (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
|
||||
}
|
||||
|
||||
export type RdiType = {
|
||||
RdiSearch: {
|
||||
isInit: boolean;
|
||||
labelArray:string[];
|
||||
},
|
||||
|
||||
Rdi : {
|
||||
isInit: boolean;
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
rdiList: RdiProps[]; // Changed from facilityAreaProps to ProcessAreaProps
|
||||
rdiCount: number;
|
||||
excelList: ExcelType[];
|
||||
},
|
||||
}
|
||||
|
||||
export const rdiInitState: RdiType = {
|
||||
RdiSearch: {
|
||||
isInit: false,
|
||||
labelArray: LabelArray,
|
||||
},
|
||||
|
||||
Rdi : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
upHeadList2 : upHeadList2,
|
||||
upHeadList3 : upHeadList3,
|
||||
rdiList : rdiList,
|
||||
rdiCount : 2,
|
||||
excelList : []
|
||||
}
|
||||
}
|
||||
|
||||
const dataFormSetting=(item : RdiProps)=> {
|
||||
DataForm({ type: 'float1', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'summerMinBodValue', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'winterAvgBodLowRainfall', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float2', column: 'rdiiValue', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float2', column: 'infoRnDay', item: item as unknown as Record<string, unknown>});
|
||||
}
|
||||
|
||||
// Add type definitions for state setter function
|
||||
type SetStateFunction = (state: RdiType | ((state: RdiType) => RdiType)) => void;
|
||||
|
||||
export type RdiStore = RdiType & RdiActions;
|
||||
|
||||
export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunction) => {
|
||||
console.log("tableActionsExport");
|
||||
return {
|
||||
searchRdiList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const res = await fetchRdiList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const data = res.data;
|
||||
const excelDownList: ExcelType[] = [];
|
||||
|
||||
const rtnData = data.map((item: RdiProps) => {
|
||||
return {
|
||||
...item,
|
||||
sido: item.lclgvrnmntNm.split(' ')[0]?.toString() || '',
|
||||
sigungo: item.lclgvrnmntNm.split(' ')[1]?.toString() || '',
|
||||
inflAmnt: item.inflAmnt?item.inflAmnt.toFixed(1) : ''
|
||||
}
|
||||
})
|
||||
|
||||
rtnData.forEach((item: RdiProps) => {
|
||||
dataFormSetting(item)
|
||||
})
|
||||
|
||||
if(pageSize>5000){
|
||||
rtnData.forEach((item: RdiProps) => {
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시설명: item.bscFctNm,
|
||||
시도: item.sido,
|
||||
시군구: item.sigungo,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc,
|
||||
하절기강우일최저유입BOD: item.summerMinBodValue,
|
||||
하절기최저유입BOD유입유량: item.inflAmnt,
|
||||
동절기청천시유입BOD: item.winterAvgBodLowRainfall,
|
||||
RDII추정 : item.rdiiValue,
|
||||
RDII추정시일강수량 : item.infoRnDay,
|
||||
});
|
||||
});
|
||||
}
|
||||
set((state: RdiType) => ({
|
||||
...state,
|
||||
Rdi: pageSize<5000?{
|
||||
...state.Rdi,
|
||||
rdiList: rtnData,
|
||||
rdiCount: res.count,
|
||||
}:{
|
||||
...state.Rdi,
|
||||
excelList: excelDownList,
|
||||
}
|
||||
}))
|
||||
},
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user