Compare commits

..
Author SHA1 Message Date
Your Name fa8db521d5 Merge branch 'iipbs/common/main' into iipbs/fo/dev 2025-07-25 14:04:36 +09:00
Your Name 59bccfe1d6 테이블 및 굵은영역 뒷쪽에 글자보이는 문제해결 2025-07-25 14:03:52 +09:00
mind-one005 84ff24c5b5 LineBarChart2 추가 2025-07-25 10:52:47 +09:00
mind-one005 e1b48ab7c8 Merge branch 'iipbs/common/main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/common/main 2025-07-25 10:44:19 +09:00
mind-one005 4c3be448f0 LineBarChar2 추가 2025-07-25 10:42:36 +09:00
jyha00 8ede32f4c4 수요처폼 글씨 크기 변경 2025-07-25 10:41:41 +09:00
Your Name 8624b36e89 Merge branch 'iipbs/common/main' into iipbs/fo/dev 2025-07-25 10:14:39 +09:00
Your Name 314e6ed9ad 조치진행중
- 강우량 숨김
- 수질조회 2023년으로 세팅
2025-07-25 09:57:47 +09:00
Your Name 99ffa1d6d4 대시보드 2021년 부산 수영으로 default 세팅 2025-07-25 09:38:50 +09:00
mind-one002 d23c9ca4b1 2023년도 기준으로 재 수정. 2025-07-25 04:53:53 +09:00
mind-one002 cc67d707d9 default 값이 2023으로 우선 고정 처리. 2025-07-25 04:49:18 +09:00
mind-one002 583559ec60 오수발생량에 기준년도 2023으로 수정. 2025-07-25 04:35:24 +09:00
mind-one002 e7195f7db0 오수발생량 나오도록 수정. 2025-07-25 04:26:17 +09:00
mind-one002 04bb3657bb idx 불필요로 삭제. 2025-07-25 04:16:27 +09:00
mind-one002 f1563aa1fc 하수사용량 수치 오류 부분 수정. 2025-07-25 04:03:03 +09:00
swcho 2862fdc9fd fix: Gis.js fetch 로직 에러 수정 2025-07-25 00:50:03 +09:00
swcho a446739432 feat:
- gis.select.js 피처 다중 셀렉트 기능 추가
- Gis.js 상류관로 조회 메서드 추가
- GisLonLat 주석 처리(위경도 표시X)
2025-07-25 00:23:02 +09:00
truthwing ec7655a71d Merge commit 'c8d2c4e17ed3b3f42ac32860f8851e5f1e472387' into iipbs/fo/dev 2025-07-24 23:38:48 +09:00
jsyang c8d2c4e17e 조치 진행 중, pnpm build any제외 작업진행 2025-07-24 10:17:58 -04:00
mind-one005 ea125605d1 Merge branch 'iipbs/common/main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/common/main 2025-07-24 22:01:01 +09:00
mind-one005 8353800dac feat: LineBarChar.tsx Null 체크 추가 2025-07-24 22:00:58 +09:00
Your Name cd08b5dad8 조치 진행중 2025-07-24 21:58:50 +09:00
Your Name 5a43b33a1d 강우량 및 단위 수정 2025-07-24 15:08:07 +09:00
114 changed files with 2384 additions and 15062 deletions
+21 -33
View File
@@ -6,8 +6,8 @@ import { keepPreviousData, useQuery } from "@tanstack/react-query";
import { getCoreRowModel, type PaginationState } from "@tanstack/react-table";
import {
Button,
DateRangePicker,
Input,
InputDatePicker,
Label,
Select,
SelectContent,
@@ -21,7 +21,7 @@ import { ENDPOINT } from "@/shared/config";
import { columns } from "@/pages/apilog/model/table-columns";
type DateRange = {
from?: Date | undefined;
from: Date | undefined;
to?: Date | undefined;
};
@@ -35,7 +35,6 @@ function ApiLogPage() {
pageIndex: 0,
pageSize: 10,
});
const [presetDateRange, setPresetDateRange] = useState("");
const [dateRange, setDateRange] = useState<DateRange>(defaultDateRange);
const [userId, setUserId] = useState("");
const [apiHttpPmhd, setApiHttpPmhd] = useState("");
@@ -85,10 +84,8 @@ function ApiLogPage() {
...searchParams,
userId,
apiHttpPmhd,
dmndDtStart: dateRange.from
? dayjs(dateRange.from).format("YYYY-MM-DD")
: "",
dmndDtEnd: dateRange.to ? dayjs(dateRange.to).format("YYYY-MM-DD") : "",
dmndDtStart: dayjs(dateRange.from).format("YYYY-MM-DD"),
dmndDtEnd: dayjs(dateRange.to).format("YYYY-MM-DD"),
});
};
@@ -129,7 +126,6 @@ function ApiLogPage() {
default:
presetDateRange = undefined;
}
setPresetDateRange(value);
setDateRange(presetDateRange || defaultDateRange);
};
@@ -138,31 +134,23 @@ function ApiLogPage() {
<div className="card card-border">
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
<Label className="mr-2">조회기간</Label>
<Select value={presetDateRange} onValueChange={handlePresetDateRange}>
<SelectTrigger className="w-[12rem]">
<SelectValue placeholder="기간 선택" className="w-[24rem]" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1W">일주일</SelectItem>
<SelectItem value="1M">1개월</SelectItem>
<SelectItem value="3M">3개월</SelectItem>
</SelectContent>
</Select>
<InputDatePicker
value={dateRange.from}
onChange={(date) => {
setDateRange({ ...dateRange, from: date });
setPresetDateRange("");
}}
/>
~
<InputDatePicker
value={dateRange.to}
onChange={(date) => {
setDateRange({ ...dateRange, to: date });
setPresetDateRange("");
}}
/>
<DateRangePicker
value={dateRange}
onValueChange={(value) => setDateRange(value || defaultDateRange)}
>
<div className="card card-border flex items-center gap-2">
<Select onValueChange={handlePresetDateRange}>
<SelectTrigger>
<SelectValue placeholder="기간 선택" className="w-[24rem]" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1W">일주일</SelectItem>
<SelectItem value="1M">1개월</SelectItem>
<SelectItem value="3M">3개월</SelectItem>
</SelectContent>
</Select>
</div>
</DateRangePicker>
<Label className="ml-4 mr-2 text-label">사용자ID</Label>
<Input
value={userId}
@@ -1,14 +0,0 @@
import { client } from "@/shared/api";
import { ENDPOINT } from "@/shared/config";
import type { Dashboard, DashboardService } from "../model/dashboard-interface";
export class DashboardApiService implements DashboardService {
public async getDashboard(): Promise<Dashboard> {
const response = await client.get<Dashboard>(
ENDPOINT.CMS_SERVICE.DASHBOARD,
);
return response.data;
}
}
export const DashboardApi = new DashboardApiService();
-49
View File
@@ -1,49 +0,0 @@
import type { ChartData, ChartDataset } from "chart.js";
import { getCssVariableValue } from "@common/components";
import type {
MenuStatisticsContent,
SiteStatisticsContent,
} from "../model/dashboard-interface";
export function processSiteAccessData(
siteAccessList: SiteStatisticsContent[],
): ChartData<"line">["datasets"] {
const siteGroups: Record<string, ChartDataset> = siteAccessList.reduce(
(acc, item) => {
if (!acc[item.siteNm]) {
acc[item.siteNm] = {
label: item.siteNm,
data: Array(24).fill(0), // 24시간 데이터 초기화
borderColor: getCssVariableValue(
`--chart-${Math.floor(Math.random() * 5) + 1}`,
),
};
}
// 시간대별 접속 카운트 누적
const hourIndex = parseInt(item.accessHour, 10);
if (!isNaN(hourIndex) && hourIndex >= 0 && hourIndex < 24) {
acc[item.siteNm]!.data[hourIndex] = item.accessCnt;
}
return acc;
},
{} as Record<string, ChartDataset>,
);
return Object.values(siteGroups) as ChartData<"line">["datasets"];
}
export function processMenuAccessData(
menuAccessList: MenuStatisticsContent[],
): ChartData<"bar">["datasets"] {
const data = menuAccessList.map((item) => item.accessCnt);
return [
{
label: "메뉴별 접속 횟수",
data,
backgroundColor: "rgb(32, 148, 250)",
},
] as ChartData<"bar">["datasets"];
}
@@ -1,172 +0,0 @@
import { type ChartData, type ChartOptions } from "chart.js";
const commonData = {
labels: ["1", "2", "3", "4", "5", "6", "7"],
datasets: [
{
fill: true,
pointRadius: 0,
tension: 0.5,
},
],
};
const commonOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false,
},
},
scales: {
x: {
display: false,
},
y: {
display: false,
},
},
};
export const chartData: Record<
string,
{ data: ChartData<"line" | "bar">; options: ChartOptions<"line" | "bar"> }
> = {
memberChartData: {
data: {
...commonData,
datasets: [
{
...commonData.datasets[0],
data: [8, 10, 7, 12, 9, 13, 12],
borderColor: "rgba(255, 255, 255, 0.6)",
backgroundColor: "rgba(255, 255, 255, 0.1)",
},
],
},
options: {
...commonOptions,
scales: {
...commonOptions.scales,
y: {
...commonOptions.scales.y,
min: 5,
max: 15,
},
},
},
},
postChartData: {
data: {
...commonData,
datasets: [
{
...commonData.datasets[0],
data: [5200, 5350, 5450, 5520, 5600, 5650, 5678],
borderColor: "rgba(86, 138, 255, 1)",
backgroundColor: "rgba(86, 138, 255, 0.1)",
},
],
},
options: {
...commonOptions,
},
},
visitorChartData: {
data: {
...commonData,
datasets: [
{
...commonData.datasets[0],
data: [1800, 2100, 1950, 2300, 2150, 2250, 2345],
borderColor: "rgba(149, 131, 252)",
backgroundColor: "rgba(149, 131, 252, 0.1)",
},
],
},
options: {
...commonOptions,
},
},
apiChartData: {
data: {
...commonData,
datasets: [
{
...commonData.datasets[0],
data: [41000, 42500, 43200, 44100, 44800, 45200, 45678],
borderColor: "rgba(220, 103, 206)",
backgroundColor: "rgba(220, 103, 206, 0.1)",
},
],
},
options: {
...commonOptions,
},
},
siteAccessChartData: {
data: {
labels: Array.from({ length: 24 }, (_, i) =>
i.toString().padStart(2, "0"),
),
datasets: [],
},
options: {
...commonOptions,
plugins: {
legend: {
position: "top",
},
tooltip: {
mode: "index",
intersect: false,
},
},
scales: {
x: {
title: {
text: "시간대",
},
},
y: {
title: {
text: "접속자 수",
},
beginAtZero: true,
},
},
},
},
menuAccessChartData: {
data: {
labels: [],
datasets: [],
},
options: {
...commonOptions,
plugins: {
legend: {
position: "top",
},
tooltip: {
mode: "index",
intersect: false,
},
},
scales: {
x: {
title: {
text: "메뉴명",
},
},
y: {
title: {
text: "접속 횟수",
},
beginAtZero: true,
},
},
},
},
};
@@ -1,32 +0,0 @@
export interface SiteStatisticsContent {
siteId: string;
siteNm: string;
accessHour: string;
accessCnt: number;
}
export interface MenuStatisticsContent {
menuCd: number;
menuNm: string;
accessCnt: number;
}
export interface Dashboard {
memberTotCnt: number;
memberTodayCnt: number;
pstTotCnt: number;
pstTodayCnt: number;
accessTodayCnt: number;
accessBefDayPer: number;
apiTodayCnt: number;
waitMemberCnt: number;
waitCntnCnt: number;
notiList: [];
schdlList: [];
siteAccessList: SiteStatisticsContent[];
menuAccessList: MenuStatisticsContent[];
}
export interface DashboardService {
getDashboard(): Promise<Dashboard>;
}
@@ -1,74 +0,0 @@
import dayjs from "dayjs";
import type { ColumnDef } from "@tanstack/react-table";
import { Badge } from "@common/components";
import type { RecentPost } from "@/entities/post";
const noticePostTableColumns: ColumnDef<RecentPost>[] = [
{
header: "번호",
cell: ({ row, table }) => {
if (row.original.upndFixYn === "Y") {
return (
<Badge
color="orange"
className="flex size-8 items-center justify-center"
>
<i className="diveicon di-volume-up-fill" />
</Badge>
);
}
const totalRows = table.getRowCount();
const currentPage = table.getState().pagination.pageIndex;
const pageSize = table.getState().pagination.pageSize;
return totalRows - (currentPage * pageSize + row.index);
},
},
{
accessorKey: "pstTtl",
header: "제목",
},
{
accessorKey: "wrtrNm",
header: "작성자",
},
{
accessorKey: "regDt",
header: "작성일",
cell: ({ row }) => dayjs(row.original.regDt).format("YYYY-MM-DD"),
},
{
accessorKey: "inqNocs",
header: "조회수",
},
];
const recentPostTableColumns: ColumnDef<RecentPost>[] = [
{
header: "번호",
cell: ({ row, table }) => {
const totalRows = table.getRowCount();
const currentPage = table.getState().pagination.pageIndex;
const pageSize = table.getState().pagination.pageSize;
return totalRows - (currentPage * pageSize + row.index);
},
},
{
accessorKey: "pstTtl",
header: "제목",
},
{
accessorKey: "wrtrNm",
header: "작성자",
},
{
accessorKey: "regDt",
header: "작성일",
cell: ({ row }) => dayjs(row.original.regDt).format("YYYY-MM-DD"),
},
{
accessorKey: "inqNocs",
header: "조회수",
},
];
export { noticePostTableColumns, recentPostTableColumns };
@@ -1,409 +1,5 @@
"use client";
import { useRouter } from "next/navigation";
import { useQuery } from "@tanstack/react-query";
import { getCoreRowModel } from "@tanstack/react-table";
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
BarElement,
Filler,
Legend,
Tooltip,
type ChartData,
} from "chart.js";
import { Bar, Line } from "react-chartjs-2";
import { PostApi, type RecentPost } from "@/entities/post";
import { ENDPOINT } from "@/shared/config";
import { useDataTable } from "@/shared/lib";
import { DashboardApi } from "../api/dashboard-service";
import { chartData } from "../model/chart-data";
import {
noticePostTableColumns,
recentPostTableColumns,
} from "../model/table-columns";
import { processMenuAccessData, processSiteAccessData } from "../lib/utils";
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
BarElement,
Filler,
Legend,
Tooltip,
);
function DashboardPage() {
const router = useRouter();
const { data } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.DASHBOARD],
queryFn: () => DashboardApi.getDashboard(),
});
const noticePostQuery = useQuery({
queryKey: [ENDPOINT.BOARD_SERVICE.POSTS],
queryFn: () =>
PostApi.getRecentPostList({
page: 0,
size: 5,
keywordType: "bbsTypeCd",
keyword: "BBSNOTICE",
}),
});
const recentPostQuery = useQuery({
queryKey: [ENDPOINT.BOARD_SERVICE.POSTS],
queryFn: () =>
PostApi.getRecentPostList({
page: 0,
size: 5,
}),
});
const handleNoticePostRowClick = (row: RecentPost) => {
router.push(`/bbs/bbsnotice/${row.bbsId}/${row.pstNo}`);
};
const handleRecentPostRowClick = (row: RecentPost) => {
router.push(
`/bbs/${row.bbsTypeCd.toLowerCase()}/${row.bbsId}/${row.pstNo}`,
);
};
const { tableComponent: noticePostTableComponent } = useDataTable({
query: noticePostQuery,
tableOptions: {
columns: noticePostTableColumns,
getCoreRowModel: getCoreRowModel(),
},
dataTableOptions: {
variant: "line",
onRowClick: handleNoticePostRowClick,
},
});
const { tableComponent: recentPostTableComponent } = useDataTable({
query: recentPostQuery,
tableOptions: {
columns: recentPostTableColumns,
getCoreRowModel: getCoreRowModel(),
},
dataTableOptions: {
variant: "line",
onRowClick: handleRecentPostRowClick,
},
});
return (
<div className="p-6">
<div className="flex flex-col gap-1">
{/* 첫번째 라인 */}
<div className="grid grid-cols-4 gap-1">
{/* 총 회원수 카드 */}
<div className="card card-border h-80 !bg-primary !p-0">
<div className="relative h-full">
<div className="absolute left-0 top-0 p-6 tracking-tighter text-white">
<h3 className="text-2xl font-medium">총 회원수</h3>
<div className="mt-2 text-6xl font-bold">
{data?.memberTotCnt ?? "-"}
</div>
<p className="mt-1 text-2xl opacity-80">
금일 신규 가입자 {data?.memberTodayCnt ?? "-"}명
</p>
</div>
{/* 차트 영역 */}
<div className="h-full">
<Line
data={chartData.memberChartData!.data as ChartData<"line">}
options={chartData.memberChartData!.options}
/>
</div>
</div>
</div>
{/* 전체 게시물 카드 */}
<div className="card card-border h-80 !p-0">
<div className="relative h-full">
<div className="absolute left-0 top-0 p-6 tracking-tighter">
<h3 className="text-2xl font-medium">전체 게시물</h3>
<div className="mt-2 text-6xl font-bold">
{data?.pstTotCnt ?? "-"}
</div>
<p className="mt-1 text-2xl opacity-80">
금일 +{data?.pstTodayCnt ?? "-"} 등록
</p>
</div>
{/* 차트 영역 */}
<div className="h-full">
<Line
data={chartData.postChartData!.data as ChartData<"line">}
options={chartData.postChartData!.options}
/>
</div>
</div>
</div>
{/* 오늘 접속자 수 카드 */}
<div className="card card-border h-80 !p-0">
<div className="relative h-full">
<div className="absolute left-0 top-0 p-6 tracking-tighter">
<h3 className="text-2xl font-medium">오늘 접속자 수</h3>
<div className="mt-2 text-6xl font-bold">
{data?.accessTodayCnt ?? "-"}
</div>
<p className="mt-1 text-2xl opacity-80">
전일 대비 +{data?.accessBefDayPer ?? "-"}%
</p>
</div>
{/* 차트 영역 */}
<div className="h-full">
<Line
data={chartData.visitorChartData!.data as ChartData<"line">}
options={chartData.visitorChartData!.options}
/>
</div>
</div>
</div>
{/* API 호출 건수 카드 */}
<div className="card card-border h-80 !p-0">
<div className="relative h-full">
<div className="absolute left-0 top-0 p-6 tracking-tighter">
<h3 className="text-2xl font-medium">API 호출 건수</h3>
<div className="mt-2 text-6xl font-bold">
{data?.apiTodayCnt ?? "-"}
</div>
<p className="mt-1 text-2xl opacity-80">금일 누적</p>
</div>
{/* 차트 영역 */}
<div className="h-full">
<Line
data={chartData.apiChartData!.data as ChartData<"line">}
options={chartData.apiChartData!.options}
/>
</div>
</div>
</div>
</div>
{/* 두번째 라인 */}
<div className="grid grid-cols-2 gap-1">
{/* 승인 대기 알림 */}
<div className="card card-border">
<div className="card-header">
<h3 className="text-2xl font-medium">승인 대기 알림</h3>
</div>
<div className="p-4">
<div className="flex gap-4">
{/* 사용자 승인 */}
<div className="flex flex-1 flex-col items-start rounded-md bg-accent p-6">
<div className="flex items-center">
<div className="mr-4 flex h-10 w-10 items-center justify-center rounded-lg bg-red-100">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="text-red-500"
>
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
</div>
<span className="text-2xl font-medium">사용자 승인</span>
</div>
<div className="mt-5">
<div className="text-5xl font-bold">
{data?.waitMemberCnt}건
</div>
<div className="mt-2 text-2xl text-gray-500">
신규 가입 승인 대기
</div>
</div>
</div>
{/* 매뉴 승인 */}
<div className="flex flex-1 flex-col items-start rounded-md bg-accent p-6">
<div className="flex items-center">
<div className="mr-4 flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="text-blue-500"
>
<rect x="3" y="3" width="7" height="7"></rect>
<rect x="14" y="3" width="7" height="7"></rect>
<rect x="14" y="14" width="7" height="7"></rect>
<rect x="3" y="14" width="7" height="7"></rect>
</svg>
</div>
<span className="text-2xl font-medium">메뉴 승인</span>
</div>
<div className="mt-5">
<div className="text-5xl font-bold">3건</div>
<div className="mt-2 text-2xl text-gray-500">
매뉴 수정 승인 대기
</div>
</div>
</div>
{/* 컨텐츠 승인 */}
<div className="flex flex-1 flex-col items-start rounded-md bg-accent p-6">
<div className="flex items-center">
<div className="mr-4 flex h-10 w-10 items-center justify-center rounded-lg bg-yellow-100">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="text-yellow-500"
>
<path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
</svg>
</div>
<span className="text-2xl font-medium">컨텐츠 승인</span>
</div>
<div className="mt-5">
<div className="text-5xl font-bold">
{data?.waitCntnCnt}건
</div>
<div className="mt-2 text-2xl text-gray-500">
컨텐츠 수정 승인 대기
</div>
</div>
</div>
</div>
</div>
</div>
<div className="grid grid-cols-2 gap-1">
{/* 실시간 알림 */}
<div className="card card-border">
<div className="card-header">
<h3 className="text-2xl font-medium">실시간 알림</h3>
</div>
<div className="p-4">
<div className="space-y-4">
<div className="flex items-center justify-between border-b border-border pb-4">
<span className="font-medium">신규 사용자 가입</span>
<span>1분 전</span>
</div>
<div className="flex items-center justify-between border-b border-border pb-4">
<span className="font-medium">메뉴 수정 요청</span>
<span>5분 전</span>
</div>
<div className="flex items-center justify-between border-b border-border pb-4">
<span className="font-medium">게시물 신고</span>
<span>10분 전</span>
</div>
<div className="flex items-center justify-between">
<span className="font-medium">컨텐츠 승인 요청</span>
<span>15분 전</span>
</div>
</div>
</div>
</div>
{/* 일정 알림 */}
<div className="card card-border">
<div className="card-header">
<h3 className="text-2xl font-medium">일정 알림</h3>
</div>
<div className="p-4">
<div className="space-y-4">
<div className="flex items-center justify-between border-b border-border pb-4">
<span className="font-medium">3월 정기 시스템 점검</span>
<span>내일</span>
</div>
<div className="flex items-center justify-between border-b border-border pb-4">
<span className="font-medium">서버 업데이트 예정</span>
<span>3일 후</span>
</div>
<div className="flex items-center justify-between border-b border-border pb-4">
<span className="font-medium">백업 스케줄</span>
<span>5일 후</span>
</div>
<div className="flex items-center justify-between">
<span className="font-medium">정기 보안 점검</span>
<span>7일 후</span>
</div>
</div>
</div>
</div>
</div>
</div>
{/* 세번째 라인 */}
<div className="grid grid-cols-2 gap-1">
{/* 접속자 통계 */}
<div className="card card-border">
<div className="card-header">
<h3 className="text-2xl font-medium">접속자 통계</h3>
</div>
<div className="h-80 p-4">
<Line
data={{
...chartData.siteAccessChartData!.data,
datasets: processSiteAccessData(data?.siteAccessList ?? []),
}}
options={chartData.siteAccessChartData!.options}
/>
</div>
</div>
{/* 메뉴별 접속 통계 */}
<div className="card card-border">
<div className="card-header">
<h3 className="text-2xl font-medium">메뉴별 접속 통계</h3>
</div>
<div className="h-80 p-4">
<Bar
data={{
labels:
data?.menuAccessList?.map((item) => item.menuNm) || [],
datasets: processMenuAccessData(data?.menuAccessList || []),
}}
options={chartData.menuAccessChartData!.options}
/>
</div>
</div>
</div>
{/* 네번째 라인 */}
<div className="grid grid-cols-2 gap-1">
{/* 공지사항 */}
<div className="card card-border !p-0">
<div className="card-header !m-0 !border-none">
<h3 className="text-2xl font-medium">공지사항</h3>
</div>
{noticePostTableComponent}
</div>
{/* 신규 게시글 */}
<div className="card card-border !p-0">
<div className="card-header !m-0 !border-none">
<h3 className="text-2xl font-medium">신규 게시글</h3>
</div>
{recentPostTableComponent}
</div>
</div>
</div>
</div>
);
return <></>;
}
export { DashboardPage };
+24 -37
View File
@@ -6,8 +6,8 @@ import { keepPreviousData, useQuery } from "@tanstack/react-query";
import { getCoreRowModel, type PaginationState } from "@tanstack/react-table";
import {
Button,
DateRangePicker,
Input,
InputDatePicker,
Label,
Select,
SelectContent,
@@ -22,7 +22,7 @@ import { ENDPOINT } from "@/shared/config";
import { columns } from "@/pages/loginlog/model/table-columns";
type DateRange = {
from?: Date | undefined;
from: Date | undefined;
to?: Date | undefined;
};
@@ -32,12 +32,13 @@ function LoginlogPage() {
to: dayjs().toDate(),
};
const [dateRange, setDateRange] = useState<DateRange>(defaultDateRange);
const [isManualLoading, setIsManualLoading] = useState(false);
const [pagination, setPagination] = useState<PaginationState>({
pageIndex: 0,
pageSize: 10,
});
const [presetDateRange, setPresetDateRange] = useState("");
const [dateRange, setDateRange] = useState<DateRange>(defaultDateRange);
const [userId, setUserId] = useState("");
const [errOcrnYn, setErrOcrnYn] = useState("N");
const [searchParams, setSearchParams] = useState<LoginlogParams>({
@@ -47,7 +48,6 @@ function LoginlogPage() {
searchDateTo: dayjs().format("YYYY-MM-DD"),
sort: "lgnDt,desc",
});
const [isManualLoading, setIsManualLoading] = useState(false);
const query = useQuery({
queryKey: [ENDPOINT.USER_SERVICE.LOGINLOG, searchParams, pagination],
@@ -88,12 +88,8 @@ function LoginlogPage() {
...searchParams,
userId,
errOcrnYn,
searchDateFrom: dateRange.from
? dayjs(dateRange.from).format("YYYY-MM-DD")
: "",
searchDateTo: dateRange.to
? dayjs(dateRange.to).format("YYYY-MM-DD")
: "",
searchDateFrom: dayjs(dateRange.from).format("YYYY-MM-DD"),
searchDateTo: dayjs(dateRange.to).format("YYYY-MM-DD"),
});
query.refetch().finally(() => {
setIsManualLoading(false);
@@ -137,7 +133,6 @@ function LoginlogPage() {
default:
presetDateRange = undefined;
}
setPresetDateRange(value);
setDateRange(presetDateRange || defaultDateRange);
};
@@ -146,31 +141,23 @@ function LoginlogPage() {
<div className="card card-border">
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
<Label className="mr-2">조회기간</Label>
<Select value={presetDateRange} onValueChange={handlePresetDateRange}>
<SelectTrigger className="w-[12rem]">
<SelectValue placeholder="기간 선택" className="w-[24rem]" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1W">일주일</SelectItem>
<SelectItem value="1M">1개월</SelectItem>
<SelectItem value="3M">3개월</SelectItem>
</SelectContent>
</Select>
<InputDatePicker
value={dateRange.from}
onChange={(date) => {
setDateRange({ ...dateRange, from: date });
setPresetDateRange("");
}}
/>
~
<InputDatePicker
value={dateRange.to}
onChange={(date) => {
setDateRange({ ...dateRange, to: date });
setPresetDateRange("");
}}
/>
<DateRangePicker
value={dateRange}
onValueChange={(value) => setDateRange(value || defaultDateRange)}
>
<div className="card card-border flex items-center gap-2">
<Select onValueChange={handlePresetDateRange}>
<SelectTrigger>
<SelectValue placeholder="기간 선택" className="w-[24rem]" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1W">일주일</SelectItem>
<SelectItem value="1M">1개월</SelectItem>
<SelectItem value="3M">3개월</SelectItem>
</SelectContent>
</Select>
</div>
</DateRangePicker>
<Label className="ml-4 mr-2 text-label">사용자ID</Label>
<Input
className="h-[3.2rem] w-[20rem] rounded-sm !text-[1.3rem]"
-1
View File
@@ -110,7 +110,6 @@ function MenuPage() {
queryClient.invalidateQueries({
queryKey: [ENDPOINT.CMS_SERVICE.MENU_ROLES],
});
form.reset();
},
});
@@ -6,8 +6,8 @@ import { keepPreviousData, useQuery } from "@tanstack/react-query";
import { getCoreRowModel, type PaginationState } from "@tanstack/react-table";
import {
Button,
DateRangePicker,
Input,
InputDatePicker,
Label,
Select,
SelectContent,
@@ -24,7 +24,7 @@ import { ENDPOINT } from "@/shared/config";
import { columns } from "@/pages/privacylog/model/table-columns";
type DateRange = {
from?: Date | undefined;
from: Date | undefined;
to?: Date | undefined;
};
@@ -38,7 +38,6 @@ function PrivacyLogPage() {
pageIndex: 0,
pageSize: 10,
});
const [presetDateRange, setPresetDateRange] = useState("");
const [dateRange, setDateRange] = useState<DateRange>(defaultDateRange);
const [inqInfoKeyword, setInqInfoKeyword] = useState("");
const [searchParams, setSearchParams] = useState<PrivacyLogParams>({
@@ -86,10 +85,8 @@ function PrivacyLogPage() {
setSearchParams({
...searchParams,
inqInfoKeyword,
inqDtStart: dateRange.from
? dayjs(dateRange.from).format("YYYY-MM-DD")
: "",
inqDtEnd: dateRange.to ? dayjs(dateRange.to).format("YYYY-MM-DD") : "",
inqDtStart: dayjs(dateRange.from).format("YYYY-MM-DD"),
inqDtEnd: dayjs(dateRange.to).format("YYYY-MM-DD"),
});
};
@@ -128,7 +125,6 @@ function PrivacyLogPage() {
default:
presetDateRange = undefined;
}
setPresetDateRange(value);
setDateRange(presetDateRange || defaultDateRange);
};
@@ -137,37 +133,30 @@ function PrivacyLogPage() {
<div className="card card-border">
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
<Label className="mr-2">조회기간</Label>
<Select value={presetDateRange} onValueChange={handlePresetDateRange}>
<SelectTrigger className="w-[12rem]">
<SelectValue placeholder="기간 선택" className="w-[24rem]" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1W">일주일</SelectItem>
<SelectItem value="1M">1개월</SelectItem>
<SelectItem value="3M">3개월</SelectItem>
</SelectContent>
</Select>
<InputDatePicker
value={dateRange.from}
onChange={(date) => {
setDateRange({ ...dateRange, from: date });
setPresetDateRange("");
}}
/>
~
<InputDatePicker
value={dateRange.to}
onChange={(date) => {
setDateRange({ ...dateRange, to: date });
setPresetDateRange("");
}}
/>
<DateRangePicker
value={dateRange}
onValueChange={(value) => setDateRange(value || defaultDateRange)}
>
<div className="card card-border flex items-center gap-2">
<Select onValueChange={handlePresetDateRange}>
<SelectTrigger>
<SelectValue placeholder="기간 선택" className="w-[24rem]" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1W">일주일</SelectItem>
<SelectItem value="1M">1개월</SelectItem>
<SelectItem value="3M">3개월</SelectItem>
</SelectContent>
</Select>
</div>
</DateRangePicker>
<Label className="ml-4 mr-2 text-label">조회정보</Label>
<Input
className="h-[3.2rem] w-[20rem] rounded-sm !text-[1.3rem]"
value={inqInfoKeyword}
onChange={(e) => setInqInfoKeyword(e.target.value)}
/>
<Button className="h-[3.2rem]" type="submit">
조회
</Button>
+25 -33
View File
@@ -12,8 +12,8 @@ import {
} from "@tanstack/react-table";
import {
Button,
DateRangePicker,
Input,
InputDatePicker,
Label,
Select,
SelectContent,
@@ -37,7 +37,7 @@ import { columns } from "../model/table-columns";
import { MovePostDialog } from "./move-post-dialog";
type DateRange = {
from?: Date | undefined;
from: Date | undefined;
to?: Date | undefined;
};
@@ -51,21 +51,22 @@ function RecentPage() {
const { confirm } = useConfirm();
const alert = useAlertStore((state) => state.setMessage);
const [dateRange, setDateRange] = useState<DateRange | undefined>({
from: undefined,
to: undefined,
});
const [tableSort, setTableSort] = useState("regDt,desc");
const [pagination, setPagination] = useState<PaginationState>({
pageIndex: 0,
pageSize: 10,
});
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
const [presetDateRange, setPresetDateRange] = useState("");
const [dateRange, setDateRange] = useState<DateRange | undefined>({
from: undefined,
to: undefined,
});
const [keywordType, setKeywordType] = useState("");
const [keyword, setKeyword] = useState("");
const [bbsId, setBbsId] = useState<string | null>(null);
const [delYn, setDelYn] = useState("N");
const [searchParams, setSearchParams] = useState<RecentPostParams>({
keywordType: "",
keyword: "",
@@ -192,7 +193,6 @@ function RecentPage() {
default:
presetDateRange = undefined;
}
setPresetDateRange(value);
setDateRange(presetDateRange);
};
@@ -250,31 +250,21 @@ function RecentPage() {
<div className="card card-border">
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
<Label className="mr-2">날짜</Label>
<Select value={presetDateRange} onValueChange={handlePresetDateRange}>
<SelectTrigger className="w-[12rem]">
<SelectValue placeholder="기간 선택" className="w-[24rem]" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1W">일주일</SelectItem>
<SelectItem value="1M">1개월</SelectItem>
<SelectItem value="3M">3개월</SelectItem>
</SelectContent>
</Select>
<InputDatePicker
value={dateRange?.from}
onChange={(date) => {
setDateRange({ ...dateRange, from: date });
setPresetDateRange("");
}}
/>
~
<InputDatePicker
value={dateRange?.to}
onChange={(date) => {
setDateRange({ ...dateRange, to: date });
setPresetDateRange("");
}}
/>
<DateRangePicker value={dateRange} onValueChange={setDateRange}>
<div className="card card-border flex items-center gap-2">
<Select onValueChange={handlePresetDateRange}>
<SelectTrigger>
<SelectValue placeholder="기간 선택" className="w-[24rem]" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1W">일주일</SelectItem>
<SelectItem value="1M">1개월</SelectItem>
<SelectItem value="3M">3개월</SelectItem>
</SelectContent>
</Select>
</div>
</DateRangePicker>
<Label className="ml-4 mr-2 text-label">게시판</Label>
<Select
value={bbsId?.toString() || ""}
@@ -291,6 +281,7 @@ function RecentPage() {
))}
</SelectContent>
</Select>
<Label className="ml-4 mr-2 text-label">상태</Label>
<Select value={delYn} onValueChange={(value) => setDelYn(value)}>
<SelectTrigger className="w-[10rem]">
@@ -301,6 +292,7 @@ function RecentPage() {
<SelectItem value="Y">삭제</SelectItem>
</SelectContent>
</Select>
<Label className="ml-4 mr-2 text-label">검색</Label>
<Select
value={keywordType}
+19 -32
View File
@@ -8,8 +8,8 @@ import { getCoreRowModel, type PaginationState } from "@tanstack/react-table";
import {
Button,
Checkbox,
DateRangePicker,
Input,
InputDatePicker,
Label,
Select,
SelectContent,
@@ -28,7 +28,7 @@ import { useDataTable } from "@/shared/lib";
import { columns } from "../model/table-columns";
type DateRange = {
from?: Date | undefined;
from: Date | undefined;
to?: Date | undefined;
};
@@ -39,7 +39,6 @@ function UsersPage() {
pageIndex: 0,
pageSize: 10,
});
const [presetDateRange, setPresetDateRange] = useState("");
const [dateRange, setDateRange] = useState<DateRange | undefined>({
from: undefined,
to: undefined,
@@ -168,7 +167,6 @@ function UsersPage() {
default:
presetDateRange = undefined;
}
setPresetDateRange(value);
setDateRange(presetDateRange);
};
@@ -279,34 +277,23 @@ function UsersPage() {
</div>
<div className="flex items-center gap-2">
<Label className="mr-2 text-label">기간</Label>
<Select
value={presetDateRange}
onValueChange={handlePresetDateRange}
>
<SelectTrigger className="w-[12rem]">
<SelectValue placeholder="기간 선택" className="w-[24rem]" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1M">1개월</SelectItem>
<SelectItem value="3M">3개월</SelectItem>
<SelectItem value="6M">6개월</SelectItem>
</SelectContent>
</Select>
<InputDatePicker
value={dateRange?.from}
onChange={(date) => {
setDateRange({ ...dateRange, from: date });
setPresetDateRange("");
}}
/>
~
<InputDatePicker
value={dateRange?.to}
onChange={(date) => {
setDateRange({ ...dateRange, to: date });
setPresetDateRange("");
}}
/>
<DateRangePicker value={dateRange} onValueChange={setDateRange}>
<div className="card card-border flex items-center gap-2">
<Select onValueChange={handlePresetDateRange}>
<SelectTrigger>
<SelectValue
placeholder="기간 선택"
className="w-[24rem]"
/>
</SelectTrigger>
<SelectContent>
<SelectItem value="1M">1개월</SelectItem>
<SelectItem value="3M">3개월</SelectItem>
<SelectItem value="6M">6개월</SelectItem>
</SelectContent>
</Select>
</div>
</DateRangePicker>
</div>
</div>
<div className="flex items-center gap-2">
-1
View File
@@ -23,7 +23,6 @@ export const ENDPOINT = {
PRIVACYLOG: "/user-service//api/v1/prvc-inq-logs",
},
CMS_SERVICE: {
DASHBOARD: "/cms-service/api/v1/dashboard",
SITES: "/cms-service/api/v1/sites",
IPS: "/cms-service/api/v1/site-ips",
DOMAINS: "/cms-service/api/v1/site-dmns",
-5
View File
@@ -1,5 +0,0 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
+2 -2
View File
@@ -1,6 +1,6 @@
NEXT_PUBLIC_SITE_ID = FO
NEXT_PUBLIC_PORT = 11300
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300
NEXT_PUBLIC_PORT = 3000
NEXT_PUBLIC_PROXY_HOST = http://localhost:3000
NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1
NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1
NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
@@ -2,7 +2,7 @@
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 { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components";
import { useEffect, useState } from "react";
import DashBoardChartModal from "./modal/page";
@@ -30,20 +30,20 @@ const headMakeColSpanPlanFclty = (upHeadList: TableUpperProps[], planYearList: s
const headMakeColSpanOperationStatus = (upHeadList: TableUpperProps[], searchYear: string) => {
return ( <>
<TableRow>
<TableHead rowSpan={1} colSpan={16} style={{ whiteSpace: 'pre-line' }}>{searchYear+'년도 운영실태'}</TableHead>
<TableHead rowSpan={1} colSpan={17} 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.upSequnce?<TableHead style={{ whiteSpace: 'pre-line' }} 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))}
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))}
(head.upName === 'upChangeRe2'||head.upName === 'upChangeRe3'||head.upName === 'upChangeRe4'||head.upName === 'upChangeRe5'?<TableHead style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>:null))}
</TableRow>
</> )
}
@@ -238,10 +238,10 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
(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 === 0)?<TableCell rowSpan={7} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
(head.id === 'rdi'&&index === 7)?<TableCell rowSpan={6} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}></TableCell>:
(head.id === 'rdiRain'&&index === 0)?<TableCell rowSpan={7} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el['rdiRain']}</TableCell>:
(head.id === 'rdiRain'&&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>:
+13 -12
View File
@@ -14,7 +14,7 @@ const tabList = [
{ value: 'facilityInfo', label: '시설정보 및 운영현황' },
{ value: 'mainGraph', label: '주요그래프' },
{ value: 'rainManage', label: '강우일 운영현황' },
{ value: 'drainageEquipment', label: '배수설비 정비현황' }
//{ value: 'drainageEquipment', label: '배수설비 정비현황' }
];
export default function DashBoard() {
@@ -57,7 +57,8 @@ export default function DashBoard() {
/******************선택된 데이터******************/
// 연도
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || '0');
//const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || '0');
const [searchYear, setSearchYear] = useState<string>('2021');
// 시설명
const [fcltyList, setFcltyList] = useState<{bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | ''}>({
bscFctCd: '',
@@ -71,11 +72,11 @@ export default function DashBoard() {
if (!isInit) {
initializeCommonData();
setFcltyList({
bscFctCd: '11000SW001R',
bscFctNm: '난지',
fcltyCpc: 860000,
trtFrfNm: '표준활성슬러지법, MLE, A2O',
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
bscFctCd: '26260PB001R',
bscFctNm: '수영',
fcltyCpc: 452000,
trtFrfNm: '표준활성슬러지법, MLE, MBR',
efflWqltStndrdNm: '500톤 이상(Ⅳ지역)'
});
}
}, [isInit, initializeCommonData]);
@@ -257,11 +258,11 @@ export default function DashBoard() {
const initVal = () => {
setFcltyList({
bscFctCd: '11000SW001R',
bscFctNm: '난지',
fcltyCpc: 860000,
trtFrfNm: '표준활성슬러지법, MLE, A2O',
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
bscFctCd: '26260PB001R',
bscFctNm: '수영',
fcltyCpc: 452000,
trtFrfNm: '표준활성슬러지법, MLE, MBR',
efflWqltStndrdNm: '500톤 이상(Ⅳ지역)'
});
}
@@ -81,7 +81,8 @@ export default function FacilityPrecipitation() {
// 시설상태
const [operationValue, setOperationValue] = useState<string>("0");
// 조회기간
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
//const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYear, setSearchYear] = useState<string>("2023");
/**
* 페이지 함수
@@ -125,9 +126,9 @@ export default function FacilityPrecipitation() {
useEffect(() => {
if (!isInit) {
initializeCommonData();
searchFacilityPrecipitationList(1, 10, selectSearchYear[0]?.val || "0");
searchFacilityPrecipitationList(1, 10, searchYear || "0");
}
}, [isInit, initializeCommonData, searchFacilityPrecipitationList, selectSearchYear]);
}, [isInit, initializeCommonData, searchFacilityPrecipitationList, searchYear]);
useEffect(() => {
if (excelList && excelList.length > 0) {
@@ -63,7 +63,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
let maxEfflWqltBod = 0;
let maxEfflWqltTn = 0;
let maxEfflWqltTp = 0;
let maxefflWqltCod = 0;
let maxefflWqltToc = 0;
let maxEfflWqltSs = 0;
let maxInflAssctAftWqltBod = 0;
@@ -80,7 +80,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
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 minefflWqltToc = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltToc) : 0;
let minEfflWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltSs) : 0;
let minInflAssctAftWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctAftWqltBod) : 0;
@@ -97,7 +97,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
let avgEfflWqltBod = 0;
let avgEfflWqltTn = 0;
let avgEfflWqltTp = 0;
let avgefflWqltCod = 0;
let avgefflWqltToc = 0;
let avgEfflWqltSs = 0;
let avgInflAssctAftWqltBod = 0;
@@ -115,7 +115,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
const efflWqltBod = parseNumber(item.efflWqltBod);
const efflWqltTn = parseNumber(item.efflWqltTn);
const efflWqltTp = parseNumber(item.efflWqltTp);
const efflWqltCod = parseNumber(item.efflWqltCod);
const efflWqltToc = parseNumber(item.efflWqltToc);
const efflWqltSs = parseNumber(item.efflWqltSs);
const inflAssctAftWqltBod = parseNumber(item.inflAssctAftWqltBod);
@@ -133,7 +133,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
maxEfflWqltBod = Math.max(maxEfflWqltBod, efflWqltBod);
maxEfflWqltTn = Math.max(maxEfflWqltTn, efflWqltTn);
maxEfflWqltTp = Math.max(maxEfflWqltTp, efflWqltTp);
maxefflWqltCod = Math.max(maxefflWqltCod, efflWqltCod);
maxefflWqltToc = Math.max(maxefflWqltToc, efflWqltToc);
maxEfflWqltSs = Math.max(maxEfflWqltSs, efflWqltSs);
maxInflAssctAftWqltBod = Math.max(maxInflAssctAftWqltBod, inflAssctAftWqltBod);
@@ -150,7 +150,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
minEfflWqltBod = Math.min(minEfflWqltBod, efflWqltBod);
minEfflWqltTn = Math.min(minEfflWqltTn, efflWqltTn);
minEfflWqltTp = Math.min(minEfflWqltTp, efflWqltTp);
minefflWqltCod = Math.min(minefflWqltCod, efflWqltCod);
minefflWqltToc = Math.min(minefflWqltToc, efflWqltToc);
minEfflWqltSs = Math.min(minEfflWqltSs, efflWqltSs);
minInflAssctAftWqltBod = Math.min(minInflAssctAftWqltBod, inflAssctAftWqltBod);
@@ -167,7 +167,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
avgEfflWqltBod += efflWqltBod;
avgEfflWqltTn += efflWqltTn;
avgEfflWqltTp += efflWqltTp;
avgefflWqltCod += efflWqltCod;
avgefflWqltToc += efflWqltToc;
avgEfflWqltSs += efflWqltSs;
avgInflAssctAftWqltBod += inflAssctAftWqltBod;
@@ -186,7 +186,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
{
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),
efflWqltToc: filteredData.length==0?'0.0':(Math.round(avgefflWqltToc / 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),
@@ -209,7 +209,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
{
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',
efflWqltToc : Math.round(maxefflWqltToc * 10) / 10?(Math.round(maxefflWqltToc * 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',
@@ -232,7 +232,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
{
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',
efflWqltToc : Math.round(minefflWqltToc * 10) / 10?(Math.round(minefflWqltToc?minefflWqltToc: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',
@@ -299,16 +299,16 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
"유입TN(mg/L)": item.inflAssctAftWqltTn,
"유입TP(mg/L)": item.inflAssctBfrWqltTp,
"유출BOD(mg/L)": item.efflWqltBod,
"유출TOC(COD)(mg/L)": item.efflWqltCod,
"유출TOC(COD)(mg/L)": item.efflWqltToc,
"유출SS(mg/L)": item.efflWqltSs,
"유출TN(mg/L)": item.efflWqltTn,
"유출TP(mg/L)": item.efflWqltTp,
"강우량(일)": item.infoRnDay?item.infoRnDay.toString():"0.0",
/* "강우량(mm/일)": 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' });
downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: searchYear+'년 '+fcltyName + ' 수질현황', sheetNameArray: [fcltyName + ' 수질현황'], headerRange: 'A1:K1' });
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
alert('다운받을 데이터가 없습니다.');
}
@@ -351,7 +351,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
</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>
{/*<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
@@ -449,6 +449,9 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
</UiTable>
</div>
<div className="mt-14">
<span className="text-2xl font-bold text-gray-500">☞ 청천시 : 강우량이 3mm미만의 날</span>
</div>
</TabsContent>
<TabsContent value="tab_term_rain">
@@ -476,6 +479,9 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
</UiTable>
</div>
<div className="mt-14">
<span className="text-2xl font-bold text-gray-500">☞ 강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날</span>
</div>
</TabsContent>
</UITab>
</TabsContent>
+3 -2
View File
@@ -48,7 +48,8 @@ export default function ProcessFacilitySearch() {
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 [searchYearValue, setSearchYearValue] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYearValue, setSearchYearValue] = useState<string>("2023");
const [fcltCpct, setFcltCpct] = useState<string>("0");
// 모달 상태 추가
@@ -196,7 +197,7 @@ export default function ProcessFacilitySearch() {
{selectedRow !== null && (
<UiModal
body={<WaterQualityModal fcltyName={fcltyNm} facilityCd={fcltyCd} searchYear={modalYear}></WaterQualityModal>}
bodyClass="sm:max-w-[90vw] w-[1200px] h-[920px]"
bodyClass="sm:max-w-[90vw] w-[1300px] h-[920px]"
open={selectedRow !== null}
onOpenChange={(open) => !open && closeModal()}
noHeaderYn="Y"
+59 -62
View File
@@ -52,6 +52,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
return Number(value.replace(/,/g, ''));
};
console.log('filteredData : ', filteredData);
let maxtotInflAmnt = 0;
let maxinflAmnt = 0;
let maxsumFlow = 0;
@@ -65,7 +66,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
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 mininfoRnDay = parseNumber(filteredData[0]?.infoRnDay && filteredData[0]?.infoRnDay.toString().trim() !== 'x' ? filteredData[0]?.infoRnDay.toString().trim() : 0);
let avgtotInflAmnt = 0;
let avginflAmnt = 0;
@@ -80,7 +81,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
const sumFlow = parseNumber(item.sumFlow);
const returnAmnt = parseNumber(item.returnAmnt);
const efflAmnt = parseNumber(item.efflAmnt);
const infoRnDay = parseNumber(item.infoRnDay);
const infoRnDay = parseNumber(item.infoRnDay && item.infoRnDay.toString().trim() !== 'x' ? item.infoRnDay.toString().trim() : 0);
maxtotInflAmnt = Math.max(maxtotInflAmnt, totInflAmnt);
maxinflAmnt = Math.max(maxinflAmnt, inflAmnt);
maxsumFlow = Math.max(maxsumFlow, sumFlow);
@@ -166,7 +167,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
"연계처리량(m³/일)": item.sumFlow,
"총인반류수량(m³/일)": item.returnAmnt,
"방류량(m³/일)": item.efflAmnt,
"강우량": item.infoRnDay,
/* "강우량(mm/일)": item.infoRnDay, */
});
});
}
@@ -194,20 +195,18 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
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 className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[370px]"
boldArray={[0,1,2]}
/>
</div>
</TabsContent>
<TabsContent value="tab_term_summer">
@@ -220,20 +219,18 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
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 className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[370px]"
boldArray={[0,1,2]}
/>
</div>
</TabsContent>
<TabsContent value="tab_term_winter">
@@ -246,20 +243,18 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
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 className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[370px]"
boldArray={[0,1,2]}
/>
</div>
</TabsContent>
<TabsContent value="tab_term_chuncheon">
@@ -272,20 +267,21 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
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 className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[370px]"
boldArray={[0,1,2]}
/>
</div>
<div className="mt-14">
<span className="text-2xl font-bold text-gray-500">☞ 청천시 : 강우량이 3mm미만의 날</span>
</div>
</TabsContent>
<TabsContent value="tab_term_rain">
@@ -298,10 +294,11 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
ref={ref}
queryClick={filterData}
/>
<div className="h-[370px] overflow-y-auto overflow-x-auto">
<div className="w-[120%]">
<div className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable headName="유량현황" tableData={copyYearList} headlist={upHeadListFlowRateModalYear} pageSize={0} total={0} cellClick={undefined} onPageChange={() => {}} className="h-[370px]" boldArray={[0,1,2]}/>
</div>
</div>
<div className="mt-14">
<span className="text-2xl font-bold text-gray-500">☞ 강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날</span>
</div>
</TabsContent>
</UITab>
+6 -4
View File
@@ -49,7 +49,8 @@ export default function ProcessFacilitySearch() {
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 [searchYearValue, setSearchYearValue] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYearValue, setSearchYearValue] = useState<string>("2023");
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
const [resetPage, setResetPage] = useState<boolean>(false);
@@ -125,10 +126,11 @@ export default function ProcessFacilitySearch() {
// 시도 데이터 초기화
useEffect(() => {
if(!isInit) {
console.log('searchYearValue', searchYearValue, isInit);
initializeCommonData();
searchFlowRateList(1, 10, selectSearchYear[0]?.val || "0");
searchFlowRateList(1, 10, searchYearValue || "0");
}
}, [isInit, initializeCommonData, searchFlowRateList, selectSearchYear]);
}, [isInit, initializeCommonData, searchFlowRateList, searchYearValue]);
useEffect(() => {
if (excelList && excelList.length > 0) {
@@ -197,7 +199,7 @@ export default function ProcessFacilitySearch() {
{selectedRow !== null && (
<UiModal
body={<FlowRateModal fcltyName={fcltyNm} facilityCd={fcltyCd} searchYear={searchYearValue}></FlowRateModal>}
bodyClass="sm:max-w-[90vw] w-[1050px] h-[700px]"
bodyClass="sm:max-w-[90vw] w-[1250px] h-[780px]"
open={selectedRow !== null}
onOpenChange={(open: boolean) => !open && closeModal()}
/>
+7 -1
View File
@@ -70,7 +70,8 @@ export default function PlanSewage() {
// 시설상태
const [operationValue, setOperationValue] = useState<string>("0");
// 조회기간
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
//const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYear, setSearchYear] = useState<string>("2023");
/**
* 페이지 함수
@@ -190,6 +191,11 @@ export default function PlanSewage() {
<div className={widthSize}>
<UiTable cellClick={ undefined } headName={"계획하수량 산정지표 현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
</div>
<div className="mt-14">
<span className="text-2xl font-bold text-gray-500">☞ 여유용량 = 하수처리시설 시설용량 – 건기시 유입유량(평균)​</span><br/>
<span className="text-2xl font-bold text-gray-500">☞ 변동부하율 = 건기시 일최대 유량/일평균​유량(기준 최근 3개년)​</span><br/>
<span className="text-2xl font-bold text-gray-500">☞ 분류식화율 = 분류식지역 면적(㎢) / 처리​구역 면적합계(㎢) ×100</span><br/>
</div>
</div>
</ListDiv>
</MainDiv>
+8 -77
View File
@@ -1,103 +1,34 @@
"use client"
import { useFoStore } from "@/app/store";
import type { SewageOccurDetailProps } from "@/app/store/sewageOccur";
import type { modalTableType } 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);
const {SewageOccurDetail, searchSewageOccurDetailList} = 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 [detailList, setDetailList] = useState<modalTableType[]>([]);
const {
upHeadListSewageOccurDetail,
gridListSewageOccurDetail
} = SewageOccurDetail;
useEffect(() => {
setDetailList(gridListSewageOccurDetail);
}, [gridListSewageOccurDetail]);
searchSewageOccurDetailList(props.facilityCd, validSearchYear);
}, [searchSewageOccurDetailList, props.facilityCd, validSearchYear]);
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]);
setDetailList(gridListSewageOccurDetail);
}, [gridListSewageOccurDetail]);
return (
<>
+11 -5
View File
@@ -18,7 +18,8 @@ export default function PlanSewage() {
SewageOccur: { sewageOccurList: [], sewageOccurCount: 0, excelList: [], upHeadList1: [], upHeadList2: [], upHeadList3: [] },
SewageOccurSearch: { labelArray: [] },
initializeCommonData: () => {},
searchSewageOccurList: () => {}
searchSewageOccurList: () => {},
calculateModalDataForAllFacilities: async () => []
};
const {
@@ -83,7 +84,8 @@ export default function PlanSewage() {
// 시설상태
const [operationValue, setOperationValue] = useState<string>("0");
// 조회기간
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
// const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYear, setSearchYear] = useState<string>("2023");
/**
* 페이지 함수
@@ -126,9 +128,9 @@ export default function PlanSewage() {
useEffect(() => {
if (!isInit) {
initializeCommonData();
searchSewageOccurList(1, 10, selectSearchYear[0]?.val || "0");
searchSewageOccurList(1, 10, searchYear || "0");
}
}, [isInit, initializeCommonData, searchSewageOccurList, selectSearchYear]);
}, [isInit, initializeCommonData, searchSewageOccurList, searchYear]);
useEffect(() => {
if (excelList && excelList.length > 0) {
@@ -224,7 +226,11 @@ export default function PlanSewage() {
</ContentsDiv>
{selectedRow !== null && (
<UiModal
body={<SewageOccurModal fcltyName={fcltyNm} facilityCd={fcltyCd} searchYear={searchYear}></SewageOccurModal>}
body={<SewageOccurModal
fcltyName={fcltyNm}
facilityCd={fcltyCd}
searchYear={searchYear}
/>}
bodyClass="sm:max-w-[90vw] w-[1000px] h-[770px]"
open={selectedRow !== null}
onOpenChange={(open) => !open && closeModal()}
+2 -1
View File
@@ -82,7 +82,8 @@ export default function UnderWaterInput() {
// 시설상태
const [operationValue, setOperationValue] = useState<string>("0");
// 조회기간
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
//const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYear, setSearchYear] = useState<string>("2023");
/**
* 페이지 함수
-11
View File
@@ -3,8 +3,6 @@
====================================**/
import { getFetch } from "@/app/components/api";
import { LoginApi } from "@/src/entities/auth";
import type { ILogin } from "@/src/entities/auth/model/login-interface";
/**
* STORE - TYPE
@@ -413,15 +411,6 @@ export const CommonReducer:(set:(fn: (state: CommonType) => CommonType) => void)
// 시도 변경 이벤트
initializeCommonData: async () => {
const payLoad : ILogin = {
userId: "tuser10003",
password: "test1234!"
};
console.log(payLoad.userId)
console.log(payLoad.password)
LoginApi.login(payLoad);
const promiseSet = await Promise.all([fetchSidoData(), fetchSigunData(), fetchRegionData(), fetchUnitWaterShedData(), fetchMiddleRegionData(), fetchEnvPartData()]);
const [sidoData, sggData, regionData, unitData, midData, envData] = promiseSet;
set((state: CommonType) => ({
+82 -80
View File
@@ -347,6 +347,7 @@ const upHeadListOperationStatus : TableUpperProps[] = [
{ id: "groundWaterSummer", title: "하절기\n평균", upName:"upChangeRe5", upSequnce:2 },
{ id: "groundWaterWinter", title: "동절기\n평균", upName:"upChangeRe5", upSequnce:3 },
{ id: "rdi", title: "RDII 추정" },
{ id: "rdiRain", title: "RDII 추정시\n일강수량(mm)" },
]
const upHeadListRainManage : TableUpperProps[] = [
@@ -1207,42 +1208,42 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
}
const fcltyCpcValue = res.data.wqltObjs[0].fctCpc;
const itemList = ['계', '3mm 미만', '3~10mm 미만', '10~20mm 미만', '20~30mm 미만', '30~40mm 미만', '40~50mm 미만', '50mm~60mm 미만', '60mm 이상'];
const rainRate = ['0', '0', '0', '0', '0', '0', '0', '0', '0'];
const rainDate = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const inflAmtCnt = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const inflAmnt = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const fcltyCpct = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const dsInflWqltBod: number[] = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const dsInflWqltCod: number[] = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const dsInflWqltSs: number[] = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const dsInflWqltTn: number[] = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const dsInflWqltTp: number[] = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltBodCnt = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltBod = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTocCnt = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltToc = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltSsCnt = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltSs = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTnCnt = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTn = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTpCnt = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTp = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltBodCnt = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltBod = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltCodCnt = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltCod = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltSsCnt = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltSs = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTnCnt = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTn = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTpCnt = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTp = [0, 0, 0, 0, 0, 0, 0, 0, 0];
const itemList = ['계', '3~10mm 미만', '10~20mm 미만', '20~30mm 미만', '30~40mm 미만', '40~50mm 미만', '50mm~60mm 미만', '60mm 이상'];
const rainRate = ['0', '0', '0', '0', '0', '0', '0', '0'];
const rainDate = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAmtCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAmnt = [0, 0, 0, 0, 0, 0, 0, 0];
const fcltyCpct = [0, 0, 0, 0, 0, 0, 0, 0];
const dsInflWqltBod: number[] = [0, 0, 0, 0, 0, 0, 0, 0];
const dsInflWqltCod: number[] = [0, 0, 0, 0, 0, 0, 0, 0];
const dsInflWqltSs: number[] = [0, 0, 0, 0, 0, 0, 0, 0];
const dsInflWqltTn: number[] = [0, 0, 0, 0, 0, 0, 0, 0];
const dsInflWqltTp: number[] = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltBodCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltBod = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTocCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltToc = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltSsCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltSs = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTnCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTn = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTpCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTp = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltBodCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltBod = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltCodCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltCod = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltSsCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltSs = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTnCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTn = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTpCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTp = [0, 0, 0, 0, 0, 0, 0, 0];
// Process the data and create rain management list
res.data.wqltObjs.forEach((item: RainManageListProps) => {
// 강우일
if(Number(item.infoRnDay) < 3){
/*if(Number(item.infoRnDay) < 3){
rainDate[1] = Number(rainDate[1] || 0) + 1;
inflAmtCnt[1] = Number(inflAmtCnt[1] || 0) + 1;
inflAmnt[1] = Number(inflAmnt[1] || 0) + Number(item.inflAmnt || 0);
@@ -1267,7 +1268,33 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
efflWqltTn[1] = Number(efflWqltTn[1] || 0) + Number(item.efflWqltTn || 0);
efflWqltTpCnt[1] = Number(efflWqltTpCnt[1] || 0) + 1;
efflWqltTp[1] = Number(efflWqltTp[1] || 0) + Number(item.efflWqltTp || 0);
}else if(Number(item.infoRnDay) >= 3 && Number(item.infoRnDay) < 10){
}*/
if(Number(item.infoRnDay) >= 3 && Number(item.infoRnDay) < 10){
rainDate[1] = Number(rainDate[1] || 0) + 1;
inflAmtCnt[1] = Number(inflAmtCnt[1] || 0) + 1;
inflAmnt[1] = Number(inflAmnt[1] || 0) + Number(item.inflAmnt || 0);
fcltyCpct[1] = 0;
inflAssctAftWqltBodCnt[1] = Number(inflAssctAftWqltBodCnt[1] || 0) + 1;
inflAssctAftWqltBod[1] = Number(inflAssctAftWqltBod[1] || 0) + Number(item.inflAssctAftWqltBod || 0);
inflAssctAftWqltTocCnt[1] = Number(inflAssctAftWqltTocCnt[1] || 0) + 1;
inflAssctAftWqltToc[1] = Number(inflAssctAftWqltToc[1] || 0) + Number(item.inflAssctAftWqltToc || 0);
inflAssctAftWqltSsCnt[1] = Number(inflAssctAftWqltSsCnt[1] || 0) + 1;
inflAssctAftWqltSs[1] = Number(inflAssctAftWqltSs[1] || 0) + Number(item.inflAssctAftWqltSs || 0);
inflAssctAftWqltTnCnt[1] = Number(inflAssctAftWqltTnCnt[1] || 0) + 1;
inflAssctAftWqltTn[1] = Number(inflAssctAftWqltTn[1] || 0) + Number(item.inflAssctAftWqltTn || 0);
inflAssctAftWqltTpCnt[1] = Number(inflAssctAftWqltTpCnt[1] || 0) + 1;
inflAssctAftWqltTp[1] = Number(inflAssctAftWqltTp[1] || 0) + Number(item.inflAssctAftWqltTp || 0);
efflWqltBodCnt[1] = Number(efflWqltBodCnt[1] || 0) + 1;
efflWqltBod[1] = Number(efflWqltBod[1] || 0) + Number(item.efflWqltBod || 0);
efflWqltCodCnt[1] = Number(efflWqltCodCnt[1] || 0) + 1;
efflWqltCod[1] = Number(efflWqltCod[1] || 0) + Number(item.efflWqltCod || 0);
efflWqltSsCnt[1] = Number(efflWqltSsCnt[1] || 0) + 1;
efflWqltSs[1] = Number(efflWqltSs[1] || 0) + Number(item.efflWqltSs || 0);
efflWqltTnCnt[1] = Number(efflWqltTnCnt[1] || 0) + 1;
efflWqltTn[1] = Number(efflWqltTn[1] || 0) + Number(item.efflWqltTn || 0);
efflWqltTpCnt[1] = Number(efflWqltTpCnt[1] || 0) + 1;
efflWqltTp[1] = Number(efflWqltTp[1] || 0) + Number(item.efflWqltTp || 0);
}else if(Number(item.infoRnDay) >= 10 && Number(item.infoRnDay) < 20){
rainDate[2] = Number(rainDate[2] || 0) + 1;
inflAmtCnt[2] = Number(inflAmtCnt[2] || 0) + 1;
inflAmnt[2] = Number(inflAmnt[2] || 0) + Number(item.inflAmnt || 0);
@@ -1283,7 +1310,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
inflAssctAftWqltTpCnt[2] = Number(inflAssctAftWqltTpCnt[2] || 0) + 1;
inflAssctAftWqltTp[2] = Number(inflAssctAftWqltTp[2] || 0) + Number(item.inflAssctAftWqltTp || 0);
efflWqltBodCnt[2] = Number(efflWqltBodCnt[2] || 0) + 1;
efflWqltBod[2] = Number(efflWqltBod[2] || 0) + Number(item.efflWqltBod || 0);
efflWqltBod[2] = Number(efflWqltBod[2] || 0) + Number(item.efflWqltBod || 0);
efflWqltCodCnt[2] = Number(efflWqltCodCnt[2] || 0) + 1;
efflWqltCod[2] = Number(efflWqltCod[2] || 0) + Number(item.efflWqltCod || 0);
efflWqltSsCnt[2] = Number(efflWqltSsCnt[2] || 0) + 1;
@@ -1292,7 +1319,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
efflWqltTn[2] = Number(efflWqltTn[2] || 0) + Number(item.efflWqltTn || 0);
efflWqltTpCnt[2] = Number(efflWqltTpCnt[2] || 0) + 1;
efflWqltTp[2] = Number(efflWqltTp[2] || 0) + Number(item.efflWqltTp || 0);
}else if(Number(item.infoRnDay) >= 10 && Number(item.infoRnDay) < 20){
}else if(Number(item.infoRnDay) >= 20 && Number(item.infoRnDay) < 30){
rainDate[3] = Number(rainDate[3] || 0) + 1;
inflAmtCnt[3] = Number(inflAmtCnt[3] || 0) + 1;
inflAmnt[3] = Number(inflAmnt[3] || 0) + Number(item.inflAmnt || 0);
@@ -1317,11 +1344,11 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
efflWqltTn[3] = Number(efflWqltTn[3] || 0) + Number(item.efflWqltTn || 0);
efflWqltTpCnt[3] = Number(efflWqltTpCnt[3] || 0) + 1;
efflWqltTp[3] = Number(efflWqltTp[3] || 0) + Number(item.efflWqltTp || 0);
}else if(Number(item.infoRnDay) >= 20 && Number(item.infoRnDay) < 30){
}else if(Number(item.infoRnDay) >= 30 && Number(item.infoRnDay) < 40){
rainDate[4] = Number(rainDate[4] || 0) + 1;
inflAmtCnt[4] = Number(inflAmtCnt[4] || 0) + 1;
inflAmnt[4] = Number(inflAmnt[4] || 0) + Number(item.inflAmnt || 0);
fcltyCpct[4] = 0;
fcltyCpct[4] = item.inflAmnt&&Number(item.inflAmnt) !== 0 ? Number(Math.round(Number(item.inflAmnt) / Number(item.fctCpc) * 10) / 10) : 0;
inflAssctAftWqltBodCnt[4] = Number(inflAssctAftWqltBodCnt[4] || 0) + 1;
inflAssctAftWqltBod[4] = Number(inflAssctAftWqltBod[4] || 0) + Number(item.inflAssctAftWqltBod || 0);
inflAssctAftWqltTocCnt[4] = Number(inflAssctAftWqltTocCnt[4] || 0) + 1;
@@ -1329,7 +1356,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
inflAssctAftWqltSsCnt[4] = Number(inflAssctAftWqltSsCnt[4] || 0) + 1;
inflAssctAftWqltSs[4] = Number(inflAssctAftWqltSs[4] || 0) + Number(item.inflAssctAftWqltSs || 0);
inflAssctAftWqltTnCnt[4] = Number(inflAssctAftWqltTnCnt[4] || 0) + 1;
inflAssctAftWqltTn[4] = Number(inflAssctAftWqltTn[4] || 0) + Number(item.inflAssctAftWqltTn || 0);
inflAssctAftWqltTn[4] = Number(inflAssctAftWqltTn[5] || 0) + Number(item.inflAssctAftWqltTn || 0);
inflAssctAftWqltTpCnt[4] = Number(inflAssctAftWqltTpCnt[4] || 0) + 1;
inflAssctAftWqltTp[4] = Number(inflAssctAftWqltTp[4] || 0) + Number(item.inflAssctAftWqltTp || 0);
efflWqltBodCnt[4] = Number(efflWqltBodCnt[4] || 0) + 1;
@@ -1338,15 +1365,15 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
efflWqltCod[4] = Number(efflWqltCod[4] || 0) + Number(item.efflWqltCod || 0);
efflWqltSsCnt[4] = Number(efflWqltSsCnt[4] || 0) + 1;
efflWqltSs[4] = Number(efflWqltSs[4] || 0) + Number(item.efflWqltSs || 0);
efflWqltTnCnt[4] = Number(efflWqltTnCnt[4] || 0) + 1;
efflWqltTnCnt[4] = Number(efflWqltTnCnt[5] || 0) + 1;
efflWqltTn[4] = Number(efflWqltTn[4] || 0) + Number(item.efflWqltTn || 0);
efflWqltTpCnt[4] = Number(efflWqltTpCnt[4] || 0) + 1;
efflWqltTpCnt[4] = Number(efflWqltTpCnt[5] || 0) + 1;
efflWqltTp[4] = Number(efflWqltTp[4] || 0) + Number(item.efflWqltTp || 0);
}else if(Number(item.infoRnDay) >= 30 && Number(item.infoRnDay) < 40){
}else if(Number(item.infoRnDay) >= 40 && Number(item.infoRnDay) < 50){
rainDate[5] = Number(rainDate[5] || 0) + 1;
inflAmtCnt[5] = Number(inflAmtCnt[5] || 0) + 1;
inflAmnt[5] = Number(inflAmnt[5] || 0) + Number(item.inflAmnt || 0);
fcltyCpct[5] = item.inflAmnt&&Number(item.inflAmnt) !== 0 ? Number(Math.round(Number(item.inflAmnt) / Number(item.fctCpc) * 10) / 10) : 0;
fcltyCpct[5] = 0;
inflAssctAftWqltBodCnt[5] = Number(inflAssctAftWqltBodCnt[5] || 0) + 1;
inflAssctAftWqltBod[5] = Number(inflAssctAftWqltBod[5] || 0) + Number(item.inflAssctAftWqltBod || 0);
inflAssctAftWqltTocCnt[5] = Number(inflAssctAftWqltTocCnt[5] || 0) + 1;
@@ -1367,7 +1394,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
efflWqltTn[5] = Number(efflWqltTn[5] || 0) + Number(item.efflWqltTn || 0);
efflWqltTpCnt[5] = Number(efflWqltTpCnt[5] || 0) + 1;
efflWqltTp[5] = Number(efflWqltTp[5] || 0) + Number(item.efflWqltTp || 0);
}else if(Number(item.infoRnDay) >= 40 && Number(item.infoRnDay) < 50){
}else if(Number(item.infoRnDay) >= 50 && Number(item.infoRnDay) < 60){
rainDate[6] = Number(rainDate[6] || 0) + 1;
inflAmtCnt[6] = Number(inflAmtCnt[6] || 0) + 1;
inflAmnt[6] = Number(inflAmnt[6] || 0) + Number(item.inflAmnt || 0);
@@ -1392,7 +1419,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
efflWqltTn[6] = Number(efflWqltTn[6] || 0) + Number(item.efflWqltTn || 0);
efflWqltTpCnt[6] = Number(efflWqltTpCnt[6] || 0) + 1;
efflWqltTp[6] = Number(efflWqltTp[6] || 0) + Number(item.efflWqltTp || 0);
}else if(Number(item.infoRnDay) >= 50 && Number(item.infoRnDay) < 60){
}else if(Number(item.infoRnDay) >= 60){
rainDate[7] = Number(rainDate[7] || 0) + 1;
inflAmtCnt[7] = Number(inflAmtCnt[7] || 0) + 1;
inflAmnt[7] = Number(inflAmnt[7] || 0) + Number(item.inflAmnt || 0);
@@ -1417,31 +1444,6 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
efflWqltTn[7] = Number(efflWqltTn[7] || 0) + Number(item.efflWqltTn || 0);
efflWqltTpCnt[7] = Number(efflWqltTpCnt[7] || 0) + 1;
efflWqltTp[7] = Number(efflWqltTp[7] || 0) + Number(item.efflWqltTp || 0);
}else if(Number(item.infoRnDay) >= 60){
rainDate[8] = Number(rainDate[8] || 0) + 1;
inflAmtCnt[8] = Number(inflAmtCnt[8] || 0) + 1;
inflAmnt[8] = Number(inflAmnt[8] || 0) + Number(item.inflAmnt || 0);
fcltyCpct[8] = 0;
inflAssctAftWqltBodCnt[8] = Number(inflAssctAftWqltBodCnt[8] || 0) + 1;
inflAssctAftWqltBod[8] = Number(inflAssctAftWqltBod[8] || 0) + Number(item.inflAssctAftWqltBod || 0);
inflAssctAftWqltTocCnt[8] = Number(inflAssctAftWqltTocCnt[8] || 0) + 1;
inflAssctAftWqltToc[8] = Number(inflAssctAftWqltToc[8] || 0) + Number(item.inflAssctAftWqltToc || 0);
inflAssctAftWqltSsCnt[8] = Number(inflAssctAftWqltSsCnt[8] || 0) + 1;
inflAssctAftWqltSs[8] = Number(inflAssctAftWqltSs[8] || 0) + Number(item.inflAssctAftWqltSs || 0);
inflAssctAftWqltTnCnt[8] = Number(inflAssctAftWqltTnCnt[8] || 0) + 1;
inflAssctAftWqltTn[8] = Number(inflAssctAftWqltTn[8] || 0) + Number(item.inflAssctAftWqltTn || 0);
inflAssctAftWqltTpCnt[8] = Number(inflAssctAftWqltTpCnt[8] || 0) + 1;
inflAssctAftWqltTp[8] = Number(inflAssctAftWqltTp[8] || 0) + Number(item.inflAssctAftWqltTp || 0);
efflWqltBodCnt[8] = Number(efflWqltBodCnt[8] || 0) + 1;
efflWqltBod[8] = Number(efflWqltBod[8] || 0) + Number(item.efflWqltBod || 0);
efflWqltCodCnt[8] = Number(efflWqltCodCnt[8] || 0) + 1;
efflWqltCod[8] = Number(efflWqltCod[8] || 0) + Number(item.efflWqltCod || 0);
efflWqltSsCnt[8] = Number(efflWqltSsCnt[8] || 0) + 1;
efflWqltSs[8] = Number(efflWqltSs[8] || 0) + Number(item.efflWqltSs || 0);
efflWqltTnCnt[8] = Number(efflWqltTnCnt[8] || 0) + 1;
efflWqltTn[8] = Number(efflWqltTn[8] || 0) + Number(item.efflWqltTn || 0);
efflWqltTpCnt[8] = Number(efflWqltTpCnt[8] || 0) + 1;
efflWqltTp[8] = Number(efflWqltTp[8] || 0) + Number(item.efflWqltTp || 0);
}
});
@@ -1488,7 +1490,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
rainDate[0] = (Number(rainDate[1]) || 0) + (Number(rainDate[2]) || 0) + (Number(rainDate[3]) || 0) +
(Number(rainDate[4]) || 0) + (Number(rainDate[5]) || 0) + (Number(rainDate[6]) || 0) +
(Number(rainDate[7]) || 0) + (Number(rainDate[8]) || 0);
(Number(rainDate[7]) || 0);
// 강수비율
for(let idx=0; idx<rainDate.length; idx++){
@@ -1532,16 +1534,16 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
inflAmnt[0] = calculateAverage(calculateTotal(inflAmnt), dataIsCount);
fcltyCpct[0] = calculateTotal(fcltyCpct);
inflAssctAftWqltBod[0] = Number((calculateTotal(inflAssctAftWqltBod)/8).toFixed(1));
inflAssctAftWqltToc[0] = Number((calculateTotal(inflAssctAftWqltToc)/8).toFixed(1));
inflAssctAftWqltSs[0] = Number((calculateTotal(inflAssctAftWqltSs)/8).toFixed(1));
inflAssctAftWqltTn[0] = Number((calculateTotal(inflAssctAftWqltTn)/8).toFixed(3));
inflAssctAftWqltTp[0] = Number((calculateTotal(inflAssctAftWqltTp)/8).toFixed(3));
efflWqltBod[0] = Number((calculateTotal(efflWqltBod)/8).toFixed(1));
efflWqltCod[0] = Number((calculateTotal(efflWqltCod)/8).toFixed(1));
efflWqltSs[0] = Number((calculateTotal(efflWqltSs as number[])/8).toFixed(1));
efflWqltTn[0] = Number((calculateTotal(efflWqltTn as number[])/8).toFixed(3));
efflWqltTp[0] = Number((calculateTotal(efflWqltTp as number[])/8).toFixed(3));
inflAssctAftWqltBod[0] = Number((calculateTotal(inflAssctAftWqltBod)/7).toFixed(1));
inflAssctAftWqltToc[0] = Number((calculateTotal(inflAssctAftWqltToc)/7).toFixed(1));
inflAssctAftWqltSs[0] = Number((calculateTotal(inflAssctAftWqltSs)/7).toFixed(1));
inflAssctAftWqltTn[0] = Number((calculateTotal(inflAssctAftWqltTn)/7).toFixed(3));
inflAssctAftWqltTp[0] = Number((calculateTotal(inflAssctAftWqltTp)/7).toFixed(3));
efflWqltBod[0] = Number((calculateTotal(efflWqltBod)/7).toFixed(1));
efflWqltCod[0] = Number((calculateTotal(efflWqltCod)/7).toFixed(1));
efflWqltSs[0] = Number((calculateTotal(efflWqltSs as number[])/7).toFixed(1));
efflWqltTn[0] = Number((calculateTotal(efflWqltTn as number[])/7).toFixed(3));
efflWqltTp[0] = Number((calculateTotal(efflWqltTp as number[])/7).toFixed(3));
// 최종 리스트
const filteredData = itemList.map((item, index) => ({
+16 -16
View File
@@ -28,7 +28,7 @@ export interface FacilityWaterQltyProps {
inflAssctAftWqltTp: string | '',
inflAssctBfrWqltTp: string | '',
efflWqltBod: string | '',
efflWqltCod: string | '',
efflWqltToc: string | '',
efflWqltSs: string | '',
efflWqltTn: string | '',
efflWqltTp: string | '',
@@ -104,7 +104,7 @@ export type modalExcelType = {
"유출SS(mg/L)": string;
"유출TN(mg/L)": string;
"유출TP(mg/L)": string;
"강우량(일)": string;
/* "강우량(mm/일)": string; */
}
/**====================================
@@ -133,7 +133,7 @@ const upHeadList1: TableUpperProps[] = [
{ 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: "efflWqltToc", 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 },
@@ -157,7 +157,7 @@ const upHeadList2: TableUpperProps[] = [
{ 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: "efflWqltToc", 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 },
@@ -185,7 +185,7 @@ const upHeadList3: TableUpperProps[] = [
{ 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: "efflWqltToc", 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 },
@@ -203,11 +203,11 @@ const upHeadListModalYear: TableUpperProps[] = [
{ 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: "efflWqltToc", 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" },
/* { id: "infoRnDay", title: "강우량(mm/일)", align: "right" }, */
];
// 처리시설 수질현황 헤더(모달-수질TMS)
@@ -409,8 +409,8 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
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.efflWqltToc){
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
}
if(item.inflAssctAftWqltBod){
item.inflAssctAftWqltBod = Number(Math.round(Number(item.inflAssctAftWqltBod) * 10)/10).toFixed(1);
@@ -427,8 +427,8 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
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.efflWqltToc){
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
}
return item;
});
@@ -456,7 +456,7 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
유입TN: item.inflAssctAftWqltTn,
유입TP: item.inflAssctAftWqltTp,
유출BOD: item.efflWqltBod,
유출TOC: item.efflWqltCod,
유출TOC: item.efflWqltToc,
유출SS: item.efflWqltSs,
유출TN: item.efflWqltTn,
유출TP: item.efflWqltTp,
@@ -610,8 +610,8 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
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.efflWqltToc){
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
}
if(item.inflAssctAftWqltBod){
item.inflAssctAftWqltBod = Number(Math.round(Number(item.inflAssctAftWqltBod) * 10)/10).toFixed(1);
@@ -628,8 +628,8 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
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.efflWqltToc){
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
}
if(item.tpInflWqltBod){
+18 -16
View File
@@ -13,8 +13,8 @@ const FlowRateSearchLabelArray:string[] = ['구분', '시도', '시군구', '용
export type flowRateListProps = {
bscFctCd : string,
sidoNm : string,
sggNm : string,
sido : string,
gugun : string,
bscFctNm : string,
daddr : string,
fctCpc : number,
@@ -50,13 +50,13 @@ export interface ExcelType {
}
export type modalExcelType = {
날짜: string,
"날짜": string,
"총유입량(m³/일)": number | '',
"하수유입량(m³/일)": number | '',
"연계처리량(m³/일)": number | '',
"총인반류수량(m³/일)": number | '',
"방류량(m³/일)": number | '',
"강우량": number | string | '',
/* "강우량(mm/일)": number | string | '', */
}
/**
* (2) 모달
@@ -93,8 +93,8 @@ export type FlowRateModalProps = {
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: "sido", title: "시도", upName:"upChangeRe", row:1 },
{ id: "gugun", 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},
@@ -131,8 +131,8 @@ const upHeadList3:TableUpperProps[] = [
{ 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: "sido", title: "시도", upName:"upChangeRe2", row:1 },
{ id: "gugun", 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 },
@@ -157,7 +157,7 @@ const upHeadListFlowRateModal:TableUpperProps[] = [
{ id: "sumFlow", title: "연계처리량(m³/일)", align:"right"},
{ id: "returnAmnt", title: "총인 반류수량(m³/일)", align:"right"},
{ id: "efflAmnt", title: "방류량(m³/일)", align:"right"},
{ id: "infoRnDay", title: "강우량", align:"right"}
/* { id: "infoRnDay", title: "강우량(mm/일)", align:"right"} */
]
const modalFlowRateListYear:FlowRateModalProps[] = [
@@ -268,11 +268,8 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow
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;
@@ -286,8 +283,8 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow
단위유역: item.lgbsn,
중권역: item.mdmbsn,
환경청: item.rgnNm,
시도: item.sidoNm,
시군구: item.sggNm,
시도: item.sido,
시군구: item.gugun,
시설이름: item.bscFctNm,
주소: item.daddr,
용량: item.fctCpc,
@@ -300,7 +297,6 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow
});
}
console.log('excelDownList' , excelDownList);
set((state: FlowRateSearchType) => ({
...state,
FlowRateList: pageSize<5000?{
@@ -316,8 +312,14 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow
searchFlowRateModalList: async (bscFctCd: string, searchYear: string) => {
const res = await fetchFlowRateModalList(bscFctCd, searchYear);
const data = res.data;
const tmpData:FlowRateModalProps[] = [];
data.forEach((item: FlowRateModalProps) => {
if(item.infoRnDay && item.infoRnDay.toString().trim() === 'x') {
item.infoRnDay = '';
}
});
// facilityPrecipitation의 rainEffectDay 계산 로직을 적용
for(let idx = 0; idx < data.length; idx++) {
const item = data[idx];
+102 -225
View File
@@ -1,4 +1,3 @@
import DataForm from "@/app/components/common/DataForm";
import type { TableUpperProps } from "../dashboard";
import { getFetch } from "@/app/components/api";
export type { TableUpperProps };
@@ -29,21 +28,14 @@ export type SewageOccurProps = {
mdmbsn : string,
msrDt : string,
}
export type modalTableType = { msrDt: string,waterUsage: number,swageChangePercent: number,estimationSewage: number};
export type SewageOccurDetailProps = {
msrDt : string,
waterUsage : number,
swageChangePercent : number,
estimationSewage : number,
cnt : number,
sum : number,
yr:string,
usege:number
}
/**====================================
* Store - data
====================================*/
/**
* (1) 메인페이지
*/
// 검색단
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
@@ -120,159 +112,13 @@ const upHeadList3:TableUpperProps[] = [
const upHeadListSewageOccurDetail:TableUpperProps[] = [
{ id: "msrDt", title: "년월" },
{ id: "waterUsage", title: "물사용량(m³/일)" },
{ id: "swageChangePercent", title: "오수전환율" },
{ id: "swageChangePercent", title: "오수전환율(%)" },
{ id: "estimationSewage", title: "오수발생량 추정(m³/일)", row:0, rowSpan:2 },
];
const sewageOccurList:SewageOccurProps[] = [
]
const sewageOccurList:SewageOccurProps[] = []
const tempSewageOccurList:SewageOccurDetailProps[] = [
{
msrDt: '2024-01',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 60,
},
{
msrDt: '2024-02',
waterUsage: 106,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2024-03',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2024-04',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2024-05',
waterUsage: 100,
swageChangePercent: 10,
estimationSewage: 80,
},
{
msrDt: '2024-06',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2024-07',
waterUsage: 100,
swageChangePercent: 580,
estimationSewage: 80,
},
{
msrDt: '2024-08',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2024-09',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2024-10',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2024-11',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2024-12',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2025-01',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2025-02',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2025-03',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2025-04',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2025-05',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2025-06',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2025-07',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2025-08',
waterUsage: 100,
swageChangePercent: 0.8,
estimationSewage: 80,
},
{
msrDt: '2025-09',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2025-10',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2025-11',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
{
msrDt: '2025-12',
waterUsage: 100,
swageChangePercent: 80,
estimationSewage: 80,
},
]
const tempSewageOccurList:modalTableType[] = []
/**====================================
* Store - API
@@ -280,11 +126,6 @@ const tempSewageOccurList:SewageOccurDetailProps[] = [
const fetchSewageOccurList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
// 20250701임시시
console.log("partCd", partCd);
console.log("nameCd", nameCd);
console.log("fcltCpct", fcltCpct);
console.log("operationValue", operationValue);
console.log("fcltyNm", fcltyNm);
console.log("searchYear", searchYear);
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
@@ -299,11 +140,18 @@ const fetchSewageOccurList = async (pageNo: number, pageSize: number, searchYear
return { data: res.data, count: res.count } */
}
const fetchSewageOccurDetailList = async (bscFctCd: string, searchYear: string) => {
const url = '/fclt/flow/' + bscFctCd + '/' + searchYear;
const res = await getFetch('fo', url);
return { data: res.data, count: res.count }
}
/**====================================
* Store - expaort
====================================*/
export type SewageOccurActions = {
searchSewageOccurList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
searchSewageOccurDetailList: (bscFctCd: string, searchYear: string) => void;
}
export type SewageOccurType = {
@@ -325,7 +173,7 @@ export type SewageOccurType = {
SewageOccurDetail : {
isInit: boolean;
upHeadListSewageOccurDetail: TableUpperProps[];
gridListSewageOccurDetail: SewageOccurDetailProps[];
gridListSewageOccurDetail: modalTableType[];
}
}
@@ -352,14 +200,6 @@ export const sewageOccurInitState: SewageOccurType = {
}
}
const dataFormSetting=(item : SewageOccurProps)=> {
DataForm({ type: 'float1', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
DataForm({ type: 'float1', column: 'waterUsage', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'estimationSewage', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'sewageInputYear', item: item as unknown as Record<string, unknown>});
DataForm({ type: 'float2', column: 'sewageInputChungchun', item: item as unknown as Record<string, unknown>});
}
export type SewageOccurStore = SewageOccurType & SewageOccurActions;
// Add type definitions for API responses
@@ -375,9 +215,7 @@ type FlowResponse = {
count: number;
}
type SetStateFunction = (state: SewageOccurType | ((state: SewageOccurType) => SewageOccurType)) => void;
export const sewageOccurReducer:(set:SetStateFunction)=>SewageOccurActions=(set: SetStateFunction) => {
export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
return {
searchSewageOccurList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
const res = await fetchSewageOccurList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
@@ -388,67 +226,32 @@ export const sewageOccurReducer:(set:SetStateFunction)=>SewageOccurActions=(set:
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
item.waterUsage = item.fctCpc * 0.6;
item.swageChangePercent = 80;
item.estimationSewage = item.waterUsage * (item.swageChangePercent/100);
const bscFctCd = item.bscFctCd;
const url2 = '/fclt/flow/' + bscFctCd + '/' + searchYear;
const res2 = await getFetch('fo', url2) as FlowResponse;
const sumFlow = res2.data.reduce((acc: number, curr: FlowDataItem) => Number(acc) + Number(curr.inflAmnt), 0);
let sumChungcunDay = 0;
let chungcunSumFlow = 0;
let totWaterUsage = 0;
res2.data.forEach((item: FlowDataItem) => {
if(Number(item.infoRnDay) ===0){
chungcunSumFlow += Number(item.inflAmnt);
sumChungcunDay += 1;
}else{
console.log(item.bscFctCd +' day : ' +' '+item.msrDt);
}
totWaterUsage += Number(item.inflAmnt);
});
item.sewageInputYear = sumFlow/res2.count;
item.sewageInputChungchun = chungcunSumFlow===0?0:(chungcunSumFlow / sumChungcunDay);
const avg = totWaterUsage /res2.count;
item.waterUsage = parseFloat((avg * 0.65).toFixed(2));
item.sewageInputYear = parseFloat(avg.toFixed(2));
item.sewageInputChungchun = parseFloat((chungcunSumFlow===0?0:(chungcunSumFlow / sumChungcunDay)).toFixed(2));
item.estimationSewage = parseFloat((item.waterUsage * (item.swageChangePercent/100)).toFixed(2));
return item;
}));
console.log('calData : ', calData);
const excelDownList: ExcelType[] = [];
if(pageSize>5000){
calData.forEach(item => {
dataFormSetting(item)
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
/* item.ctpvNm = 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.daddr,
시설용량: item.fctCpc,
물사용량: item.waterUsage,
오수전환율: item.swageChangePercent,
오수발생량추정: item.estimationSewage,
연간하수유입량: item.sewageInputYear,
청천시하수유입량: item.sewageInputChungchun,
});
});
}else{
calData.forEach((item: SewageOccurProps) => {
dataFormSetting(item)
/* item.sidoNmNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; */
});
}
set((state: SewageOccurType) => ({
// 조회 데이터 설정
set((state: any) => ({
...state,
SewageOccur: pageSize<5000?{
...state.SewageOccur,
@@ -456,7 +259,81 @@ export const sewageOccurReducer:(set:SetStateFunction)=>SewageOccurActions=(set:
sewageOccurCount: res.count,
}:{
...state.SewageOccur,
excelList: excelDownList,
excelList: [],
}
}))
},
searchSewageOccurDetailList: async (bscFctCd: string, searchYear: string) => {
const res = await fetchSewageOccurDetailList(bscFctCd, searchYear);
const monthData: SewageOccurDetailProps[] = [];
let tot = 0, cnt= 0
res.data.forEach((item: FlowDataItem) => {
const month = item.msrDt?.substring(4, 6);
const monthIdx = month ? Number(month) - 1 : -1;
if (monthIdx >= 0) {
if (typeof monthData[monthIdx] === 'object') {
monthData[monthIdx].sum += Number(item.inflAmnt);
monthData[monthIdx].cnt++;
} else {
monthData[monthIdx] = {cnt:1, sum:Number(item.inflAmnt), yr:item.msrDt.substring(0,4), usege:0};
}
}
tot += Number(item.inflAmnt)
cnt++
})
console.log('tot', tot, cnt, tot/cnt, tot/cnt*0.65);
const tableData:modalTableType[] = []
let maxWaterUsage = 0;
let minWaterUsage = 9999999999;
let avgWaterUsage = 0;
monthData.forEach((item, index) => {
item.usege = item.sum/item.cnt *0.65
tableData.push({
msrDt: item.yr+'-'+(index+1>10?String(index+1):'0'+(index+1)),
waterUsage: Math.round(item.usege*100) /100,
swageChangePercent: Math.round((item.usege/item.usege*0.8) * 100) / 100,
estimationSewage: Math.round(item.usege*0.8 * 100) / 100
})
if (item.usege > maxWaterUsage) {
maxWaterUsage = item.usege;
}
if (item.usege < minWaterUsage) {
minWaterUsage = item.usege;
}
});
avgWaterUsage = tot/cnt*0.65
const newData= [
{
msrDt: '평균',
waterUsage: Math.round(avgWaterUsage*100) /100,
swageChangePercent: 0.8,
estimationSewage: Math.round(avgWaterUsage*0.8*100) /100,
},
{
msrDt: '최대',
waterUsage: Math.round(maxWaterUsage*100) /100,
swageChangePercent: 0.8,
estimationSewage: Math.round(maxWaterUsage*0.8*100) /100,
},
{
msrDt: '최소',
waterUsage: Math.round(minWaterUsage*100) /100,
swageChangePercent: 0.8,
estimationSewage: Math.round(minWaterUsage*0.8*100) /100,
},
...tableData
]
set((state: SewageOccurType) => ({
...state,
SewageOccurDetail: {
...state.SewageOccurDetail,
gridListSewageOccurDetail: newData,
}
}))
},
+14 -12
View File
@@ -1,13 +1,19 @@
import { LoginApi } from '@/src/entities/auth/api/login-service';
import { createStore } from 'zustand/vanilla';
import { CommonReducer, commonState, type CommonStore, type CommonType } from './common';
import { dashBoardReducer, dashBoardInitState, type DashBoardStore, type DashBoardType } from './dashboard';
import { dashBoardInitState, dashBoardReducer, type DashBoardStore, type DashBoardType } from './dashboard';
import {
facilityPrecipitationInitState,
facilityPrecipitationReducer,
type FacilityPrecipitationStore, type FacilityPrecipitationType
} from './facilityPrecipitation';
import { planSewageInitState, planSewageReducer, type PlanSewageStore, type PlanSewageType } from './planSewage';
import {
facilityWaterQltyInitState,
facilityWaterQltyReducer,
type FacilityWaterQltyStore, type FacilityWaterQltyType
} from './facilityWaterQlty';
import { flowRateSearchInitState, flowRateSearchReducer, type FlowRateSearchStore, type FlowRateSearchType } from './flowRate';
import { planSewageInitState, planSewageReducer, type PlanSewageStore, type PlanSewageType } from './planSewage';
import {
processAreaInitState,
processAreaReducer,
@@ -18,11 +24,12 @@ import {
processFacilityReducer,
type ProcessFacilityStore, type ProcessFacilityType
} from './processFacility';
import { tableActionsExport, tableStateExport, type tableState, type tableType } from './publicReuseFaciltyInsert/index';
import {
facilityWaterQltyInitState,
facilityWaterQltyReducer,
type FacilityWaterQltyStore, type FacilityWaterQltyType
} from './facilityWaterQlty';
rdiInitState,
rdiReducer,
type RdiStore, type RdiType
} from './rdi';
import {
sewageOccurInitState,
sewageOccurReducer,
@@ -33,12 +40,6 @@ import {
underWaterReducer,
type UnderWaterStore, type UnderWaterType
} from './underWaterInput';
import {
rdiInitState,
rdiReducer,
type RdiStore, type RdiType
} from './rdi';
import { tableActionsExport, tableStateExport, type tableState, type tableType } from './publicReuseFaciltyInsert/index';
export type FoStore = CommonStore & tableType & DashBoardStore & ProcessFacilityStore & ProcessAreaStore & FlowRateSearchStore & FacilityPrecipitationStore & FacilityWaterQltyStore & PlanSewageStore & SewageOccurStore & UnderWaterStore & RdiStore;
export type FoState = CommonType & tableState & ProcessFacilityType & ProcessAreaType & FacilityPrecipitationType & FlowRateSearchType & DashBoardType & FacilityWaterQltyType & PlanSewageType & SewageOccurType & UnderWaterType & RdiType;
@@ -58,6 +59,7 @@ export const StoreZus =
}
) => {
return createStore<FoStore>()((set) => {
LoginApi.login({userId: "admin1gmail", password: "test1234!"})
return {
...initState,
...CommonReducer(set),
+4
View File
@@ -11,6 +11,10 @@ const compat = new FlatCompat({
const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"),
{rules:{
// other rules..
"@typescript-eslint/no-explicit-any": "off",
}},
];
export default eslintConfig;
-5
View File
@@ -1,5 +0,0 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -20,7 +20,7 @@ export class TokenManager {
public setToken(key: string, value: string): void {
setCookie(key, value, {
secure: window.location.protocol === "https:",
secure: location.protocol === "https:",
sameSite: "lax",
});
}
+8 -8
View File
@@ -1,13 +1,13 @@
NEXT_PUBLIC_SITE_ID = SN
NEXT_PUBLIC_PORT = 11302
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11302
NEXT_PUBLIC_ADDR_URL = http://con.mind-one.co.kr:11082
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver_swl
NEXT_PUBLIC_DC_URL = https://apigateway.rsonesoft.com #자료관 데이터
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_PORT = 3000
NEXT_PUBLIC_PROXY_HOST = https://sn.hasuon.or.kr
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000
NEXT_PUBLIC_ADDR_URL = http://con.mind-one.co.kr:11082
NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl
NEXT_PUBLIC_DC_URL = https://apigateway.rsonesoft.com #자료관 데이터
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
@@ -376,7 +376,7 @@ export const MsSwageMhlCol = [
{ id: 'vrtc_len', title: '세로길이(m)' },
// { id: 'ang_dir', title: '표고' },
{ id: 'altd_vl', title: '표고(EL.m)' },
{ id: 'dpthl_vl', title: '심도(m)' },
{ id: 'dpthlVl', title: '심도(m)' },
// { id: 'inst_mng_no', title: '기관관리번호' }
];
export const MsSwageMhlCol2 = [
@@ -507,7 +507,7 @@ export const ExclnSewagePumpCol2 = [
// { id: 'instMngNo', title: '기관관리번호' },
]
// 오수펌프장
export const DrtwSewagePumpCol = [
export const DrtwSewagePumpCol1 = [
// { id: 'fid', title: 'FID' },
// { id: 'geom', title: 'geometry' },
// { id: 'ftreSmbolCd', title: '지형지물부호코드' },
@@ -574,16 +574,16 @@ export const stofcbrCol = [
{ id: 'drtn_angl', title: '방향각도(°)' },
]
export const stofcbrCol2 = [
// { id: 'ftreSmbolCd', title: '지형지물부호코드' },
{ id: 'fcltMngNo', title: '시설관리번호' },
// { id: 'pbadmsEmdCd', title: '행정읍면동코드' },
// { id: 'ftre_smbol_cd', title: '지형지물부호코드' },
{ id: 'pbadmsEmdCd', title: '시설관리번호' },
// { id: 'pbadms_emd_cd', title: '행정읍면동코드' },
{ id: 'mapshtNo', title: '도엽번호' },
// { id: 'mngInstCd', title: '관리기관코드' },
// { id: 'mng_inst_cd', title: '관리기관코드' },
{ id: 'instlYmd', title: '설치일자' },
// { id: 'fcltyShpCd', title: '시설물형태코드' },
// { id: 'fclty_shp_cd', title: '시설물형태코드' },
{ id: 'worflwWallHgt', title: '월류벽높이(m)' },
// { id: 'mhlExstYnCd', title: '맨홀존재여부코드' },
// { id: 'swageMhlFtreSmbolCd', title: '하수맨홀지형지물부호코드' },
// { id: 'mhl_exst_yn_cd', title: '맨홀존재여부코드' },
// { id: 'swage_mhl_ftre_smbol_cd', title: '하수맨홀지형지물부호코드' },
{ id: 'swageMhlMngNo', title: '하수맨홀관리번호' },
{ id: 'drtnAngl', title: '방향각도(°)' },
]
@@ -39,13 +39,14 @@ const MsSwagePpl = ({ featureData, onSaveClick }: { featureData: any, onSaveClic
{ lwpoCd: "203", lwpoCdNm: "청소, 준설" },
{ lwpoCd: "204", lwpoCdNm: "단순보수" },
];
// const BIZ_TY_CD = useBizByFcltStore(state => state.BIZ_TY_CD);
const BIZ_TY_CD = [
{ lwpoCd: "SV", lwpoCdNm: "용역" },
{ lwpoCd: "SF", lwpoCdNm: "자체" },
{ lwpoCd: "SC", lwpoCdNm: "공사" },
];
console.log('BIZ_SE_CD', BIZ_SE_CD);
// 마운트 및 업데이트 시 API 호출
useEffect(() => {
@@ -6,7 +6,7 @@ import { useGisContext } from "@common/business_components/ui/map/Gis";
import { Button } from "@common/components/ui";
import { useEffect, useRef, useState, useCallback, useMemo } from "react";
import { getLayerContentComponent } from "./components/common";
import { SwtrmtFcltCol, SwtrmtFcltCol2, SwtrmtPrcsZoneCol, SwtrmtPrcsZoneCol2, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, MsSwagePplCol2, ExclnSewagePumpCol, ExclnSewagePumpCol2, DrtwSewagePumpCol, DrtwSewagePumpCol2, MsSwageMhlCol, MsSwageMhlCol2, stofcbrCol, stofcbrCol2, MS_SWAGE_MHL_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from "./components/common/table";
import { SwtrmtFcltCol, SwtrmtFcltCol2, SwtrmtPrcsZoneCol, SwtrmtPrcsZoneCol2, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, MsSwagePplCol2, ExclnSewagePumpCol, ExclnSewagePumpCol2, DrtwSewagePumpCol1, DrtwSewagePumpCol2, MsSwageMhlCol, MsSwageMhlCol2, stofcbrCol, stofcbrCol2, MS_SWAGE_MHL_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from "./components/common/table";
import InfilChart from './components/popupComponent/chart/infilChart';
import RdiiChart from './components/popupComponent/chart/rdiiChart';
import { useInfilChartModalStore, useRdiiChartModalStore } from "./components/popupComponent/chartModalStore";
@@ -14,6 +14,7 @@ import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue';
import { codeMapper } from "./components/common/codeMapper";
// TODO:
const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, featureData: any }) => {
const { gisMap } = useGisContext() as unknown as { checkedLayerIds: React.MutableRefObject<number[]>; treeData: { lyrSn: number }[] | null; gisCore: any; gisMap: any; };
const [layerNm, setLayerNm] = useState<string>(""); // 레이어 이름 상태
@@ -58,124 +59,59 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
let result = null;
const layers = gisMap.getLayers().getArray(); // gisMap에서 모든 레이어 가져오기
let featureLayer: { get: (key: string) => any }; // 피처가 속한 레이어를 찾기 위한 변수
layers.some((layer: any) => {
layers.forEach((layer: any) => {
const source = layer.getSource();
// console.log('실행됨3 source', source);
// console.log('실행됨3 featureData', featureData);
// console.log('실행됨3 featureData.fid', featureData.fid);
// if (source && featureData && featureData.fid) {
// featureLayer = layer; // 피처가 속한 레이어 찾기
// }
if (source && source.hasFeature && featureData
&& typeof featureData.getId === 'function' && source.hasFeature(featureData)) {
featureLayer = layer; // 피처가 속한 레이어 찾기
return true; // 반복 종료
}
return false;
});
if (featureData['ol_uid']) {
// Gis 레이어 클릭 이벤트
setIsClicked(true);
console.log('gis data', featureData.values_);
const lyrTyNm = featureData.id_.split('.')[0];
if (lyrTyNm === 'tb_ms_swage_ppl') {
result = '하수관로';
setHeadlist(MsSwagePplCol);
setLayerSpecificNm(featureData.values_.fclt_mng_no);
}
else if (lyrTyNm === 'tb_ms_swage_mhl') {
result = '하수맨홀';
setHeadlist(MsSwageMhlCol);
setLayerSpecificNm(featureData.values_.fclt_mng_no);
}
else if (lyrTyNm === 'tb_ms_swage_pmstn') { // 하수펌프장
// console.log("featureLayer.get('lyrTyNm');", featureLayer.get('lyrTyNm'));
// SearchModal 클릭 이벤트
if (featureLayer.get('lyrNm') === null) {
setIsClicked(false);
if (featureData.lyrTypeNm === 'tb_il_swage_prcs_fclt') result = '하수처리시설';
else if (featureData.lyrTypeNm === 'tb_ms_swage_prcs_zone') result = '하수처리구역';
else if (featureData.lyrTypeNm === 'tb_ms_stofcbr') result = '우수토실';
else if (featureData.lyrTypeNm === 'om_dt_untrt_swg_rain') result = '중점우수토실';
else if (featureData.lyrTypeNm === 'tb_ms_swage_ppl') result = '하수관로';
else if (featureData.lyrTypeNm === 'tb_ms_swage_pmstn') {
const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장');
console.log('값 비교', featureData.values_.usg_cd.trim(), drtwPumpCode?.val);
if (drtwPumpCode && featureData.values_.usg_cd.trim() === drtwPumpCode.val) {
setIsDrtwSewagePump(false);
setHeadlist(ExclnSewagePumpCol);
}
else {
} else {
setIsDrtwSewagePump(true);
setHeadlist(DrtwSewagePumpCol);
}
setLayerSpecificNm(featureData.values_.fclt_mng_no);
result = '하수펌프장';
}
else if (lyrTyNm === 'tb_il_swage_prcs_fclt') {
result = '하수처리시설';
setHeadlist(SwtrmtFcltCol);
setLayerSpecificNm(featureData.values_.swtrmt_fclt_cd);
}
else if (lyrTyNm === 'tb_ms_swage_prcs_zone') {
result = '하수처리구역';
setHeadlist(SwtrmtPrcsZoneCol);
setLayerSpecificNm(featureData.values_.swtrmt_fclt_cd);
}
else if (lyrTyNm === 'tb_ms_stofcbr') {
result = '우수토실';
setHeadlist(stofcbrCol);
setLayerSpecificNm(featureData.values_.fclt_mng_no);
}
else if (lyrTyNm === 'om_dt_untrt_swg_rain') {
result = '중점우수토실';
setHeadlist(untrtSwgRainCol1);
setHeadlist2(untrtSwgRainCol2);
setLayerSpecificNm(featureData.values_.manage_no);
}
else result = featureLayer.get('lyrNm');
else if (featureData.lyrTypeNm === 'tb_ms_swage_mhl') result = '하수맨홀';
}
else {
// SearchModal 클릭 이벤트
setIsClicked(false);
console.log('SearchModal data', featureData);
const lyrTyNm = featureData.lyrTypeNm;
console.log('실행됨4 SearchModal 클릭 이벤트', lyrTyNm);
console.log('실행됨4 SearchModal 클릭 이벤트 featureData', featureData);
if (featureData.lyrTypeNm === 'tb_ms_swage_ppl') {
result = '하수관로';
setHeadlist(MsSwagePplCol2)
setLayerSpecificNm(featureData.swtrmtFcltCd);
}
else if (featureData.lyrTypeNm === 'tb_ms_swage_mhl') {
result = '하수맨홀';
setHeadlist(MsSwageMhlCol2)
setLayerSpecificNm(featureData.fcltMngNo);
}
else if (featureData.lyrTypeNm === 'tb_ms_swage_pmstn') { // 하수펌프장
// Gis 레이어 클릭 이벤트
setIsClicked(true);
const lyrTyNm = featureLayer.get('lyrTyNm');
if (lyrTyNm === 'tb_il_swage_prcs_fclt') result = '하수처리시설';
else if (lyrTyNm === 'tb_ms_swage_prcs_zone') result = '하수처리구역';
else if (lyrTyNm === 'tb_ms_stofcbr') result = '우수토실';
else if (lyrTyNm === 'om_dt_untrt_swg_rain') result = '중점우수토실';
else if (lyrTyNm === 'tb_ms_swage_ppl') result = '하수관로';
else if (lyrTyNm === 'tb_ms_swage_pmstn') {
const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장');
if (drtwPumpCode && featureData.usgCd.trim() === drtwPumpCode.val) {
console.log('오수펌프장');
console.log('값 비교', featureData.values_.usg_cd.trim(), drtwPumpCode?.val);
if (drtwPumpCode && featureData.values_.usg_cd.trim() === drtwPumpCode.val) {
setIsDrtwSewagePump(false);
setHeadlist(ExclnSewagePumpCol2)
}
else {
console.log('빗물펌프장');
} else {
setIsDrtwSewagePump(true);
setHeadlist(DrtwSewagePumpCol2)
}
setLayerSpecificNm(featureData.fcltMngNo);
result = '하수펌프장';
}
else if (featureData.lyrTypeNm === 'tb_il_swage_prcs_fclt') {
result = '하수처리시설';
setHeadlist(SwtrmtFcltCol2)
setLayerSpecificNm(featureData.swtrmtFcltCd);
}
else if (featureData.lyrTypeNm === 'tb_ms_swage_prcs_zone') {
result = '하수처리구역';
setHeadlist(SwtrmtPrcsZoneCol2);
setLayerSpecificNm(featureData.swtrmtFcltCd);
}
else if (featureData.lyrTypeNm === 'tb_ms_stofcbr') {
result = '우수토실';
setHeadlist(stofcbrCol2)
setLayerSpecificNm(featureData.fcltMngNo);
}
// else if (featureData.lyrTypeNm === 'om_dt_untrt_swg_rain') result = '중점우수토실';
else if (lyrTyNm === 'tb_ms_swage_mhl') result = '하수맨홀';
else result = featureLayer.get('lyrNm');
}
return result;
// return featureLayer.get('lyrNm'); // 레이어 이름 출력
};
useEffect(() => {
@@ -186,10 +122,8 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
const selectedLayerName = getSelectedLayers(); // 레이어 이름 가져오기
setLayerNm(selectedLayerName); // 상태 업데이트
// console.log('gis data', featureData.values_);
let data;
if (featureData['ol_uid']) data = featureData.values_; // Gis 레이어 클릭 이벤트일 때
else data = featureData; // SearchModal 클릭 이벤트일 때
console.log('gis data', featureData.values_);
const data = featureData.values_;
// 하수맨홀인 경우 용도코드를 텍스트로 변환
if (selectedLayerName === '하수맨홀' && data) {
@@ -205,11 +139,16 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
// 🎯 기본 데이터 포맷팅
const formattedData = formatDisplayData(data);
if (featureData?.values_?.fclt_mng_no) setLayerSpecificNm(featureData.values_.fclt_mng_no);
else if (featureData?.values_?.swtrmt_fclt_cd) setLayerSpecificNm(featureData.values_.swtrmt_fclt_cd);
else setLayerSpecificNm(featureData?.values_?.manage_no);
setFetchData(formattedData);
setTableData(formattedData);
switch (selectedLayerName) {
case '하수관로':
if (isClicked) setHeadlist(MsSwagePplCol)
else setHeadlist(MsSwagePplCol2)
setButtonChk(true)
// ✅ codeMapper 사용하여 API 결과도 변환
@@ -217,8 +156,12 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
layerName: selectedLayerName,
data: { ...formattedData }
}));
// setFetchData(mappedData);
// setTableData(mappedData);
break;
case '하수맨홀':
if (isClicked) setHeadlist(MsSwageMhlCol)
else setHeadlist(MsSwageMhlCol2)
setButtonChk(true)
// ✅ codeMapper 사용하여 API 결과도 변환
@@ -226,26 +169,46 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
layerName: selectedLayerName,
data: { ...formattedData }
}));
// setFetchData(mappedData);
// setTableData(mappedData);
break;
case '하수펌프장':
if (isDrtwSewagePump) {
if (isClicked) setHeadlist(DrtwSewagePumpCol1)
else setHeadlist(DrtwSewagePumpCol2)
} else {
if (isClicked) setHeadlist(ExclnSewagePumpCol)
else setHeadlist(ExclnSewagePumpCol2)
}
setButtonChk(true)
setTableData(codeMapper({
layerName: selectedLayerName,
data: { ...formattedData }
}));
// setFetchData(mappedData);
// setTableData(mappedData);
break;
case '하수처리시설':
if (isClicked) setHeadlist(SwtrmtFcltCol)
else setHeadlist(SwtrmtFcltCol2)
setButtonChk(false)
break;
case '하수처리구역':
if (isClicked) setHeadlist(SwtrmtPrcsZoneCol)
else setHeadlist(SwtrmtPrcsZoneCol2)
setButtonChk(false)
break;
case '우수토실':
if (isClicked) setHeadlist(stofcbrCol)
else setHeadlist(stofcbrCol2)
setButtonChk(true)
setIsMainSsc(false)
break;
case '중점우수토실':
setHeadlist(untrtSwgRainCol1)
setHeadlist2(untrtSwgRainCol2)
setButtonChk(false)
setIsMainSsc(true)
// 🎯 processedData도 포맷팅하여 설정
@@ -1,199 +0,0 @@
import React from 'react';
import { MS_SWAGE_MHL_USE_CODES, MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_USE_CODES } from '../components/common/table';
import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox';
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { SelectBox } from '@common/business_components/ui';
import { Button, Input, Label } from '@common/components';
import SwagePpl from './swagePpl';
import SwagePrcsFclt from './swagePrcsFclt';
import SwagePrcsZone from './swagePrcsZone';
import SwageMhl from './swageMhl';
import SwagePmstn from './swagePmstn';
// 기본정보 '구분' 선택 목록
export const BASIC_TYPES = [
{ val: "tb_ms_swage_ppl", text: "하수관로" },
{ val: "tb_il_swage_prcs_fclt", text: "하수처리시설" },
{ val: "tb_ms_swage_prcs_zone", text: "하수처리구역" },
{ val: "tb_ms_swage_mhl", text: "하수맨홀" },
{ val: "tb_ms_swage_pmstn", text: "하수펌프장" },
{ val: "tb_ms_stofcbr", text: "우수토실" },
];
interface BasicTabProps {
open?: boolean;
basicType: string;
city: number;
sgg: number;
start1: string;
start2: string;
end1: string;
end2: string;
var1: string;
var2: string;
yearFilter: { start: string; end: string; };
handleSearch: () => void;
// onOpenChange?: (open: boolean) => void;
// onFeatureSelect?: (row: any) => void;
// setTableData?: (data: any[]) => void;
// setTableCount?: (count: number) => void;
setBasicType: (type: string) => void;
setCity: (city: number) => void;
setSgg: (sgg: number) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
setStart1: (value: string) => void;
setStart2: (value: string) => void;
setEnd1: (value: string) => void;
setEnd2: (value: string) => void;
setVar1: (value: string) => void;
setVar2: (value: string) => void;
}
const BasicTab: React.FC<BasicTabProps> = ({
// open,
basicType,
city,
sgg,
start1,
start2,
end1,
end2,
var1,
var2,
yearFilter,
handleSearch,
// onOpenChange,
// onFeatureSelect,
// setTableData,
// setTableCount,
setBasicType,
setCity,
setSgg,
setYearFilter,
setStart1,
setStart2,
setEnd1,
setEnd2,
setVar1,
setVar2,
}) => {
return (
<div className="relative border rounded-lg p-6 mt-4 w-full h-[10vh]">
{/* 구분 */}
<div className="mb-3 flex items-center justify-between gap-4">
<div className="flex items-center">
<SelectBox
className="w-[150px] mr-3"
selectClass="rounded-lg bg-white"
label="구분"
selectArray={BASIC_TYPES}
onSelectValue={(value: string | number) =>
setBasicType(String(value))
}
value={basicType}
selectContentClass="z-[101]"
/>
</div>
</div>
{/* 분기처리: 하수관로 */}
{basicType === "tb_ms_swage_ppl" && (
<SwagePpl
var1={var1}
var2={var2}
start1={start1}
end1={end1}
yearFilter={yearFilter}
setVar1={setVar1}
setVar2={setVar2}
setStart1={setStart1}
setEnd1={setEnd1}
setYearFilter={setYearFilter}
handleSearch={handleSearch}
/>
)}
{/* 분기처리: 하수처리시설 */}
{basicType === "tb_il_swage_prcs_fclt" && (
<SwagePrcsFclt
var1={var1}
start1={start1}
start2={start2}
end1={end1}
end2={end2}
yearFilter={yearFilter}
setVar1={setVar1}
setStart1={setStart1}
setStart2={setStart2}
setEnd1={setEnd1}
setEnd2={setEnd2}
setYearFilter={setYearFilter}
handleSearch={handleSearch}
/>
)}
{/* 분기처리: 하수처리구역 */}
{basicType === "tb_ms_swage_prcs_zone" && (
<SwagePrcsZone
var1={var1}
var2={var2}
city={city}
sgg={sgg}
setVar1={setVar1}
setVar2={setVar2}
setCity={setCity}
setSgg={setSgg}
handleSearch={handleSearch}
/>
)}
{/* 분기처리: 하수맨홀 */}
{basicType === "tb_ms_swage_mhl" && (
<SwageMhl
var1={var1}
start1={start1}
end1={end1}
yearFilter={yearFilter}
setVar1={setVar1}
setStart1={setStart1}
setEnd1={setEnd1}
setYearFilter={setYearFilter}
handleSearch={handleSearch}
/>
)}
{/* 분기처리: 하수펌프장 */}
{basicType === "tb_ms_swage_pmstn" && (
<SwagePmstn
start1={start1}
start2={start2}
end1={end1}
end2={end2}
yearFilter={yearFilter}
setStart1={setStart1}
setStart2={setStart2}
setEnd1={setEnd1}
setEnd2={setEnd2}
setYearFilter={setYearFilter}
handleSearch={handleSearch}
/>
)}
{/* 분기처리: 우수토실 */}
{basicType === "tb_ms_stofcbr" && (
<div className="mb-3">
{/* 설치년도 */}
<div className="flex items-center mb-2">
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
onChange={range => setYearFilter({ ...yearFilter, start: range.start, end: range.end })}
startLabel="설치년도"
endLabel=""
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
</div>
</div>
</div>
)}
</div>
);
};
export default React.memo(BasicTab);
@@ -1,162 +0,0 @@
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { SelectBox } from '@common/business_components/ui';
import { Button, Input, Label } from '@common/components';
import React from 'react';
//import { useDcTree, flattenFolders, useSggCd, useCityCd } from './components/searchModalReportApi';
// import { useBizByFcltStore } from "../../../store/StoreProvider";
// 운영정보 '구분' 선택 목록
// const WORK_TYPES = [
// { val: "maintenance", text: "보수 및 갱신" },
// { val: "cleaning", text: "청소 및 준설" },
// { val: "inspection", text: "점검 및 진단" },
// ];
export const WORK_TYPES = [
{ val: "200", text: "보수 및 갱신(개대체)" },
{ val: "201", text: "보수 및 갱신(유지보수)" },
{ val: "204", text: "보수 및 갱신(단순보수)" },
{ val: "100", text: "점검 및 진단" },
{ val: "203", text: "청소 및 준설" },
];
// const BIZ_SE_CD = useBizByFcltStore(state => state.BIZ_SE_CD);
export const BIZ_SE_CD = [
{ lwpoCd: "100", lwpoCdNm: "관로기술진단" },
{ lwpoCd: "200", lwpoCdNm: "개대체" },
{ lwpoCd: "201", lwpoCdNm: "유지보수" },
{ lwpoCd: "203", lwpoCdNm: "청소, 준설" },
{ lwpoCd: "204", lwpoCdNm: "단순보수" },
];
// const BIZ_TY_CD = useBizByFcltStore(state => state.BIZ_TY_CD);
export const BIZ_TY_CD = [
{ lwpoCd: "0", lwpoCdNm: "전체" },
{ lwpoCd: "SV", lwpoCdNm: "용역" },
{ lwpoCd: "SF", lwpoCdNm: "자체" },
{ lwpoCd: "SC", lwpoCdNm: "공사" },
];
export const BIZ_TY_CD_SELECT_ARRAY = BIZ_TY_CD.map(item => ({
val: item.lwpoCd,
text: item.lwpoCdNm,
}));
// 운영정보 - 사업 현황
export const operationTableHeadlist = [
{ id: "bizNm", title: "사업명" },
{ id: "flfmtBgngYmd", title: "수행시작일자" },
{ id: "flfmtEndYmd", title: "수행종료일자" },
{ id: "flfmtYr", title: "수행년도" },
{ id: "bizTyCd", title: "사업유형" },
{ id: "bizAmt", title: "사업금액" },
];
// 운영정보 - 보수 및 갱신 결과표
export const operationMaintenanceTableHeadlist = [
{ id: "fcltMngNo", title: "관리번호" },
{ id: "usgCd", title: "용도" },
{ id: "mqltCd", title: "재질" },
{ id: "pdmt", title: "관경(mm)" },
{ id: "prlg", title: "연장(m)" },
{ id: "instlYmd", title: "설치일자" },
// { id: "instlYmd", title: "사업구분" },
];
// 운영정보 - 청소 및 준설 결과표
export const operationCleaningTableHeadlist = [
{ id: "fcltMngNo", title: "관리번호" },
{ id: "usgCd", title: "용도" },
{ id: "mqltCd", title: "재질" },
{ id: "pdmt", title: "관경(mm)" },
{ id: "prlg", title: "연장(m)" },
{ id: "instlYmd", title: "설치일자" },
];
// 운영정보 - 점검 및 진단 결과표
export const operationInspectionTableHeadlist = [
{ id: "fcltMngNo", title: "관리번호" },
{ id: "usgCd", title: "용도" },
{ id: "mqltCd", title: "재질" },
{ id: "pdmt", title: "관경(mm)" },
{ id: "prlg", title: "연장(m)" },
{ id: "instlYmd", title: "설치일자" },
{ id: "strct_stat_grd", title: "구조적 상태등급" },
{ id: "oper_stat_grd", title: "운영적 상태등급" },
];
interface OperationTabProps {
open: boolean;
workType: string;
var1: string;
var2: string;
yearFilter: { start: string; end: string; };
handleSearch: () => void;
// onOpenChange: (open: boolean) => void;
// setTableData: (data: any[]) => void;
// setTableCount: (count: number) => void;
setWorkType: (type: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
setVar1: (value: string) => void;
setVar2: (value: string) => void;
}
const OperationTab: React.FC<OperationTabProps> = ({
open,
workType,
var1,
var2,
yearFilter,
handleSearch,
// onOpenChange,
// setTableData,
// setTableCount,
setWorkType,
setVar1,
setVar2,
setYearFilter,
}) => {
return (
<div className="relative flex flex-col border rounded-lg p-6 mt-4 w-full h-[10vh]">
<div className="flex items-center mb-3">
<SelectBox
className="w-80 mr-8"
selectClass="rounded-lg bg-white text-xl"
label="업무구분"
selectArray={WORK_TYPES.map((w) => ({
val: w.val,
text: w.text,
}))}
onSelectValue={(val) => setWorkType(String(val))}
value={workType}
selectContentClass="z-[101]"
/>
</div>
<div className="flex items-center mb-6">
<Label className="mr-2 w-auto text-xl text-gray-600">사업명</Label>
<Input
className="w-[100px] !text-xl placeholder:text-center mr-4"
placeholder="입력"
value={var1}
onChange={(e) => { setVar1(e.target.value); }}
/>
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
onChange={range => setYearFilter({ ...yearFilter, start: range.start, end: range.end })}
startLabel="수행기간"
endLabel=""
/>
<SelectBox
className="ml-8 w-60 mr-8"
selectClass="rounded-lg bg-white text-xl"
label="사업 유형"
selectArray={BIZ_TY_CD_SELECT_ARRAY}
value={var2}
onSelectValue={(val) => {
setVar2(String(val));
}}
selectContentClass="z-[101]"
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
</div>
</div>
</div>
)
};
export default React.memo(OperationTab);
@@ -1,109 +0,0 @@
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { SelectBox } from '@common/business_components/ui';
import { Button, Input } from '@common/components';
import React from 'react';
//import { useDcTree, flattenFolders, useSggCd, useCityCd } from './components/searchModalReportApi';
import { type SelectDataType } from '../commonStore';
import { useCityCd, useSggCd } from '../components/searchModalReportApi';
// import { useBizByFcltStore } from "../../../store/StoreProvider";
// // 하수도정비 기본계획 보고서
export const reportTableHeadlist = [
{ id: "no", title: "NO" },
{ id: "sido", title: "시도" },
{ id: "sigungu", title: "시군구" },
{ id: "approvalYear", title: "승인년도" },
{ id: "plantZoneGugun", title: "구분" },
{ id: "reportGubun", title: "보고서구분" },
{ id: "fileName", title: "파일명" },
{ id: "regDate", title: "등록일자" },
];
interface BasicTabProps {
open?: boolean;
gubun: string;
sidos: SelectDataType[];
ctpvCd: string | number;
sigungu: string;
filteredSiguns: SelectDataType[];
yearFilter: { start: string; end: string; };
handleSearch: () => void;
handleCtpvCdChange: (val: string | number) => void;
// onOpenChange?: (open: boolean) => void;
// onFeatureSelect?: (row: any) => void;
// setTableData?: (data: any[]) => void;
// setTableCount?: (count: number) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
setGubun: (gubun: string) => void;
setSigungu: (sigungu: string) => void;
}
const ReportTab: React.FC<BasicTabProps> = ({
open,
gubun,
sidos,
ctpvCd,
sigungu,
filteredSiguns = [{ val: '0', text: '전체', sido: '0' }],
yearFilter,
handleSearch,
handleCtpvCdChange,
// onOpenChange,
// onFeatureSelect,
// setTableData,
// setTableCount,
setYearFilter,
setGubun,
setSigungu,
}) => {
return (
<div className="relative flex flex-col border rounded-lg p-6 mt-4 w-full h-[10vh]">
<div className="flex items-center mb-3">
<SelectBox
className="w-[150px] mr-8"
selectClass="rounded-lg bg-white"
label="시도"
selectArray={sidos}
value={ctpvCd}
onSelectValue={handleCtpvCdChange}
selectContentClass="z-[101]"
/>
<SelectBox
className="w-48"
selectClass="w-48 rounded-lg bg-white truncate"
label="시군구"
selectArray={filteredSiguns}
value={sigungu}
onSelectValue={val => setSigungu(String(val))}
selectContentClass="z-[101]"
/>
</div>
<div className="flex items-center mb-6">
<label className="inline-block w-auto whitespace-nowrap text-xl text-gray-600 mr-2">구분</label>
<Input
className='!text-xl w-[100px] placeholder:text-center mr-8'
placeholder="입력"
value={gubun}
onChange={(e) => { setGubun(e.target.value); }}
/>
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
onChange={range => setYearFilter({ ...yearFilter, start: range.start, end: range.end })}
startLabel="승인년도"
endLabel=""
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
</div>
</div>
</div>
);
};
export default React.memo(ReportTab);
File diff suppressed because it is too large Load Diff
@@ -1,38 +0,0 @@
// 우수토실
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { Button } from '@common/components';
import React from 'react';
interface StofcbrProps {
yearFilter: { start: string; end: string };
setYearFilter: (filter: { start: string; end: string }) => void;
handleSearch: () => void;
}
const Stofcbr: React.FC<StofcbrProps> = ({
yearFilter,
setYearFilter,
handleSearch,
}) => {
return (
<div className="mb-3">
{/* 설치년도 */}
<div className="flex items-center mb-2">
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
onChange={range => setYearFilter({ ...yearFilter, start: range.start, end: range.end })}
startLabel="설치년도"
endLabel=""
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
</div>
</div>
</div>
);
};
export default React.memo(Stofcbr);
@@ -1,94 +0,0 @@
// 하수맨홀
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { Button, Input, Label } from '@common/components';
import React from 'react';
import { MS_SWAGE_MHL_USE_CODES } from '../components/common/table';
import { SelectBox } from '@common/business_components/ui';
interface SwageMhlProps {
var1: string;
start1: string;
end1: string;
yearFilter: { start: string; end: string };
setVar1: (value: string) => void;
setStart1: (value: string) => void;
setEnd1: (value: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
handleSearch: () => void;
}
const SwageMhl: React.FC<SwageMhlProps> = ({
var1,
start1,
end1,
yearFilter,
setVar1,
setStart1,
setEnd1,
setYearFilter,
handleSearch,
}) => {
return (
<div className="mb-3">
<div className="mb-2 flex items-center">
{/* 설치년도 */}
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
onChange={(range) =>
setYearFilter({
...yearFilter,
start: range.start,
end: range.end,
})
}
startLabel="설치년도"
endLabel=""
/>
{/* 용도 */}
<SelectBox
className="ml-8 w-60 mr-8"
selectClass="rounded-lg bg-white text-xl"
label="용도"
selectArray={MS_SWAGE_MHL_USE_CODES}
value={var1}
onSelectValue={(val) => {
setVar1(String(val));
}}
selectContentClass="z-[101]"
/>
{/* 하수맨홀 구경 */}
<Label className="mr-2 w-auto text-xl text-gray-600">구경(mm)</Label>
<Input
className="w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
value={start1}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setStart1(val);
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
className="mr-8 w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
value={end1}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd1(val);
}}
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
</div>
</div>
</div>
);
};
export default React.memo(SwageMhl);
@@ -1,102 +0,0 @@
// 하수펌프장
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { Button, Input, Label } from '@common/components';
import React from 'react';
interface SwagePmstnProps {
start1: string;
start2: string;
end1: string;
end2: string;
yearFilter: { start: string; end: string };
setStart1: (value: string) => void;
setStart2: (value: string) => void;
setEnd1: (value: string) => void;
setEnd2: (value: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
handleSearch: () => void;
}
const SwagePmstn: React.FC<SwagePmstnProps> = ({
start1,
start2,
end1,
end2,
yearFilter,
setStart1,
setStart2,
setEnd1,
setEnd2,
setYearFilter,
handleSearch,
}) => {
return (
<div className="mb-3">
<div className="flex items-center mb-2">
{/* 설치년도 */}
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
onChange={range => setYearFilter({ ...yearFilter, start: range.start, end: range.end })}
startLabel="설치년도"
endLabel=""
/>
{/* 일일처리용량 - 오수맨홀 */}
<Label className="ml-8 mr-2 w-auto text-xl text-gray-600">일일처리용량(㎥)</Label>
<Input
className="w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
value={start1}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setStart1(val);
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
className="mr-8 w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
value={end1}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd1(val);
}}
/>
{/* 양수능력 - 우수맨홀 */}
<Label className="mr-2 w-auto text-xl text-gray-600">
양수능력(m²/d)
</Label>
<Input
className="w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
value={start2}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setStart2(val);
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
className="mr-8 w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
value={end2}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd2(val);
}}
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
</div>
</div>
</div>
);
};
export default React.memo(SwagePmstn);
@@ -1,132 +0,0 @@
// 하수관로
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { SelectBox } from '@common/business_components/ui';
import { Button, Input, Label } from '@common/components';
import React from 'react';
import { MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_USE_CODES } from '../components/common/table';
interface SwagePplProps {
var1: string;
var2: string;
start1: string;
end1: string;
yearFilter: { start: string; end: string };
setVar1: (value: string) => void;
setVar2: (value: string) => void;
setStart1: (value: string) => void;
setEnd1: (value: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
handleSearch: () => void;
}
const SwagePpl: React.FC<SwagePplProps> = ({
var1,
var2,
start1,
end1,
yearFilter,
setVar1,
setVar2,
setStart1,
setEnd1,
setYearFilter,
handleSearch,
}) => {
return (
<div className="mb-6">
<div className="mb-2 flex items-center">
{/* 설치년도 */}
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
onChange={(range) =>
setYearFilter({
...yearFilter,
start: range.start,
end: range.end,
})
}
startLabel="설치년도"
endLabel=""
/>
{/* 용도 */}
<SelectBox
className="ml-8 w-60 mr-8"
selectClass="rounded-lg bg-white text-xl"
label="용도"
selectArray={MS_SWAGE_PPL_USE_CODES}
value={var1}
onSelectValue={(val) => {
setVar1(String(val));
}}
selectContentClass="z-[101]"
/>
{/* 재질 */}
<SelectBox
className="w-60 mr-8"
selectClass="rounded-lg bg-white text-xl"
label="재질"
selectArray={MS_SWAGE_PPL_CODES}
value={var2}
onSelectValue={(val) => {
setVar2(String(val));
}}
selectContentClass="z-[101]"
/>
{/* 관경 */}
<Label className="mr-2 w-auto text-xl text-gray-600">관경(mm)</Label>
<Input
className="w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={var1}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setVar1(val);
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
className="mr-8 w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={end1}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd1(val);
}}
/>
{/* 연장 */}
<Label className="mr-2 w-auto text-xl text-gray-600">연장(m)</Label>
<Input
className="w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={start1}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setStart1(val);
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
className="mr-8 w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={end1}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd1(val);
}}
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
</div>
</div>
</div>
);
};
export default React.memo(SwagePpl);
@@ -1,121 +0,0 @@
// 하수처리시설
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { Button, Input, Label } from '@common/components';
import React from 'react';
interface SwagePrcsFcltProps {
var1: string;
start1: string;
start2: string;
end1: string;
end2: string;
yearFilter: { start: string; end: string };
setVar1: (value: string) => void;
setStart1: (value: string) => void;
setStart2: (value: string) => void;
setEnd1: (value: string) => void;
setEnd2: (value: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
handleSearch: () => void;
}
const SwagePrcsFclt: React.FC<SwagePrcsFcltProps> = ({
var1,
start1,
start2,
end1,
end2,
yearFilter,
setVar1,
setStart1,
setStart2,
setEnd1,
setEnd2,
setYearFilter,
handleSearch,
}) => {
return (
<div className="mb-3">
{/* 가동개시일자 */}
<div className="mb-2 flex items-center">
<Label className="mr-2 w-auto text-xl text-gray-600">가동개시일자</Label>
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
onChange={(range) =>
setYearFilter({
...yearFilter,
start: range.start,
end: range.end,
})
}
startLabel=""
endLabel=""
/>
{/* 시설용량 */}
<Label className="ml-8 mr-2 w-auto text-xl text-gray-600">시설용량(㎥/d)</Label>
<Input
className="w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={start1}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setStart1(val);
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
className="mr-8 w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={end1}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd1(val);
}}
/>
{/* 처리구역 면적 */}
<Label className="mr-2 w-auto text-xl text-gray-600">처리구역 면적(m²)</Label>
<Input
className="w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={start2}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setStart2(val);
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
className="mr-8 w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={end2}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd2(val);
}}
/>
{/* 하수처리시설명 */}
<Label className="mr-2 w-auto text-xl text-gray-600">하수처리시설명</Label>
<Input
className="mr-8 w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
value={var1}
onChange={(e) => {
setVar1(e.target.value);
}}
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
</div>
</div>
</div>
);
};
export default React.memo(SwagePrcsFclt);
@@ -1,69 +0,0 @@
// 하수처리구역
import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox';
import { Button, Input, Label } from '@common/components';
import React from 'react';
interface swagePrcsZoneProps {
var1: string;
var2: string;
city: number;
sgg: number;
setVar1: (value: string) => void;
setVar2: (value: string) => void;
setCity: (value: number) => void;
setSgg: (value: number) => void;
handleSearch: () => void;
}
const swagePrcsZone: React.FC<swagePrcsZoneProps> = ({
var1,
var2,
city,
sgg,
setVar1,
setVar2,
setCity,
setSgg,
handleSearch,
}) => {
return (
<div className="mb-3">
<div className="mb-2 flex items-center">
<SidoSigunguSelectBox
sido={city}
sigungu={sgg}
onSidoChange={(sidoId) => {
setCity(sidoId);
setSgg(0);
}}
onSigunguChange={setSgg}
/>
<Label className="mr-2 w-auto text-xl text-gray-600">하수처리구역명</Label>
<Input
className="mr-8 w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
value={var1}
onChange={(e) => {
setVar1(e.target.value);
}}
/>
<Label className="mr-2 w-auto text-xl text-gray-600">하수처리시설명</Label>
<Input
className='!text-xl w-[120px] placeholder:text-center mr-8'
placeholder="입력"
value={var2}
onChange={(e) => {
setVar2(e.target.value);
}}
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
</div>
</div>
</div>
);
};
export default React.memo(swagePrcsZone);
@@ -4,6 +4,7 @@ import ContentLayout from '@/components/ui/contentLayout'
import { GovSidoSigunguSearchForm } from '@/components/ui/govSidoSigunguSearchForm'
import { DatePicker, DateMonthPicker, Form, SearchFormRight, SelectBox } from '@common/business_components/ui'
import ListDiv from '@common/business_components/ui/list_div'
import { SelectBox2 } from '@common/business_components/ui/select/index-2'
import { Button, Label } from '@common/components/ui'
import { useEffect, useState, type ReactNode } from 'react'
import LoadingOverlay from '@/components/ui/LoadingBar'
@@ -258,8 +259,8 @@ const BaseLayout = ({
setRtnEnvPartSidoValue={(val) => setCtpvCd?.(val)}
setRtnEnvPartSigunValue={setSigungu} // 선택된 시군구 값을 받을 콜백 함수 전달
>
<SelectBox label={"하수처리장"} value={selectedSwageTreatmentPlant} selectArray={treatmentFacilityOptions} className="col-span-3" selectClass="rounded-lg bg-white truncate" onSelectValue={(val) => onSwageTreatmentPlantChange?.(val)} selectContentClass="z-[101]" />
{/* <SelectBox label={"하수처리구역"} value={selectedSwageProcessingZone} selectArray={processingZoneOptions} className="col-span-3" selectClass="rounded-lg bg-white truncate" onSelectValue={(val) => onSwageProcessingZoneChange?.(val)} selectContentClass="z-[101]" /> */}
<SelectBox2 label={"하수처리장"} value={selectedSwageTreatmentPlant} selectArray={treatmentFacilityOptions} className="col-span-3" selectClass="rounded-lg bg-white truncate" onSelectValue={(val) => onSwageTreatmentPlantChange?.(val)} />
{/* <SelectBox2 label={"하수처리구역"} value={selectedSwageProcessingZone} selectArray={processingZoneOptions} className="col-span-3" selectClass="rounded-lg bg-white truncate" onSelectValue={(val) => onSwageProcessingZoneChange?.(val)} /> */}
</GovSidoSigunguSearchForm>
{selectBox?.searchChk ? <SearchFormRight><Button size="sm" onClick={() => selectBox.onSearchClick?.()}>조회</Button></SearchFormRight> : null}
</div>
+4 -22
View File
@@ -5,29 +5,11 @@ const BASE_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || '';
export const getData = async (url: string, data?: object): Promise<any> => {
const res = await fetch(url.startsWith('/') ? `${url}` : `${BASE_URL}/${url}`, {
method: "GET",
body: JSON.stringify(data),
});
if (res.ok) {
try {
// 응답이 비어있는지 확인
const contentLength = res.headers.get('content-length');
if (contentLength === '0') {
return null;
}
// 응답 텍스트를 먼저 가져와서 빈 문자열인지 확인
const text = await res.text();
if (!text || text.trim() === '') {
return null;
}
// JSON 파싱 시도
const data = JSON.parse(text);
return data;
} catch (error) {
console.error('JSON parsing error:', error);
// JSON 파싱에 실패한 경우, 원본 텍스트 또는 null 반환
throw new Error('Invalid JSON response from server');
}
const data = await res.json();
return data;
}
throw new Error('Failed to fetch data');
};
@@ -111,7 +93,7 @@ export const getCmsData = async (url: string, data?: object): Promise<any> => {
throw new Error('Failed to fetch data');
};
export function getCookie(name: string) {
export function getCookie(name:string) {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match && match[2]) {
return decodeURIComponent(match[2]);
@@ -1,5 +1,5 @@
import React, { useMemo } from "react";
import { SelectBox } from '@common/business_components/ui'
import { SelectBox2 } from "@common/business_components/ui/select/index-2";
interface Option {
id: number;
@@ -138,23 +138,21 @@ export function SidoSigunguSelectBox({
return (
<div className={`flex items-center justify-center ${className} mr-8`}>
<SelectBox
<SelectBox2
className="w-[150px] mr-8"
selectClass="rounded-lg bg-white"
label="시도"
selectArray={sidoList.map(opt => ({ val: opt.id, text: opt.name }))}
value={sido}
onSelectValue={val => onSidoChange(Number(val))}
selectContentClass="z-[101]"
/>
<SelectBox
<SelectBox2
className="w-48"
selectClass="w-48 rounded-lg bg-white truncate"
label="시군구"
selectArray={sigunguList.map(opt => ({ val: opt.id, text: opt.name }))}
value={sigungu}
onSelectValue={val => onSigunguChange(Number(val))}
selectContentClass="z-[101]"
/>
</div>
);
@@ -1,5 +1,5 @@
import React from "react";
import { SelectBox } from '@common/business_components/ui'
import { SelectBox2 } from "@common/business_components/ui/select/index-2";
interface YearRangeSelectBoxProps {
start: string;
@@ -89,24 +89,22 @@ export function YearRangeSelectBox({
return (
<div className={`flex items-center ${className}`}>
<SelectBox
<SelectBox2
className="flex-1 mr-3"
selectClass={selectClass}
label={startLabel}
selectArray={getStartYearArray()}
onSelectValue={val => onChange({ start: String(val), end })}
value={start}
selectContentClass="z-[101]"
/>
<span className="font-semibold text-xl mx-2">~</span>
<SelectBox
<SelectBox2
className="flex-1 ml-1"
selectClass={selectClass}
label={endLabel}
selectArray={getEndYearArray()}
onSelectValue={val => onChange({ start, end: String(val) })}
value={end}
selectContentClass="z-[101]"
/>
</div>
);
+11 -17
View File
@@ -456,7 +456,7 @@ const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
if (isPrcsFclt) {
if (viewMode == 'list') {
return (
<div style={{overflowY:'auto'}}>
<>
<div className="flex justify-between items-center mb-4">
<Title title="하수처리시설 현황" />
</div>
@@ -470,11 +470,11 @@ const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
cellClick={hasuCellClick}
onPageChange={setHasuPage}
/>
</div>
</>
)
} else {
return (
<div style={{overflowX:'hidden'}}>
<>
<div className="flex justify-between items-center mb-4">
<Title title="하수처리시설 상세정보" />
</div>
@@ -497,7 +497,7 @@ const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
cellClick={() => { }}
onPageChange={() => { }}
/>
</div>
</>
)
}
}
@@ -528,7 +528,7 @@ const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
} else {
// 재이용시설 목록
return (
<div style={{overflowY:'auto'}}>
<>
<div className="flex justify-between items-center">
<Title title="하수재이용시설 현황" />
{/* <div className="flex gap-2 mt-8">
@@ -550,7 +550,7 @@ const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
>
<HeadMakeColSpan upHeadList={pbnstSttn.pbnstSttNodeList} />
</UiTable>
</div>
</>
);
}
}
@@ -600,7 +600,7 @@ const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
} else {
// 중수도시설 목록
return (
<div style={{overflowY:'auto'}}>
<>
<div className="flex justify-between items-center">
<Title title="중수도시설 현황" />
{/* <div className="flex gap-2 mt-8">
@@ -622,7 +622,7 @@ const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
>
<HeadMakeColSpan upHeadList={rswtSttn.rswtSttNodeList} />
</UiTable>
</div>
</>
);
}
}
@@ -636,7 +636,7 @@ const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
} else {
// 온배수시설 목록
return (
<div style={{overflowY:'auto'}}>
<>
<div className="flex justify-between items-center">
<Title title="온배수시설 현황" />
{/* <div className="flex gap-2 mt-8">
@@ -658,7 +658,7 @@ const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
>
<HeadMakeColSpan upHeadList={htdflSttn.htdflSttNodeList} />
</UiTable>
</div>
</>
);
}
}
@@ -668,13 +668,7 @@ const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
return (
viewMode == 'nothing' ? <></> :
<NewWindowPortal
onClose={memoizedOnClose}
title="시설 상세 정보"
width={viewMode == 'list' ? window.screen.availWidth : 1100}
height={viewMode == 'list' ? window.screen.availHeight : layerId == '하수처리시설' && viewMode == 'detail' ? 450 : 900}
scrollbars='yes'
resizable='no'>
<NewWindowPortal onClose={memoizedOnClose} title="시설 상세 정보">
{/* 체크된 레이어에 따른 조건부 렌더링 */}
{renderConditionalContent()}
</NewWindowPortal>
+5 -18
View File
@@ -27,13 +27,9 @@ interface NewWindowPortalProps {
children: React.ReactNode;
onClose: () => void;
title?: string;
width?: number;
height?: number;
resizable?: string;
scrollbars?: string;
}
const NewWindowPortal: React.FC<NewWindowPortalProps> = ({ children, onClose, title = "", width = 900, height = 800, resizable = "yes", scrollbars = "yes" }) => {
const NewWindowPortal: React.FC<NewWindowPortalProps> = ({ children, onClose, title = "Detail" }) => {
const [container, setContainer] = useState<HTMLElement | null>(null);
const newWindowRef = useRef<Window | null>(null);
const onCloseRef = useRef(onClose);
@@ -50,23 +46,13 @@ const NewWindowPortal: React.FC<NewWindowPortalProps> = ({ children, onClose, ti
useEffect(() => {
// 이미 창이 열려있으면 새로 열지 않음
if (newWindowRef.current && !newWindowRef.current.closed) return;
// 브라우저 화면 정보
const screenLeft = window.screenLeft ?? window.screenX;
const screenTop = window.screenTop ?? window.screenY;
const screenWidth = window.innerWidth ?? document.documentElement.clientWidth;
const screenHeight = window.innerHeight ?? document.documentElement.clientHeight;
// 중앙 위치 계산
const left = screenLeft + (screenWidth - width) / 2;
const top = screenTop + (screenHeight - height) / 2;
// 1. 새 창을 열고 참조를 저장합니다.
const popupOptions = `width=${width},height=${height},left=${left}, top=${top}, resizable=${resizable},scrollbars=${scrollbars}`;
newWindowRef.current = window.open('', title, popupOptions);
newWindowRef.current = window.open('', title, 'width=900,height=800,resizable=yes,scrollbars=yes');
if (newWindowRef.current) {
newWindowRef.current.document.title = title;
// 2. React 컴포넌트를 마운트할 컨테이너 div를 생성하여 새 창의 body에 추가합니다.
const div = newWindowRef.current.document.createElement('div');
newWindowRef.current.document.body.appendChild(div);
@@ -74,6 +60,7 @@ const NewWindowPortal: React.FC<NewWindowPortalProps> = ({ children, onClose, ti
// 3. 메인 창의 스타일을 새 창으로 복사합니다. (매우 중요)
copyStyles(document, newWindowRef.current.document);
// 4. 사용자가 창을 닫을 때 부모에게 알리기 위한 이벤트 리스너를 설정합니다.
// const handleUnload = () => {
// onClose();
-158
View File
@@ -1,158 +0,0 @@
"use client";
import Gis from "@common/business_components/ui/map/Gis";
import { useEffect, useRef, useState, useCallback } from "react";
import { mapService } from "../service";
import NewWindowPopup from "../newWindowPopup";
import GisApp from "@common/business_components/ui/map/lib/gis.core";
const Map = () => {
const [treeData, setTreeData] = useState([]); // 초기값을 객체 또는 null로 설정
const gisMaps = useRef<any | null>(null);
const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태
const [isSearchModalOpen, setIsSearchModalOpen] = useState(true); // SearchModal 열림 상태
const [featureData, setFeatureData] = useState(null); // 선택된 피쳐 데이터
const [checkedLayers, setCheckedLayers] = useState<string[]>([]);
const [checkedLayersData, setCheckedLayersData] = useState<any[]>([]);
const fetchData = async () => {
try {
const response = await mapService.getLyrStngs();
setTreeData(response); // API 응답 저장
} catch (error) {
console.error("데이터 불러오기 실패:", error);
}
};
// 팝업 닫기 핸들러를 useCallback으로 메모이제이션
const handlePopupClose = useCallback(() => {
setIsOpen(false);
setFeatureData(null);
}, []);
// 컴포넌트 마운트 시 1회 실행
useEffect(() => {
fetchData();
}, []);
// 체크된 레이어 정보를 받는 핸들러
const handleCheckedLayersChange = (checkedIds: string[], checkedNodesData: any[]) => {
setCheckedLayers(checkedIds);
setCheckedLayersData(checkedNodesData);
};
// SearchModal, GisContent 등에서 호출
const onFeatureSelect = (data: any) => {
const map = gisMaps.current;
if (!map) {
console.warn("지도가 초기화되지 않았습니다.");
return;
}
// 항상 같은 select 객체 사용
const select = GisApp.Module.select as any;
if (!select) return;
// 1. 기존 선택 초기화
select.resetSelectedFeature();
// 2. data가 OpenLayers Feature 인스턴스인지 확인
let foundFeature: any = 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: any) => {
const source = layer.getSource?.();
if (source?.getFeatureById) {
const feature = source.getFeatureById(String(featureId).trim());
if (feature) foundFeature = feature;
}
});
}
// 3. 피처 선택
if (foundFeature) {
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);
};
// MapSearchBar 래퍼 컴포넌트
// const CustomMapSearchBar = (props: any) => {
// return (
// <MapSearchBar
// {...props}
// searchType="공급처 후보지 조회"
// showApplyButton={false}
// />
// );
// };
return (
<div className="bg-container">
<Gis
treeData={treeData}
isSearch={false}
gisMaps={gisMaps}
isMiniMap={false}
searchView={undefined}
// searchView={(props: any) => (
// <MapSearchBar
// searchType="공급처 후보지 조회"
// showApplyButton={false}
// checkedLayers={checkedLayers}
// checkedLayersData={checkedLayersData}
// {...props}
// />
// )
// }
detailView={(props: any) =>(
<NewWindowPopup
onClose={handlePopupClose} // 메모이제이션된 함수 사용
checkedLayers={checkedLayers}
checkedLayersData={checkedLayersData}
{...props}
/>
)}
onFeatureSelect={onFeatureSelect}
setIsOpen={setIsOpen}
setFeatureData={setFeatureData}
featureData={featureData}
setIsSearchModalOpen={setIsSearchModalOpen}
isOpen={isOpen}
isSearchModalOpen={isSearchModalOpen}
onCheckedLayersChange={handleCheckedLayersChange}
imgVisble={true}
/>
</div>
);
};
export default Map;
+411 -418
View File
@@ -41,11 +41,9 @@ import toast, { Toaster } from "react-hot-toast";
import { z } from "zod";
export default function CoMatRvw() {
const { auth, code, coRvw, coMatRvwInit, coMatRvwSearch, coMatRvwInqua } =
const { code, coRvw, coMatRvwInit, coMatRvwSearch, coMatRvwInqua } =
useWrStore((state) => state);
const { coMatRvwRes, coMatRvwCount } = coRvw;
const { regAuthrtYn } = auth;
const { coMatRvwRes,coMatRvwCount } = coRvw;
//init, sub, match
const initRef = useRef<boolean>(false);
const { coRvwHeadList } = coRvw;
@@ -93,9 +91,10 @@ export default function CoMatRvw() {
const form = useForm<z.infer<typeof DmdCoReqSchema>>({
resolver: zodResolver(DmdCoReqSchema),
shouldUnregister: false,
// defaultValues: DmdCoReqSchema.parse({})
// defaultValues: DmdCoReqSchema.parse({})
});
const TableCellClick = (index: number) => {
if (coMatRvwRes && coMatRvwRes[index]) {
setSelectData(coMatRvwRes[index]);
@@ -104,21 +103,23 @@ export default function CoMatRvw() {
};
const useUsgCdWatch = useWatch({ control: form.control, name: "useUsgCd" });
useEffect(() => {
if (useUsgCdWatch) {
form.setValue(
"demandCst.usgPrcsProcs",
usageProcData?.find((item) => item.usage === useUsgCdWatch)?.process ??
""
usageProcData?.find(
(item) => item.usage === useUsgCdWatch
)?.process ?? ""
);
}
}, [useUsgCdWatch, form, selectionVersion]);
}, [useUsgCdWatch, form,selectionVersion]);
useEffect(() => {
if (coMatRvwRes && coMatRvwRes.length > 0) {
if (coMatRvwRes&&coMatRvwRes.length > 0) {
const data = coMatRvwRes?.map((item) => {
let flag = "";
flag = getdmdMatFlag(item?.demandMatching?.splyFcltFlg || undefined);
flag = getdmdMatFlag(item?.demandMatching?.splyFcltFlg ||undefined);
return {
...item,
@@ -126,7 +127,7 @@ export default function CoMatRvw() {
sggCd: item.demandCo?.sggCd,
dmdCoNm: item.demandCo?.dmdCoNm,
daddr: item.demandCo?.daddr,
telno: formatPhoneNumber(item?.demandCo?.telno || ""),
telno: formatPhoneNumber(item?.demandCo?.telno||''),
dmndTmng: item?.dmndTmng,
splyFcltFlg: flag,
};
@@ -155,6 +156,7 @@ export default function CoMatRvw() {
useEffect(() => {
if (selectData) {
try {
DmdCoReqSchema.parse(selectData);
} catch (e) {
@@ -162,14 +164,15 @@ export default function CoMatRvw() {
console.log(e.flatten());
}
}
form.reset(selectData);
setSelectionVersion((v) => v + 1); // 강제로 바뀌었다고 알리기
form.reset( selectData);
setSelectionVersion((v) => v + 1); // 강제로 바뀌었다고 알리기
}
}, [selectData, form]);
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<Title title={"수요매칭검토"} />
<SearchDiv>
@@ -192,7 +195,7 @@ export default function CoMatRvw() {
<div className="col-span-7 w-full">
<div className="flex flex-row items-center">
<Label className="text-xl text-gray-600 mx-6">
수요신청년도
수요신청년도
</Label>
<SelectBox
className="h-full w-32 text-2xl"
@@ -245,10 +248,7 @@ export default function CoMatRvw() {
if (String(objSearch.city).length > 0) {
con = String(objSearch.city);
}
if (
String(objSearch.sgg).length > 0 &&
String(objSearch.sgg) !== "0"
) {
if (String(objSearch.sgg).length > 0 && String(objSearch.sgg) !== "0") {
con = String(objSearch.sgg);
}
getSearch(fromNum, toNum, con, dmdCoNm);
@@ -279,410 +279,403 @@ export default function CoMatRvw() {
TableCellClick(index);
}
}}
onPageChange={(val) => {
setPageNatiion(val);
}}
onPageChange={(val) => {setPageNatiion(val)}}
></UiTable>
</ListDiv>
<hr />
{/* <ScrollArea className="h-[49vh]"> */}
<ListDiv>
<h3 className="mt-4 ml-2 text-2xl font-medium text-label">
수요신청 상세현황
</h3>
<Form {...form}>
<div className="grid grid-cols-12 gap-4 ml-4 mr-4">
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="dmndTmng"
render={({ field }) => (
<FormUi label="요구시기">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(String(e.target.value));
}}
value={
moment(field.value).format("YYYY-MM-DD") ?? ""
}
readOnly
/>
</FormUi>
)}
/>
<ListDiv>
<h3 className="mt-4 ml-2 text-2xl font-medium text-label">
수요신청 상세현황
</h3>
<Form {...form}>
<div className="grid grid-cols-12 gap-4 ml-4 mr-4">
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="dmndTmng"
render={({ field }) => (
<FormUi label="요구시기">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(String(e.target.value));
}}
value={
moment(field.value).format("YYYY-MM-DD") ?? ""
}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="dmndQty"
render={({ field }) => (
<FormUi label="요구수량(m³/일)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="useUsgCd"
render={({ field }) => (
<FormUi label="사용용도">
<Input
placeholder=""
type="text"
step="0.1"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="wntUntprc"
render={({ field }) => (
<FormUi label="희망단가(원/m3)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-12 w-full">
<h1 className={formH1Class}>요구수질</h1>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="grssClfg"
render={({ field }) => (
<FormUi label="총대장균군수 (개/100ml)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="combResdch"
render={({ field }) => (
<FormUi label="결합잔류염소(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="trbt"
render={({ field }) => (
<FormUi label="탁도(NTU)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="blgcOxygDmndQnt"
render={({ field }) => (
<FormUi label="생물학적 산소요구량(BOD)(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="smll"
render={({ field }) => (
<FormUi label="냄새">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="crmty"
render={({ field }) => (
<FormUi label="색도(도)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="tn"
render={({ field }) => (
<FormUi label="총질소 (T-N)(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="tph"
render={({ field }) => (
<FormUi label="총인(T-P)(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="ph"
render={({ field }) => (
<FormUi label="수소이온농도(pH)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="clIonQnt"
render={({ field }) => (
<FormUi label="염화물(mgCL/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="cdtnv"
render={({ field }) => (
<FormUi label="전기전도도(㎲/cm)">
<Input
placeholder=""
type="number"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="rmrk"
render={({ field }) => (
<FormUi label="비고">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-12 w-full">
<h1 className={formH1Class}>공급처 후보지</h1>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${0}`}
render={({ field }) => (
<FormUi label="후보지1">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(String(e.target.value));
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${1}`}
render={({ field }) => (
<FormUi label="후보지2">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${2}`}
render={({ field }) => (
<FormUi label="후보지3">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="dmndQty"
render={({ field }) => (
<FormUi label="요구수량(m³/일)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="useUsgCd"
render={({ field }) => (
<FormUi label="사용용도">
<Input
placeholder=""
type="text"
step="0.1"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="wntUntprc"
render={({ field }) => (
<FormUi label="희망단가(원/m3)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-12 w-full">
<h1 className={formH1Class}>요구수질</h1>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="grssClfg"
render={({ field }) => (
<FormUi label="총대장균군수 (개/100ml)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="combResdch"
render={({ field }) => (
<FormUi label="결합잔류염소(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="trbt"
render={({ field }) => (
<FormUi label="탁도(NTU)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="blgcOxygDmndQnt"
render={({ field }) => (
<FormUi label="생물학적 산소요구량(BOD)(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="smll"
render={({ field }) => (
<FormUi label="냄새">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="crmty"
render={({ field }) => (
<FormUi label="색도(도)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="tn"
render={({ field }) => (
<FormUi label="총질소 (T-N)(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="tph"
render={({ field }) => (
<FormUi label="총인(T-P)(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="ph"
render={({ field }) => (
<FormUi label="수소이온농도(pH)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="clIonQnt"
render={({ field }) => (
<FormUi label="염화물(mgCL/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="cdtnv"
render={({ field }) => (
<FormUi label="전기전도도(㎲/cm)">
<Input
placeholder=""
type="number"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="rmrk"
render={({ field }) => (
<FormUi label="비고">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-12 w-full">
<h1 className={formH1Class}>공급처 후보지</h1>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${0}`}
render={({ field }) => (
<FormUi label="후보지1">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(String(e.target.value));
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${1}`}
render={({ field }) => (
<FormUi label="후보지2">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${2}`}
render={({ field }) => (
<FormUi label="후보지3">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
</div>
</Form>
<ConCostForm
form={form}
type={"mat"}
selectionVersion={selectionVersion}
readonly={regAuthrtYn ==="N"}
/>
</ListDiv>
</Form>
<ConCostForm form={form} type={"mat"} selectionVersion={selectionVersion} />
</ListDiv>
{/* </ScrollArea> */}
</div>
</div>
@@ -30,7 +30,6 @@ import toast, { Toaster } from "react-hot-toast";
import { useTranslation } from "react-i18next";
export default function RuseRvwHstry() {
const {
auth,
code,
ruseHist,
ruseRvwHistInit,
@@ -39,8 +38,6 @@ export default function RuseRvwHstry() {
ruseRvwComplete,
} = useWrStore((state) => state);
const { rvwHistRes, ruseHistHeadList, rvwHistCount } = ruseHist;
const { regAuthrtYn } = auth;
const [pageNation, setPageNatiion] = useState<number>(1);
const [dmdCoNm, setDmdCoNm] = useState<string>("");
@@ -308,7 +305,7 @@ export default function RuseRvwHstry() {
>
조회
</Button>
<Button size={"sm"} onClick={confrirmToast} disabled={regAuthrtYn==='N'}>
<Button size={"sm"} onClick={confrirmToast}>
저장
</Button>
</div>
-4
View File
@@ -33,7 +33,6 @@ import toast, { Toaster } from "react-hot-toast";
export default function CoSttn() {
const {
auth,
code,
coSttn,
coSttnInit,
@@ -44,7 +43,6 @@ export default function CoSttn() {
coSttnTxtSearch,
demandCompList,
} = useWrStore((state) => state);
const { regAuthrtYn, mdfcnAuthrtYn } = auth;
const [bdstTable, setBdstTable] = useState<DemandCompType[]>();
const [pageNation, setPageNation] = useState(1);
@@ -207,7 +205,6 @@ export default function CoSttn() {
setUpdateData(undefined);
setIsDmdModal({ ...isDmdModal, isMoal: true });
}}
disabled={regAuthrtYn === "N"}
>
등록
</Button>
@@ -225,7 +222,6 @@ export default function CoSttn() {
});
}
}}
disabled={mdfcnAuthrtYn === "N"}
>
수정
</Button>
+8 -9
View File
@@ -15,9 +15,9 @@ import { toast, Toaster } from "react-hot-toast";
export default function DrgtSttn() {
const { code, drgt, drgtSearch, drgtModalSearch, drgtInit } = useWrStore((state) => state);
const { drgtRes, drgtMoRes } = drgt;
const [fromDate, setFromDate] = useState<string>('202506');
const [toDate, setToDate] = useState<string>('202506');
const [selectSgg, setSelectSgg] = useState<SelectDataType[]>([{ val: '0', text: '전체' }]);
const [fromDate, setFromDate] = useState<string>();
const [toDate, setToDate] = useState<string>();
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>();
const [objSearch, setObjSearch] = useState<objSearchType>({ sgg: "", city: "" });
const [tableData, setTableData] = useState<customDrgt[]>();
const [selectedSgg, setSelectedSgg] = useState<string>('');
@@ -93,9 +93,9 @@ export default function DrgtSttn() {
const cityValue = String(val);
if (cityValue === "0") {
setSelectSgg([{ val: '0', text: '전체' }]);
setSelectedSgg('0');
setObjSearch({ city: cityValue, sgg: '0' });
setSelectSgg([]);
setSelectedSgg('');
setObjSearch({ city: cityValue, sgg: '' });
} else {
const data = getCity(cityValue, code.sggCd);
setSelectSgg(data);
@@ -136,15 +136,14 @@ export default function DrgtSttn() {
selectClass={""}
selectArray={code.cityCd || []}
onSelectValue={getSelCity}
value={objSearch?.city ||code.cityCd[0]?.val ||""}
/>
<SelectBox
className="col-span-2 w-1/6 h-full text-2xl ml-8"
label="시군구"
selectClass={""}
selectArray={selectSgg || [{ val: '0', text: '전체' }]}
selectArray={selectSgg || []}
onSelectValue={getSgg}
value={selectedSgg ||'0'}
value={selectedSgg}
/>
<div className="col-span-5 w-auto">
<div className="flex flex-row items-center">
+9 -13
View File
@@ -33,7 +33,7 @@ import toast, { Toaster } from "react-hot-toast";
import { useTranslation } from "react-i18next";
export default function LdrmntCoSttn() {
const { auth, code, ldrmnt, ldrmntInit, ldrmntSearch, ldrmntUpdate } = useWrStore(
const { code, ldrmnt, ldrmntInit, ldrmntSearch, ldrmntUpdate } = useWrStore(
(state) => state
);
const { ldrmntRes, excelList, ldrmntResCount } = ldrmnt;
@@ -47,7 +47,6 @@ export default function LdrmntCoSttn() {
const [resetPage, isResetPage] = useState(false);
const [isDownloadClicked, setIsDownloadClicked] = useState(false);
const { t } = useTranslation('base');
const { regAuthrtYn, mdfcnAuthrtYn } = auth;
const excelClick = useCallback(() => {
excelDownload(
@@ -225,7 +224,6 @@ export default function LdrmntCoSttn() {
onClick={() => {
setIsExcelOpen({ isModal: true });
}}
disabled={regAuthrtYn === 'N'}
>
엑셀등록
</Button>
@@ -271,16 +269,14 @@ export default function LdrmntCoSttn() {
setDetailModal({ ...detailModal, isOpen: !detailModal.isOpen })
}}
bodyClass={"w-[40vw] max-w-none max-h-[calc(100%-70px)]"}
body={<CoDetailModal formObj={detailModal.data}
readonly={mdfcnAuthrtYn === 'N'}
onFormSubmit={async (value) => {
const handleConfirm = async () => {
await ldrmntUpdate(value);
setDetailModal({ ...detailModal, isOpen: false });
ldrmntSearch(false, pageNation, '20', computeCityNm(), searchTxt || "");
};
confirmToast(t('isUpdateMsg'), handleConfirm);
}} />}
body={<CoDetailModal formObj={detailModal.data} onFormSubmit={async (value) => {
const handleConfirm = async () => {
await ldrmntUpdate(value);
setDetailModal({ ...detailModal, isOpen: false });
ldrmntSearch(false, pageNation, '20', computeCityNm(), searchTxt || "");
};
confirmToast(t('isUpdateMsg'), handleConfirm);
}} />}
/>
<UiModal
@@ -21,7 +21,7 @@ import { useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
export default function Home() {
const { auth,code, htdfl, initHtdflReg, getHtdflBdstData, htdflNmSearch } =
const { code, htdfl, initHtdflReg, getHtdflBdstData, htdflNmSearch } =
useWrStore((state) => state);
const [searchTxt, setSearchTxt] = useState("");
const [pageNation, setPageNation] = useState(1);
@@ -30,9 +30,12 @@ export default function Home() {
const [bdstTable, setbdstTable] = useState<customHtdflBdst[]>();
const [issNewReg, setIsNewReg] = useState<boolean>(false);
// const [bdstChgProps, setBdstChgProps] = useState<{
// isOpen: boolean;
// chgBuilding: chgBuilding[];
// }>({ isOpen: false, chgBuilding: [] });
const { htdflRes ,htdflResCount} = htdfl;
const { regAuthrtYn, mdfcnAuthrtYn } = auth;
useEffect(() => {
if (!htdfl.isInit) {
@@ -113,10 +116,7 @@ export default function Home() {
>
조회
</Button>
<Button size={"sm"}
onClick={() => setIsNewReg(!issNewReg)}
disabled={regAuthrtYn === "N"}
>
<Button size={"sm"} onClick={() => setIsNewReg(!issNewReg)}>
신규등록
</Button>
</div>
@@ -149,7 +149,6 @@ export default function Home() {
<HtdflRegForm
htdflForm={htdflForm ?? ({} as customHtdflBdst)}
isModal={false}
readonly={mdfcnAuthrtYn === "N"}
/>
</ScrollArea>
</ListDiv>
@@ -38,7 +38,6 @@ import { useTranslation } from "react-i18next";
export default function PublicReuseFaciltyInsert() {
const {
auth,
code,
pbnst,
pubHasuInit,
@@ -48,10 +47,8 @@ export default function PublicReuseFaciltyInsert() {
pubHasuSearch,
pbnstRuseBizUpdate,
} = useWrStore((state) => state);
const { t } = useTranslation("base");
const { pubFacHeadList, pbnstHasuResCount, pbnstHasuRes, pbnstRes } = pbnst;
const { regAuthrtYn, mdfcnAuthrtYn } = auth;
const [, setCurrentTab] = useState<string>("mng");
const [isRuseReg, setIsRuseReg] = useState<{
isModal: boolean;
@@ -293,7 +290,6 @@ export default function PublicReuseFaciltyInsert() {
}
isResetPage(true);
}}
>
조회
</Button>
@@ -311,7 +307,6 @@ export default function PublicReuseFaciltyInsert() {
appendPbnstRuseFclt();
}
}}
disabled={regAuthrtYn === "N"}
>
신규등록
</Button>
@@ -324,17 +319,19 @@ export default function PublicReuseFaciltyInsert() {
<div className="grid grid-cols-8 gap-4">
<div className="col-span-5 h-full min-h-0">
<ListDiv className="min-h-0">
{/* <ScrollArea className="h-[60vh]"> */} {/* 높이 조정 */}
<UiTable
tableData={bdstTable || []}
headlist={pubFacHeadList}
pageSize={10}
total={pbnstHasuResCount || 20}
headName={"공공 하수처리시설 목록"}
cellClick={cellClick}
onPageChange={setPageNation}
resetPageNo={resetPage}
/>
{/* <ScrollArea className="h-[60vh]"> */}
{" "}
{/* 높이 조정 */}
<UiTable
tableData={bdstTable || []}
headlist={pubFacHeadList}
pageSize={10}
total={pbnstHasuResCount || 20}
headName={"공공 하수처리시설 목록"}
cellClick={cellClick}
onPageChange={setPageNation}
resetPageNo={resetPage}
/>
{/* </ScrollArea> */}
</ListDiv>
</div>
@@ -354,7 +351,6 @@ export default function PublicReuseFaciltyInsert() {
size={"sm"}
onClick={form.handleSubmit(onSubmit, onInvalid)}
className="mr-5 mt-2"
disabled={mdfcnAuthrtYn === "N"}
>
저장
</Button>
@@ -368,7 +364,7 @@ export default function PublicReuseFaciltyInsert() {
setIndexMng(index);
}}
indexMng={indexMng}
readonly={mdfcnAuthrtYn === "N"}
readonly={false}
/>
</TabsContent>
<TabsContent className="max-h-full" value="buse">
@@ -380,9 +376,9 @@ export default function PublicReuseFaciltyInsert() {
}}
indexMng={indexMng}
indexBiz={indexBiz}
readonly={mdfcnAuthrtYn === "N"}
/>
</TabsContent>
</ScrollArea>
</Tabs>
) : (
@@ -1,6 +1,8 @@
"use client";
import { useWrStore } from "@/app/store";
import { type customRainBdst } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import {
type customRainBdst,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { formatCommaNumber, tableData } from "@/components/lib/func/commom";
import RainRegForm from "@/components/ui/form/fcltReg/rainReg/rainRegForm";
import { BdstReg } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
@@ -17,19 +19,14 @@ import {
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components";
import { useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
import { Toaster } from "react-hot-toast";
export default function Home() {
const { auth, rain, code, initRain, rainSearch, getRainData } = useWrStore(
const { rain, code, initRain, rainSearch, getRainData } = useWrStore(
(state) => {
return state;
}
);
const { regAuthrtYn, mdfcnAuthrtYn } = auth;
const { rainRes, rainResCount } = rain;
const [rainForm, setRainForm] = useState<customRainBdst>();
const [issNewReg, setIsNewReg] = useState<boolean>(false);
@@ -56,7 +53,7 @@ export default function Home() {
return {
...item,
archArea: formatCommaNumber(archArea),
bdstChgYn: item.chgBuilding[0]?.bdstChgNm != null ? "Y" : "N",
};
}
);
@@ -67,10 +64,13 @@ export default function Home() {
}
}
}, [code, rainRes]);
const cellClick: (val: number | undefined) => void = (val) => {
const cellClick: (val: number | undefined) => void = (
val
) => {
if (val !== undefined) {
setRainForm(rainRes[val]);
}
};
useEffect(() => {
@@ -99,7 +99,7 @@ export default function Home() {
size={"sm"}
onClick={() => {
rainSearch(searchTxt || "", 1, "41");
//rainSearch(searchTxt || "", pageNation, "41");
//rainSearch(searchTxt || "", pageNation, "41");
}}
>
조회
@@ -107,10 +107,7 @@ export default function Home() {
<Button
size={"sm"}
className=""
onClick={() => {
setIsNewReg(!issNewReg);
}}
disabled={regAuthrtYn === "N"}
onClick={() => setIsNewReg(!issNewReg)}
>
신규등록
</Button>
@@ -146,7 +143,6 @@ export default function Home() {
<RainRegForm
rainForm={rainForm ?? ({} as customRainBdst)}
isModal={false}
readonly={mdfcnAuthrtYn !== "Y"}
></RainRegForm>
</ScrollArea>
</ListDiv>
@@ -20,11 +20,9 @@ import { useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
export default function Home() {
const { auth,code, rswt, initRswt, rswtBdstSearch, getRswtBdstData } = useWrStore(
const { code, rswt, initRswt, rswtBdstSearch, getRswtBdstData } = useWrStore(
(state) => state
);
const { regAuthrtYn, mdfcnAuthrtYn } = auth;
const [rswtForm, setRswtForm] = useState<customRswtBdst>();
const [searchTxt, setSearchTxt] = useState<string>();
const [issNewReg, setIsNewReg] = useState<boolean>(false);
@@ -116,7 +114,6 @@ export default function Home() {
size={"sm"}
className="mr-4"
onClick={() => setIsNewReg(!issNewReg)}
disabled={regAuthrtYn === "N"}
>
신규등록
</Button>
@@ -149,7 +146,6 @@ export default function Home() {
<RswtrRegForm
rswtForm={rswtForm ?? ({} as customRswtBdst)}
isModal={false}
readonly={mdfcnAuthrtYn === "N"}
/>
</ScrollArea>
</ListDiv>
@@ -1,11 +1,6 @@
"use client";
import { useWrStore } from "@/app/store";
import { btnClass } from "@/app/store/common/code";
import type { customPbnst } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import type { WaterReuseFacility } from "@/app/store/ruseFcltMng/fcltSttn/pbnstSttn/type";
import { excelDownload, yearOptions } from "@/components/lib/func/commom";
import HeadChModal from "@/components/ui/modal/sttn/headChModal/headChModal";
import { PbnstSttnModal } from "@/components/ui/modal/sttn/pbnstSttnModal/pbnstSttnModal";
import {
ContentsDiv,
SearchBaseForm,
@@ -17,9 +12,14 @@ import {
type ReturnType,
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import { Button, Label } from "@common/components/ui";
import HeadChModal from "@/components/ui/modal/sttn/headChModal/headChModal";
import { useCallback, useEffect, useRef, useState } from "react";
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import type { customPbnst } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import { excelDownload, yearOptions } from "@/components/lib/func/commom";
import type { WaterReuseFacility } from "@/app/store/ruseFcltMng/fcltSttn/pbnstSttn/type";
import { PbnstSttnModal } from "@/components/ui/modal/sttn/pbnstSttnModal/pbnstSttnModal";
export default function PbnstSttn() {
const {
@@ -29,7 +29,6 @@ export default function PbnstSttn() {
pbnSttnInit,
getPbnStnDetail,
getFlcts,
resetPbnstDetail
} = useWrStore((state) => state);
const { pbnstSttnRes, fclts, pbnstSttnResCount } = pbnstSttn;
@@ -104,6 +103,9 @@ export default function PbnstSttn() {
});
}, [pbnstSttn.pbnstDetail]);
useEffect(() => {
console.log("pbnDetaileData.isModal ", pbnDetaileData.isModal);
}, [pbnDetaileData.isModal]);
return (
<>
<ContentsDiv>
@@ -231,9 +233,8 @@ export default function PbnstSttn() {
open={pbnDetaileData.isModal}
onOpenChange={(open) => {
//TODO:OPEN 상태 확인필요
if (!open)
setPbnDetaileData({ data: {} as customPbnst, isModal: open });
resetPbnstDetail();
if(!open)
setPbnDetaileData({ data: {} as customPbnst, isModal: open });
}}
/>
</ContentsDiv>
@@ -44,7 +44,6 @@ import { useTranslation } from "react-i18next";
export default function Page() {
const {
auth,
code,
rainChkgdn,
rswtChkgdn,
@@ -65,7 +64,6 @@ export default function Page() {
} = useWrStore((state) => {
return state;
});
const { regAuthrtYn, mdfcnAuthrtYn, delAuthrtYn } = auth;
const [isRegExcel, setIsRegExcel] = useState(false);
const [updateRainDetail, setUpdateRainDetail] = useState<rainChkZodType[]>(
[]
@@ -303,7 +301,6 @@ export default function Page() {
onClick={() => {
clickDelete(deleteIdx, selFcltDiv);
}}
disabled={delAuthrtYn === 'N'}
>
삭제
</Button>
@@ -316,7 +313,6 @@ export default function Page() {
onClick={() => {
chkUpdateTable(selFcltDiv);
}}
disabled={mdfcnAuthrtYn === 'N'}
>
저장
</Button>
@@ -334,7 +330,6 @@ export default function Page() {
onClick={() => {
setIsRegExcel(!isRegExcel);
}}
disabled={regAuthrtYn === 'N'}
>
결과등록
</Button>
@@ -359,7 +354,6 @@ export default function Page() {
pageNation={rainPageNation}
onPageChange={rainPageChange}
pageCount={rainChkgdn.rainChkCount}
readonly={mdfcnAuthrtYn === 'N'}
/>
) : (
<RswtChkgdTable
@@ -370,7 +364,6 @@ export default function Page() {
pageNation={rswtPageNation}
onPageChange={rswtPageChange}
pageCount={rswtChkgdn.rswtChkCount}
readonly={mdfcnAuthrtYn === 'N'}
/>
)}
</ListDiv>
@@ -387,7 +380,6 @@ export default function Page() {
type={selFcltDiv}
obj={isModal.data}
setIsModal={(open) => setIsModal((prev) => ({ ...prev, open }))}
readonly={mdfcnAuthrtYn === 'N' ? false : true}
/>
}
></UiModal>
@@ -38,11 +38,10 @@ import { useTranslation } from "react-i18next";
import { headMakeprfmnc } from "../chkgdnReg/TableHead";
export default function PrfmncPrfmncReg() {
const { auth, prfmnc, prfmncHasuInit, prfmnRegData, prfmncHasuNmSearch } = useWrStore(
const { prfmnc, prfmncHasuInit, prfmnRegData, prfmncHasuNmSearch } = useWrStore(
(state) => state
);
const { pbnstPrfmncHeadList, monthHeadList, prfmncRes, prfmncResCount } = prfmnc;
const { regAuthrtYn, mdfcnAuthrtYn } = auth;
const [bdstTable, setbdstTable] = useState<FcPrfType[]>();
const [searchTxt, setSearchTxt] = useState<string>();
const [isExcelOpen, setIsExcelOPen] = useState<{
@@ -93,7 +92,7 @@ export default function PrfmncPrfmncReg() {
searchYear,
pbnstRuseFcltId
) as unknown as PrfType
, searchYear
,searchYear
);
};
@@ -260,7 +259,6 @@ export default function PrfmncPrfmncReg() {
onClick={() => {
onSave();
}}
disabled={mdfcnAuthrtYn === 'N'}
>
저장
</Button>
@@ -274,7 +272,6 @@ export default function PrfmncPrfmncReg() {
setIsExcelOPen({ ...isExcelOpen, isModal: true });
}
}}
disabled={regAuthrtYn === 'N'}
>
파일등록
</Button>
@@ -324,7 +321,7 @@ export default function PrfmncPrfmncReg() {
{headMakeprfmnc(monthHeadList, [])}
</TableHeader>
<TableBody key={prfmnc.pageKey + 'pageKey'}>
{InputTableBody(inputData ?? [], monthHeadList, setInputData, mdfcnAuthrtYn === 'N' ? false : true)}
{InputTableBody(inputData ?? [], monthHeadList, setInputData)}
</TableBody>
</Table>
</ScrollArea>
@@ -351,7 +348,7 @@ export default function PrfmncPrfmncReg() {
}
open={isExcelOpen.isModal}
onOpenChange={() => {
setIsExcelOPen({ ...isExcelOpen, isModal: false });
setIsExcelOPen({ isModal: false, data: {} as FcPrfType });
}}
></UiModal>
<Toaster position="top-center" />
@@ -99,9 +99,7 @@ export default function Page() {
isRainSttn(true)
rainChkSttnInit(1, rainPageSize, new Date().getFullYear().toString(), commonCd);
setIsModal({ data: {}, open: false });
}
}, [rainChkSttn.isInit, rainChkSttnInit, rainPageSize]);
useEffect(() => {
@@ -228,7 +226,6 @@ export default function Page() {
pageNation={rainPageNation}
onPageChange={rainPageChange}
pageCount={rainChkSttn.rainChkCount}
readonly={true}
/>
) : (
<RswtChkgdTable
@@ -239,7 +236,6 @@ export default function Page() {
pageNation={rswtPageNation}
onPageChange={rswtPageChange}
pageCount={rswtChkSttn.rswtChkCount}
readonly={true}
/>
)}
</ListDiv>
@@ -251,7 +247,7 @@ export default function Page() {
setIsModal({ open: !open, data: {} });
}}
bodyClass={"w-[80vw] max-w-none"}
body={<ChkgdModal readonly={true} type={selFcltDiv} obj={isModal.data} setIsModal={() => { }} />}
body={<ChkgdModal type={selFcltDiv} obj={isModal.data} setIsModal={() => { }} />}
></UiModal>
<Toaster position="top-center" />
</ContentsDiv>
+1
View File
@@ -140,6 +140,7 @@ export default function RainStat() {
const excelData = [...sidoTotalSummary, ...sidoSummaryList, ...summaryExcelData];
console.log(' excelData ', excelData)
excelDownload(
excelData as unknown as [][],
"빗물이용시설 통계",
+16 -1
View File
@@ -1,6 +1,21 @@
import { getFetchWithCount } from "@/components/lib/api";
import { getFetch, getFetchWithCount } from "@/components/lib/api";
import toast from "react-hot-toast";
export const getMenuAuthrts = async (menuCd: number) => {
const response = await getFetch(
"LOCAL",
`/cms-service/api/v1/menu-authrts/pageinfo/${menuCd}`
);
authStateExport.auth = {
mngAuthrtYn: response[0].mngAuthrtYn,
inqAuthrtYn: response[0].mngAuthrtYn,
regAuthrtYn: response[0].mngAuthrtYn,
mdfcnAuthrtYn: response[0].mngAuthrtYn,
delAuthrtYn: response[0].mngAuthrtYn,
};
};
export type authState = {
auth: {
mngAuthrtYn: string;
+3 -4
View File
@@ -98,10 +98,9 @@ export const drgtActionsExport: (set: any) => drgtActions = (
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0');
const formatted = `${year}${month}`;
let fromDate = formatted;
let toDate = formatted;
fromDate='202506'
toDate='202506'
const fromDate = formatted;
const toDate = formatted;
const drgtRes = await initFetch(fromDate, toDate, []);
set((state: drgtState) => {
return {
@@ -27,9 +27,9 @@ export type pbnstSttnState = {
ruseGuranteeHeadList: TableUpperProps[]
ruseDmdHeadList: TableUpperProps[]
ruseFcltHeadList: TableUpperProps[]
pbnstSttnResCount: number;
pbnstSttnResCount:number;
excelList: [];
fclts: string[]
fclts:string[]
isInit: boolean;
};
};
@@ -43,15 +43,15 @@ type pbnstSttnActions = {
reurnValue: ReturnType,
searchNm: string | undefined,
year: string,
fclts: string[]
fclts:string[]
) => void;
getFlcts: () => void;
getFlcts:()=>void;
pbnSttnInit: (
page: string,
total: string,
reurnValue: ReturnType,
year: string,
flcts: string[]
flcts:string[]
) => void;
getPbnStnDetail: (pbnstRuseFcltId: string) => void;
pbnNmSearch: (
@@ -60,9 +60,8 @@ type pbnstSttnActions = {
reurnValue: ReturnType,
searchNm: string | undefined,
year: string,
flcts: string[]
flcts:string[]
) => void;
resetPbnstDetail: () => void;
};
export type pbnstSttnType = pbnstSttnState & pbnstSttnActions;
@@ -78,11 +77,11 @@ export const pbnstSttnStateExport: pbnstSttnState = {
ruseDmdHeadList: ruseDmdHeadListExport,
ruseFcltHeadList: ruseFcltHeadListExport,
pbnstSttnRes: [],
pbnstSttnResCount: 1,
pbnstSttnResCount:1,
pbnstDetail: {} as customPbnst,
pbnstSearchData: [],
excelList: [],
fclts: [],
fclts:[],
isInit: false,
},
};
@@ -93,12 +92,12 @@ const hasuListFetch = async (
reurnValue: ReturnType,
searchNm: string | undefined,
year: string,
flcts: string[]
flcts:string[]
) => {
let url = `/prcsFclt/ruseInfo/`;
if (reurnValue.partValue === "A") {
url += `${page}/${total}/${reurnValue.partValue}/${
url+=`${page}/${total}/${reurnValue.partValue}/${
// reurnValue.sidoValue ? reurnValue.sidoValue : reurnValue.sigunValue
reurnValue.sigunValue !== '0' ? reurnValue.sigunValue : reurnValue.sidoValue
}/0/1/SW`
@@ -109,12 +108,12 @@ const hasuListFetch = async (
? reurnValue.unitWaterShedValue
: reurnValue.middleRegionValue
}/0/1/SW`
} else if (reurnValue.partValue === 'G') {
} else if( reurnValue.partValue === 'G'){
url += `${page}/${total}/${reurnValue.envPartValue}/${reurnValue.sigunValue !== '0' ? reurnValue.sigunValue : reurnValue.sidoValue}/0/1/SW`
} else {
}else{
url += `1/2/A/0/0/1/SW`
}
@@ -122,7 +121,8 @@ const hasuListFetch = async (
url += "/" + searchNm
}
const pbnList = await postFectch(url, flcts, fetchType.COMMON);
console.log(' flcts ' ,flcts)
const pbnList = await postFectch(url, flcts,fetchType.COMMON);
const getRuseList = await postFectch(
`/reuseFc/pubDetailList/${year}`,
flcts,
@@ -139,7 +139,7 @@ const hasuListFetch = async (
fclt.bscFctCd === item.pbnstRuseFcltId.substring(0, 11)
);
if (findData) {
if(findData){
const usage = item.prfList.reduce(
(acc, cur) => {
@@ -161,42 +161,48 @@ const hasuListFetch = async (
cur.rvrKeepUswtr +
cur.indstUswtr;
acc.total = acc.inUsage + acc.outUsage;
return acc;
},
{ total: 0, inUsage: 0, outUsage: 0 }
);
console.log('findData ', findData)
return {
rvbsn: findData?.rvbsn || '-',
lgbsn: findData?.lgbsn || '-',
mdmbsn: findData?.mdmbsn || '-',
rgnNm: findData?.rgnNm || '-',
sido: findData?.sido || '-',
gugun: findData?.gugun || '-',
bscFctNm: findData?.bscFctNm || '-',
efflWqltStndrdNm: findData?.efflWqltStndrdNm || '-',
fctCpc: Number(findData?.fctCpc) || 0,
rvbsn: findData?.rvbsn ||'-',
lgbsn: findData?.lgbsn||'-',
mdmbsn: findData?.mdmbsn||'-',
rgnNm: findData?.rgnNm||'-',
sido: findData?.sido||'-',
gugun: findData?.gugun||'-',
bscFctNm: findData?.bscFctNm||'-',
efflWqltStndrdNm: findData?.efflWqltStndrdNm||'-',
fctCpc: Number(findData?.fctCpc)||0,
tel: findData?.tel ?? "-",
ruseUtztnFcltNm: item?.ruseUtztnFcltNm || '-',
fcltCpct: item?.fcltCpct || '-',
splyExtraCpct: item?.splyExtraCpct || '-',
ruseCpct: item?.ruseCpct || '-',
pbnstRuseFcltId: item.pbnstRuseFcltId || '-',
ruseUtztnFcltNm: item?.ruseUtztnFcltNm||'-',
fcltCpct: item?.fcltCpct||'-',
splyExtraCpct: item?.splyExtraCpct||'-',
ruseCpct: item?.ruseCpct||'-',
pbnstRuseFcltId: item.pbnstRuseFcltId||'-',
usageTotal: usage?.total,
inUsage: usage?.inUsage,
outUsage: usage?.outUsage,
operMthd: item.operList[0]?.operMthd || '-',
operMthd: item.operList[0]?.operMthd||'-',
rprtvBzenty: item.operList[0]?.rprtvBzenty,
bgngDt: moment(item.operList[0]?.bgngDt).format("YYYY-MM-DD") ?? "",
endDt: moment(item.operList[0]?.endDt).format("YYYY-MM-DD") ?? "",
searchNm: findData?.bscFctNm || '-',
searchPk: findData?.bscFctCd || '-',
searchNm: findData?.bscFctNm||'-',
searchPk: findData?.bscFctCd||'-',
prfList: item?.prfList ?? []
};
}
}
).filter(Boolean);
console.log( ' checkWrRegListRes ', getRuseList.data)
console.log( ' data ', data)
return data;
};
@@ -204,12 +210,12 @@ export const pbnstSttnActionsExport: (set: any) => pbnstSttnActions = (
set: any
) => {
return {
getFlcts: async () => {
const fclts = await getFetch(fetchType.WR, '/reuseFc/pubFc')
getFlcts:async ()=>{
const fclts= await getFetch(fetchType.WR,'/reuseFc/pubFc')
return set((state: pbnstSttnState) => ({
pbnstSttn: {
...state.pbnstSttn,
fclts: fclts
fclts:fclts
},
}));
},
@@ -233,11 +239,11 @@ export const pbnstSttnActionsExport: (set: any) => pbnstSttnActions = (
reurnValue: ReturnType,
searchNm: string | undefined,
year: string,
fclts: string[]
fclts:string[]
) => {
try {
const pbnstSttnRes = await hasuListFetch(
page,
total,
@@ -259,7 +265,7 @@ export const pbnstSttnActionsExport: (set: any) => pbnstSttnActions = (
},
};
});
} else {
} else{
set((state: pbnstSttnState) => {
return {
@@ -267,8 +273,8 @@ export const pbnstSttnActionsExport: (set: any) => pbnstSttnActions = (
pbnstSttn: {
...state.pbnstSttn,
pbnstSttnRes: pbnstSttnRes,
pbnstSttnResCount: pbnstSttnRes.length
// isInit: false,
pbnstSttnResCount:pbnstSttnRes.length
// isInit: false,
},
};
});
@@ -277,31 +283,31 @@ export const pbnstSttnActionsExport: (set: any) => pbnstSttnActions = (
console.log("error", erTxt);
}
},
pbnSttnInit: async (
pbnSttnInit: async(
page: string,
total: string,
reurnValue: ReturnType,
year: string,
fclts: string[]
fclts:string[]
) => {
try {
const pbnstSttnRes = await hasuListFetch(
page,
total,
reurnValue,
undefined,
year,
fclts
);
set((state: pbnstSttnState) => {
page,
total,
reurnValue,
undefined,
year,
fclts
);
console.log('pbnstSttnRes ' , pbnstSttnRes)
set( (state: pbnstSttnState) => {
return {
...state,
pbnstSttn: {
...state.pbnstSttn,
pbnstSttnRes: pbnstSttnRes,
pbnstSttnResCount: pbnstSttnRes.length,
pbnstSttnResCount:pbnstSttnRes.length,
isInit: false,
pbnstDetail: {} as customPbnst
},
};
});
@@ -309,17 +315,6 @@ export const pbnstSttnActionsExport: (set: any) => pbnstSttnActions = (
console.log("error", erTxt);
}
},
resetPbnstDetail: async () => {
set((state: pbnstSttnState) => {
return {
...state,
pbnstSttn: {
...state.pbnstSttn,
pbnstDetail: {} as customPbnst
},
};
})
},
getPbnStnDetail: async (pbnstRuseFcltId: string) => {
try {
let pbnstDetail = await getFetch("wr", `/reuseFc/pubFc/${pbnstRuseFcltId}`);
@@ -345,7 +340,7 @@ export const pbnstSttnActionsExport: (set: any) => pbnstSttnActions = (
reurnValue: ReturnType,
searchNm: string | undefined,
year: string,
flcts: string[]
flcts:string[]
) => {
try {
@@ -364,7 +359,7 @@ export const pbnstSttnActionsExport: (set: any) => pbnstSttnActions = (
pbnstSttn: {
...state.pbnstSttn,
pbnstSearchData: pbnstSttnRes,
pbnstSttnResCount: pbnstSttnRes.length,
pbnstSttnResCount:pbnstSttnRes.length,
},
};
});
@@ -1,7 +1,6 @@
import type { SelectDataType } from "@common/business_components/ui";
import type { customRainBdst } from "../../fcltReg/rainReg";
import { bdstUsgCd } from "@/app/store/common/code/basicCode";
//TODO: 공통코드시 삭제되니 수정 해야됨
export const excelRainSttnParsing = (
excel: { data: customRainBdst[] },
sidoCode: SelectDataType[],
@@ -10,15 +9,14 @@ export const excelRainSttnParsing = (
const excelExportData: string[][] = [];
excel.data.forEach((item) => {
console.log("item", item)
excelExportData.push([
sidoCode.find((sido) => sido.val === item.ctpvCd?.toString())?.text ?? "",
sggCode.find((sgg) => sgg.val === item.sggCd?.toString())?.text ?? "",
item.bdstNm ?? "",
item.daddr ?? "",
bdstUsgCd.find((cd) => cd.val === item.reuseBuilding?.[0]?.bdstUsgCd.toString())?.text ?? "", //건축물용도
String(item.bdstInfoSn ?? ""),
String(item.frstArchPrmsnDt ?? ""),
String(item.archArea.split('.')[0] === '-1' ? '확인불가' : item.archArea.split('.')[0]),
String(item.archArea ?? ""),
String(item.chgBuilding.length > 0 ? "Y" : "N"),
String(item.reuseBuilding?.[0]?.lawTrgtYn ?? ""),
String(item.reuseBuilding?.[0]?.instlCmptnDt ?? ""),
@@ -30,7 +28,7 @@ export const excelRainSttnParsing = (
String(item.reuseBuilding?.[0]?.rainyObj?.filtrTrtmfctPrs ?? ""),
String(item.reuseBuilding?.[0]?.rainyObj?.dtfcltCpct ?? ""),
String(item.reuseBuilding?.[0]?.instlCstSprtYn ?? ""),
String(item.reuseBuilding?.[0]?.instlCstSprtAmt === -1 ? "확인불가" : String(item.reuseBuilding?.[0]?.instlCstSprtAmt) ?? ""),
String(item.reuseBuilding?.[0]?.instlCstSprtAmt ?? ""),
String(item.reuseBuilding?.[0]?.grntchBdstCertYn ?? ""),
String(item.reuseBuilding?.[0]?.grntchBdstCertYr ?? ""),
String(item.reuseBuilding?.[0]?.grntchBdstCertNo ?? ""),
+3 -3
View File
@@ -133,7 +133,7 @@ export const rainStatActionsExport = (
tmp: 0,
instlCst: 0, //설치비
dtfcltCpct: 0, //저류조용량
wtrUsqty: 0, //연간사용량
bdstUsgCd: 0, //연간사용량
lndwtr: 0, //조경용수
cleanToilUswtr: 0, //청소화장실용수
resn: 0, //세척살수용수
@@ -153,8 +153,8 @@ export const rainStatActionsExport = (
totalObj.dtfcltCpct += !isNaN(Number(item.dtfcltCpct))
? Number(item.dtfcltCpct)
: 0;
totalObj.wtrUsqty += !isNaN(Number(item.wtrUsqty))
? Number(item.wtrUsqty)
totalObj.bdstUsgCd += !isNaN(Number(item.bdstUsgCd))
? Number(item.bdstUsgCd)
: 0;
totalObj.lndwtr += !isNaN(Number(item.lndwtr))
? Number(item.lndwtr)
+1 -1
View File
@@ -195,7 +195,7 @@ export const StoreZus = (
getMiddleRegionCd(set);
getUnitWaterShedCd(set);
getEnvPartCd(set);
LoginApi.login({userId: "admin1gmail", password: "test1234!"})
LoginApi.login({userId: "tuser10003", password: "test1234!"})
return {
...initState,
...comFcltSearchAction(set),
+2 -6
View File
@@ -95,8 +95,7 @@ export const chRowspanTable = (
) => void,
toggleSelection: (pk: number, checked: boolean) => void,
selectedIds: number[],
handleCellClick: (index: number, headId: string) => void,
disable? : boolean
handleCellClick: (index: number, headId: string) => void
) => {
let order = 0
// rowspan된 셀 렌더링 여부 추적용
@@ -139,7 +138,6 @@ export const chRowspanTable = (
onCheckedChange={(checked) =>
toggleSelection(row.chkgdnSn, checked === true)
}
disabled={disable}
></Checkbox>
) : key === "order" ? (
++order
@@ -341,9 +339,7 @@ export const InputTableBody = (
// className={`${head.id !== "utztnUsgCd" ? "text-right" : "text-center"} !text-xl h-10 w-full`}
className={`${textAlignClass} !text-xl h-10 w-full`}
onChange={(e) =>
handleCommaNumberChange(e, val =>
handleChange(dataIndex, head.id, String(val), setInputData)
)
handleChange(dataIndex, head.id, e.target.value, setInputData)
}
value={formatCommaNumber(data[head.id as keyof any]) ?? ""}
maxLength={numSize}
@@ -31,12 +31,10 @@ export default function ConCostForm({
form,
type,
selectionVersion,
readonly = false,
}: {
form: UseFormReturn<DmdCoReqType>;
type: string;
selectionVersion: number;
readonly: boolean;
}) {
const {
constCostRes,
@@ -60,11 +58,14 @@ export default function ConCostForm({
}
}, [ref, getConstCostFee, getRateFee]);
useEffect(() => {
// 다른 행을 선택하면(selectionVersion 변경) 체크박스 상태를 초기화합니다.
setCheckFinish(false);
}, [selectionVersion]);
const zipDowonLoad = () => {
fetch(`/2024_constarctFeeProgram.zip`, {}).then(async (response) => {
const blobRet = await response.blob();
@@ -94,7 +95,7 @@ export default function ConCostForm({
return;
}
const dmndQtyYear = dmndQtyWatch;
const dmndQtyYear = dmndQtyWatch * 365;
if (usgPrcsProcs && usgPrcsProcs?.length > 0) {
const firstProc =
getConstFctCode(usgPrcsProcs?.split("+")[0] || "") || "";
@@ -164,32 +165,29 @@ export default function ConCostForm({
cstrnCst: value.demandCst.cstrnCst || 0,
fcltSbsdCstrnCst: value.demandCst.fcltSbsdCstrnCst || 0,
prcsFcltCpctCstrnCst: value.demandCst.prcsFcltCpctCstrnCst || 0,
flg: checkFinish ? "Checked" : "Sub",
flg: checkFinish?'Checked':'Sub',
rgtr: TEST_UUID,
};
if (checkFinish) {
toast((t) => (
<span className="flex flex-col items-center text-2xl">
검토완료 변경시 공사비는 변경할수 없습니다.
<span className="flex flex-col items-center text-2xl" >
검토완료 변경시 공사비는 변경할수 없습니다.
<br />
진행하시겠습니까?
<div className="flex gap-2 mt-2">
<Button
size="sm"
onClick={() => {
toast.dismiss(t.id);
coMatRvwUpdate(
"11000SW001R1",
form.getValues("dmdInfoId"),
data
);
}}
>
확인
</Button>
<Button size="sm" onClick={() => toast.dismiss(t.id)}>
취소
</Button>
<Button
size='sm'
onClick={() => {
toast.dismiss(t.id);
coMatRvwUpdate("11000SW001R1", form.getValues("dmdInfoId"), data);
}}
>
확인
</Button>
<Button
size='sm'
onClick={() => toast.dismiss(t.id)}>취소</Button>
</div>
</span>
));
@@ -231,7 +229,6 @@ export default function ConCostForm({
className="mr-3"
size={"sm"}
onClick={form.handleSubmit(onSubmit)}
disabled={readonly}
>
저장
</Button>
@@ -239,14 +236,9 @@ export default function ConCostForm({
<Checkbox
className="ml-3 mr-6"
checked={checkFinish}
onCheckedChange={
(checked) => {
if (readonly) return;
setCheckFinish(checked === true);
}
onCheckedChange={(checked) =>
// 'indeterminate' 상태를 무시하고 순수 boolean 값으로만 상태를 업데이트합니다.
}
setCheckFinish(checked === true)}
></Checkbox>
<Label>관로 표준공사비 산정 프로그램</Label>
<Button
@@ -358,11 +350,10 @@ export default function ConCostForm({
type="number"
step="0.001"
onChange={(e) => {
console.log("dmndQty ", e);
console.log('dmndQty ', e)
//field.onChange(Number(e.target.value) * 365 );
}}
// value={Number(field.value) * 365 || 0}
value={Number(field.value) || 0}
value={Number(field.value) * 365 || 0}
readOnly
/>
</FormUi>
@@ -386,7 +377,7 @@ export default function ConCostForm({
}
childrenBody={
<>
<ConstCostFeeTable />
<ConstCostFeeTable/>
</>
}
bodyClassName={"w-[40vw] h-full"}
@@ -423,7 +414,8 @@ export default function ConCostForm({
}
childrenBody={
<>
<RateFeeTableModal />
<RateFeeTableModal/>
</>
}
bodyClassName={"w-[22vw]"}
@@ -484,7 +476,8 @@ export default function ConCostForm({
type="number"
step="0.01"
onChange={(e) => {
console.log("totalConstCost ", e);
console.log('totalConstCost ', e)
}}
value={field.value ?? 0}
readOnly
@@ -528,9 +521,6 @@ export default function ConCostForm({
type="number"
step="0.01"
onChange={(e) => {
if(readonly) return;
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
@@ -44,7 +44,6 @@ export function PbnstBuseForm({
indexBiz = 0,
setIndexBiz,
form,
readonly = false,
}: {
formType: string;
firstBizData?: fcBizType[];
@@ -52,7 +51,6 @@ export function PbnstBuseForm({
indexMng: number;
indexBiz: number;
setIndexBiz: (index: number) => void;
readonly?: boolean;
}) {
const {
code,
@@ -331,7 +329,6 @@ export function PbnstBuseForm({
onClick={addRuseFcltObj}
type="button"
size={commonButonSize}
disabled={readonly}
>
추가
</Button>
@@ -346,7 +343,6 @@ export function PbnstBuseForm({
sonClass="col-span-4"
indexMng={indexMng}
indexBiz={indexBiz}
readonly={readonly}
/>
<MngRegFormDetail
key={`buziMoney-${indexMng}-${indexBiz}`}
@@ -357,7 +353,6 @@ export function PbnstBuseForm({
sonClass="col-span-4"
indexMng={indexMng}
indexBiz={indexBiz}
readonly={readonly}
/>
<MngRegFormDetail
@@ -369,7 +364,6 @@ export function PbnstBuseForm({
sonClass="col-span-4"
indexMng={indexMng}
indexBiz={indexBiz}
readonly={readonly}
/>
<MngRegFormDetail
key={`concertedWater-${indexMng}-${indexBiz}`}
@@ -380,7 +374,6 @@ export function PbnstBuseForm({
sonClass="col-span-4"
indexMng={indexMng}
indexBiz={indexBiz}
readonly={readonly}
/>
<MngRegFormDetail
key={`wasteFcltinfo-${indexMng}-${indexBiz}`}
@@ -391,7 +384,6 @@ export function PbnstBuseForm({
sonClass="col-span-4"
indexMng={indexMng}
indexBiz={indexBiz}
readonly={readonly}
/>
<h1 className={formH1Class}>재이용 원수취수 현황</h1>
@@ -402,7 +394,6 @@ export function PbnstBuseForm({
onClick={() => setIsFcOrgwts(true)}
size={commonButonSize}
className=""
disabled={readonly}
>
추가등록
</Button>
@@ -421,7 +412,6 @@ export function PbnstBuseForm({
indexMng={indexMng}
formNm={"fcOrgwts"}
indexBiz={indexBiz}
readonly={readonly}
/>
</div>
<h1 className={formH1Class}>재이용 공급관로 설치 현황</h1>
@@ -434,7 +424,6 @@ export function PbnstBuseForm({
className="w-32"
selectClass="w-full"
onSelectValue={(val) => setPpiYn(String(val))}
readOnly={readonly}
/>
<Label className="text-right">합계</Label>
<Input
@@ -450,7 +439,6 @@ export function PbnstBuseForm({
size={commonButonSize}
className="!text-xl"
onClick={plusHist}
disabled={readonly}
>
추가등록
</Button>
@@ -459,7 +447,6 @@ export function PbnstBuseForm({
size={commonButonSize}
className="!text-xl !bg-red-500 !text-white ml-1"
onClick={removeSelected}
disabled={readonly}
>
삭제
</Button>
@@ -484,7 +471,6 @@ export function PbnstBuseForm({
form={form}
formNm={"pplInstls"}
upHeadList={[]}
readonly={readonly}
/>
</div>
@@ -508,7 +494,7 @@ export function PbnstBuseForm({
sonClass="col-span-4"
indexMng={indexMng}
indexBiz={indexBiz}
readonly={readonly}
readonly={false}
/>
</div>
@@ -524,7 +510,6 @@ export function PbnstBuseForm({
}}
size={commonButonSize}
className="mt-6 mr-3"
disabled={readonly}
>
수요처 추가
</Button>
@@ -538,7 +523,6 @@ export function PbnstBuseForm({
}}
size={commonButonSize}
className="mt-6"
disabled={readonly}
>
수요처 신규등록
</Button>
@@ -591,7 +575,6 @@ export function PbnstBuseForm({
searchPk: item.dmdInfoId,
};
})}
readonly={readonly}
></SearchInputText>
</FormUi>
)}
@@ -628,7 +611,6 @@ export function PbnstBuseForm({
selectArray={code.dmdUszCd}
onSelectValue={f.onChange}
value={f.value ?? code.dmdUszCd[0]?.val}
readOnly={readonly}
/>
</FormUi>
)}
@@ -648,7 +630,6 @@ export function PbnstBuseForm({
f.onChange(date),
}}
selectClass={"rounded-lg !w-full"}
readOnly={readonly}
/>
</FormUi>
)}
@@ -671,7 +652,6 @@ export function PbnstBuseForm({
f.onChange(date),
}}
selectClass={"rounded-lg !w-full"}
readOnly={readonly}
/>
</FormUi>
)}
@@ -690,7 +670,6 @@ export function PbnstBuseForm({
handleCommaNumberChange(e, f.onChange);
}}
value={formatCommaNumber(f.value)}
readOnly={readonly}
/>
</FormUi>
)}
@@ -711,7 +690,6 @@ export function PbnstBuseForm({
f.onChange(val)
}
value={f.value ?? code.yn[0]?.val}
readOnly={readonly}
/>
</FormUi>
)}
@@ -41,13 +41,13 @@ export function PbnstMngForm({
formType,
indexMng,
setIndexMng,
readonly,
readonly
}: {
form: UseFormReturn<{ items: PbnstRegArrrayType }>;
formType: string;
indexMng: number;
setIndexMng: (index: number) => void;
readonly: boolean;
readonly:boolean
}) {
const { code, pbnst, fileDelete, fileDownLoad } = useWrStore(
(state) => state
@@ -60,7 +60,6 @@ export function PbnstMngForm({
const [mngMtdCode, setMngMtdCode] =
useState<{ name: string; val: SelectDataType[] }[]>();
const {
fields: fcOpersField,
prepend,
@@ -88,6 +87,7 @@ export function PbnstMngForm({
endDt: new Date(),
});
//trigger(`items.${indexMng}.fcOpers`);
};
const removeSelected = () => {
@@ -318,7 +318,6 @@ export function PbnstMngForm({
size={commonButonSize}
className="!text-xl"
onClick={plusHist}
disabled={readonly}
>
추가등록
</Button>
@@ -327,7 +326,6 @@ export function PbnstMngForm({
size={commonButonSize}
className="!text-xl !bg-red-500 !text-white ml-1"
onClick={removeSelected}
disabled={readonly}
>
삭제
</Button>
@@ -337,11 +335,20 @@ export function PbnstMngForm({
<div className="h-[200px] overflow-y-auto">
<RuseMngTableForm
key={`ruse-table-${indexMng}-${fcOpersField.length}`} // 🔥 length까지 넣어야 동기화됨
tableData={form.getValues(`items.${indexMng}.fcOpers`) || []}
headList={pbnst.pbnstMngUpHeadList}
tableData={form.getValues(`items.${indexMng}.fcOpers`) ||[]}
headList={
formType === "sttn"
? pbnst.pbnstMngUpHeadList.map((item) => {
return {
...item,
readonly: true,
};
})
: pbnst.pbnstMngUpHeadList
}
upHeadList={pbnst.pbnstMngNm}
code={mngMtdCode || []}
readonly={readonly}
indexMng={indexMng}
form={form}
formNm={"fcOpers"}
@@ -365,6 +372,7 @@ export function PbnstMngForm({
maxLength={numSize} //입력제한
type="text"
onChange={(e) => {
if (formType !== "sttn")
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
@@ -388,6 +396,7 @@ export function PbnstMngForm({
maxLength={numSize} //입력제한
type="text"
onChange={(e) => {
if (formType !== "sttn")
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
@@ -410,6 +419,7 @@ export function PbnstMngForm({
maxLength={numSize} //입력제한
type="text"
onChange={(e) => {
if (formType !== "sttn")
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
@@ -425,7 +435,7 @@ export function PbnstMngForm({
</div>
<div className="grid grid-cols-12 gap-4 my-4">
<div className="col-span-6">
{readonly ? (
{formType === "sttn" ? (
relationfiles && relationfiles?.length > 0 ? (
<>
<Label className="text-3xl">계통도</Label>
@@ -462,7 +472,7 @@ export function PbnstMngForm({
)}
</div>
<div className="col-span-6">
{readonly ? (
{formType === "sttn" ? (
planFiles && planFiles?.length > 0 ? (
<>
<Label className="text-3xl">평면도</Label>
@@ -21,7 +21,6 @@ export default function MngRegFormDetail({
sonClass,
indexBiz,
indexMng,
readonly
}: {
formList: formDetailType[];
h1Title?: string;
@@ -31,7 +30,6 @@ export default function MngRegFormDetail({
indexBiz?: number;
indexMng?: number;
sonClass?: string;
readonly?:boolean
}) {
const { code } = useWrStore((state) => state);
@@ -69,10 +67,7 @@ export default function MngRegFormDetail({
field.onChange(date),
}}
selectClass={"w-full"}
readOnly={readonly
//|| formHead.option === "disabled" ? true : false
}
disabled={formHead.option === "disabled" ? true : false}
/>
) : formHead.type === "number" ? (
@@ -86,9 +81,7 @@ export default function MngRegFormDetail({
);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly
// || formHead.option === "readOnly" ? true : false
}
readOnly={formHead.option === "readOnly" ? true : false}
disabled={formHead.option === "disabled" ? true : false}
maxLength={numSize}
/>
@@ -110,9 +103,7 @@ export default function MngRegFormDetail({
}
onSelectValue={field.onChange}
value={field.value?.trim() ?? (Array.isArray(potentialOptions) && potentialOptions[0]?.val)}
readOnly={readonly
// || formHead.option === "readOnly"
}
readOnly={formHead.option === "readOnly"}
/>
);
})()
@@ -122,9 +113,7 @@ export default function MngRegFormDetail({
type="text"
value={field.value ?? ""}
onChange={field.onChange}
readOnly={readonly
// || formHead.option === "readOnly" ? true : false
}
readOnly={formHead.option === "readOnly" ? true : false}
disabled={formHead.option === "disabled" ? true : false}
maxLength={txtSize}
/>
@@ -511,7 +511,6 @@ export default function RainRegForm({
selectArray={code.bdstIncenYn}
onSelectValue={readonly ? () => { } : field.onChange}
value={field.value ?? code.yn[0]?.val}
readOnly={readonly}
/>
</FormUi>
)}
@@ -8,7 +8,7 @@ import { Button } from "@common/components/ui";
import React, { useEffect, useState } from "react";
import type { z } from "zod";
export default function ChkgdModal({ type, obj, setIsModal, readonly }: { type: string; obj: any, setIsModal: (open: boolean) => void, readonly: boolean }) {
export default function ChkgdModal({ type, obj, setIsModal }: { type: string; obj: any, setIsModal: (open: boolean) => void }) {
const {
rainChkgdn,
rswtChkgdn,
@@ -247,7 +247,7 @@ export default function ChkgdModal({ type, obj, setIsModal, readonly }: { type:
}
></Title>
{!rainChkSttn.isSttn ? (
<Button className="mt-8 mr-7" onClick={allDataUpdate} disabled={!readonly}>
<Button className="mt-8 mr-7" onClick={allDataUpdate}>
저장
</Button>
) : (
@@ -274,7 +274,6 @@ export default function ChkgdModal({ type, obj, setIsModal, readonly }: { type:
setChGuidData={(data) => {
setChGuidData(data);
}}
readonly={readonly}
/>
<div className="card-header">
<h3 className="text-2xl font-medium text-label">
@@ -289,7 +288,6 @@ export default function ChkgdModal({ type, obj, setIsModal, readonly }: { type:
setChGuidData={(data) => {
setChGuidData(data);
}}
readonly={readonly}
/>
{type !== "RNB" && polutionData !== undefined ? (
@@ -312,7 +310,6 @@ export default function ChkgdModal({ type, obj, setIsModal, readonly }: { type:
setChGuidData={(data) => {
getPolutionData(data);
}}
readonly={readonly}
/>
</React.Fragment>
);
@@ -138,6 +138,7 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
});
});
}
console.log(tableData);
if (tableData && tableData.length > 0) {
setRuseTableData(tableData as any[]);
}
@@ -215,6 +216,9 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
(usageTotalObj as any)[key] = val;
}
const tableData = [...inUsageData, ...outUsageData, usageTotalObj];
console.log("inusageData", inUsageData)
console.log("outUsageData", outUsageData)
console.log("tableData", tableData)
setPrfData({
inPrf: inUsageData,
outPrf: outUsageData,
@@ -244,6 +248,10 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
}, [data, form])
useEffect(() => {
console.log("prfData", prfData);
}, [prfData])
return (
<>
<div>
@@ -12,13 +12,10 @@ import { useForm } from "react-hook-form";
import type { z } from "zod";
export default function CoDetailModal({
formObj,
onFormSubmit,
readonly
formObj,onFormSubmit
}: {
formObj: any;
onFormSubmit: (values: customLdrmnt) => void;
readonly?: boolean;
onFormSubmit:(values:customLdrmnt)=>void;
}) {
const defaultValues: z.infer<typeof ldrmntZod> = ldrmntZod.parse({});
const form = useForm<z.infer<typeof ldrmntZod>>({
@@ -55,11 +52,7 @@ export default function CoDetailModal({
<h1 className="text-2xl font-medium text-label col-span-10">
잠재수요처 상세정보
</h1>
<Button type="submit"
className="col-start-12 col-span-1"
size={"sm"}
disabled={readonly}
>
<Button type="submit" className="col-start-12 col-span-1" size={"sm"}>
저장
</Button>
</div>
@@ -78,6 +71,7 @@ export default function CoDetailModal({
</FormUi>
)}
/>
<div className="grid grid-cols-4 gap-2 mt-4">
<div className="col-span-2">
<FormField
@@ -92,9 +86,8 @@ export default function CoDetailModal({
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -115,13 +108,13 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
/>
</div>
</div>
<div className="grid grid-cols-4 gap-2 mt-4">
<div className="col-span-2">
<FormField
@@ -138,7 +131,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -159,7 +151,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -182,7 +173,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -203,7 +193,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -224,7 +213,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -247,12 +235,12 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
/>
</div>
<div className="col-span-2">
<FormField
control={form.control}
@@ -268,7 +256,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -291,7 +278,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -312,7 +298,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -333,13 +318,14 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={13}
readOnly={readonly}
/>
</FormUi>
)}
/>
</div>
</div>
<div className="grid grid-cols-5 gap-2 mt-4">
<div className="col-span-1">
<FormField
@@ -358,7 +344,6 @@ export default function CoDetailModal({
value={formatCommaNumber(field.value)}
min={0}
maxLength={8}
readOnly={readonly}
/>
</FormUi>
)}
@@ -380,7 +365,6 @@ export default function CoDetailModal({
value={formatCommaNumber(field.value)}
min={0}
maxLength={8}
readOnly={readonly}
/>
</FormUi>
)}
@@ -402,7 +386,6 @@ export default function CoDetailModal({
value={formatCommaNumber(field.value)}
min={0}
maxLength={8}
readOnly={readonly}
/>
</FormUi>
)}
@@ -424,7 +407,6 @@ export default function CoDetailModal({
value={formatCommaNumber(field.value)}
min={0}
maxLength={8}
readOnly={readonly}
/>
</FormUi>
)}
@@ -452,6 +434,7 @@ export default function CoDetailModal({
/>
</div>
</div>
<div className="grid grid-cols-12 gap-2 mt-4">
<div className="col-span-4">
<FormField
@@ -468,7 +451,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -489,7 +471,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -510,13 +491,13 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
/>
</div>
</div>
<div className="grid grid-cols-12 gap-2 mt-4">
<div className="col-span-4">
<FormField
@@ -533,7 +514,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -554,7 +534,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -575,13 +554,14 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
/>
</div>
</div>
<div className="grid grid-cols-12 gap-2 mt-4">
<div className="col-span-4">
<FormField
@@ -598,7 +578,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -619,7 +598,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -640,13 +618,14 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
/>
</div>
</div>
<div className="grid grid-cols-12 gap-2 mt-4">
<div className="col-span-4">
<FormField
@@ -663,7 +642,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -684,7 +662,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -705,13 +682,13 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
/>
</div>
</div>
<div className="grid grid-cols-12 gap-2 mt-4">
<div className="col-span-4">
<FormField
@@ -728,7 +705,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -749,7 +725,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -770,7 +745,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -793,7 +767,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
@@ -814,13 +787,13 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={txtSize}
readOnly={readonly}
/>
</FormUi>
)}
/>
</div>
</div>
<div className="grid grid-cols-4 gap-2 mt-4">
<div className="col-span-2">
<FormField
@@ -837,7 +810,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={50}
readOnly={readonly}
/>
</FormUi>
)}
@@ -858,7 +830,6 @@ export default function CoDetailModal({
}}
value={field.value ?? ""}
maxLength={50}
readOnly={readonly}
/>
</FormUi>
)}
@@ -1,4 +1,3 @@
import { Input } from "@common/components/ui";
import React, { useCallback, useEffect, useRef, useState } from "react";
type SearchType = {
@@ -11,7 +10,6 @@ type thisProps = {
setValue: (searchNm?: string) => void;
setRtnData: (rtnData: any) => void;
searchList?: any[];
readonly?:boolean
};
export default function SearchInputText({
label = undefined,
@@ -19,7 +17,6 @@ export default function SearchInputText({
setValue = () => {},
setRtnData = () => {},
searchList = undefined,
readonly = false, // 추가: readonly prop
}: thisProps) {
const [isOpen, setIsOpen] = useState(false);
@@ -68,14 +65,13 @@ export default function SearchInputText({
return (
<div ref={wrapperRef}>
<Input
<input
type="text"
value={textValue}
onChange={handleInputChange}
/* onFocus={() => setIsOpen(true)} */
className="w-full h-[3.2rem] !text-xl pl-3 text-gray-600 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder={`${label}을(를) 입력하세요`}
readOnly={readonly} // readonly 상태 적용
/>
{isOpen && (
<div className=" z-1 w-full mt-2 bg-white border border-gray-300 rounded-md shadow-lg h-90 overflow-auto">
@@ -17,14 +17,12 @@ export function GuideDetailsTable({
headList,
upheadList,
setChGuidData,
readonly
}: {
chgRes: any[];
headList: TableUpperProps[];
upheadList: chHeadType[];
type: string;
setChGuidData: (chgRes: any[]) => void;
readonly?: boolean;
}) {
const [inputData, setInputData] = useState<any[]>();
@@ -32,6 +30,7 @@ export function GuideDetailsTable({
setInputData(chgRes);
}, [chgRes]);
useEffect(() => {
setChGuidData(inputData ?? []);
@@ -44,7 +43,7 @@ export function GuideDetailsTable({
<Table variant="secondary">
<TableHeader className="font-bold">{headMakeprfmnc(headList, upheadList)}</TableHeader>
<TableBody >
{InputTableBody(inputData ?? [], headList, setInputData, readonly)}
{InputTableBody(inputData ?? [], headList, setInputData)}
</TableBody>
</Table>
</div>
@@ -25,7 +25,6 @@ export default function RainChkgdTable({
pageNation,
onPageChange,
pageCount,
readonly,
}: {
detailUp: (data: rainChkZodType[]) => void;
handleClick?: (data: any) => void;
@@ -34,7 +33,6 @@ export default function RainChkgdTable({
pageNation: number;
onPageChange: (page: number) => void;
pageCount: number;
readonly: boolean;
}) {
const { code, rainChkgdn, rainChkSttn, getRainSttnExcel } = useWrStore((state) => state);
const [makeTableData, setMakeTableData] = useState<any[]>([]);
@@ -193,8 +191,7 @@ export default function RainChkgdTable({
handleChange,
toggleSelection,
selectedIds,
handleCellClick,
readonly
handleCellClick
)}
</TableBody>
</Table>
@@ -26,7 +26,6 @@ export default function RswtChkgdTable({
pageNation,
onPageChange,
pageCount,
readonly = false,
}: {
detaiRswtlUpdate: (data: rswtrChkDetailsZodType[]) => void;
handleRswtClick?: (data: any) => void;
@@ -35,7 +34,6 @@ export default function RswtChkgdTable({
pageNation: number;
onPageChange: (page: number) => void;
pageCount: number;
readonly:boolean
}) {
const { code, rswtChkgdn, rswtChkSttn, rswtChkPolAndGuide, getRswtSttnExcel } = useWrStore(
(state) => state
@@ -151,8 +149,7 @@ export default function RswtChkgdTable({
handleChange,
toggleSelection,
selectedIds,
handleCellClick,
readonly
handleCellClick
)}
</TableBody>
</Table>
@@ -35,7 +35,6 @@ type RuseMngTableProps = {
indexBiz?: number;
form?: any;
formNm?: string;
readonly?: boolean;
};
const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
@@ -49,7 +48,6 @@ const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
form,
formNm,
indexBiz,
readonly= false
},
ref
) => {
@@ -113,7 +111,7 @@ const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
? formatCommaNumber(field.value)
: field.value || ""
}
readOnly={readonly|| head.readonly ? true : false}
readOnly={head.readonly ? true : false}
maxLength={head.maxLength?head.maxLength:15}
/>
) : head.type === "select" ? (
@@ -134,7 +132,7 @@ const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
field.onChange(val);
}
}}
readOnly={ readonly||head.readonly ? true : false}
readOnly={head.readonly ? true : false}
// Disabled prop removed as SelectBox does not support it
></SelectBox>
) : head.type === "date" ? (
@@ -151,18 +149,14 @@ const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
},
}}
selectClass={"w-full"}
readOnly={readonly||head.readonly ? true : false}
readOnly={head.readonly ? true : false}
/>
) : head.type === "checkbox" ? (
<Checkbox
className=""
checked={field.value || false}
onCheckedChange={(checked) => {
if(readonly || head.readonly) {
return;
}else{
field.onChange(checked);
}
field.onChange(checked);
}}
></Checkbox>
) : (
Binary file not shown.
Binary file not shown.
-2
View File
@@ -20,9 +20,7 @@
"preinstall": "npx only-allow pnpm"
},
"dependencies": {
"chart.js": "^4.4.8",
"react": "^18.3.1",
"react-chartjs-2": "^5.3.0",
"react-dom": "^18.3.1",
"zustand": "^5.0.3"
},
@@ -94,6 +94,7 @@ export default function LineBarchart({
// 데이터의 최대값 계산
const getMaxValue = (data: any[], keyPrefix: string) => {
if (!data || data.length === 0) return 0;
return Math.max(...data.map(item =>
Object.keys(item)
.filter(key => key.includes(keyPrefix))
@@ -0,0 +1,186 @@
"use client"
import type { CSSProperties } from "react";
import { Bar, CartesianGrid, ComposedChart, Legend, Line, Tooltip, XAxis, YAxis } from "recharts";
import {
ChartContainer,
type ChartConfig
} from "./lib/chart";
import type { ContentType } from "recharts/types/component/DefaultLegendContent";
// 툴크 커스텀 css
/** 차트 기본 스타일 */
const customStyles = {
legendContainer: {
display: "flex",
justifyContent: "center",
gap: "20px",
fontSize: "9px",
fontWeight : "bold",
marginTop: "10px",
} as CSSProperties,
};
type LineBarChartProps = {
chartConfig: ChartConfig | undefined;
chartData: any[] | undefined;
chartTitle: string;
chartClassName?: string;
graphSize?: number;
yFieldText?: string | undefined;
yFieldText2?: string | undefined;
showLegend?: boolean;
}
type LegendEntry = {
value: string;
color: string;
type?: string;
payload?: unknown;
};
type LegendProps = {
payload?: LegendEntry[];
};
// 커스텀 툴팁
const CustomTooltip = ({ active, payload, label }: { active?: boolean; payload?: Array<{ name: string; value: number; color: string }>; label?: string }) => {
if (active && payload && payload.length) {
return (
<div className="w-[180px] rounded bg-white p-2.5 shadow-[0px_2px_10px_rgba(0,0,0,0.2)]">
<p className="text-[12px] font-bold m-3">{label}</p>
{payload.map((item, index) => (
<div key={index} style={{ marginTop: "10px", display: "flex", alignItems: "center", gap: "8px" }}>
{/* 색상 박스 추가 (범례 색상과 동일) */}
<div style={{ width: "10px", height: "10px", backgroundColor: item.color, borderRadius: "50%" }}></div>
<span className="text-[11px] font-bold">{` ${item.name} : ${item.value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`}</span>
</div>
))}
</div>
);
}
return null;
};
// 커스텀 범례 (글씨 크기 키우기 + 스타일 추가)
const CustomLegend = (props: LegendProps) => {
const { payload } = props;
if (!payload) return null;
return (
<div style={customStyles.legendContainer}>
{payload.map((entry: LegendEntry, index: number) => (
<div key={`legend-${index}`} className="flex items-center gap-2">
<div className="w-[14px] h-[14px] ml-10" style={{ backgroundColor: entry.color }}></div>
<span className="text-[12px]">{entry.value}</span>
</div>
))}
</div>
);
};
export default function LineBarchart2({
chartConfig,
chartData,
chartTitle,
chartClassName = 'w-full h-full',
graphSize = 40,
yFieldText,
yFieldText2,
showLegend = true
}: LineBarChartProps) {
if (!chartData || chartData.length === 0) {
return <div>데이터가 없습니다.</div>;
}
// 데이터의 최대값 계산
const getMaxValue = (data: any[], keyPrefix: string) => {
if (!data || data.length === 0) return 0;
return Math.max(...data.map(item =>
Object.keys(item)
.filter(key => key.includes(keyPrefix))
.map(key => item[key])
).flat());
};
const lineMaxValue = getMaxValue(chartData, 'lineVal');
const barMaxValue = getMaxValue(chartData, 'barVal');
return (
<div className={chartClassName}>
{chartTitle && chartTitle !== "" && chartTitle !== "undefined" ? (
<div style={{ textAlign: "left", fontSize: "13px", fontWeight: "bold", marginTop:"13px", marginBottom: "10px" }}>
{chartTitle}
</div>
) : null}
<div className="h-[calc(100%-42px)] flex justify-center">
<ChartContainer config={chartConfig ?? {}} className="h-full w-full">
<ComposedChart
data={chartData}
height={graphSize * 7.5}
width={graphSize * 12.5}
margin={{ top: 5, right: 30, left: 20, bottom: 5 }}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="label" fontSize="8px" fontWeight="bold"/>
{/* 왼쪽 Y축: lineVal */}
{yFieldText && <YAxis
yAxisId="left"
className="text-[12px] font-bold"
tickCount={6}
orientation="left"
domain={[0, Math.ceil(lineMaxValue * 1)+170]}
label={{ value: yFieldText, angle: -90, position: 'insideLeft', offset: -8 }}
/>}
{/* 오른쪽 Y축: barVal */}
{yFieldText2 && <YAxis
yAxisId="right"
className="text-[12px] font-bold"
tickCount={6}
orientation="right"
domain={[0, Math.ceil(barMaxValue * 1)+20]}
label={{ value: yFieldText2, angle: -90, position: 'insideRight' }}
reversed={true}
/>}
<Tooltip content={<CustomTooltip active={undefined} payload={undefined} label={undefined} />} />
{showLegend && <Legend content={CustomLegend as ContentType}/>}
{/* 바 차트 (오른쪽 Y축 사용) */}
{Object.keys(chartData[0]).map((key, index) => {
const config = chartConfig?.[key];
if(key.includes("barVal")) {
return (
<Bar
key={`bar-${key}-${index}`}
yAxisId="right"
dataKey={key}
fill={config?.color || "black"}
name={String(config?.label || "Y축")}
maxBarSize={80}
/>
);
}
return null;
})}
{/* 라인 차트 (왼쪽 Y축 사용) */}
{Object.keys(chartData[0]).map((key, index) => {
const config = chartConfig?.[key];
if(key.includes("lineVal")) {
return (
<Line
key={`line-${key}-${index}`}
yAxisId="left"
type="linear"
dataKey={key}
stroke={config?.color || "black"}
strokeWidth={2}
dot={{r: 0}}
name={String(config?.label || "X축")}
/>
);
}
return null;
})}
</ComposedChart>
</ChartContainer>
</div>
</div>
);
}
@@ -2,6 +2,7 @@
import DoubleBarChart from './DoubleBar';
import DoughnutChart from './DoughnutChart';
import LineBarchart from './LineBarChart';
import LineBarchart2 from './LineBarChart2';
import LineChart from './LineChart';
/**차트 FORM */
@@ -14,6 +15,8 @@ const CHART_FORM = {
DN :'daughnut',
/**LINE,BAR차트 */
LINEBAR : 'linebar',
/**LINE,BAR차트 */
LINEBAR2 : 'linebar2',
/**더블바 차트 형태*/
DOUBLEBAR : 'doublebar'
};
@@ -72,6 +75,10 @@ function MainChart(props: MainChartProps) {
return (
<LineBarchart chartConfig={props.chartConfig} chartData={props.chartData} chartTitle={props.chartTitle} chartClassName={props.chartClassName} graphSize={props.graphSize} yFieldText={props.yFieldText} yFieldText2={props.yFieldText2} showLegend={props.showLegend}/>
);
} else if (props.chartForm == CHART_FORM.LINEBAR2){
return (
<LineBarchart2 chartConfig={props.chartConfig} chartData={props.chartData} chartTitle={props.chartTitle} chartClassName={props.chartClassName} graphSize={props.graphSize} yFieldText={props.yFieldText} yFieldText2={props.yFieldText2} showLegend={props.showLegend}/>
);
} else if (props.chartForm == CHART_FORM.DOUBLEBAR){
return (
<DoubleBarChart chartConfig={props.chartConfig} chartData={props.chartData} chartTitle={props.chartTitle} chartClassName={props.chartClassName} graphSize={props.graphSize} yFieldText={props.yFieldText} showLegend={props.showLegend}/>
@@ -20,6 +20,73 @@ import GisApp from './lib/gis.core';
export const GisContext = createContext({ gisCore: null, gisMap: null, treeData: null, checkedLayerIds: null });
export const useGisContext = () => useContext(GisContext);
export const searchUpperPpls = async (fcltMngNo) => {
const BASE_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || '';
const res = await fetch(`${BASE_URL}/v1/fcltmhl/upperPpls/${fcltMngNo}`, {
method: "GET",
});
let data = null;
if (res.ok) {
try {
// 응답이 비어있는지 확인
const contentLength = res.headers.get('content-length');
if (contentLength === '0') alert(`해당 맨홀의 상류관로를 찾을 수 없습니다.`);
// 응답 텍스트를 먼저 가져와서 빈 문자열인지 확인
const text = await res.text();
if (!text || text.trim() === '') alert(`해당 맨홀의 상류관로를 찾을 수 없습니다.`);
// JSON 파싱 시도
data = JSON.parse(text);
} catch (error) {
console.error('JSON parsing error:', error);
alert(`해당 맨홀의 상류관로를 찾을 수 없습니다.`);
}
}
const select = GisApp.Module.select;
const gisMap = GisApp.Module.core?.map;
let foundFeature = null;
data.forEach(item => {
const pplMngNo = item.ppl_mng_no.trim();
gisMap.getLayers().getArray().filter(e => e.get("lyrTyNm") == 'tb_ms_swage_ppl').forEach(layer => {
const source = layer.getSource?.();
if (source?.getFeatures) {
const features = source.getFeatures();
for (const f of features) {
if (f.values_.fclt_mng_no.trim() === pplMngNo) {
foundFeature = f;
break;
}
}
}
});
if (foundFeature) select.selectMultiFeature(foundFeature, true);
});
if (!foundFeature) alert(`해당 맨홀의 상류관로를 찾을 수 없습니다.`);
let geometry = foundFeature?.getGeometry();
if (geometry) {
let extent = geometry.getExtent();
gisMap.getView().fit(extent, {
duration: 300,
padding: [50, 50, 50, 50],
maxZoom: 14,
constrainResolution: true,
nearest: true,
});
}
};
function Gis({
isOpen,
@@ -418,6 +485,7 @@ function Gis({
onFeatureSelect={handleFeatureSelect}
/>
)}
{/* <GisLonLat /> */}
<GisToolBar />
<GisMapToggle />
<GisSelect onFeatureSelect={handleFeatureSelect} />
@@ -1,11 +1,11 @@
import {
MultiBackend,
Tree,
getBackendOptions,
DndProvider
getBackendOptions
} from "@minoru/react-dnd-treeview";
import { ChevronLeft, ChevronRight } from 'lucide-react';
import React, { useEffect, useState } from 'react';
import { DndProvider } from "react-dnd";
import { useGisContext } from './Gis';
import GisApp from './lib/gis.core';
@@ -42,15 +42,10 @@ GisApp.GOOGLE_SATELLITE_URL = `https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z
GisApp.GOOGLE_HYBRID_URL = `https://mt1.google.com/vt/lyrs=y&x={x}&y={y}&z={z}&key=${GisApp.GOOGLE_API_KEY}`;
GisApp.GOOGLE_3D_URL = `https://tile.googleapis.com/v1/3dtiles/root.json?key=${GisApp.GOOGLE_API_KEY}`;
// 인터넷망: NGII 정보
// TODO: NGII 정보
GisApp.NGII_API_KEY = '04trYP9_xwLAfALjwZ-B8g'; // NGII에서 발급받은 API 키
GisApp.NGII_WMTS_URL = `https://map.ngii.go.kr/openapi/Gettile.do?apikey=${GisApp.NGII_API_KEY}`;
//행정망: NGII 정보
//GisApp.NGII_API_KEY = 'BDE2BEF39DAFEC293AB6730150F222AC'; // NGII에서 발급받은 API 키
//GisApp.NGII_WMTS_URL = `http://10.98.25.94:18080/openapi/Gettile.do?apikey=${GisApp.NGII_API_KEY}`;
GisApp.EMAP_URL = '/emap/';
GisApp.EMAP_SATELLITE_URL = '/emap/satellite/';
GisApp.VWORLD_URL = 'https://xdworld.vworld.kr/2d/Base/service/{z}/{x}/{y}.png';
@@ -71,7 +71,7 @@ GisOlLayer.prototype = {
/**
* [사용]WFS 벡터 소스 반환
*/
getVectorSourceBbox: function (options) {
getVectorSourceGeoserver: function (options) {
let url = GisApp.GEOSERVER_URL;
let toProj = GisApp.TO_PROJ;
let lyrTyNm = options.lyrTyNm;
@@ -110,11 +110,8 @@ GisOlLayer.prototype = {
getVectorTileSource: function (options) {
let url = GisApp.GEOSERVER_URL;
let toProj = GisApp.TO_PROJ;
let lyrTyNm = options.lyrTyNm;
let typename = this.storageNm + lyrTyNm;
let params = {};
params['TYPENAME'] = typename;
params['TYPENAME'] = this.storageNm + options.typeName;
params['SERVICE'] = 'WFS';
params['VERSION'] = '1.1.0';
params['REQUEST'] = 'GetFeature';
@@ -122,14 +119,19 @@ GisOlLayer.prototype = {
params['OUTPUTFORMAT'] = 'application/json';
let strParams = new URLSearchParams(params).toString();
let source = new VectorSource({
let source = new VectorTile({
format: new GeoJSON(),
url: function (extent) {
return url + '?' + strParams;
tileUrlFunction: function (tileCoord, pixelRatio, projection) {
let filterStr = '&CQL_FILTER=bbox(GEOM,' + source.getTileGrid().getTileCoordExtent(tileCoord).join(',') + ",'" + projection.getCode() + "')";
if (options.flterSql) {
filterStr += ' AND ' + options.flterSql;
}
let paramWithUrl = url + '?' + strParams + filterStr;
return paramWithUrl;
},
strategy: all,
tileGrid: createXYZ,
});
return source;
return source;
},
@@ -140,9 +142,8 @@ GisOlLayer.prototype = {
option = option || {};
//레이어 생성
let returnLayer = this.makeLayer(option);
//레이어 소스 생성
let source = this.getVectorSourceBbox(option);
let source = this.getVectorSourceGeoserver(option);
returnLayer.setSource(source);
//스타일 추가
returnLayer.setStyle(this.gisStyle.getLayerStyleFunction(returnLayer, option));

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