diff --git a/apps/st/src/components/module/SearchForm.tsx b/apps/st/src/components/module/SearchForm.tsx index 530b3579b..bd15477f8 100644 --- a/apps/st/src/components/module/SearchForm.tsx +++ b/apps/st/src/components/module/SearchForm.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import useSWR from 'swr'; import { @@ -18,9 +18,9 @@ from "@common/components"; import { useAlertStore } from "@/shared/lib"; import { type SearchFormProps, type SearchFormValues, defaultSearchFormProps } from "../type/SearchForm.type"; import { statisticsAPi } from "@/entities/statistics/api/statistics-service"; -import type { ApiResponse, Sido, Sgg } from "@/entities/statistics/model/statistics-interface"; +import type { ApiResponse, SearchCondition, Sgg } from "@/entities/statistics/model/statistics-interface"; -const getSidoListFetcher = async (): Promise> => { +const getSidoListFetcher = async (): Promise> => { return statisticsAPi.getSidoList(); }; @@ -36,8 +36,6 @@ const SearchForm = (props: SearchFormProps = {}) => { const defaultYear = currentYear - 1; const startYear = currentYear - 10; - const yearOptions = Array.from({ length: currentYear - startYear + 1 }, (_, i) => currentYear - i); - const [values, setValues] = useState({ sido: props.defaultValues?.sido || "", gugun: props.defaultValues?.gugun || '', @@ -47,7 +45,11 @@ const SearchForm = (props: SearchFormProps = {}) => { bsnmCd: props.defaultValues?.bsnmCd || '', }); - const { data: sidoList } = useSWR>( + useEffect(() => { + props.onValuesChange?.(values); + }, [values]); + + const { data: sidoList } = useSWR>( "sido-list", getSidoListFetcher, { @@ -111,7 +113,7 @@ const SearchForm = (props: SearchFormProps = {}) => { }; const handleSidoChange = (value: string) => { - const selectedBsnm = sidoList?.data.find((v) => v.sido === value)?.bsnmCd || ''; + const selectedBsnm = sidoList?.data.sidoList.find((v) => v.sido === value)?.bsnmCd || ''; setValues((prev) => ({ ...prev, @@ -136,7 +138,7 @@ const SearchForm = (props: SearchFormProps = {}) => { 선택 - {sidoList?.data?.map((sido) => ( + {sidoList?.data?.sidoList?.map((sido) => ( {sido.sido} @@ -175,7 +177,7 @@ const SearchForm = (props: SearchFormProps = {}) => { - {yearOptions.map((year) => ( + {sidoList?.data?.yearList.map((year) => ( {year}년 diff --git a/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx b/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx index b0069a82a..24a88436c 100644 --- a/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx +++ b/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useState, useMemo } from "react"; import SearchForm from "@/components/module/SearchForm"; // import { DataGrid } from "@rsone/components"; @@ -12,47 +12,63 @@ import { LoadingWithAnimation } from "@common/components"; import { useAlertStore } from "@/shared/lib"; import { statisticsInputAPi } from "@/entities/statistics/api/statistics-input-service"; import type { SearchFormValues } from "@/components/type/SearchForm.type"; -import type { SewerageSupplyRateItem } from "@/entities/statistics/model/statistics-input-interface"; +import type { + SewerageSupplyRateItem, + SewerageSupplyRateRequestParams, +} from "@/entities/statistics/model/statistics-input-interface"; import { SeweragePenetrationRateInpColumn } from "@/components/util/column/input/SeweragePenetrationRateInpColumn"; import { toGridRows } from "@/components/util/grid/gridFunction"; +function getSewerageSupplyRateParams( + values: SearchFormValues, + overrides?: { yr?: string; demoYr?: string; mode?: string } +): SewerageSupplyRateRequestParams { + return { + sido: values.sido, + gugun: values.gugun === 'ALL' ? '' : values.gugun, + bsnmCd: values.bsnmCd, + yr: overrides?.yr ?? values.year, + demoYr: overrides?.demoYr ?? values.year, + ...(overrides?.mode && { mode: overrides.mode }), + }; +} + // 하수도 통계 관리 > 01. 하수도 보급률 const SeweragePenetrationRateInp = () => { const { setMessage: alert } = useAlertStore((state) => state); const [rowData, setRowData] = useState[]>([]); const [isLoading, setIsLoading] = useState(false); + const [searchValues, setSearchValues] = useState(null); + const [isEnterable, setIsEnterable] = useState(true); + + const columnInfo = useMemo(() => { + const { columns, columnLayout } = SeweragePenetrationRateInpColumn; + return { + columnLayout, + columns: isEnterable + ? columns + : columns.map((col) => ({ ...col, editable: false as const })), + }; + }, [isEnterable]); const handleReset = () => { setRowData([]); }; - const handleSearch = async (values: SearchFormValues) => { + const fetchSewerageSupplyRate = async (params: SewerageSupplyRateRequestParams) => { try { - if (values.sido !== '' && values.sido !== 'ALL') { - setIsLoading(true); - - const response = await statisticsInputAPi.getSewerageSupplyRateList({ - sido: values.sido, - gugun: values.gugun === 'ALL' ? '' : values.gugun, - bsnmCd: values.bsnmCd, - yr: values.year, - demoYr: values.year, - }); - - if (response.status === 'success' && response.data) { - const convertedData: SewerageSupplyRateItem[] = response.data.sewerageSupplyRateList.map((d) => ({ - ...d, - speclCntrplnAr: d.speclCntrplnAr === '' || d.speclCntrplnAr === null ? '해당없음' : d.speclCntrplnAr, - })); - - setRowData(toGridRows(convertedData)); - } else { - alert(response.message); - } + setIsLoading(true); + const response = await statisticsInputAPi.getSewerageSupplyRateList(params); + if (response.status === 'success' && response.data) { + const convertedData: SewerageSupplyRateItem[] = response.data.sewerageSupplyRateList.map((d) => ({ + ...d, + speclCntrplnAr: d.speclCntrplnAr === '' || d.speclCntrplnAr === null ? '해당없음' : d.speclCntrplnAr, + })); + setRowData(toGridRows(convertedData)); } else { - alert('시도를 선택해주세요.'); + alert(response.message); } - } catch (error) { + } catch { alert('데이터 조회 중 오류가 발생했습니다.'); setRowData([]); } finally { @@ -60,12 +76,40 @@ const SeweragePenetrationRateInp = () => { } }; - const SubmitExceptionFunc = () => { - // 예외 제출 로직 + const handleSearch = async (values: SearchFormValues) => { + if (values.sido === '' || values.sido === 'ALL') { + alert('시도를 선택해주세요.'); + return; + } + + try { + const response = await statisticsInputAPi.checkInputPeriod(searchValues?.year || ''); + + if (response.status === 'success') { + setIsEnterable(response.data); + + await fetchSewerageSupplyRate(getSewerageSupplyRateParams(values)); + } else { + alert(response.message); + } + } catch { + alert('데이터 조회 중 오류가 발생했습니다.'); + } }; - const getLastYearDataFunc = () => { - // 지난연도 데이터 가져오기 + const SubmitExceptionFunc = () => { + // 예외 제출 로직 + }; + + const getLastYearDataFunc = async (values: SearchFormValues) => { + if (values.sido === '' || values.sido === 'ALL') { + alert('시도를 선택해주세요.'); + return; + } + const prevYear = (Number(values.year) - 1).toString(); + await fetchSewerageSupplyRate( + getSewerageSupplyRateParams(values, { yr: prevYear, demoYr: prevYear, mode: 'PRE' }) + ); }; const submitFunc = () => { @@ -78,22 +122,25 @@ const SeweragePenetrationRateInp = () => { return (
- -
-
- - - - + + {rowData.length > 0 && +
+
+ + getLastYearDataFunc(searchValues ?? {})} /> + + +
-
+ } {isLoading &&
} void; onReset?: () => void; + onValuesChange?: (values: SearchFormValues) => void; defaultValues?: SearchFormValues; }; -export const defaultSearchFormProps: Required> = { +export const defaultSearchFormProps: Required> = { sido: true, gugun: true, year: true, diff --git a/apps/st/src/entities/statistics/api/statistics-input-service.ts b/apps/st/src/entities/statistics/api/statistics-input-service.ts index ca5d4e102..32cae5723 100644 --- a/apps/st/src/entities/statistics/api/statistics-input-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-input-service.ts @@ -5,6 +5,7 @@ import { type StatisticsInputService, type SewerageSupplyRateRequestParams, type SewerageSupplyRateApiResponse, + type CheckInputPeriodResponse, } from "../model/statistics-input-interface"; export class StatisticsInputAPiService implements StatisticsInputService { @@ -18,6 +19,14 @@ export class StatisticsInputAPiService implements StatisticsInputService { return response.data; } + + public async checkInputPeriod(params: string): Promise { + const response = await axios.get ( + `${ENDPOINT.ST_SERVICE.INPUTCOMMON}/check-input-period?year=${params}`, + ); + + return response.data; + } } export const statisticsInputAPi = new StatisticsInputAPiService(); \ No newline at end of file diff --git a/apps/st/src/entities/statistics/api/statistics-service.ts b/apps/st/src/entities/statistics/api/statistics-service.ts index dfec7d694..8455e68c5 100644 --- a/apps/st/src/entities/statistics/api/statistics-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-service.ts @@ -3,16 +3,16 @@ import { ENDPOINT } from "@/shared/config"; import { type StatisticsService, - type Sido, + type SearchCondition, type ApiResponse, type Sgg } from "../model/statistics-interface"; export class StatisticsAPiService implements StatisticsService { - public async getSidoList(): Promise> { - const response = await axios.get>( - `${ENDPOINT.ST_SERVICE.COMMON}/sido`, + public async getSidoList(): Promise> { + const response = await axios.get>( + `${ENDPOINT.ST_SERVICE.COMMON}/search-condition`, ); return response.data; diff --git a/apps/st/src/entities/statistics/model/statistics-input-interface.ts b/apps/st/src/entities/statistics/model/statistics-input-interface.ts index 111216424..6a76d567e 100644 --- a/apps/st/src/entities/statistics/model/statistics-input-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-input-interface.ts @@ -1,6 +1,6 @@ import type { ApiResponse } from "./statistics-interface"; -// 하수도 보급률 API 응답의 상태 정보 +// 하수도 보급률 데이터 항목 export interface SewerageSupplyRateStatusInfo { locgStatus: string; locgDt: string; @@ -13,7 +13,6 @@ export interface SewerageSupplyRateStatusInfo { returnOpinionSm: string | null; } -// 하수도 보급률 데이터 항목 export interface SewerageSupplyRateItem { sido: string; gugun: string; @@ -103,7 +102,7 @@ export interface SewerageSupplyRateResponseData { export type SewerageSupplyRateApiResponse = ApiResponse & { message: string; -}; +} export interface SewerageSupplyRateRequestParams { sido?: string; @@ -111,6 +110,14 @@ export interface SewerageSupplyRateRequestParams { bsnmCd?: string; yr?: string; demoYr?: string; + mode?: string; +} + +// 하수도 통계 입력 기간 조회 +export interface CheckInputPeriodResponse { + status: string; + message: string; + data: boolean; } export interface StatisticsInputService { diff --git a/apps/st/src/shared/config/api.ts b/apps/st/src/shared/config/api.ts index 1fd2505c3..cd1527192 100644 --- a/apps/st/src/shared/config/api.ts +++ b/apps/st/src/shared/config/api.ts @@ -67,6 +67,7 @@ export const ENDPOINT = { ST_SERVICE: { COMMON: "/st-management-service/api/v1/common", INPUT: "/st-input-service/api/v1/input", + INPUTCOMMON: "/st-input-service/api/v1/common", } };