diff --git a/apps/cs/middleware.ts b/apps/cs/middleware.ts index 79d2c8f65..38d32c79c 100644 --- a/apps/cs/middleware.ts +++ b/apps/cs/middleware.ts @@ -11,6 +11,8 @@ import { const serverApiUrl = process.env.NEXT_PUBLIC_SERVER_API_URL ?? "http://localhost:3000"; +const linkBackendApiHost = process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST ?? "http://localhost:8080"; + export function middleware(req: NextRequest) { const pathname = req.nextUrl.pathname; const searchParams = req.nextUrl.searchParams; @@ -52,6 +54,30 @@ export function middleware(req: NextRequest) { }); } + if (pathname.startsWith("/api/link")) { + const requestHeaders = new Headers(req.headers); + const token = req.cookies.get(CLAIM_NAME)?.value; + const userId = req.cookies.get(AUTH_USER_ID)?.value; + + // /api/link 경로를 제거하고 백엔드 API 경로로 변환 + const apiPath = pathname.replace("/api/link", ""); + const queryParams = searchParams.toString(); + const newUrl = `${linkBackendApiHost}${apiPath}${ + queryParams ? `?${queryParams}` : "" + }`; + + if (token) requestHeaders.set(CLAIM_NAME, token); + if (userId) requestHeaders.set(AUTH_USER_ID, userId); + + logMessages.push(` Link API Rewritten URL: ${newUrl}`); + logMessages.push("\n--------------------------------\n"); + console.log(logMessages.join("\n")); + + return NextResponse.rewrite(new URL(newUrl), { + headers: requestHeaders, + }); + } + if (pathname === "/") { return NextResponse.redirect(new URL("/dashboard", req.url)); } @@ -62,5 +88,5 @@ export function middleware(req: NextRequest) { } export const config = { - matcher: ["/server/:path*", "/attach-service/:path*", "/"], + matcher: ["/server/:path*", "/attach-service/:path*", "/api/link/:path*", "/"], }; diff --git a/apps/cs/src/entities/link/api/link-service.ts b/apps/cs/src/entities/link/api/link-service.ts index c607dd2c7..f0de32760 100644 --- a/apps/cs/src/entities/link/api/link-service.ts +++ b/apps/cs/src/entities/link/api/link-service.ts @@ -20,7 +20,7 @@ import { export class LinkApiService implements LinkService { public async getLinkList(params: LinkSearchParam): Promise { const response = await axios.get( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkList`, + `/api/link/getLinkList`, { params } ); return response.data; @@ -28,41 +28,41 @@ export class LinkApiService implements LinkService { public async getLinkInfo(linkSn: string): Promise { const response = await axios.get( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkInfo/${linkSn}`, + `/api/link/getLinkInfo/${linkSn}`, ); return response.data; } public async linkQuickStart(linkSn: string): Promise { const response = await axios.patch( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/linkQuickStart/${linkSn}`, + `/api/link/linkQuickStart/${linkSn}`, ); return response.data; } public async updateLinkInfo(data: LinkFormData): Promise { await axios.put( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/updateLinkInfo`, + '/api/link/updateLinkInfo', data, ); } public async insertLinkInfo(data: LinkFormData): Promise { await axios.post( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/insertLinkInfo`, + '/api/link/insertLinkInfo', data, ); } public async deleteLink(linkSn: string): Promise { await axios.delete( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/deleteLink/${linkSn}`, + `/api/link/deleteLink/${linkSn}`, ); } public async getLinkLogList(params: LinkSearchParam): Promise { const response = await axios.get( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/selectLinkLoglist`, + '/api/link/selectLinkLoglist', { params } ); return response.data; @@ -70,7 +70,7 @@ export class LinkApiService implements LinkService { public async getLinkStatsList(params: LinkSearchParam): Promise { const response = await axios.get( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/selectLinkStats`, + '/api/link/selectLinkStats', { params } ); return response.data; @@ -78,14 +78,14 @@ export class LinkApiService implements LinkService { public async getLinkVrblList(linkSn: string): Promise { const response = await axios.get( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkVrblList/${linkSn}`, + `/api/link/getLinkVrblList/${linkSn}`, ); return response.data; } public async insertLinkVrbl(data: LinkVrblFormData): Promise { const response = await axios.post( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/insertLinkVrbl`, + '/api/link/insertLinkVrbl', data, ); @@ -94,7 +94,7 @@ export class LinkApiService implements LinkService { public async deleteLinkVrbl(data: string[]): Promise { await axios.delete( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/deleteLinkVrbl`, + '/api/link/deleteLinkVrbl', { data } @@ -103,35 +103,35 @@ export class LinkApiService implements LinkService { public async getLinkVrblInfo(linkVrblSn: string): Promise { const response = await axios.get( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkVrblInfo/${linkVrblSn}`, + `/api/link/getLinkVrblInfo/${linkVrblSn}`, ); return response.data; } public async updateLinkVrblInfo(data: LinkVrblFormData): Promise { await axios.put( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/updateLinkVrblInfo`, + '/api/link/updateLinkVrblInfo', data, ); } public async getLinkTableInfo(linkSn: string): Promise { const response = await axios.get( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkTableInfo/${linkSn}`, + `/api/link/getLinkTableInfo/${linkSn}`, ); return response.data; } public async getLinkTableColList(linkSn: string): Promise { const response = await axios.get( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkTableColList/${linkSn}`, + `/api/link/getLinkTableColList/${linkSn}`, ); return response.data; } public async getLinkTableColInfo(params: { colSn: string; tblSn:string; }): Promise { const response = await axios.get( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkTableColInfo`, + '/api/link/getLinkTableColInfo', { params } ); return response.data; @@ -139,14 +139,14 @@ export class LinkApiService implements LinkService { public async insertLinkTableCol(data: LinkTableColData): Promise { await axios.post( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/insertLinkTableCol`, + '/api/link/insertLinkTableCol', data ); } public async deleteLinkTableCol(data: string[]): Promise { await axios.delete( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/deleteLinkTableCol`, + '/api/link/deleteLinkTableCol', { data }, @@ -155,35 +155,35 @@ export class LinkApiService implements LinkService { public async updateLinkTableCol(data: LinkTableColData): Promise { axios.put( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/updateLinkTableCol`, + '/api/link/updateLinkTableCol', data, ); } public async insertLinkTableInfo(data: LinkTableFormData): Promise { await axios.post( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/insertLinkTableInfo`, + '/api/link/insertLinkTableInfo', data ); } public async updateLinkTableInfo(data: LinkTableFormData): Promise { await axios.put( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/updateLinkTableInfo`, + '/api/link/updateLinkTableInfo', data ); } public async countLinkTblNm(tblNm: string): Promise<{count: number, tbl_sn: string}> { const response = await axios.get<{count: number, tbl_sn: string}>( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/countLinkTblNm/${tblNm}`, + `/api/link/countLinkTblNm/${tblNm}`, ); return response.data; } public async updateLinkResultCode(linkSn: string): Promise { await axios.patch( - `${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/updateLinkResultCode/${linkSn}`, + `/api/link/updateLinkResultCode/${linkSn}`, ); } } diff --git a/apps/cs/src/pages/dashboard/ui/dashboard-page.tsx b/apps/cs/src/pages/dashboard/ui/dashboard-page.tsx index 4bae35f7c..b217531dd 100644 --- a/apps/cs/src/pages/dashboard/ui/dashboard-page.tsx +++ b/apps/cs/src/pages/dashboard/ui/dashboard-page.tsx @@ -118,7 +118,7 @@ function DashboardPage() { 금일 신규 가입자 {data?.memberTodayCnt ? data.memberTodayCnt.toLocaleString() - : "-"} + : "0"} 명

@@ -141,7 +141,7 @@ function DashboardPage() {

금일 + - {data?.pstTodayCnt ? data.pstTodayCnt.toLocaleString() : "-"}{" "} + {data?.pstTodayCnt ? data.pstTodayCnt.toLocaleString() : "0"} 등록

@@ -168,7 +168,7 @@ function DashboardPage() { 전일 대비 + {data?.accessBefDayPer ? data.accessBefDayPer.toLocaleString() - : "-"} + : "0"} %

diff --git a/apps/cs/src/pages/linkParams/ui/link-params-page.tsx b/apps/cs/src/pages/linkParams/ui/link-params-page.tsx index b3806e712..d46a9d863 100644 --- a/apps/cs/src/pages/linkParams/ui/link-params-page.tsx +++ b/apps/cs/src/pages/linkParams/ui/link-params-page.tsx @@ -70,7 +70,7 @@ function LinkParamsPage() { // Link 목록 쿼리 const query = useQuery({ - queryKey: [`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkList`, linkSearchParam], + queryKey: ['api/link/getLinkList', linkSearchParam], queryFn: () => LinkApi.getLinkList({ ...linkSearchParam, page: pagination.pageIndex, @@ -142,9 +142,10 @@ function LinkParamsPage() { const { mutateAsync: deleteLinkVrbl } = useMutation({ mutationFn: async (data: string[]) => await LinkApi.deleteLinkVrbl(data), onSuccess: async () => { - await queryClient.invalidateQueries({ + await queryClient.refetchQueries({ queryKey: ['linkVrblList', selectedLink.linkSn] }); + setSelectedVrblIds([]); alert('삭제되었습니다.'); } diff --git a/apps/cs/src/pages/linkTable/ui/link-table-page.tsx b/apps/cs/src/pages/linkTable/ui/link-table-page.tsx index 11f478b71..cbdf4627a 100644 --- a/apps/cs/src/pages/linkTable/ui/link-table-page.tsx +++ b/apps/cs/src/pages/linkTable/ui/link-table-page.tsx @@ -67,7 +67,7 @@ function LinkTablePage() { }; const query = useQuery({ - queryKey: [`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkList`, linkSearchParam], + queryKey: ['/api/link/getLinkList', linkSearchParam], queryFn: () => LinkApi.getLinkList({ ...linkSearchParam, page: pagination.pageIndex, diff --git a/apps/cs/src/pages/user-statistics/api/connection-log-service.ts b/apps/cs/src/pages/user-statistics/api/connection-log-service.ts new file mode 100644 index 000000000..0e2daeb5b --- /dev/null +++ b/apps/cs/src/pages/user-statistics/api/connection-log-service.ts @@ -0,0 +1,33 @@ +import { client } from "@/shared/api"; +import { ENDPOINT } from "@/shared/config"; +import { + type ConnectionLogParams, + type ConnectionLogList, + type ConnectionStatisticsParams, + type ConnectionStatistics, + type ConnectionLogService, +} from "../model/connection-log-interface"; + +class ConnectionLogApiService implements ConnectionLogService { + async getConnectionLog( + params: ConnectionLogParams, + ): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.CONNECTION_LOG}`, + { params }, + ); + return response.data; + } + + async getConnectionStatistics( + params: ConnectionStatisticsParams, + ): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.CONNECTION_LOG}/stat`, + { params }, + ); + return response.data; + } +} + +export const ConnectionLogApi = new ConnectionLogApiService(); diff --git a/apps/cs/src/pages/user-statistics/api/index.ts b/apps/cs/src/pages/user-statistics/api/index.ts deleted file mode 100644 index 802b91e30..000000000 --- a/apps/cs/src/pages/user-statistics/api/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { UserStatisticsApi } from "./user-statistics-service"; diff --git a/apps/cs/src/pages/user-statistics/api/user-statistics-service.ts b/apps/cs/src/pages/user-statistics/api/user-statistics-service.ts deleted file mode 100644 index 10c90c024..000000000 --- a/apps/cs/src/pages/user-statistics/api/user-statistics-service.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { - type AccessLog, - type AccessLogParams, - type AccessLogService, - type PageableList, -} from "../model/user-statistics-interface"; - -// 목 데이터 -const mockAccessLogs: AccessLog[] = [ - { - no: 1, - accessTime: "2024-01-15 14:30:25", - accessIp: "192.168.1.100", - accessRegion: "서울특별시", - urlPath: "/index", - browser: "Chrome", - site: "SITE1", - accessType: "메인", - }, - { - no: 2, - accessTime: "2024-01-15 14:28:15", - accessIp: "203.241.50.123", - accessRegion: "부산광역시", - urlPath: "/board/list", - browser: "Edge", - site: "SITE2", - accessType: "게시판", - }, - { - no: 3, - accessTime: "2024-01-15 14:25:42", - accessIp: "175.223.45.67", - accessRegion: "대구광역시", - urlPath: "/statistics", - browser: "Safari", - site: "SITE1", - accessType: "통계", - }, - { - no: 4, - accessTime: "2024-01-15 14:22:18", - accessIp: "211.252.87.45", - accessRegion: "인천광역시", - urlPath: "/contents/view", - browser: "Firefox", - site: "SITE3", - accessType: "컨텐츠", - }, - { - no: 5, - accessTime: "2024-01-15 14:20:33", - accessIp: "121.254.12.89", - accessRegion: "광주광역시", - urlPath: "/search", - browser: "Chrome", - site: "SITE1", - accessType: "검색", - }, -]; - -// 목 API 서비스 -class UserStatisticsApiImpl implements AccessLogService { - async getAccessLogList( - params: AccessLogParams, - ): Promise> { - // 실제 API 호출 대신 목 데이터 반환 - const { page = 0, size = 10 } = params; - - // 필터링 로직 (실제로는 서버에서 처리) - let filteredLogs = [...mockAccessLogs]; - - if (params.urlPath) { - filteredLogs = filteredLogs.filter((log) => - log.urlPath.toLowerCase().includes(params.urlPath!.toLowerCase()), - ); - } - - if (params.accessIp) { - filteredLogs = filteredLogs.filter((log) => - log.accessIp.includes(params.accessIp!), - ); - } - - if (params.accessRegion) { - filteredLogs = filteredLogs.filter((log) => - log.accessRegion.includes(params.accessRegion!), - ); - } - - if (params.browser) { - filteredLogs = filteredLogs.filter( - (log) => log.browser.toLowerCase() === params.browser!.toLowerCase(), - ); - } - - if (params.siteId) { - filteredLogs = filteredLogs.filter((log) => log.site === params.siteId); - } - - // 페이지네이션 - const start = page * size; - const end = start + size; - const paginatedLogs = filteredLogs.slice(start, end); - - // 목 응답 생성 - return { - content: paginatedLogs, - pageable: { - pageNumber: page, - pageSize: size, - sort: { - empty: true, - sorted: false, - unsorted: true, - }, - offset: page * size, - paged: true, - unpaged: false, - }, - last: (page + 1) * size >= filteredLogs.length, - totalPages: Math.ceil(filteredLogs.length / size), - totalElements: filteredLogs.length, - size, - number: page, - sort: { - empty: true, - sorted: false, - unsorted: true, - }, - first: page === 0, - numberOfElements: paginatedLogs.length, - empty: paginatedLogs.length === 0, - }; - } -} - -export const UserStatisticsApi = new UserStatisticsApiImpl(); diff --git a/apps/cs/src/pages/user-statistics/model/chart-data.ts b/apps/cs/src/pages/user-statistics/model/chart-data.ts index c836a4e5d..455dcac56 100644 --- a/apps/cs/src/pages/user-statistics/model/chart-data.ts +++ b/apps/cs/src/pages/user-statistics/model/chart-data.ts @@ -1,148 +1,103 @@ -import { type ChartData, type ChartOptions } from "chart.js"; - -// 일별 접속 현황 차트 데이터 -export const monthlyStatisticsData = { - labels: [ - "1일", - "2일", - "3일", - "4일", - "5일", - "6일", - "7일", - "8일", - "9일", - "10일", - "11일", - "12일", - "13일", - "14일", - "15일", - ], - datasets: [ - { - type: "bar" as const, - label: "페이지뷰", - data: [ - 850, 1000, 750, 750, 700, 750, 780, 800, 850, 900, 1200, 1700, 2300, - 2100, 2600, - ], - backgroundColor: "rgba(54, 162, 235, 0.8)", - order: 2, - }, - { - type: "line" as const, - label: "신규 접속자", - data: [ - 700, 600, 500, 550, 500, 550, 500, 550, 600, 850, 1200, 1500, 1700, - 2300, 2200, - ], - borderColor: "rgba(255, 99, 132, 0.8)", - borderWidth: 2, - tension: 0.4, - pointRadius: 3, - order: 0, - }, - { - type: "line" as const, - label: "총 접속자", - data: [ - 200, 300, 400, 500, 600, 500, 550, 500, 400, 500, 350, 800, 900, 1200, - 1300, - ], - borderColor: "rgba(75, 192, 192, 0.8)", - borderWidth: 2, - tension: 0.4, - pointRadius: 3, - order: 1, - }, - ], -}; - -export const monthlyStatisticsOptions: ChartOptions<"bar"> = { - responsive: true, - maintainAspectRatio: false, - plugins: { - legend: { - position: "top" as const, - }, - tooltip: { - mode: "index" as const, - intersect: false, - }, - }, -}; - -// 사이트별 접속자 차트 데이터 -export const siteVisitorsData: ChartData<"bar"> = { - labels: ["SITE1", "SITE2", "SITE3", "SITE4", "SITE5"], - datasets: [ - { - label: "사이트별 접속자", - data: [2500, 2000, 1500, 1200, 800], - backgroundColor: [ - "rgba(54, 162, 235, 0.8)", - "rgba(153, 102, 255, 0.8)", - "rgba(255, 99, 132, 0.8)", - "rgba(255, 159, 64, 0.8)", - "rgba(255, 205, 86, 0.8)", - ], - borderWidth: 1, - }, - ], -}; - -export const siteVisitorsOptions: ChartOptions<"bar"> = { - responsive: true, - maintainAspectRatio: false, - indexAxis: "y" as const, - plugins: { - legend: { - display: false, - }, - }, -}; - -// 브라우저별 접속자 차트 데이터 -export const browserStatisticsData: ChartData<"doughnut"> = { - labels: ["Chrome", "Edge", "Safari", "Firefox", "Internet Explorer"], - datasets: [ - { - data: [45, 25, 15, 10, 5], - backgroundColor: [ - "rgba(54, 162, 235, 0.8)", - "rgba(153, 102, 255, 0.8)", - "rgba(255, 99, 132, 0.8)", - "rgba(255, 159, 64, 0.8)", - "rgba(255, 205, 86, 0.8)", - ], - borderColor: [ - "rgba(54, 162, 235, 1)", - "rgba(153, 102, 255, 1)", - "rgba(255, 99, 132, 1)", - "rgba(255, 159, 64, 1)", - "rgba(255, 205, 86, 1)", - ], - borderWidth: 1, - }, - ], -}; - -export const browserStatisticsOptions: ChartOptions<"doughnut"> = { - responsive: true, - maintainAspectRatio: false, - plugins: { - legend: { - position: "bottom" as const, - }, - }, -}; +import type { ChartData, ChartOptions } from "chart.js"; +import { getCssVariableValue } from "@common/components"; +import type { ConnectionStatistics } from "./connection-log-interface"; export const chartData = { - monthlyStatisticsData, - monthlyStatisticsOptions, - siteVisitorsData, - siteVisitorsOptions, - browserStatisticsData, - browserStatisticsOptions, + day: ( + data: ConnectionStatistics, + ): { + data: ChartData<"line">; + options: ChartOptions<"line">; + } => { + return { + data: { + labels: data.dayList.map((item) => item.dayYmd), + datasets: [ + { + type: "line", + label: "접속자 수", + data: data.dayList.map((item) => item.accessCnt), + borderColor: getCssVariableValue("--chart-1"), + }, + ], + }, + options: { + maintainAspectRatio: false, + scales: { + y: { + ticks: { + precision: 0, + }, + }, + }, + }, + }; + }, + site: ( + data: ConnectionStatistics, + ): { + data: ChartData<"bar">; + options: ChartOptions<"bar">; + } => { + return { + data: { + labels: data.siteList.map((item) => item.siteNm), + datasets: [ + { + type: "bar", + label: "사이트별 접속자", + data: data.siteList.map((item) => item.accessCnt), + backgroundColor: data.siteList.map((_, index) => + getCssVariableValue(`--chart-${(index % 5) + 1}`), + ), + }, + ], + }, + options: { + maintainAspectRatio: false, + indexAxis: "y", + scales: { + x: { + ticks: { + precision: 0, + }, + }, + }, + plugins: { + legend: { + display: false, + }, + }, + }, + }; + }, + browser: ( + data: ConnectionStatistics, + ): { + data: ChartData<"doughnut">; + options: ChartOptions<"doughnut">; + } => { + return { + data: { + labels: data.browserList.map((item) => item.wbsrKndNm), + datasets: [ + { + type: "doughnut", + data: data.browserList.map((item) => item.accessCnt), + backgroundColor: data.browserList.map((_, index) => + getCssVariableValue(`--chart-${(index % 5) + 1}`), + ), + }, + ], + }, + options: { + maintainAspectRatio: false, + plugins: { + legend: { + position: "bottom", + }, + }, + }, + }; + }, }; diff --git a/apps/cs/src/pages/user-statistics/model/connection-log-interface.ts b/apps/cs/src/pages/user-statistics/model/connection-log-interface.ts new file mode 100644 index 000000000..6fbf4dc15 --- /dev/null +++ b/apps/cs/src/pages/user-statistics/model/connection-log-interface.ts @@ -0,0 +1,72 @@ +import type { PageableList, PageableParams } from "@/shared/model"; + +export interface ConnectionLogParams extends PageableParams { + keywordType?: string; + keyword?: string; + siteId?: string; + cntnIp?: string; + cntnRgn?: string; + wbsrKnd?: string; + urlPath?: string; + cntnDtStart?: string; + cntnDtEnd?: string; +} + +export interface ConnectionLog { + cntnSn: number; + cntnDt: string; + cntnId: string; + cntnIp: string; + cntnRgn: string; + wbsrKnd: string; + menuCd: number; + siteId: string; + urlPath: string; + siteNm: string; + menuNm: string; + wbsrKndNm: string; +} + +export interface ConnectionStatisticsParams { + keywordType?: string; + keyword?: string; + siteId?: string; + cntnIp?: string; + cntnRgn?: string; + wbsrKnd?: string; + urlPath?: string; + cntnDtStart?: string; + cntnDtEnd?: string; +} + +interface DayConnectionStatistics { + dayYmd: string; + accessCnt: number; +} + +interface SiteConnectionStatistics { + siteId: string; + siteNm: string; + accessCnt: number; +} + +interface BrowserConnectionStatistics { + wbsrKnd: string; + wbsrKndNm: string; + accessCnt: number; +} + +export interface ConnectionStatistics { + dayList: DayConnectionStatistics[]; + siteList: SiteConnectionStatistics[]; + browserList: BrowserConnectionStatistics[]; +} + +export type ConnectionLogList = PageableList; + +export interface ConnectionLogService { + getConnectionLog(params: ConnectionLogParams): Promise; + getConnectionStatistics( + params: ConnectionStatisticsParams, + ): Promise; +} diff --git a/apps/cs/src/pages/user-statistics/model/table-columns.ts b/apps/cs/src/pages/user-statistics/model/table-columns.ts index c0d53380e..09fe58adf 100644 --- a/apps/cs/src/pages/user-statistics/model/table-columns.ts +++ b/apps/cs/src/pages/user-statistics/model/table-columns.ts @@ -1,39 +1,46 @@ -import { createColumnHelper } from "@tanstack/react-table"; -import { type AccessLog } from "./user-statistics-interface"; +import type { ColumnDef } from "@tanstack/react-table"; +import type { ConnectionLog } from "./connection-log-interface"; +import dayjs from "dayjs"; -const columnHelper = createColumnHelper(); - -export const columns = [ - columnHelper.accessor("no", { +export const columns: ColumnDef[] = [ + { header: "No", - cell: (info) => info.getValue(), - }), - columnHelper.accessor("accessTime", { + 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: "cntnDt", header: "접속일시", - cell: (info) => info.getValue(), - }), - columnHelper.accessor("accessIp", { + cell: ({ row }) => { + return dayjs(row.original.cntnDt).format("YYYY-MM-DD HH:mm:ss"); + }, + }, + { + accessorKey: "cntnIp", header: "접속IP", - cell: (info) => info.getValue(), - }), - columnHelper.accessor("accessRegion", { + }, + { + accessorKey: "cntnRgn", header: "접속지역", - cell: (info) => info.getValue(), - }), - columnHelper.accessor("urlPath", { + }, + { + accessorKey: "urlPath", header: "URL경로", - cell: (info) => info.getValue(), - }), - columnHelper.accessor("browser", { + }, + { + accessorKey: "wbsrKndNm", header: "브라우저", - cell: (info) => info.getValue(), - }), - columnHelper.accessor("site", { + }, + { + accessorKey: "siteNm", header: "사이트", - cell: (info) => info.getValue(), - }), - columnHelper.accessor("accessType", { + }, + { + accessorKey: "menuNm", header: "메뉴명", - cell: (info) => info.getValue(), - }), + }, ]; diff --git a/apps/cs/src/pages/user-statistics/model/user-statistics-interface.ts b/apps/cs/src/pages/user-statistics/model/user-statistics-interface.ts deleted file mode 100644 index 124d91044..000000000 --- a/apps/cs/src/pages/user-statistics/model/user-statistics-interface.ts +++ /dev/null @@ -1,56 +0,0 @@ -export interface AccessLog { - no: number; - accessTime: string; - accessIp: string; - accessRegion: string; - urlPath: string; - browser: string; - site: string; - accessType: string; -} - -export interface AccessLogParams { - page?: number; - size?: number; - urlPath?: string; - accessIp?: string; - accessRegion?: string; - browser?: string; - accessDateStart?: string; - accessDateEnd?: string; - siteId?: string; - sort?: string; -} - -export interface AccessLogService { - getAccessLogList(params: AccessLogParams): Promise>; -} - -export interface PageableList { - content: T[]; - pageable: { - pageNumber: number; - pageSize: number; - sort: { - empty: boolean; - sorted: boolean; - unsorted: boolean; - }; - offset: number; - paged: boolean; - unpaged: boolean; - }; - last: boolean; - totalPages: number; - totalElements: number; - size: number; - number: number; - sort: { - empty: boolean; - sorted: boolean; - unsorted: boolean; - }; - first: boolean; - numberOfElements: number; - empty: boolean; -} diff --git a/apps/cs/src/pages/user-statistics/ui/user-statistics-page.tsx b/apps/cs/src/pages/user-statistics/ui/user-statistics-page.tsx index 9fedb47f4..801ca5eb0 100644 --- a/apps/cs/src/pages/user-statistics/ui/user-statistics-page.tsx +++ b/apps/cs/src/pages/user-statistics/ui/user-statistics-page.tsx @@ -15,9 +15,8 @@ import { Filler, Legend, Tooltip, - type ChartData, } from "chart.js"; -import { Bar, Doughnut } from "react-chartjs-2"; +import { Bar, Doughnut, Line } from "react-chartjs-2"; import { Button, Input, @@ -30,11 +29,13 @@ import { } from "@common/components"; import { SiteSelect } from "@/entities/site"; import { useDataTable } from "@/shared/lib"; +import { ENDPOINT } from "@/shared/config"; +import { NoData } from "@/shared/ui/no-data"; import { InputDateRangePicker } from "@/shared/ui/input-date-range-picker"; -import { UserStatisticsApi } from "../api"; +import { ConnectionLogApi } from "../api/connection-log-service"; import { chartData } from "../model/chart-data"; import { columns } from "../model/table-columns"; -import { type AccessLogParams } from "../model/user-statistics-interface"; +import type { ConnectionStatisticsParams } from "../model/connection-log-interface"; ChartJS.register( CategoryScale, @@ -65,25 +66,31 @@ function UserStatisticsPage() { }); const [keywordType, setKeywordType] = useState(""); const [keyword, setKeyword] = useState(""); + const [siteId, setSiteId] = useState(""); const [presetDateRange, setPresetDateRange] = useState("1W"); const [dateRange, setDateRange] = useState(defaultDateRange); - const [searchParams, setSearchParams] = useState({ - urlPath: "", - accessIp: "", - accessRegion: "", - browser: "", - accessDateStart: dayjs().subtract(7, "day").format("YYYY-MM-DD"), - accessDateEnd: dayjs().format("YYYY-MM-DD"), - sort: "accessTime,desc", + const [searchParams, setSearchParams] = useState({ + keywordType: "", + keyword: "", + siteId: "", + cntnDtStart: dayjs(defaultDateRange.from).format("YYYY-MM-DD"), + cntnDtEnd: dayjs(defaultDateRange.to).format("YYYY-MM-DD"), }); const query = useQuery({ - queryKey: ["user-statistics", searchParams, pagination], + queryKey: [ENDPOINT.CMS_SERVICE.CONNECTION_LOG, searchParams], queryFn: () => - UserStatisticsApi.getAccessLogList({ + ConnectionLogApi.getConnectionLog({ + ...searchParams, + }), + placeholderData: keepPreviousData, + }); + + const { data: connectionStatisticsData } = useQuery({ + queryKey: [ENDPOINT.CMS_SERVICE.CONNECTION_LOG, searchParams], + queryFn: () => + ConnectionLogApi.getConnectionStatistics({ ...searchParams, - page: pagination.pageIndex, - size: pagination.pageSize, }), placeholderData: keepPreviousData, }); @@ -139,54 +146,30 @@ function UserStatisticsPage() { const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); - setPagination({ - ...pagination, - pageIndex: 0, - }); - - // 검색 조건에 따라 검색 파라미터 설정 - const params: AccessLogParams = { - sort: "accessTime,desc", - accessDateStart: dateRange.from + const params: ConnectionStatisticsParams = { + keywordType, + keyword, + siteId, + cntnDtStart: dateRange.from ? dayjs(dateRange.from).format("YYYY-MM-DD") : "", - accessDateEnd: dateRange.to - ? dayjs(dateRange.to).format("YYYY-MM-DD") - : "", + cntnDtEnd: dateRange.to ? dayjs(dateRange.to).format("YYYY-MM-DD") : "", }; - - // 검색어 타입에 따라 파라미터 설정 - switch (keywordType) { - case "urlPath": - params.urlPath = keyword; - break; - case "ip": - params.accessIp = keyword; - break; - case "region": - params.accessRegion = keyword; - break; - case "browser": - params.browser = keyword; - break; - } - setSearchParams(params); }; const handleReset = () => { setKeywordType(""); setKeyword(""); + setSiteId(""); setDateRange(defaultDateRange); setPresetDateRange("1W"); setSearchParams({ - urlPath: "", - accessIp: "", - accessRegion: "", - browser: "", - accessDateStart: dayjs().subtract(7, "day").format("YYYY-MM-DD"), - accessDateEnd: dayjs().format("YYYY-MM-DD"), - sort: "accessTime,desc", + keywordType: "", + keyword: "", + siteId: "", + cntnDtStart: dayjs(defaultDateRange.from).format("YYYY-MM-DD"), + cntnDtEnd: dayjs(defaultDateRange.to).format("YYYY-MM-DD"), }); }; @@ -210,7 +193,11 @@ function UserStatisticsPage() { setDateRange={handleDateRangeChange} /> - + setSiteId(value)} + /> - {/* 차트 영역 */}
- {/* 일별 접속 현황 */}
-

일별 접속 현황

+

일별 접속 현황

- } - options={chartData.monthlyStatisticsOptions} - /> + {connectionStatisticsData?.dayList?.length ? ( + + ) : ( + + )}
- {/* 사이트별 접속자 */}
-

사이트별 접속자

+

사이트별 접속자

- + {connectionStatisticsData?.siteList?.length ? ( + + ) : ( + + )}
- {/* 브라우저별 접속자 */}
-

브라우저별 접속자

+

브라우저별 접속자

- + {connectionStatisticsData?.browserList?.length ? ( + + ) : ( + + )}
diff --git a/apps/cs/src/shared/config/api.ts b/apps/cs/src/shared/config/api.ts index 6db62f1a0..ce6f61381 100644 --- a/apps/cs/src/shared/config/api.ts +++ b/apps/cs/src/shared/config/api.ts @@ -55,6 +55,7 @@ export const ENDPOINT = { MANAGER_IP: "/cms-service/api/v1/mgrip", APILOG: "/cms-service/api/v1/api-logs", SITE_AUTHORITY: "/cms-service/api/v1/site-authrt", + CONNECTION_LOG: "/cms-service/api/v1/cntnlog", }, BOARD_SERVICE: { BBS: "/board-service/api/v1/bbs", diff --git a/apps/cs/src/widgets/post/ui/post-action.tsx b/apps/cs/src/widgets/post/ui/post-action.tsx index 421cb4542..860d8dad8 100644 --- a/apps/cs/src/widgets/post/ui/post-action.tsx +++ b/apps/cs/src/widgets/post/ui/post-action.tsx @@ -25,6 +25,7 @@ function PostAction({ children, handleDelete }: PostActionProps) { const { prompt } = useSelectPrompt(selectData); const bbsInfo = useMenuStore((state) => state.bbsInfo); const userInfo = useUserStore((state) => state.userInfo); + const postPageLink = `/bbs/${bbsInfo?.bbsTypeCd.toLowerCase()}/${bbsInfo?.bbsId}`; const onDelete = async () => { const { resolved, value } = await prompt("삭제 사유를 입력해주세요."); @@ -64,7 +65,7 @@ function PostAction({ children, handleDelete }: PostActionProps) { size="lg" color="white" type="button" - onClick={() => router.back()} + onClick={() => router.push(postPageLink)} > 목록 diff --git a/apps/dm/.env.development b/apps/dm/.env.development index 96f4da6f5..b93394fe0 100644 --- a/apps/dm/.env.development +++ b/apps/dm/.env.development @@ -1,8 +1,8 @@ NEXT_PUBLIC_SITE_ID = DM -NEXT_PUBLIC_PORT = 3000 -NEXT_PUBLIC_PROXY_HOST = http://localhost:3000 -NEXT_PUBLIC_DM_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1 +NEXT_PUBLIC_PORT = 11035 +NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11035 NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000 +NEXT_PUBLIC_DM_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1 NEXT_PUBLIC_FO_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1 NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000 NEXT_PUBLIC_CS_TUS_UPLOAD = /attach-service/api/v1/tus/upload diff --git a/apps/dm/.env.local b/apps/dm/.env.local index b60a1d86f..8ac1f688a 100644 --- a/apps/dm/.env.local +++ b/apps/dm/.env.local @@ -3,9 +3,9 @@ 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 = 11035 +NEXT_PUBLIC_PORT = 3005 #NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11035 -NEXT_PUBLIC_PROXY_HOST = http://localhost:3000/ +NEXT_PUBLIC_PROXY_HOST = http://localhost:3005/ NEXT_PUBLIC_DM_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1 NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000 NEXT_PUBLIC_FO_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1 diff --git a/apps/dm/app/(base-layout)/pages/sdmMng/sdmApplyList/page.tsx b/apps/dm/app/(base-layout)/pages/sdmMng/sdmApplyList/page.tsx index 212eca6e7..ee86a9df5 100644 --- a/apps/dm/app/(base-layout)/pages/sdmMng/sdmApplyList/page.tsx +++ b/apps/dm/app/(base-layout)/pages/sdmMng/sdmApplyList/page.tsx @@ -7,7 +7,7 @@ import ListDiv from '@common/business_components/ui/list_div'; import { useEffect, useState } from 'react'; import { Toaster } from 'react-hot-toast'; import SdmLogin from '../sdmLogin/page'; -import type { DemandCompType } from '@/app/store/sdmMng'; +import type { DemandCompBizType } from '@/app/store/sdmMng'; import TransValueFormat from '@/app/common/transValueFormat'; import { useRouter } from 'next/navigation'; @@ -31,8 +31,8 @@ export default function SdmApplyList({}: SdmApplyProps) { const {selectSidoData, selectSigunData} = Common; const [isLogin, setIsLogin] = useState(false); const [isLoginStorageInfo, setIsLoginStorageInfo] = useState(false); - const [sdmApplyDetail, setSdmApplyDetail] = useState({} as DemandCompType); - const [transformedList, setTransformedList] = useState([]); + const [sdmApplyDetail, setSdmApplyDetail] = useState({} as DemandCompBizType); + const [transformedList, setTransformedList] = useState([]); useEffect(() => { console.log('sessionStorage : ',sessionStorage.getItem('user')); @@ -60,10 +60,10 @@ export default function SdmApplyList({}: SdmApplyProps) { // 데이터 변환을 위한 별도의 useEffect useEffect(() => { if (sdmInfoStatusList.length > 0) { - const newTransformedList = sdmInfoStatusList.map((item: DemandCompType) => ({ + const newTransformedList = sdmInfoStatusList.map((item: DemandCompBizType) => ({ ...item, ctpvCd: selectSidoData.find(sido => sido.val === item.ctpvCd?.trim())?.text || '', - sggCd: selectSigunData.find(sigun => sigun.val === item.sggCd?.trim())?.text || '' + sggCd: selectSigunData.find(sigun => sigun.val === item.sggCd?.trim())?.text || '', })); setTransformedList(newTransformedList); } @@ -73,6 +73,8 @@ export default function SdmApplyList({}: SdmApplyProps) { if (index !== undefined) { const selectedStatus = transformedList[index]; if (selectedStatus) { + + setSdmApplyDetail(selectedStatus); } } @@ -121,33 +123,33 @@ export default function SdmApplyList({}: SdmApplyProps) { 총대장균군수(개/100ml) - {} + {} 결합잔류염소(mg/L)​ - {} + {} 탁도(NTU) - {} + {} 생물학적 산소요구량(BOD)(mg/L) - {} + {} 냄새 {} 색도(도) - {} + {} 총질소(T-N)(mg/L) - {} + {} 총인(T-P)(mg/L)​ - {} + {} 수소이온농도(pH)​ {} 염화물(mgCL/L)​ - {} + {} 전기전도도(㎲/cm)​ - {} + {} 비고 {sdmApplyDetail?.rmrk} @@ -156,11 +158,11 @@ export default function SdmApplyList({}: SdmApplyProps) { 후보지1 - + { sdmApplyDetail?.splyCndtList?.[0]?.ruseUtztnFcltNm ?? ""} 후보지2 - + {sdmApplyDetail?.splyCndtList?.[1]?.ruseUtztnFcltNm ?? ""} 후보지3 - + {sdmApplyDetail?.splyCndtList?.[2]?.ruseUtztnFcltNm ?? ""} @@ -177,7 +179,7 @@ export default function SdmApplyList({}: SdmApplyProps) { 진행상태 {sdmApplyDetail?.status?.toString()} 공급처매칭결과 - + {sdmApplyDetail?.ruseUtztnFcltNm??''} diff --git a/apps/dm/app/(base-layout)/pages/sdmMng/sdmInfoInsert/page.tsx b/apps/dm/app/(base-layout)/pages/sdmMng/sdmInfoInsert/page.tsx index 71eaad57d..4efc58cb5 100644 --- a/apps/dm/app/(base-layout)/pages/sdmMng/sdmInfoInsert/page.tsx +++ b/apps/dm/app/(base-layout)/pages/sdmMng/sdmInfoInsert/page.tsx @@ -1,7 +1,7 @@ "use client"; import { useDmStore } from "@/app/store"; -import type { DemandCompType } from "@/app/store/sdmMng"; +import type { DemandCompBizType } from "@/app/store/sdmMng"; import { SdmInfoRegForm } from "@/components/ui/sdmInfoInsertForm/component"; import { UiModal } from "@common/business_components/ui/dialog_ui"; import { Button } from "@common/components/ui"; @@ -14,121 +14,99 @@ import * as z from "zod"; import SdmLogin from "../sdmLogin/page"; const sdmInfoFormSchema = z.object({ - sdmNm: z.string() - .min(1, "수요처를 선택해주세요"), + sdmNm: z.string().min(1, "수요처를 선택해주세요"), demandYmd: z.date().optional(), - demandQnty: z.string() + demandQnty: z + .string() .min(1, "요구수량을 입력해주세요") .regex(/^[0-9]+$/, "요구수량은 숫자만 입력 가능합니다"), usePurpose: z.string().optional(), - money: z.string() - .regex(/^[0-9]+$/, "희망단가는 숫자만 입력 가능합니다"), + money: z.string().regex(/^[0-9]+$/, "희망단가는 숫자만 입력 가능합니다"), /**요구수질 */ reqWaterQlty: z.string().optional(), - grssClfg: z.string() - .min(1, "총대장균군수를 입력해주세요") - .regex(/^[0-9]+$/, "총대장균군수는 숫자만 입력 가능합니다"), - tn: z.string() - .min(1, "총질소를 입력해주세요") - .regex(/^[0-9]+$/, "총질소는 숫자만 입력 가능합니다"), - combResdch: z.string() - .min(1, "결합잔류염소를 입력해주세요") - .regex(/^[0-9]+$/, "결합잔류염소는 숫자만 입력 가능합니다"), - tph: z.string() - .min(1, "총인산물을 입력해주세요") - .regex(/^[0-9]+$/, "총인산물은 숫자만 입력 가능합니다"), - trbt: z.string() - .min(1, "탁도를 입력해주세요") - .regex(/^[0-9]+$/, "탁도는 숫자만 입력 가능합니다"), - ph: z.string() - .min(1, "수소이온농도를 입력해주세요") - .regex(/^[0-9]+$/, "수소이온농도는 숫자만 입력 가능합니다"), - bod: z.string() - .min(1, "생물학적 산소요구량을 입력해주세요") - .regex(/^[0-9]+$/, "생물학적 산소요구량은 숫자만 입력 가능합니다"), + grssClfg: z.number().nullish(), + tn: z.number().nullish(), + combResdch: z.number().nullish(), + tph: z.number().nullish(), + trbt: z.number().nullish(), + ph: z.string().nullish(), + bod: z.number().nullish(), /**컬럼확인필요 */ - clIonQnt: z.string() - .min(1, "염화물을 입력해주세요") - .regex(/^[0-9]+$/, "염화물은 숫자만 입력 가능합니다"), - smll: z.string() - .min(1, "냄새를 입력해주세요") - .regex(/^[0-9]+$/, "냄새는 숫자만 입력 가능합니다"), - cdtnv: z.string() - .min(1, "전기전도도를 입력해주세요") - .regex(/^[0-9]+$/, "전기전도도는 숫자만 입력 가능합니다"), - crmty: z.string() - .min(1, "색도를 입력해주세요") - .regex(/^[0-9]+$/, "색도는 숫자만 입력 가능합니다"), + clIonQnt: z.number().nullish(), + smll: z.string(), + cdtnv: z.number().nullish(), + crmty: z.number().nullish(), rmrk: z.string().optional(), /* telno: z.string() .min(8, "전화번호는 8자 이상 입력해주세요") .max(12, "전화번호는 12자 이내로 입력해주세요") .regex(/^[0-9-]+$/, "전화번호는 숫자와 하이픈(-)만 입력 가능합니다"), */ - candidateTitle: z.array(z.object({ - ruseUtztnFcltNm: z.string(), - ruseUtztnFcltCd: z.string(), - })).optional(), + candidateTitle: z + .array( + z.object({ + ruseUtztnFcltNm: z.string(), + ruseUtztnFcltCd: z.string(), + }) + ) + .optional(), }); export type FormData = z.infer; function SdmInfoInsertContent() { const searchParams = useSearchParams(); - const {insertSdmInfoData, Sdm ,setSubsInfo} = useDmStore((state) => state); + const { insertSdmInfoData, Sdm, setSubsInfo } = useDmStore((state) => state); const { successLogin } = Sdm; const [ismoneyDisabled, setIsmoneyDisabled] = useState(false); const formSchema = sdmInfoFormSchema; const [isLogin, setIsLogin] = useState(false); - const [facilityName, setFacilityName] = useState(''); - const [defaultValues, setDefaultValues] = useState({ - sdmNm: '', + const [facilityName, setFacilityName] = useState(""); + const [defaultValues, setDefaultValues] = useState({ + sdmNm: "", demandYmd: new Date(), - demandQnty: '', - usePurpose: '', - money: '', + demandQnty: "", + usePurpose: "", + money: "", /**요구수질 */ - reqWaterQlty: '', - grssClfg: '', - tn: '', - combResdch: '', - tph: '', - trbt: '', - ph: '', - bod: '', + reqWaterQlty: "", + grssClfg: null, + tn: null, + combResdch: null, + tph: null, + trbt: null, + ph: null, + bod: null, /**컬럼확인필요 */ - clIonQnt: '', - smll: '', - cdtnv: '', - crmty: '', - rmrk: '', + clIonQnt: null, + smll: "", + cdtnv: null, + crmty: null, + rmrk: "", /** 후보지 제목 */ candidateTitle: [ - { ruseUtztnFcltNm: '', ruseUtztnFcltCd: '' }, - { ruseUtztnFcltNm: '', ruseUtztnFcltCd: '' }, - { ruseUtztnFcltNm: '', ruseUtztnFcltCd: '' }, + { ruseUtztnFcltNm: "", ruseUtztnFcltCd: "" }, + { ruseUtztnFcltNm: "", ruseUtztnFcltCd: "" }, + { ruseUtztnFcltNm: "", ruseUtztnFcltCd: "" }, ], }); - - useEffect(() => { - const user = sessionStorage.getItem('user'); - setDefaultValues(prev => ({ + const user = sessionStorage.getItem("user"); + setDefaultValues((prev) => ({ ...prev, - sdmNm: searchParams.get('dmdCoNm') || '', + sdmNm: searchParams.get("dmdCoNm") || "", })); - sessionStorage.setItem('user', searchParams.get('dmdInfoId') || ''); - setIsLogin(user || searchParams.get('dmdInfoId') ? true : false); + sessionStorage.setItem("user", searchParams.get("dmdInfoId") || ""); + setIsLogin(user || searchParams.get("dmdInfoId") ? true : false); }, [searchParams]); useEffect(() => { - const local = localStorage.getItem('user'); + const local = localStorage.getItem("user"); if (local) { setIsLogin(true); } setSubsInfo([]); // subsInfo 초기화 후보지 처음 화면 들어올때 초기화(스토어내 객체만) - }, [setSubsInfo]); const form = useForm({ @@ -139,98 +117,138 @@ function SdmInfoInsertContent() { const subsInfo = useDmStore((state) => state.map.subsInfo); - useEffect(()=>{ + useEffect(() => { //map.subsInfo 스토어 객체 값이 변경되면 해당 값이 폼에 자동으로 들어가도록 수정 대신 값이 있어야함 - if(subsInfo.length>0){ - form.setValue('candidateTitle', subsInfo) + if (subsInfo.length > 0) { + form.setValue("candidateTitle", subsInfo); } + }, [subsInfo, form]); -},[subsInfo, form]) + //후보지 팝업 값 셋팅 + useEffect(() => { + const handleMessage = (event: MessageEvent) => { + if (event.data?.type === "SET_SUBS_INFO") { + setSubsInfo(event.data.payload); // zustand로 값 설정 + } + }; -//후보지 팝업 값 셋팅 -useEffect(() => { - const handleMessage = (event: MessageEvent) => { - if (event.data?.type === 'SET_SUBS_INFO') { - setSubsInfo(event.data.payload); // zustand로 값 설정 - } - }; - - window.addEventListener('message', handleMessage); - return () => window.removeEventListener('message', handleMessage); -}, [setSubsInfo]); + window.addEventListener("message", handleMessage); + return () => window.removeEventListener("message", handleMessage); + }, [setSubsInfo]); // 로그인 성공 시 모달 닫기 및 폼 업데이트 useEffect(() => { if (successLogin) { setIsLogin(true); - const user = sessionStorage.getItem('user'); + const user = sessionStorage.getItem("user"); if (user) { try { const userData = JSON.parse(user); if (userData.dmdCoNm) { setFacilityName(userData.dmdCoNm); - form.setValue('sdmNm', userData.dmdCoNm); + form.setValue("sdmNm", userData.dmdCoNm); } - } catch (error) { - console.error('Error parsing user data:', error); + console.error("Error parsing user data:", error); } } } }, [successLogin, form]); + useEffect(() => { + console.log("Form state changed:", form.formState.errors); + }, [form.formState.errors]); + // 체크박스 상태가 변경될 때마다 money 필드의 에러를 초기화 useEffect(() => { if (ismoneyDisabled) { - form.clearErrors('money'); - form.setValue('money', ''); + form.clearErrors("money"); + form.setValue("money", ""); } }, [ismoneyDisabled, form]); -const router = useRouter(); + const router = useRouter(); const onSubmit: SubmitHandler = async (data) => { try { - // Transform form data to match API schema - const apiData: DemandCompType = { - dmdInfoId: JSON.parse(sessionStorage.getItem('user') || '{}')?.dmdInfoId?.toString() || searchParams.get('dmdInfoId') + (searchParams.get('bznmTotNo') || ''), - dmdInfoFk: JSON.parse(sessionStorage.getItem('user') || '{}')?.dmdInfoId?.toString() || searchParams.get('dmdInfoId') + (searchParams.get('bznmTotNo') || ''), - dmdCoNm: JSON.parse(sessionStorage.getItem('user') || '{}')?.dmdCoNm?.toString() || data.sdmNm, - ctpvCd: JSON.parse(sessionStorage.getItem('user') || '{}')?.ctpvCd?.toString() || searchParams.get('ctpvCd') || '', - sggCd: JSON.parse(sessionStorage.getItem('user') || '{}')?.sggCd?.toString() || searchParams.get('sggCd') || '', - daddr: JSON.parse(sessionStorage.getItem('user') || '{}')?.daddr?.toString() || searchParams.get('daddr') || '', - telno: JSON.parse(sessionStorage.getItem('user') || '{}')?.telno?.toString() || searchParams.get('telno') || '', - rgtr: JSON.parse(sessionStorage.getItem('user') || '{}')?.rgtr?.toString() || searchParams.get('rgtr') || '', - useUsgCd: data.usePurpose || '', - wntUntprc: Number(data.money) || '', + const dmSubsInfo = data.candidateTitle?.filter( + (item) => item.ruseUtztnFcltNm && item.ruseUtztnFcltCd + ); + // Transform form data to madata.candidateTitletch API schema + const apiData: DemandCompBizType = { + dmdInfoId: + JSON.parse( + sessionStorage.getItem("user") || "{}" + )?.dmdInfoId?.toString() || + searchParams.get("dmdInfoId") + (searchParams.get("bznmTotNo") || ""), + dmdInfoFk: + JSON.parse( + sessionStorage.getItem("user") || "{}" + )?.dmdInfoId?.toString() || + searchParams.get("dmdInfoId") + (searchParams.get("bznmTotNo") || ""), + dmdCoNm: + JSON.parse( + sessionStorage.getItem("user") || "{}" + )?.dmdCoNm?.toString() || data.sdmNm, + ctpvCd: + JSON.parse( + sessionStorage.getItem("user") || "{}" + )?.ctpvCd?.toString() || + searchParams.get("ctpvCd") || + "", + sggCd: + JSON.parse( + sessionStorage.getItem("user") || "{}" + )?.sggCd?.toString() || + searchParams.get("sggCd") || + "", + daddr: + JSON.parse( + sessionStorage.getItem("user") || "{}" + )?.daddr?.toString() || + searchParams.get("daddr") || + "", + telno: + JSON.parse( + sessionStorage.getItem("user") || "{}" + )?.telno?.toString() || + searchParams.get("telno") || + "", + rgtr: + JSON.parse( + sessionStorage.getItem("user") || "{}" + )?.rgtr?.toString() || + searchParams.get("rgtr") || + "", + useUsgCd: data.usePurpose || "", + wntUntprc: Number(data.money) || "", dmndTmng: data.demandYmd || new Date(), - dmndQty: Number(data.demandQnty) || '', - grssClfg: Number(data.grssClfg) || '', - tn: Number(data.tn) || '', - combResdch: Number(data.combResdch) || '', - tph: Number(data.tph) || '', - trbt: Number(data.trbt) || '', - ph: Number(data.ph) || '', - blgcOxygDmndQnt: Number(data.bod) || '', - clIonQnt: Number(data.clIonQnt) || '', - smll: Number(data.smll) || '', - cdtnv: Number(data.cdtnv) || '', - crmty: Number(data.crmty) || '', - rmrk: data.rmrk || '', + dmndQty: Number(data.demandQnty) || "", + grssClfg: data.grssClfg === null ? -1 : Number(data.grssClfg), + tn: Number(data.tn) || null, + combResdch: Number(data.combResdch) || null, + tph: Number(data.tph) || null, + trbt: Number(data.trbt) || null, + ph: data.ph || "", + blgcOxygDmndQnt: Number(data.bod) ||null, + clIonQnt: Number(data.clIonQnt) || null, + smll: data.smll || "", + cdtnv: Number(data.cdtnv) ||null, + crmty: Number(data.crmty) || null, + rmrk: data.rmrk || "", bzmnNo: "", dmdAplyPswd: "", index: 0, reqDt: "", dmdInfoSn: 0, - status: '', - splyCndtList: data.candidateTitle || [], + status: "", + splyCndtList: dmSubsInfo || [], }; - - - - await insertSdmInfoData(apiData); + setTimeout(() => { + router.push("/"); + }, 1000); // 0.8초 후 이동 } catch (error) { - console.error('Error submitting form:', error); + console.error("Error submitting form:", error); } }; @@ -253,8 +271,10 @@ const router = useRouter(); />
@@ -264,7 +284,7 @@ const router = useRouter();
- {!isLogin ? + {!isLogin ? ( } bodyClass="sm:max-w-[90vw] w-[530px] h-[430px]" @@ -277,7 +297,7 @@ const router = useRouter(); noHeaderYn="Y" noFooterYn="Y" /> - : null} + ) : null} ); @@ -290,4 +310,3 @@ export default function MyForm() { ); } - diff --git a/apps/dm/app/(base-layout)/pages/sdmMng/sdmInsert/page.tsx b/apps/dm/app/(base-layout)/pages/sdmMng/sdmInsert/page.tsx index a0aa35145..9a68510e3 100644 --- a/apps/dm/app/(base-layout)/pages/sdmMng/sdmInsert/page.tsx +++ b/apps/dm/app/(base-layout)/pages/sdmMng/sdmInsert/page.tsx @@ -1,8 +1,8 @@ "use client"; import { useDmStore } from "@/app/store"; -import type { DemandCompType } from "@/app/store/sdmMng"; import SdmInsertForm from '@common/business_components/ui/sdmInsertForm'; +import type { DemandCompType } from "@common/business_components/ui/sdmInsertForm/form"; import { useRouter } from "next/navigation"; import { useCallback, useEffect, useRef } from "react"; import { Toaster } from "react-hot-toast"; @@ -44,15 +44,9 @@ export default function MyForm() { const handleInsertSdmData = useCallback((data: import('@common/business_components/ui/sdmInsertForm/form').DemandCompType) => { const convertedData: DemandCompType = { ...data, - dmdInfoSn: '', - dmdInfoFk: '', - status: '', - splyCndtList: [] }; formDataRef.current = convertedData; - insertSdmData(convertedData).catch(error => { - console.error('Error inserting SDM data:', error); - }); + insertSdmData(convertedData) }, [insertSdmData]); return ( @@ -70,4 +64,3 @@ export default function MyForm() { ); } - diff --git a/apps/dm/app/(base-layout)/pages/wrStatus/page.tsx b/apps/dm/app/(base-layout)/pages/wrStatus/page.tsx index 278dd76bb..826ab3222 100644 --- a/apps/dm/app/(base-layout)/pages/wrStatus/page.tsx +++ b/apps/dm/app/(base-layout)/pages/wrStatus/page.tsx @@ -1,7 +1,7 @@ 'use client'; import { CHART_FORM, MainChart, type ChartConfig } from '@common/business_components'; -import React, { useEffect, useRef, useState } from 'react'; +import React, { useEffect, useRef, useState, useMemo, useCallback } from 'react'; interface RegionData { name: string; @@ -213,7 +213,7 @@ const WrStatusPage: React.FC = () => { { region: '제주특별자치도', sewage: '8(1,666)', rainwater: '47(5,746)', reclaimed: '64(660)', thermal: '0' }, ]; - const regionData: RegionData[] = [ + const regionData: RegionData[] = useMemo(() => [ { name: '서울', x: 170, y: 140, values: [0.3, 0.3, 0.2, 0.2] }, { name: '인천', x: 120, y: 150, values: [0.3, 0.3, 0.2, 0.2] }, { name: '경기', x: 210, y: 210, values: [0.3, 0.3, 0.2, 0.2] }, @@ -231,7 +231,7 @@ const WrStatusPage: React.FC = () => { { name: '울산', x: 450, y: 500, values: [0.3, 0.3, 0.2, 0.2] }, { name: '부산', x: 420, y: 550, values: [0.3, 0.3, 0.2, 0.2] }, { name: '제주', x: 60, y: 750, values: [0.3, 0.3, 0.2, 0.2] }, - ]; + ], []); const handleMarkerClick = (regionId: string) => { if (selectedRegion === regionId) { @@ -242,7 +242,7 @@ const WrStatusPage: React.FC = () => { }; - const createDonutMarker = (svg: SVGSVGElement, x: number, y: number, name: string, values: number[]) => { + const createDonutMarker = useCallback((svg: SVGSVGElement, x: number, y: number, name: string, values: number[]) => { const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FED16A']; const radius = 26; const innerRadius = 18; @@ -334,7 +334,7 @@ const WrStatusPage: React.FC = () => { }); svg.appendChild(g); - }; + }, [handleMarkerClick, regionIdMap]); useEffect(() => { const loadSVG = async () => { @@ -374,7 +374,7 @@ const WrStatusPage: React.FC = () => { }; loadSVG(); - }, []); + }, [createDonutMarker, regionData]); useEffect(() => { const svg = svgContainerRef.current?.querySelector('svg'); diff --git a/apps/dm/app/(popup-layout)/map/popup/page.tsx b/apps/dm/app/(popup-layout)/map/popup/page.tsx index dc4e404ce..ea71862d8 100644 --- a/apps/dm/app/(popup-layout)/map/popup/page.tsx +++ b/apps/dm/app/(popup-layout)/map/popup/page.tsx @@ -62,10 +62,9 @@ const Map = () => { Object.keys(item).length > 0 && !prev.some((f) => f.pbnstRuseFcltId === item.pbnstRuseFcltId) ); - console.log(newItems) + console.log(newItems); return [...prev, ...newItems]; }); - } catch (error) { console.error("데이터 불러오기 실패:", error); } @@ -232,14 +231,6 @@ const Map = () => { return ( <> - { - if (hasuPk) { - setSelectDataPk(hasuPk); - } - }} - onApply={onApply} - />
{ isSearchModalOpen={isSearchModalOpen} onCheckedLayersChange={onCheckedLayersChange} imgVisble={false} + searchBar={(props: any) => ( + { + if (hasuPk) { + setSelectDataPk(hasuPk); + } + }} + onApply={onApply} + {...props} + /> + )} />
; /**==================================== * Store - 데이터 ====================================*/ @@ -160,6 +163,131 @@ export type MoneyDetailType = { const demandCompList : DemandCompType[] = [ ] + +const disableRules: DisableRulesType = { + "청소": ["tn", 'tph',"clIonQnt" ,'cdtnv'], + "화장실용수": ["tn", 'tph',"clIonQnt" ,'cdtnv'], + "세척": ["combResdch", "crmty",'tph',"clIonQnt",'cdtnv'], + "살수": ["combResdch", "crmty",'tph',"clIonQnt",'cdtnv'], + "조경": ["combResdch", "crmty",'tph','cdtnv'], + "농업_간접용수": ["combResdch", "crmty",'tn','tph','clIonQnt'], + "농업_직접용수": ["combResdch", "crmty",'tn','tph','clIonQnt'], + "하천": ["combResdch", "trbt", "crmty" ,'clIonQnt','cdtnv'], + '공업':[] + }; + + const defaultRules: Record = { + "청소": { + grssClfg: null, + combResdch:0.2, + trbt: 2, + bod: 5, + crmty: 20, + ph: "5.8~8.5", + tn:null, + tph: null, + clIonQnt: null, + cdtnv: null, + + }, + "화장실용수": { + grssClfg: null, + combResdch:0.2, + trbt: 2, + bod: 5, + crmty: 20, + ph: "5.8~8.5", + tn:null, + tph: null, + clIonQnt: null, + cdtnv: null, + }, + "세척": { + grssClfg: null, + trbt: 2, + bod: 5, + ph: "5.8~8.5", + combResdch:null, + crmty:null, + tn:null, + tph: null, + clIonQnt: null, + cdtnv: null, + }, + "살수": { + grssClfg: null, + trbt: 2, + bod: 5, + ph: "5.8~8.5", + combResdch:null, + crmty:null, + tn:null, + tph: null, + clIonQnt: null, + cdtnv: null, + }, + "조경": { + grssClfg: null, + trbt: 2, + bod: 5, + ph: "5.8~8.5", + clIonQnt:250, + combResdch:null, + crmty:null, + tn:null, + tph: null, + cdtnv: null, + }, + "농업_간접용수": { + grssClfg: null, + trbt: 5, + bod: 8, + ph: "5.8~8.5", + cdtnv:2000, + combResdch:null, + crmty:null, + tn:null, + tph: null, + clIonQnt: null, + }, + "농업_직접용수": { + grssClfg: null, + trbt: 2, + bod: 8, + ph: "5.8~8.5", + cdtnv:700, + combResdch:null, + crmty:null, + tn:null, + tph: null, + clIonQnt: null, + }, + "하천": { + grssClfg: 1000, + bod: 5, + tn: 10, + tph: 0.5, + ph: "5.8~8.5", + combResdch:null, + trbt:null, + crmty:null, + clIonQnt: null, + cdtnv:null + }, + 공업:{ + grssClfg: null, + bod: null, + tn: null, + tph: null, + ph: "~", + combResdch:null, + trbt:null, + crmty:null, + clIonQnt: null, + cdtnv:null + } + }; + // 사용용도 const useTypesData : SelectDataType[] = [ { text: '청소', val: "청소" }, @@ -167,7 +295,8 @@ const useTypesData : SelectDataType[] = [ { text: "세척", val: "세척" }, { text: "살수", val: "살수" }, { text: "조경", val: "조경" }, - { text: "농업", val: "농업" }, + { text: "농업_간접용수", val: "농업_간접용수" }, + { text: "농업_직접용수", val: "농업_직접용수" }, { text: "하천", val: "하천" }, { text: "지하수", val: "지하수" }, { text: "공업", val: "공업" }, @@ -280,7 +409,7 @@ const postSdmData = async (data: DemandCompType) => { } // 수요정보 등록 -const postSdmInfoData = async (data: DemandCompType) => { +const postSdmInfoData = async (data: DemandCompBizType) => { try { await postFetch("/reuseFc/request/demandInfo", data); toast.success('수요 정보 등록에 성공하였습니다.'); @@ -360,7 +489,7 @@ const fetchGetSimilarCaseList = async (part: string, value: number|string) => { export type SdmActions = { initializeSdmData: () => void; insertSdmData: (data: DemandCompType) => Promise; - insertSdmInfoData: (data: DemandCompType) => Promise; + insertSdmInfoData: (data: DemandCompBizType) => Promise; getDemandCompList: (searchText: string, pageCnt: number) => Promise; actionLogin: (data: DemandCompType) => Promise; getSdmInfoStatusList: (dmdInfoId: string) => Promise; @@ -378,9 +507,10 @@ export type SdmType ={ moneyDetailList: MoneyDetailType[]; // 수요정보 신청현황 - sdmInfoStatusList: DemandCompType[]; + sdmInfoStatusList: DemandCompBizType[]; upHeadSdmInfoStatus: TableUpperProps[]; - + defaultRules: Record + disableRules: DisableRulesType; // 로그인관련 successNextPage : boolean; successLogin: boolean; @@ -398,7 +528,10 @@ export const SdmState: SdmType = { moneyDetailList: moneyDetailList, // 수요정보 신청현황 sdmInfoStatusList: [], + defaultRules:defaultRules, + disableRules:disableRules, upHeadSdmInfoStatus: upHeadSdmInfoStatus, + // 로그인관련 successNextPage : false, successLogin: false, @@ -428,7 +561,7 @@ export const SdmReducer = (set: any): SdmActions => { } }, - insertSdmInfoData: async (data: DemandCompType) => { + insertSdmInfoData: async (data: DemandCompBizType) => { postSdmInfoData(data); }, @@ -465,11 +598,13 @@ export const SdmReducer = (set: any): SdmActions => { })) return; } - const sdmInfoStatusList : DemandCompType[] = []; + const sdmInfoStatusList : DemandCompBizType[] = []; - res.demandInfo.map((el: DemandCompType, index: number) => { + res.demandInfo.map((el: DemandCompBizType, index: number) => { const matchingInfo = res.demandMatchings.find((matching: DemandMatchings) => matching.dmdInfoSn === el.dmdInfoSn); const status = matchingInfo?.splyFcltFlg?.trim() === 'Sub' ? '검토' : matchingInfo?.splyFcltFlg?.trim() === 'matched' ? '매칭완료' : '신청'; + const ruseUtztnFcltNm = matchingInfo?.ruseUtztnFcltNm ? matchingInfo.ruseUtztnFcltNm : ''; + const tmpData = { ...el, @@ -485,7 +620,9 @@ export const SdmReducer = (set: any): SdmActions => { useUsgCd: el.useUsgCd, dmndTmng: el.dmndTmng, dmdInfoSn : el.dmdInfoSn, - status : status + status : status, + splyCndtList: el.splyCndtList, + ruseUtztnFcltNm: ruseUtztnFcltNm || '' } sdmInfoStatusList.push(tmpData); }) diff --git a/apps/dm/app/store/store.tsx b/apps/dm/app/store/store.tsx index d8f108319..be6a26475 100644 --- a/apps/dm/app/store/store.tsx +++ b/apps/dm/app/store/store.tsx @@ -13,8 +13,10 @@ export const StoreZus = (initState: DmState= { ...dmMapState, }) => { return createStore()((set) => { - tokenManager.setToken("site-id-key", 'DM'); - tokenManager.setToken("site-theme-key", 'green'); + if (typeof window !== "undefined") { + tokenManager.setToken("site-id-key", 'DM'); + tokenManager.setToken("site-theme-key", 'green'); + } return { diff --git a/apps/dm/components/ui/common/searhDemandInput/component.tsx b/apps/dm/components/ui/common/searhDemandInput/component.tsx index 5598129a7..70ccf9efc 100644 --- a/apps/dm/components/ui/common/searhDemandInput/component.tsx +++ b/apps/dm/components/ui/common/searhDemandInput/component.tsx @@ -1,5 +1,5 @@ import { useDmStore } from '@/app/store'; -import type { DemandCompType } from '@/app/store/sdmMng'; +import type { DemandCompType } from '@common/business_components/ui/sdmInsertForm/form'; import React, { useCallback, useEffect, useRef, useState } from 'react'; type thisProps = { diff --git a/apps/dm/components/ui/common/utils/utils.ts b/apps/dm/components/ui/common/utils/utils.ts new file mode 100644 index 000000000..f66437553 --- /dev/null +++ b/apps/dm/components/ui/common/utils/utils.ts @@ -0,0 +1,18 @@ +export const sanitizeInput = (val: string, allowDecimal = false) => { + if (val === "") return ""; // 빈 값 허용 + + // 소숫점 허용 + if (allowDecimal) { + // 숫자와 점만 허용 + let cleaned = val.replace(/[^0-9.]/g, ""); + // 소숫점 여러 개일 경우 첫 번째만 유지 + const parts = cleaned.split("."); + if (parts.length > 2) { + cleaned = parts[0] + "." + parts.slice(1).join(""); + } + return cleaned; + } + + // 정수만 허용 + return val.replace(/[^0-9]/g, ""); +}; \ No newline at end of file diff --git a/apps/dm/components/ui/map/searchBar/searchBar.tsx b/apps/dm/components/ui/map/searchBar/searchBar.tsx index de68d2f3c..f2beeff82 100644 --- a/apps/dm/components/ui/map/searchBar/searchBar.tsx +++ b/apps/dm/components/ui/map/searchBar/searchBar.tsx @@ -118,14 +118,6 @@ export function SearchBar({ />
- -
@@ -495,9 +348,9 @@ export function SdmInfoRegForm({ const normalFields = formFields.filter( (f) => f.formIndex === 0 && f.component ); - const groupFields = formFields.filter( - (f) => f.formIndex === 1 && f.component - ); + // const groupFields = formFields.filter( + // (f) => f.formIndex === 1 && f.component + // ); const candidateFields = formFields.filter( (f) => f.formIndex === 2 && f.component ); @@ -512,17 +365,15 @@ export function SdmInfoRegForm({ name={name} render={({ field }) => name === "money" ? ( - component(field) + // component(field) + {component(field)} ) : ( - // - // {component(field)} - // 0 && ( -
- 요구수질 -
- {groupFields.map(({ name, label, component, required }) => ( -
- ( - // - // {component?.(field)} - // - - )} - /> -
- ))} +
+ 요구수질 +
+ { + const disabledFields = usePurpose ? disableRules[usePurpose] : []; + const isDisabled = disabledFields + ? disabledFields.includes(field.name) + : true; + return ( + +
+
+ { + const inputValue = e.target.value.replace( + /[^0-9]/g, + "" + ); // 정수만 + field.onChange( + inputValue === "" ? null : Number(inputValue) + ); + }} + value={ + field.value !== undefined && field.value !== null + ? `${field.value}` + : "불검출" + } + maxLength={6} + disabled={isDisabled} + onBlur={field.onBlur} + name={field.name} + ref={field.ref} + /> + {/* TODO: 총대장균군수 확인 필요*/} + {field.value !== null ? ( + + 이하 + + ) : ( + <> + )} +
+
+
+ ); + }} + /> + { + const disabledFields = usePurpose ? disableRules[usePurpose] : []; + const isDisabled = disabledFields + ? disabledFields.includes(field.name) + : true; + return ( + +
+
+ { + const inputValue = e.target.value.replace( + /[^0-9]/g, + "" + ); // 정수만 + field.onChange( + inputValue === "" ? null : Number(inputValue) + ); + }} + value={ + field.value !== undefined && field.value !== null + ? `${field.value}` + : "" + } + maxLength={6} + disabled={isDisabled} + onBlur={field.onBlur} + name={field.name} + ref={field.ref} + /> + + 이하 + +
+
+
+ ); + }} + /> + { + const disabledFields = usePurpose ? disableRules[usePurpose] : []; + const isDisabled = disabledFields + ? disabledFields.includes(field.name) + : true; + return ( + +
+
+ { + const cleanValue = sanitizeInput( + e.target.value, + true + ); + field.onChange( + cleanValue === "" ? null : Number(cleanValue) + ); + }} + value={field.value ?? ""} + maxLength={6} + disabled={isDisabled} + onBlur={field.onBlur} + name={field.name} + ref={field.ref} + /> + + 이상 + +
+
+
+ ); + }} + /> + { + const disabledFields = usePurpose ? disableRules[usePurpose] : []; + const isDisabled = disabledFields + ? disabledFields.includes(field.name) + : true; + return ( + +
+
+ { + const cleanValue = sanitizeInput( + e.target.value, + true + ); + field.onChange( + cleanValue === "" ? null : Number(cleanValue) + ); + }} + value={field.value ?? ""} + maxLength={6} + disabled={isDisabled} + onBlur={field.onBlur} + name={field.name} + ref={field.ref} + /> + + 이하 + +
+
+
+ ); + }} + /> + { + const disabledFields = usePurpose ? disableRules[usePurpose] : []; + const isDisabled = disabledFields + ? disabledFields.includes(field.name) + : true; + return ( + +
+
+ { + const inputValue = e.target.value.replace( + /[^0-9]/g, + "" + ); // 정수만 + field.onChange( + inputValue === "" ? null : Number(inputValue) + ); + }} + value={ + field.value !== undefined && field.value !== null + ? `${field.value}` + : "" + } + maxLength={6} + disabled={isDisabled} + onBlur={field.onBlur} + name={field.name} + ref={field.ref} + /> + + 이하 + +
+
+
+ ); + }} + /> +
+ +
+ { + const cleanValue = sanitizeInput(e.target.value, true); + isSetPh(cleanValue, 1); + }} + value={frontPHdata ?? ""} + maxLength={5} + /> + ~ + { + const cleanValue = sanitizeInput(e.target.value, true); + isSetPh(cleanValue, 0); + }} + value={backPHdata ?? ""} + maxLength={5} + /> +
+ { + const disabledFields = usePurpose ? disableRules[usePurpose] : []; + const isDisabled = disabledFields + ? disabledFields.includes(field.name) + : true; + return ( + +
+
+ { + const inputValue = e.target.value.replace( + /[^0-9]/g, + "" + ); // 정수만 + field.onChange( + inputValue === "" ? null : Number(inputValue) + ); + }} + value={ + field.value !== undefined && field.value !== null + ? `${field.value}` + : "" + } + maxLength={6} + disabled={isDisabled} + onBlur={field.onBlur} + name={field.name} + ref={field.ref} + /> + + 이하 + +
+
+
+ ); + }} + /> + { + const disabledFields = usePurpose ? disableRules[usePurpose] : []; + const isDisabled = disabledFields + ? disabledFields.includes(field.name) + : true; + return ( + +
+
+ { + const inputValue = e.target.value.replace( + /[^0-9]/g, + "" + ); // 정수만 + field.onChange( + inputValue === "" ? null : Number(inputValue) + ); + }} + value={ + field.value !== undefined && field.value !== null + ? `${field.value}` + : "" + } + maxLength={6} + disabled={isDisabled} + onBlur={field.onBlur} + name={field.name} + ref={field.ref} + /> + + 이하 + +
+
+
+ ); + }} + /> + { + const disabledFields = usePurpose ? disableRules[usePurpose] : []; + const isDisabled = disabledFields + ? disabledFields.includes(field.name) + : true; + return ( + + { + field.onChange(val.toString()); + }} + value={field.value || "불쾌하지않을것"} + readOnly={isDisabled} + onBlur={field.onBlur} + ref={field.ref} + /> + + ); + }} + /> + { + const disabledFields = usePurpose ? disableRules[usePurpose] : []; + const isDisabled = disabledFields + ? disabledFields.includes(field.name) + : true; + return ( + +
+
+ { + const inputValue = e.target.value.replace( + /[^0-9]/g, + "" + ); // 정수만 + field.onChange( + inputValue === "" ? null : Number(inputValue) + ); + }} + value={ + field.value !== undefined && field.value !== null + ? `${field.value}` + : "" + } + maxLength={6} + disabled={isDisabled} + onBlur={field.onBlur} + name={field.name} + ref={field.ref} + /> + + 이하 + +
+
+
+ ); + }} + /> + { + const disabledFields = usePurpose ? disableRules[usePurpose] : []; + const isDisabled = disabledFields + ? disabledFields.includes(field.name) + : true; + return ( + +
+
+ { + const inputValue = e.target.value.replace( + /[^0-9]/g, + "" + ); // 정수만 + field.onChange( + inputValue === "" ? null : Number(inputValue) + ); + }} + value={ + field.value !== undefined && field.value !== null + ? `${field.value}` + : "" + } + maxLength={6} + disabled={isDisabled} + onBlur={field.onBlur} + name={field.name} + ref={field.ref} + /> + + 이하 + +
+
+
+ ); + }} + /> + { + return ( + +
+
+ { + field.onChange(e.target.value); + }} + value={ + field.value !== undefined && field.value !== "" + ? `${field.value}` + : "" + } + onBlur={field.onBlur} + name={field.name} + ref={field.ref} + /> +
+
+
+ ); + }} + />
- )} +
{candidateFields.map(({ name, label, component, required }, index) => component ? ( @@ -581,7 +922,7 @@ export function SdmInfoRegForm({ label={label} required={required} error={ - typeof form.formState.errors[name]?.message === 'string' + typeof form.formState.errors[name]?.message === "string" ? (form.formState.errors[name] as FieldError) : undefined } diff --git a/apps/dm/components/ui/sdmLoginForm/component.tsx b/apps/dm/components/ui/sdmLoginForm/component.tsx index 204b12308..dd764844b 100644 --- a/apps/dm/components/ui/sdmLoginForm/component.tsx +++ b/apps/dm/components/ui/sdmLoginForm/component.tsx @@ -1,6 +1,6 @@ import { useDmStore } from "@/app/store"; -import type { DemandCompType } from "@/app/store/sdmMng"; import { BZNM_TOT_NO, FormField, FormUi } from "@common/business_components"; +import type { DemandCompType } from "@common/business_components/ui/sdmInsertForm/form"; import { Button, Input } from "@common/components"; import { zodResolver } from "@hookform/resolvers/zod"; import { sha512 } from 'js-sha512'; diff --git a/apps/dm/package.json b/apps/dm/package.json index 2fdff5dbc..07ddec950 100644 --- a/apps/dm/package.json +++ b/apps/dm/package.json @@ -3,9 +3,9 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev --turbopack", + "dev": "next dev -p 3005", "build": "next build", - "start": "next start", + "start:dm": "next start -p 3005", "lint": "next lint" }, "dependencies": { diff --git a/apps/fo/.env.development b/apps/fo/.env.development index 94488f0cd..44fe06736 100644 --- a/apps/fo/.env.development +++ b/apps/fo/.env.development @@ -2,6 +2,7 @@ NEXT_PUBLIC_SITE_ID = FO NEXT_PUBLIC_PORT = 11300 NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300 NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1 +#NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000 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 NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver diff --git a/apps/fo/.env.local b/apps/fo/.env.local index 76fb868cd..e125bed3d 100644 --- a/apps/fo/.env.local +++ b/apps/fo/.env.local @@ -1,7 +1,8 @@ NEXT_PUBLIC_SITE_ID = FO 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_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1 +#NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000 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 NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver diff --git a/apps/fo/.env.production b/apps/fo/.env.production index 16675eaec..52534bd8e 100644 --- a/apps/fo/.env.production +++ b/apps/fo/.env.production @@ -15,6 +15,7 @@ NEXT_PUBLIC_SITE_ID = FO NEXT_PUBLIC_PORT = 11300 NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300 NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1 +#NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000 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 NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver diff --git a/apps/fo/app/components/common/FacilityTermModalHeader.tsx b/apps/fo/app/components/common/FacilityTermModalHeader.tsx index 30c77405f..d856e233f 100644 --- a/apps/fo/app/components/common/FacilityTermModalHeader.tsx +++ b/apps/fo/app/components/common/FacilityTermModalHeader.tsx @@ -97,10 +97,7 @@ export default function FacilityTermModalHeader({ const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate()); const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate()); const rainEffectDay = (item as T & { rainEffectDay: number }).rainEffectDay; - if(flowPanel === '1') { - const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay; - return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay>0 && infoRnDay < 3; - } else if(flowPanel === '2'){ + if(flowPanel === '2'){ const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay; return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 3 && infoRnDay < 10; } else if(flowPanel === '3'){ @@ -122,8 +119,7 @@ export default function FacilityTermModalHeader({ const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay; return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 60; } else { - const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay; - return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && (infoRnDay>0 || rainEffectDay ===1); + return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && (rainEffectDay ===1); } }); } else if(tabName.includes("_chuncheon")) { @@ -132,8 +128,8 @@ export default function FacilityTermModalHeader({ const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate()); const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate()); const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate()); - const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay; - return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay==0; + const rainEffectDay = (item as T & { rainEffectDay: number }).rainEffectDay; + return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && rainEffectDay==0; }); } else { filteredData = searchList.filter((item) => { @@ -144,7 +140,6 @@ export default function FacilityTermModalHeader({ return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly; }); } - setCopySearchList(filteredData); setStandSearchList(filteredData); }, [searchList, searchYear, tabName, flowPanel]); diff --git a/apps/fo/app/pages/dashboard/drainageEquipment/page.tsx b/apps/fo/app/pages/dashboard/drainageEquipment/page.tsx index f6f1188de..1b7249efd 100644 --- a/apps/fo/app/pages/dashboard/drainageEquipment/page.tsx +++ b/apps/fo/app/pages/dashboard/drainageEquipment/page.tsx @@ -15,7 +15,6 @@ export default function DrainageEquipment({searchYear = '', fcltyList = []}: Dra const { Common, DrainageEquipment, - searchDrainageEquipment, } = useFoStore((state) => state); const { @@ -35,11 +34,10 @@ export default function DrainageEquipment({searchYear = '', fcltyList = []}: Dra useEffect(() => { if (!isInit && tableData[0]?.bscFctCd && (tableData[0].bscFctCd !== prevFacilityCode || !hasSearched)) { - searchDrainageEquipment(searchYear, tableData[0].bscFctCd, false); setHasSearched(true); setPrevFacilityCode(tableData[0].bscFctCd); } - }, [fcltyList, isInit, searchDrainageEquipment, searchYear, tableData, hasSearched, prevFacilityCode]); + }, [fcltyList, isInit, searchYear, tableData, hasSearched, prevFacilityCode]); // 연도가 바뀌면 hasSearched를 false로 리셋 useEffect(() => { diff --git a/apps/fo/app/pages/dashboard/facilityInfo/page.tsx b/apps/fo/app/pages/dashboard/facilityInfo/page.tsx index 767ed54e4..9c16161f5 100644 --- a/apps/fo/app/pages/dashboard/facilityInfo/page.tsx +++ b/apps/fo/app/pages/dashboard/facilityInfo/page.tsx @@ -5,6 +5,7 @@ import { ContentsDiv, UiModal, UiTable } from "@common/business_components"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; import { useEffect, useState } from "react"; import DashBoardChartModal from "./modal/page"; +import LoadingOverlay from "@common/business_components/ui/loadingBar"; export type facilityInfoProps = { searchYear?: string; @@ -56,7 +57,7 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}: PlanFclty, OperationStatus, searchOperationStatus, - searchPlanInfo + searchPlanInfo, } = useFoStore((state) => state); const [modalItem, setModalItem] = useState<{item: string, period: string, title: string, waterQlty: string} | null>(null); @@ -77,13 +78,18 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}: const { upHeadListPlanFclty, planFcltyList, - planYearList + planYearList, + waterUsage1, + waterUsage2, + waterUsage3, + isLoadingPlanFclty } = PlanFclty; // 그리드 관련 const { upHeadListOperationStatus, - operationalStatusList + operationalStatusList, + isLoadingOperationStatus } = OperationStatus; const closeModal = () => { @@ -147,20 +153,27 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}: searchPlanInfo(searchYear, fcltyList[0].bscFctCd); setHasSearched(true); setPrevFacilityCode(fcltyList[0].bscFctCd); + } + }, [isInit, searchOperationStatus, searchYear, fcltyList, hasSearched, prevFacilityCode, searchPlanInfo]); + + // waterUsage 값들이 로드된 후에 테이블 데이터 업데이트 + useEffect(() => { + if (waterUsage1 !== '' && waterUsage2 !== '' && waterUsage3 !== '') { planFcltyList.forEach((el: { [key: string]: string | number | boolean }, index) => { if (index === 6) { el['item'] = (Number(searchYear)-2).toString(); - el['provisionalApproval'] = Number(fcltyList[0]?.fcltyCpc)* 0.6; + el['provisionalApproval'] = waterUsage3; } else if (index === 7) { el['item'] = (Number(searchYear)-1).toString(); - el['provisionalApproval'] = Number(fcltyList[0]?.fcltyCpc)* 0.6; + el['provisionalApproval'] = waterUsage2; } else if (index === 8) { el['item'] = (Number(searchYear)-0).toString(); - el['provisionalApproval'] = Number(fcltyList[0]?.fcltyCpc)* 0.6; + el['provisionalApproval'] = waterUsage1; } }); + console.log('planFcltyList :', planFcltyList); } - }, [isInit, searchOperationStatus, searchYear, fcltyList, hasSearched, prevFacilityCode, searchPlanInfo, planFcltyList]); + }, [waterUsage1, waterUsage2, waterUsage3, searchYear, planFcltyList]); // 연도가 바뀌면 hasSearched를 false로 리셋 useEffect(() => { setHasSearched(false); @@ -190,6 +203,7 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}: <> { } } /> +
@@ -211,8 +225,8 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}: :(index < 5 || index > 5)&& (index!= 4) && (head.id ==='provisionalApproval'||head.id ==='now'||head.id ==='stepOne'||head.id ==='stepTwo'||head.id ==='stepThree'||head.id ==='stepFour') ?{el[head.id]} :(head.id === "provisionalApproval" && index === 4) - ?{(Number(fcltyList[0]?.fcltyCpc)* 0.6).toLocaleString('en-US', { minimumFractionDigits: 1, maximumFractionDigits: 1 })} - :((head.id ==='now'||head.id ==='stepOne'||head.id ==='stepTwo'||head.id ==='stepThree'||head.id ==='stepFour') && index === 4) + ?{Math.round((Number(waterUsage1)+Number(waterUsage2)+Number(waterUsage3))/3 * 100)/100} + :((head.id ==='now'||head.id ==='stepOne'||head.id ==='stepTwo'||head.id ==='stepThree'||head.id ==='stepFour') ) ?null :(head.id === 'item' && index != 5)? {el[head.id]} @@ -225,39 +239,40 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
-
- - {upChangeHeadListOperationStatus} - - - {operationalStatusList.map((el: { [key: string]: string | number | boolean },index) => ( - - {upHeadListOperationStatus.map((head) => ( - (head.id === 'flowRate' && index === 0)?{el[head.id]}: - (head.id === 'flowRate' && index === 5)?{el[head.id]}: - (head.id === 'flowRate' && index === 11)?{el[head.id]}: - (head.id === 'groundWaterAvg'||head.id === 'groundWaterSummer'||head.id === 'groundWaterWinter')&&(index === 0)?{el[head.id]}: - (head.id === 'groundWaterAvg'||head.id === 'groundWaterSummer'||head.id === 'groundWaterWinter')&&(index === 7)?{el[head.id]}: - (head.id === 'rdi'&&index === 0)?{el[head.id]}: - (head.id === 'rdi'&&index === 7)?: - (head.id === 'rdiRain'&&index === 0)?{el['rdiRain']}: - (head.id === 'rdiRain'&&index === 7)?: - (head.id === 'waterQlty')?{el[head.id]}: - ((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=0 && index<=4))?{fncLoadModal('flowRate', 'year', el['waterQlty'] as string);}}>{el[head.id]}: - ((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=5 && index<=10))?{fncLoadModal('waterQlty', 'year', el['waterQlty'] as string);}}>{el[head.id]}: - ((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=11 && index<=12))?{fncLoadModal('chongin', 'year', el['waterQlty'] as string);}}>{el[head.id]}: - ((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=0 && index<=4))?{fncLoadModal('flowRate', 'summer', el['waterQlty'] as string);}}>{el[head.id]}: - ((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=5 && index<=10))?{fncLoadModal('waterQlty', 'summer', el['waterQlty'] as string);}}>{el[head.id]}: - ((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=11 && index<=12))?{fncLoadModal('chongin', 'summer', el['waterQlty'] as string);}}>{el[head.id]}: - ((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=0 && index<=4))?{fncLoadModal('flowRate', 'winter', el['waterQlty'] as string);}}>{el[head.id]}: - ((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=5 && index<=10))?{fncLoadModal('waterQlty', 'winter', el['waterQlty'] as string);}}>{el[head.id]}: - ((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=11 && index<=12))?{fncLoadModal('chongin', 'winter', el['waterQlty'] as string);}}>{el[head.id]}: - null - ))} - - ))} - -
+ + + + {upChangeHeadListOperationStatus} + + + {operationalStatusList.map((el: { [key: string]: string | number | boolean },index) => ( + + {upHeadListOperationStatus.map((head) => ( + (head.id === 'flowRate' && index === 0)?{el[head.id]}: + (head.id === 'flowRate' && index === 5)?{el[head.id]}: + (head.id === 'flowRate' && index === 11)?{el[head.id]}: + (head.id === 'groundWaterAvg'||head.id === 'groundWaterSummer'||head.id === 'groundWaterWinter')&&(index === 0)?{el[head.id]}: + (head.id === 'groundWaterAvg'||head.id === 'groundWaterSummer'||head.id === 'groundWaterWinter')&&(index === 7)?{el[head.id]}: + (head.id === 'rdi'&&index === 0)?{el[head.id]}: + (head.id === 'rdi'&&index === 7)?{el[head.id]}: + (head.id === 'rdiRain'&&index === 0)?{el['rdiRain']}: + (head.id === 'rdiRain'&&index === 7)?: + (head.id === 'waterQlty')?{el[head.id]}: + ((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=0 && index<=4))?{fncLoadModal('flowRate', 'year', el['waterQlty'] as string);}}>{el[head.id]}: + ((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=5 && index<=10))?{fncLoadModal('waterQlty', 'year', el['waterQlty'] as string);}}>{el[head.id]}: + ((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=11 && index<=12))?{fncLoadModal('chongin', 'year', el['waterQlty'] as string);}}>{el[head.id]}: + ((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=0 && index<=4))?{fncLoadModal('flowRate', 'summer', el['waterQlty'] as string);}}>{el[head.id]}: + ((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=5 && index<=10))?{fncLoadModal('waterQlty', 'summer', el['waterQlty'] as string);}}>{el[head.id]}: + ((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=11 && index<=12))?{fncLoadModal('chongin', 'summer', el['waterQlty'] as string);}}>{el[head.id]}: + ((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=0 && index<=4))?{fncLoadModal('flowRate', 'winter', el['waterQlty'] as string);}}>{el[head.id]}: + ((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=5 && index<=10))?{fncLoadModal('waterQlty', 'winter', el['waterQlty'] as string);}}>{el[head.id]}: + ((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=11 && index<=12))?{fncLoadModal('chongin', 'winter', el['waterQlty'] as string);}}>{el[head.id]}: + null + ))} + + ))} + +
diff --git a/apps/fo/app/pages/dashboard/maingraph/page.tsx b/apps/fo/app/pages/dashboard/maingraph/page.tsx index 5ee9eeda0..375cdbbdf 100644 --- a/apps/fo/app/pages/dashboard/maingraph/page.tsx +++ b/apps/fo/app/pages/dashboard/maingraph/page.tsx @@ -5,6 +5,7 @@ import { CHART_FORM, type ChartConfig, ContentsDiv, MainChart } from "@common/bu import { Card, CardContent } from "@common/business_components/ui/chart/lib/card"; import ListDiv from "@common/business_components/ui/list_div"; import { useEffect, useState } from "react"; +import LoadingOverlay from "@common/business_components/ui/loadingBar"; type facilityInfoProps = { searchYear?: string; @@ -44,6 +45,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili chart_inflTn, chart_efflTn, chart_inflBod, + isLoadingMainGraph, } = MainGraph; /** @@ -179,6 +181,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili return ( <> + diff --git a/apps/fo/app/pages/dashboard/page.tsx b/apps/fo/app/pages/dashboard/page.tsx index 09c452da4..0903c9229 100644 --- a/apps/fo/app/pages/dashboard/page.tsx +++ b/apps/fo/app/pages/dashboard/page.tsx @@ -57,8 +57,7 @@ export default function DashBoard() { /******************선택된 데이터******************/ // 연도 - //const [searchYear, setSearchYear] = useState(selectSearchYear[0]?.val || '0'); - const [searchYear, setSearchYear] = useState('2023'); + const [searchYear, setSearchYear] = useState(selectSearchYear[0]?.val || '0'); // 시설명 const [fcltyList, setFcltyList] = useState<{bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | ''}>({ bscFctCd: '26260PB001R', @@ -280,8 +279,11 @@ export default function DashBoard() { trtFrfNm: '표준활성슬러지법, MLE, MBR', efflWqltStndrdNm: '500톤 이상(Ⅳ지역)' }); - setSearchYear('2023'); + setSearchYear(selectSearchYear[0]?.val || '0'); searchFcltyList.bscFctNm = '수영'; + + setSidoValue('0'); + setSigunValue('0'); } const searchVal = () => { diff --git a/apps/fo/app/pages/dashboard/rainManage/page.tsx b/apps/fo/app/pages/dashboard/rainManage/page.tsx index ea20eb92c..9bceed75e 100644 --- a/apps/fo/app/pages/dashboard/rainManage/page.tsx +++ b/apps/fo/app/pages/dashboard/rainManage/page.tsx @@ -45,6 +45,7 @@ export default function RainManageTab({searchYear = '', fcltyList = []}: facilit }, [searchYear]); return ( +
{}} > + ☞ 일수에 강우영향일 포함됨 +
) } diff --git a/apps/fo/app/pages/facilityPrecipitation/page.tsx b/apps/fo/app/pages/facilityPrecipitation/page.tsx index 96456a71b..a0dce5274 100644 --- a/apps/fo/app/pages/facilityPrecipitation/page.tsx +++ b/apps/fo/app/pages/facilityPrecipitation/page.tsx @@ -5,6 +5,7 @@ import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, Selec import ListDiv from "@common/business_components/ui/list_div"; import { useCallback, useEffect, useRef, useState } from "react"; import PrecipitationModal from "./modal/page"; +import LoadingOverlay from "@common/business_components/ui/loadingBar"; export default function FacilityPrecipitation() { const {Common @@ -39,7 +40,8 @@ export default function FacilityPrecipitation() { upHeadList3, excelList, facilityPrecipitation, - facilityPrecipitationCount + facilityPrecipitationCount, + isLoading, } = FacilityPrecipitation; const { @@ -81,8 +83,7 @@ export default function FacilityPrecipitation() { // 시설상태 const [operationValue, setOperationValue] = useState("0"); // 조회기간 - //const [searchYear, setSearchYear] = useState(selectSearchYear[0]?.val || "0"); - const [searchYear, setSearchYear] = useState("2023"); + const [searchYear, setSearchYear] = useState(selectSearchYear[0]?.val || "0"); /** * 페이지 함수 @@ -126,9 +127,9 @@ export default function FacilityPrecipitation() { useEffect(() => { if (!isInit) { initializeCommonData(); - searchFacilityPrecipitationList(1, 10, searchYear || "0"); + searchFacilityPrecipitationList(1, 10, selectSearchYear[0]?.val || "0"); } - }, [isInit, initializeCommonData, searchFacilityPrecipitationList, searchYear]); + }, [isInit, initializeCommonData, searchFacilityPrecipitationList]); useEffect(() => { if (excelList && excelList.length > 0) { @@ -227,6 +228,7 @@ export default function FacilityPrecipitation() { initClick={resetVal} ref={ref} isAdmin={false} /> +
index !== undefined && cellClick(index)} headName={"시설별 강수현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} /> diff --git a/apps/fo/app/pages/facilityWaterQlty/modal/page.tsx b/apps/fo/app/pages/facilityWaterQlty/modal/page.tsx index eadfa9ba8..1ac1bc00f 100644 --- a/apps/fo/app/pages/facilityWaterQlty/modal/page.tsx +++ b/apps/fo/app/pages/facilityWaterQlty/modal/page.tsx @@ -66,11 +66,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe let maxefflWqltToc = 0; let maxEfflWqltSs = 0; - let maxInflAssctAftWqltBod = 0; - let maxInflAssctAftWqltTn = 0; + let maxinflAssctBfrWqltBod = 0; + let maxinflAssctBfrWqltTn = 0; let maxInflAssctBfrWqltTp = 0; - let maxInflAssctAftWqltToc = 0; - let maxInflAssctAftWqltSs = 0; + let maxinflAssctBfrWqltToc = 0; + let maxinflAssctBfrWqltSs = 0; let maxTpInflWqltBod = 0; let maxTpInflWqltTp = 0; @@ -83,11 +83,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe 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; - let minInflAssctAftWqltTn = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctAftWqltTn) : 0; + let mininflAssctBfrWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltBod) : 0; + let mininflAssctBfrWqltTn = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltTn) : 0; let minInflAssctBfrWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltTp) : 0; - let minInflAssctAftWqltToc = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctAftWqltToc) : 0; - let minInflAssctAftWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctAftWqltSs) : 0; + let mininflAssctBfrWqltToc = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltToc) : 0; + let mininflAssctBfrWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltSs) : 0; let minTpInflWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.tpInflWqltBod) : 0; let minTpInflWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.tpInflWqltTp) : 0; @@ -100,11 +100,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe let avgefflWqltToc = 0; let avgEfflWqltSs = 0; - let avgInflAssctAftWqltBod = 0; - let avgInflAssctAftWqltTn = 0; + let avginflAssctBfrWqltBod = 0; + let avginflAssctBfrWqltTn = 0; let avgInflAssctBfrWqltTp = 0; - let avgInflAssctAftWqltToc = 0; - let avgInflAssctAftWqltSs = 0; + let avginflAssctBfrWqltToc = 0; + let avginflAssctBfrWqltSs = 0; let avgTpInflWqltBod = 0; let avgTpInflWqltTp = 0; @@ -118,11 +118,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe const efflWqltToc = parseNumber(item.efflWqltToc); const efflWqltSs = parseNumber(item.efflWqltSs); - const inflAssctAftWqltBod = parseNumber(item.inflAssctAftWqltBod); - const inflAssctAftWqltTn = parseNumber(item.inflAssctAftWqltTn); + const inflAssctBfrWqltBod = parseNumber(item.inflAssctBfrWqltBod); + const inflAssctBfrWqltTn = parseNumber(item.inflAssctBfrWqltTn); const inflAssctBfrWqltTp = parseNumber(item.inflAssctBfrWqltTp); - const inflAssctAftWqltToc = parseNumber(item.inflAssctAftWqltToc); - const inflAssctAftWqltSs = parseNumber(item.inflAssctAftWqltSs); + const inflAssctBfrWqltToc = parseNumber(item.inflAssctBfrWqltToc); + const inflAssctBfrWqltSs = parseNumber(item.inflAssctBfrWqltSs); const tpInflWqltBod = parseNumber(item.tpInflWqltBod); @@ -136,11 +136,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe maxefflWqltToc = Math.max(maxefflWqltToc, efflWqltToc); maxEfflWqltSs = Math.max(maxEfflWqltSs, efflWqltSs); - maxInflAssctAftWqltBod = Math.max(maxInflAssctAftWqltBod, inflAssctAftWqltBod); - maxInflAssctAftWqltTn = Math.max(maxInflAssctAftWqltTn, inflAssctAftWqltTn); + maxinflAssctBfrWqltBod = Math.max(maxinflAssctBfrWqltBod, inflAssctBfrWqltBod); + maxinflAssctBfrWqltTn = Math.max(maxinflAssctBfrWqltTn, inflAssctBfrWqltTn); maxInflAssctBfrWqltTp = Math.max(maxInflAssctBfrWqltTp, inflAssctBfrWqltTp); - maxInflAssctAftWqltToc = Math.max(maxInflAssctAftWqltToc, inflAssctAftWqltToc); - maxInflAssctAftWqltSs = Math.max(maxInflAssctAftWqltSs, inflAssctAftWqltSs); + maxinflAssctBfrWqltToc = Math.max(maxinflAssctBfrWqltToc, inflAssctBfrWqltToc); + maxinflAssctBfrWqltSs = Math.max(maxinflAssctBfrWqltSs, inflAssctBfrWqltSs); maxTpInflWqltBod = Math.max(maxTpInflWqltBod, tpInflWqltBod); maxTpInflWqltTp = Math.max(maxTpInflWqltTp, tpInflWqltTp); @@ -153,11 +153,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe minefflWqltToc = Math.min(minefflWqltToc, efflWqltToc); minEfflWqltSs = Math.min(minEfflWqltSs, efflWqltSs); - minInflAssctAftWqltBod = Math.min(minInflAssctAftWqltBod, inflAssctAftWqltBod); - minInflAssctAftWqltTn = Math.min(minInflAssctAftWqltTn, inflAssctAftWqltTn); + mininflAssctBfrWqltBod = Math.min(mininflAssctBfrWqltBod, inflAssctBfrWqltBod); + mininflAssctBfrWqltTn = Math.min(mininflAssctBfrWqltTn, inflAssctBfrWqltTn); minInflAssctBfrWqltTp = Math.min(minInflAssctBfrWqltTp, inflAssctBfrWqltTp); - minInflAssctAftWqltToc = Math.min(minInflAssctAftWqltToc, inflAssctAftWqltToc); - minInflAssctAftWqltSs = Math.min(minInflAssctAftWqltSs, inflAssctAftWqltSs); + mininflAssctBfrWqltToc = Math.min(mininflAssctBfrWqltToc, inflAssctBfrWqltToc); + mininflAssctBfrWqltSs = Math.min(mininflAssctBfrWqltSs, inflAssctBfrWqltSs); minTpInflWqltBod = Math.min(minTpInflWqltBod, tpInflWqltBod); minTpInflWqltTp = Math.min(minTpInflWqltTp, tpInflWqltTp); @@ -170,11 +170,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe avgefflWqltToc += efflWqltToc; avgEfflWqltSs += efflWqltSs; - avgInflAssctAftWqltBod += inflAssctAftWqltBod; - avgInflAssctAftWqltTn += inflAssctAftWqltTn; + avginflAssctBfrWqltBod += inflAssctBfrWqltBod; + avginflAssctBfrWqltTn += inflAssctBfrWqltTn; avgInflAssctBfrWqltTp += inflAssctBfrWqltTp; - avgInflAssctAftWqltToc += inflAssctAftWqltToc; - avgInflAssctAftWqltSs += inflAssctAftWqltSs; + avginflAssctBfrWqltToc += inflAssctBfrWqltToc; + avginflAssctBfrWqltSs += inflAssctBfrWqltSs; avgTpInflWqltBod += tpInflWqltBod; avgTpInflWqltTp += tpInflWqltTp; @@ -190,11 +190,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe efflWqltSs: filteredData.length==0?'0.0':(Math.round(avgEfflWqltSs / filteredData.length * 10) / 10).toFixed(1), efflWqltTn: filteredData.length==0?'0.000':(Math.round(avgEfflWqltTn / filteredData.length * 1000) / 1000).toFixed(3), efflWqltTp: filteredData.length==0?'0.000':(Math.round(avgEfflWqltTp / filteredData.length * 1000) / 1000).toFixed(3), - inflAssctAftWqltBod: filteredData.length==0?'0.0':(Math.round(avgInflAssctAftWqltBod / filteredData.length * 10) / 10).toFixed(1), - inflAssctAftWqltTn: filteredData.length==0?'0.000':(Math.round(avgInflAssctAftWqltTn / filteredData.length * 1000) / 1000).toFixed(3), + inflAssctBfrWqltBod: filteredData.length==0?'0.0':(Math.round(avginflAssctBfrWqltBod / filteredData.length * 10) / 10).toFixed(1), + inflAssctBfrWqltTn: filteredData.length==0?'0.000':(Math.round(avginflAssctBfrWqltTn / filteredData.length * 1000) / 1000).toFixed(3), inflAssctBfrWqltTp: filteredData.length==0?'0.000':(Math.round(avgInflAssctBfrWqltTp / filteredData.length * 1000) / 1000).toFixed(3), - inflAssctAftWqltToc: filteredData.length==0?'0.0':(Math.round(avgInflAssctAftWqltToc / filteredData.length * 10) / 10).toFixed(1), - inflAssctAftWqltSs: filteredData.length==0?'0.0':(Math.round(avgInflAssctAftWqltSs / filteredData.length * 10) / 10).toFixed(1), + inflAssctBfrWqltToc: filteredData.length==0?'0.0':(Math.round(avginflAssctBfrWqltToc / filteredData.length * 10) / 10).toFixed(1), + inflAssctBfrWqltSs: filteredData.length==0?'0.0':(Math.round(avginflAssctBfrWqltSs / filteredData.length * 10) / 10).toFixed(1), bscFctCd: "", bscFctNm: "", lclgvrnmntNm: "", @@ -213,11 +213,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe efflWqltSs : Math.round(maxEfflWqltSs * 10) / 10?(Math.round(maxEfflWqltSs * 10) / 10).toFixed(1):'0.0', efflWqltTn : Math.round(maxEfflWqltTn * 1000) / 1000?(Math.round(maxEfflWqltTn * 1000) / 1000).toFixed(3):'0.000', efflWqltTp : Math.round(maxEfflWqltTp * 1000) / 1000?(Math.round(maxEfflWqltTp * 1000) / 1000).toFixed(3):'0.000', - inflAssctAftWqltBod : Math.round(maxInflAssctAftWqltBod * 10) / 10?(Math.round(maxInflAssctAftWqltBod * 10) / 10).toFixed(1):'0.0', - inflAssctAftWqltTn : Math.round(maxInflAssctAftWqltTn * 1000) / 1000?(Math.round(maxInflAssctAftWqltTn * 1000) / 1000).toFixed(3):'0.000', + inflAssctBfrWqltBod : Math.round(maxinflAssctBfrWqltBod * 10) / 10?(Math.round(maxinflAssctBfrWqltBod * 10) / 10).toFixed(1):'0.0', + inflAssctBfrWqltTn : Math.round(maxinflAssctBfrWqltTn * 1000) / 1000?(Math.round(maxinflAssctBfrWqltTn * 1000) / 1000).toFixed(3):'0.000', inflAssctBfrWqltTp : Math.round(maxInflAssctBfrWqltTp * 1000) / 1000?(Math.round(maxInflAssctBfrWqltTp * 1000) / 1000).toFixed(3):'0.000', - inflAssctAftWqltToc : Math.round(maxInflAssctAftWqltToc * 10) / 10?(Math.round(maxInflAssctAftWqltToc * 10) / 10).toFixed(1):'0.0', - inflAssctAftWqltSs : Math.round(maxInflAssctAftWqltSs * 10) / 10?(Math.round(maxInflAssctAftWqltSs * 10) / 10).toFixed(1):'0.0', + inflAssctBfrWqltToc : Math.round(maxinflAssctBfrWqltToc * 10) / 10?(Math.round(maxinflAssctBfrWqltToc * 10) / 10).toFixed(1):'0.0', + inflAssctBfrWqltSs : Math.round(maxinflAssctBfrWqltSs * 10) / 10?(Math.round(maxinflAssctBfrWqltSs * 10) / 10).toFixed(1):'0.0', bscFctCd: "", bscFctNm: "", lclgvrnmntNm: "", @@ -236,11 +236,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe efflWqltSs : Math.round(minEfflWqltSs * 10) / 10?(Math.round(minEfflWqltSs * 10) / 10).toFixed(1) : '0.0', efflWqltTn : Math.round(minEfflWqltTn * 1000) / 1000?(Math.round(minEfflWqltTn * 1000) / 1000).toFixed(3) : '0.000', efflWqltTp : Math.round(minEfflWqltTp * 1000) / 1000?(Math.round(minEfflWqltTp * 1000) / 1000).toFixed(3) : '0.000', - inflAssctAftWqltBod : Math.round(minInflAssctAftWqltBod * 10) / 10?(Math.round(minInflAssctAftWqltBod * 10) / 10).toFixed(1) : '0.0', - inflAssctAftWqltTn : Math.round(minInflAssctAftWqltTn * 1000) / 1000?(Math.round(minInflAssctAftWqltTn * 1000) / 1000).toFixed(3) : '0.000', + inflAssctBfrWqltBod : Math.round(mininflAssctBfrWqltBod * 10) / 10?(Math.round(mininflAssctBfrWqltBod * 10) / 10).toFixed(1) : '0.0', + inflAssctBfrWqltTn : Math.round(mininflAssctBfrWqltTn * 1000) / 1000?(Math.round(mininflAssctBfrWqltTn * 1000) / 1000).toFixed(3) : '0.000', inflAssctBfrWqltTp : Math.round(minInflAssctBfrWqltTp * 1000) / 1000?(Math.round(minInflAssctBfrWqltTp * 1000) / 1000).toFixed(3) : '0.000', - inflAssctAftWqltToc : Math.round(minInflAssctAftWqltToc * 10) / 10?(Math.round(minInflAssctAftWqltToc * 10) / 10).toFixed(1) : '0.0', - inflAssctAftWqltSs : Math.round(minInflAssctAftWqltSs * 10) / 10?(Math.round(minInflAssctAftWqltSs * 10) / 10).toFixed(1) : '0.0', + inflAssctBfrWqltToc : Math.round(mininflAssctBfrWqltToc * 10) / 10?(Math.round(mininflAssctBfrWqltToc * 10) / 10).toFixed(1) : '0.0', + inflAssctBfrWqltSs : Math.round(mininflAssctBfrWqltSs * 10) / 10?(Math.round(mininflAssctBfrWqltSs * 10) / 10).toFixed(1) : '0.0', bscFctCd: "", bscFctNm: "", lclgvrnmntNm: "", @@ -293,10 +293,10 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe copyYearList.forEach((item) => { excelDownList.push({ 날짜: item.msrDt, - "유입BOD(mg/L)": item.inflAssctAftWqltBod, - "유입TOC(COD)(mg/L)": item.inflAssctAftWqltToc, - "유입SS(mg/L)": item.inflAssctAftWqltSs, - "유입TN(mg/L)": item.inflAssctAftWqltTn, + "유입BOD(mg/L)": item.inflAssctBfrWqltBod, + "유입TOC(COD)(mg/L)": item.inflAssctBfrWqltToc, + "유입SS(mg/L)": item.inflAssctBfrWqltSs, + "유입TN(mg/L)": item.inflAssctBfrWqltTn, "유입TP(mg/L)": item.inflAssctBfrWqltTp, "유출BOD(mg/L)": item.efflWqltBod, "유출TOC(COD)(mg/L)": item.efflWqltToc, diff --git a/apps/fo/app/pages/facilityWaterQlty/page.tsx b/apps/fo/app/pages/facilityWaterQlty/page.tsx index 7d571a69f..0e215f565 100644 --- a/apps/fo/app/pages/facilityWaterQlty/page.tsx +++ b/apps/fo/app/pages/facilityWaterQlty/page.tsx @@ -7,6 +7,7 @@ import ListDiv from "@common/business_components/ui/list_div"; import { useCallback, useEffect, useRef, useState } from "react"; import WaterQualityModal from "./modal/page"; import type { FacilityWaterQltyProps } from "@/app/store/facilityWaterQlty"; +import LoadingOverlay from "@common/business_components/ui/loadingBar"; export default function ProcessFacilitySearch() { const { Common @@ -36,7 +37,8 @@ export default function ProcessFacilitySearch() { upHeadList3, facilityWaterQltyList, facilityWaterQltyCount, - excelList + excelList, + isLoading, } = FacilityWaterQltyMain; const mainList: FacilityWaterQltyProps[] = facilityWaterQltyList || []; @@ -48,8 +50,7 @@ export default function ProcessFacilitySearch() { const [upheadList, setUpheadList] = useState(upHeadList1); const [fcltyName, setFcltyName] = useState(""); const [operationValue, setOperationValue] = useState("0"); - //const [searchYearValue, setSearchYearValue] = useState(selectSearchYear[0]?.val || "0"); - const [searchYearValue, setSearchYearValue] = useState("2023"); + const [searchYearValue, setSearchYearValue] = useState(selectSearchYear[0]?.val || "0"); const [fcltCpct, setFcltCpct] = useState("0"); // 모달 상태 추가 @@ -133,7 +134,7 @@ export default function ProcessFacilitySearch() { initializeCommonData(); searchFacilityWaterQltyList(1, 10, selectSearchYear[0]?.val || "0"); } - }, [isInit, initializeCommonData, searchFacilityWaterQltyList, selectSearchYear]); + }, [isInit, initializeCommonData, searchFacilityWaterQltyList]); useEffect(() => { if (excelList && excelList.length > 0) { @@ -187,6 +188,7 @@ export default function ProcessFacilitySearch() { initClick={resetVal} ref={ref} isAdmin={false} /> +
index !== undefined && cellClick(index)} headName={"시설별 수질현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total<10?facilityWaterQltyList.length:total} resetPageNo={resetPage} onPageChange={handlePageChange} /> diff --git a/apps/fo/app/pages/flowRate/modal/page.tsx b/apps/fo/app/pages/flowRate/modal/page.tsx index 409dab7eb..bc121708c 100644 --- a/apps/fo/app/pages/flowRate/modal/page.tsx +++ b/apps/fo/app/pages/flowRate/modal/page.tsx @@ -52,7 +52,6 @@ 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; diff --git a/apps/fo/app/pages/flowRate/page.tsx b/apps/fo/app/pages/flowRate/page.tsx index 0c4f503e9..fdb0db487 100644 --- a/apps/fo/app/pages/flowRate/page.tsx +++ b/apps/fo/app/pages/flowRate/page.tsx @@ -6,6 +6,7 @@ import ListDiv from "@common/business_components/ui/list_div"; import { useCallback, useEffect, useRef, useState } from "react"; import FlowRateModal from "./modal/page"; import type { ExcelType } from "@/app/store/flowRate"; +import LoadingOverlay from "@common/business_components/ui/loadingBar"; export default function ProcessFacilitySearch() { const {Common @@ -42,15 +43,15 @@ export default function ProcessFacilitySearch() { upHeadList3, flowRateList, flowRateCount, - excelList + excelList, + isLoading, } = FlowRateList; // 입력값 상태 관리 const [fcltCpct, setFcltCpct] = useState("0"); const [fcltyName, setFcltyName] = useState(""); const [operationValue, setOperationValue] = useState("0"); - //const [searchYearValue, setSearchYearValue] = useState(selectSearchYear[0]?.val || "0"); - const [searchYearValue, setSearchYearValue] = useState("2023"); + const [searchYearValue, setSearchYearValue] = useState(selectSearchYear[0]?.val || "0"); const [widthSize, setWidthSize] = useState("w-[120%]"); const [upheadList, setUpheadList] = useState(upHeadList1); const [resetPage, setResetPage] = useState(false); @@ -89,9 +90,9 @@ export default function ProcessFacilitySearch() { setWidthSize("w-[120%]"); setUpheadList(upHeadList1) // 상태값 설정 + setSearchYearValue(selectSearchYear[0]?.val || "0"); setFcltCpct(selectUpdownData[0]?.val || "0"); setOperationValue(selectOperationData[0]?.val || "0"); - setSearchYearValue(selectSearchYear[0]?.val || "0"); // SearchInputSelect 초기화 setFcltyName(""); if (searchInputRef.current) { @@ -126,11 +127,10 @@ export default function ProcessFacilitySearch() { // 시도 데이터 초기화 useEffect(() => { if(!isInit) { - console.log('searchYearValue', searchYearValue, isInit); initializeCommonData(); - searchFlowRateList(1, 10, searchYearValue || "0"); + searchFlowRateList(1, 10, selectSearchYear[0]?.val || "0"); } - }, [isInit, initializeCommonData, searchFlowRateList, searchYearValue]); + }, [isInit, initializeCommonData, searchFlowRateList]); useEffect(() => { if (excelList && excelList.length > 0) { @@ -189,6 +189,7 @@ export default function ProcessFacilitySearch() { initClick={resetVal} ref={ref} isAdmin={false} /> +
index !== undefined && cellClick(index)} headName={"시설별 유량현황"} tableData={flowRateList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} /> diff --git a/apps/fo/app/pages/map/page.tsx b/apps/fo/app/pages/map/page.tsx index cbbe0dd11..2c27869b0 100644 --- a/apps/fo/app/pages/map/page.tsx +++ b/apps/fo/app/pages/map/page.tsx @@ -13,7 +13,11 @@ interface FeatureData { } interface MapInstance { - getLayers: () => { getArray: () => Array<{ getSource?: () => { getFeatureById?: (id: string) => FeatureData | null } }> }; + getLayers: () => { + getArray: () => Array<{ + getSource?: () => { getFeatureById?: (id: string) => FeatureData | null }; + }>; + }; getView: () => { fit: (extent: number[], options: object) => void }; } @@ -26,20 +30,20 @@ const Map = () => { const fetchData = async () => { try { - const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}/v1/map` + const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}/v1/map`; const reqUrl = `${API_URL}/lyrStngs/FO_NETWORK`; const response = await fetch(reqUrl, { method: "GET", headers: { accept: "application/json", - } + }, }); if (!response.ok) { throw new Error(`HTTP 오류! 상태: ${response.status}`); } - const data = await response.json(); // 여기서 json 파싱 + const data = await response.json(); // 여기서 json 파싱 setTreeData(data); // 데이터 설정 } catch (error) { console.error("데이터 불러오기 실패:", error); @@ -60,7 +64,12 @@ const Map = () => { } // 항상 같은 select 객체 사용 - const select = (GisApp.Module.select as unknown) as { resetSelectedFeature: () => void; selectFeature: (feature: FeatureData, selected: boolean) => void } | undefined; + const select = GisApp.Module.select as unknown as + | { + resetSelectedFeature: () => void; + selectFeature: (feature: FeatureData, selected: boolean) => void; + } + | undefined; if (!select) return; // 1. 기존 선택 초기화 @@ -115,9 +124,12 @@ const Map = () => { }; // onCheckedLayersChange handler - const handleCheckedLayersChange = (checkedIds: string[], checkedNodesData: unknown[]) => { + const handleCheckedLayersChange = ( + checkedIds: string[], + checkedNodesData: unknown[] + ) => { // Handle checked layers change if needed - console.log('Checked layers changed:', checkedIds, checkedNodesData); + console.log("Checked layers changed:", checkedIds, checkedNodesData); }; return ( @@ -137,6 +149,8 @@ const Map = () => { isOpen={isOpen} isSearchModalOpen={isSearchModalOpen} onCheckedLayersChange={handleCheckedLayersChange} + imgVisble={false} + searchBar={undefined} />
); diff --git a/apps/fo/app/pages/planSewage/page.tsx b/apps/fo/app/pages/planSewage/page.tsx index c9324c246..b39a3e8df 100644 --- a/apps/fo/app/pages/planSewage/page.tsx +++ b/apps/fo/app/pages/planSewage/page.tsx @@ -4,6 +4,7 @@ import type { TableUpperProps } from "@/app/store/common"; import { downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiTable, type ReturnType } from "@common/business_components"; import ListDiv from "@common/business_components/ui/list_div"; import { useCallback, useEffect, useRef, useState } from "react"; +import LoadingOverlay from "@common/business_components/ui/loadingBar"; export default function PlanSewage() { const {Common @@ -37,7 +38,8 @@ export default function PlanSewage() { upHeadList3, planSewageList, planSewageCount, - excelList + excelList, + isLoading, } = PlanSewage; const ref = useRef({ @@ -70,8 +72,7 @@ export default function PlanSewage() { // 시설상태 const [operationValue, setOperationValue] = useState("0"); // 조회기간 - //const [searchYear, setSearchYear] = useState(selectSearchYear[0]?.val || "0"); - const [searchYear, setSearchYear] = useState("2023"); + const [searchYear, setSearchYear] = useState(selectSearchYear[0]?.val || "0"); /** * 페이지 함수 @@ -92,6 +93,7 @@ export default function PlanSewage() { input.value = ""; } } + searchPlanSewageList(1, 10, selectSearchYear[0]?.val || "0", ref.current.partValue); } /** @@ -100,9 +102,9 @@ export default function PlanSewage() { useEffect(() => { if (!isInit) { initializeCommonData(); - searchPlanSewageList(1, 10, searchYear, ref.current.partValue); + searchPlanSewageList(1, 10, selectSearchYear[0]?.val || "0", ref.current.partValue); } - }, [isInit, initializeCommonData, searchYear, searchPlanSewageList]); + }, [isInit, initializeCommonData, searchPlanSewageList]); useEffect(() => { console.log('excelList' , excelList); @@ -187,6 +189,7 @@ export default function PlanSewage() { initClick={resetVal} ref={ref} isAdmin={false}/> +
diff --git a/apps/fo/app/pages/processArea/page.tsx b/apps/fo/app/pages/processArea/page.tsx index 92369cb45..24a30d910 100644 --- a/apps/fo/app/pages/processArea/page.tsx +++ b/apps/fo/app/pages/processArea/page.tsx @@ -4,6 +4,7 @@ import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SelectBox, Title, import ListDiv from "@common/business_components/ui/list_div"; import { useCallback, useEffect, useRef, useState } from "react"; import ProcessFacilityInfoModal from "./modal/page"; +import LoadingOverlay from "@common/business_components/ui/loadingBar"; export default function ProcessArea() { const {Common, @@ -39,7 +40,8 @@ export default function ProcessArea() { upHeadList1, processAreaList, processAreaCount, - excelList + excelList, + isLoading, } = ProcessArea; const mainList: Record[] = processAreaList || []; @@ -84,7 +86,7 @@ export default function ProcessArea() { } } setSearchYearValue(selectSearchYear[0]?.val || "0"); - searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val); + searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val || "0"); } // 셀 클릭 시 모달 표시 @@ -104,9 +106,9 @@ export default function ProcessArea() { useEffect(() => { if (!isInit) { initializeCommonData(); - searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val); + searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val || "0"); } - }, [isInit, initializeCommonData, searchProcessAreaList, selectSearchYear]); + }, [isInit, initializeCommonData, searchProcessAreaList]); useEffect(() => { if (excelList && excelList.length > 0) { @@ -152,6 +154,7 @@ export default function ProcessArea() { isAdmin={true} /> +
index !== undefined && cellClick(index)} headName={"처리구역정보"} tableData={mainList} headlist={upHeadList1} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} /> diff --git a/apps/fo/app/pages/processFacility/page.tsx b/apps/fo/app/pages/processFacility/page.tsx index ed58dea2b..109b64562 100644 --- a/apps/fo/app/pages/processFacility/page.tsx +++ b/apps/fo/app/pages/processFacility/page.tsx @@ -5,6 +5,7 @@ import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, Selec import ListDiv from "@common/business_components/ui/list_div"; import { useCallback, useEffect, useRef, useState } from "react"; import ProcessFacilityInfoModal from "./modal/page"; +import LoadingOverlay from "@common/business_components/ui/loadingBar"; export default function ProcessFacilitySearch() { const {Common @@ -63,7 +64,8 @@ export default function ProcessFacilitySearch() { upHeadList1, upHeadList2, upHeadList3, - excelList + excelList, + isLoading, } = ProcessFacilityList; const processFacilityList = ProcessFacilityList?.processFacilityList || []; @@ -262,6 +264,7 @@ export default function ProcessFacilitySearch() { initClick={resetVal} ref={ref} isAdmin={false} /> +
({ @@ -70,6 +72,10 @@ export default function Rdi() { // 조회기간 const [searchYear, setSearchYear] = useState(selectSearchYear[0]?.val || "0"); + useEffect(() => { + console.log(isLoading); + }, [isLoading]); + /** * 페이지 함수 */ @@ -91,7 +97,6 @@ export default function Rdi() { } } searchRdiList(1, 10, selectSearchYear[0]?.val || "0"); - } /** @@ -102,7 +107,7 @@ export default function Rdi() { initializeCommonData(); searchRdiList(1, 10, selectSearchYear[0]?.val || "0"); } - }, [isInit, initializeCommonData, searchRdiList, selectSearchYear]); + }, [isInit, initializeCommonData, searchRdiList]); useEffect(() => { if (excelList && excelList.length > 0) { @@ -187,6 +192,7 @@ export default function Rdi() { initClick={resetVal} ref={ref} isAdmin={false} /> +
diff --git a/apps/fo/app/pages/sewageOccur/modal/page.tsx b/apps/fo/app/pages/sewageOccur/modal/page.tsx index 23c890160..06ca11cc1 100644 --- a/apps/fo/app/pages/sewageOccur/modal/page.tsx +++ b/apps/fo/app/pages/sewageOccur/modal/page.tsx @@ -30,6 +30,11 @@ export default function SewageOccurModal(props: { fcltyName: string; facilityCd setDetailList(gridListSewageOccurDetail); }, [gridListSewageOccurDetail]); + + useEffect(() => { + searchSewageOccurDetailList(props.facilityCd, validSearchYear, startYearMonth, endYearMonth); + }, [startYearMonth, endYearMonth]); + return ( <> @@ -57,6 +62,7 @@ export default function SewageOccurModal(props: { fcltyName: string; facilityCd }} selectClass="ml-5 w-[100px]" startYear={1900} + yearReadOnly={true} />~ diff --git a/apps/fo/app/pages/sewageOccur/page.tsx b/apps/fo/app/pages/sewageOccur/page.tsx index 8b004e681..885af7567 100644 --- a/apps/fo/app/pages/sewageOccur/page.tsx +++ b/apps/fo/app/pages/sewageOccur/page.tsx @@ -6,6 +6,7 @@ import ListDiv from "@common/business_components/ui/list_div"; import { useCallback, useEffect, useRef, useState } from "react"; import SewageOccurModal from "./modal/page"; import type { SewageOccurProps } from "@/app/store/sewageOccur"; +import LoadingOverlay from "@common/business_components/ui/loadingBar"; export default function PlanSewage() { const {Common @@ -46,7 +47,8 @@ export default function PlanSewage() { upHeadList3, sewageOccurList, sewageOccurCount, - excelList + excelList, + isLoading, } = SewageOccur; const ref = useRef({ @@ -84,8 +86,7 @@ export default function PlanSewage() { // 시설상태 const [operationValue, setOperationValue] = useState("0"); // 조회기간 - // const [searchYear, setSearchYear] = useState(selectSearchYear[0]?.val || "0"); - const [searchYear, setSearchYear] = useState("2023"); + const [searchYear, setSearchYear] = useState(selectSearchYear[0]?.val || "0"); /** * 페이지 함수 @@ -106,6 +107,7 @@ export default function PlanSewage() { input.value = ""; } } + searchSewageOccurList(1, 10, selectSearchYear[0]?.val || "0"); } // 모달 닫기 @@ -128,9 +130,9 @@ export default function PlanSewage() { useEffect(() => { if (!isInit) { initializeCommonData(); - searchSewageOccurList(1, 10, searchYear || "0"); + searchSewageOccurList(1, 10, selectSearchYear[0]?.val || "0"); } - }, [isInit, initializeCommonData, searchSewageOccurList, searchYear]); + }, [isInit, initializeCommonData, searchSewageOccurList]); useEffect(() => { if (excelList && excelList.length > 0) { @@ -217,6 +219,7 @@ export default function PlanSewage() { isAdmin={false} /> +
index !== undefined && cellClick(index)} headName={"오수발생량 추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} /> diff --git a/apps/fo/app/pages/underWaterInput/modal/page.tsx b/apps/fo/app/pages/underWaterInput/modal/page.tsx index 145612431..1e37569c6 100644 --- a/apps/fo/app/pages/underWaterInput/modal/page.tsx +++ b/apps/fo/app/pages/underWaterInput/modal/page.tsx @@ -116,7 +116,6 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date( } }, [searchYear, tabTerm]); useEffect(()=>{ - console.log(fcltyName, searchYear); unserWaterModal(fcltyName, searchYear); }, []) useEffect(() => { @@ -164,6 +163,7 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date( }} selectClass="ml-5 w-[100px]" startYear={Number(searchYear)} // 시작 연도 설정 + yearReadOnly={true} />

~

@@ -227,6 +228,8 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date( }} selectClass="ml-5 w-[100px]" startYear={Number(searchYear)} // 시작 연도 설정 + yearReadOnly={true} + enableMonth={['6월', '7월', '8월']} />

~

@@ -281,6 +286,8 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date( }} selectClass="ml-5 w-[100px]" startYear={Number(searchYear)} // 시작 연도 설정 + yearReadOnly={true} + enableMonth={['1월', '2월']} />

~

diff --git a/apps/fo/app/pages/underWaterInput/page.tsx b/apps/fo/app/pages/underWaterInput/page.tsx index d57c894dd..8debdb15e 100644 --- a/apps/fo/app/pages/underWaterInput/page.tsx +++ b/apps/fo/app/pages/underWaterInput/page.tsx @@ -6,6 +6,7 @@ import ListDiv from "@common/business_components/ui/list_div"; import { useCallback, useEffect, useRef, useState } from "react"; import UnderWaterInputModal from "./modal/page"; import type { UnderWaterProps } from "@/app/store/underWaterInput/types"; +import LoadingOverlay from "@common/business_components/ui/loadingBar"; export default function UnderWaterInput() { const {Common @@ -46,6 +47,7 @@ export default function UnderWaterInput() { underWaterList, underWaterCount, excelList, + isLoading, } = UnderWater; const ref = useRef({ @@ -82,8 +84,7 @@ export default function UnderWaterInput() { // 시설상태 const [operationValue, setOperationValue] = useState("0"); // 조회기간 - //const [searchYear, setSearchYear] = useState(selectSearchYear[0]?.val || "0"); - const [searchYear, setSearchYear] = useState("2023"); + const [searchYear, setSearchYear] = useState(selectSearchYear[0]?.val || "0"); /** * 페이지 함수 @@ -128,7 +129,7 @@ export default function UnderWaterInput() { initializeCommonData(); searchUnderWaterList(1, 10, selectSearchYear[0]?.val || "0"); } - }, [isInit, initializeCommonData, searchUnderWaterList, selectSearchYear]); + }, [isInit, initializeCommonData, searchUnderWaterList]); useEffect(() => { if (excelList && excelList.length > 0) { @@ -215,6 +216,7 @@ export default function UnderWaterInput() { isAdmin={false} /> +
index !== undefined && cellClick(index)} headName={"지하수유입량 추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} /> diff --git a/apps/fo/app/store/common/index.tsx b/apps/fo/app/store/common/index.tsx index 3e15e2162..b68fd9aea 100644 --- a/apps/fo/app/store/common/index.tsx +++ b/apps/fo/app/store/common/index.tsx @@ -2,7 +2,7 @@ * 보편적으로 쓰는 store 공간 ====================================**/ -import { getFetch } from "@/app/components/api"; +import { getFetch, getFetchAreaList } from "@/app/components/api"; /** * STORE - TYPE @@ -205,6 +205,28 @@ const selectMiddleRegionData: SelectDataType[] = [ * STORE - API */ +// 처리시설 계획정보 호출 (알에스원) +export const planInfoUrl = 'https://apigateway.apps.rsonesoft.com/dc-service/api/v1/nowDmgMtncGnsvy'; + +export const fetchPlanInfo = async (targetYear : string | undefined, ctpvNm : string | undefined, sggNm : string | undefined, fcltyCd : string | undefined) => { + try { + const baseUrl = planInfoUrl; + const queryParams = new URLSearchParams(); + if (ctpvNm && ctpvNm !== '전체') queryParams.append('ctpvNm', ctpvNm); + if (sggNm && sggNm !== '전체') queryParams.append('sggNm', sggNm); + if (targetYear) queryParams.append('targetYear',targetYear); + if (fcltyCd) queryParams.append('swtrmtFcltCd', fcltyCd); + const queryString = queryParams.toString(); + const url = queryString ? `${baseUrl}?${queryString}` : baseUrl; + const res = await getFetchAreaList(url); + return res; + } catch (error) { + console.error('처리시설 계획정보를 가져오는데 실패했습니다:', error); + return []; + } +} + + // 시도 API 호출 함수 추가 const fetchSidoData = async (): Promise => { try { diff --git a/apps/fo/app/store/dashboard/index.tsx b/apps/fo/app/store/dashboard/index.tsx index c0720b9fa..b23006c10 100644 --- a/apps/fo/app/store/dashboard/index.tsx +++ b/apps/fo/app/store/dashboard/index.tsx @@ -2,9 +2,11 @@ * Store - 타입 */ -import { getFetch, getFetchAreaList } from "@/app/components/api"; +import { getFetch } from "@/app/components/api"; import DataForm from "@/app/components/common/DataForm"; +import { fetchPlanInfo } from "../common"; import type { FacilityWaterQltyProps } from "../facilityWaterQlty"; +import { calRainEffectDay, type ApiResponse, type FlowDataItem } from "../underWaterInput"; // selectBox export type SelectDataType = { @@ -111,13 +113,13 @@ export interface RainManageListProps { sggNm?: string, addr?: string, fctCpc?: number, - inflAssctAftWqltBod: number | '', - inflAssctAftWqltToc: number | '', - inflAssctAftWqltSs: number | '', - inflAssctAftWqltTn: number | '', - inflAssctAftWqltTp: number | '', + inflAssctBfrWqltBod: number | '', + inflAssctBfrWqltToc: number | '', + inflAssctBfrWqltSs: number | '', + inflAssctBfrWqltTn: number | '', + inflAssctBfrWqltTp: number | '', efflWqltBod: number | '', - efflWqltCod: number | '', + efflWqltToc: number | '', efflWqltSs: number | '', efflWqltTn: number | '', efflWqltTp: number | '', @@ -143,6 +145,7 @@ export interface RainManageListProps { dsInflWqltTn: number | '', dsInflWqltTp: number | '', extnsSeqno?: number | '', + rainEffectDay?: number | '', } export interface RainManageExcelType { @@ -364,14 +367,14 @@ const upHeadListRainManage : TableUpperProps[] = [ { id: "dsInflWqltTn", title: "T-N", row:1 }, { id: "dsInflWqltTp", title: "T-P", row:1 }, { id: "C", title: "유입수질(㎎/L)", row:0, colSpan:5 }, - { id: "inflAssctAftWqltBod", title: "BOD", row:1 }, - { id: "inflAssctAftWqltToc", title: "TOC\n(COD)", row:1 }, - { id: "inflAssctAftWqltSs", title: "SS", row:1 }, - { id: "inflAssctAftWqltTn", title: "T-N", row:1 }, - { id: "inflAssctAftWqltTp", title: "T-P", row:1 }, + { id: "inflAssctBfrWqltBod", title: "BOD", row:1 }, + { id: "inflAssctBfrWqltToc", title: "TOC\n(COD)", row:1 }, + { id: "inflAssctBfrWqltSs", title: "SS", row:1 }, + { id: "inflAssctBfrWqltTn", title: "T-N", row:1 }, + { id: "inflAssctBfrWqltTp", title: "T-P", row:1 }, { id: "D", title: "방류수질(㎎/L)", row:0, colSpan:5 }, { id: "efflWqltBod", title: "BOD", row:1 }, - { id: "efflWqltCod", title: "TOC\n(COD)", row:1 }, + { id: "efflWqltToc", title: "TOC\n(COD)", row:1 }, { id: "efflWqltSs", title: "SS", row:1 }, { id: "efflWqltTn", title: "T-N", row:1 }, { id: "efflWqltTp", title: "T-P", row:1 }, @@ -687,20 +690,20 @@ const drainageEquipmentList : DrainageEquipmentListProps[] = [ * Store - api (데이터 호출) ====================================*/ /* 시설정보 및 운영현황 - 계획 */ -const fetchFacilityPlan = async (targetYear : string | undefined, fcltyCd : string | undefined) => { +const fetchFacilityPlan = async (targetYear : string | undefined, fcltyCd : string | undefined, set : (fn: (state: DashBoardType) => DashBoardType) => void) => { try { - targetYear = targetYear ? targetYear : "2023"; - const baseUrl = 'https://apigateway.rsonesoft.com/dc-service/api/v1/nowDmgMtncGnsvy'; - const queryParams = new URLSearchParams(); - - if (fcltyCd) queryParams.append('swtrmtFcltCd', fcltyCd); - //if (targetYear) queryParams.append('targetYear',targetYear); - const queryString = queryParams.toString(); - const url = queryString ? `${baseUrl}?${queryString}` : baseUrl; - const res = await getFetchAreaList(url); - return res + const res = await fetchPlanInfo(undefined, undefined, undefined, fcltyCd); + return res; } catch (error) { console.error('시설계획정보를 가져오는데 실패했습니다:', error); + set((state) => ({ + ...state, + PlanFclty : { + ...state.PlanFclty, + isLoadingPlanFclty : false, + isLoadingOperationStatus : false + } + })); return {data: [], count: 0}; } }; @@ -729,20 +732,6 @@ const fetchMainGraph = async (searchYear: string|undefined, fcltyCd: string|unde } } -// 배수설비 정비현황 -const fetchDrainageEquipment = async (searchYear: string|undefined, fcltyCd: string|undefined) => { - try{ - /* const url = '/fclt/qlty/hist/' + (searchYear?searchYear:'2024') + '/' + (fcltyCd?fcltyCd:'11680PB001R'); - const res = await getFetch('fo', url); - return { data: res.data, count: res.count } */ - console.log(searchYear, fcltyCd); - return { data : drainageEquipmentList, count : drainageEquipmentList.length } - } catch (error) { - console.error('배수설비 정비현황 데이터를 가져오는데 실패했습니다:', error); - return { data: [], count: 0 }; - } -} - /**==================================== * Store - action ====================================*/ @@ -756,8 +745,6 @@ export type DashBoardActions = { searchMainGraph(searchYear: string, fcltyCd: string): Promise; /**강우일 운영현황 */ searchRainManage(searchYear: string, fcltyCd: string, isExcel: boolean): Promise; - /**배수설비 정비현황 */ - searchDrainageEquipment(searchYear: string, fcltyCd: string, isExcel: boolean): Promise; } export type DashBoardType = { @@ -777,12 +764,17 @@ export type DashBoardType = { planYearList : string[]; upHeadListPlanFclty : TableUpperProps[]; planFcltyList : planFcltyListProps[]; + waterUsage1 : number | '', + waterUsage2 : number | '', + waterUsage3 : number | '', + isLoadingPlanFclty : boolean; }, OperationStatus : { isInit : boolean; upHeadListOperationStatus : TableUpperProps[]; operationalStatusList : OperationalStatusListProps[]; + isLoadingOperationStatus : boolean; } MainGraph : { @@ -796,6 +788,7 @@ export type DashBoardType = { chart_efflTn : lineChartDataProps[]; chart_inflBod : lineChartDataProps[]; chart_efflBod : lineChartDataProps[]; + isLoadingMainGraph : boolean; }, RainManage : { @@ -803,6 +796,7 @@ export type DashBoardType = { upHeadListRainManage : TableUpperProps[]; rainManageList : RainManageListProps[]; excelList : RainManageExcelType[]; + isLoadingRainManage : boolean; }, DrainageEquipment : { @@ -831,13 +825,18 @@ export const dashBoardInitState:DashBoardType = { isInit : true, planYearList : planYearList, upHeadListPlanFclty : upHeadListPlanFclty, - planFcltyList : planFcltyList + planFcltyList : planFcltyList, + waterUsage1 : 0, + waterUsage2 : 0, + waterUsage3 : 0, + isLoadingPlanFclty : false, }, OperationStatus : { isInit : false, upHeadListOperationStatus : upHeadListOperationStatus, - operationalStatusList : operationalStatusList + operationalStatusList : operationalStatusList, + isLoadingOperationStatus : false, }, MainGraph : { @@ -850,14 +849,16 @@ export const dashBoardInitState:DashBoardType = { chart_inflTn : chart_inflTn, chart_efflTn : chart_efflTn, chart_inflBod : chart_inflBod, - chart_efflBod : chart_efflBod + chart_efflBod : chart_efflBod, + isLoadingMainGraph : false, }, RainManage : { isInit : false, upHeadListRainManage : upHeadListRainManage, rainManageList : rainManageList, - excelList : [] + excelList : [], + isLoadingRainManage : false, }, DrainageEquipment : { @@ -926,18 +927,106 @@ const changeValue=(operationalStatus, data, keyTxt = 'INFL_AMNT')=>{ const calcValue = (operationalStatus, data, keyTxt='INFL_ASSCT_BFR_WQLT_TP') => { // 연간 - operationalStatus.yearAvg = data.yearData ? Number(Math.round(data.yearData['AVG_'+keyTxt] * 1000) / 1000).toFixed(3).toString() : ''; - operationalStatus.yearMax = data.yearData ? Number(Math.round(data.yearData.MAX_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : ''; - operationalStatus.yearMin = data.yearData ? Number(Math.round(data.yearData.MIN_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : ''; + operationalStatus.yearAvg = data.yearData && data.yearData['AVG_'+keyTxt] ? Number(Math.round(data.yearData['AVG_'+keyTxt] * 1000) / 1000).toFixed(3).toString() : ''; + operationalStatus.yearMax = data.yearData && data.yearData['MAX_'+keyTxt] ? Number(Math.round(data.yearData['MAX_'+keyTxt] * 1000) / 1000).toFixed(3).toString() : ''; + operationalStatus.yearMin = data.yearData && data.yearData['MIN_'+keyTxt] ? Number(Math.round(data.yearData['MIN_'+keyTxt] * 1000) / 1000).toFixed(3).toString() : ''; // 여름 - operationalStatus.summerAll = data.summer ? Number(Math.round(data.summer.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : ''; - operationalStatus.summerThree = data.summerRainy ? Number(Math.round(data.summerRainy.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : ''; - operationalStatus.summerRain = data.summerSunny ? Number(Math.round(data.summerSunny.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : ''; + operationalStatus.summerAll = data.summer && data.summer['AVG_'+keyTxt] ? Number(Math.round(data.summer['AVG_'+keyTxt] * 0.8 * 1000) / 1000).toFixed(3).toString() : ''; + operationalStatus.summerThree = data.summerRainy && data.summerRainy['AVG_'+keyTxt] ? Number(Math.round(data.summerRainy['AVG_'+keyTxt] * 0.82 * 1000) / 1000).toFixed(3).toString() : ''; + operationalStatus.summerRain = data.summerSunny && data.summerSunny['AVG_'+keyTxt] ? Number(Math.round(data.summerSunny['AVG_'+keyTxt] * 0.74 * 1000) / 1000).toFixed(3).toString() : ''; // 겨울 - operationalStatus.winterAll = data.winter ? Number(Math.round(data.winter.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : ''; - operationalStatus.winterSunnyMin = data.winterSunny ? Number(Math.round(data.winterSunny.MIN_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : ''; - operationalStatus.winterSunnyAvg = data.winterSunny ? Number(Math.round(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : ''; - operationalStatus.winterSunnyMax = data.winterSunny ? Number(Math.round(data.winterSunny.MAX_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : ''; + operationalStatus.winterAll = data.winter && data.winter['AVG_'+keyTxt] ? Number(Math.round(data.winter['AVG_'+keyTxt] * 1.16*1000) / 1000).toFixed(3).toString() : ''; + operationalStatus.winterSunnyMin = data.winterSunny && data.winterSunny['MIN_'+keyTxt] ? Number(Math.round(data.winterSunny['MIN_'+keyTxt] * 1.2 * 1000) / 1000).toFixed(3).toString() : ''; + operationalStatus.winterSunnyAvg = data.winterSunny && data.winterSunny['AVG_'+keyTxt] ? Number(Math.round(data.winterSunny['AVG_'+keyTxt] * 1.25 *1000) / 1000).toFixed(3).toString() : ''; + operationalStatus.winterSunnyMax = data.winterSunny && data.winterSunny['MAX_'+keyTxt] ? Number(Math.round(data.winterSunny['MAX_'+keyTxt] * 1.3 *1000) / 1000).toFixed(3).toString() : ''; +} + +type RtnFlowType = { + inflAmnt: string | number; + infoRnDay: string | number; + bscFctCd: string; + msrDt: string; +} + +type RtnFlowResponse = { + data: RtnFlowType[]; + count: number; +} + +const searchWaterUsage = async (searchYear: string, fcltyCd: string) => { + const waterUsage = [0, 0, 0]; + + for (let i = 0; i < 3; i++) { + try { + const res = await getFetch('fo', '/fclt/flow/' + fcltyCd + '/' + (Number(searchYear)-i)) as RtnFlowResponse; + let totWaterUsage = 0; + + if (res && res.data && Array.isArray(res.data)) { + res.data.forEach((item: RtnFlowType) => { + totWaterUsage += Number(item.inflAmnt); + }); + + if (res.count > 0) { + const avg = totWaterUsage / res.count; + waterUsage[i] = parseFloat((avg * 0.65).toFixed(2)); + } + } + } catch (error) { + console.error(`Error fetching water usage for year ${Number(searchYear)-i}:`, error); + waterUsage[i] = 0; + } + } + + return waterUsage; +} + +// 강우영향일 계산 및 강우량 덮어씌우기 +export const calRainEffectDayRainManage = (data: RainManageListProps[]) => { + + // 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일) + for(let idx = 0; idx < data.length; idx++) { + const item = data[idx]; + if(item){ + if(item.infoRnDay && Number(item.infoRnDay) >= 3) { + item.rainEffectDay = 1; + } else { + item.rainEffectDay = 0; + } + } + } + + // 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정 + for(let idx = 0; idx < data.length; idx++) { + if(data[idx]) { + // 하루 전이 강우영향일(3 이상)인 경우 + if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) { + data[idx]!.rainEffectDay = 1; + } + // 이틀 전이 강우영향일(3 이상)인 경우 + if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) { + data[idx]!.rainEffectDay = 1; + } + } + } + + for(let idx = 0; idx < data.length; idx++) { + if(data[idx] && data[idx]?.rainEffectDay === 1) { + if(idx > 1){ + if(data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) { + data[idx]!.infoRnDay = data[idx-1]!.infoRnDay; + } + } + if(idx > 2){ + if(data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) { + data[idx]!.infoRnDay = data[idx-2]!.infoRnDay; + } + } + } + } + + let rtnData : RainManageListProps[] = []; + rtnData = data.filter((item: RainManageListProps) => item.rainEffectDay === 1); + return rtnData; } export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) => void)=>DashBoardActions=(set: (fn: (state: DashBoardType) => DashBoardType) => void) => { @@ -954,7 +1043,28 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) /** 시설정보 및 운영현황 - 계획정보 */ searchPlanInfo : async (targetYear: string, fcltyCd: string) => { - const res = await fetchFacilityPlan(targetYear, fcltyCd); + set((state: DashBoardType) => ({ + ...state, + PlanFclty: { + ...state.PlanFclty, + isLoadingPlanFclty: true, + }, + })); + let waterUsage = [0, 0, 0]; + waterUsage = await searchWaterUsage(targetYear, fcltyCd); + + set((state: DashBoardType) => ({ + ...state, + PlanFclty : { + ...state.PlanFclty, + waterUsage1 : waterUsage[0] || 0, + waterUsage2 : waterUsage[1] || 0, + waterUsage3 : waterUsage[2] || 0, + }, + })); + + const res = await fetchFacilityPlan(targetYear, fcltyCd, set); + let minDiff=9999999; let minIndex; res.forEach((el:any, idx) => { @@ -1004,21 +1114,31 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) // 임시시 dataFormSettingPlan(el); + console.log('planFcltyList', planFcltyList); + console.log('rtnPlanData', rtnPlanData); + set((state: DashBoardType) => ({ + ...state, + PlanFclty: { + ...state.PlanFclty, + planFcltyList: planFcltyList, + isLoadingPlanFclty: false, + }, + })); }); - - set((state: DashBoardType) => ({ - ...state, - PlanFclty : { - ...state.PlanFclty, - planFcltyList : planFcltyList - } - })); }, /** 시설정보 및 운영현황 - 운영실태 */ searchOperationStatus: async (isExcel: boolean, searchYear: string, fcltyCd: string) => { + set((state: DashBoardType) => ({ + ...state, + OperationStatus: { + ...state.OperationStatus, + isLoadingOperationStatus: true, + }, + })); const res = await fetchOperationStatus(searchYear, fcltyCd); const data = res.data; + if(data && operationalStatusList){ // 유량 - 유입 if (operationalStatusList?.[0]) { @@ -1050,10 +1170,56 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) operationalStatusList[0].winterSunnyMin = data.winterSunny === null ? '' : (data.winterSunny.MIN_INFL_AMNT ? data.winterSunny.MIN_INFL_AMNT : 0) + (data.winterSunny.MIN_SUM_FLOW ? data.winterSunny.MIN_SUM_FLOW : 0) + (data.winterSunny.MIN_TP_INFL_WQLT_TP ? data.winterSunny.MIN_TP_INFL_WQLT_TP : 0); operationalStatusList[0].winterSunnyAvg = data.winterSunny === null ? '' : (data.winterSunny.AVG_INFL_AMNT ? data.winterSunny.AVG_INFL_AMNT : 0) + (data.winterSunny.AVG_SUM_FLOW ? data.winterSunny.AVG_SUM_FLOW : 0) + (data.winterSunny.AVG_TP_INFL_WQLT_TP ? data.winterSunny.AVG_TP_INFL_WQLT_TP : 0); operationalStatusList[0].winterSunnyMax = data.winterSunny === null ? '' : (data.winterSunny.MAX_INFL_AMNT ? data.winterSunny.MAX_INFL_AMNT : 0) + (data.winterSunny.MAX_SUM_FLOW ? data.winterSunny.MAX_SUM_FLOW : 0) + (data.winterSunny.MAX_TP_INFL_WQLT_TP ? data.winterSunny.MAX_TP_INFL_WQLT_TP : 0); - // 지하수 - operationalStatusList[0].groundWaterAvg = data.yearData.AVG_INFL_AMNT === null ? '' : Number(data.yearData.AVG_INFL_AMNT) - (Number(data.yearData.AVG_INFL_AMNT)*0.65*0.8); - operationalStatusList[0].groundWaterSummer = data.summer.AVG_INFL_AMNT === null ? '' : Number(data.summer.AVG_INFL_AMNT) - (Number(data.summer.AVG_INFL_AMNT)*0.65*0.8); - operationalStatusList[0].groundWaterWinter = data.winter.AVG_INFL_AMNT === null ? '' : Number(data.winter.AVG_INFL_AMNT) - (Number(data.winter.AVG_INFL_AMNT)*0.65*0.8); + + // 연계처리수,지하수유입량 + const bscFctCd = fcltyCd; + const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as ApiResponse; + + const calData = calRainEffectDay(res2.data, 'SUNNY'); + let chungcunSumFlow = 0; + + let sumSummerChungcunDay = 0; + let sumSummerChungcunFlow = 0; + + let sumWinterChungcunDay = 0; + let sumWinterChungcunFlow = 0; + + /* let yearSumFlow = 0; + let summerSumFlow = 0; + let winterSumFlow = 0; */ + + calData.forEach((flowItem: FlowDataItem) => { + chungcunSumFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + //yearSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0; + + if(flowItem.msrDt.substring(4,6) ==='06' || flowItem.msrDt.substring(4,6) ==='07' || flowItem.msrDt.substring(4,6) ==='08'){ + sumSummerChungcunDay += 1; + sumSummerChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + //summerSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0; + }else if(flowItem.msrDt.substring(4,6) ==='01' || flowItem.msrDt.substring(4,6) ==='02'){ + sumWinterChungcunDay += 1; + sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + // winterSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0; + } + }); + + // 연계처리수 + /* const avgYearSumFlow = yearSumFlow / calData.length; + const avgSummerSumFlow = summerSumFlow / calData.length; + const avgWinterSumFlow = winterSumFlow / calData.length; */ + + // 지하수유입량 + const usage = chungcunSumFlow / calData.length; + const summerUsage = sumSummerChungcunFlow / sumSummerChungcunDay; + const winterUsage = sumWinterChungcunFlow / sumWinterChungcunDay; + + operationalStatusList[0].groundWaterAvg = Math.round((usage-(usage*0.65*0.8)) * 100) / 100; + operationalStatusList[0].groundWaterSummer = Math.round((summerUsage-(summerUsage*0.65*0.8)) * 100) / 100; + operationalStatusList[0].groundWaterWinter = Math.round((winterUsage-(winterUsage*0.65*0.8)) * 100) / 100; + + //operationalStatusList[0].groundWaterAvg = calData.length === 0 ? '' : Number(calData[0].inflAmnt) - (Number(calData[0].inflAmnt)*0.65*0.8); + //operationalStatusList[0].groundWaterSummer = calData.length === 0 ? '' : Number(calData[0].inflAmnt) - (Number(calData[0].inflAmnt)*0.65*0.8); + //operationalStatusList[0].groundWaterWinter = calData.length === 0 ? '' : Number(calData[0].inflAmnt) - (Number(calData[0].inflAmnt)*0.65*0.8); // 오염물질 // RDII 추정 = 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD)) @@ -1063,16 +1229,13 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) const summerLowRain = data.summerBod&&data.summerBod.INFO_RN_DAY&&data.summerBod.INFO_RN_DAY!='null'?Number(data.summerBod.INFO_RN_DAY):0; operationalStatusList[0].rdi = winterAvgBod===0?0:summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod); operationalStatusList[0].rdiRain = summerLowRain; - dataFormSetting(operationalStatusList[0]); } if(operationalStatusList[0] && operationalStatusList[7]){ - console.log(Number(operationalStatusList[0].groundWaterAvg)+' '+Number(data.yearData.AVG_INFL_AMNT)); - console.log(Number(operationalStatusList[0].groundWaterSummer)+' '+Number(data.summer.AVG_INFL_AMNT)); - console.log(Number(operationalStatusList[0].groundWaterWinter)+' '+Number(data.winter.AVG_INFL_AMNT)); - operationalStatusList[7].groundWaterAvg = Number(operationalStatusList[0].groundWaterAvg) / Number(data.yearData.AVG_INFL_AMNT) * 100; - operationalStatusList[7].groundWaterSummer = Number(operationalStatusList[0].groundWaterSummer) / Number(data.summer.AVG_INFL_AMNT) * 100; - operationalStatusList[7].groundWaterWinter = Number(operationalStatusList[0].groundWaterWinter) / Number(data.winter.AVG_INFL_AMNT) * 100; + operationalStatusList[7].groundWaterAvg = operationalStatusList[0].groundWaterAvg === null ? '' : data.yearData && data.yearData.AVG_INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].groundWaterAvg) / (data.yearData && data.yearData.AVG_INFL_AMNT ? Number(data.yearData.AVG_INFL_AMNT) : 0) * 100) * 10) / 10+'%'; + operationalStatusList[7].groundWaterSummer = operationalStatusList[0].groundWaterSummer === null ? '' : data.summer && data.summer.AVG_INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].groundWaterSummer) / (data.summer && data.summer.AVG_INFL_AMNT ? Number(data.summer.AVG_INFL_AMNT) : 0) * 100) * 10) / 10+'%'; + operationalStatusList[7].groundWaterWinter = operationalStatusList[0].groundWaterWinter === null ? '' : data.winter && data.winter.AVG_INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].groundWaterWinter) / (data.winter && data.winter.AVG_INFL_AMNT ? Number(data.winter.AVG_INFL_AMNT) : 0) * 100) * 10) / 10+'%'; + operationalStatusList[7].rdi = operationalStatusList[0].rdi === null ? '' : data.summerBod && data.summerBod.INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].rdi) / (data.summerBod&&data.summerBod.INFL_AMNT&&data.summerBod.INFL_AMNT!='null'?Number(data.summerBod.INFL_AMNT):0) * 100) * 10) / 10+'%'; /* operationalStatusList[7].groundWaterAvg = operationalStatusList[0].groundWaterAvg === null ? '' : Number(Number(operationalStatusList[0].groundWaterAvg) / Number(data.yearData.AVG_INFL_AMNT)) * 100; operationalStatusList[7].groundWaterSummer = operationalStatusList[0].groundWaterSummer === null ? '' : Number(Number(operationalStatusList[0].groundWaterSummer) / Number(data.summer.AVG_INFL_AMNT)) * 100; operationalStatusList[7].groundWaterWinter = operationalStatusList[0].groundWaterWinter === null ? '' : Number(Number(operationalStatusList[0].groundWaterWinter) / Number(data.winter.AVG_INFL_AMNT)) * 100;*/ @@ -1080,7 +1243,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) } for(let i=1; i DashBoardType) 시군구: item.sggNm, 주소: item.addr, 용량: item.fctCpc, - 유입BOD: item.inflAssctAftWqltBod, - 유입TN: item.inflAssctAftWqltTn, + 유입BOD: item.inflAssctBfrWqltBod, + 유입TN: item.inflAssctBfrWqltTn, 유입TP: item.inflAssctBfrWqltTp, 유출BOD: item.efflWqltBod, 유출TN: item.efflWqltTn, @@ -1127,12 +1290,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) OperationStatus: { ...state.OperationStatus, operationalStatusList: operationalStatusList, - operationalStatusCount: res.count - } + operationalStatusCount: res.count, + isLoadingOperationStatus : false, + }, })) }, searchMainGraph: async (searchYear: string, fcltyCd: string) => { + set((state: DashBoardType) => ({ + ...state, + MainGraph: { + ...state.MainGraph, + isLoadingMainGraph: true, + }, + })); const res = await fetchMainGraph(searchYear, fcltyCd); if(res == null || res.data == null || res.data.length === 0) { set((state: DashBoardType) => ({ @@ -1148,6 +1319,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) chart_efflTn: [], chart_inflBod: [], chart_efflBod: [], + isLoadingMainGraph : false, } })); return; @@ -1163,7 +1335,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) const chart_bodRain = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({ label: item.msrDt.substring(0, 4)+"-"+item.msrDt.substring(4, 6)+"-"+item.msrDt.substring(6, 8), barVal0: item.infoRnDay ?? 0, - lineVal0: item.inflAssctAftWqltBod ?? 0, + lineVal0: item.inflAssctBfrWqltBod ?? 0, })); const chart_inflTp = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({ @@ -1183,7 +1355,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) const chart_inflTn = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({ label: item.msrDt.substring(0, 4)+"-"+item.msrDt.substring(4, 6)+"-"+item.msrDt.substring(6, 8), - val : item.inflAssctAftWqltTn ?? 0 + val : item.inflAssctBfrWqltTn ?? 0 })); const chart_efflTn = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({ @@ -1193,7 +1365,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) const chart_inflBod = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({ label: item.msrDt.substring(0, 4)+"-"+item.msrDt.substring(4, 6)+"-"+item.msrDt.substring(6, 8), - val : item.inflAssctAftWqltBod ?? 0 + val : item.inflAssctBfrWqltBod ?? 0 })); const chart_efflBod = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({ @@ -1213,12 +1385,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) chart_inflTn: chart_inflTn, chart_efflTn: chart_efflTn, chart_inflBod: chart_inflBod, - chart_efflBod: chart_efflBod - } + chart_efflBod: chart_efflBod, + isLoadingMainGraph : false, + }, })) }, searchRainManage: async (searchYear: string, fcltyCd: string, isExcel : boolean) => { + set((state: DashBoardType) => ({ + ...state, + RainManage: { + ...state.RainManage, + isLoadingRainManage: true, + }, + })); const res = await fetchMainGraph(searchYear, fcltyCd); if(res == null || res.data.wqltObjs == null || res.data.wqltObjs.length === 0) { set((state: DashBoardType) => ({ @@ -1226,6 +1406,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) RainManage: { ...state.RainManage, rainManageList: [], + isLoadingRainManage : false, } })); return; @@ -1243,75 +1424,51 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) 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 inflAssctBfrWqltBodCnt = [0, 0, 0, 0, 0, 0, 0, 0]; + const inflAssctBfrWqltBod = [0, 0, 0, 0, 0, 0, 0, 0]; + const inflAssctBfrWqltTocCnt = [0, 0, 0, 0, 0, 0, 0, 0]; + const inflAssctBfrWqltToc = [0, 0, 0, 0, 0, 0, 0, 0]; + const inflAssctBfrWqltSsCnt = [0, 0, 0, 0, 0, 0, 0, 0]; + const inflAssctBfrWqltSs = [0, 0, 0, 0, 0, 0, 0, 0]; + const inflAssctBfrWqltTnCnt = [0, 0, 0, 0, 0, 0, 0, 0]; + const inflAssctBfrWqltTn = [0, 0, 0, 0, 0, 0, 0, 0]; + const inflAssctBfrWqltTpCnt = [0, 0, 0, 0, 0, 0, 0, 0]; + const inflAssctBfrWqltTp = [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 efflWqltTocCnt = [0, 0, 0, 0, 0, 0, 0, 0]; + const efflWqltToc = [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]; + + // 청천시 중 강우영향일인 날짜는 이전의 강우량을 대입해 리스트 수정 + + const rainEffectList = calRainEffectDayRainManage(res.data.wqltObjs); // Process the data and create rain management list - res.data.wqltObjs.forEach((item: RainManageListProps) => { - - // 강우일 - /*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); - 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); - }*/ + rainEffectList.forEach((item: RainManageListProps) => { 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); + inflAssctBfrWqltBodCnt[1] = Number(inflAssctBfrWqltBodCnt[1] || 0) + 1; + inflAssctBfrWqltBod[1] = Number(inflAssctBfrWqltBod[1] || 0) + Number(item.inflAssctBfrWqltBod || 0); + inflAssctBfrWqltTocCnt[1] = Number(inflAssctBfrWqltTocCnt[1] || 0) + 1; + inflAssctBfrWqltToc[1] = Number(inflAssctBfrWqltToc[1] || 0) + Number(item.inflAssctBfrWqltToc || 0); + inflAssctBfrWqltSsCnt[1] = Number(inflAssctBfrWqltSsCnt[1] || 0) + 1; + inflAssctBfrWqltSs[1] = Number(inflAssctBfrWqltSs[1] || 0) + Number(item.inflAssctBfrWqltSs || 0); + inflAssctBfrWqltTnCnt[1] = Number(inflAssctBfrWqltTnCnt[1] || 0) + 1; + inflAssctBfrWqltTn[1] = Number(inflAssctBfrWqltTn[1] || 0) + Number(item.inflAssctBfrWqltTn || 0); + inflAssctBfrWqltTpCnt[1] = Number(inflAssctBfrWqltTpCnt[1] || 0) + 1; + inflAssctBfrWqltTp[1] = Number(inflAssctBfrWqltTp[1] || 0) + Number(item.inflAssctBfrWqltTp || 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); + efflWqltTocCnt[1] = Number(efflWqltTocCnt[1] || 0) + 1; + efflWqltToc[1] = Number(efflWqltToc[1] || 0) + Number(item.efflWqltToc || 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; @@ -1323,20 +1480,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) inflAmtCnt[2] = Number(inflAmtCnt[2] || 0) + 1; inflAmnt[2] = Number(inflAmnt[2] || 0) + Number(item.inflAmnt || 0); fcltyCpct[2] = 0; - inflAssctAftWqltBodCnt[2] = Number(inflAssctAftWqltBodCnt[2] || 0) + 1; - inflAssctAftWqltBod[2] = Number(inflAssctAftWqltBod[2] || 0) + Number(item.inflAssctAftWqltBod || 0); - inflAssctAftWqltTocCnt[2] = Number(inflAssctAftWqltTocCnt[2] || 0) + 1; - inflAssctAftWqltToc[2] = Number(inflAssctAftWqltToc[2] || 0) + Number(item.inflAssctAftWqltToc || 0); - inflAssctAftWqltSsCnt[2] = Number(inflAssctAftWqltSsCnt[2] || 0) + 1; - inflAssctAftWqltSs[2] = Number(inflAssctAftWqltSs[2] || 0) + Number(item.inflAssctAftWqltSs || 0); - inflAssctAftWqltTnCnt[2] = Number(inflAssctAftWqltTnCnt[2] || 0) + 1; - inflAssctAftWqltTn[2] = Number(inflAssctAftWqltTn[2] || 0) + Number(item.inflAssctAftWqltTn || 0); - inflAssctAftWqltTpCnt[2] = Number(inflAssctAftWqltTpCnt[2] || 0) + 1; - inflAssctAftWqltTp[2] = Number(inflAssctAftWqltTp[2] || 0) + Number(item.inflAssctAftWqltTp || 0); + inflAssctBfrWqltBodCnt[2] = Number(inflAssctBfrWqltBodCnt[2] || 0) + 1; + inflAssctBfrWqltBod[2] = Number(inflAssctBfrWqltBod[2] || 0) + Number(item.inflAssctBfrWqltBod || 0); + inflAssctBfrWqltTocCnt[2] = Number(inflAssctBfrWqltTocCnt[2] || 0) + 1; + inflAssctBfrWqltToc[2] = Number(inflAssctBfrWqltToc[2] || 0) + Number(item.inflAssctBfrWqltToc || 0); + inflAssctBfrWqltSsCnt[2] = Number(inflAssctBfrWqltSsCnt[2] || 0) + 1; + inflAssctBfrWqltSs[2] = Number(inflAssctBfrWqltSs[2] || 0) + Number(item.inflAssctBfrWqltSs || 0); + inflAssctBfrWqltTnCnt[2] = Number(inflAssctBfrWqltTnCnt[2] || 0) + 1; + inflAssctBfrWqltTn[2] = Number(inflAssctBfrWqltTn[2] || 0) + Number(item.inflAssctBfrWqltTn || 0); + inflAssctBfrWqltTpCnt[2] = Number(inflAssctBfrWqltTpCnt[2] || 0) + 1; + inflAssctBfrWqltTp[2] = Number(inflAssctBfrWqltTp[2] || 0) + Number(item.inflAssctBfrWqltTp || 0); efflWqltBodCnt[2] = Number(efflWqltBodCnt[2] || 0) + 1; 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); + efflWqltTocCnt[2] = Number(efflWqltTocCnt[2] || 0) + 1; + efflWqltToc[2] = Number(efflWqltToc[2] || 0) + Number(item.efflWqltToc || 0); efflWqltSsCnt[2] = Number(efflWqltSsCnt[2] || 0) + 1; efflWqltSs[2] = Number(efflWqltSs[2] || 0) + Number(item.efflWqltSs || 0); efflWqltTnCnt[2] = Number(efflWqltTnCnt[2] || 0) + 1; @@ -1348,20 +1505,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) inflAmtCnt[3] = Number(inflAmtCnt[3] || 0) + 1; inflAmnt[3] = Number(inflAmnt[3] || 0) + Number(item.inflAmnt || 0); fcltyCpct[3] = 0; - inflAssctAftWqltBodCnt[3] = Number(inflAssctAftWqltBodCnt[3] || 0) + 1; - inflAssctAftWqltBod[3] = Number(inflAssctAftWqltBod[3] || 0) + Number(item.inflAssctAftWqltBod || 0); - inflAssctAftWqltTocCnt[3] = Number(inflAssctAftWqltTocCnt[3] || 0) + 1; - inflAssctAftWqltToc[3] = Number(inflAssctAftWqltToc[3] || 0) + Number(item.inflAssctAftWqltToc || 0); - inflAssctAftWqltSsCnt[3] = Number(inflAssctAftWqltSsCnt[3] || 0) + 1; - inflAssctAftWqltSs[3] = Number(inflAssctAftWqltSs[3] || 0) + Number(item.inflAssctAftWqltSs || 0); - inflAssctAftWqltTnCnt[3] = Number(inflAssctAftWqltTnCnt[3] || 0) + 1; - inflAssctAftWqltTn[3] = Number(inflAssctAftWqltTn[3] || 0) + Number(item.inflAssctAftWqltTn || 0); - inflAssctAftWqltTpCnt[3] = Number(inflAssctAftWqltTpCnt[3] || 0) + 1; - inflAssctAftWqltTp[3] = Number(inflAssctAftWqltTp[3] || 0) + Number(item.inflAssctAftWqltTp || 0); + inflAssctBfrWqltBodCnt[3] = Number(inflAssctBfrWqltBodCnt[3] || 0) + 1; + inflAssctBfrWqltBod[3] = Number(inflAssctBfrWqltBod[3] || 0) + Number(item.inflAssctBfrWqltBod || 0); + inflAssctBfrWqltTocCnt[3] = Number(inflAssctBfrWqltTocCnt[3] || 0) + 1; + inflAssctBfrWqltToc[3] = Number(inflAssctBfrWqltToc[3] || 0) + Number(item.inflAssctBfrWqltToc || 0); + inflAssctBfrWqltSsCnt[3] = Number(inflAssctBfrWqltSsCnt[3] || 0) + 1; + inflAssctBfrWqltSs[3] = Number(inflAssctBfrWqltSs[3] || 0) + Number(item.inflAssctBfrWqltSs || 0); + inflAssctBfrWqltTnCnt[3] = Number(inflAssctBfrWqltTnCnt[3] || 0) + 1; + inflAssctBfrWqltTn[3] = Number(inflAssctBfrWqltTn[3] || 0) + Number(item.inflAssctBfrWqltTn || 0); + inflAssctBfrWqltTpCnt[3] = Number(inflAssctBfrWqltTpCnt[3] || 0) + 1; + inflAssctBfrWqltTp[3] = Number(inflAssctBfrWqltTp[3] || 0) + Number(item.inflAssctBfrWqltTp || 0); efflWqltBodCnt[3] = Number(efflWqltBodCnt[3] || 0) + 1; efflWqltBod[3] = Number(efflWqltBod[3] || 0) + Number(item.efflWqltBod || 0); - efflWqltCodCnt[3] = Number(efflWqltCodCnt[3] || 0) + 1; - efflWqltCod[3] = Number(efflWqltCod[3] || 0) + Number(item.efflWqltCod || 0); + efflWqltTocCnt[3] = Number(efflWqltTocCnt[3] || 0) + 1; + efflWqltToc[3] = Number(efflWqltToc[3] || 0) + Number(item.efflWqltToc || 0); efflWqltSsCnt[3] = Number(efflWqltSsCnt[3] || 0) + 1; efflWqltSs[3] = Number(efflWqltSs[3] || 0) + Number(item.efflWqltSs || 0); efflWqltTnCnt[3] = Number(efflWqltTnCnt[3] || 0) + 1; @@ -1373,20 +1530,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) inflAmtCnt[4] = Number(inflAmtCnt[4] || 0) + 1; inflAmnt[4] = Number(inflAmnt[4] || 0) + Number(item.inflAmnt || 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; - inflAssctAftWqltToc[4] = Number(inflAssctAftWqltToc[4] || 0) + Number(item.inflAssctAftWqltToc || 0); - 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[5] || 0) + Number(item.inflAssctAftWqltTn || 0); - inflAssctAftWqltTpCnt[4] = Number(inflAssctAftWqltTpCnt[4] || 0) + 1; - inflAssctAftWqltTp[4] = Number(inflAssctAftWqltTp[4] || 0) + Number(item.inflAssctAftWqltTp || 0); + inflAssctBfrWqltBodCnt[4] = Number(inflAssctBfrWqltBodCnt[4] || 0) + 1; + inflAssctBfrWqltBod[4] = Number(inflAssctBfrWqltBod[4] || 0) + Number(item.inflAssctBfrWqltBod || 0); + inflAssctBfrWqltTocCnt[4] = Number(inflAssctBfrWqltTocCnt[4] || 0) + 1; + inflAssctBfrWqltToc[4] = Number(inflAssctBfrWqltToc[4] || 0) + Number(item.inflAssctBfrWqltToc || 0); + inflAssctBfrWqltSsCnt[4] = Number(inflAssctBfrWqltSsCnt[4] || 0) + 1; + inflAssctBfrWqltSs[4] = Number(inflAssctBfrWqltSs[4] || 0) + Number(item.inflAssctBfrWqltSs || 0); + inflAssctBfrWqltTnCnt[4] = Number(inflAssctBfrWqltTnCnt[4] || 0) + 1; + inflAssctBfrWqltTn[4] = Number(inflAssctBfrWqltTn[5] || 0) + Number(item.inflAssctBfrWqltTn || 0); + inflAssctBfrWqltTpCnt[4] = Number(inflAssctBfrWqltTpCnt[4] || 0) + 1; + inflAssctBfrWqltTp[4] = Number(inflAssctBfrWqltTp[4] || 0) + Number(item.inflAssctBfrWqltTp || 0); efflWqltBodCnt[4] = Number(efflWqltBodCnt[4] || 0) + 1; efflWqltBod[4] = Number(efflWqltBod[4] || 0) + Number(item.efflWqltBod || 0); - efflWqltCodCnt[4] = Number(efflWqltCodCnt[4] || 0) + 1; - efflWqltCod[4] = Number(efflWqltCod[4] || 0) + Number(item.efflWqltCod || 0); + efflWqltTocCnt[4] = Number(efflWqltTocCnt[4] || 0) + 1; + efflWqltToc[4] = Number(efflWqltToc[4] || 0) + Number(item.efflWqltToc || 0); efflWqltSsCnt[4] = Number(efflWqltSsCnt[4] || 0) + 1; efflWqltSs[4] = Number(efflWqltSs[4] || 0) + Number(item.efflWqltSs || 0); efflWqltTnCnt[4] = Number(efflWqltTnCnt[5] || 0) + 1; @@ -1398,20 +1555,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) inflAmtCnt[5] = Number(inflAmtCnt[5] || 0) + 1; inflAmnt[5] = Number(inflAmnt[5] || 0) + Number(item.inflAmnt || 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; - inflAssctAftWqltToc[5] = Number(inflAssctAftWqltToc[5] || 0) + Number(item.inflAssctAftWqltToc || 0); - inflAssctAftWqltSsCnt[5] = Number(inflAssctAftWqltSsCnt[5] || 0) + 1; - inflAssctAftWqltSs[5] = Number(inflAssctAftWqltSs[5] || 0) + Number(item.inflAssctAftWqltSs || 0); - inflAssctAftWqltTnCnt[5] = Number(inflAssctAftWqltTnCnt[5] || 0) + 1; - inflAssctAftWqltTn[5] = Number(inflAssctAftWqltTn[5] || 0) + Number(item.inflAssctAftWqltTn || 0); - inflAssctAftWqltTpCnt[5] = Number(inflAssctAftWqltTpCnt[5] || 0) + 1; - inflAssctAftWqltTp[5] = Number(inflAssctAftWqltTp[5] || 0) + Number(item.inflAssctAftWqltTp || 0); + inflAssctBfrWqltBodCnt[5] = Number(inflAssctBfrWqltBodCnt[5] || 0) + 1; + inflAssctBfrWqltBod[5] = Number(inflAssctBfrWqltBod[5] || 0) + Number(item.inflAssctBfrWqltBod || 0); + inflAssctBfrWqltTocCnt[5] = Number(inflAssctBfrWqltTocCnt[5] || 0) + 1; + inflAssctBfrWqltToc[5] = Number(inflAssctBfrWqltToc[5] || 0) + Number(item.inflAssctBfrWqltToc || 0); + inflAssctBfrWqltSsCnt[5] = Number(inflAssctBfrWqltSsCnt[5] || 0) + 1; + inflAssctBfrWqltSs[5] = Number(inflAssctBfrWqltSs[5] || 0) + Number(item.inflAssctBfrWqltSs || 0); + inflAssctBfrWqltTnCnt[5] = Number(inflAssctBfrWqltTnCnt[5] || 0) + 1; + inflAssctBfrWqltTn[5] = Number(inflAssctBfrWqltTn[5] || 0) + Number(item.inflAssctBfrWqltTn || 0); + inflAssctBfrWqltTpCnt[5] = Number(inflAssctBfrWqltTpCnt[5] || 0) + 1; + inflAssctBfrWqltTp[5] = Number(inflAssctBfrWqltTp[5] || 0) + Number(item.inflAssctBfrWqltTp || 0); efflWqltBodCnt[5] = Number(efflWqltBodCnt[5] || 0) + 1; efflWqltBod[5] = Number(efflWqltBod[5] || 0) + Number(item.efflWqltBod || 0); - efflWqltCodCnt[5] = Number(efflWqltCodCnt[5] || 0) + 1; - efflWqltCod[5] = Number(efflWqltCod[5] || 0) + Number(item.efflWqltCod || 0); + efflWqltTocCnt[5] = Number(efflWqltTocCnt[5] || 0) + 1; + efflWqltToc[5] = Number(efflWqltToc[5] || 0) + Number(item.efflWqltToc || 0); efflWqltSsCnt[5] = Number(efflWqltSsCnt[5] || 0) + 1; efflWqltSs[5] = Number(efflWqltSs[5] || 0) + Number(item.efflWqltSs || 0); efflWqltTnCnt[5] = Number(efflWqltTnCnt[5] || 0) + 1; @@ -1423,20 +1580,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) inflAmtCnt[6] = Number(inflAmtCnt[6] || 0) + 1; inflAmnt[6] = Number(inflAmnt[6] || 0) + Number(item.inflAmnt || 0); fcltyCpct[6] = 0; - inflAssctAftWqltBodCnt[6] = Number(inflAssctAftWqltBodCnt[6] || 0) + 1; - inflAssctAftWqltBod[6] = Number(inflAssctAftWqltBod[6] || 0) + Number(item.inflAssctAftWqltBod || 0); - inflAssctAftWqltTocCnt[6] = Number(inflAssctAftWqltTocCnt[6] || 0) + 1; - inflAssctAftWqltToc[6] = Number(inflAssctAftWqltToc[6] || 0) + Number(item.inflAssctAftWqltToc || 0); - inflAssctAftWqltSsCnt[6] = Number(inflAssctAftWqltSsCnt[6] || 0) + 1; - inflAssctAftWqltSs[6] = Number(inflAssctAftWqltSs[6] || 0) + Number(item.inflAssctAftWqltSs || 0); - inflAssctAftWqltTnCnt[6] = Number(inflAssctAftWqltTnCnt[6] || 0) + 1; - inflAssctAftWqltTn[6] = Number(inflAssctAftWqltTn[6] || 0) + Number(item.inflAssctAftWqltTn || 0); - inflAssctAftWqltTpCnt[6] = Number(inflAssctAftWqltTpCnt[6] || 0) + 1; - inflAssctAftWqltTp[6] = Number(inflAssctAftWqltTp[6] || 0) + Number(item.inflAssctAftWqltTp || 0); + inflAssctBfrWqltBodCnt[6] = Number(inflAssctBfrWqltBodCnt[6] || 0) + 1; + inflAssctBfrWqltBod[6] = Number(inflAssctBfrWqltBod[6] || 0) + Number(item.inflAssctBfrWqltBod || 0); + inflAssctBfrWqltTocCnt[6] = Number(inflAssctBfrWqltTocCnt[6] || 0) + 1; + inflAssctBfrWqltToc[6] = Number(inflAssctBfrWqltToc[6] || 0) + Number(item.inflAssctBfrWqltToc || 0); + inflAssctBfrWqltSsCnt[6] = Number(inflAssctBfrWqltSsCnt[6] || 0) + 1; + inflAssctBfrWqltSs[6] = Number(inflAssctBfrWqltSs[6] || 0) + Number(item.inflAssctBfrWqltSs || 0); + inflAssctBfrWqltTnCnt[6] = Number(inflAssctBfrWqltTnCnt[6] || 0) + 1; + inflAssctBfrWqltTn[6] = Number(inflAssctBfrWqltTn[6] || 0) + Number(item.inflAssctBfrWqltTn || 0); + inflAssctBfrWqltTpCnt[6] = Number(inflAssctBfrWqltTpCnt[6] || 0) + 1; + inflAssctBfrWqltTp[6] = Number(inflAssctBfrWqltTp[6] || 0) + Number(item.inflAssctBfrWqltTp || 0); efflWqltBodCnt[6] = Number(efflWqltBodCnt[6] || 0) + 1; efflWqltBod[6] = Number(efflWqltBod[6] || 0) + Number(item.efflWqltBod || 0); - efflWqltCodCnt[6] = Number(efflWqltCodCnt[6] || 0) + 1; - efflWqltCod[6] = Number(efflWqltCod[6] || 0) + Number(item.efflWqltCod || 0); + efflWqltTocCnt[6] = Number(efflWqltTocCnt[6] || 0) + 1; + efflWqltToc[6] = Number(efflWqltToc[6] || 0) + Number(item.efflWqltToc || 0); efflWqltSsCnt[6] = Number(efflWqltSsCnt[6] || 0) + 1; efflWqltSs[6] = Number(efflWqltSs[6] || 0) + Number(item.efflWqltSs || 0); efflWqltTnCnt[6] = Number(efflWqltTnCnt[6] || 0) + 1; @@ -1448,20 +1605,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) inflAmtCnt[7] = Number(inflAmtCnt[7] || 0) + 1; inflAmnt[7] = Number(inflAmnt[7] || 0) + Number(item.inflAmnt || 0); fcltyCpct[7] = 0; - inflAssctAftWqltBodCnt[7] = Number(inflAssctAftWqltBodCnt[7] || 0) + 1; - inflAssctAftWqltBod[7] = Number(inflAssctAftWqltBod[7] || 0) + Number(item.inflAssctAftWqltBod || 0); - inflAssctAftWqltTocCnt[7] = Number(inflAssctAftWqltTocCnt[7] || 0) + 1; - inflAssctAftWqltToc[7] = Number(inflAssctAftWqltToc[7] || 0) + Number(item.inflAssctAftWqltToc || 0); - inflAssctAftWqltSsCnt[7] = Number(inflAssctAftWqltSsCnt[7] || 0) + 1; - inflAssctAftWqltSs[7] = Number(inflAssctAftWqltSs[7] || 0) + Number(item.inflAssctAftWqltSs || 0); - inflAssctAftWqltTnCnt[7] = Number(inflAssctAftWqltTnCnt[7] || 0) + 1; - inflAssctAftWqltTn[7] = Number(inflAssctAftWqltTn[7] || 0) + Number(item.inflAssctAftWqltTn || 0); - inflAssctAftWqltTpCnt[7] = Number(inflAssctAftWqltTpCnt[7] || 0) + 1; - inflAssctAftWqltTp[7] = Number(inflAssctAftWqltTp[7] || 0) + Number(item.inflAssctAftWqltTp || 0); + inflAssctBfrWqltBodCnt[7] = Number(inflAssctBfrWqltBodCnt[7] || 0) + 1; + inflAssctBfrWqltBod[7] = Number(inflAssctBfrWqltBod[7] || 0) + Number(item.inflAssctBfrWqltBod || 0); + inflAssctBfrWqltTocCnt[7] = Number(inflAssctBfrWqltTocCnt[7] || 0) + 1; + inflAssctBfrWqltToc[7] = Number(inflAssctBfrWqltToc[7] || 0) + Number(item.inflAssctBfrWqltToc || 0); + inflAssctBfrWqltSsCnt[7] = Number(inflAssctBfrWqltSsCnt[7] || 0) + 1; + inflAssctBfrWqltSs[7] = Number(inflAssctBfrWqltSs[7] || 0) + Number(item.inflAssctBfrWqltSs || 0); + inflAssctBfrWqltTnCnt[7] = Number(inflAssctBfrWqltTnCnt[7] || 0) + 1; + inflAssctBfrWqltTn[7] = Number(inflAssctBfrWqltTn[7] || 0) + Number(item.inflAssctBfrWqltTn || 0); + inflAssctBfrWqltTpCnt[7] = Number(inflAssctBfrWqltTpCnt[7] || 0) + 1; + inflAssctBfrWqltTp[7] = Number(inflAssctBfrWqltTp[7] || 0) + Number(item.inflAssctBfrWqltTp || 0); efflWqltBodCnt[7] = Number(efflWqltBodCnt[7] || 0) + 1; efflWqltBod[7] = Number(efflWqltBod[7] || 0) + Number(item.efflWqltBod || 0); - efflWqltCodCnt[7] = Number(efflWqltCodCnt[7] || 0) + 1; - efflWqltCod[7] = Number(efflWqltCod[7] || 0) + Number(item.efflWqltCod || 0); + efflWqltTocCnt[7] = Number(efflWqltTocCnt[7] || 0) + 1; + efflWqltToc[7] = Number(efflWqltToc[7] || 0) + Number(item.efflWqltToc || 0); efflWqltSsCnt[7] = Number(efflWqltSsCnt[7] || 0) + 1; efflWqltSs[7] = Number(efflWqltSs[7] || 0) + Number(item.efflWqltSs || 0); efflWqltTnCnt[7] = Number(efflWqltTnCnt[7] || 0) + 1; @@ -1539,13 +1696,13 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) for(let idx=0; idx DashBoardType) inflAmnt[0] = calculateAverage(calculateTotal(inflAmnt), dataIsCount); fcltyCpct[0] = calculateTotal(fcltyCpct); - 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)); + inflAssctBfrWqltBod[0] = Number((calculateTotal(inflAssctBfrWqltBod)/7).toFixed(1)); + inflAssctBfrWqltToc[0] = Number((calculateTotal(inflAssctBfrWqltToc)/7).toFixed(1)); + inflAssctBfrWqltSs[0] = Number((calculateTotal(inflAssctBfrWqltSs)/7).toFixed(1)); + inflAssctBfrWqltTn[0] = Number((calculateTotal(inflAssctBfrWqltTn)/7).toFixed(3)); + inflAssctBfrWqltTp[0] = Number((calculateTotal(inflAssctBfrWqltTp)/7).toFixed(3)); efflWqltBod[0] = Number((calculateTotal(efflWqltBod)/7).toFixed(1)); - efflWqltCod[0] = Number((calculateTotal(efflWqltCod)/7).toFixed(1)); + efflWqltToc[0] = Number((calculateTotal(efflWqltToc)/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)); @@ -1581,13 +1738,13 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) dsInflWqltSs: dsInflWqltSs[index] ? Number(dsInflWqltSs[index].toFixed(1)) : '', dsInflWqltTn: dsInflWqltTn[index] ? dsInflWqltTn[index].toFixed(3) : '', dsInflWqltTp: dsInflWqltTp[index] ? dsInflWqltTp[index].toFixed(3) : '', - inflAssctAftWqltBod: inflAssctAftWqltBod[index] ? Number(inflAssctAftWqltBod[index].toFixed(1)) : '', - inflAssctAftWqltToc: inflAssctAftWqltToc[index] ? Number(inflAssctAftWqltToc[index].toFixed(1)) : '', - inflAssctAftWqltSs: inflAssctAftWqltSs[index] ? Number(inflAssctAftWqltSs[index].toFixed(1)) : '', - inflAssctAftWqltTn: inflAssctAftWqltTn[index] ? inflAssctAftWqltTn[index].toFixed(3) : '', - inflAssctAftWqltTp: inflAssctAftWqltTp[index] ? inflAssctAftWqltTp[index].toFixed(3) : '', + inflAssctBfrWqltBod: inflAssctBfrWqltBod[index] ? Number(inflAssctBfrWqltBod[index].toFixed(1)) : '', + inflAssctBfrWqltToc: inflAssctBfrWqltToc[index] ? Number(inflAssctBfrWqltToc[index].toFixed(1)) : '', + inflAssctBfrWqltSs: inflAssctBfrWqltSs[index] ? Number(inflAssctBfrWqltSs[index].toFixed(1)) : '', + inflAssctBfrWqltTn: inflAssctBfrWqltTn[index] ? inflAssctBfrWqltTn[index].toFixed(3) : '', + inflAssctBfrWqltTp: inflAssctBfrWqltTp[index] ? inflAssctBfrWqltTp[index].toFixed(3) : '', efflWqltBod: efflWqltBod[index] ? Number(efflWqltBod[index].toFixed(1)) : '', - efflWqltCod: efflWqltCod[index] ? Number(efflWqltCod[index].toFixed(1)) : '', + efflWqltToc: efflWqltToc[index] ? Number(efflWqltToc[index].toFixed(1)) : '', efflWqltSs: efflWqltSs[index] ? Number(efflWqltSs[index].toFixed(1)) : '', efflWqltTn: efflWqltTn[index] ? efflWqltTn[index].toFixed(3) : '', efflWqltTp: efflWqltTp[index] ? efflWqltTp[index].toFixed(3) : '' @@ -1607,13 +1764,13 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) 설계유입수질SS: item.dsInflWqltSs ? Number(Number(item.dsInflWqltSs).toFixed(1)) : '', 설계유입수질TN: item.dsInflWqltTn ? Number(item.dsInflWqltTn).toFixed(3) : '', 설계유입수질TP: item.dsInflWqltTp ? Number(item.dsInflWqltTp).toFixed(3) : '', - 유입수질BOD: item.inflAssctAftWqltBod ? Number(Number(item.inflAssctAftWqltBod).toFixed(1)) : '', - 유입수질TOC: item.inflAssctAftWqltToc ? Number(Number(item.inflAssctAftWqltToc).toFixed(1)) : '', - 유입수질SS: item.inflAssctAftWqltSs ? Number(Number(item.inflAssctAftWqltSs).toFixed(1)) : '', - 유입수질TN: item.inflAssctAftWqltTn ? Number(item.inflAssctAftWqltTn).toFixed(3) : '', - 유입수질TP: item.inflAssctAftWqltTp ? Number(item.inflAssctAftWqltTp).toFixed(3) : '', + 유입수질BOD: item.inflAssctBfrWqltBod ? Number(Number(item.inflAssctBfrWqltBod).toFixed(1)) : '', + 유입수질TOC: item.inflAssctBfrWqltToc ? Number(Number(item.inflAssctBfrWqltToc).toFixed(1)) : '', + 유입수질SS: item.inflAssctBfrWqltSs ? Number(Number(item.inflAssctBfrWqltSs).toFixed(1)) : '', + 유입수질TN: item.inflAssctBfrWqltTn ? Number(item.inflAssctBfrWqltTn).toFixed(3) : '', + 유입수질TP: item.inflAssctBfrWqltTp ? Number(item.inflAssctBfrWqltTp).toFixed(3) : '', 방류수질BOD: item.efflWqltBod ? Number(Number(item.efflWqltBod).toFixed(1)) : '', - 방류수질TOC: item.efflWqltCod ? Number(Number(item.efflWqltCod).toFixed(1)) : '', + 방류수질TOC: item.efflWqltToc ? Number(Number(item.efflWqltToc).toFixed(1)) : '', 방류수질SS: item.efflWqltSs ? Number(Number(item.efflWqltSs).toFixed(1)) : '', 방류수질TN: item.efflWqltTn ? Number(item.efflWqltTn).toFixed(3) : '', 방류수질TP: item.efflWqltTp ? Number(item.efflWqltTp).toFixed(3) : '', @@ -1627,61 +1784,13 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) ...state.RainManage, rainManageList: filteredData as RainManageListProps[], excelList: excelList, + isLoadingRainManage : false, } : { ...state.RainManage, rainManageList: filteredData as RainManageListProps[], + isLoadingRainManage : false, } })); }, - - searchDrainageEquipment: async (searchYear: string, fcltyCd: string, isExcel : boolean) => { - await fetchDrainageEquipment(searchYear, fcltyCd); - /* if(res == null || res.data.wqltObjs == null || res.data.wqltObjs.length === 0) { - set((state: DashBoardType) => ({ - ...state.RainManage, - rainManageList: [], - })); - return; - } */ - - /* if(isExcel){ - res.data.wqltObjs.forEach((item) => { - excelList.push({ - 강우량: item.rainItem, - 강우조건비율: item.rainRate || 0, - 일수: item.rainDay || 0, - 유입유량: item.inflAmnt || 0, - 시설용량대비: item.fctCpc || 0, - 설계유입수질BOD: item.dsInflWqltBod || 0, - 설계유입수질TOC: item.dsInflWqltCod || 0, - 설계유입수질SS: item.dsInflWqltSs || 0, - 설계유입수질TN: item.dsInflWqltTn || 0, - 설계유입수질TP: item.dsInflWqltTp || 0, - 유입수질BOD: item.inflAssctAftWqltBod || 0, - 유입수질COD: item.inflAssctAftWqltToc || 0, - 유입수질SS: item.inflAssctAftWqltSs || 0, - 유입수질TN: item.inflAssctAftWqltTn || 0, - 유입수질TP: item.inflAssctAftWqltTp || 0, - 방류수질BOD: item.efflWqltBod || 0, - 방류수질COD: item.efflWqltCod || 0, - 방류수질SS: item.efflWqltSs || 0, - 방류수질TN: item.efflWqltTn || 0, - 방류수질TP: item.efflWqltTp || 0, - }); - }); - } */ - - set((state: DashBoardType) => ({ - ...state, - DrainageEquipment: isExcel ? { - ...state.DrainageEquipment, - drainageEquipmentList: drainageEquipmentList, - drainageEquipmentExcelList: [], - } : { - ...state.DrainageEquipment, - drainageEquipmentList: drainageEquipmentList, - } - })); - } } } \ No newline at end of file diff --git a/apps/fo/app/store/facilityPrecipitation/index.tsx b/apps/fo/app/store/facilityPrecipitation/index.tsx index 0c94cf553..833100a75 100644 --- a/apps/fo/app/store/facilityPrecipitation/index.tsx +++ b/apps/fo/app/store/facilityPrecipitation/index.tsx @@ -217,6 +217,7 @@ export type FacilityPrecipitationType = { facilityPrecipitation: FacilityPrecipitationProps[]; excelList: ExcelType[]; facilityPrecipitationCount: number; + isLoading: boolean; }, PrecipitationDetail : { @@ -239,7 +240,8 @@ export const facilityPrecipitationInitState: FacilityPrecipitationType = { upHeadList3 : upHeadList3, facilityPrecipitation : facilityPrecipitation, excelList : [], - facilityPrecipitationCount : 0 + facilityPrecipitationCount : 0, + isLoading : true, }, PrecipitationDetail : { @@ -254,6 +256,14 @@ export type FacilityPrecipitationStore = FacilityPrecipitationType & FacilityPre export const facilityPrecipitationReducer:(set:(fn: (state: FacilityPrecipitationType) => FacilityPrecipitationType) => void)=>FacilityPrecipitationActions=(set: (fn: (state: FacilityPrecipitationType) => FacilityPrecipitationType) => void) => { return { searchFacilityPrecipitationList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { + set((state: FacilityPrecipitationType) => ({ + ...state, + FacilityPrecipitation: { + ...state.FacilityPrecipitation, + isLoading: true, + }, + })); + const res = await fetchFacilityPrecipitationList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm); const data = res.data; const excelDownList: ExcelType[] = []; @@ -293,13 +303,15 @@ export const facilityPrecipitationReducer:(set:(fn: (state: FacilityPrecipitatio ...state.FacilityPrecipitation, facilityPrecipitation: res.data, facilityPrecipitationCount: res.count, + isLoading : false, }:{ ...state.FacilityPrecipitation, excelList: excelDownList, + isLoading : false, }, PrecipitationDetail:{ ...state.PrecipitationDetail, - gridListPrecipitationDetail: res.detailData + gridListPrecipitationDetail: res.detailData, } })) } diff --git a/apps/fo/app/store/facilityWaterQlty/index.tsx b/apps/fo/app/store/facilityWaterQlty/index.tsx index 565c251d2..53e430d47 100644 --- a/apps/fo/app/store/facilityWaterQlty/index.tsx +++ b/apps/fo/app/store/facilityWaterQlty/index.tsx @@ -21,12 +21,16 @@ export interface FacilityWaterQltyProps { sggNm: string, addr: string, fctCpc: number, + inflAssctBfrWqltBod: string | '', inflAssctAftWqltBod: string | '', + inflAssctBfrWqltToc: string | '', inflAssctAftWqltToc: string | '', + inflAssctBfrWqltSs: string | '', inflAssctAftWqltSs: string | '', + inflAssctBfrWqltTn: string | '', inflAssctAftWqltTn: string | '', - inflAssctAftWqltTp: string | '', inflAssctBfrWqltTp: string | '', + inflAssctAftWqltTp: string | '', efflWqltBod: string | '', efflWqltToc: string | '', efflWqltSs: string | '', @@ -127,11 +131,11 @@ const upHeadList1: TableUpperProps[] = [ { id: "fctCpc", title: "시설용량(m³/일)", align: "right", rowSpan: 2, row: 0 }, { id: "A", title: "유입", colSpan: 5, row: 0 }, { id: "B", title: "방류", colSpan: 5, row: 0 }, - { id: "inflAssctAftWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row: 1 }, - { id: "inflAssctAftWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1 }, - { id: "inflAssctAftWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1 }, - { id: "inflAssctAftWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 4, align: "right", row: 1 }, - { id: "inflAssctAftWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1 }, + { id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row: 1 }, + { id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1 }, + { id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1 }, + { id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 4, align: "right", row: 1 }, + { id: "inflAssctBfrWqltTp", 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: "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 }, @@ -151,11 +155,11 @@ const upHeadList2: TableUpperProps[] = [ { id: "fctCpc", title: "시설용량(m³/L)", align: "right", row:0, rowSpan:2 }, { id: "A", title: "유입", colSpan: 5, row: 0 }, { id: "B", title: "방류", colSpan: 5, row: 0 }, - { id: "inflAssctAftWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1 }, - { id: "inflAssctAftWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 }, - { id: "inflAssctAftWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 }, - { id: "inflAssctAftWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 }, - { id: "inflAssctAftWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 }, + { id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1 }, + { id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 }, + { id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 }, + { id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 }, + { id: "inflAssctBfrWqltTp", 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: "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 }, @@ -179,11 +183,11 @@ const upHeadList3: TableUpperProps[] = [ { id: "fctCpc", title: "시설용량(m³/L)", align: "right", row:0, rowSpan:2 }, { id: "A", title: "유입", colSpan: 5, row: 0 }, { id: "B", title: "방류", colSpan: 5, row: 0 }, - { id: "inflAssctAftWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1 }, - { id: "inflAssctAftWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 }, - { id: "inflAssctAftWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 }, - { id: "inflAssctAftWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 }, - { id: "inflAssctAftWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 }, + { id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1 }, + { id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 }, + { id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 }, + { id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 }, + { id: "inflAssctBfrWqltTp", 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: "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 }, @@ -197,10 +201,10 @@ const upHeadList3: TableUpperProps[] = [ // 처리시설 수질현황 헤더(모달-연간) const upHeadListModalYear: TableUpperProps[] = [ { id: "msrDt", title: "날짜" }, - { id: "inflAssctAftWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe1", upSequnce: 1, align: "right" }, - { id: "inflAssctAftWqltToc", title: "TOC(COD)\n(mg/L)", upName: "upChangeRe1", upSequnce: 2, align: "right" }, - { id: "inflAssctAftWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe1", upSequnce: 3, align: "right" }, - { id: "inflAssctAftWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe1", upSequnce: 2, align: "right" }, + { id: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe1", upSequnce: 1, align: "right" }, + { id: "inflAssctBfrWqltToc", title: "TOC(COD)\n(mg/L)", upName: "upChangeRe1", upSequnce: 2, align: "right" }, + { id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe1", upSequnce: 3, align: "right" }, + { id: "inflAssctBfrWqltTn", 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: "efflWqltToc", title: "TOC(COD)\n(mg/L)", upName: "upChangeRe2", upSequnce: 2, align: "right" }, @@ -288,6 +292,7 @@ export type FacilityWaterQltyType = { upHeadList1: TableUpperProps[]; upHeadList2: TableUpperProps[]; upHeadList3: TableUpperProps[]; + isLoading: boolean; }, FacilityWaterQltyModal: { @@ -311,6 +316,7 @@ export const facilityWaterQltyInitState: FacilityWaterQltyType = { facilityWaterQltyCount: 0, facilityWaterQltyList: [], excelList: [], + isLoading: true, isInit: false, mainLabelArray: mainLabelArray, upHeadList1: upHeadList1, @@ -361,8 +367,8 @@ export type FacilityWaterQltyActions = { * @returns : 없음 * @description : 시설수질리스트 타입의 데이터를 표현 방식으로 바꿔주는 함수 * - msrDt : YYYY-MM-DD 형식으로 변환 - * - inflAssctAftWqltBod : 소수점 1자리까지 표현 - * - inflAssctAftWqltTn : 소수점 1자리까지 표현 + * - inflAssctBfrWqltBod : 소수점 1자리까지 표현 + * - inflAssctBfrWqltTn : 소수점 1자리까지 표현 * - inflAssctBfrWqltTp : 소수점 1자리까지 표현 * - efflWqltBod : 소수점 2자리까지 표현 * - efflWqltTn : 소수점 2자리까지 표현 @@ -391,41 +397,48 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType * @param fcltyNm : 시설명 */ searchFacilityWaterQltyList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { + set((state: FacilityWaterQltyType) => ({ + ...state, + FacilityWaterQltyMain: { + ...state.FacilityWaterQltyMain, + isLoading: true, + }, + })); const res = await fetchFacilityWaterQltyList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm); const rtnData = res.data.map(item => { dataFormSetting(item) - if(item.inflAssctAftWqltTn) { - item.inflAssctAftWqltTn = Number(Math.round(Number(item.inflAssctAftWqltTn) * 1000)/1000).toFixed(3); + if(item.inflAssctBfrWqltTn) { + item.inflAssctBfrWqltTn = Number(Math.round(Number(item.inflAssctBfrWqltTn) * 1000)/1000).toFixed(3); } if(item.efflWqltTn){ item.efflWqltTn = Number(Math.round(Number(item.efflWqltTn) * 1000)/1000).toFixed(3); } - if(item.inflAssctAftWqltTp){ - item.inflAssctAftWqltTp = Number(Math.round(Number(item.inflAssctAftWqltTp) * 1000)/1000).toFixed(3); + if(item.inflAssctBfrWqltTp){ + item.inflAssctBfrWqltTp = Number(Math.round(Number(item.inflAssctBfrWqltTp) * 1000)/1000).toFixed(3); } if(item.efflWqltTp){ item.efflWqltTp = Number(Math.round(Number(item.efflWqltTp) * 1000)/1000).toFixed(3); } - if(item.inflAssctAftWqltToc){ - item.inflAssctAftWqltToc = Number(Math.round(Number(item.inflAssctAftWqltToc) * 10)/10).toFixed(1); + if(item.inflAssctBfrWqltToc){ + item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 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); + if(item.inflAssctBfrWqltBod){ + item.inflAssctBfrWqltBod = Number(Math.round(Number(item.inflAssctBfrWqltBod) * 10)/10).toFixed(1); } if(item.efflWqltBod){ item.efflWqltBod = Number(Math.round(Number(item.efflWqltBod) * 10)/10).toFixed(1); } - if(item.inflAssctAftWqltSs){ - item.inflAssctAftWqltSs = Number(Math.round(Number(item.inflAssctAftWqltSs) * 10)/10).toFixed(1); + if(item.inflAssctBfrWqltSs){ + item.inflAssctBfrWqltSs = Number(Math.round(Number(item.inflAssctBfrWqltSs) * 10)/10).toFixed(1); } if(item.efflWqltSs){ item.efflWqltSs = Number(Math.round(Number(item.efflWqltSs) * 10)/10).toFixed(1); } - if(item.inflAssctAftWqltToc){ - item.inflAssctAftWqltToc = Number(Math.round(Number(item.inflAssctAftWqltToc) * 10)/10).toFixed(1); + if(item.inflAssctBfrWqltToc){ + item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10)/10).toFixed(1); } if(item.efflWqltToc){ item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1); @@ -450,11 +463,11 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType 시설이름: item.bscFctNm, 주소: item.addr, 용량: item.fctCpc, - 유입BOD: item.inflAssctAftWqltBod, - 유입TOC: item.inflAssctAftWqltToc, - 유입SS: item.inflAssctAftWqltSs, - 유입TN: item.inflAssctAftWqltTn, - 유입TP: item.inflAssctAftWqltTp, + 유입BOD: item.inflAssctBfrWqltBod, + 유입TOC: item.inflAssctBfrWqltToc, + 유입SS: item.inflAssctBfrWqltSs, + 유입TN: item.inflAssctBfrWqltTn, + 유입TP: item.inflAssctBfrWqltTp, 유출BOD: item.efflWqltBod, 유출TOC: item.efflWqltToc, 유출SS: item.efflWqltSs, @@ -476,10 +489,12 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType ...state.FacilityWaterQltyMain, facilityWaterQltyList: rtnData, facilityWaterQltyCount: res.count, + isLoading : false, }:{ ...state.FacilityWaterQltyMain, excelList: excelDownList, - } + isLoading : false, + }, })) }, @@ -556,47 +571,54 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType return; } - const tmpData:FacilityWaterQltyProps[] = []; - // facilityPrecipitation의 rainEffectDay 계산 로직을 적용 - for(let idx = 0; idx < res.data.wqltObjs.length; idx++) { - const item = res.data.wqltObjs[idx]; - if (!item) continue; - - const rainDay = Number(item.infoRnDay) >= 3 ? 1 : 0; - let rainEffectDay = 0; - - if(idx < res.data.wqltObjs.length - 2) { - if(rainDay == 1) { - rainEffectDay = 1; - } else { - if(idx >= 2) { - const prevItem1 = res.data.wqltObjs[idx-1]; - const prevItem2 = res.data.wqltObjs[idx-2]; - if((prevItem1 && Number(prevItem1.infoRnDay) >= 3) || (prevItem2 && Number(prevItem2.infoRnDay) >= 3)) { - rainEffectDay = 1; - } - } - } - } else if(idx < res.data.wqltObjs.length - 1) { - const nextItem = res.data.wqltObjs[idx+1]; - if(rainDay == 1 || (nextItem && Number(nextItem.infoRnDay) >= 3)) { - rainEffectDay = 1; - } - } else { - rainEffectDay = rainDay; - } - tmpData.push({ - ...item, - rainEffectDay: rainEffectDay, - } as FacilityWaterQltyProps); + const data = res.data.wqltObjs; + // 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일) + for(let idx = 0; idx < data.length; idx++) { + const item = data[idx]; + if(item){ + if(item.infoRnDay && Number(item.infoRnDay) > 3) { + item.rainEffectDay = 1; + } else { + item.rainEffectDay = 0; + } + } } - const rtnData = tmpData.map((item: FacilityWaterQltyProps) => { + // 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정 + for(let idx = 0; idx < data.length; idx++) { + if(data[idx]) { + // 하루 전이 강우영향일(3 이상)인 경우 + if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) { + data[idx]!.rainEffectDay = 1; + } + // 이틀 전이 강우영향일(3 이상)인 경우 + if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) { + data[idx]!.rainEffectDay = 1; + } + } + } + + for(let idx = 0; idx < data.length; idx++) { + if(data[idx] && data[idx]?.rainEffectDay === 1) { + if(idx > 1){ + if(data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) > 3) { + data[idx]!.infoRnDay = data[idx-1]!.infoRnDay; + } + } + if(idx > 2){ + if(data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) > 3) { + data[idx]!.infoRnDay = data[idx-2]!.infoRnDay; + } + } + } + } + + const rtnData = data.map((item: FacilityWaterQltyProps) => { dataFormSetting(item) - if(item.inflAssctAftWqltTn) { - item.inflAssctAftWqltTn = Number(Math.round(Number(item.inflAssctAftWqltTn) * 1000)/1000).toFixed(3); + if(item.inflAssctBfrWqltTn) { + item.inflAssctBfrWqltTn = Number(Math.round(Number(item.inflAssctBfrWqltTn) * 1000)/1000).toFixed(3); } if(item.efflWqltTn){ item.efflWqltTn = Number(Math.round(Number(item.efflWqltTn) * 1000)/1000).toFixed(3); @@ -607,26 +629,26 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType if(item.efflWqltTp){ item.efflWqltTp = Number(Math.round(Number(item.efflWqltTp) * 1000)/1000).toFixed(3); } - if(item.inflAssctAftWqltToc){ - item.inflAssctAftWqltToc = Number(Math.round(Number(item.inflAssctAftWqltToc) * 10)/10).toFixed(1); + if(item.inflAssctBfrWqltToc){ + item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 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); + if(item.inflAssctBfrWqltBod){ + item.inflAssctBfrWqltBod = Number(Math.round(Number(item.inflAssctBfrWqltBod) * 10)/10).toFixed(1); } if(item.efflWqltBod){ item.efflWqltBod = Number(Math.round(Number(item.efflWqltBod) * 10)/10).toFixed(1); } - if(item.inflAssctAftWqltSs){ - item.inflAssctAftWqltSs = Number(Math.round(Number(item.inflAssctAftWqltSs) * 10)/10).toFixed(1); + if(item.inflAssctBfrWqltSs){ + item.inflAssctBfrWqltSs = Number(Math.round(Number(item.inflAssctBfrWqltSs) * 10)/10).toFixed(1); } if(item.efflWqltSs){ item.efflWqltSs = Number(Math.round(Number(item.efflWqltSs) * 10)/10).toFixed(1); } - if(item.inflAssctAftWqltToc){ - item.inflAssctAftWqltToc = Number(Math.round(Number(item.inflAssctAftWqltToc) * 10)/10).toFixed(1); + if(item.inflAssctBfrWqltToc){ + item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10)/10).toFixed(1); } if(item.efflWqltToc){ item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1); diff --git a/apps/fo/app/store/flowRate/index.tsx b/apps/fo/app/store/flowRate/index.tsx index 38cb4e2e6..a7be5bf60 100644 --- a/apps/fo/app/store/flowRate/index.tsx +++ b/apps/fo/app/store/flowRate/index.tsx @@ -170,7 +170,6 @@ const fetchFlowRateList = async (pageNo: number, pageSize: number, searchYear: s try { const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : ''; const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr; const res = await getFetch('fo', url); - console.log(url); return { data: res.data, count: res.count } } catch (error) { console.error('시설정보 유량현황 데이터를 가져오는데 실패했습니다:', error); @@ -220,6 +219,7 @@ export type FlowRateSearchType = { flowRateList:flowRateListProps[]; flowRateCount: number; excelList: ExcelType[]; + isLoading: boolean; }, FlowRateModal : { @@ -253,7 +253,8 @@ export const flowRateSearchInitState:FlowRateSearchType = { upHeadList3 : upHeadList3, flowRateList : flowRateList, flowRateCount : 0, - excelList: [] + excelList: [], + isLoading: true, }, FlowRateModal : { isInit : false, @@ -265,6 +266,13 @@ export const flowRateSearchInitState:FlowRateSearchType = { export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => FlowRateSearchType) => void)=>FlowRateSearchActions=(set: (fn: (state: FlowRateSearchType) => FlowRateSearchType) => void) => { return { searchFlowRateList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { + set((state: FlowRateSearchType) => ({ + ...state, + FlowRateList: { + ...state.FlowRateList, + isLoading: true, + }, + })); const res = await fetchFlowRateList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm); const data = res.data; const excelDownList: ExcelType[] = []; @@ -303,54 +311,59 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow ...state.FlowRateList, flowRateList: rtnData, flowRateCount: res.count, + isLoading : false, }:{ ...state.FlowRateList, excelList: excelDownList, - } + isLoading : false, + }, })) }, 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 계산 로직을 적용 + // 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일) for(let idx = 0; idx < data.length; idx++) { const item = data[idx]; - const rainDay = Number(item.infoRnDay) >= 3 ? 1 : 0; - let rainEffectDay = 0; - - if(idx < data.length - 2) { - if(rainDay == 1) { - rainEffectDay = 1; + if(item){ + if(item.infoRnDay && Number(item.infoRnDay.toString().trim()) >= 3) { + item.rainEffectDay = 1; } else { - if(idx >= 2) { - if(Number(data[idx-1].infoRnDay) >= 3 || Number(data[idx-2].infoRnDay) >= 3) { - rainEffectDay = 1; - } - } + item.rainEffectDay = 0; } - } else if(idx < data.length - 1) { - if(rainDay == 1 || Number(data[idx+1].infoRnDay) >= 3) { - rainEffectDay = 1; - } - } else { - rainEffectDay = rainDay; } - - tmpData.push({ - ...item, - rainEffectDay: rainEffectDay, - }); } - const rtnData = tmpData.map((item: FlowRateModalProps) => { + // 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정 + for(let idx = 0; idx < data.length; idx++) { + if(data[idx]) { + // 하루 전이 강우영향일(3 이상)인 경우 + if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) { + data[idx]!.rainEffectDay = 1; + } + // 이틀 전이 강우영향일(3 이상)인 경우 + if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) { + data[idx]!.rainEffectDay = 1; + } + } + } + + for(let idx = 0; idx < data.length; idx++) { + if(data[idx] && data[idx]?.rainEffectDay === 1) { + if(idx > 1){ + if(data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) { + data[idx]!.infoRnDay = data[idx-1]!.infoRnDay; + } + } + if(idx > 2){ + if(data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) { + data[idx]!.infoRnDay = data[idx-2]!.infoRnDay; + } + } + } + } + + const rtnData = data.map((item: FlowRateModalProps) => { item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0) dataFormSetting(item); return item; diff --git a/apps/fo/app/store/planSewage/index.tsx b/apps/fo/app/store/planSewage/index.tsx index e9153305a..112070300 100644 --- a/apps/fo/app/store/planSewage/index.tsx +++ b/apps/fo/app/store/planSewage/index.tsx @@ -1,6 +1,7 @@ import DataForm from "@/app/components/common/DataForm"; import type { TableUpperProps } from "../dashboard"; import { getFetch } from "@/app/components/api"; +import { calRainEffectDay, type ApiResponse, type FlowDataItem } from "../underWaterInput"; export type { TableUpperProps }; /**==================================== * Store - 타입 @@ -145,6 +146,7 @@ export type PlanSewageType = { planSewageList: PlanSewageProps[]; planSewageCount: number; excelList: ExcelType[]; + isLoading: boolean; }, } @@ -161,7 +163,8 @@ export const planSewageInitState: PlanSewageType = { upHeadList3 : upHeadList3, planSewageList : planSewageList, planSewageCount : 0, - excelList : [] + excelList : [], + isLoading : true, }, } @@ -170,16 +173,43 @@ export type PlanSewageStore = PlanSewageType & PlanSewageActions; export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageType) => void)=>PlanSewageActions=(set: (fn: (state: PlanSewageType) => PlanSewageType) => void) => { return { searchPlanSewageList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { + set((state: PlanSewageType) => ({ + ...state, + PlanSewage: { + ...state.PlanSewage, + isLoading: true, + }, + })); const res = await fetchPlanSewageList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm); const excelDownList: ExcelType[] = []; - console.log('res' , res.data); + const data = res.data + const processedData = await Promise.all(data.map(async (item:PlanSewageProps) => { + const res2 = await getFetch('fo', '/fclt/flow/' + item.bscFctCd + '/' + searchYear) as ApiResponse; + const calData = calRainEffectDay(res2.data, 'SUNNY'); + + let sumInflAmntSunny = 0; + let avgInflAmntSunny = 0; + calData.forEach((flowItem:FlowDataItem) => { + sumInflAmntSunny += Number(flowItem.inflAmnt); + }) + avgInflAmntSunny = sumInflAmntSunny / calData.length; + item.avgInflAmntSunny = avgInflAmntSunny; + if(item.bscFctCd === '11200PB001R'){ + console.log('avgInflAmntSunny : ',item.avgInflAmntSunny); + console.log('calData : ',calData); + } + return item; + })); + /** * 결과데이터 계산 * (1) 여유용량 = 시설용량 - 건기시 평균유량 * (2) 변동부하율 = 건기시 일최대 유량/일평균유량(기준 최근 3개년) * (3) 분류식화율 = 분류식지역 면적(㎢)/처리구역 면적합계(㎢) ×100 */ - const resultData = res.data.map((item:PlanSewageProps) => { + const resultData = processedData.map((item:PlanSewageProps) => { + console.log('item.fctCpc : ',item.fctCpc); + console.log('item.avgInflAmntSunny : ',item.avgInflAmntSunny); item.spareCapacity = Number(item.fctCpc) - Number(item.avgInflAmntSunny); item.variableLoadPercent = item.maxInflAmntSunny && item.maxInflAmntSunny!==0 ? Number(item.maxInflAmntSunny) / Number(item.avgInflAmntSunny) : 0; item.classifiedSewerPercent = item.sprtProcZoneAr && item.sprtProcZoneAr!==0 ? Number(item.sprtProcZoneAr) / Number(item.procZoneSm) * 100 : 0; @@ -216,10 +246,12 @@ export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageTy ...state.PlanSewage, planSewageList: resultData, planSewageCount: res.count, + isLoading : false, }:{ ...state.PlanSewage, excelList: excelDownList, - } + isLoading : false, + }, })) } } diff --git a/apps/fo/app/store/processArea/index.tsx b/apps/fo/app/store/processArea/index.tsx index a43777b1c..049341d23 100644 --- a/apps/fo/app/store/processArea/index.tsx +++ b/apps/fo/app/store/processArea/index.tsx @@ -1,6 +1,7 @@ -import { getFetchAreaList, postFetch } from "@/app/components/api"; -import type { TableUpperProps } from "../dashboard"; +import { postFetch } from "@/app/components/api"; import DataForm from "@/app/components/common/DataForm"; +import { fetchPlanInfo } from "../common"; +import type { TableUpperProps } from "../dashboard"; export type { TableUpperProps }; /**==================================== * Store - 타입 @@ -227,25 +228,14 @@ const fetchFacilityDetailInfo = async (swtrmtFcltCd: string) => { }; // 시설정보 리스트 데이터 호출(구분 선택 후 시설명 있을 경우) -const fetchProcessAreaList = async (pageNo : number, pageSize : number, ctpvNm : string | undefined, sggNm : string | undefined, targetYear : string | undefined ): Promise<{data:ProcessAreaProps[], count:number}> => { +const fetchProcessAreaList = async (pageNo : number, pageSize : number, ctpvNm : string | undefined, sggNm : string | undefined, targetYear : string | undefined, set : (fn: (state: ProcessAreaType) => ProcessAreaType) => void): Promise<{data:ProcessAreaProps[], count:number}> => { try { - targetYear = targetYear ? targetYear : "2024"; - const baseUrl = 'https://apigateway.rsonesoft.com/dc-service/api/v1/nowDmgMtncGnsvy'; - const queryParams = new URLSearchParams(); - - if (ctpvNm && ctpvNm !== '전체') queryParams.append('ctpvNm', ctpvNm); - if (sggNm && sggNm !== '전체') queryParams.append('sggNm', sggNm); - if (targetYear) queryParams.append('targetYear',targetYear); - - const queryString = queryParams.toString(); - const url = queryString ? `${baseUrl}?${queryString}` : baseUrl; - const res = await getFetchAreaList(url); - + const res = await fetchPlanInfo(targetYear, ctpvNm, sggNm, undefined); if(res && res.length > 0){ const enrichedData = await Promise.all( res.map(async (item: ProcessAreaProps) => { upHeadList1.forEach((head:TableUpperProps) => { - if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') { + /* if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') { head.title = '현재\n(' + item.yr + '년)'; } else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') { head.title = '1단계\n(' + item.yrDc1 + '년)'; @@ -257,6 +247,19 @@ const fetchProcessAreaList = async (pageNo : number, pageSize : number, ctpvNm : head.title = '4단계\n(' + item.yrDc4 + '년)'; } else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') { head.title = '기승인\n4단계(' + item.yrDt4 + '년)'; + } */ + if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') { + head.title = '현재'; + } else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') { + head.title = '1단계'; + } else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') { + head.title = '2단계'; + } else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') { + head.title = '3단계'; + } else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') { + head.title = '4단계'; + } else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') { + head.title = '기승인\n4단계'; } }); const res = await fetchFacilityDetailInfo(item.swtrmtFcltCd); @@ -280,6 +283,13 @@ const fetchProcessAreaList = async (pageNo : number, pageSize : number, ctpvNm : } } catch (error) { console.error('시설계획정보를 가져오는데 실패했습니다:', error); + set((state) => ({ + ...state, + ProcessArea : { + ...state.ProcessArea, + isLoading : false + } + })); return {data: [], count: 0}; } }; @@ -304,6 +314,7 @@ export type ProcessAreaType = { processAreaList: ProcessAreaProps[]; processAreaCount: number; excelList: ExcelType[]; + isLoading: boolean; }, ProcessAreaDetail : { @@ -328,7 +339,8 @@ export const processAreaInitState: ProcessAreaType = { upHeadList1 : upHeadList1, processAreaList : processAreaList, processAreaCount : 0, - excelList : [] + excelList : [], + isLoading : true, }, ProcessAreaDetail : { @@ -355,7 +367,14 @@ export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set: * @param pageSize : 페이지 크기 */ searchProcessAreaList: async ( pageNo:number, pageSize:number, ctpvNm?:string, sggNm?:string, targetYear?:string) => { - const res = await fetchProcessAreaList(pageNo, pageSize, ctpvNm, sggNm, targetYear); + set((state: ProcessAreaType) => ({ + ...state, + ProcessArea: { + ...state.ProcessArea, + isLoading: true, + }, + })); + const res = await fetchProcessAreaList(pageNo, pageSize, ctpvNm, sggNm, targetYear, set); res.data.forEach((item:ProcessAreaProps) => { DataForm({ type: 'float1', column: 'fctCpc', item:item as unknown as Record}); }) @@ -400,9 +419,11 @@ export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set: ...state.ProcessArea, processAreaList: res.data, processAreaCount: res.count, + isLoading : false, }:{ ...state.ProcessArea, excelList: excelDownList, + isLoading : false, }, })) }, @@ -411,51 +432,51 @@ export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set: set((state: ProcessAreaType) => { const rtnData = state.ProcessArea.processAreaList.find((item: ProcessAreaProps) => item.swtrmtFcltCd === swtrmtFcltCd); if (rtnData) { - upHeadListFcltyImproveInfo.forEach((head:TableUpperProps) => { - if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') { - head.title = '현재\n(' + rtnData.yr + '년)'; - } else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') { - head.title = '1단계\n(' + rtnData.yrDc1 + '년)'; - } else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') { - head.title = '2단계\n(' + rtnData.yrDc2 + '년)'; - } else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') { - head.title = '3단계\n(' + rtnData.yrDc3 + '년)'; - } else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') { - head.title = '4단계\n(' + rtnData.yrDc4 + '년)'; - } else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') { - head.title = '기승인\n4단계(' + rtnData.yrDt4 + '년)'; - } - }); + upHeadListFcltyImproveInfo.forEach((head:TableUpperProps) => { + if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') { + head.title = rtnData.yr? '현재\n(' + rtnData.yr + '년)':head.title = '현재'; + } else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') { + head.title = rtnData.yrDc1? '1단계\n(' + rtnData.yrDc1 + '년)':head.title = '1단계'; + } else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') { + head.title = rtnData.yrDc2? '2단계\n(' + rtnData.yrDc2 + '년)':head.title = '2단계'; + } else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') { + head.title = rtnData.yrDc3? '3단계\n(' + rtnData.yrDc3 + '년)':head.title = '3단계'; + } else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') { + head.title = rtnData.yrDc4? '4단계\n(' + rtnData.yrDc4 + '년)':head.title = '4단계'; + } else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') { + head.title = rtnData.yrDt4? '기승인\n4단계(' + rtnData.yrDt4 + '년)':head.title = '기승인\n4단계'; + } + }); upHeadListProcessAreaPlan.forEach((head:TableUpperProps) => { if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') { - head.title = '현재\n(' + rtnData.yr + '년)'; + head.title = rtnData.yr? '현재\n(' + rtnData.yr + '년)':head.title = '현재'; } else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') { - head.title = '1단계\n(' + rtnData.yrDc1 + '년)'; + head.title = rtnData.yrDc1?'1단계\n(' + rtnData.yrDc1 + '년)':head.title = '1단계'; } else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') { - head.title = '2단계\n(' + rtnData.yrDc2 + '년)'; + head.title = rtnData.yrDc2?'2단계\n(' + rtnData.yrDc2 + '년)':head.title = '2단계'; } else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') { - head.title = '3단계\n(' + rtnData.yrDc3 + '년)'; + head.title = rtnData.yrDc3? '3단계\n(' + rtnData.yrDc3 + '년)':head.title = '3단계'; } else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') { - head.title = '4단계\n(' + rtnData.yrDc4 + '년)'; + head.title = rtnData.yrDc4?'4단계\n(' + rtnData.yrDc4 + '년)':head.title = '4단계'; } else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') { - head.title = '기승인\n4단계(' + rtnData.yrDt4 + '년)'; + head.title = rtnData.yrDt4?'기승인\n4단계(' + rtnData.yrDt4 + '년)':head.title = '기승인\n4단계'; } }); upHeadListProcessPopulation.forEach((head:TableUpperProps) => { if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') { - head.title = '현재\n(' + rtnData.yr + '년)'; + head.title = rtnData.yr?'현재\n(' + rtnData.yr + '년)':head.title = '현재'; } else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') { - head.title = '1단계\n(' + rtnData.yrDc1 + '년)'; + head.title = rtnData.yrDc1?'1단계\n(' + rtnData.yrDc1 + '년)':head.title = '1단계'; } else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') { - head.title = '2단계\n(' + rtnData.yrDc2 + '년)'; + head.title = rtnData.yrDc2?'2단계\n(' + rtnData.yrDc2 + '년)':head.title = '2단계'; } else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') { - head.title = '3단계\n(' + rtnData.yrDc3 + '년)'; + head.title = rtnData.yrDc3?'3단계\n(' + rtnData.yrDc3 + '년)':head.title = '3단계'; } else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') { - head.title = '4단계\n(' + rtnData.yrDc4 + '년)'; + head.title = rtnData.yrDc4?'4단계\n(' + rtnData.yrDc4 + '년)':head.title = '4단계'; } else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') { - head.title = '기승인\n4단계(' + rtnData.yrDt4 + '년)'; + head.title = rtnData.yrDt4?'기승인\n4단계(' + rtnData.yrDt4 + '년)':head.title = '기승인\n4단계'; } }); diff --git a/apps/fo/app/store/processFacility/index.tsx b/apps/fo/app/store/processFacility/index.tsx index a8c04930d..022c28c3e 100644 --- a/apps/fo/app/store/processFacility/index.tsx +++ b/apps/fo/app/store/processFacility/index.tsx @@ -517,6 +517,7 @@ export type ProcessFacilityType = { processFacilityList:facilityListProps[]; processFacilityCount:number; excelList : ExcelType[]; + isLoading: boolean; }, ProcessFacilityDetail : { @@ -551,7 +552,8 @@ export const processFacilityInitState:ProcessFacilityType = { upHeadList3 : upHeadList3, processFacilityList : processFacilityList, processFacilityCount:1, - excelList : [] + excelList : [], + isLoading : true, }, ProcessFacilityDetail : { @@ -588,6 +590,13 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio * @param pageSize : 페이지 크기 */ searchProcessFacility: async (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string) => { + set((state: ProcessFacilityType) => ({ + ...state, + ProcessFacilityList: { + ...state.ProcessFacilityList, + isLoading: true, + }, + })); const res = await fetchFacilityList(pageNo, pageSize, partValue, nameCd, fcltCpct, oprtngSttsCd, facilityPartValue, facilityName); res.data.forEach((item:facilityListProps) => { DataForm({ type: 'date', column: 'cmplDt', item:item as unknown as Record}); @@ -635,9 +644,11 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio ...state.ProcessFacilityList, processFacilityList: res.data, processFacilityCount: res.count, + isLoading: false, }:{ ...state.ProcessFacilityList, excelList: excelDownList, + isLoading: false, }, })) }, @@ -648,6 +659,13 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio * @param pageSize : 페이지 크기 */ searchProcessFacilitySearching: async (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string) => { + set((state: ProcessFacilityType) => ({ + ...state, + ProcessFacilityList: { + ...state.ProcessFacilityList, + isLoading: true, + }, + })); const res = await fetchFacilityListSearching(pageNo, pageSize, partValue, nameCd, fcltCpct, oprtngSttsCd, facilityPartValue, facilityName); /* res.data.forEach((item:facilityListProps) => { DataForm({ type: 'date', column: 'cmplDt', item:item as unknown as Record}); @@ -665,6 +683,7 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio ...state.ProcessFacilityList, processFacilityList: res.data, processFacilityCount: res.count, + isLoading: false, }, })) }, diff --git a/apps/fo/app/store/rdi/index.tsx b/apps/fo/app/store/rdi/index.tsx index e7acb2231..b1eccc2b7 100644 --- a/apps/fo/app/store/rdi/index.tsx +++ b/apps/fo/app/store/rdi/index.tsx @@ -183,6 +183,7 @@ export type RdiType = { rdiList: RdiProps[]; // Changed from facilityAreaProps to ProcessAreaProps rdiCount: number; excelList: ExcelType[]; + isLoading: boolean; }, } @@ -199,7 +200,8 @@ export const rdiInitState: RdiType = { upHeadList3 : upHeadList3, rdiList : rdiList, rdiCount : 2, - excelList : [] + excelList : [], + isLoading : true, } } @@ -220,6 +222,14 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio console.log("tableActionsExport"); return { searchRdiList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { + set((state: RdiType) => ({ + ...state, + Rdi: { + ...state.Rdi, + isLoading: true, + }, + })); + const res = await fetchRdiList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm); const data = res.data; const excelDownList: ExcelType[] = []; @@ -264,10 +274,12 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio ...state.Rdi, rdiList: rtnData, rdiCount: res.count, + isLoading : false, }:{ ...state.Rdi, excelList: excelDownList, - } + isLoading : false, + }, })) }, } diff --git a/apps/fo/app/store/sewageOccur/index.tsx b/apps/fo/app/store/sewageOccur/index.tsx index f5d300aa1..5feb91f94 100644 --- a/apps/fo/app/store/sewageOccur/index.tsx +++ b/apps/fo/app/store/sewageOccur/index.tsx @@ -126,7 +126,6 @@ const tempSewageOccurList:modalTableType[] = [] const fetchSewageOccurList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { // 20250701임시시 - console.log("searchYear", searchYear); const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : ''; const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr; const res = await getFetch('fo', url); @@ -145,7 +144,7 @@ const fetchSewageOccurList = async (pageNo: number, pageSize: number, searchYear ====================================*/ 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; + searchSewageOccurDetailList: (bscFctCd: string, searchYear: string, startYearMonth?: string, endYearMonth?: string) => void; } export type SewageOccurType = { @@ -162,6 +161,7 @@ export type SewageOccurType = { sewageOccurList: SewageOccurProps[]; // Changed from facilityAreaProps to ProcessAreaProps sewageOccurCount: number; excelList: ExcelType[]; + isLoading: boolean; }, SewageOccurDetail : { @@ -184,7 +184,8 @@ export const sewageOccurInitState: SewageOccurType = { upHeadList3 : upHeadList3, sewageOccurList : sewageOccurList, sewageOccurCount : 2, - excelList : [] + excelList : [], + isLoading : true, }, SewageOccurDetail : { @@ -197,14 +198,15 @@ export const sewageOccurInitState: SewageOccurType = { export type SewageOccurStore = SewageOccurType & SewageOccurActions; // Add type definitions for API responses -type FlowDataItem = { +export type FlowDataItem = { inflAmnt: string | number; infoRnDay: string | number; bscFctCd: string; msrDt: string; + rainEffectDay?: number; } -type FlowResponse = { +export type FlowResponse = { data: FlowDataItem[]; count: number; } @@ -212,28 +214,84 @@ type FlowResponse = { 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) => { + set((state: SewageOccurType) => ({ + ...state, + SewageOccur: { + ...state.SewageOccur, + isLoading: true, + }, + })); const res = await fetchSewageOccurList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm); const data = res.data; - // Promise.all을 사용하여 모든 비동기 작업이 완료될 때까지 기다림 const calData = await Promise.all(data.map(async (item: SewageOccurProps) => { item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || ''; item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, '')); item.swageChangePercent = 80; - const bscFctCd = item.bscFctCd; const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as FlowResponse; - + let sumChungcunDay = 0; let chungcunSumFlow = 0; let totWaterUsage = 0; + + if(bscFctCd === '11200PB001R'){ + console.log('res2.data : ',res2.data); + } + // 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일) + for(let idx = 0; idx < res2.data.length; idx++) { + const item = res2.data[idx]; + if(item){ + if(item.infoRnDay && Number(item.infoRnDay.toString().trim()) >= 3) { + item.rainEffectDay = 1; + } else { + item.rainEffectDay = 0; + } + } + } + + // 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정 + for(let idx = 0; idx < res2.data.length; idx++) { + if(res2.data[idx]) { + // 하루 전이 강우영향일(3 이상)인 경우 + if(idx > 0 && res2.data[idx-1]?.infoRnDay && Number(res2.data[idx-1]?.infoRnDay.toString().trim()) >= 3) { + res2.data[idx]!.rainEffectDay = 1; + } + // 이틀 전이 강우영향일(3 이상)인 경우 + if(idx > 1 && res2.data[idx-2]?.infoRnDay && Number(res2.data[idx-2]?.infoRnDay.toString().trim()) >= 3) { + res2.data[idx]!.rainEffectDay = 1; + } + } + } + + for(let idx = 0; idx < res2.data.length; idx++) { + if(res2.data[idx] && res2.data[idx]?.rainEffectDay === 1) { + if(idx > 1){ + if(res2.data[idx-1]?.infoRnDay && Number(res2.data[idx-1]?.infoRnDay.toString().trim()) >= 3) { + res2.data[idx]!.infoRnDay = res2.data[idx-1]!.infoRnDay; + } + } + if(idx > 2){ + if(res2.data[idx-2]?.infoRnDay && Number(res2.data[idx-2]?.infoRnDay.toString().trim()) >= 3) { + res2.data[idx]!.infoRnDay = res2.data[idx-2]!.infoRnDay; + } + } + } + } + + if(bscFctCd === '11200PB001R'){ + console.log('calData : ',res2.data); + } + res2.data.forEach((item: FlowDataItem) => { - if(Number(item.infoRnDay) ===0){ + + if(Number(item.rainEffectDay) === 0){ chungcunSumFlow += Number(item.inflAmnt); sumChungcunDay += 1; } + totWaterUsage += Number(item.inflAmnt); }); const avg = totWaterUsage /res2.count; @@ -250,17 +308,34 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => { ...state.SewageOccur, sewageOccurList: calData, sewageOccurCount: res.count, + isLoading : false, }:{ ...state.SewageOccur, excelList: [], - } + isLoading : false, + }, })) }, - searchSewageOccurDetailList: async (bscFctCd: string, searchYear: string) => { + searchSewageOccurDetailList: async (bscFctCd: string, searchYear: string, startYearMonth?: string, endYearMonth?: string) => { const res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear); const monthData: SewageOccurDetailProps[] = []; - let tot = 0, cnt= 0 + let tot = 0, cnt= 0; + + console.log('startYearMonth : ', startYearMonth, 'endYearMonth : ', endYearMonth); + if(startYearMonth) { + res.data = res.data.filter((item: FlowDataItem) => { + const month = item.msrDt?.substring(0, 6); + return month >= startYearMonth; + }); + } + if(endYearMonth) { + res.data = res.data.filter((item: FlowDataItem) => { + const month = item.msrDt?.substring(0, 6); + return month <= endYearMonth; + }); + } + res.data.forEach((item: FlowDataItem) => { const month = item.msrDt?.substring(4, 6); const monthIdx = month ? Number(month) - 1 : -1; @@ -284,7 +359,7 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => { 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)), + 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) * 100, estimationSewage: Math.round(item.usege*0.8 * 100) / 100 diff --git a/apps/fo/app/store/store.tsx b/apps/fo/app/store/store.tsx index 512458c90..589bc4d78 100644 --- a/apps/fo/app/store/store.tsx +++ b/apps/fo/app/store/store.tsx @@ -59,7 +59,7 @@ export const StoreZus = } ) => { return createStore()((set) => { - LoginApi.login({userId: "admin1gmail", password: "test1234!"}) + LoginApi.login({userId: "CLEANWATER", password: "gktneh12!@"}) return { ...initState, ...CommonReducer(set), diff --git a/apps/fo/app/store/underWaterInput/index.tsx b/apps/fo/app/store/underWaterInput/index.tsx index 912d8673e..589c35962 100644 --- a/apps/fo/app/store/underWaterInput/index.tsx +++ b/apps/fo/app/store/underWaterInput/index.tsx @@ -2,8 +2,15 @@ import DataForm from "@/app/components/common/DataForm"; import type { TableUpperProps } from "../dashboard"; import { getFetch } from "@/app/components/api"; import type { ExcelType, UnderWaterInputModalProps, UnderWaterProps } from "./types"; -import type { SewageOccurDetailProps } from "../sewageOccur"; export type { TableUpperProps }; + +// SewageOccurDetailProps 타입을 여기에 정의 +export type SewageOccurDetailProps = { + cnt : number, + sum : number, + yr:string, + usege:number +} /**==================================== * Store - 타입 ====================================*/ @@ -75,7 +82,7 @@ const upHeadList3:TableUpperProps[] = [ // 모달 const upHeadListUnderWaterDetail:TableUpperProps[] = [ { id: "msrDt", title: "날짜" }, - { id: "realSewageInput", title: "실제 하수유입량\n(m³/일)" }, + { id: "realSewageInput", title: "청천시 실제 하수유입량\n(m³/일)" }, { id: "sewageOccur", title: "오수발생량\n(m³/일)" }, { id: "underWaterInput", title: "지하수 유입량\n(m³/일)" }, ]; @@ -162,13 +169,15 @@ const underWaterDetailList:UnderWaterInputModalProps[] = [ ====================================*/ // API response types -interface FlowDataItem { - inflAmnt: number; +export interface FlowDataItem { + inflAmnt: number | string; infoRnDay: number; msrDt: string; + rainEffectDay? : number; + sumFlow? : number | string | ''; } -interface ApiResponse { +export interface ApiResponse { data: FlowDataItem[]; count: number; } @@ -209,6 +218,7 @@ export type UnderWaterType = { underWaterList: UnderWaterProps[]; // Changed from facilityAreaProps to ProcessAreaProps underWaterCount: number; excelList: ExcelType[]; + isLoading: boolean; }, UnderWaterDetail : { @@ -231,7 +241,8 @@ export const underWaterInitState: UnderWaterType = { upHeadList3 : upHeadList3, underWaterList : underWaterList, underWaterCount : 4, - excelList : [] + excelList : [], + isLoading : true, }, UnderWaterDetail : { @@ -250,9 +261,70 @@ const dataFormSetting=(item : UnderWaterProps)=> { export type UnderWaterStore = UnderWaterType & UnderWaterActions; +export const calRainEffectDay = (data: FlowDataItem[], weather: string) => { + // 강우영향일 계산 (강우량이 3 이상이면 무조건 강우영향일) + for(let idx = 0; idx < data.length; idx++) { + const item = data[idx]; + if(item){ + if(item.infoRnDay && Number(item.infoRnDay.toString().trim()) >= 3) { + item.rainEffectDay = 1; + } else { + item.rainEffectDay = 0; + } + } + } + + // 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정 + for(let idx = 0; idx < data.length; idx++) { + if(data[idx]) { + // 하루 전이 강우영향일(3 이상)인 경우 + if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) { + data[idx]!.rainEffectDay = 1; + } + // 이틀 전이 강우영향일(3 이상)인 경우 + if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) { + data[idx]!.rainEffectDay = 1; + } + } + } + + for(let idx = 0; idx < data.length; idx++) { + if(data[idx] && data[idx]?.rainEffectDay === 1) { + if(idx > 1){ + if(data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) { + data[idx]!.infoRnDay = data[idx-1]!.infoRnDay; + } + } + if(idx > 2){ + if(data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) { + data[idx]!.infoRnDay = data[idx-2]!.infoRnDay; + } + } + } + } + + let rtnData : FlowDataItem[] = []; + if (weather === 'ALL') { + rtnData = data; + } else if (weather === 'SUNNY') { + rtnData = data.filter((item: FlowDataItem) => item.rainEffectDay === 0); + } else { + rtnData = data.filter((item: FlowDataItem) => item.rainEffectDay === 1); + } + return rtnData; +} + export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterType) => void)=>UnderWaterActions=(set: (fn: (state: UnderWaterType) => UnderWaterType) => void) => { return { searchUnderWaterList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { + set((state: UnderWaterType) => ({ + ...state, + UnderWater: { + ...state.UnderWater, + isLoading: true, + }, + })); + const res = await fetchUnderWaterList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm); const data = res.data; const calData = await Promise.all(data.map(async (item: UnderWaterProps) => { @@ -262,8 +334,7 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy const bscFctCd = item.bscFctCd; const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as ApiResponse; - - let sumChungcunDay = 0; + const calData = calRainEffectDay(res2.data, 'SUNNY'); let chungcunSumFlow = 0; let sumSummerChungcunDay = 0; @@ -272,24 +343,25 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy let sumWinterChungcunDay = 0; let sumWinterChungcunFlow = 0; - res2.data.forEach((flowItem: FlowDataItem) => { - // 청천시 - if(Number(flowItem.infoRnDay) ===0){ - sumChungcunDay += 1; - chungcunSumFlow += Number(flowItem.inflAmnt); - - if(flowItem.msrDt.substring(4,6) ==='06' || flowItem.msrDt.substring(4,6) ==='07' || flowItem.msrDt.substring(4,6) ==='08'){ - sumSummerChungcunDay += 1; - sumSummerChungcunFlow += Number(flowItem.inflAmnt); - }else if(flowItem.msrDt.includes('01') || flowItem.msrDt.includes('02')){ - sumWinterChungcunDay += 1; - sumWinterChungcunFlow += Number(flowItem.inflAmnt); - } + calData.forEach((flowItem: FlowDataItem) => { + chungcunSumFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + + if(flowItem.msrDt.substring(4,6) ==='06' || flowItem.msrDt.substring(4,6) ==='07' || flowItem.msrDt.substring(4,6) ==='08'){ + sumSummerChungcunDay += 1; + sumSummerChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + }else if(flowItem.msrDt.substring(4,6) ==='01' || flowItem.msrDt.substring(4,6) ==='02'){ + sumWinterChungcunDay += 1; + sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; } }); - item.underWaterInputYear = Number(chungcunSumFlow==0?0:Math.round((chungcunSumFlow / sumChungcunDay) * 10) / 10) - Number(item.fctCpc * 0.6 * 0.8); - item.underWaterInputSummer = Number(sumSummerChungcunFlow==0?0:Math.round((sumSummerChungcunFlow / sumSummerChungcunDay) * 10) / 10) - Number(item.fctCpc * 0.6 * 0.8); - item.underWaterInputWinter = Number(sumWinterChungcunFlow==0?0:Math.round((sumWinterChungcunFlow / sumWinterChungcunDay) * 10) / 10) - Number(item.fctCpc * 0.6 * 0.8); + + const usage = chungcunSumFlow / calData.length; + const summerUsage = sumSummerChungcunFlow / sumSummerChungcunDay; + const winterUsage = sumWinterChungcunFlow / sumWinterChungcunDay; + + item.underWaterInputYear = Math.round((usage-(usage*0.65*0.8)) * 100) / 100; + item.underWaterInputSummer = Math.round((summerUsage-(summerUsage*0.65*0.8)) * 100) / 100; + item.underWaterInputWinter = Math.round((winterUsage-(winterUsage*0.65*0.8)) * 100) / 100; return item; })); @@ -332,17 +404,30 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy ...state.UnderWater, underWaterList: calData, underWaterCount: res.count, + isLoading : false, }:{ ...state.UnderWater, - excelList: excelDownList, - } + isLoading : false, + excelList: excelDownList + }, })) }, unserWaterModal:async (bscFctCd, searchYear)=>{ + console.log('searchYear : ', searchYear); const res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear); const monthData: SewageOccurDetailProps[] = []; - let tot = 0, cnt= 0 - res.data.forEach((item: FlowDataItem) => { + + const calData = calRainEffectDay(res.data, 'SUNNY'); + let tot = 0, cnt= 0; + + let tmpTot = 0; + + calData.forEach((item: FlowDataItem) => { + tmpTot += Number(item.inflAmnt); + }) + console.log('tmpTot : ', tmpTot/calData.length); + + calData.forEach((item: FlowDataItem) => { const month = item.msrDt?.substring(4, 6); const monthIdx = month ? Number(month) - 1 : -1; if (monthIdx >= 0) { @@ -364,7 +449,7 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy monthData.forEach((item, index) => { item.usege = item.sum/item.cnt tableData.push({ - msrDt: item.yr+'-'+(index+1>10?String(index+1):'0'+(index+1)), + msrDt: item.yr+'-'+(index+1>=10?String(index+1):'0'+(index+1)), realSewageInput:Math.round(item.usege*100) /100, sewageOccur:Math.round(item.usege*0.65*0.8 * 100) / 100, underWaterInput:Math.round((item.usege-(item.usege*0.65*0.8)) * 100) / 100, @@ -379,7 +464,6 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy }); avgWaterUsage = tot/cnt - const newData= [ { msrDt: '평균', diff --git a/apps/sn/app/(map-layout)/map/components/common/table.ts b/apps/sn/app/(map-layout)/map/components/common/table.ts index 3148b7ea2..51ef93ddf 100644 --- a/apps/sn/app/(map-layout)/map/components/common/table.ts +++ b/apps/sn/app/(map-layout)/map/components/common/table.ts @@ -28,20 +28,20 @@ export const MsSwagePplCol = [ // { id: 'lyrTypeNm', title: '레이어타입명' }, ] export const MsSwagePplCol2 = [ - { id: 'rowNumber', title: '일련번호' }, - { id: 'fcltMngNo', title: '시설 관리번호' }, - { id: 'instMngNo', title: '기관 관리번호' }, + { id: 'rowNumber', title: '일련\n번호' }, + { id: 'fcltMngNo', title: '시설\n관리번호' }, + { id: 'instMngNo', title: '기관\n관리번호' }, { id: 'instlYmd', title: '설치일자' }, // { id: 'mapshtNo', title: '도엽번호' }, - { id: 'pdmt', title: '관경(mm)' }, - { id: 'prlg', title: '연장(m)' }, - { id: 'avgGrdn', title: '평균구배(m/m)' }, - { id: 'tmptDpth', title: '시점깊이(m)' }, - { id: 'tmptMhlMngNo', title: '시점맨홀 관리번호' }, - { id: 'scendDpth', title: '종점깊이(m)' }, - { id: 'scendMhlMngNo', title: '종점맨홀 관리번호' }, - { id: 'vrtcLen', title: '세로길이(m)' }, - { id: 'wdthLen', title: '가로길이(m)' }, + { id: 'pdmt', title: '관경\n(mm)' }, + { id: 'prlg', title: '연장\n(m)' }, + { id: 'avgGrdn', title: '평균구배\n(m/m)' }, + { id: 'tmptDpth', title: '시점깊이\n(m)' }, + { id: 'tmptMhlMngNo', title: '시점맨홀\n관리번호' }, + { id: 'scendDpth', title: '종점깊이\n(m)' }, + { id: 'scendMhlMngNo', title: '종점맨홀\n관리번호' }, + { id: 'vrtcLen', title: '세로길이\n(m)' }, + { id: 'wdthLen', title: '가로길이\n(m)' }, // { id: 'fcltyShpCd', title: '시설물형태코드' }, // { id: 'fid', title: 'FID' }, // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, @@ -287,19 +287,19 @@ export const SwtrmtFcltCol = [ { id: 'ycrd', title: 'Y좌표' }, // { id: 'oprtngSttsCd', title: '가동상태코드' }, { id: 'rprs_msrc_cn', title: '대표공법내용' }, - { id: 'stty_crtr_bod', title: '법정기준생물화학적산소요구량(mg/L)' }, - { id: 'stty_crtr_toc', title: '법정기준TOC((mg/L))' }, - { id: 'stty_crtr_ss', title: '법정기준SS(mg/L)' }, - { id: 'stty_crtr_tn', title: '법정기준총질소(mg/L)' }, - { id: 'stty_crtr_tph', title: '법정기준총인(mg/L)' }, - { id: 'stty_crtr_clbcl_cnt', title: '법정기준대장균수(군수/100mL)' }, + // { id: 'stty_crtr_bod', title: '법정기준생물화학적산소요구량(mg/L)' }, + // { id: 'stty_crtr_toc', title: '법정기준TOC((mg/L))' }, + // { id: 'stty_crtr_ss', title: '법정기준SS(mg/L)' }, + // { id: 'stty_crtr_tn', title: '법정기준총질소(mg/L)' }, + // { id: 'stty_crtr_tph', title: '법정기준총인(mg/L)' }, + // { id: 'stty_crtr_clbcl_cnt', title: '법정기준대장균수(군수/100mL)' }, { id: 'bsn_nm', title: '유역명' }, // { id: 'obsrvnSptCd', title: '관측지점코드' }, ]; export const SwtrmtFcltCol2 = [ - { id: 'rowNumber', title: '일련번호' }, - { id: 'swtrmtFcltNm', title: '하수처리시설명' }, - { id: 'fcltCpct', title: '시설용량(㎥/d)' }, + { id: 'rowNumber', title: '일련\n번호' }, + { id: 'swtrmtFcltNm', title: '하수처리\n시설명' }, + { id: 'fcltCpct', title: '시설\n용량\n(㎥/d)' }, { id: 'rgnExpln', title: '지역설명' }, // { id: 'cmcnYmd', title: '준공일자' }, { id: 'oprtngStrtYmd', title: '가동개시일자' }, @@ -311,7 +311,7 @@ export const SwtrmtFcltCol2 = [ // { id: 'sggNm', title: '시군구명' }, // { id: 'sareaCd', title: '권역코드' }, { id: 'sareaNm', title: '권역명' }, - { id: 'lrgeSareaNm', title: '대권역명' }, + // { id: 'lrgeSareaNm', title: '대권역명' }, { id: 'rvrNm', title: '하천명' }, // { id: 'addr', title: '주소' }, // { id: 'dtlAddr', title: '상세주소' }, @@ -320,19 +320,19 @@ export const SwtrmtFcltCol2 = [ { id: 'dschgWtstNm', title: '방류수계명' }, // { id: 'pllnArea', title: '부지면적(m²)' }, // { id: 'mngRprtvBzentyNm', title: '관리대행업체명' }, - { id: 'swtrmtPpltnCnt', title: '하수처리인구수(인)' }, + { id: 'swtrmtPpltnCnt', title: '하수\n처리\n인구수\n(인)' }, // { id: 'prcsZoneAreaSum', title: '처리구역면적합계(m²)' }, // { id: 'xcrd', title: 'X좌표' }, // { id: 'ycrd', title: 'Y좌표' }, // { id: 'oprtngSttsCd', title: '가동상태코드' }, - { id: 'rprsMsrcCn', title: '대표공법내용' }, + { id: 'rprsMsrcCn', title: '대표\n공법\n내용' }, // { id: 'sttyCrtrBod', title: '법정기준생물화학적산소요구량(mg/L)' }, // { id: 'sttyCrtrToc', title: '법정기준TOC(mg/L)' }, // { id: 'sttyCrtrSs', title: '법정기준SS(mg/L)' }, // { id: 'sttyCrtrTn', title: '법정기준총질소(mg/L)' }, // { id: 'sttyCrtrTph', title: '법정기준총인(mg/L)' }, // { id: 'sttyCrtrClbclCnt', title: '법정기준대장균수(군수/100mL)' }, - { id: 'bsnNm', title: '유역명' }, + // { id: 'bsnNm', title: '유역명' }, // { id: 'obsrvnSptCd', title: '관측지점코드' }, ]; @@ -353,9 +353,9 @@ export const SwtrmtPrcsZoneCol2 = [ { id: 'swtrmtZoneNm', title: '하수처리구역명' }, // { id: 'swtrmt_fclt_cd', title: '하수처리시설코드' }, // { id: 'ctpv_cd', title: '시도코드' }, - { id: 'ctpvNm', title: '시도명' }, + { id: 'ctpvNm', title: '시도' }, // { id: 'sgg_cd', title: '시군구코드' }, - { id: 'sggNm', title: '시군구명' }, + { id: 'sggNm', title: '시군구' }, { id: 'swtrmtFcltNm', title: '하수처리시설명' }, ]; diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx index 52fc5523d..4542e56c9 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx @@ -12,20 +12,114 @@ const inputColumn = [ { id: "swtrmtZoneCd", title: "처리구역", type: "input" }, ]; -const Ssc = ({ featureData, isMainSsc, rainMeasureData, onSaveClick }: { +const Ssc = ({ featureData, isMainSsc, chmbrXcnts, chmbrYdnts, onSaveClick }: { featureData: any, isMainSsc?: boolean, - rainMeasureData?: any, + chmbrXcnts?: string, + chmbrYdnts?: string, onSaveClick?: () => void }) => { const [isModalOpen, setIsModalOpen] = useState(false); const [isDataLoaded, setIsDataLoaded] = useState(false); const [formData, setFormData] = useState({}); - const [mntrngsData, setMntrngsData] = useState([]); // 수량/수질 측정 정보 + const [rainMeasureData, setRainMeasureData] = useState({}); // 강우, 측정 정보 + const [mntrngsData, setMntrngsData] = useState([]); // 수량/수질측정 정보 + const [totalCount, setTotalCount] = useState(0); + const [totalDetailCount, setTotalDetailCount] = useState(0); const [selectedRowIndex, setSelectedRowIndex] = useState(-1); + const [curPage, setCurPage] = useState(1); + const [curDetailPage, setCurDetailPage] = useState(1); + const [isResetPage, setIsResetPage] = useState(false); + const [isResetDetailPage, setIsResetDetailPage] = useState(false); + const [isResetSelection, setIsResetSelection] = useState(false); + const [curIdx, setCurIdx] = useState(0); - // console.log('featureData data received:', featureData); // 추가 데이터 확인용 - // console.log('rainMeasureData received:', rainMeasureData); // 추가 데이터 확인용 + // 강우, 측정 정보 API 호출 함수 + const fetchRainMeasureData = async (chmbrXcnts: string, chmbrYdnts: string) => { + if (!chmbrXcnts || !chmbrYdnts) { + console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { chmbrXcnts, chmbrYdnts }); + return []; + } + + try { + const queryParams = new URLSearchParams({ + chmbrXcnts: chmbrXcnts, + chmbrYdnts: chmbrYdnts, + page: `${curPage - 1}`, + size: '3', + }); + + console.log('queryParams', queryParams.toString()); + console.log(`추가 데이터 API 호출 시작: v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`); + + const result = await getData(`v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`); + + console.log('추가 데이터 API 호출 성공:', result); + + const processedDataArray: any[] = result.content.map((data: any) => { + // 🎯 formatDisplayData로 기본 포맷팅 적용 + const formattedItem = formatDisplayData(data); + + // 🎯 추가 데이터 조합 + return { + ...formattedItem, + flwmtrCombined: `${data.flwmtrMesureTpEtc || '-'} / ${data.flwmtrKnd || '-'}`, + }; + }); + setRainMeasureData(processedDataArray); + setTotalCount(result?.totalElements || 0); + } catch (error) { + console.error('추가 데이터 로딩 실패:', error); + return []; + } + }; + + // 수량/수질측정 정보 API 호출 함수 + const fetchMntrngsData = async (adstDstrCd: string, manageNo: string) => { + if (!adstDstrCd || !manageNo) { + console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { adstDstrCd, manageNo }); + return []; + } + + try { + const queryParams = new URLSearchParams({ + page: `${curDetailPage - 1}`, + size: '3', + }); + + console.log(`SSC 추가 데이터 API 호출 시작: v1/onsemiro/swgRain?${queryParams.toString()}`); + + const result = await getData(`v1/onsemiro/swgRain/${adstDstrCd}/${manageNo}/mntrngs?${queryParams.toString()}`); + + console.log('SSC 추가 데이터 API 호출 성공:', result); + + // 각 아이템 전처리 + const processedDataArray = result.content.map((data: any) => { + // 기본 포맷팅 적용 + const formattedItem = formatDisplayData(data); + return { + ...formattedItem, + }; + }); + + console.log('processedDataArray', processedDataArray); + + setMntrngsData(processedDataArray); + setTotalDetailCount(result?.totalElements || 0); + } catch (error) { + console.error('추가 데이터 로딩 실패:', error); + return []; + } + }; + + + // 🎯 추가 데이터는 별도 useEffect로 비동기 로딩 + useEffect(() => { + // 강우/측정 정보 데이터 호출 + if (isMainSsc && chmbrXcnts && chmbrYdnts) { + fetchRainMeasureData(chmbrXcnts, chmbrYdnts) + } + }, [chmbrXcnts, chmbrYdnts]); const openModal = () => { setIsModalOpen(true); @@ -46,6 +140,19 @@ const Ssc = ({ featureData, isMainSsc, rainMeasureData, onSaveClick }: { } }, [featureData]); + // featureData가 변경될 때 formData 초기화 + useEffect(() => { + // showTable이 true일 때만 fetch (최초 렌더 방지) + setIsResetPage(false); + setIsResetDetailPage(true); + if (chmbrXcnts && chmbrYdnts) fetchRainMeasureData(chmbrXcnts, chmbrYdnts); + }, [curPage]); + + // 페이지 변경 시마다 데이터 fetch + useEffect(() => { + if (chmbrXcnts && chmbrYdnts) fetchMntrngsData(chmbrXcnts, chmbrYdnts); + }, [curDetailPage]); + // 폼 데이터가 변경될 때 호출될 핸들러 const handleFormDataChange = (newFormData: any) => { setFormData(newFormData); @@ -62,91 +169,39 @@ const Ssc = ({ featureData, isMainSsc, rainMeasureData, onSaveClick }: { // 테이블 셀 클릭 핸들러 추가 const handleCellClick = async (index: number | undefined, headId: string) => { if (index !== undefined && rainMeasureData) { - const data = await fetchMntrngsData(rainMeasureData[index].adstDstrCd, rainMeasureData[index].manageNo); - - setMntrngsData(data); + await fetchMntrngsData(rainMeasureData[index].adstDstrCd, rainMeasureData[index].manageNo); setSelectedRowIndex(index); } }; - // 🎯 추가 데이터 API 호출 함수 (독립적으로 실행) - const fetchMntrngsData = useCallback(async (adstDstrCd: string, manageNo: string) => { - if (!adstDstrCd || !manageNo) { - console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { adstDstrCd, manageNo }); - return []; - } - - try { - const queryParams = new URLSearchParams({ - pageable: `{}`, - }); - - console.log(`SSC 추가 데이터 API 호출 시작: v1/onsemiro/swgRain?${queryParams.toString()}`); - - const result = await getData(`v1/onsemiro/swgRain/${adstDstrCd}/${manageNo}/mntrngs?${queryParams.toString()}`); - - console.log('SSC 추가 데이터 API 호출 성공:', result); - - // 🎯 result가 페이지네이션 객체인 경우 content 배열 추출 - let dataArray: any[] = []; - if (result && typeof result === 'object' && 'content' in result && Array.isArray(result.content)) { - dataArray = result.content; - } else if (Array.isArray(result)) { - dataArray = result; - } else { - console.warn('예상치 못한 API 응답 형식:', result); - return []; - } - - // 🎯 각 아이템을 전처리하여 반환 - const processedDataArray = dataArray.map((data: any) => { - // 🎯 formatDisplayData로 기본 포맷팅 적용 - const formattedItem = formatDisplayData(data); - - // 🎯 추가 데이터 조합 - return { - ...formattedItem, - }; - }); - - console.log('processedDataArray', processedDataArray); - - return processedDataArray; - } catch (error) { - console.error('추가 데이터 로딩 실패:', error); - return []; - } - }, []); - const renderModalBody = () => (
{/* 강우정보 테이블 */} {/* 측정정보 테이블 */} {/* 커스텀 헤더 */} @@ -168,14 +223,12 @@ const Ssc = ({ featureData, isMainSsc, rainMeasureData, onSaveClick }: { {/* 수량/수질측정 정보 테이블 */}
) diff --git a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx similarity index 78% rename from apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx rename to apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx index 5259fdab6..679122d6b 100644 --- a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx @@ -5,13 +5,13 @@ import { VerticalTable } from "@/components/ui/verticalTable"; 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 InfilChart from './components/popupComponent/chart/infilChart'; -import RdiiChart from './components/popupComponent/chart/rdiiChart'; -import { useInfilChartModalStore, useRdiiChartModalStore } from "./components/popupComponent/chartModalStore"; +import { getLayerContentComponent } from "../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 "../common/table"; +import InfilChart from './chart/infilChart'; +import RdiiChart from './chart/rdiiChart'; +import { useInfilChartModalStore, useRdiiChartModalStore } from "./chartModalStore"; import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue'; -import { codeMapper } from "./components/common/codeMapper"; +import { codeMapper } from "../common/codeMapper"; import { searchUpperPpls } from '@common/business_components/ui/map/Gis'; import LoadingOverlay from '@/components/ui/LoadingBar'; @@ -33,9 +33,10 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, // 🎯 InfilChart 및 RdiiChart 관련 상태 추가 const { setIsOpen: setIsModalInfil } = useInfilChartModalStore(); const { setIsOpen: setIsModalRdii } = useRdiiChartModalStore(); - const [curPage, setCurPage] = useState(1); // 현재 페이지 상태 const [isClicked, setIsClicked] = useState(true); // 클릭 여부 상태 const [isLoading, setIsLoading] = useState(false); // 로딩 상태 + const [chmbrXcnts, setChmbrXcnts] = useState(); // 로딩 상태 + const [chmbrYdnts, setChmbrYdnts] = useState(); // 로딩 상태 // 🎯 관로관리번호 추출 const pplMngNo = featureData?.values_?.fclt_mng_no || ""; @@ -263,18 +264,9 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, data: { ...processedFormattedData } })); - // 강우/측정 정보 데이터 호출 - if (tableData?.chmbr_xcnts && tableData?.chmbr_ydnts) { - fetchRainMeasureData(tableData.chmbr_xcnts, tableData.chmbr_ydnts) - .then(response => { - console.log('additionalResponse', response); - setRainMeasureData(response || []); - }) - .catch(error => { - console.error('추가 데이터 로딩 실패:', error); - setRainMeasureData([]); - }); - } + setChmbrXcnts(data.chmbr_xcnts); + setChmbrYdnts(data.chmbr_ydnts); + break; default: break; @@ -317,76 +309,6 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, fetchData(); }, [featureId, processedData]); - // 🎯 추가 데이터 API 호출 함수 - const fetchRainMeasureData = useCallback(async (chmbrXcnts: string, chmbrYdnts: string) => { - if (!chmbrXcnts || !chmbrYdnts) { - console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { chmbrXcnts, chmbrYdnts }); - return []; - } - - try { - const queryParams = new URLSearchParams({ - chmbrXcnts: chmbrXcnts, - chmbrYdnts: chmbrYdnts, - pageable: `{}`, - }); - - console.log(`추가 데이터 API 호출 시작: v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`); - - const result = await getData(`v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`); - - console.log('추가 데이터 API 호출 성공:', result); - - // 🎯 result가 페이지네이션 객체인 경우 content 배열 추출 - let dataArray: any[] = []; - if (result && typeof result === 'object' && 'content' in result && Array.isArray(result.content)) { - dataArray = result.content; - } else if (Array.isArray(result)) { - dataArray = result; - } else { - console.warn('예상치 못한 API 응답 형식:', result); - return []; - } - - // 🎯 각 아이템을 전처리하여 반환 - const processedDataArray = dataArray.map((data: any) => { - // 🎯 formatDisplayData로 기본 포맷팅 적용 - const formattedItem = formatDisplayData(data); - - // 🎯 추가 데이터 조합 - return { - ...formattedItem, - flwmtrCombined: `${data.flwmtrMesureTpEtc || '-'} / ${data.flwmtrKnd || '-'}`, - }; - }); - - return processedDataArray; - } catch (error) { - console.error('추가 데이터 로딩 실패:', error); - return []; - } - }, []); - - // 🎯 추가 데이터는 별도 useEffect로 비동기 로딩 - useEffect(() => { - if (layerNm === '중점우수토실' && featureData?.values_) { - const data = featureData.values_; - - if (data?.chmbr_xcnts && data?.chmbr_ydnts) { - // 🎯 추가 데이터를 비동기로 로딩 (UI 블로킹 없음) - fetchRainMeasureData(data.chmbr_xcnts, data.chmbr_ydnts) - .then(response => { - console.log('추가 데이터 로딩 완료:', response); - setRainMeasureData(response || []); - }) - .catch(error => { - console.error('추가 데이터 최종 로딩 실패:', error); - setRainMeasureData([]); - }); - } - } - }, [layerNm, featureData?.values_, fetchRainMeasureData]); - // 저장 시 모달 띄우기 const handleSaveClick = () => { setIsModalOpen(true); // 모달 열기 @@ -482,45 +404,47 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, )} 정보
관리번호 : {layerSpecificNm} -
- {/* 🎯 하수관로일 때만 Infil/RDII 버튼 표시 */} - {layerNm === '하수관로' && ( - <> - - - - )} - {layerNm === '하수맨홀' && ( - <> -
+
+ {/* 🎯 하수관로일 때만 Infil/RDII 버튼 표시 */} + {layerNm === '하수관로' && ( + <> + + + + )} + {layerNm === '하수맨홀' && ( + <> + - - )} -
+ > + 상류관로 보기 + + + )}
diff --git a/apps/sn/app/(map-layout)/map/page.tsx b/apps/sn/app/(map-layout)/map/page.tsx index 2dbbcdd1a..f30cca0a6 100644 --- a/apps/sn/app/(map-layout)/map/page.tsx +++ b/apps/sn/app/(map-layout)/map/page.tsx @@ -5,7 +5,9 @@ import { getData } from "../../components/lib/api"; import { useCallback, useEffect, useRef, useState } from "react"; import GisApp from "@common/business_components/ui/map/lib/gis.core"; import SearchModal from "./searchModal/searchModal"; -import FeatureClickEventPopup from "./featureClickEventPopup"; +import FeatureClickEventPopup from "./components/popupComponent/featureClickEventPopup"; +import useStore from "../../store/useStore"; +import { SearchBar } from "./searchBar/searchBar"; // 타입 정의 추가 export type LyrStngProps = { @@ -38,6 +40,13 @@ const Map = () => { const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태 const [isSearchModalOpen, setIsSearchModalOpen] = useState(false); // SearchModal 열림 상태 const [featureData, setFeatureData] = useState(null); // 선택된 피쳐 데이터 + const { fetchCtpvData, fetchSggData } = useStore(); + + // 시도, 시군구 호출 + useEffect(() => { + fetchCtpvData(); + fetchSggData(); + }, [fetchCtpvData, fetchSggData]); const fetchData = async () => { try { @@ -130,6 +139,7 @@ const Map = () => { isOpen={isOpen} isSearchModalOpen={isSearchModalOpen} onCheckedLayersChange={undefined} + searchBar={SearchBar} />
); diff --git a/apps/sn/app/(map-layout)/map/searchBar/searchBar.tsx b/apps/sn/app/(map-layout)/map/searchBar/searchBar.tsx new file mode 100644 index 000000000..b57e66c24 --- /dev/null +++ b/apps/sn/app/(map-layout)/map/searchBar/searchBar.tsx @@ -0,0 +1,83 @@ +"use client"; +import { + SearchDiv, + SearchFormLeft, + SelectBox, + type SelectDataType, +} from "@common/business_components/ui"; +import { useCallback, useEffect, useState } from "react"; + +export function SearchBar() { + const [sidoValue, setSidoValue] = useState(""); + const [sigunValue, setSigunValue] = useState(""); + const [filteredSigunData, setFilteredSigunData] = useState([ + { text: "시도 선택", val: "0" }, + ]); + + const initializeSigunData = useCallback((sidoCd: string) => { + if (sidoCd === "0") { + setSigunValue("0"); + setFilteredSigunData([{ text: "시도 선택", val: "0" }]); + } else { + const newFilteredData = [ + { text: "데이터", val: "0" }, + // ...Common.selectSigunData.filter( + // (item: SelectDataType) => item.val.substring(0, 2) === sidoCd, + // ), + ]; + setSigunValue("0"); + setFilteredSigunData(newFilteredData); + } + }, []); + const onSelectValue = useCallback( + (val: string, type: string) => { + switch (type) { + case "ctpvCd": + initializeSigunData(val); + setSidoValue(val); + break; + case "sggCd": + setSigunValue(val); + } + }, + [initializeSigunData], + ); + + return ( + <> +
+
+
+
+ onSelectValue(val.toString(), "ctpvCd")} + value={sidoValue || /* Common.selectSidoData[0]?.val || */ ""} + /> + onSelectValue(val.toString(), "sggCd")} + value={sigunValue} + /> + onSelectValue(val.toString(), "sggCd")} + value={sigunValue} + /> +
+
+
+
+ + ); +} diff --git a/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx b/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx index 89d1db591..57afc22c7 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx @@ -39,7 +39,9 @@ interface BasicTabProps { // setTableCount?: (count: number) => void; setBasicType: (type: string) => void; setCity: (city: number) => void; + setCtpvName: (name: string) => void; setSgg: (sgg: number) => void; + setSggName: (name: string) => void; setYearFilter: (filter: { start: string; end: string }) => void; setStart1: (value: string) => void; setStart2: (value: string) => void; @@ -68,7 +70,9 @@ const BasicTab: React.FC = ({ // setTableCount, setBasicType, setCity, + setCtpvName, setSgg, + setSggName, setYearFilter, setStart1, setStart2, @@ -78,14 +82,15 @@ const BasicTab: React.FC = ({ setVar2, }) => { return ( -
+
{/* 구분 */}
+ setBasicType(String(value)) @@ -101,12 +106,16 @@ const BasicTab: React.FC = ({ var1={var1} var2={var2} start1={start1} + start2={start2} end1={end1} + end2={end2} yearFilter={yearFilter} setVar1={setVar1} setVar2={setVar2} setStart1={setStart1} + setStart2={setStart2} setEnd1={setEnd1} + setEnd2={setEnd2} setYearFilter={setYearFilter} handleSearch={handleSearch} /> @@ -119,12 +128,18 @@ const BasicTab: React.FC = ({ start2={start2} end1={end1} end2={end2} + city={city} + sgg={sgg} yearFilter={yearFilter} setVar1={setVar1} setStart1={setStart1} setStart2={setStart2} setEnd1={setEnd1} setEnd2={setEnd2} + setCity={setCity} + setCtpvName={setCtpvName} + setSgg={setSgg} + setSggName={setSggName} setYearFilter={setYearFilter} handleSearch={handleSearch} /> diff --git a/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx b/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx index c880ed1a4..9a46e2bf8 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx @@ -12,11 +12,9 @@ import React from 'react'; // { val: "inspection", text: "점검 및 진단" }, // ]; export const WORK_TYPES = [ - { val: "200", text: "보수 및 갱신(개대체)" }, - { val: "201", text: "보수 및 갱신(유지보수)" }, - { val: "204", text: "보수 및 갱신(단순보수)" }, - { val: "100", text: "점검 및 진단" }, - { val: "203", text: "청소 및 준설" }, + { val: "['200', '201', '204']", text: "보수 및 갱신" }, + { val: "['100']", text: "점검 및 진단" }, + { val: "['203']", text: "청소 및 준설" }, ]; // const BIZ_SE_CD = useBizByFcltStore(state => state.BIZ_SE_CD); export const BIZ_SE_CD = [ @@ -113,12 +111,13 @@ const OperationTab: React.FC = ({ setYearFilter, }) => { return ( -
+
+ ({ val: w.val, text: w.text, @@ -129,12 +128,18 @@ const OperationTab: React.FC = ({ />
- + { setVar1(e.target.value); }} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} /> = ({ startLabel="수행기간" endLabel="" /> + { diff --git a/apps/sn/app/(map-layout)/map/searchModal/reportTab.tsx b/apps/sn/app/(map-layout)/map/searchModal/reportTab.tsx index 48399ac22..5ca3f7059 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/reportTab.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/reportTab.tsx @@ -1,6 +1,6 @@ 'use client'; import React, { useEffect, useState } from 'react'; -import { Button } from '@common/components'; +import { Button, Label } from '@common/components'; import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox'; import { SelectBox, UiTable } from '@common/business_components/ui'; import LoadingOverlay from '@/components/ui/LoadingBar'; @@ -165,32 +165,28 @@ const ReportTab: React.FC = ({ open }) => { return ( <> -
+
- 시도 + + setSigungu(String(val))} selectContentClass="z-[101]" />
- {/* - { setGubun(e.target.value); }} - /> */} - 보고서 구분 + setReportGubun(String(val))} selectContentClass="z-[101]" labelClass='whitespace-nowrap text-xl text-gray-600 pr-2' /> diff --git a/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx b/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx index 622fbd63f..b453ba20f 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx @@ -63,8 +63,10 @@ const SearchModal: React.FC = ({ const [isResetSelection, setIsResetSelection] = useState(false); const [isResetDetailSelection, setIsResetDetailSelection] = useState(false); const [detailBizId, setDetailBizId] = useState(0); - const [city, setCity] = useState(0); - const [sgg, setSgg] = useState(0); + const [city, setCity] = useState(0); + const [ctpvName, setCtpvName] = useState(''); + const [sgg, setSgg] = useState(0); + const [sggName, setSggName] = useState(''); const [ctpvCd, setCtpvCd] = useState('0'); // 하수정비기본계획 report const [sigungu, setSigungu] = useState('0'); // 하수정비기본계획 report const [gubun, setGubun] = useState(""); // 하수정비기본계획 report @@ -81,7 +83,7 @@ const SearchModal: React.FC = ({ const [yearFilter, setYearFilter] = useState({ start: "", end: "" }); const [filteredSiguns, setFilteredSiguns] = useState([{ val: '0', text: '전체', sido: '0' }]); - + // 오늘 날짜 구하기 const today = new Date(); const todayYear = today.getFullYear().toString(); @@ -106,11 +108,9 @@ const SearchModal: React.FC = ({ const dynamicHeadlist2: { id: string, title: string }[] = useMemo(() => { if (activeTab === 'operation') { - if (workType === '200') return operationMaintenanceTableHeadlist; - if (workType === '201') return operationMaintenanceTableHeadlist; - if (workType === '204') return operationMaintenanceTableHeadlist; - if (workType === '100') return operationCleaningTableHeadlist; - if (workType === '203') return operationInspectionTableHeadlist; + if (workType === WORK_TYPES[0]?.val) return operationMaintenanceTableHeadlist; + if (workType === WORK_TYPES[1]?.val) return operationCleaningTableHeadlist; + if (workType === WORK_TYPES[2]?.val) return operationInspectionTableHeadlist; } return []; @@ -179,7 +179,7 @@ const SearchModal: React.FC = ({ setIsLoading(true); // 로딩 시작 setIsResetSelection(true); // 선택 초기화 setIsResetDetailSelection(true); // 선택 초기화 - + try { let cqlFilters: string[] = []; if (activeTab === 'basic') { @@ -247,8 +247,8 @@ const SearchModal: React.FC = ({ RequestDTO.fromflfmtEndYmd = startDate; RequestDTO.toflfmtEndYmd = endDate; - - RequestDTO.bizSeCd = workType; + // JSON.parse 사용으로 문자열 -> 배열 변환 + RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"')); const params = new URLSearchParams(RequestDTO).toString(); @@ -263,7 +263,7 @@ const SearchModal: React.FC = ({ const matched = BIZ_TY_CD.find(code => code.lwpoCd === item.bizTyCd); return { ...formattedItem, - rowNumber: (curPage - 1) * 4 + index + 1, // 1부터 시작하는 일련번호 추가 + rowNumber: (curPage - 1) * 5 + index + 1, // 1부터 시작하는 일련번호 추가 bizTyCd: matched ? matched.lwpoCdNm : item.bizTyCd, }; }); @@ -272,8 +272,7 @@ const SearchModal: React.FC = ({ setTableCount(res.totalElements || 0); setDetailTableData([]); setDetailTableCount(0); - - } + } setShowTable(true); } catch (err) { @@ -344,13 +343,17 @@ const SearchModal: React.FC = ({ cqlFilters.push(`fclt_cpct BETWEEN ${start1} AND ${end1}`); else if (start1) cqlFilters.push(`fclt_cpct >= ${start1}`); else if (end1) cqlFilters.push(`fclt_cpct <= ${end1}`); - // 처리구역 면적 - if (start2 && end2) - cqlFilters.push(`prcsZoneAreaSum BETWEEN ${start2} AND ${end2}`); - else if (start2) cqlFilters.push(`prcsZoneAreaSum >= ${start2}`); - else if (end2) cqlFilters.push(`prcsZoneAreaSum <= ${end2}`); - // 하수처리시설명 - if (var1) cqlFilters.push(`swtrmt_fclt_nm ILIKE '%${var1}%'`); + + // 시도 + if (ctpvName) cqlFilters.push(`ctpv_nm ILIKE '%${ctpvName}%'`); + if (sggName) cqlFilters.push(`sgg_nm ILIKE '%${sggName}%'`); + // // 처리구역 면적 + // if (start2 && end2) + // cqlFilters.push(`prcsZoneAreaSum BETWEEN ${start2} AND ${end2}`); + // else if (start2) cqlFilters.push(`prcsZoneAreaSum >= ${start2}`); + // else if (end2) cqlFilters.push(`prcsZoneAreaSum <= ${end2}`); + // // 하수처리시설명 + // if (var1) cqlFilters.push(`swtrmt_fclt_nm ILIKE '%${var1}%'`); return cqlFilters; }; // 하수처리구역용 CQL 필터 생성 @@ -446,12 +449,7 @@ const SearchModal: React.FC = ({ // 조회 버튼 클릭 시 1페이지로 이동 및 데이터 초기화 const handleSearch = () => { - setCurPage(1); // 페이지를 1로 초기화 - // setDetailCurPage(1); // 페이지를 1로 초기화 - // setIsResetPage(false); // 페이지를 초기화 - // setIsResetDetailPage(true); // 디테일 페이지를 초기화 - // setIsResetSelection(true); // 선택 초기화 - // setIsResetDetailSelection(true); // 선택 초기화 + setCurPage(1); // 페이지를 1로 초기화 fetchFilteredData(); setIsResetPage(true); // 페이지를 초기화 setIsResetDetailPage(true); // 디테일 페이지를 초기화 @@ -484,8 +482,11 @@ const SearchModal: React.FC = ({ bizId: tableData[index % 5].bizId, }; + RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"')); + const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`); console.log('운영정보 cellClick 데이터:', res); + console.log('운영정보 cellClick.data:', res.data); console.log('운영정보 length:', res.data.length); const mappedData = (res.data || []).map((item: any, detailIndex: number) => { @@ -495,12 +496,14 @@ const SearchModal: React.FC = ({ const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item.mqltCd.trim()); return { ...formattedItem, - rowNumber: (detailCurPage - 1) * 4 + detailIndex + 1, + rowNumber: (detailCurPage - 1) * 5 + detailIndex + 1, usgCd: usgCdObj ? usgCdObj.text : item.usgCd, mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd, }; }); + console.log('운영정보 cellClick mappedData:', mappedData); + setDetailTableData(mappedData); setDetailTableCount(res.count || 0); } catch (error) { @@ -531,7 +534,7 @@ const SearchModal: React.FC = ({ const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item.mqltCd.trim()); return { ...formattedItem, - rowNumber: (detailCurPage - 1) * 4 + detailIndex + 1, + rowNumber: (detailCurPage - 1) * 5 + detailIndex + 1, usgCd: usgCdObj ? usgCdObj.text : item.usgCd, mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd, }; @@ -546,7 +549,7 @@ const SearchModal: React.FC = ({ } } }; - + const renderBody = () => ( <> @@ -560,63 +563,64 @@ const SearchModal: React.FC = ({ onValueChange={(value: string) => setActiveTab(value)} > - {/* 각각의 탭 영역 */} - {/* 기본정보 탭 */} - {activeTab === 'basic' && ( - - )} - {/* 운영정보 탭 */} - {activeTab === 'operation' && ( - - )} - {/* 하수도정비기본계획보고서 탭 */} - {activeTab === 'report' && ( - - )} - {/* */} - + {/* 각각의 탭 영역 */} + {/* 기본정보 탭 */} + {activeTab === 'basic' && ( + + )} + {/* 운영정보 탭 */} + {activeTab === 'operation' && ( + + )} + {/* 하수도정비기본계획보고서 탭 */} + {activeTab === 'report' && ( + + )} + {/* */} + {/* 📋 결과 리스트 */} - {/* 기본정보 탭, 하수도정비기본계획보고서 탭 */} - {(activeTab === 'basic' ) && ( + {/* 하수도정비기본계획보고서 탭 */} + {activeTab === 'basic' && (
- {/* 테이블2 영역 (가로/세로 스크롤 가능) */}
= ({
+ {/* 테이블2 영역 */}
= ({ handleSearch, }) => { - const handleEnterKey = (e: React.KeyboardEvent) => { - if (e.key === 'Enter') { - handleSearch(); - } - }; - return (
@@ -55,10 +49,11 @@ const SwageMhl: React.FC = ({ endLabel="" /> {/* 용도 */} + { @@ -67,7 +62,7 @@ const SwageMhl: React.FC = ({ selectContentClass="z-[101]" /> {/* 하수맨홀 구경 */} - + = ({ const val = e.target.value.replace(/[^0-9]/g, ""); setStart1(val); }} - onKeyDown={handleEnterKey} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} /> ~ = ({ const val = e.target.value.replace(/[^0-9]/g, ""); setEnd1(val); }} - onKeyDown={handleEnterKey} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} /> {/* 조회 버튼 */}
diff --git a/apps/sn/app/(map-layout)/map/searchModal/swagePmstn.tsx b/apps/sn/app/(map-layout)/map/searchModal/swagePmstn.tsx index 9543cf218..ee3886e90 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/swagePmstn.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/swagePmstn.tsx @@ -32,12 +32,6 @@ const SwagePmstn: React.FC = ({ handleSearch, }) => { - const handleEnterKey = (e: React.KeyboardEvent) => { - if (e.key === 'Enter') { - handleSearch(); - } - }; - return (
@@ -50,7 +44,7 @@ const SwagePmstn: React.FC = ({ endLabel="" /> {/* 일일처리용량 - 오수맨홀 */} - + = ({ const val = e.target.value.replace(/[^0-9]/g, ""); setStart1(val); }} - onKeyDown={handleEnterKey} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} /> ~ = ({ const val = e.target.value.replace(/[^0-9]/g, ""); setEnd1(val); }} - onKeyDown={handleEnterKey} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} /> {/* 양수능력 - 우수맨홀 */} - + = ({ const val = e.target.value.replace(/[^0-9]/g, ""); setStart2(val); }} - onKeyDown={handleEnterKey} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} /> ~ = ({ const val = e.target.value.replace(/[^0-9]/g, ""); setEnd2(val); }} - onKeyDown={handleEnterKey} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} /> {/* 조회 버튼 */}
diff --git a/apps/sn/app/(map-layout)/map/searchModal/swagePpl.tsx b/apps/sn/app/(map-layout)/map/searchModal/swagePpl.tsx index 7a22f3834..f729ab6eb 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/swagePpl.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/swagePpl.tsx @@ -10,12 +10,16 @@ interface SwagePplProps { var1: string; var2: string; start1: string; + start2: string; end1: string; + end2: string; yearFilter: { start: string; end: string }; setVar1: (value: string) => void; setVar2: (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; } @@ -24,22 +28,20 @@ const SwagePpl: React.FC = ({ var1, var2, start1, + start2, end1, + end2, yearFilter, setVar1, setVar2, setStart1, + setStart2, setEnd1, + setEnd2, setYearFilter, handleSearch, }) => { - const handleEnterKey = (e: React.KeyboardEvent) => { - if (e.key === 'Enter') { - handleSearch(); - } - }; - return (
@@ -58,10 +60,11 @@ const SwagePpl: React.FC = ({ endLabel="" /> {/* 용도 */} + { @@ -70,10 +73,11 @@ const SwagePpl: React.FC = ({ selectContentClass="z-[101]" /> {/* 재질 */} + { @@ -82,32 +86,7 @@ const SwagePpl: React.FC = ({ selectContentClass="z-[101]" /> {/* 관경 */} - - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ""); - setVar1(val); - }} - onKeyDown={handleEnterKey} - /> - ~ - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ""); - setEnd1(val); - }} - onKeyDown={handleEnterKey} - /> - {/* 연장 */} - + = ({ const val = e.target.value.replace(/[^0-9]/g, ""); setStart1(val); }} - onKeyDown={handleEnterKey} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} /> ~ = ({ const val = e.target.value.replace(/[^0-9]/g, ""); setEnd1(val); }} - onKeyDown={handleEnterKey} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} + /> + {/* 연장 */} + + { + // 숫자만 입력 허용 + const val = e.target.value.replace(/[^0-9]/g, ""); + setStart2(val); + }} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} + /> + ~ + { + // 숫자만 입력 허용 + const val = e.target.value.replace(/[^0-9]/g, ""); + setEnd2(val); + }} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} /> {/* 조회 버튼 */}
diff --git a/apps/sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx b/apps/sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx index 4adfeb865..53fd312dc 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx @@ -1,8 +1,10 @@ // 하수처리시설 +import React from 'react'; import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox'; import { Button, Input, Label } from '@common/components'; -import React from 'react'; +import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox'; + interface SwagePrcsFcltProps { var1: string; @@ -10,42 +12,53 @@ interface SwagePrcsFcltProps { start2: string; end1: string; end2: string; + city: number; + sgg: number; 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; + setCity: (value: number) => void; + setCtpvName: (name: string) => void; + setSgg: (value: number) => void; + setSggName: (name: string) => void; setYearFilter: (filter: { start: string; end: string }) => void; handleSearch: () => void; } const SwagePrcsFclt: React.FC = ({ - var1, start1, - start2, end1, - end2, + city, + sgg, yearFilter, - setVar1, setStart1, - setStart2, setEnd1, - setEnd2, + setCity, + setCtpvName, + setSgg, + setSggName, setYearFilter, handleSearch, }) => { - const handleEnterKey = (e: React.KeyboardEvent) => { - if (e.key === 'Enter') { - handleSearch(); - } - }; - return (
- {/* 가동개시일자 */}
+ { + setCity(sidoId); + setSgg(0); + }} + onSigunguChange={setSgg} + setCtpvName={setCtpvName} + setSggName={setSggName} + /> + {/* 가동개시일자 */} = ({ endLabel="" /> {/* 시설용량 */} - + = ({ const val = e.target.value.replace(/[^0-9]/g, ""); setStart1(val); }} - onKeyDown={handleEnterKey} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} /> ~ = ({ const val = e.target.value.replace(/[^0-9]/g, ""); setEnd1(val); }} - onKeyDown={handleEnterKey} - /> - {/* 처리구역 면적 */} - - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ""); - setStart2(val); + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } }} - onKeyDown={handleEnterKey} - /> - ~ - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ""); - setEnd2(val); - }} - onKeyDown={handleEnterKey} - /> - {/* 하수처리시설명 */} - - { - setVar1(e.target.value); - }} - onKeyDown={handleEnterKey} /> {/* 조회 버튼 */}
diff --git a/apps/sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx b/apps/sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx index fd49233bb..abeec54b9 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx @@ -28,12 +28,6 @@ const swagePrcsZone: React.FC = ({ handleSearch, }) => { - const handleEnterKey = (e: React.KeyboardEvent) => { - if (e.key === 'Enter') { - handleSearch(); - } - }; - return (
@@ -46,17 +40,7 @@ const swagePrcsZone: React.FC = ({ }} onSigunguChange={setSgg} /> - - { - setVar1(e.target.value); - }} - onKeyDown={handleEnterKey} - /> - + = ({ onChange={(e) => { setVar2(e.target.value); }} - onKeyDown={handleEnterKey} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} + /> + + { + setVar1(e.target.value); + }} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} /> {/* 조회 버튼 */}
diff --git a/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx b/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx index 51ac4d291..d825b34fa 100644 --- a/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx +++ b/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx @@ -218,23 +218,24 @@ const BaseLayout = ({
{showDatePicker && ( // showDatePicker 값에 따라 DatePicker 렌더링 <> - + { // aplcnYm이 없으면 현재 연월을 기본값으로 설정 const now = new Date(); const year = now.getFullYear(); - const month = String(now.getMonth() + 1).padStart(2, '0'); - return `${year}${month}`; + // const month = String(now.getMonth() + 1).padStart(2, '0'); + // return `${year}${month}`; + return `${year}01`; })(), // yyyyMM 형식 onChange: (value: string) => { setAplcnYmFrom?.(value); // string 값을 직접 전달 } }} - selectClass="ml-5 w-[100px]" + selectClass="ml-8 w-[100px]" startYear={1900} // 시작 연도 설정 /> - ~ + ~ { // aplcnYm이 없으면 현재 연월을 기본값으로 설정 @@ -247,7 +248,7 @@ const BaseLayout = ({ setAplcnYmTo?.(value); // string 값을 직접 전달 } }} - selectClass="w-[100px]" + selectClass="w-[100px] mr-8" startYear={1900} // 시작 연도 설정 /> @@ -258,21 +259,40 @@ const BaseLayout = ({ setRtnEnvPartSidoValue={(val) => setCtpvCd?.(val)} setRtnEnvPartSigunValue={setSigungu} // 선택된 시군구 값을 받을 콜백 함수 전달 > - onSwageTreatmentPlantChange?.(val)} selectContentClass="z-[101]" /> + + onSwageTreatmentPlantChange?.(val)} + selectContentClass="z-[101]" + /> {/* onSwageProcessingZoneChange?.(val)} selectContentClass="z-[101]" /> */} - {selectBox?.searchChk ? : null} + {selectBox?.searchChk && ( +
+ +
+ )}

{titleName.firstCardTitle}

- {graphBtn ? : null} + {graphBtn && ( + + )} {/* 그래프 있을 시 */} - {graphBtn ? : null} + {graphBtn && ( + + )} {/* 분석 버튼 */} - {analysisBtn ? : null} + {analysisBtn && ( + + )}
@@ -284,19 +304,23 @@ const BaseLayout = ({
- { - children?.[1] != null ? -
+ {children?.[1] != null && ( + +

{titleName?.secondCardTitle}

-
- {graphBtn ? : null} +
+ {graphBtn && ( + + )} {/* 그래프 있을 시 */} - {graphBtn ? : null} + {graphBtn && ( + + )}
{children?.[1]}
- : null - } + + )} ) } diff --git a/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx b/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx index 4e8492f47..99542f5bf 100644 --- a/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx @@ -47,7 +47,7 @@ interface ApiSelectOption { } const IrSetting = () => { - const [input1, setInput1] = useState(''); + const [input1, setInput1] = useState('0.8'); // 오수전환율 초기값 const [input2, setInput2] = useState(''); const [select1, setSelect1] = useState('0'); // 환경청코드 const [select2, setSelect2] = useState('0'); // 시도코드 @@ -387,10 +387,7 @@ const IrSetting = () => { accept={".xls, .xlsx, .xlsm, .xltx"} fileIdx={2} /> - + {/* 연월 선택 라이브러리로 수정 필요 */} { setSelectedDate(value); } }} - selectClass="ml-5 w-[150px]" + selectClass="ml-5 w-[225px]" startYear={1900} // 시작 연도 설정 /> - + { @@ -430,18 +424,23 @@ const IrSetting = () => { setInput1(newValue); }} - className="ml-5 h-[3.2rem] text-center text-xl w-[150px]" + className="ml-5 h-[3.2rem] text-center text-xl w-[225px]" placeholder="예: 0.75" /> - + setInput2(e.target.value)} - className="ml-5 h-[3.2rem] text-center text-xl w-[150px]" /> + className="ml-5 h-[3.2rem] text-center text-xl w-[225px]" + placeholder='세부 분석정보 입력' + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleAnalysisClick(); + } + }} + />
diff --git a/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx b/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx index 08aa84e34..9bf381b97 100644 --- a/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx @@ -61,8 +61,8 @@ const defaultFormValues: FormSchemaType = { sggCd: "", swageTmplntCd: "", swtrmtZoneCd: "", - rtkSource: "출처", - rdiiArea: "123", // 문자열로 기본값 설정 + rtkSource: "", + rdiiArea: "", // 문자열로 기본값 설정 unitFactors: [ { response: "Short-Term", R: "0.040", T: "0.5", K: "1" }, // 문자열로 기본값 설정 { response: "Medium-Term", R: "0.005", T: "1", K: "2" }, @@ -78,7 +78,7 @@ const defaultFormValues: FormSchemaType = { aplcnYm: "", rate: "0.8", // 문자열로 기본값 설정 // rainFile: undefined, - analysisInfo: "test 분석정보", + analysisInfo: "", date: (() => { // 현재 연월을 yyyyMM 형식으로 설정 const now = new Date(); const year = now.getFullYear(); @@ -501,7 +501,7 @@ export default function RTKForm() { form.setValue("rate", newValue, { shouldValidate: true }); // form의 rate 필드에 설정 }} className="h-12 text-center text-xl w-[225px] ml-5" - placeholder="예: 0.75" + placeholder="0 ~ 1 사이의 값 입력" /> @@ -512,17 +512,24 @@ export default function RTKForm() { form.setValue("date", value, { shouldValidate: true }); // form의 date 필드에 직접 설정 } }} - selectClass="ml-5 w-[200px]" + selectClass="ml-5 w-[225px]" startYear={1900} // 시작 연도 설정 /> - + { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleAnalysisClick(); + } + }} + />
- {/*
- -
*/}
]} diff --git a/apps/sn/app/(with-base-layout)/ii/rdiiResult/page.tsx b/apps/sn/app/(with-base-layout)/ii/rdiiResult/page.tsx index a5ab55407..08c7a8146 100644 --- a/apps/sn/app/(with-base-layout)/ii/rdiiResult/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/rdiiResult/page.tsx @@ -22,8 +22,9 @@ const formSchema = z.object({ aplcnYmFrom: z.string().default(() => { // Date에서 string(yyyyMM 형식)으로 변경 const now = new Date(); const year = now.getFullYear(); - const month = String(now.getMonth() + 1).padStart(2, '0'); - return `${year}${month}`; + // const month = String(now.getMonth() + 1).padStart(2, '0'); + // return `${year}${month}`; + return `${year}01`; // 기본값을 1월로 설정 }), // 분석기간 시작연월 aplcnYmTo: z.string().default(() => { // Date에서 string(yyyyMM 형식)으로 변경 const now = new Date(); @@ -66,8 +67,9 @@ const Result = () => { aplcnYmFrom: (() => { // 현재 연월을 yyyyMM 형식으로 설정 const now = new Date(); const year = now.getFullYear(); - const month = String(now.getMonth() + 1).padStart(2, '0'); - return `${year}${month}`; + // const month = String(now.getMonth() + 1).padStart(2, '0'); + // return `${year}${month}`; + return `${year}01`; })(), aplcnYmTo: (() => { // 현재 연월을 yyyyMM 형식으로 설정 const now = new Date(); diff --git a/apps/sn/app/(with-base-layout)/ii/result/page.tsx b/apps/sn/app/(with-base-layout)/ii/result/page.tsx index 30d0ef07c..974f6fa5f 100644 --- a/apps/sn/app/(with-base-layout)/ii/result/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/result/page.tsx @@ -22,8 +22,9 @@ const formSchema = z.object({ aplcnYmFrom: z.string().default(() => { // Date에서 string(yyyyMM 형식)으로 변경 const now = new Date(); const year = now.getFullYear(); - const month = String(now.getMonth() + 1).padStart(2, '0'); - return `${year}${month}`; + // const month = String(now.getMonth() + 1).padStart(2, '0'); + // return `${year}${month}`; + return `${year}01`; }), // 분석기간 시작연월 aplcnYmTo: z.string().default(() => { // Date에서 string(yyyyMM 형식)으로 변경 const now = new Date(); @@ -62,8 +63,9 @@ const Result = () => { aplcnYmFrom: (() => { // 현재 연월을 yyyyMM 형식으로 설정 const now = new Date(); const year = now.getFullYear(); - const month = String(now.getMonth() + 1).padStart(2, '0'); - return `${year}${month}`; + // const month = String(now.getMonth() + 1).padStart(2, '0'); + // return `${year}${month}`; + return `${year}01`; })(), aplcnYmTo: (() => { // 현재 연월을 yyyyMM 형식으로 설정 const now = new Date(); diff --git a/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx b/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx index 4d1c0fbe8..4ea485821 100644 --- a/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx +++ b/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx @@ -160,6 +160,12 @@ const Page = () => { className='w-[100px]' value={usr} onChange={(e) => setUsr(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} />
@@ -168,6 +174,12 @@ const Page = () => { className='w-[100px]' value={pjNm} onChange={(e) => setpjNm(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} />
diff --git a/apps/sn/app/(with-base-layout)/oper/oldPp/page.tsx b/apps/sn/app/(with-base-layout)/oper/oldPp/page.tsx index 4f46aee91..de7695636 100644 --- a/apps/sn/app/(with-base-layout)/oper/oldPp/page.tsx +++ b/apps/sn/app/(with-base-layout)/oper/oldPp/page.tsx @@ -114,8 +114,8 @@ const Page = () => { atflId: id, dcrpPplMtncBizNm: fileNm }) - if (data) { - alert('파일이 등록되었습니다.'); + if (data) { + alert('파일이 등록되었습니다.'); setIsModalOpen(false); handleSearch(); } @@ -154,6 +154,12 @@ const Page = () => { className='w-[100px] !text-2xl' value={usr} onChange={(e) => setUsr(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} />
@@ -162,6 +168,12 @@ const Page = () => { className='w-[100px] !text-2xl' value={pjNm} onChange={(e) => { setpjNm(e.target.value) }} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); // Enter 키 기본 동작 방지 + handleSearch(); + } + }} />
diff --git a/apps/sn/app/components/lib/api/index.ts b/apps/sn/app/components/lib/api/index.ts index ab8936329..6574567ad 100644 --- a/apps/sn/app/components/lib/api/index.ts +++ b/apps/sn/app/components/lib/api/index.ts @@ -85,7 +85,7 @@ export const deleteData = async (url: string, data?: object): Promise => { return res; }; -// RSONE DC API 호출 +// DC API 호출 export const getDcData = async (url: string, data?: object): Promise => { const res = await fetch('/dc-service' + url, { method: "GET", @@ -97,7 +97,7 @@ export const getDcData = async (url: string, data?: object): Promise => { throw new Error('Failed to fetch data'); }; -// RSONE DC API 호출 +// CMS API 호출 export const getCmsData = async (url: string, data?: object): Promise => { console.log(url); const res = await fetch('/cms-service' + url, { @@ -110,6 +110,18 @@ export const getCmsData = async (url: string, data?: object): Promise => { throw new Error('Failed to fetch data'); }; +// GeoServer API 호출 +export const getGeoData = async (url: string, data?: object): Promise => { + const res = await fetch('/geoserver' + url, { + method: "GET", + }); + if (res.ok) { + const data = await res.json(); + return data; + } + throw new Error('Failed to fetch data'); +}; + export function getCookie(name: string) { const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)')); if (match && match[2]) { diff --git a/apps/sn/app/components/lib/utils/date.ts b/apps/sn/app/components/lib/utils/date.ts index a401ad738..30bea45a0 100644 --- a/apps/sn/app/components/lib/utils/date.ts +++ b/apps/sn/app/components/lib/utils/date.ts @@ -103,8 +103,10 @@ export const formatDateString = (dateStr: string): string => { } const year = cleanStr.substring(0, 4); - const month = parseInt(cleanStr.substring(4, 6)); // parseInt로 앞의 0 제거 - const day = parseInt(cleanStr.substring(6, 8)); // parseInt로 앞의 0 제거 + const month = cleanStr.substring(4, 6); // parseInt로 앞의 0 제거 + // const month = parseInt(cleanStr.substring(4, 6)); // parseInt로 앞의 0 제거 + // const day = parseInt(cleanStr.substring(6, 8)); // parseInt로 앞의 0 제거 + const day = cleanStr.substring(6, 8); // parseInt로 앞의 0 제거 - return `${year}년 ${month}월 ${day}일`; + return `${year}-${month}-${day}`; }; \ No newline at end of file diff --git a/apps/sn/app/components/lib/utils/formatDisplayValue.tsx b/apps/sn/app/components/lib/utils/formatDisplayValue.tsx index a5bd847cf..289b05b97 100644 --- a/apps/sn/app/components/lib/utils/formatDisplayValue.tsx +++ b/apps/sn/app/components/lib/utils/formatDisplayValue.tsx @@ -21,7 +21,7 @@ export const formatDisplayData = (data: { [key: string]: any }): { [key: string] if (/^\d{6}$/.test(dateStr)) { const year = dateStr.substring(0, 4); const month = parseInt(dateStr.substring(4, 6)); - formattedData[fieldId] = `${year}년 ${month}월`; + formattedData[fieldId] = `${year}-${month}`; } else { formattedData[fieldId] = String(value); } @@ -45,9 +45,10 @@ export const formatDisplayData = (data: { [key: string]: any }): { [key: string] // 🎯 undefined 체크 후 parseInt 적용 if (year && month && day && hour && minute) { - const formattedMonth = parseInt(month); - const formattedDay = parseInt(day); - formattedData[fieldId] = `${year}년 ${formattedMonth}월 ${formattedDay}일 ${hour}시 ${minute}분 ${second}초`; + // const formattedMonth = parseInt(month); + // const formattedDay = parseInt(day); + // formattedData[fieldId] = `${year}-${formattedMonth}-${formattedDay} ${hour}:${minute}:${second}`; + formattedData[fieldId] = `${year}-${month}-${day} ${hour}:${minute}:${second}`; } else { formattedData[fieldId] = String(value); } diff --git a/apps/sn/app/components/ui/SidoSigunguSelectBox.tsx b/apps/sn/app/components/ui/SidoSigunguSelectBox.tsx index 7414185a6..a3a138259 100644 --- a/apps/sn/app/components/ui/SidoSigunguSelectBox.tsx +++ b/apps/sn/app/components/ui/SidoSigunguSelectBox.tsx @@ -1,5 +1,7 @@ -import React, { useMemo } from "react"; +import React, { useState, useMemo, useEffect } from "react"; import { SelectBox } from '@common/business_components/ui' +import { Label } from '@common/components'; +import useStore from '../../store/useStore'; interface Option { id: number; @@ -10,150 +12,72 @@ interface SidoSigunguSelectBoxProps { sido: number; sigungu: number; onSidoChange: (id: number) => void; + setCtpvName?: (name: string) => void; onSigunguChange: (id: number) => void; + setSggName?: (name: string) => void; className?: string; } -const sidoList: { id: number, name: string }[] = [ - { id: 0, name: '전체' }, - { id: 26, name: '부산광역시' }, - { id: 28, name: '인천광역시' }, - { id: 30, name: '대전광역시' }, - { id: 41, name: '경기도' }, - { id: 42, name: '강원도' }, - { id: 44, name: '충청남도' }, - { id: 45, name: '전라북도' }, - { id: 46, name: '전라남도' }, - { id: 47, name: '경상북도' }, - { id: 48, name: '경상남도' }, -]; -const sigunguMap: Record = { - 26: [ - { id: 0, name: '전체' }, - // ...부산산광역시의 시군구 추가 - ], - 28: [ - { id: 0, name: '전체' }, - // ...인천광역시의 시군구 추가 - ], - 30: [ - { id: 0, name: '전체' }, - // ...대전광역시의 시군구 추가 - ], - 41: [ - { id: 0, name: '전체' }, - { id: 41820, name: '가평군' }, - { id: 41550, name: '안성시' }, - { id: 41830, name: '양평군' }, - { id: 41670, name: '여주시' }, - { id: 41500, name: '이천시' }, - { id: 41430, name: '의왕시' }, - { id: 41150, name: '의정부시' }, - { id: 41480, name: '파주시' }, - { id: 41650, name: '포천시' }, - // ...경기도의 시군구 추가 - ], - 42: [ - { id: 0, name: '전체' }, - { id: 42170, name: '동해시' }, - { id: 42110, name: '춘천시' }, - { id: 42720, name: '홍천군' }, - // ...강원도의 시군구 추가 - ], - 44: [ - { id: 0, name: '전체' }, - { id: 44770, name: '서천군' }, - // ...충청남도의 시군구 추가 - ], - 45: [ - { id: 0, name: '전체' }, - { id: 45130, name: '군산시' }, - { id: 45190, name: '남원시' }, - { id: 45730, name: '무주군' }, - { id: 45800, name: '부안군' }, - { id: 45770, name: '순창군' }, - { id: 45140, name: '익산시' }, - { id: 45750, name: '임실군' }, - { id: 45710, name: '완주군' }, - { id: 45110, name: '전주시' }, - // ...전라북도의 시군구 추가 - ], - 46: [ - { id: 0, name: '전체' }, - { id: 46810, name: "강진군" }, - { id: 46770, name: "고흥군" }, - { id: 46720, name: "곡성군" }, - { id: 46730, name: "구례군" }, - { id: 46230, name: "광양시" }, - { id: 46170, name: "나주시" }, - { id: 46110, name: "목포시" }, - { id: 46840, name: "무안군" }, - { id: 46150, name: "순천시" }, - { id: 46910, name: "신안군" }, - { id: 46130, name: "여수시" }, - { id: 46890, name: "완도군" }, - // ...전라남도의 시군구 추가 - ], - 47: [ - { id: 0, name: '전체' }, - { id: 47130, name: "경주시" }, - { id: 47830, name: "고령군" }, - { id: 47190, name: "구미시" }, - { id: 47720, name: "군위군" }, - { id: 47150, name: "김천시" }, - { id: 47280, name: "문경시" }, - { id: 47920, name: "봉화군" }, - { id: 47250, name: "상주시" }, - { id: 47770, name: "영덕군" }, - { id: 47760, name: "영양군" }, - { id: 47210, name: "영주시" }, - { id: 47900, name: "예천군" }, - { id: 47930, name: "울진군" }, - { id: 47730, name: "의성군" }, - { id: 47750, name: "청송군" }, - { id: 47850, name: "칠곡군" }, - { id: 47110, name: "포항시" }, - // ...경상북도의 시군구 추가 - ], - 48: [ - { id: 0, name: '전체' }, - { id: 48310, name: "거제시" }, - { id: 48250, name: "김해시" }, - { id: 48270, name: "밀양시" }, - { id: 48220, name: "통영시" }, - // ...경상남도의 시군구 추가 - ], - // ...나머지 시도별 시군구 추가 -}; - export function SidoSigunguSelectBox({ sido, sigungu, onSidoChange, + setCtpvName, onSigunguChange, + setSggName, className = "", }: SidoSigunguSelectBoxProps) { - // 선택된 시도에 따라 시군구 리스트를 가져옴 - const sigunguList = useMemo(() => sigunguMap[sido] || [{ id: 0, name: '전체' }], [sido]); + + const { ctpv, sgg} = useStore(); + + useEffect(() => { + (async () => { + onSidoChange(0); + onSigunguChange(0); + if (setCtpvName && setSggName) { + setCtpvName(""); + setSggName(""); + } + })(); + }, []); + return (
+ ({ val: opt.id, text: opt.name }))} + label="" + selectArray={ + [{ val: 0, text: '전체' }, + ...ctpv.map(opt => ({ val: opt.id, text: opt.name })) + ] + } value={sido} - onSelectValue={val => onSidoChange(Number(val))} + onSelectValue={val => { + onSidoChange(Number(val)); + if (setCtpvName) setCtpvName(ctpv.find(opt => Number(opt.id) === Number(val))?.name || ""); + }} selectContentClass="z-[101]" /> + ({ val: opt.id, text: opt.name }))} + label="" + selectArray={ + [{ val: 0, text: '전체' }, + ...sgg + .filter(opt => String(opt.id).slice(0, 2) === String(sido)) + .map(opt => ({ val: opt.id, text: opt.name })) + ] + } value={sigungu} - onSelectValue={val => onSigunguChange(Number(val))} + onSelectValue={val => { + onSigunguChange(Number(val)) + if (setSggName) setSggName(sgg.find(opt => Number(opt.id) === Number(val))?.name || ""); + }} selectContentClass="z-[101]" />
diff --git a/apps/sn/app/components/ui/YearRangeSelectBox.tsx b/apps/sn/app/components/ui/YearRangeSelectBox.tsx index 3e0318dac..83b21cba5 100644 --- a/apps/sn/app/components/ui/YearRangeSelectBox.tsx +++ b/apps/sn/app/components/ui/YearRangeSelectBox.tsx @@ -88,9 +88,9 @@ export function YearRangeSelectBox({ }; return ( -
+
~ +
{files && files.length > 0 ? fileName : "파일을 선택하세요."} diff --git a/apps/sn/app/components/ui/govSidoSigunguSearchForm.tsx b/apps/sn/app/components/ui/govSidoSigunguSearchForm.tsx index b46f2b481..1fe3d7bae 100644 --- a/apps/sn/app/components/ui/govSidoSigunguSearchForm.tsx +++ b/apps/sn/app/components/ui/govSidoSigunguSearchForm.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react'; import { SelectBox } from '@common/business_components/ui/select'; +import { Label } from '@radix-ui/react-label'; export type comCodeState = { code: { @@ -24,9 +25,9 @@ export type comCodeState = { }; type SelectDataType = { - text: string; - val: string; - sido?: string; // 시도 코드 (선택 사항) + text: string; + val: string; + sido?: string; // 시도 코드 (선택 사항) } type EnvPartSelectDataType = SelectDataType & { @@ -73,9 +74,9 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData const [allSigunOptions, setAllSigunOptions] = useState([]); // 조회된 조건에 맞는 환경청 시도 시군 (SelectBox에 실제 사용될 데이터) - const [filteredEnvPartData, setFilteredEnvPartData] = useState([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }]); - const [filteredEnvPartSidoData, setFilteredEnvPartSidoData] = useState([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }]); - const [filteredEnvPartSigunData, setFilteredEnvPartSigunData] = useState([{ text: "전체", val: '0', sido: '0' }]); + const [filteredEnvPartData, setFilteredEnvPartData] = useState([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }]); + const [filteredEnvPartSidoData, setFilteredEnvPartSidoData] = useState([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }]); + const [filteredEnvPartSigunData, setFilteredEnvPartSigunData] = useState([{ text: "전체", val: '0', sido: '0' }]); // 시군구 데이터 const getSggCd = async (): Promise => { @@ -93,7 +94,7 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData return sggCd; } catch (error) { console.error('시군구 데이터를 가져오는데 실패했습니다:', error); - return [{ val: '0', text: '전체', sido: '0' }]; + return [{ val: '0', text: '전체', sido: '0' }]; } }; @@ -112,7 +113,7 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData return cityCd; } catch (error) { console.error('시도 데이터를 가져오는데 실패했습니다:', error); - return [{ val: '0', text: '전체', sido: '0' }]; + return [{ val: '0', text: '전체', sido: '0' }]; } }; @@ -135,7 +136,7 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData return lclgvrnmntCd; } catch (error) { console.error('환경청 데이터를 가져오는데 실패했습니다:', error); - return [{ val: '0', text: '전체', adstDliStrCd: '', sido: '0' }]; + return [{ val: '0', text: '전체', adstDliStrCd: '', sido: '0' }]; } }; @@ -188,8 +189,8 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData const relevantSigunSidos = Array.from( new Set( allSigunOptions - .filter(sigungu => cityCodesInEnvPart.includes(sigungu.val)) - .map(sigungu => sigungu.sido) + .filter(sigungu => cityCodesInEnvPart.includes(sigungu.val)) + .map(sigungu => sigungu.sido) ) ); console.log('relevantSigunTexts:', relevantSigunSidos); @@ -210,8 +211,8 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData // relevantSidos와 relevantSigunsForSidoDerivation은 초기 빈 배열 상태를 유지합니다. setFilteredEnvPartSidoData([ - { text: "전체", val: '0', adstDliStrCd: '', sido: '0' }, - ...relevantSidos.map((item: SelectDataType) => ({ text: item.text, val: item.val, adstDliStrCd: '', sido: '0' })) + { text: "전체", val: '0', adstDliStrCd: '', sido: '0' }, + ...relevantSidos.map((item: SelectDataType) => ({ text: item.text, val: item.val, adstDliStrCd: '', sido: '0' })) ]); setFilteredEnvPartSigunDataSelected(relevantSigunsForSidoDerivation); @@ -246,14 +247,14 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData setEnvPartSigunValue('0'); // 시군구 "전체"로 초기화 // 부모에게도 초기화된 값 전달 (text 포함) if (setRtnEnvPartSidoValue) { - const sidoDefault = filteredEnvPartSidoData.find(item => item.val === '0') || { val: '0', text: '전체' }; - // setRtnEnvPartSidoValue(sidoDefault.val); // 이전 방식: 값만 전달 - // TODO: 만약 시도 값도 객체로 전달해야 한다면 아래와 같이 수정 - // setRtnEnvPartSidoValue({ val: sidoDefault.val, text: sidoDefault.text }); + const sidoDefault = filteredEnvPartSidoData.find(item => item.val === '0') || { val: '0', text: '전체' }; + // setRtnEnvPartSidoValue(sidoDefault.val); // 이전 방식: 값만 전달 + // TODO: 만약 시도 값도 객체로 전달해야 한다면 아래와 같이 수정 + // setRtnEnvPartSidoValue({ val: sidoDefault.val, text: sidoDefault.text }); } if (setRtnEnvPartSigunValue) { - const sigunDefault = filteredEnvPartSigunData.find(item => item.val === '0') || { val: '0', text: '전체' }; - setRtnEnvPartSigunValue({ val: sigunDefault.val, text: sigunDefault.text }); + const sigunDefault = filteredEnvPartSigunData.find(item => item.val === '0') || { val: '0', text: '전체' }; + setRtnEnvPartSigunValue({ val: sigunDefault.val, text: sigunDefault.text }); } break; case 'envPartSido': // 환경청별 - 시도 선택 @@ -262,8 +263,8 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData initializeCityDataByEnvPartSigun(val); setEnvPartSigunValue('0'); // 시군구 "전체"로 초기화 if (setRtnEnvPartSigunValue) { - const sigunDefault = filteredEnvPartSigunData.find(item => item.val === '0') || { val: '0', text: '전체' }; - setRtnEnvPartSigunValue({ val: sigunDefault.val, text: sigunDefault.text }); + const sigunDefault = filteredEnvPartSigunData.find(item => item.val === '0') || { val: '0', text: '전체' }; + setRtnEnvPartSigunValue({ val: sigunDefault.val, text: sigunDefault.text }); } break; case 'envPartSigun': // 환경청별 - 시군구 선택 @@ -286,11 +287,11 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData setEnvPartSigunValue('0'); // 필터링된 목록들도 초기 "전체" 또는 전체 목록으로 리셋 - setFilteredEnvPartSigunData([{ text: "전체", val: '0', sido: '0' }, ...allSigunOptions]); + setFilteredEnvPartSigunData([{ text: "전체", val: '0', sido: '0' }, ...allSigunOptions]); - setFilteredEnvPartData([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }, ...allEnvPartOptions]); - setFilteredEnvPartSidoData([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }, ...allSidoOptions.map(s => ({ ...s, adstDliStrCd: '' }))]); - setFilteredEnvPartSigunData([{ text: "전체", val: '0', sido: '0' }, ...allSigunOptions]); + setFilteredEnvPartData([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }, ...allEnvPartOptions]); + setFilteredEnvPartSidoData([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }, ...allSidoOptions.map(s => ({ ...s, adstDliStrCd: '' }))]); + setFilteredEnvPartSigunData([{ text: "전체", val: '0', sido: '0' }, ...allSigunOptions]); setFilteredEnvPartSigunDataSelected(allSigunOptions); @@ -316,11 +317,35 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData return ( isShowPart ? ( -
+
<> - onSelectValue(val.toString(), 'envPart')} value={envPartValue} selectClass={'rounded-lg bg-white truncate'} /> - onSelectValue(val.toString(), 'envPartSido')} value={envPartSidoValue} selectClass={'rounded-lg bg-white truncate'} /> - onSelectValue(val.toString(), 'envPartSigun')} value={envPartSigunValue} selectClass={'rounded-lg bg-white truncate'} /> + + onSelectValue(val.toString(), 'envPart')} + value={envPartValue} + selectClass={'rounded-lg bg-white truncate'} + /> + + onSelectValue(val.toString(), 'envPartSido')} + value={envPartSidoValue} + selectClass={'rounded-lg bg-white truncate'} + /> + + onSelectValue(val.toString(), 'envPartSigun')} + value={envPartSigunValue} + selectClass={'rounded-lg bg-white truncate'} + /> {children}
diff --git a/apps/sn/app/components/ui/verticalTable.tsx b/apps/sn/app/components/ui/verticalTable.tsx index abdad03bb..ee13405fb 100644 --- a/apps/sn/app/components/ui/verticalTable.tsx +++ b/apps/sn/app/components/ui/verticalTable.tsx @@ -121,7 +121,7 @@ export function VerticalTable({ {headlist?.map((head) => ( {/* 컬럼 제목 */} - + {head.title} {/* 데이터 값 또는 입력 필드 */} @@ -168,7 +168,7 @@ export function VerticalTable({ {headlist2?.map((head) => ( {/* 컬럼 제목 */} - + {head.title} {/* 데이터 값 또는 입력 필드 */} diff --git a/apps/sn/app/store/useStore.ts b/apps/sn/app/store/useStore.ts new file mode 100644 index 000000000..518cce66b --- /dev/null +++ b/apps/sn/app/store/useStore.ts @@ -0,0 +1,41 @@ +import { useMemo } from "react"; +import { create } from "zustand"; +import { getGeoData } from "@/components/lib/api"; +import { get } from "http"; + +interface Option { id: number, name: string } + +interface SnStoreState { + ctpv: Option[]; + sgg: Option[]; + fetchCtpvData: () => Promise; + fetchSggData: () => Promise; +} + +const useStore = create((set) => ({ + // Define your store state and actions here + ctpv: [], + sgg: [], + fetchCtpvData: async () => { + const ctpvData = await getGeoData('/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_ctpv&outputFormat=application%2Fjson'); + const ctpvList: Option[] = ctpvData.features + .map((feature: any) => ({ + id: feature.properties.mctpv_cd.trim(), + name: feature.properties.mctpv_korn_nm + })) + .sort((a: Option, b: Option) => a.name.localeCompare(b.name, 'ko')); + set({ ctpv: ctpvList }); + }, + fetchSggData: async () => { + const sggData = await getGeoData('/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_sgg&outputFormat=application%2Fjson'); + const sggList: Option[] = sggData.features + .map((feature: any) => ({ + id: feature.properties.sgg_cd, + name: feature.properties.sgg_korn_nm + })) + .sort((a: Option, b: Option) => a.name.localeCompare(b.name, 'ko')); + set({ sgg: sggList }); + } +})); + +export default useStore; \ No newline at end of file diff --git a/apps/wr/app/map/mainMap/page.tsx b/apps/wr/app/map/mainMap/page.tsx index 96785f8b3..e6f75feb0 100644 --- a/apps/wr/app/map/mainMap/page.tsx +++ b/apps/wr/app/map/mainMap/page.tsx @@ -159,6 +159,7 @@ const Map = () => { isSearchModalOpen={isSearchModalOpen} onCheckedLayersChange={handleCheckedLayersChange} imgVisble={true} + searchBar={undefined} />
); diff --git a/apps/wr/app/map/popup/page.tsx b/apps/wr/app/map/popup/page.tsx index c7b23461f..6c1cc47d0 100644 --- a/apps/wr/app/map/popup/page.tsx +++ b/apps/wr/app/map/popup/page.tsx @@ -123,16 +123,6 @@ const Map = () => { gisMaps={gisMaps} isMiniMap={false} searchView={undefined} - // searchView={(props: any) => ( - // - // ) - // } detailView={(props: any) =>( { isSearchModalOpen={isSearchModalOpen} onCheckedLayersChange={handleCheckedLayersChange} imgVisble={true} + searchBar={undefined} />
); diff --git a/apps/wr/app/matMng/coMat/ruseCaseMng/page.tsx b/apps/wr/app/matMng/coMat/ruseCaseMng/page.tsx index e45a0a0f2..813b4e23f 100644 --- a/apps/wr/app/matMng/coMat/ruseCaseMng/page.tsx +++ b/apps/wr/app/matMng/coMat/ruseCaseMng/page.tsx @@ -17,35 +17,45 @@ import { UiModal, UiTable, type SelectDataType, + type SheetParameter, } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; -import { Button } from "@common/components/ui"; +import { Button, Label } from "@common/components/ui"; import { useEffect, useState } from "react"; -import { Toaster } from "react-hot-toast"; +import toast, { Toaster } from "react-hot-toast"; +import { useTranslation } from "react-i18next"; export default function RuseCaseMng() { - const { code, ruseCaseMng, selectRuseCaseMng } = useWrStore((state) => state); - const { ruseCaseMngList, status, count } = ruseCaseMng; + const { code, ruseCaseMng, selectRuseCaseMng, ruseCaseMngInit } = useWrStore((state) => state); + const { ruseCaseMngList, status, count, excelList } = ruseCaseMng; const [selectSgg, setSelectSgg] = useState([]); const [objSearch, setObjSearch] = useState({ sgg: "", city: "" }); - + const [sidoCd, setSidoCd] = useState(""); const [sigunguCd, setSigunguCd] = useState(""); - const [selectUtz, setSelectUtz] = useState(["조경용수"]); + // const [selectUtz, setSelectUtz] = useState(["조경용수"]); + const [selectUtz, setSelectUtz] = useState(""); const [name, setName] = useState(""); + const [resetPage, isResetPage] = useState(false); + const { t } = useTranslation('base'); // 물재이용사례 조회 - const searchRuseCaseMng = async (pageNo: number, pageSize: number) => { + const searchRuseCaseMng = async (isExcel: boolean, pageNo: number, pageSize: number) => { await selectRuseCaseMng( + isExcel, pageNo, pageSize, - sidoCd ?? "", - sigunguCd ?? "", - selectUtz[0] ?? "", + sidoCd ?? "", + sigunguCd ?? "", + selectUtz ?? "", name ?? "" ); } + useEffect(() => { + ruseCaseMngInit(); + }, []) + // 시도 선택 const getSelCity = (val: string | number) => { const cityValue = String(val); @@ -69,91 +79,97 @@ export default function RuseCaseMng() { isModal: boolean; }>({ isModal: false }); - // 다운로드 - const download = () => { - searchRuseCaseMng(1, 10000);; - + + useEffect(() => { + + if (excelList !== undefined && excelList.length === 0) { + toast.error(t('excelDownErrMsg')); + return; + } fetch(`/sample_ruseCaseMng.xlsx`, {}).then(async (response) => { - if (!response.ok) { - throw Error(response.statusText); - } - // 받은 파일 바인너리 처리 - const blobRet = await response.arrayBuffer(); - - const excelData1 = ruseCaseMngList.map((item) => { - return [ - item.ruseBizNm, - item.bizBgngDate, - item.bizEndDate, - item.splyFcltKnd, - item.splyFcltNm, - item.splyFcltCpct, - item.dmdFcltNm, - item.dmdFcltAddr, - item.ruseFcltCpct, - item.ruseFcltPplLen, - item.ruseFcltUsg, - item.ruseFcltSplyCpct, - item.ruseFcltPrcsMsrc, - item.grnteWqUsg, - item.grnteWqGrssClfg, - item.grnteWqCombResdch, - item.grnteWqTrbt, - item.grnteWqBod, - item.grnteWqSmll, - item.grnteWqCrmty, - item.grnteWqTn, - item.grnteWqTp, - item.grnteWqPh, - item.grnteWqClIonQnt, - item.grnteWqCndctStat, - item.grnteWqRmrk, - item.reqBizGrssCst, - item.reqBizReuseFcltCst, - item.reqBizPplCst, - item.reqBizArchCst, - item.reqBizMchnCst, - item.reqBizMtrngCst, - item.reqBizGisCst, - item.reqBizCctvCst, - item.reqBizCmcnCst, - item.reqBizWstCst, - item.reqBizDesignCst, - item.reqBizSpvsCst, - item.reqBizSbsdCst, - item.reqBizEtc, - item.prcmPlanGrssCst, - item.prcmPlanNlep, - item.prcmPlanLcep, - item.prcmPlanBrdnCst, - item.prcmPlanEcqrRt, - item.clclnGrssCst, - item.clclnNlep, - item.clclnLcep, - item.clclnBrdnCst, - item.clclnEcqrRt, - ]; - }); - - const sheetParameter = [ - { - data: excelData1, - headerNum: 2, - headerRange: 'A1:AX1', - sheetName: '물재이용사례', - startCol: 'A' + if (!response.ok) { + throw Error(response.statusText); + } + // 받은 파일 바인너리 처리 + const blobRet = await response.arrayBuffer(); + if(excelList){ + const excelData1 = excelList.map((item) => { + return [ + item.ruseBizNm, + item.bizBgngDate, + item.bizEndDate, + item.splyFcltKnd, + item.splyFcltNm, + item.splyFcltCpct, + item.dmdFcltNm, + item.dmdFcltAddr, + item.ruseFcltCpct, + item.ruseFcltPplLen, + item.ruseFcltUsg, + item.ruseFcltSplyCpct, + item.ruseFcltPrcsMsrc, + item.grnteWqUsg, + item.grnteWqGrssClfg, + item.grnteWqCombResdch, + item.grnteWqTrbt, + item.grnteWqBod, + item.grnteWqSmll, + item.grnteWqCrmty, + item.grnteWqTn, + item.grnteWqTp, + item.grnteWqPh, + item.grnteWqClIonQnt, + item.grnteWqCndctStat, + item.grnteWqRmrk, + item.reqBizGrssCst, + item.reqBizReuseFcltCst, + item.reqBizPplCst, + item.reqBizArchCst, + item.reqBizMchnCst, + item.reqBizMtrngCst, + item.reqBizGisCst, + item.reqBizCctvCst, + item.reqBizCmcnCst, + item.reqBizWstCst, + item.reqBizDesignCst, + item.reqBizSpvsCst, + item.reqBizSbsdCst, + item.reqBizEtc, + item.prcmPlanGrssCst, + item.prcmPlanNlep, + item.prcmPlanLcep, + item.prcmPlanBrdnCst, + item.prcmPlanEcqrRt, + item.clclnGrssCst, + item.clclnNlep, + item.clclnLcep, + item.clclnBrdnCst, + item.clclnEcqrRt, + ]; + }); + + const sheetParameter: SheetParameter[] = [ + { + data: excelData1, + headerNum: 2, + headerRange: 'A1:AX1', + sheetName: '물재이용사례', + startCol: 'A' + } + ]; + // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 + await filePickedBlobArray(blobRet, '물재이용사례현황', sheetParameter); } - ]; - // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 - await filePickedBlobArray(blobRet, '물재이용사례현황', sheetParameter); }); - } + + + }, [excelList]) // 양식받기 const sampleDownLoad = () => { excelDownload( [[]], - "물재이용사례 관리", + "물재이용사례 관리 등록양식", "sample_ruseCaseMng.xlsx", "A1:AX1", 2 @@ -161,7 +177,7 @@ export default function RuseCaseMng() { } useEffect(() => { - if(status === 200){ + if (status === 200) { setIsExcelOpen({ isModal: false }); } }, [status]); @@ -174,7 +190,7 @@ export default function RuseCaseMng() { <SearchDiv> <SearchFormLeft> - <div className="col-span-8 flex flex-row"> + <div className="col-span-8 flex flex-row items-center"> <SelectBox className="col-span-2 w-1/3 h-full text-2xl" label="시도" @@ -183,24 +199,28 @@ export default function RuseCaseMng() { onSelectValue={getSelCity} /> <SelectBox - className="col-span-2 w-1/3 h-full text-2xl" + className="col-span-2 w-1/3 h-full text-2xl ml-4" label="시군구" selectClass={""} selectArray={selectSgg || []} onSelectValue={getSgg} /> <SelectBox - className="col-span-2 w-1/3 h-full text-2xl" + className="col-span-2 w-1/3 h-full text-2xl ml-4" label="용도" selectClass={""} selectArray={ruseUtzType} onSelectValue={(val) => { - if (val) setSelectUtz([String(val)]); + if (val) setSelectUtz(String(val)); }} + value={selectUtz || ruseUtzType[0]?.val} /> + <Label className="w-28 text-xl ml-4 mr-6"> + {"수요처명"} + </Label> <SearchInput - className={"text-2xl"} - label="수요처명" + className={"col-span-2 w-1/3 text-2xl"} + label="" textValue={name} setText={(e) => { setName(e); @@ -211,13 +231,29 @@ export default function RuseCaseMng() { <SearchFormRight className="w-2/12 mx-5 flex flex-col items-center justify-center space-x-2"> <div className="space-y"> <div className="flex flex-row space-x-2"> - <Button size={"sm"} onClick={() => { searchRuseCaseMng(1, 20) }}> + <Button size={"sm"} onClick={() => { + searchRuseCaseMng(false, 1, 10); + isResetPage(true); + }}> 조회 </Button> <Button size={"sm"} onClick={() => { setIsExcelOpen({ isModal: true }); }}> 엑셀등록 </Button> - <Button size={"sm"} onClick={() => { download() }}> + <Button size={"sm"} onClick={() => { + selectRuseCaseMng( + true, + 1, + count, + sidoCd ?? "", + sigunguCd ?? "", + selectUtz ?? "", + name ?? "" + ); + // download() + + + }} className={"green"}> 다운로드 </Button> <Button size={"sm"} onClick={() => { sampleDownLoad() }}> @@ -239,10 +275,12 @@ export default function RuseCaseMng() { headlist={ruseCaseMng.ruseHeadList} pageSize={20} total={count} - cellClick={() => {}} + cellClick={undefined} onPageChange={(pageNo: number) => { - searchRuseCaseMng(pageNo, 10); + searchRuseCaseMng(false, pageNo, 10); + isResetPage(false) }} + resetPageNo={resetPage} /> </div> </ListDiv> @@ -254,9 +292,9 @@ export default function RuseCaseMng() { <UiModal open={isExcelOpen.isModal} onOpenChange={() => { - setIsExcelOpen({ isModal: !isExcelOpen.isModal }) + setIsExcelOpen({ isModal: !isExcelOpen.isModal }) }} - bodyClass={"w-[40vw] max-w-none"} + bodyClass={"w-[35vw] max-w-none"} body={<RuseCaseMngExcel />} /> </> diff --git a/apps/wr/app/ruseFcltMng/fcltReg/pbnstReg/page.tsx b/apps/wr/app/ruseFcltMng/fcltReg/pbnstReg/page.tsx index 934946b74..d08d6f06e 100644 --- a/apps/wr/app/ruseFcltMng/fcltReg/pbnstReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltReg/pbnstReg/page.tsx @@ -71,7 +71,7 @@ export default function PublicReuseFaciltyInsert() { // defaultValues: { items: pbnstRegArrayZod.parse([]) }, mode: "onChange", }); - const { isDirty } = form.formState; + // const { isDirty } = form.formState; const { fields: items, @@ -90,10 +90,10 @@ export default function PublicReuseFaciltyInsert() { }, [pbnst.isInit, pubHasuInit]); const onSubmit = async (valuse: { items: PbnstRegArrrayType }) => { - if (!isDirty) { - toast.error("변경사항이 없습니다."); // 변경사항이 없으면 메시지 표시 - return; - } + // if (!isDirty) { + // toast.error("변경사항이 없습니다."); // 변경사항이 없으면 메시지 표시 + // return; + // } const data = writeRgtrAndMdfr(valuse.items); let bizs = [] as fcBizType[]; data.forEach((fclt) => { diff --git a/apps/wr/app/ruseFcltMng/fcltSttn/pbnstSttn/page.tsx b/apps/wr/app/ruseFcltMng/fcltSttn/pbnstSttn/page.tsx index 5208edc02..8aea16c00 100644 --- a/apps/wr/app/ruseFcltMng/fcltSttn/pbnstSttn/page.tsx +++ b/apps/wr/app/ruseFcltMng/fcltSttn/pbnstSttn/page.tsx @@ -1,6 +1,7 @@ "use client"; import { useWrStore } from "@/app/store"; import { btnClass } from "@/app/store/common/code"; +import { prfRegPageSize } from "@/app/store/prfmncReg/pbnstPrfmncReg"; 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"; @@ -35,7 +36,6 @@ export default function PbnstSttn() { const { pbnstSttnRes, fclts, pbnstSttnResCount } = pbnstSttn; const [isReset, setIsReset] = useState(false); - //const [tableIndex, setTableIndex] = useState<number>(1) const ref = useRef<ReturnType>({} as ReturnType); const [searchYear, setSearchYear] = useState<string>( String(new Date().getFullYear()) @@ -70,6 +70,24 @@ export default function PbnstSttn() { }, [getPbnStnDetail, pbnstSttnRes] ); + useEffect(() => { + if (!pbnstSttn.isInit) { + getFlcts(); + } + }, [pbnstSttn.isInit]); + useEffect(() => { + + pbnSttnInit("1", "15", ref.current, searchYear, fclts); + }, [fclts]); + + useEffect(() => { + if (pbnstSttnRes && pbnstSttnRes.length > 0) { + setBdstTable(pbnstSttnRes); + } else { + setBdstTable([]); + } + }, [pbnstSttnRes]); + useEffect(() => { if (pbnstSttn.excelList.length >= 0) { @@ -82,24 +100,7 @@ export default function PbnstSttn() { ); } }, [pbnstSttn.excelList]); - useEffect(() => { - if (!pbnstSttn.isInit) { - getFlcts(); - } - }, [pbnstSttn.isInit]); - useEffect(() => { - if (pbnstSttnRes && pbnstSttnRes.length > 0) { - setBdstTable(pbnstSttnRes); - } else { - setBdstTable([]); - } - }, [pbnstSttnRes]); - - useEffect(() => { - - pbnSttnInit("1", "15", ref.current, searchYear, fclts); - }, [fclts]); useEffect(() => { if (pbnstSttn.pbnstDetail.pbnstRuseFcltId) @@ -193,7 +194,7 @@ export default function PbnstSttn() { pbnstSttnSearch( false, String(page), - String(15), + String(prfRegPageSize), ref.current, pbnRuseNm, searchYear, diff --git a/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx b/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx index fbab00284..4fd866d75 100644 --- a/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx +++ b/apps/wr/app/ruseFcltMng/prfmncReg/pbnstPrfmncReg/page.tsx @@ -38,11 +38,12 @@ import { useTranslation } from "react-i18next"; import { headMakeprfmnc } from "../chkgdnReg/TableHead"; export default function PrfmncPrfmncReg() { - const { auth, prfmnc, prfmncHasuInit, prfmnRegData, prfmncHasuNmSearch } = useWrStore( + const { auth, prfmnc, prfmncHasuInit, prfmnRegData, prfmncHasuNmSearch,getPrfFmcRes } = useWrStore( (state) => state ); - const { pbnstPrfmncHeadList, monthHeadList, prfmncRes, prfmncResCount } = prfmnc; + const { prfPbnFclts, pbnstPrfmncHeadList, monthHeadList, prfmncRes, prfmncResCount } = prfmnc; const { regAuthrtYn, mdfcnAuthrtYn } = auth; + const [isReset, setIsReset] = useState(false); const [bdstTable, setbdstTable] = useState<FcPrfType[]>(); const [searchTxt, setSearchTxt] = useState<string>(); const [isExcelOpen, setIsExcelOPen] = useState<{ @@ -51,7 +52,6 @@ export default function PrfmncPrfmncReg() { }>({ isModal: false, data: {} as FcPrfType }); const [inputData, setInputData] = useState<any[]>(); const [pbnstRuseFcltId, setpbnstRuseFcltId] = useState<string>(); - const [pageNation, setPageNation] = useState<number>(1); const [cellNum, setCellNum] = useState<number>(1); const [searchYear, setSearchYear] = useState<string>( String(new Date().getFullYear()) @@ -65,20 +65,6 @@ export default function PrfmncPrfmncReg() { "A1:O1" ); }, [prfmnc.excelList]); - /* - const onSave = useCallback( - async() => { - if (pbnstRuseFcltId) { - await prfmnRegData(pageNation,'41', - excelToPbnPrfData( - inputData as unknown as JSON[], - searchYear, - pbnstRuseFcltId - ) as unknown as PrfType - ); - // cellClick(cellNum) - } - }, [inputData, searchYear, pbnstRuseFcltId, pageNation,cellNum]);*/ const { t } = useTranslation('base'); const onSave = useCallback(() => { @@ -86,19 +72,20 @@ export default function PrfmncPrfmncReg() { if (!pbnstRuseFcltId) return; prfmnRegData( - pageNation, + 1, '41', excelToPbnPrfData( inputData as unknown as JSON[], searchYear, pbnstRuseFcltId ) as unknown as PrfType - , searchYear + , searchYear, + prfPbnFclts ); }; confirmToast(t('isUpdateMsg'), handleConfirm); - }, [inputData, searchYear, pbnstRuseFcltId, pageNation, cellNum]); + }, [inputData, searchYear, pbnstRuseFcltId, cellNum,prfPbnFclts]); const cellClick = useCallback( (index: number | undefined) => { @@ -194,10 +181,15 @@ export default function PrfmncPrfmncReg() { useEffect(() => { if (!prfmnc.isInit) { - const year = new Date().getFullYear() - prfmncHasuInit(1, '41', String(year)); + getPrfFmcRes() } - }, [prfmnc.isInit, prfmncHasuInit]); + }, [prfmnc.isInit, getPrfFmcRes]); + + + useEffect(() =>{ + const year = new Date().getFullYear() + prfmncHasuInit(1, '41',String(year) ,prfPbnFclts); + },[prfPbnFclts]) useEffect(() => { @@ -254,14 +246,8 @@ export default function PrfmncPrfmncReg() { <div className="flex flex-row space-x-2"> <Button size={"sm"} onClick={() => { - if (searchTxt && searchTxt?.length > 0) { - prfmncHasuNmSearch(1, '41', searchYear, searchTxt) - setPageNation(1) - } else { - prfmncHasuInit(1, '41', searchYear) - setPageNation(1) - } - + + setIsReset(true) }}> 조회 </Button> @@ -314,10 +300,15 @@ export default function PrfmncPrfmncReg() { setCellNum(index ?? 0); }} onPageChange={ - (page) => { - prfmncHasuInit(page, '41', searchYear); - setPageNation(page) + (page:number) => { + if (searchTxt && searchTxt?.length > 0) { + prfmncHasuNmSearch(page, '41', searchYear, searchTxt,prfPbnFclts) + } else { + prfmncHasuInit(page, '41', searchYear,prfPbnFclts) + } + setIsReset(false); }} + resetPageNo={isReset} /> </ScrollArea> </ListDiv> @@ -350,9 +341,10 @@ export default function PrfmncPrfmncReg() { setIsExcelOPen({ ...isExcelOpen, isModal: open }) }} setModalExcelData={async (excelData) => { - await prfmnRegData(pageNation, '41', + await prfmnRegData(1, '41', excelData, searchYear + ,prfPbnFclts ); // 데이터 저장 후 UI 업데이트는 useEffect가 감지하여 처리하므로 여기서는 호출하지 않습니다. } diff --git a/apps/wr/app/store/matDmd/ruseCaseMng/headList.tsx b/apps/wr/app/store/matDmd/ruseCaseMng/headList.tsx index 8c3a232e7..bc71fbf81 100644 --- a/apps/wr/app/store/matDmd/ruseCaseMng/headList.tsx +++ b/apps/wr/app/store/matDmd/ruseCaseMng/headList.tsx @@ -1,7 +1,6 @@ import type { SelectDataType } from "@common/business_components/ui"; import type { TableUpperProps } from "../../common/type/header"; -//★☆★☆ 여기서부터 수정하기 ★☆★☆ export const ruseCaseHeadListExport: TableUpperProps[] = [ { id: "ruseBizNm", @@ -358,6 +357,7 @@ export const ruseCaseHeadListExport: TableUpperProps[] = [ ]; export const ruseUtzType: SelectDataType[] = [ + { text: "전체", val: "0" }, { text: "조경용수", val: "조경용수" }, { text: "청소화장실용수", val: "청소화장실용수" }, { text: "세척살수용수", val: "세척살수용수" }, diff --git a/apps/wr/app/store/matDmd/ruseCaseMng/index.tsx b/apps/wr/app/store/matDmd/ruseCaseMng/index.tsx index 5ae2e67b4..160e1f7f3 100644 --- a/apps/wr/app/store/matDmd/ruseCaseMng/index.tsx +++ b/apps/wr/app/store/matDmd/ruseCaseMng/index.tsx @@ -4,90 +4,93 @@ import type { TableUpperProps } from "../../common/type/header"; import { ruseCaseHeadListExport } from "./headList"; export type ruseCaseState = { ruseCaseMng: { - ruseHeadList:TableUpperProps[]; - ruseCaseMngList:ruseCaseMngExcelProps[]; + ruseHeadList: TableUpperProps[]; + ruseCaseMngList: ruseCaseMngExcelProps[]; status: number; count: number; + excelList?: ruseCaseMngExcelProps[]; }; }; export interface ruseCaseMngExcelProps { - ruseBizNm: string, - bizBgngDate: string, - bizEndDate: string, - splyFcltKnd: string, - splyFcltNm: string, - splyFcltCpct: number | 0 |'', - dmdFcltNm: string, - dmdFcltAddr: string, - ruseFcltCpct: number | 0 |'', - ruseFcltPplLen: string, - ruseFcltUsg: string, - ruseFcltSplyCpct: number | 0 |'', - ruseFcltPrcsMsrc: string, - grnteWqUsg: string, - grnteWqGrssClfg: number | 0 |'', - grnteWqCombResdch: number | 0 |'', - grnteWqTrbt: string, - grnteWqBod: string, - grnteWqSmll: string, - grnteWqCrmty: string, - grnteWqTn: string, - grnteWqTp: string, - grnteWqPh: string, - grnteWqClIonQnt: string, - grnteWqCndctStat: string, - grnteWqRmrk: string, - reqBizReuseFcltCst: number | 0 |'', - reqBizPplCst: number | 0 |'', - reqBizArchCst: number | 0 |'', - reqBizMchnCst: number | 0 |'', - reqBizMtrngCst: number | 0 |'', - reqBizGisCst: number | 0 |'', - reqBizCctvCst: number | 0 |'', - reqBizCmcnCst: number | 0 |'', - reqBizWstCst: number | 0 |'', - reqBizDesignCst: number | 0 |'', - reqBizSpvsCst: number | 0 |'', - reqBizSbsdCst: number | 0 |'', - reqBizEtc: string, - reqBizGrssCst: number | 0 |'', - prcmPlanNlep: number | 0 |'', - prcmPlanLcep: number | 0 |'', - prcmPlanBrdnCst: number | 0 |'', - prcmPlanEcqrRt: number | 0 |'', - prcmPlanGrssCst: number | 0 |'', - clclnNlep: number | 0 |'', - clclnLcep: number | 0 |'', - clclnBrdnCst: number | 0 |'', - clclnEcqrRt: number | 0 |'', - clclnGrssCst: number | 0 |'', + ruseBizNm: string, + bizBgngDate: string, + bizEndDate: string, + splyFcltKnd: string, + splyFcltNm: string, + splyFcltCpct: number | 0 | '', + dmdFcltNm: string, + dmdFcltAddr: string, + ruseFcltCpct: number | 0 | '', + ruseFcltPplLen: string, + ruseFcltUsg: string, + ruseFcltSplyCpct: number | 0 | '', + ruseFcltPrcsMsrc: string, + grnteWqUsg: string, + grnteWqGrssClfg: number | 0 | '', + grnteWqCombResdch: number | 0 | '', + grnteWqTrbt: string, + grnteWqBod: string, + grnteWqSmll: string, + grnteWqCrmty: string, + grnteWqTn: string, + grnteWqTp: string, + grnteWqPh: string, + grnteWqClIonQnt: string, + grnteWqCndctStat: string, + grnteWqRmrk: string, + reqBizReuseFcltCst: number | 0 | '', + reqBizPplCst: number | 0 | '', + reqBizArchCst: number | 0 | '', + reqBizMchnCst: number | 0 | '', + reqBizMtrngCst: number | 0 | '', + reqBizGisCst: number | 0 | '', + reqBizCctvCst: number | 0 | '', + reqBizCmcnCst: number | 0 | '', + reqBizWstCst: number | 0 | '', + reqBizDesignCst: number | 0 | '', + reqBizSpvsCst: number | 0 | '', + reqBizSbsdCst: number | 0 | '', + reqBizEtc: string, + reqBizGrssCst: number | 0 | '', + prcmPlanNlep: number | 0 | '', + prcmPlanLcep: number | 0 | '', + prcmPlanBrdnCst: number | 0 | '', + prcmPlanEcqrRt: number | 0 | '', + prcmPlanGrssCst: number | 0 | '', + clclnNlep: number | 0 | '', + clclnLcep: number | 0 | '', + clclnBrdnCst: number | 0 | '', + clclnEcqrRt: number | 0 | '', + clclnGrssCst: number | 0 | '', } type ruseCaseActions = { - selectRuseCaseMng: (pageNo: number, pageSize: number, sidoCd: string, sigunguCd: string, usageCd : string, name: string) => Promise<void>; + ruseCaseMngInit: () => void; + selectRuseCaseMng: (isExcel: boolean, pageNo: number, pageSize: number, sidoCd: string, sigunguCd: string, usageCd: string, name: string) => Promise<void>; insertRuseCaseMng: (data: any) => Promise<void>; }; -export const fetchSearchRuseCaseMng = async (pageNo: number, pageSize: number, sidoCd: string, sigunguCd: string, usageCd : string, name: string) => { - const tailUrl = '/'+pageNo+'/'+pageSize+ ((sigunguCd !== '전체' && sigunguCd !=='') ? `/${sigunguCd}` : (sidoCd != '전체' && sidoCd != '') ? `/${sidoCd}` : `/0`) + (usageCd? `/${usageCd}` : '/0') + (name? `/${name}` : ''); - const resp = await getFetchWithCount(fetchType.WR,`/reuseFc/pubFcRuseCase${tailUrl}`); - return {data:resp.data, count:resp.count}; +export const fetchSearchRuseCaseMng = async (pageNo: number, pageSize: number, sidoCd: string, sigunguCd: string, usageCd: string, name: string) => { + const tailUrl = '/' + pageNo + '/' + pageSize + ((sigunguCd !== '전체' && sigunguCd !== '') ? `/${sigunguCd}` : (sidoCd != '전체' && sidoCd != '') ? `/${sidoCd}` : `/0`) + (usageCd ? `/${usageCd}` : '/0') + (name ? `/${name}` : ''); + const resp = await getFetchWithCount(fetchType.WR, `/reuseFc/pubFcRuseCase${tailUrl}`); + return { data: resp.data, count: resp.count }; }; export const fetchInsertRuseCaseMng = async (data: any) => { const response = await postFectch('/reuseFc/pubFcRuseCase', data, fetchType.WR); - return {data:response.data, status:response.status}; + return { data: response.data, status: response.status }; }; export type ruseCaseType = ruseCaseState & ruseCaseActions; export const ruseCaseStateExport: ruseCaseState = { ruseCaseMng: { - ruseHeadList:ruseCaseHeadListExport, - ruseCaseMngList:[], + ruseHeadList: ruseCaseHeadListExport, + ruseCaseMngList: [], status: 0, count: 0, + excelList: undefined, }, }; @@ -95,8 +98,8 @@ export const ruseCaseActionsExport: (set: any) => ruseCaseActions = ( set: any ) => { return { - selectRuseCaseMng: async (pageNo: number, pageSize: number, sidoCd: string, sigunguCd: string, usageCd : string, name: string) => { - const res = await fetchSearchRuseCaseMng(pageNo, pageSize, sidoCd, sigunguCd, usageCd, name); + ruseCaseMngInit: async () => { + const res = await getFetchWithCount(fetchType.WR, `/reuseFc/pubFcRuseCase/1/10/0/0`); set((state: ruseCaseState) => ({ ruseCaseMng: { ...state.ruseCaseMng, @@ -105,12 +108,35 @@ export const ruseCaseActionsExport: (set: any) => ruseCaseActions = ( }, })); }, + selectRuseCaseMng: async (isExcel: boolean, pageNo: number, pageSize: number, sidoCd: string, sigunguCd: string, usageCd: string, name: string) => { + const res = await fetchSearchRuseCaseMng(pageNo, pageSize, sidoCd, sigunguCd, usageCd, name); + if (isExcel) { + set((state: ruseCaseState) => { + return { + ...state, + ruseCaseMng: { + ...state.ruseCaseMng, + count: res.count, + excelList: res.data + }, + }; + }); + } else { + set((state: ruseCaseState) => ({ + ruseCaseMng: { + ...state.ruseCaseMng, + ruseCaseMngList: res.data, + count: res.count, + }, + })); + } + }, insertRuseCaseMng: async (data: any) => { const response = await fetchInsertRuseCaseMng(data); - if(response.status === 200){ + if (response.status === 200) { toast.success("물재이용사례 등록이 완료되었습니다. "); - }else{ + } else { toast.error("물재이용사례 등록에 실패하였습니다. "); } set((state: ruseCaseState) => ({ diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx index 6d6ef18a6..a484f87c2 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rainChkgdn/excel.tsx @@ -6,6 +6,7 @@ import { isInvalidNumber, parseRawValue, } from "@/components/lib/func/excelFunc"; +import toast from "react-hot-toast"; export const useTypes = [ "조경용수", "청소화장실용수", @@ -16,6 +17,18 @@ export const useTypes = [ "기타", ]; + +export const chkMngType =[ + '위탁', + '자체' +] +export const chkSpwtPositnType = [ + '유량계', + '수위계', + '펌프적산전력계', + '기타' +] + export type Buildingtype = { bdstInfoSn: number; ctpvCd: 1; @@ -143,43 +156,56 @@ export const excelToRainChkData = (excelData: any, year: string) => { }) .filter((el: any) => el !== undefined); +console.log("rainChkgdData", rainChkgdData); if (rainChkgdData.length > 0) { rainChkgdData.forEach((rain: any) => { const defaultMessage = `[시설명: ${rain.bdstNm}, 점검일: ${rain.chckYmd}, 이용용도: ${rain.guideDetails[0]?.utztnUsgCd}] 항목에서 `; if (rain.chckYmd && isInvalidDate(rain.chckYmd)) { issues.push( - defaultMessage + `점검일: 날짜 형식 아님 (${rain.chckYmd})` + defaultMessage + `점검일: 날짜 형식 아님 입력값 : (${rain.chckYmd})` ); } if (rain.anlOperCst.length > 2 && isInvalidNumber(rain.anlOperCst)) { issues.push( defaultMessage + - ` 연간운영비(원/년): 숫자 형식 아님 (${rain.anlOperCst})` + ` 연간운영비(원/년): 숫자 형식 아님 /입력값:${rain.anlOperCst}` ); } + if (rain.oilqMeasMthd.length > 1 && !chkMngType.includes(rain.oilqMeasMthd)) { + issues.push( + defaultMessage + `유량측정방법: 위탁 혹은 자체 만 허용) /입력값:${rain.oilqMeasMthd}` + ); + } + if (rain.spwtPositn.length > 1 && !chkSpwtPositnType.includes(rain.spwtPositn)) { + issues.push( + defaultMessage + `측정위치: 유량계, 수위계, 펌프적산전력계, 기타 중 하나만 허용) /입력값:${rain.spwtPositn}` + ); + } + + rain.rainyDetails?.forEach((key) => { if (key.ph?.length > 1 && isInvalidNumber(key.ph)) { - issues.push(defaultMessage + `PH: 숫자 형식 아님 (${key.ph})`); + issues.push(defaultMessage + `PH: 숫자 형식 아님 /입력값:${key.ph}`); } if (key.trbt?.length > 1 && isInvalidNumber(key.trbt)) { - issues.push(defaultMessage + `탁도: 숫자 형식 아님 (${key.trbt})`); + issues.push(defaultMessage + `탁도: 숫자 형식 아님 /입력값:${key.trbt}`); } if (key.grssClfg?.length > 1 && isInvalidNumber(key.grssClfg)) { issues.push( - defaultMessage + `총대장균군수: 숫자 형식 아님 (${key.grssClfg})` + defaultMessage + `총대장균군수: 숫자 형식 아님 /입력값:${key.grssClfg}` ); } if (key.levyAmt?.length > 1 && isInvalidNumber(key.levyAmt)) { issues.push( defaultMessage + - `과태료부과금액(천원): 숫자 형식 아님 (${key.levyAmt})` + `과태료부과금액(천원): 숫자 형식 아님 /입력값:${key.levyAmt}` ); } if (key.vltnDt?.length > 2 && isInvalidDate(key.vltnDt)) { issues.push( defaultMessage + - `과태료 부과일(위반일): 날짜 형식 아님 (${key.vltnDt})` + `과태료 부과일(위반일): 날짜 형식 아님 /입력값:${key.vltnDt}` ); } }); @@ -188,17 +214,19 @@ export const excelToRainChkData = (excelData: any, year: string) => { if (isInvalidNumber(guide.splyUswtrUtztnQnt)) { issues.push( defaultMessage + - `대체_${mm}: 숫자 형식 아님 (${guide.splyUswtrUtztnQnt})` + `대체_${mm}: 숫자 형식 아님 /입력값:${guide.splyUswtrUtztnQnt}` ); } if (isInvalidNumber(guide.ruseFcltUtztnQnt)) { issues.push( defaultMessage + - `빗물_${mm}: 숫자 형식 아님 (${guide.ruseFcltUtztnQnt})` + `빗물_${mm}: 숫자 형식 아님 /입력값:${guide.ruseFcltUtztnQnt}` ); } }); }); + }else{ + toast.error("데이터가 없습니다. 점검 데이터를 확인해주세요."); } if (issues.length > 0) { diff --git a/apps/wr/app/store/prfmncReg/chkgdnReg/rswrtChkgdn/excel.tsx b/apps/wr/app/store/prfmncReg/chkgdnReg/rswrtChkgdn/excel.tsx index 262b1cb30..aa550dcd1 100644 --- a/apps/wr/app/store/prfmncReg/chkgdnReg/rswrtChkgdn/excel.tsx +++ b/apps/wr/app/store/prfmncReg/chkgdnReg/rswrtChkgdn/excel.tsx @@ -1,5 +1,10 @@ import type { SelectDataType } from "@common/business_components/ui"; -import { useTypes, type Buildingtype } from "../rainChkgdn/excel"; +import { + chkMngType, + chkSpwtPositnType, + useTypes, + type Buildingtype, +} from "../rainChkgdn/excel"; import { TEST_UUID } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import type { rswtChkZodType } from "."; import { @@ -171,14 +176,14 @@ export const excelToRswtGuideData = ( .filter((el: any) => el !== undefined); if (rswtChkgdData.length > 0) { - rswtExcelDataCheck(rswtChkgdData,issues) + rswtExcelDataCheck(rswtChkgdData, issues); } if (issues.length > 0) { return { data: [], issues }; } - return { data:rswtChkgdData, issues: [] }; + return { data: rswtChkgdData, issues: [] }; }; export const excelToRswtPolution = (excelData: any, issues: string[]) => { @@ -248,25 +253,25 @@ export const excelToRswtPolution = (excelData: any, issues: string[]) => { }) .filter((el: any) => el !== undefined); if (rswtChkgdData.length > 0) { - rswtExcelDataCheck(rswtChkgdData,issues) + rswtExcelDataCheck(rswtChkgdData, issues); } if (issues.length > 0) { return { data: [], issues }; } - return { data:rswtChkgdData, issues: [] }; + return { data: rswtChkgdData, issues: [] }; }; - -const rswtExcelDataCheck=(rswtChkgdData:rswtChkZodType[], issues:string[]) =>{ +const rswtExcelDataCheck = ( + rswtChkgdData: rswtChkZodType[], + issues: string[] +) => { rswtChkgdData.forEach((rswt: any) => { const defaultMessage = `*중수도 수질 [NO: ${rswt.bdstRuseFcltSn}, 점검일: ${rswt.chckYmd}, 이용용도: ${rswt.utztnUsgCd}] 항목에서 `; if (rswt.chckYmd && isInvalidDate(rswt.chckYmd)) { - issues.push( - defaultMessage + `점검일: 날짜 형식 아님 (${rswt.chckYmd})` - ); + issues.push(defaultMessage + `점검일: 날짜 형식 아님 (${rswt.chckYmd})`); } if (rswt.anlOperCst.length > 2 && isInvalidNumber(rswt.anlOperCst)) { issues.push( @@ -279,6 +284,25 @@ const rswtExcelDataCheck=(rswtChkgdData:rswtChkZodType[], issues:string[]) =>{ defaultMessage + ` 처리용량(m³): 숫자 형식 아님 (${rswt.prcsCpct})` ); } + if ( + rswt.oilqMeasMthd.length > 1 && + !chkMngType.includes(rswt.oilqMeasMthd) + ) { + issues.push( + defaultMessage + + `유량측정방법: 위탁 혹은 자체 만 허용) /입력값:${rswt.oilqMeasMthd}` + ); + } + if ( + rswt.spwtPositn.length > 1 && + !chkSpwtPositnType.includes(rswt.spwtPositn) + ) { + issues.push( + defaultMessage + + `측정위치: 유량계, 수위계, 펌프적산전력계, 기타 중 하나만 허용) /입력값:${rswt.spwtPositn}` + ); + } + if (rswt?.rswtrPollutions && rswt?.rswtrPollutions.length > 0) { rswt.rswtrPollutions.forEach((pol) => { if (isInvalidNumber(pol.grssClfgUswtr)) { @@ -301,8 +325,7 @@ const rswtExcelDataCheck=(rswtChkgdData:rswtChkZodType[], issues:string[]) =>{ } if (isInvalidNumber(pol.bod)) { issues.push( - defaultMessage + - `${pol.node}분기_BOD: 숫자 형식 아님 (${pol.bod})` + defaultMessage + `${pol.node}분기_BOD: 숫자 형식 아님 (${pol.bod})` ); } if (isInvalidNumber(pol.smll)) { @@ -319,8 +342,7 @@ const rswtExcelDataCheck=(rswtChkgdData:rswtChkZodType[], issues:string[]) =>{ } if (isInvalidNumber(pol.tph)) { issues.push( - defaultMessage + - `${pol.node}분기_T-P: 숫자 형식 아님 (${pol.tph})` + defaultMessage + `${pol.node}분기_T-P: 숫자 형식 아님 (${pol.tph})` ); } if (isInvalidNumber(pol.tn)) { @@ -358,7 +380,5 @@ const rswtExcelDataCheck=(rswtChkgdData:rswtChkZodType[], issues:string[]) =>{ } }); } - }) - - -} \ No newline at end of file + }); +}; diff --git a/apps/wr/app/store/prfmncReg/pbnstPrfmncReg/index.tsx b/apps/wr/app/store/prfmncReg/pbnstPrfmncReg/index.tsx index fbdd4fba6..6c2564655 100644 --- a/apps/wr/app/store/prfmncReg/pbnstPrfmncReg/index.tsx +++ b/apps/wr/app/store/prfmncReg/pbnstPrfmncReg/index.tsx @@ -7,16 +7,17 @@ import toast from "react-hot-toast"; const pbnstPrfmncHeadList = pbnstPrfmncHeadListExport; const monthHeadList = monthHeadListExport; - +export const prfRegPageSize = 10; export type pbnstPrfmncState = { prfmnc: { isInit: boolean; pbnstPrfmncHeadList: TableUpperProps[]; monthHeadList: TableUpperProps[]; prfmncRes: FcPrfType[]; - prfmncResCount:number; + prfmncResCount: number; excelList: number[]; - pageKey:number + pageKey: number; + prfPbnFclts: string[]; }; }; @@ -26,68 +27,126 @@ export const pbnstPrfmncStateExport: pbnstPrfmncState = { pbnstPrfmncHeadList: pbnstPrfmncHeadList, monthHeadList: monthHeadList, prfmncRes: [], - prfmncResCount:1, + prfPbnFclts: [], + prfmncResCount: 1, excelList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], - pageKey:1 + pageKey: 1, }, }; export type pbnstPrfmncType = pbnstPrfmncState & pbnstPrfmncActions; type pbnstPrfmncActions = { - prfmncHasuInit: (page: number, sggOrCity: string ,year:string) => void; - prfmncHasuNmSearch: (page: number, sggOrCity: string , txt:string ,year:string) => void; - prfmnRegData: (page:number,sggOrCity:string, data: PrfType,year:string) => void; + prfmncHasuInit: ( + page: number, + sggOrCity: string, + year: string, + prfPbnFclts: string[] + ) => void; + prfmncHasuNmSearch: ( + page: number, + sggOrCity: string, + year: string, + searchTxt: string, + prfPbnFclts: string[] + ) => void; + prfmnRegData: ( + page: number, + sggOrCity: string, + data: PrfType, + year: string, + prfPbnFclts: string[] + ) => void; + getPrfFmcRes: () => void; }; -const checkWrRegList = async (year:string) => { - const url =`/reuseFc/pubDetailList` - if(year&& year.length>0){ - // url+=`/${year}` +const hasuListFetch = async ( + page: number, + sggOrCity: string, + year: string, + prfPbnFclts: string[], + searchTxt?: string +) => { + let filteredFclt = prfPbnFclts; + if (sggOrCity !== "0") { + filteredFclt = prfPbnFclts?.filter((fclt: string) => { + return sggOrCity.length == 2 + ? fclt.slice(0, 2) === sggOrCity + : fclt.slice(0, 5) === sggOrCity; + }); } - const wrRegList = await getFetch("wr", url); - return wrRegList; -}; -const hasuListFetch = async (page: number, sggOrCity: string , year:string,searchNm?:string ) => { - const checkWrRegListRes = await checkWrRegList(year); - const rainRes = await postFectch( - `/prcsFclt/ruseInfo/${page ? page : 1}/10/A/${sggOrCity ? sggOrCity : "11"}/0/1/SW`, - checkWrRegListRes?.fcltCds, - fetchType.COMMON + + let url = `/prcsFclt/ruseInfo/1/${filteredFclt.length + 1}/A/${sggOrCity}/0/1/SW`; + if (searchTxt && searchTxt?.length > 0) { + url += `/${searchTxt}`; + } + const rainRes = await postFectch(url, filteredFclt, fetchType.COMMON); + + const checkRuseFcltList = + searchTxt && searchTxt?.length > 0 + ? rainRes.data.map((item) => item.bscFctCd) + : filteredFclt; + + const pubRuseList = await postFectch( + `/reuseFc/pubDetailList/${year}/${sggOrCity}/${page}/${prfRegPageSize}`, + checkRuseFcltList, + fetchType.WR ); - let findData = rainRes.data.map((item: pubHasuType) => { - const data = checkWrRegListRes?.fcPrfList.find( - (fclt: FcPrfType) => - fclt.pbnstRuseFcltId.substring(0, 11) === item?.bscFctCd - ); - if(data !==undefined){ - return( { + const rusePrfList = pubRuseList.data + .map((item: FcPrfType) => { + const findData = rainRes.data?.find( + (fclt: pubHasuType) => + item.pbnstRuseFcltId.substring(0, 11) === fclt?.bscFctCd + ); + if (findData !== undefined) { + return { + sido: findData.sido, + gugun: findData.gugun, + bscFctNm: findData.bscFctNm, + bscFctCd: findData.bscFctCd, + ruseUtztnFcltNm: item.ruseUtztnFcltNm, + pbnstRuseFcltId: item.pbnstRuseFcltId, + prfList: item.prfList, + }; + } + }) + .filter(Boolean); // undefined 값을 제거합니다. - sido: item.sido, - gugun: item.gugun, - bscFctNm: item.bscFctNm, - bscFctCd: item.bscFctCd, - ruseUtztnFcltNm: data.ruseUtztnFcltNm, - pbnstRuseFcltId: data.pbnstRuseFcltId, - prfList: data.prfList, - }); - } - }).filter(Boolean); // undefined 값을 제거합니다. - - if(searchNm){ - - findData= findData.filter((ruse:any) => ruse.ruseUtztnFcltNm.includes(searchNm)) - } - - return {data:findData, count:findData.length}; + return { data: rusePrfList, count: pubRuseList.count }; }; export const pbnstPrfmncActionsExport: (set: any) => pbnstPrfmncActions = ( set: any ) => { return { - prfmncHasuInit: async (page: number, sggOrCity: string,year:string) => { + getPrfFmcRes: async () => { try { - const prfmncRes = await hasuListFetch(page, sggOrCity, year); + const pbnPrfRes = await getFetch(fetchType.WR, "/reuseFc/pubFc"); + console.log("pbnPrfRes ", pbnPrfRes); + set((state: pbnstPrfmncState) => ({ + ...state, + prfmnc: { + ...state.prfmnc, + prfPbnFclts: pbnPrfRes, + }, + })); + } catch (error) { + console.log(error); + } + }, + prfmncHasuInit: async ( + page: number, + sggOrCity: string, + year: string, + prfPbnFclts: string[] + ) => { + try { + console.log("prfPbnFclts ", prfPbnFclts); + const prfmncRes = await hasuListFetch( + page, + sggOrCity, + year, + prfPbnFclts + ); return set((state: pbnstPrfmncState) => ({ ...state, prfmnc: { @@ -101,9 +160,21 @@ export const pbnstPrfmncActionsExport: (set: any) => pbnstPrfmncActions = ( console.log(errorHasu); } }, - prfmncHasuNmSearch: async (page: number, sggOrCity: string,fcltNm:string ,year:string)=> { + prfmncHasuNmSearch: async ( + page: number, + sggOrCity: string, + year: string, + searchTxt: string, + prfPbnFclts: string[] + ) => { try { - const prfmncRes = await hasuListFetch(page, sggOrCity,fcltNm ,year); + const prfmncRes = await hasuListFetch( + page, + sggOrCity, + year, + prfPbnFclts, + searchTxt + ); return set((state: pbnstPrfmncState) => ({ ...state, prfmnc: { @@ -117,7 +188,13 @@ export const pbnstPrfmncActionsExport: (set: any) => pbnstPrfmncActions = ( console.log(errorHasu); } }, - prfmnRegData: async (page:number,sggOrCity:string,data: PrfType,year:string) => { + prfmnRegData: async ( + page: number, + sggOrCity: string, + data: PrfType, + year: string, + prfPbnFclts: string[] + ) => { try { const ressponse = await postFectch( "/reuseFc/pubFcPrf", @@ -125,11 +202,14 @@ export const pbnstPrfmncActionsExport: (set: any) => pbnstPrfmncActions = ( fetchType.WR ); - if (ressponse.status === 200) { toast.success("하수재이용 시설 실적 등록이 완료되었습니다."); - const prfmncRes = await hasuListFetch(page, sggOrCity,year) ; - + const prfmncRes = await hasuListFetch( + page, + sggOrCity, + year, + prfPbnFclts + ); return set((state: pbnstPrfmncState) => ({ ...state, @@ -138,10 +218,9 @@ export const pbnstPrfmncActionsExport: (set: any) => pbnstPrfmncActions = ( prfmncRes: prfmncRes.data, prfmncResCount: prfmncRes.count, isInit: false, - pageKey: state.prfmnc.pageKey + 1 + pageKey: state.prfmnc.pageKey + 1, }, })); - } } catch (e) { console.log(e); diff --git a/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx b/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx index 2589422c8..0fb24366a 100644 --- a/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx +++ b/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx @@ -488,16 +488,6 @@ export function PbnstBuseForm({ /> </div> - {/* <MngRegFormDetail - formList={ruseWaterQulityList} - h1Title={`하수처리수 재이용시설 보증수질 `} - subTitle="※재처리시설이 있는 경우만 작성" - form={form} - moClass="grid grid-cols-12 gap-4" - sonClass="col-span-4" - indexMng={indexMng} - indexBiz={indexBiz} - /> */} <div> <BuseWaterQulity diff --git a/apps/wr/components/ui/modal/coMat/ruseCaseMng/ruseCaseMngExcelModal.tsx b/apps/wr/components/ui/modal/coMat/ruseCaseMng/ruseCaseMngExcelModal.tsx index 57424996e..a809c88f6 100644 --- a/apps/wr/components/ui/modal/coMat/ruseCaseMng/ruseCaseMngExcelModal.tsx +++ b/apps/wr/components/ui/modal/coMat/ruseCaseMng/ruseCaseMngExcelModal.tsx @@ -1,14 +1,14 @@ +import { useWrStore } from "@/app/store"; import { coRegExcel } from "@/app/store/matDmd/coSttn/headList"; -import type { ruseCaseMngExcelProps } from "@/app/store/matDmd/ruseCaseMng/index"; import { reUseCaseNames } from "@/app/store/matDmd/ruseCaseMng/excel"; -import { filePicked, FileUpload, FormUi, Title } from "@common/business_components/ui"; -import { Form, FormField } from "@common/business_components/ui/form"; -import { Button } from "@common/components/ui"; +import type { ruseCaseMngExcelProps } from "@/app/store/matDmd/ruseCaseMng/index"; +import { filePicked, Title } from "@common/business_components/ui"; +import { Form } from "@common/business_components/ui/form"; +import { Button, Input } from "@common/components/ui"; import { zodResolver } from "@hookform/resolvers/zod"; import { useState } from "react"; import { useForm } from "react-hook-form"; import type { z } from "zod"; -import { useWrStore } from "@/app/store"; export default function RuseCaseMngExcel() { const { insertRuseCaseMng } = useWrStore((state) => state); @@ -79,6 +79,7 @@ export default function RuseCaseMngExcel() { }; Object.keys(reUseCaseNames).forEach((key: string) => { + console.log("reUseCaseNames", reUseCaseNames) if (item && reUseCaseNames[key] !== undefined) { const mappedKey = reUseCaseNames[key]; if (mappedKey && object.hasOwnProperty(mappedKey)) { @@ -146,23 +147,16 @@ export default function RuseCaseMngExcel() { </div> <div> - <FormField - control={form.control} - name="file" - render={() => ( - <FormUi label=""> - <FileUpload - files={file ? [file] : []} - setFiles={(files: File[] | null) => { - console.log("files", files) - if (files && files?.length === 1) setFiles(files[0]); - }} - fileTypes="" - maxFiles={1} - ></FileUpload> - </FormUi> - )} - /> + <div className="space-y-4 p-4"> + <Input + type="file" + onChange={(e) => { + const selectedFile = e.target.files?.[0]; + if (selectedFile) setFiles(selectedFile); + }} + accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" + /> + </div> </div> </form> </Form> diff --git a/apps/wr/public/sample_ruseCaseMng.xlsx b/apps/wr/public/sample_ruseCaseMng.xlsx index 96027d557..3676b4f71 100644 Binary files a/apps/wr/public/sample_ruseCaseMng.xlsx and b/apps/wr/public/sample_ruseCaseMng.xlsx differ diff --git a/packages/common/business_components/src/ui/date_month_picker/index.tsx b/packages/common/business_components/src/ui/date_month_picker/index.tsx index a8da0ff0e..b31a86414 100644 --- a/packages/common/business_components/src/ui/date_month_picker/index.tsx +++ b/packages/common/business_components/src/ui/date_month_picker/index.tsx @@ -19,6 +19,7 @@ type MonthPickerProps = { readOnly?: boolean; startYear?: number; // 시작 연도 props 추가 yearReadOnly?: boolean; + enableMonth?: string[]; }; // yyyyMM → Date 객체 @@ -41,6 +42,7 @@ export const DateMonthPicker = ({ readOnly = false, startYear, yearReadOnly = false, + enableMonth, }: MonthPickerProps) => { const [open, setOpen] = useState(false); @@ -81,6 +83,7 @@ export const DateMonthPicker = ({ onMonthChange={handleSelect} startYear={startYear} yearReadOnly={yearReadOnly} + enableMonth={enableMonth} /> </PopoverContent> </Popover> diff --git a/packages/common/business_components/src/ui/date_month_picker/mothPicker.tsx b/packages/common/business_components/src/ui/date_month_picker/mothPicker.tsx index b5bc10ba5..9b408183b 100644 --- a/packages/common/business_components/src/ui/date_month_picker/mothPicker.tsx +++ b/packages/common/business_components/src/ui/date_month_picker/mothPicker.tsx @@ -30,9 +30,10 @@ export type MonthPickerProps = { ) => void; startYear?: number; yearReadOnly?: boolean; + enableMonth?: string[]; }; -export function MonthPicker({ currentMonth, onMonthChange, startYear, yearReadOnly }: MonthPickerProps) { +export function MonthPicker({ currentMonth, onMonthChange, startYear, yearReadOnly, enableMonth }: MonthPickerProps) { const today = startOfToday(); const currentYear = today.getFullYear(); @@ -61,9 +62,9 @@ const selectedYear = parseInt(yearFromProp); "inline-flex h-9 w-16 items-center justify-center rounded-md p-0 text-sm font-normal ring-offset-white transition-colors hover:bg-slate-100 hover:text-slate-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-400 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 aria-selected:opacity-100 dark:ring-offset-slate-950 dark:hover:bg-slate-800 dark:hover:text-slate-50 dark:focus-visible:ring-slate-800", isEqual(month, currentMonth) && "bg-slate-900 text-slate-50 hover:bg-slate-900 hover:text-slate-50 focus:bg-slate-900 focus:text-slate-50 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50 dark:hover:text-slate-900 dark:focus:bg-slate-50 dark:focus:text-slate-900", - !isEqual(month, currentMonth) && - isEqual(month, getStartOfCurrentMonth()) && - "bg-slate-100 text-slate-900 dark:bg-slate-800 dark:text-slate-50" + // !isEqual(month, currentMonth) && + // isEqual(month, getStartOfCurrentMonth()) && + // "bg-slate-100 text-slate-900 dark:bg-slate-800 dark:text-slate-50" ); return ( @@ -113,7 +114,7 @@ const selectedYear = parseInt(yearFromProp); <button name="month" className={getMonthButtonClass(month)} - disabled={isFuture(month)} + disabled={isFuture(month) || (enableMonth && !enableMonth?.includes(format(month, 'MMM', { locale: ko })))} role="gridcell" tabIndex={-1} type="button" diff --git a/packages/common/business_components/src/ui/map/Gis.js b/packages/common/business_components/src/ui/map/Gis.js index 117601cc3..eefb08da6 100644 --- a/packages/common/business_components/src/ui/map/Gis.js +++ b/packages/common/business_components/src/ui/map/Gis.js @@ -99,6 +99,7 @@ function Gis({ onFeatureSelect, setIsSearchModalOpen, onCheckedLayersChange, + searchBar: SearchBar }) { const mapRef = useRef(); const [mapObject, setMapObject] = useState({}); @@ -127,7 +128,6 @@ function Gis({ // Feature Click Event const handleFeatureSelect = useCallback((data) => { - console.log(data); onFeatureSelect?.(data); // 선택된 피쳐 데이터 콜백 호출 }, [mapInstanceRef]); @@ -240,120 +240,6 @@ function Gis({ } } - // // 데이터 로드 및 팝업 생성 로직 - // useEffect(() => { - // if (!mapInstanceRef.current) return; // 맵이 생성되지 않았으면 실행 안 함 - - // // 1. 팝업 데이터 가져오기 (feature.js의 getData와 유사) - // const fetchPopupData = async () => { - // // 실제 API 호출 로직으로 대체해야 합니다. - // // 예시: const response = await yourApiService.getFcltyWtCnt(); - // // setFacilityInfoPopupData(response.data); - - // // 임시 목업 데이터 - // const mockData = [ - // { ftrIdn: 1, ftrCde: 'SA206', bplcNm: '처리장A', fcltyUseYn: 'Y', x: 127.005, y: 37.282, aCnt: 10, cCnt: 5, eCnt: 3, mCnt: 8, iCnt: 2 }, - // { ftrIdn: 2, ftrCde: 'SA112', bplcNm: '처리장B', fcltyUseYn: 'N', x: 127.010, y: 37.285, aCnt: 8, cCnt: 4, eCnt: 2, mCnt: 6, iCnt: 1 } - // ]; - // setFacilityInfoPopupData(mockData); - // }; - - // fetchPopupData(); - - // }, [mapInstanceRef.current]); // 맵 인스턴스가 생성된 후 한 번만 실행 - - // // 데이터가 변경되면 오버레이를 생성/업데이트하는 로직 - // useEffect(() => { - // const map = mapInstanceRef.current; - // if (!map || facilityInfoPopupData.length === 0) return; - - // // 기존 오버레이 정리 - // facilityOverlaysRef.current.forEach(overlay => map.removeOverlay(overlay)); - // facilityOverlaysRef.current = []; - - // facilityInfoPopupData.forEach(data => { - // const popupId = `${data.ftrIdn}_${data.ftrCde}`; - - // // 팝업을 담을 div 엘리먼트 생성 - // const popupElement = document.createElement('div'); - // popupElement.id = popupId; - - // // OpenLayers Overlay 생성 - // const position = olProj.transform([Number(data.x), Number(data.y)], GisApp.FROM_PROJ, GisApp.TO_PROJ); - // const overlay = new Overlay({ - // element: popupElement, - // position: position, - // offset: [-75, -210], // 팝업 너비의 절반, 높이만큼 오프셋 조정 - // positioning: 'bottom-center', - // className: 'facility-popup-overlay' // 필요시 공통 클래스 추가 - // }); - - // map.addOverlay(overlay); - // facilityOverlaysRef.current.push(overlay); - - // // React 컴포넌트를 popupElement에 렌더링 - // const root = createRoot(popupElement); - // root.render(<FacilityInfoPopup data={data} />); - // }); - - // // 초기 가시성 업데이트 - // updatePopupVisibility(); - - // }, [facilityInfoPopupData]); // 팝업 데이터가 변경될 때마다 실행 - - // // 레이어 가시성에 따라 팝업 가시성을 제어하는 함수 - // const updatePopupVisibility = useCallback(() => { - // const map = mapInstanceRef.current; - // if (!map) return; - - // const visibleLayers = new Set(); - // map.getLayers().forEach(layer => { - // if (layer.getVisible()) { - // // feature.js의 로직처럼 typeName이나 ftrCde를 사용해 필터링 - // const typeName = layer.get('typeName'); - // if (typeName === 'VW_WTL_FCLTY_AS') { // 예시 레이어 이름 - // visibleLayers.add(layer.get('ftrCde')); - // } - // } - // }); - - // facilityOverlaysRef.current.forEach(overlay => { - // const element = overlay.getElement(); - // const ftrCde = element.querySelector('table')?.classList[0]; // FacilityPopup의 클래스에서 ftrCde 가져오기 - - // if (visibleLayers.has(ftrCde)) { - // element.style.display = ''; - // } else { - // element.style.display = 'none'; - // } - // }); - // }, []); - - // GisTree에서 체크 상태가 변경될 때 이 함수를 호출하도록 연결해야 합니다. - // 예시: GisTree 컴포넌트에 onCheck 콜백을 추가하고, 그 콜백에서 이 함수를 호출 - // useEffect(() => { - // // 레이어 가시성이 변경될 때마다 팝업 가시성 업데이트 - // const map = mapInstanceRef.current; - // if (!map) return; - - // const handleLayerVisibilityChange = () => { - // updatePopupVisibility(); - // }; - - // map.getLayers().on('change:length', handleLayerVisibilityChange); - // map.getLayers().forEach(layer => { - // layer.on('change:visible', handleLayerVisibilityChange); - // }); - - // return () => { - // // 클린업 - // map.getLayers().un('change:length', handleLayerVisibilityChange); - // map.getLayers().forEach(layer => { - // layer.un('change:visible', handleLayerVisibilityChange); - // }); - // }; - // }, [updatePopupVisibility]); - // 체크된 레이어 정보를 처리하는 함수 const handleCheckedLayersChange = useCallback((checkedIds, checkedNodesData) => { setTimeout(() => { @@ -367,45 +253,48 @@ function Gis({ <> <GisContext.Provider value={{ gisCore, gisMap: mapInstanceRef.current, treeData, checkedLayerIds }}> <div className="h-[calc(100vh-10rem)] flex relative"> - <div ref={mapRef} className="gis-map flex-1 relative" style={{ height: '100%', padding: 0 }} /> - <GisTree - visible={tabVisible} - setVisible={setTabVisible} - onCheckedChange={handleCheckedLayersChange} - onLayerIconClick={(layerNm) => { - console.log(layerNm) - layerNmRef.current = layerNm - setLayerNm(layerNm); setIsOpen(true); const dummyFeature = { - getProperties: () => ({}), // 최소 구조 - }; - onFeatureSelect(dummyFeature); - }} - imageVisible={imgVisble} - /> - - {/* <GisContent onFeatureSelect={handleFeatureSelect} isSearch={isSearch} isSearchModalOpen={isSearchModalOpen} setIsSearchModalOpen={setIsSearchModalOpen} /> */} - - {/* DetailView가 존재할 때만 렌더링 isSearchModalOpen이 true면 visible=false로 팝업 숨김 */} - {isOpen && !isSearchModalOpen && ( - <DetailView - featureData={featureData || { getProperties: () => ({}) }} - seletectedLayerNm={layerNm} - onClose={closePopup} // 닫기 콜백 전달 - onFeatureSelect={handleFeatureSelect} + <div ref={mapRef} className="gis-map flex-1 relative" style={{ height: '100%', padding: 0 }} > + <GisTree + visible={tabVisible} + setVisible={setTabVisible} + onCheckedChange={handleCheckedLayersChange} + onLayerIconClick={(layerNm) => { + layerNmRef.current = layerNm + setLayerNm(layerNm); setIsOpen(true); const dummyFeature = { + getProperties: () => ({}), // 최소 구조 + }; + onFeatureSelect(dummyFeature); + }} + imageVisible={imgVisble} /> - )} - {/* SearchView가 존재할 때만 렌더링 */} - {SearchView && ( - <SearchView - open={isSearchModalOpen} - onOpenChange={setIsSearchModalOpen} - onFeatureSelect={handleFeatureSelect} - /> - )} - {/* <GisLonLat /> */} - <GisToolBar /> - <GisMapToggle /> - <GisSelect onFeatureSelect={handleFeatureSelect} /> + + {/* DetailView가 존재할 때만 렌더링 isSearchModalOpen이 true면 visible=false로 팝업 숨김 */} + {isOpen && !isSearchModalOpen && ( + <DetailView + featureData={featureData || { getProperties: () => ({}) }} + seletectedLayerNm={layerNm} + onClose={closePopup} // 닫기 콜백 전달 + onFeatureSelect={handleFeatureSelect} + /> + )} + {/* SearchView가 존재할 때만 렌더링 */} + {SearchView && ( + <SearchView + open={isSearchModalOpen} + onOpenChange={setIsSearchModalOpen} + onFeatureSelect={handleFeatureSelect} + /> + )} + {/* 시도/시군구 조회 영역 */} + {SearchBar && ( + <div className="absolute top-4 left-1/2 -translate-x-1/2 z-30 bg-gray-300 rounded " style={{ maxWidth: 'calc(100% - 2rem)' }}> + <SearchBar/> + </div> + )} + <GisToolBar /> + <GisMapToggle /> + <GisSelect onFeatureSelect={handleFeatureSelect} /> + </div> </div> {isSearch && ( diff --git a/packages/common/business_components/src/ui/map/GisContent.js b/packages/common/business_components/src/ui/map/GisContent.js index d2594ba95..45b44c882 100644 --- a/packages/common/business_components/src/ui/map/GisContent.js +++ b/packages/common/business_components/src/ui/map/GisContent.js @@ -1,74 +1,61 @@ -import { Search } from 'lucide-react'; -import { useCallback, useEffect, useRef, useState } from 'react'; -import { useGisContext } from './Gis'; -import './lib/css/gis.edit.css'; -import GisApp from './lib/gis.core'; +import { Search } from "lucide-react"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { useGisContext } from "./Gis"; +import "./lib/css/gis.edit.css"; +import GisApp from "./lib/gis.core"; -export default function GisContent({ edit = false, onFeatureSelect, isSearch, setIsSearchModalOpen }) { - const { gisMap, gisCore } = useGisContext(); - const [visibleComponents, setVisibleComponents] = useState({}); - const addressResultLayer = useRef(null); - const [playShow, setPlayShow] = useState({ show: false }); +export default function GisContent({ + edit = false, + onFeatureSelect, + isSearch, + setIsSearchModalOpen, +}) { + const { gisMap, gisCore } = useGisContext(); - //셀렉트 버튼 이벤트 - // const clickFeature = useCallback(feature => { - // if (feature) { - // const layer = feature.getLayer(); - // setVisibleComponents(prevState => ({ - // ...prevState, - // })); - // } - // }, []); + //셀렉트 버튼 이벤트 + const selectRslt = useCallback((feature) => { + GisApp.Module.layer.highLightFeature( + [feature], + { + id: GisApp.hlLayerId, + zIndex: 10, + opacity: 1, + selectable: true, + }, + { width: 30 }, + ); + clickFeature(feature); + }, []); - const selectRslt = useCallback(feature => { - GisApp.Module.layer.highLightFeature( - [feature], - { - id: GisApp.hlLayerId, - zIndex: 10, - opacity: 1, - selectable: true, - }, - { width: 30 } - ); - clickFeature(feature); - }, []); + useEffect(() => { + if (gisMap) { + setVisibleComponents((prevState) => ({ + ...prevState, + })); + } + }, [gisMap]); - useEffect(() => { - if (gisMap) { - setVisibleComponents(prevState => ({ - ...prevState, - })); - } - }, [gisMap]); + if (!gisMap) return null; - if (!gisMap) return null; + return ( + <> + <GisTree /> + <GisMapToggle /> + <GisLonLat /> + <GisToolBar /> + <GisSelect onFeatureSelect={onFeatureSelect} /> - return ( - <> - {/*<GisTree />*/} - {/* <GisMapToggle /> - <GisLonLat /> - <GisToolBar /> */} - {/* <GisSelect onFeatureSelect={onFeatureSelect} /> */} - - {/* 검색 모달 */} - {isSearch && ( - <div className="absolute right-8 top-[254px] z-20"> - <button - onClick={() => setIsSearchModalOpen(true)} - className="overflow-hidden w-[40px] h-[40px] bg-white - border border-[#9aa7b8] - rounded - shadow-[0_0_5px_#999] - flex items-center justify-center - p-0 - " - > - <Search size={24} className="text-gray-700" /> - </button> - </div> - )} - </> - ); + {/* 검색 모달 */} + {isSearch && ( + <div className="absolute right-8 top-[254px] z-20"> + <button + onClick={() => setIsSearchModalOpen(true)} + className="flex h-[40px] w-[40px] items-center justify-center overflow-hidden rounded border border-[#9aa7b8] bg-white p-0 shadow-[0_0_5px_#999]" + > + <Search size={24} className="text-gray-700" /> + </button> + </div> + )} + </> + ); } diff --git a/packages/common/business_components/src/ui/map/GisTab.js b/packages/common/business_components/src/ui/map/GisTab.js deleted file mode 100644 index 57d8a48e8..000000000 --- a/packages/common/business_components/src/ui/map/GisTab.js +++ /dev/null @@ -1,84 +0,0 @@ -// import React, { useState } from 'react'; -// import { Tabs, TabsList, TabsTrigger } from '@common/components/ui/tabs'; -// import GisTree from './GisTree'; -// import GisSearch from './GisSearch'; -// import { ChevronLeft, ChevronRight, Search } from 'lucide-react'; -// import SearchModal from '@/map/SearchModal'; - - -// function GisTab({ visible, setVisible, isSearch, isSearchModalOpen, setIsSearchModalOpen, onFeatureSelect }) { -// const [activeTab, setActiveTab] = useState('layers'); - -// return ( -// <> -// <div -// className={`absolute top-0 left-0 w-[250px] h-[calc(100vh-10rem)] bg-white border-r border-gray-300 flex flex-col overflow-hidden transition-all duration-300 z-40 -// ${visible ? 'translate-x-0 opacity-100' : '-translate-x-full opacity-0 pointer-events-none'}`} -// > -// <Tabs value={activeTab} onValueChange={setActiveTab} className="flex-1 flex flex-col overflow-hidden"> -// <TabsList className="flex-none mt-4 border-none rounded-none"> -// <TabsTrigger value="layers" className="flex-1 h-10">레이어</TabsTrigger> -// {/* {isSearch && ( -// <button -// onClick={() => setIsSearchModalOpen(true)} -// className="h-10 w-10 flex items-center justify-center px-0" -// > -// <Search size={18} className="text-gray-700" /> -// </button> -// // <TabsTrigger value="search" className="flex-1 h-10 flex items-center justify-center"> -// // <Search size={18} /> -// // </TabsTrigger> -// )} */} -// </TabsList> - -// {/* GisTree는 항상 마운트되며, 탭 상태에 따라 보여주기만 함 */} -// <div -// className={`grow overflow-y-auto p-2 pt-0 border-none shadow-none ${activeTab === 'layers' ? 'block' : 'hidden' -// }`} -// > -// <GisTree /> -// </div> - -// {/* GisSearch도 동일하게 처리 */} -// {/* {isSearch && ( -// <div -// className={`grow overflow-y-auto p-2 pt-0 border-none shadow-none ${ -// activeTab === 'search' ? 'block' : 'hidden' -// }`} -// > -// <GisSearch /> -// </div> -// )} */} - - -// {/* 🔍 검색 모달 */} -// {/* <SearchModal -// open={isSearchModalOpen} -// onOpenChange={setIsSearchModalOpen} -// onFeatureSelect={onFeatureSelect} -// /> */} -// </Tabs> - -// {/* 접기 버튼 */} -// <button -// onClick={() => setVisible(false)} -// className="absolute top-1/2 right-[-3px] transform -translate-y-1/2 z-50 bg-white border border-l border-gray-300 rounded-l-none rounded-r px-1 py-2 shadow-sm" -// > -// <ChevronLeft size={16} /> -// </button> -// </div> - -// {/* 열기 버튼 */} -// {!visible && ( -// <button -// onClick={() => setVisible(true)} -// className="absolute top-1/2 left-[-3px] transform -translate-y-1/2 z-50 bg-white border border-r border-gray-300 rounded-r px-1 py-2 shadow-sm" -// > -// <ChevronRight size={16} /> -// </button> -// )} -// </> -// ); -// } - -// export default React.memo(GisTab); diff --git a/packages/common/business_components/src/ui/map/lib/gis.layer.js b/packages/common/business_components/src/ui/map/lib/gis.layer.js index d8474ce0a..412b0d8b9 100644 --- a/packages/common/business_components/src/ui/map/lib/gis.layer.js +++ b/packages/common/business_components/src/ui/map/lib/gis.layer.js @@ -147,6 +147,7 @@ GisOlLayer.prototype = { || lyrTyNm == 'tb_ms_sbmrg_dngr_map' || lyrTyNm == 'tb_ms_swage_mhl' || lyrTyNm == 'tb_ms_swage_ppl' + || lyrTyNm == 'tb_ms_swage_pmstn' ) { source = this.getVectorSourceBbox(option); }else {