From 43f210a14152cdda7a9224479e21f1b2bcdc6d52 Mon Sep 17 00:00:00 2001 From: jyha00 Date: Wed, 16 Jul 2025 13:17:04 +0900 Subject: [PATCH 01/12] =?UTF-8?q?searchBaseForm,=20searchFormLeft=EC=97=90?= =?UTF-8?q?=20className=20=ED=94=84=EB=A1=9C=ED=8D=BC=ED=8B=B0=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/search_base_form/index.tsx | 12 ++++++++-- .../src/ui/search_form_left/index.tsx | 24 ++++++++++--------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/common/business_components/src/ui/search_base_form/index.tsx b/packages/common/business_components/src/ui/search_base_form/index.tsx index 2649c67db..cd26f7742 100644 --- a/packages/common/business_components/src/ui/search_base_form/index.tsx +++ b/packages/common/business_components/src/ui/search_base_form/index.tsx @@ -21,6 +21,9 @@ type SearchBaseType = { btnClass:string; ref:React.RefObject; isAdmin:boolean; + rightClassName?: string; + leftClassName?: string; + leftSelectClassName?: string; } export type ReturnType = { partValue: string; @@ -49,7 +52,10 @@ function SearchBaseForm ({ excelClick, initClick, ref, - isAdmin=false + isAdmin=false, + rightClassName, + leftClassName, + leftSelectClassName }: SearchBaseType) { const [partValue, setPartValue] = useState("A"); const [sidoValue, setSidoValue] = useState("0"); @@ -133,10 +139,12 @@ function SearchBaseForm ({ setRtnSigunText={setSigunText} resetTrigger={resetTrigger} isAdmin={isAdmin} + leftClassName={leftClassName} + leftSelectClassName={leftSelectClassName} > {leftChildren} - + diff --git a/packages/common/business_components/src/ui/search_form_left/index.tsx b/packages/common/business_components/src/ui/search_form_left/index.tsx index a891ec207..a989995ed 100644 --- a/packages/common/business_components/src/ui/search_form_left/index.tsx +++ b/packages/common/business_components/src/ui/search_form_left/index.tsx @@ -44,6 +44,8 @@ type SearchFormLeftProps = { setRtnSigunText?: (value: string) => void; resetTrigger?: boolean; isAdmin?: boolean; + leftClassName?: string; + leftSelectClassName?: string; } export type EnvPartSelectDataType = SelectDataType & { @@ -56,7 +58,7 @@ const selectPartData:SelectDataType[] = [ { text: "환경청별", val: 'G' }, ]; -function SearchFormLeft({ isShowPart = false, children, selectSidoData = [], selectSigunData = [], selectRegionData = [], selectUnitWaterShedData = [], selectMiddleRegionData = [], selectEnvPartData = [], setRtnPartValue, setRtnSidoValue, setRtnSidoText, setRtnSigunValue, setRtnSigunText, setRtnRegionValue, setRtnUnitWaterShedValue, setRtnMiddleRegionValue, setRtnEnvPartValue, setRtnEnvPartSidoValue, setRtnEnvPartSigunValue, resetTrigger = false, isAdmin = false }: SearchFormLeftProps) { +function SearchFormLeft({ isShowPart = false, children, selectSidoData = [], selectSigunData = [], selectRegionData = [], selectUnitWaterShedData = [], selectMiddleRegionData = [], selectEnvPartData = [], setRtnPartValue, setRtnSidoValue, setRtnSidoText, setRtnSigunValue, setRtnSigunText, setRtnRegionValue, setRtnUnitWaterShedValue, setRtnMiddleRegionValue, setRtnEnvPartValue, setRtnEnvPartSidoValue, setRtnEnvPartSigunValue, resetTrigger = false, isAdmin = false, leftClassName, leftSelectClassName }: SearchFormLeftProps) { /******************선택된 데이터******************/ const [partValue, setPartValue] = useState('A'); //행정별 시도 시군구 @@ -308,24 +310,24 @@ function SearchFormLeft({ isShowPart = false, children, selectSidoData = [], sel return ( isShowPart ? ( -
- onSelectValue(val.toString(), 'part')} value={partValue} selectClass={undefined}/> +
+ onSelectValue(val.toString(), 'part')} value={partValue} selectClass={undefined}/> {partValue === 'R' ? ( <> - onSelectValue(val.toString(), 'region')} value={regionValue} selectClass={undefined}/> - onSelectValue(val.toString(), 'unitWaterShed')} value={unitWaterShedValue} selectClass={undefined}/> - onSelectValue(val.toString(), 'middleRegion')} value={middleRegionValue} selectClass={undefined}/> + onSelectValue(val.toString(), 'region')} value={regionValue} selectClass={undefined}/> + onSelectValue(val.toString(), 'unitWaterShed')} value={unitWaterShedValue} selectClass={undefined}/> + onSelectValue(val.toString(), 'middleRegion')} value={middleRegionValue} selectClass={undefined}/> ) : partValue === 'G' ? ( <> - onSelectValue(val.toString(), 'envPart')} value={envPartValue} selectClass={undefined}/> - onSelectValue(val.toString(), 'envPartSido')} value={sidoValue} selectClass={undefined}/> - onSelectValue(val.toString(), 'envPartSigun')} value={sigunValue} selectClass={undefined}/> + onSelectValue(val.toString(), 'envPart')} value={envPartValue} selectClass={undefined}/> + onSelectValue(val.toString(), 'envPartSido')} value={sidoValue} selectClass={undefined}/> + onSelectValue(val.toString(), 'envPartSigun')} value={sigunValue} selectClass={undefined}/> ) : ( <> - onSelectValue(val.toString(), 'sido')} value={sidoValue} selectClass={undefined}/> - onSelectValue(val.toString(), 'sigun')} value={sigunValue} selectClass={undefined}/> + onSelectValue(val.toString(), 'sido')} value={sidoValue} selectClass={undefined}/> + onSelectValue(val.toString(), 'sigun')} value={sigunValue} selectClass={undefined}/> )} {children} From e0171a5a28f06e2e19d3b80908d16ca67ac343a8 Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Wed, 16 Jul 2025 13:30:25 +0900 Subject: [PATCH 02/12] =?UTF-8?q?=EB=B0=94=EC=B0=A8=ED=8A=B8=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EA=B5=AC=EC=84=B1=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/common/business_components/src/ui/chart/BarChart.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/common/business_components/src/ui/chart/BarChart.tsx b/packages/common/business_components/src/ui/chart/BarChart.tsx index ddd0ac272..218ebac34 100644 --- a/packages/common/business_components/src/ui/chart/BarChart.tsx +++ b/packages/common/business_components/src/ui/chart/BarChart.tsx @@ -87,7 +87,7 @@ const getGlobalMax = (data: Record[]) => { }; export default function Chart({chartConfig=undefined, chartData=[], chartTitle='차트', chartClassName='w-full h-full', graphSize=40, yFieldText='', showLegend=false} : BarChartProps) { - const colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#FED16A", "#FFEEAD", "#D4A5A5"]; + const colors = ["#FF6B6B", "#4ECDC4", "#44ad57", "#FED16A", "#FFEEAD", "#D4A5A5"]; const globalMax = getGlobalMax(chartData); const tickCount = 5; // interval을 globalMax / tickCount로 계산 From 8b1e8ae2ebadf69e013cde087e4eba08a36d830a Mon Sep 17 00:00:00 2001 From: jyha00 Date: Wed, 16 Jul 2025 15:33:57 +0900 Subject: [PATCH 03/12] =?UTF-8?q?datepicker=20=EB=82=A0=EC=A7=9C=EA=B0=80?= =?UTF-8?q?=20=ED=95=98=EB=A3=A8=20=EC=A0=84=20=EB=82=A0=EB=A1=9C=20?= =?UTF-8?q?=EB=93=A4=EC=96=B4=EA=B0=80=EB=8A=94=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/date_picker/index.tsx | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/packages/common/business_components/src/ui/date_picker/index.tsx b/packages/common/business_components/src/ui/date_picker/index.tsx index 722b82a3c..2652eabd7 100644 --- a/packages/common/business_components/src/ui/date_picker/index.tsx +++ b/packages/common/business_components/src/ui/date_picker/index.tsx @@ -32,10 +32,27 @@ export function DatePicker({ }: DatePickerProps) { const [open, setOpen] = useState(false); + // const handleSelect = (date: Date | undefined) => { + // console.log("날짜", date) + // if (!readOnly) { + // // readOnly가 아닐 때만 변경 허용 + // field.onChange(date); // React Hook Form 업데이트 + // setOpen(false); + // } + // }; + + //저장시 9시간 전으로 돌아가는 문제 const handleSelect = (date: Date | undefined) => { if (!readOnly) { - // readOnly가 아닐 때만 변경 허용 - field.onChange(date); // React Hook Form 업데이트 + if (date) { + const utcMidnight = new Date( + //utc 삽입 + Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) + ); + field.onChange(utcMidnight); + } else { + field.onChange(undefined); + } setOpen(false); } }; @@ -53,17 +70,17 @@ export function DatePicker({ className={ !selectClass ? cn( - "w-[240px] pl-3 text-left font-normal", - !field?.value && "text-muted-foreground", + "w-[240px] pl-3 text-left font-normal", + !field?.value && "text-muted-foreground", - //감리 지적사항으로 삭제 예정 리드온리는 리드온리 로만 보일수 있도록 수정 - // disabled={readOnly} // readOnly일 때 버튼 비활성화 - //readOnly && "opacity-60 cursor-not-allowed" 감리 지적사항으로 - ) + //감리 지적사항으로 삭제 예정 리드온리는 리드온리 로만 보일수 있도록 수정 + // disabled={readOnly} // readOnly일 때 버튼 비활성화 + //readOnly && "opacity-60 cursor-not-allowed" 감리 지적사항으로 + ) : cn( - selectClass, - // , readOnly && "opacity-60 cursor-not-allowed" - ) + selectClass, + // , readOnly && "opacity-60 cursor-not-allowed" + ) } > {field?.value ? ( @@ -87,10 +104,10 @@ export function DatePicker({ className="w-full" //-- 데이트 피커가 드롭박스 형태로 년월을 선택할수 있도록 하는 Props 로 활성화 되면 드롭박스로 선택 - - // captionLayout="dropdown-buttons" - // fromYear={2000} - // toYear={new Date().getFullYear()} + + // captionLayout="dropdown-buttons" + // fromYear={2000} + // toYear={new Date().getFullYear()} toDate={new Date()} // 금일까지만 표시됨 (금일 이후는 안보임) showOutsideDays={false} // 금월 까지만 표출되도록 mode="single" From 18ec5c937fa39ac83ba25f0bc5a30f58352a4417 Mon Sep 17 00:00:00 2001 From: jyha00 Date: Thu, 17 Jul 2025 13:08:14 +0900 Subject: [PATCH 04/12] =?UTF-8?q?=EB=8F=84=EB=84=9B=EC=B0=A8=ED=8A=B8=20cu?= =?UTF-8?q?stom=20label=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/chart/DoughnutChart.tsx | 55 ++++++++++++++----- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/packages/common/business_components/src/ui/chart/DoughnutChart.tsx b/packages/common/business_components/src/ui/chart/DoughnutChart.tsx index 3dd14e5b7..6f113bee3 100644 --- a/packages/common/business_components/src/ui/chart/DoughnutChart.tsx +++ b/packages/common/business_components/src/ui/chart/DoughnutChart.tsx @@ -53,12 +53,37 @@ const customStyles = { minHeight: "32px", // 범례 영역 높이 통일 } as CSSProperties, }; +const renderCustomizedLabel = ({ + cx, + cy, + midAngle, + outerRadius, + payload, +}: any) => { + const RADIAN = Math.PI / 180; + const radius = outerRadius + 25; + const x = cx + radius * Math.cos(-midAngle * RADIAN); + const y = cy + radius * Math.sin(-midAngle * RADIAN); + + return ( + cx ? "start" : "end"} + dominantBaseline="central" + > + {`${payload.label}: ${payload.val.toLocaleString()}`} + + ); +}; // 커스텀 툴팁 -const CustomTooltip = ({ active, payload, label }: { - active?: boolean; - payload?: TooltipPayloadItem[]; - label?: string +const CustomTooltip = ({ active, payload, label }: { + active?: boolean; + payload?: TooltipPayloadItem[]; + label?: string }) => { if (active && payload && payload.length) { return ( @@ -79,7 +104,6 @@ const CustomTooltip = ({ active, payload, label }: { const CustomLegend = (props: LegendProps) => { const { payload } = props; if (!payload) return null; - return (
{payload.map((entry: LegendEntry, index: number) => ( @@ -111,9 +135,9 @@ const CustomLegend = (props: LegendProps) => { ); }; -export default function DoughnutChart(props: { - chartConfig: ChartConfig; - chartData: ChartDataItem[] | undefined; +export default function DoughnutChart(props: { + chartConfig: ChartConfig; + chartData: ChartDataItem[] | undefined; chartTitle: string }) { const legendData = props.chartData?.map(item => ({ @@ -125,19 +149,20 @@ export default function DoughnutChart(props: { fill: props.chartConfig?.[item.label]?.color || 'blue' } })) ?? []; - + return ( {props.chartTitle && props.chartTitle !== "" && props.chartTitle !== "undefined" ? ( -
+
{props.chartTitle}
) : null}
+ label={(props) => { + return renderCustomizedLabel(props); + }} + > + - +
From c22e07bc16afbc2888806b4e0d36606b8ea0d35f Mon Sep 17 00:00:00 2001 From: leedj312 Date: Thu, 17 Jul 2025 15:59:22 +0900 Subject: [PATCH 05/12] =?UTF-8?q?=EB=A1=9C=EB=94=A9=EB=B0=94=20className?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20z-index=EB=B3=80=EA=B2=BD=ED=95=A0?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/loadingBar/index.tsx | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/common/business_components/src/ui/loadingBar/index.tsx b/packages/common/business_components/src/ui/loadingBar/index.tsx index 4d637dd25..7c6df0114 100644 --- a/packages/common/business_components/src/ui/loadingBar/index.tsx +++ b/packages/common/business_components/src/ui/loadingBar/index.tsx @@ -1,20 +1,26 @@ -import { LoadingWithAnimation } from '@common/components/ui/loading'; -import React from 'react'; +import { LoadingWithAnimation } from "@common/components/ui/loading"; +import React from "react"; interface LoadingOverlayProps { isLoading: boolean; + customZindex?: string; } -const LoadingOverlay: React.FC = ({ isLoading }) => { +const LoadingOverlay: React.FC = ({ + isLoading, + customZindex, +}) => { if (!isLoading) return null; return ( -
-
+
+
); }; -export default LoadingOverlay; \ No newline at end of file +export default LoadingOverlay; From 0bb16f97953a156b2a30ce309b342bc134a31003 Mon Sep 17 00:00:00 2001 From: jyha00 Date: Mon, 21 Jul 2025 15:28:42 +0900 Subject: [PATCH 06/12] =?UTF-8?q?=EB=8F=84=EB=84=9B=EC=B0=A8=ED=8A=B8=20?= =?UTF-8?q?=EB=B2=94=EB=A1=80=20=EB=86=92=EC=9D=B4=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/business_components/src/ui/chart/DoughnutChart.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/common/business_components/src/ui/chart/DoughnutChart.tsx b/packages/common/business_components/src/ui/chart/DoughnutChart.tsx index 6f113bee3..ec8fc2fd9 100644 --- a/packages/common/business_components/src/ui/chart/DoughnutChart.tsx +++ b/packages/common/business_components/src/ui/chart/DoughnutChart.tsx @@ -50,7 +50,7 @@ const customStyles = { fontWeight: "normal", marginTop: "16px", marginBottom: "8px", - minHeight: "32px", // 범례 영역 높이 통일 + minHeight: "60px", // 범례 영역 높이 통일 } as CSSProperties, }; const renderCustomizedLabel = ({ From ddf3a5cfa0aedbb2bb73e073ff97fa68ca2c5d9a Mon Sep 17 00:00:00 2001 From: leedj312 Date: Mon, 21 Jul 2025 19:56:57 +0900 Subject: [PATCH 07/12] =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=98=A4=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/business_components/src/ui/date_picker/index.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/common/business_components/src/ui/date_picker/index.tsx b/packages/common/business_components/src/ui/date_picker/index.tsx index 2652eabd7..34760c245 100644 --- a/packages/common/business_components/src/ui/date_picker/index.tsx +++ b/packages/common/business_components/src/ui/date_picker/index.tsx @@ -108,12 +108,11 @@ export function DatePicker({ // captionLayout="dropdown-buttons" // fromYear={2000} // toYear={new Date().getFullYear()} - toDate={new Date()} // 금일까지만 표시됨 (금일 이후는 안보임) showOutsideDays={false} // 금월 까지만 표출되도록 mode="single" selected={field?.value} onSelect={handleSelect} - initialFocus + disabled={{ after: new Date() }} // 금일까지만 표시됨 (금일 이후는 안보임) 20250721 캘린더가 변경됨!! locale={ko} /> From 7d95ddf6a521f108b3b49d71760ba6e92a56d2dc Mon Sep 17 00:00:00 2001 From: truthwing Date: Tue, 22 Jul 2025 13:55:31 +0900 Subject: [PATCH 08/12] =?UTF-8?q?ChkClass=20=ED=83=80=EC=9E=85=EC=9D=98=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=EB=A1=9C=20=EB=8F=99=EC=9E=91=EB=90=98?= =?UTF-8?q?=EB=8A=94=20=EC=B2=B4=ED=81=AC=EB=B0=95=EC=8A=A4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business_components/src/ui/table/index.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/common/business_components/src/ui/table/index.tsx b/packages/common/business_components/src/ui/table/index.tsx index 85ffb85ea..b4a66d839 100644 --- a/packages/common/business_components/src/ui/table/index.tsx +++ b/packages/common/business_components/src/ui/table/index.tsx @@ -5,7 +5,10 @@ import { useEffect, useState, useRef } from "react"; import { HeadMakeColSpan } from "./HeadMakeColSpan"; import UiPageNations from "./uiPageNations"; import { Check } from "lucide-react"; - +export type ChkClass={ + chk:boolean + readonly:boolean +} type UiTableProps = { headName: React.ReactNode | undefined; tableData: { [key: string]: any }[]; @@ -109,7 +112,17 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr onClick={() => handleCellClick(index, head.id)} key={`cell-${head.id}-${index}`} > - {typeof el[head.id] === 'boolean' + {typeof el[head.id] === 'object' + ? { + if((el[head.id] as ChkClass).readonly == true) return + (el[head.id] as ChkClass).chk = Boolean(checked); + }} + > + + : + typeof el[head.id] === 'boolean' ? { From a028b6ae8bba8e074e82900d05925d4e5a9c6951 Mon Sep 17 00:00:00 2001 From: leedj312 Date: Tue, 22 Jul 2025 15:37:54 +0900 Subject: [PATCH 09/12] =?UTF-8?q?ui=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC=EB=B0=95=EC=8A=A4=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=8B=9C=20=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=ED=83=80=EC=9E=85?= =?UTF-8?q?=EC=9D=84=20=EC=82=AC=EC=9A=A9=20=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/table/index.tsx | 253 ++++++++++++------ 1 file changed, 170 insertions(+), 83 deletions(-) diff --git a/packages/common/business_components/src/ui/table/index.tsx b/packages/common/business_components/src/ui/table/index.tsx index b4a66d839..de6fed944 100644 --- a/packages/common/business_components/src/ui/table/index.tsx +++ b/packages/common/business_components/src/ui/table/index.tsx @@ -1,14 +1,21 @@ -"use client" +"use client"; -import { Checkbox, Table, TableBody, TableCell, TableHeader, TableRow } from "@common/components"; +import { + Checkbox, + Table, + TableBody, + TableCell, + TableHeader, + TableRow, +} from "@common/components"; import { useEffect, useState, useRef } from "react"; import { HeadMakeColSpan } from "./HeadMakeColSpan"; import UiPageNations from "./uiPageNations"; import { Check } from "lucide-react"; -export type ChkClass={ - chk:boolean - readonly:boolean -} +export type ChkClass = { + chk: boolean; + readonly: boolean; +}; type UiTableProps = { headName: React.ReactNode | undefined; tableData: { [key: string]: any }[]; @@ -23,22 +30,35 @@ type UiTableProps = { boldArray?: number[]; resetSelection?: boolean; index?: number; -} +}; type UiHeadProps = { id: string; title: string; align?: string; visible?: boolean; -} +}; -export function UiTable({ tableData, headlist, pageSize, total, headName, children, cellClick, onPageChange, className = '', resetPageNo = false, boldArray = [], resetSelection = false, index = -1 }: UiTableProps) { +export function UiTable({ + tableData, + headlist, + pageSize, + total, + headName, + children, + cellClick, + onPageChange, + className = "", + resetPageNo = false, + boldArray = [], + resetSelection = false, + index = -1, +}: UiTableProps) { const [cur, setCur] = useState(1); const [idx, setIdx] = useState(index); const [headerHeight, setHeaderHeight] = useState(0); const headerRef = useRef(null); - useEffect(() => { if (resetPageNo) { setCur(1); @@ -54,14 +74,14 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr useEffect(() => { if (headerRef.current) { - setHeaderHeight(headerRef.current.offsetHeight-5); + setHeaderHeight(headerRef.current.offsetHeight - 5); } }, [tableData, headlist]); const handlePageChange = (page: number) => { setCur(page); onPageChange(page); - } + }; const handleCellClick = (index: number, headId: string) => { if (cellClick) { @@ -70,91 +90,158 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr } }; - return ( <> - {headName ?
-

{headName}

-
: <>} -
+ {headName ? ( +
+

{headName}

+
+ ) : ( + <> + )} +
{children ? children : } - - {tableData.length > 0 ? tableData?.map((el: Record, index) => ( - - {headlist - .filter((item) => item.visible != false) - .map((head) => ( - head.id && head.id.length > 1 && ( - boldArray.includes(index) - ? - handleCellClick(index, head.id)} - key={`cell-${head.id}-${index}`} - > - {typeof el[head.id] !== 'number' ? String(el[head.id] ?? '') : String(el[head.id]).includes('.') - ? String(el[head.id]).split('.').map((part, index) => - index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part - ).join('.') - : String(el[head.id] ?? '').replace(/\B(?=(\d{3})+(?!\d))/g, ",")} - - : - + {tableData.length > 0 ? ( + tableData?.map((el: Record, index) => ( + + {headlist + .filter((item) => item.visible != false) + .map( + (head) => + head.id && + head.id.length > 1 && + (boldArray.includes(index) ? ( + handleCellClick(index, head.id)} + key={`cell-${head.id}-${index}`} + > + {typeof el[head.id] !== "number" + ? String(el[head.id] ?? "") + : String(el[head.id]).includes(".") + ? String(el[head.id]) + .split(".") + .map((part, index) => + index === 0 + ? part.replace( + /\B(?=(\d{3})+(?!\d))/g, + ",", + ) + : part, + ) + .join(".") + : String(el[head.id] ?? "").replace( + /\B(?=(\d{3})+(?!\d))/g, + ",", + )} + + ) : ( + handleCellClick(index, head.id)} - key={`cell-${head.id}-${index}`} - > - {typeof el[head.id] === 'object' - ? { - if((el[head.id] as ChkClass).readonly == true) return - (el[head.id] as ChkClass).chk = Boolean(checked); - }} - > - - : - typeof el[head.id] === 'boolean' - ? { - el[head.id] = checked; - }} - > - - - : - typeof el[head.id] !== 'number' ? - String(el[head.id] ?? '') : - String(el[head.id]).includes('.') - ? String(el[head.id]).split('.').map((part, index) => - index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part - ).join('.') - : - String(el[head.id] ?? '').replace(/\B(?=(\d{3})+(?!\d))/g, ",")} - - ) - ))} - - )) : ( + onClick={() => handleCellClick(index, head.id)} + key={`cell-${head.id}-${index}`} + > + { + //체크박스 유형애서 readOnly가 필요한 경우를 위해서 ChkClass 를 사용해서 readOnly 처리함. + typeof el[head.id] === "object" && + el[head.id] !== null && + "chk" in (el[head.id] as object) && + "readonly" in (el[head.id] as object) ? ( + { + { + console.log(el[head.id]); + } + if ( + (el[head.id] as ChkClass).readonly == true + ) + return; + (el[head.id] as ChkClass).chk = + Boolean(checked); + }} + > + + + ) : typeof el[head.id] === "boolean" ? ( + { + el[head.id] = checked; + }} + > + + + ) : typeof el[head.id] !== "number" ? ( + String(el[head.id] ?? "") + ) : String(el[head.id]).includes(".") ? ( + String(el[head.id]) + .split(".") + .map((part, index) => + index === 0 + ? part.replace( + /\B(?=(\d{3})+(?!\d))/g, + ",", + ) + : part, + ) + .join(".") + ) : ( + String(el[head.id] ?? "").replace( + /\B(?=(\d{3})+(?!\d))/g, + ",", + ) + ) + } + + )), + )} + + )) + ) : ( - item.visible != false).length} className="h-24 text-center text-gray-500"> + item.visible != false).length + } + className="h-24 text-center text-gray-500" + > 조회된 결과가 없습니다. )}
- {total <= 0 ? <> : } + {total <= 0 ? ( + <> + ) : ( + + )}
); -} \ No newline at end of file +} From 8435096e5a20865b8559a48e1b7b16fcafc0a471 Mon Sep 17 00:00:00 2001 From: swcho Date: Tue, 22 Jul 2025 16:16:42 +0900 Subject: [PATCH 10/12] =?UTF-8?q?remove:=20UITab2=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/tab/index-2.tsx | 38 ------------------- 1 file changed, 38 deletions(-) delete mode 100644 packages/common/business_components/src/ui/tab/index-2.tsx diff --git a/packages/common/business_components/src/ui/tab/index-2.tsx b/packages/common/business_components/src/ui/tab/index-2.tsx deleted file mode 100644 index 71c103835..000000000 --- a/packages/common/business_components/src/ui/tab/index-2.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Tabs, TabsList, TabsTrigger } from '@common/components/ui'; -import React from 'react'; - -interface TabItem { - value: string; - label: string; - onClick?: () => void; -} - -interface UITabProps extends React.HTMLAttributes { - defaultValue?: string; - tabList: TabItem[]; - children: React.ReactNode; -} - -const UITab2 = React.forwardRef< - HTMLDivElement, - UITabProps ->(({defaultValue, tabList, children}, ref)=>{ - return ( - - - {tabList.map((tab) => ( - - {tab.label} - - ))} - - {children} - - ) -}) -export { UITab2 }; From 804688b3c1b8875f211b87d329b7eb7267aa2a5d Mon Sep 17 00:00:00 2001 From: swcho Date: Tue, 22 Jul 2025 16:28:48 +0900 Subject: [PATCH 11/12] =?UTF-8?q?remove:=20UITable2=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/table/index-2.tsx | 155 ------------------ 1 file changed, 155 deletions(-) delete mode 100644 packages/common/business_components/src/ui/table/index-2.tsx diff --git a/packages/common/business_components/src/ui/table/index-2.tsx b/packages/common/business_components/src/ui/table/index-2.tsx deleted file mode 100644 index 9756d2dfa..000000000 --- a/packages/common/business_components/src/ui/table/index-2.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components"; -import { useEffect, useState } from "react"; -import UiPageNations from "./uiPageNations"; - -type UiTableProps = { - headName: React.ReactNode | undefined; - tableData: { [key: string]: string | number | boolean | object }[]; - headlist: UiHeadProps[]; - pageSize: number; - total: number; - children: React.ReactNode | undefined; - cellClick: ((index: number | undefined, headId: string) => void) | undefined; - onPageChange: (page: number) => void; - className?: string; - resetPageNo?: boolean; - cur?: number; - height?: string; // ✅ 추가된 prop -}; - -type UiHeadProps = { - id: string; - title: string; - align?: string; -}; - -export function UiTable2({ - tableData, - headlist, - pageSize, - total, - children, - headName, - cellClick, - onPageChange, - className = '', - resetPageNo = false, - cur, - height = '45vh', // ✅ 기본값 설정 -}: UiTableProps) { - const [idx, setIdx] = useState(-1); - const [curState, setCurState] = useState(cur ?? 1); - - useEffect(() => { - setCurState(cur ?? 1); - }, [cur]); - - useEffect(() => { - if (resetPageNo) { - setCurState(1); - onPageChange(1); - } - }, [onPageChange, resetPageNo]); - - const handlePageChange = (page: number) => { - setCurState(page); - onPageChange(page); - }; - - const handleCellClick = (index: number, headId: string) => { - if (cellClick) { - cellClick(index, headId); - setIdx(index); - } - }; - - const startIdx = (curState - 1) * pageSize; - - return ( - <> - {headName && ( -
-
-

{headName}

-
-
- )} - -
- {/* ✅ 외부에서 조절 가능한 높이 적용 */} -
- - - {children ? ( - <>{children} - ) : ( - - {headlist.map((head) => ( - - {head.title} - - ))} - - )} - - - - {tableData.length > 0 ? ( - tableData.map((el, index) => ( - - {headlist.map((head) => ( - handleCellClick(startIdx + index, head.id)} - > - {typeof el[head.id] === 'number' - ? String(el[head.id]).replace(/\B(?=(\d{3})+(?!\d))/g, ",") - : String(el[head.id] ?? '')} - - ))} - - )) - ) : ( - - - {/* ✅ 높이 보장 + 가운데 정렬용 div */} -
- 🔍 검색 결과가 없습니다. -
-
-
- )} -
-
-
- - {/* 페이지네이션 하단 고정 */} - {( -
- -
- )} -
- - ); -} From 527b4293c4c0490d54fb8f44f57e6ef0ebceb68b Mon Sep 17 00:00:00 2001 From: swcho Date: Tue, 22 Jul 2025 21:06:09 +0900 Subject: [PATCH 12/12] =?UTF-8?q?feat,=20refactor:=20-=20=ED=95=98?= =?UTF-8?q?=EC=88=98=EA=B4=80=EB=A1=9C=20=EC=83=81=EC=84=B8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=20=EC=9A=B4=EC=98=81=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=97=B0=EA=B3=84=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?-=20=EC=9A=B4=EC=98=81=EC=A0=95=EB=B3=B4=20=ED=83=AD=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?-=20UITab2,=20UITable2=20=EC=82=AD=EC=A0=9C=20=ED=9B=84=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=20(UITab,=20UITable)=20-=20SearchModal.tsx?= =?UTF-8?q?=20UI=20=EC=88=98=EC=A0=95=20-=20featureClickEvent=EC=97=90=20i?= =?UTF-8?q?sClicked=20state=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../map/components/InputSection.tsx | 22 +- .../map/components/common/index.ts | 4 +- .../map/components/common/table.ts | 47 +- .../components/popupComponent/MsSwagePpl.tsx | 105 ++- .../map/components/popupComponent/Ssc.tsx | 2 +- .../map/featureClickEventPopup.tsx | 50 +- apps/sn/app/(map-layout)/map/page.tsx | 34 +- .../searchModal.tsx} | 700 +++++++++--------- .../app/(with-base-layout)/ii/BaseLayout.tsx | 2 +- apps/sn/app/components/lib/api/index.ts | 70 +- .../app/components/ui/YearRangeSelectBox.tsx | 4 +- 11 files changed, 571 insertions(+), 469 deletions(-) rename apps/sn/app/(map-layout)/map/{SearchModal.tsx => searchModal/searchModal.tsx} (67%) diff --git a/apps/sn/app/(map-layout)/map/components/InputSection.tsx b/apps/sn/app/(map-layout)/map/components/InputSection.tsx index 209361293..539122d44 100644 --- a/apps/sn/app/(map-layout)/map/components/InputSection.tsx +++ b/apps/sn/app/(map-layout)/map/components/InputSection.tsx @@ -3,7 +3,7 @@ import React from "react"; interface InputSectionProps { title: string; - data: { year: string; type: string }[]; + data: { year: string; type: string, bizNm: string, bizType: string }[]; sectionKey: string; onInputChange: (section: string, index: number, field: string, value: string) => void; } @@ -13,21 +13,26 @@ const InputSection: React.FC = ({ title, data, sectionKey, on
{/* 섹션 제목 */}
-

{title}

+

{title}

{/* 테이블 */}
- 년도 - 구분 + 구분 + 년도 + 사업명 + 유형 {data.map((row, index) => ( - + + {row.type} + + = ({ title, data, sectionKey, on className="w-full text-xl border-radius-0 px-3 py-2 text-base text-center leading-normal" /> - - {row.type} + + {row.bizNm} + + + {row.bizType} ))} diff --git a/apps/sn/app/(map-layout)/map/components/common/index.ts b/apps/sn/app/(map-layout)/map/components/common/index.ts index 055c7062a..23602b632 100644 --- a/apps/sn/app/(map-layout)/map/components/common/index.ts +++ b/apps/sn/app/(map-layout)/map/components/common/index.ts @@ -49,8 +49,8 @@ export const handleInputChange = (section: string, value: string, dataMap: { [key: string]: { - data: { year: string; type: string }[]; - setData: React.Dispatch>; + data: { year: string; type: string, bizNm: string, bizType: string }[]; + setData: React.Dispatch>; }; } ) => { 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 6834e6b43..cabb95649 100644 --- a/apps/sn/app/(map-layout)/map/components/common/table.ts +++ b/apps/sn/app/(map-layout)/map/components/common/table.ts @@ -28,22 +28,17 @@ export const MsSwagePplCol = [ // { id: 'lyrTypeNm', title: '레이어타입명' }, ] export const MsSwagePplCol2 = [ - { id: 'fcltMngNo', title: '시설관리번호' }, - { id: 'instMngNo', title: '기관관리번호' }, + { id: 'fcltMngNo', title: '시설 관리번호' }, + { id: 'instMngNo', title: '기관 관리번호' }, { id: 'instlYmd', title: '설치일자' }, { id: 'mapshtNo', title: '도엽번호' }, { id: 'pdmt', title: '관경(mm)' }, { id: 'prlg', title: '연장(m)' }, { id: 'avgGrdn', title: '평균구배(m/m)' }, - { id: 'rnysnFvlc', title: '우기 시 유속(m/s)' }, - { id: 'clarFvlc', title: '건기 시 유속(m/s)' }, - { id: 'drtwMltvArea', title: '오수배수면적(m²)' }, - { id: 'exclnMltvArea', title: '우수배수면적(m²)' }, { id: 'tmptDpth', title: '시점깊이(m)' }, - { id: 'tmptMhlMngNo', title: '시점맨홀관리번호' }, + { id: 'tmptMhlMngNo', title: '시점맨홀 관리번호' }, { id: 'scendDpth', title: '종점깊이(m)' }, - { id: 'scendMhlMngNo', title: '종점맨홀관리번호' }, - { id: 'trflnCnt', title: '차선수' }, + { id: 'scendMhlMngNo', title: '종점맨홀 관리번호' }, { id: 'vrtcLen', title: '세로길이(m)' }, { id: 'wdthLen', title: '가로길이(m)' }, // { id: 'fcltyShpCd', title: '시설물형태코드' }, @@ -306,35 +301,35 @@ export const SwtrmtFcltCol2 = [ { id: 'rgnExpln', title: '지역설명' }, { id: 'cmcnYmd', title: '준공일자' }, { id: 'oprtngStrtYmd', title: '가동개시일자' }, - { id: 'clsgYmd', title: '폐쇄일자' }, + // { id: 'clsgYmd', title: '폐쇄일자' }, // { id: 'prcsMsrcCd', title: '처리공법코드' }, // { id: 'laeCd', title: '지자체코드' }, { id: 'laeNm', title: '지자체명' }, - { id: 'ctpvNm', title: '시도명' }, - { id: 'sggNm', title: '시군구명' }, + // { id: 'ctpvNm', title: '시도명' }, + // { id: 'sggNm', title: '시군구명' }, // { id: 'sareaCd', title: '권역코드' }, { id: 'sareaNm', title: '권역명' }, { id: 'lrgeSareaNm', title: '대권역명' }, { id: 'rvrNm', title: '하천명' }, - { id: 'addr', title: '주소' }, - { id: 'dtlAddr', title: '상세주소' }, - { id: 'rdnmAddr', title: '도로명주소' }, - { id: 'dtlRdnmAddr', title: '상세도로명주소' }, + // { id: 'addr', title: '주소' }, + // { id: 'dtlAddr', title: '상세주소' }, + // { id: 'rdnmAddr', title: '도로명주소' }, + // { id: 'dtlRdnmAddr', title: '상세도로명주소' }, { id: 'dschgWtstNm', title: '방류수계명' }, - { id: 'pllnArea', title: '부지면적(m²)' }, - { id: 'mngRprtvBzentyNm', title: '관리대행업제명' }, + // { id: 'pllnArea', title: '부지면적(m²)' }, + // { id: 'mngRprtvBzentyNm', title: '관리대행업체명' }, { id: 'swtrmtPpltnCnt', title: '하수처리인구수(인)' }, { id: 'prcsZoneAreaSum', title: '처리구역면적합계(m²)' }, - { id: 'xcrd', title: 'X좌표' }, - { id: 'ycrd', title: 'Y좌표' }, + // { id: 'xcrd', title: 'X좌표' }, + // { id: 'ycrd', title: 'Y좌표' }, // { id: 'oprtngSttsCd', title: '가동상태코드' }, { id: 'rprsMsrcCn', title: '대표공법내용' }, - { 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: '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: 'obsrvnSptCd', title: '관측지점코드' }, ]; diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx index b68684ffd..6526eef14 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx @@ -3,6 +3,8 @@ import { VerticalTable } from '@/components/ui/verticalTable'; import React, { useState, useEffect } from 'react' import InputSection from '../InputSection'; import { handleInputChange } from '../common'; +import { getData } from "@/components/lib/api"; +// import { useBizByFcltStore } from "../../../../store/StoreProvider"; // 하수관로 const inputColumn = [ @@ -16,18 +18,9 @@ const inputColumn = [ ]; const MsSwagePpl = ({ featureData, onSaveClick }: { featureData: any, onSaveClick?: () => void }) => { - const [repairData, setRepairData] = useState([ - { year: "2025", type: "개대체" }, - { year: "2025", type: "보수" }, - ]); - const [cleaningData, setCleaningData] = useState([ - { year: "2025", type: "청소" }, - { year: "2025", type: "준설" }, - ]); - const [inspectionData, setInspectionData] = useState([ - { year: "2025", type: "관로기술진단" }, - { year: "2025", type: "관로기술진단" }, - ]); + const [repairData, setRepairData] = useState<{ year: string; type: string, bizNm: string, bizType: string }[]>([]); + const [cleaningData, setCleaningData] = useState<{ year: string; type: string, bizNm: string, bizType: string }[]>([]); + const [inspectionData, setInspectionData] = useState<{ year: string; type: string, bizNm: string, bizType: string }[]>([]); const dataMap = { repair: { data: repairData, setData: setRepairData }, cleaning: { data: cleaningData, setData: setCleaningData }, @@ -36,12 +29,84 @@ const MsSwagePpl = ({ featureData, onSaveClick }: { featureData: any, onSaveClic const [formData, setFormData] = useState({}); - // featureData가 변경될 때 formData 초기화 + // const BIZ_SE_CD = useBizByFcltStore(state => state.BIZ_SE_CD); + const BIZ_SE_CD = [ + { lwpoCd: "100", lwpoCdNm: "관로기술진단" }, + { lwpoCd: "200", lwpoCdNm: "개대체" }, + { lwpoCd: "201", lwpoCdNm: "유지보수" }, + { lwpoCd: "203", lwpoCdNm: "청소, 준설" }, + { lwpoCd: "204", lwpoCdNm: "단순보수" }, + ]; + const BIZ_TY_CD = [ + { lwpoCd: "SV", lwpoCdNm: "용역" }, + { lwpoCd: "SF", lwpoCdNm: "자체" }, + { lwpoCd: "SC", lwpoCdNm: "공사" }, + ]; + + console.log('BIZ_SE_CD', BIZ_SE_CD); + + // 마운트 및 업데이트 시 API 호출 useEffect(() => { + // featureData가 변경될 때 formData 초기화 if (featureData) { setFormData(featureData); } - }, [featureData]); + + const fetchAll = async () => { + const operationData = await getData(`v1/bizInfo/bizByFclt?mngInstCd=${featureData?.mng_inst_cd}&fcltMngNo=${featureData?.fclt_mng_no}&page=0&size=1`); + + let inspectionArr: { year: string; type: string, bizNm: string, bizType: string }[] = []; + let cleaningArr: { year: string; type: string, bizNm: string, bizType: string }[] = []; + let repairArr: { year: string; type: string, bizNm: string, bizType: string }[] = []; + + if (Array.isArray(operationData)) { + operationData.forEach(item => { + if (!item.flfmt_yr) return; + // biz_se_cd에 해당하는 type명 찾기 + const seCodeObj = BIZ_SE_CD.find(code => code.lwpoCd === item.biz_se_cd); + const tyCodeObj = BIZ_TY_CD.find(code => code.lwpoCd === item.biz_ty_cd); + const seTypeName = seCodeObj ? seCodeObj.lwpoCdNm : ""; + const tyTypeName = tyCodeObj ? tyCodeObj.lwpoCdNm : ""; + switch (item.biz_se_cd) { + case "100": + inspectionArr.push({ + year: String(item.flfmt_yr), + type: seTypeName, + bizNm: String(item.biz_nm), + bizType: tyTypeName, + }); + break; + case "203": + cleaningArr.push({ + year: String(item.flfmt_yr), + type: seTypeName, + bizNm: String(item.biz_nm), + bizType: tyTypeName, + }); + break; + case "200": + case "201": + case "204": + repairArr.push({ + year: String(item.flfmt_yr), + type: seTypeName, + bizNm: String(item.biz_nm), + bizType: tyTypeName, + }); + break; + } + }); + } + + setInspectionData(inspectionArr); + setCleaningData(cleaningArr); + setRepairData(repairArr); + console.log('inspectionArr', inspectionArr); + console.log('cleaningArr', cleaningArr); + console.log('repairArr', repairArr); + }; + fetchAll(); + }, []); // 폼 데이터가 변경될 때 호출될 핸들러 const handleFormDataChange = (newFormData: any) => { @@ -56,6 +121,18 @@ const MsSwagePpl = ({ featureData, onSaveClick }: { featureData: any, onSaveClic } }; + // 변환 함수: 객체 → [{ year, type }] + // function convertToYearTypeArray(obj: any): { year: string, type: string }[] { + // if (!obj || typeof obj !== "object") return []; + // // 이미 배열이면 그대로 반환 + // if (Array.isArray(obj)) return obj; + // // 객체의 각 key를 type, value를 year로 변환 + // return Object.entries(obj).map(([type, year]) => ({ + // year: String(year ?? ""), + // type: String(type ?? ""), + // })); + // } + return ( <> 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 acc9cc657..52fc5523d 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx @@ -8,7 +8,7 @@ import { getData } from "@/components/lib/api"; import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue'; const inputColumn = [ - { id: "prrtymngYn", title: "중점여부", type: "select", options: ["중점우수토실", "우수토실"] }, + { id: "prrtymngYn", title: "중점여부", type: "select", options: ["우수토실", "중점우수토실"] }, { id: "swtrmtZoneCd", title: "처리구역", type: "input" }, ]; diff --git a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx b/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx index e40a5bfb6..8c799b942 100644 --- a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx +++ b/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx @@ -6,7 +6,7 @@ import { useGisContext } from "@common/business_components/ui/map/Gis"; import { Button } from "@common/components/ui"; import { useEffect, useRef, useState, useCallback, useMemo } from "react"; import { getLayerContentComponent } from "./components/common"; -import { SwtrmtFcltCol, SwtrmtPrcsZoneCol, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, ExclnSewagePumpCol, MsSwageMhlCol, stofcbrCol, MS_SWAGE_MHL_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from "./components/common/table"; +import { SwtrmtFcltCol, SwtrmtFcltCol2, SwtrmtPrcsZoneCol, SwtrmtPrcsZoneCol2, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, MsSwagePplCol2, ExclnSewagePumpCol, ExclnSewagePumpCol2, DrtwSewagePumpCol1, DrtwSewagePumpCol2, MsSwageMhlCol, MsSwageMhlCol2, stofcbrCol, stofcbrCol2, MS_SWAGE_MHL_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from "./components/common/table"; import InfilChart from './components/popupComponent/chart/infilChart'; import RdiiChart from './components/popupComponent/chart/rdiiChart'; import { useInfilChartModalStore, useRdiiChartModalStore } from "./components/popupComponent/chartModalStore"; @@ -33,6 +33,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, const { setIsOpen: setIsModalInfil } = useInfilChartModalStore(); const { setIsOpen: setIsModalRdii } = useRdiiChartModalStore(); const [curPage, setCurPage] = useState(1); // 현재 페이지 상태 + const [isClicked, setIsClicked] = useState(true); // 클릭 여부 상태 // 🎯 관로관리번호 추출 const pplMngNo = featureData?.values_?.fclt_mng_no || ""; @@ -66,8 +67,9 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, } }); // console.log("featureLayer.get('lyrTyNm');", featureLayer.get('lyrTyNm')); - // SearchModal 클릭 이벤트와 Gis 클릭 이벤트 구분하기 + // SearchModal 클릭 이벤트 if (featureLayer.get('lyrNm') === null) { + setIsClicked(false); if (featureData.lyrTypeNm === 'tb_il_swage_prcs_fclt') result = '하수처리시설'; else if (featureData.lyrTypeNm === 'tb_ms_swage_prcs_zone') result = '하수처리구역'; else if (featureData.lyrTypeNm === 'tb_ms_stofcbr') result = '우수토실'; @@ -77,15 +79,17 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장'); console.log('값 비교', featureData.values_.usg_cd.trim(), drtwPumpCode?.val); if (drtwPumpCode && featureData.values_.usg_cd.trim() === drtwPumpCode.val) { - setIsDrtwSewagePump(true); - } else { setIsDrtwSewagePump(false); + } else { + setIsDrtwSewagePump(true); } result = '하수펌프장'; } else if (featureData.lyrTypeNm === 'tb_ms_swage_mhl') result = '하수맨홀'; } else { + // Gis 레이어 클릭 이벤트 + setIsClicked(true); const lyrTyNm = featureLayer.get('lyrTyNm'); if (lyrTyNm === 'tb_il_swage_prcs_fclt') result = '하수처리시설'; else if (lyrTyNm === 'tb_ms_swage_prcs_zone') result = '하수처리구역'; @@ -96,9 +100,9 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장'); console.log('값 비교', featureData.values_.usg_cd.trim(), drtwPumpCode?.val); if (drtwPumpCode && featureData.values_.usg_cd.trim() === drtwPumpCode.val) { - setIsDrtwSewagePump(true); - } else { setIsDrtwSewagePump(false); + } else { + setIsDrtwSewagePump(true); } result = '하수펌프장'; } @@ -135,15 +139,16 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, // 🎯 기본 데이터 포맷팅 const formattedData = formatDisplayData(data); - if (featureData.values_.fclt_mng_no) setLayerSpecificNm(featureData.values_.fclt_mng_no); - else if (featureData.values_.swtrmt_fclt_cd) setLayerSpecificNm(featureData.values_.swtrmt_fclt_cd); - else setLayerSpecificNm(featureData.values_.manage_no); + if (featureData?.values_?.fclt_mng_no) setLayerSpecificNm(featureData.values_.fclt_mng_no); + else if (featureData?.values_?.swtrmt_fclt_cd) setLayerSpecificNm(featureData.values_.swtrmt_fclt_cd); + else setLayerSpecificNm(featureData?.values_?.manage_no); setFetchData(formattedData); setTableData(formattedData); switch (selectedLayerName) { case '하수관로': - setHeadlist(MsSwagePplCol) + if (isClicked) setHeadlist(MsSwagePplCol) + else setHeadlist(MsSwagePplCol2) setButtonChk(true) // ✅ codeMapper 사용하여 API 결과도 변환 @@ -155,7 +160,8 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, // setTableData(mappedData); break; case '하수맨홀': - setHeadlist(MsSwageMhlCol) + if (isClicked) setHeadlist(MsSwageMhlCol) + else setHeadlist(MsSwageMhlCol2) setButtonChk(true) // ✅ codeMapper 사용하여 API 결과도 변환 @@ -167,10 +173,17 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, // setTableData(mappedData); break; case '하수펌프장': - setHeadlist(ExclnSewagePumpCol) + if (isDrtwSewagePump) { + if (isClicked) setHeadlist(DrtwSewagePumpCol1) + else setHeadlist(DrtwSewagePumpCol2) + } else { + if (isClicked) setHeadlist(ExclnSewagePumpCol) + else setHeadlist(ExclnSewagePumpCol2) + } + setButtonChk(true) - setTableData(codeMapper({ + setTableData(codeMapper({ layerName: selectedLayerName, data: { ...formattedData } })); @@ -178,15 +191,18 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, // setTableData(mappedData); break; case '하수처리시설': - setHeadlist(SwtrmtFcltCol); + if (isClicked) setHeadlist(SwtrmtFcltCol) + else setHeadlist(SwtrmtFcltCol2) setButtonChk(false) break; case '하수처리구역': - setHeadlist(SwtrmtPrcsZoneCol) + if (isClicked) setHeadlist(SwtrmtPrcsZoneCol) + else setHeadlist(SwtrmtPrcsZoneCol2) setButtonChk(false) break; case '우수토실': - setHeadlist(stofcbrCol) + if (isClicked) setHeadlist(stofcbrCol) + else setHeadlist(stofcbrCol2) setButtonChk(true) setIsMainSsc(false) break; @@ -477,7 +493,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
정보를 저장하시겠습니까?
{ContentComponent && { }; return (
- +
); }; diff --git a/apps/sn/app/(map-layout)/map/SearchModal.tsx b/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx similarity index 67% rename from apps/sn/app/(map-layout)/map/SearchModal.tsx rename to apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx index e893fc036..1163def9c 100644 --- a/apps/sn/app/(map-layout)/map/SearchModal.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx @@ -1,18 +1,18 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useMemo } from 'react'; import axios from 'axios'; -import { UiModal, UiTable, DatePickerRange, SelectBox } from '@common/business_components/ui'; +import { UiModal, UiTable, DatePickerRange, SelectBox, UITab } from '@common/business_components/ui'; import { Button, Input, Label } from '@common/components'; -import { UiTable2 } from '@common/business_components/ui/table/index-2'; -import { UITab2 } from '@common/business_components/ui/tab/index-2'; import { SelectBox2 } from '@common/business_components/ui/select/index-2'; import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox'; import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox'; -import { MsSwagePplCol2, SwtrmtFcltCol2, SwtrmtPrcsZoneCol2, MsSwageMhlCol2, ExclnSewagePumpCol2, stofcbrCol2 } from './components/common/table'; +import { MsSwagePplCol2, SwtrmtFcltCol2, SwtrmtPrcsZoneCol2, MsSwageMhlCol2, ExclnSewagePumpCol2, stofcbrCol2 } from '../components/common/table'; import LoadingOverlay from '@/components/ui/LoadingBar'; //import { useDcTree, flattenFolders, useSggCd, useCityCd } from './components/searchModalReportApi'; -import { useDcTree, flattenFolders, useSggCd, useCityCd, addFileName, getFileDownload } from './components/searchModalReportApi'; -import { useCityCdStore, type SelectDataType } from './commonStore'; -import { MS_SWAGE_PPL_USE_CODES, MS_SWAGE_PPL_CODES, MS_SWAGE_MHL_USE_CODES } from '../map/components/common/table'; +import { useDcTree, flattenFolders, useSggCd, useCityCd, addFileName, getFileDownload } from '../components/searchModalReportApi'; +import { useCityCdStore, type SelectDataType } from '../commonStore'; +import { MS_SWAGE_PPL_USE_CODES, MS_SWAGE_PPL_CODES, MS_SWAGE_MHL_USE_CODES } from '../components/common/table'; +// import { useBizByFcltStore } from "../../../store/StoreProvider"; +import { getData } from "@/components/lib/api"; const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}`; @@ -40,16 +40,44 @@ const WORK_TYPES = [ { val: "inspection", text: "점검 및 진단" }, ]; -const YEARS = Array.from({ length: 100 }, (_, i) => `${2025 - i}`); - -// 운영정보 +// 운영정보 - 사업 현황 const operationTableHeadlist = [ - { id: "no", title: "NO" }, - { id: "manageNumber", title: "관리번호" }, - { id: "diagnosisYear", title: "진단년도" }, - { id: "null1", title: "..." }, - { id: "null2", title: "..." }, - { id: "installationLocation", title: "매설위치" }, + { id: "bizNm", title: "사업명" }, + { id: "flfmtBgngYmd", title: "수행시작일자" }, + { id: "flfmtEndYmd", title: "수행종료일자" }, + { id: "flfmtYr", title: "수행년도" }, + { id: "bizTyCd", title: "사업유형" }, + { id: "bizAmt", title: "사업금액" }, +]; +// 운영정보 - 보수 및 갱신 결과표 +const operationMaintenanceTableHeadlist = [ + { id: "fcltMngNo", title: "관리번호" }, + { id: "usgCd", title: "용도" }, + { id: "mqltCd", title: "재질" }, + { id: "pdmt", title: "관경(mm)" }, + { id: "prlg", title: "연장(m)" }, + { id: "instlYmd", title: "설치일자" }, + // { id: "instlYmd", title: "사업구분" }, +]; +// 운영정보 - 청소 및 준설 결과표 +const operationCleaningTableHeadlist = [ + { id: "fcltMngNo", title: "관리번호" }, + { id: "usgCd", title: "용도" }, + { id: "mqltCd", title: "재질" }, + { id: "pdmt", title: "관경(mm)" }, + { id: "prlg", title: "연장(m)" }, + { id: "instlYmd", title: "설치일자" }, +]; +// 운영정보 - 점검 및 진단 결과표 +const operationInspectionTableHeadlist = [ + { id: "fcltMngNo", title: "관리번호" }, + { id: "usgCd", title: "용도" }, + { id: "mqltCd", title: "재질" }, + { id: "pdmt", title: "관경(mm)" }, + { id: "prlg", title: "연장(m)" }, + { id: "instlYmd", title: "설치일자" }, + { id: "strct_stat_grd", title: "구조적 상태등급" }, + { id: "oper_stat_grd", title: "운영적 상태등급" }, ]; // 하수도정비 기본계획 보고서 const reportTableHeadlist = [ @@ -89,12 +117,14 @@ const SearchModal: React.FC = ({ onFeatureSelect, }) => { const [activeTab, setActiveTab] = useState(TABS[0]?.val ?? "basic"); + const [basicType, setBasicType] = useState(BASIC_TYPES[0]?.val ?? ""); const [workType, setWorkType] = useState(WORK_TYPES[0]?.val ?? ""); const [showTable, setShowTable] = useState(false); const [tableData, setTableData] = useState([]); + const [detailTableData, setDetailTableData] = useState([]); const [tableCount, setTableCount] = useState(0); + const [detailTableCount, setDetailTableCount] = useState(0); const [curPage, setCurPage] = useState(1); - const [basicType, setBasicType] = useState(BASIC_TYPES[0]?.val ?? ""); const [시도, set시도] = useState(0); const [시군구, set시군구] = useState(0); const [ctpvCd, setCtpvCd] = useState('0'); @@ -121,9 +151,11 @@ const SearchModal: React.FC = ({ const [가동개시_종료_월, set가동개시_종료_월] = useState(''); const [가동개시_시작_일, set가동개시_시작_일] = useState(''); const [가동개시_종료_일, set가동개시_종료_일] = useState(''); - const [fromDate, setFromDate] = useState(() => { const date = new Date(); date.setDate(date.getDate() - 7); return date }) + // const [fromDate, setFromDate] = useState(() => { const date = new Date(); date.setDate(date.getDate() - 7); return date }) const [toDate, setToDate] = useState(new Date()) const [filteredSiguns, setFilteredSiguns] = useState([{ val: '0', text: '전체', sido: '0' }]); + // const [dynamicHeadlist, setDynamicHeadlist] = useState<{ id: string, title: string }[]>([]); + // const [dynamicHeadlist2, setDynamicHeadlist2] = useState<{ id: string, title: string }[]>([]); // 로딩바 const [isLoading, setIsLoading] = useState(false); @@ -138,31 +170,61 @@ const SearchModal: React.FC = ({ const todayMonth = (today.getMonth() + 1).toString().padStart(2, "0"); const todayDate = today.getDate().toString().padStart(2, "0"); - const isDateInRanges = (date: Date) => { - const standYear = parseInt(fromDate.getFullYear().toString()); - const dateRanges = []; - dateRanges.push({ - start: new Date(standYear, 0, 1), - end: new Date(standYear, 11, 31) - }); + // const isDateInRanges = (date: Date) => { + // const standYear = parseInt(fromDate.getFullYear().toString()); + // const dateRanges = []; + // dateRanges.push({ + // start: new Date(standYear, 0, 1), + // end: new Date(standYear, 11, 31) + // }); - return dateRanges.some(range => { - const start = new Date(range.start); - const end = new Date(range.end); - return date >= start && date <= end; - }); - }; + // return dateRanges.some(range => { + // const start = new Date(range.start); + // const end = new Date(range.end); + // return date >= start && date <= end; + // }); + // }; - // UiTable2에 넘길 headlist를 BASIC_TYPES 값에 따라 분기 처리 - let dynamicHeadlist = MsSwagePplCol2; // default 값 - if (activeTab === 'operation') dynamicHeadlist = operationTableHeadlist; // 운영정보 - else if (activeTab === 'report') dynamicHeadlist = reportTableHeadlist; // 하수도정비기본계획보고서 - else if (basicType === 'tb_ms_swage_ppl') dynamicHeadlist = MsSwagePplCol2; // 하수관로 - else if (basicType === 'tb_il_swage_prcs_fclt') dynamicHeadlist = SwtrmtFcltCol2; // 하수처리시설 - else if (basicType === 'tb_ms_swage_prcs_zone') dynamicHeadlist = SwtrmtPrcsZoneCol2; // 하수처리구역 - else if (basicType === 'tb_ms_swage_mhl') dynamicHeadlist = MsSwageMhlCol2; // 하수맨홀 - else if (basicType === 'tb_ms_swage_pmstn') dynamicHeadlist = ExclnSewagePumpCol2; // 하수펌프장 - else if (basicType === 'tb_ms_stofcbr') dynamicHeadlist = stofcbrCol2; // 우수토실 + // const BIZ_TY_CD = useBizByFcltStore(state => state.BIZ_TY_CD); + const BIZ_TY_CD = [ + { lwpoCd: "0", lwpoCdNm: "전체" }, + { lwpoCd: "SV", lwpoCdNm: "용역" }, + { lwpoCd: "SF", lwpoCdNm: "자체" }, + { lwpoCd: "SC", lwpoCdNm: "공사" }, + ]; + console.log('BIZ_TY_CD', BIZ_TY_CD); + + const BIZ_TY_CD_SELECT_ARRAY = BIZ_TY_CD.map(item => ({ + val: item.lwpoCd, + text: item.lwpoCdNm, + })); + + const dynamicHeadlist = useMemo(() => { + if (activeTab === 'basic') { + if (basicType === 'tb_ms_swage_ppl') return MsSwagePplCol2; + if (basicType === 'tb_il_swage_prcs_fclt') return SwtrmtFcltCol2; + if (basicType === 'tb_ms_swage_prcs_zone') return SwtrmtPrcsZoneCol2; + if (basicType === 'tb_ms_swage_mhl') return MsSwageMhlCol2; + if (basicType === 'tb_ms_swage_pmstn') return ExclnSewagePumpCol2; + if (basicType === 'tb_ms_stofcbr') return stofcbrCol2; + + return []; + } + if (activeTab === 'operation') return operationTableHeadlist; + if (activeTab === 'report') return reportTableHeadlist; + + return []; + }, [activeTab, basicType, workType]); + + const dynamicHeadlist2 = useMemo(() => { + if (activeTab === 'operation') { + if (workType === 'maintenance') return operationMaintenanceTableHeadlist; + if (workType === 'cleaning') return operationCleaningTableHeadlist; + if (workType === 'inspection') return operationInspectionTableHeadlist; + } + + return []; + }, [activeTab, workType]); // 조회 버튼 클릭 시 1페이지로 이동하도록 수정 @@ -172,20 +234,32 @@ const SearchModal: React.FC = ({ setShowTable(true); }; - // cellClick 함수 타입 지정 - const handleCellClick = (index?: number) => { + // 기본정보 테이블 cellClick 핸들러 + const handleBasicCellClick = (index?: number | undefined, headId?: String) => { if (typeof index === "number") { onFeatureSelect(tableData[index % 10]); // 10은 page size 하드 코딩한 숫자 onOpenChange(false); // SearchModal 닫기 } }; - // 하수도정비기본계획.table cellClick - const handleReportCellClick = (index: number) => { + // 운영정보 테이블 cellClick 핸들러 + const handleOperationCellClick = async (index?: number | undefined, headId?: String) => { + if (typeof index === "number") { + const res = await getData(`v1/bizInfo/fclts?bizId=${tableData[index % 5].bizId}`); + console.log('운영정보 cellClick 데이터:', res); + console.log('운영정보 length:', res.data.length); + setDetailTableData(res.data || []); + setDetailTableCount(res.count || 0); + } + }; + // 하수도정비기본계획 테이블 cellClick 핸들러 + const handleReportCellClick = (index: number | undefined, headId?: String) => { console.log(index); - const reportData = tableData[index]; - const fileName = reportData.fileName; - if (reportData.fileSn !== "") { - getFileDownload(reportData.fileSn, fileName); + if (typeof index === "number" && tableData[index]) { + const reportData = tableData[index]; + const fileName = reportData.fileName; + if (reportData.fileSn !== "") { + getFileDownload(reportData.fileSn, fileName); + } } }; @@ -204,7 +278,6 @@ const SearchModal: React.FC = ({ useEffect(() => { // filterParams 초기화 - // setFilterParams({}); set시작1(""); set시작2(""); set종료1(""); @@ -224,7 +297,6 @@ const SearchModal: React.FC = ({ setYearFilter({ 시작: "", 종료: "", - // 경과년도: "", }); setShowTable(false); setTableCount(0); @@ -232,6 +304,16 @@ const SearchModal: React.FC = ({ // queryParams는 fetchFilteredData 내에서 매번 새로 생성되므로 별도 상태 초기화는 필요 없음 }, [activeTab, basicType, open]); + useEffect(() => { + setActiveTab(TABS[0]?.val ?? "basic"); + setBasicType(BASIC_TYPES[0]?.val ?? ""); + setWorkType(WORK_TYPES[0]?.val ?? ""); + setTableCount(0); + setTableData([]); + setDetailTableCount(0); + setDetailTableData([]); + }, [open]); + // 페이지 변경 시마다 데이터 fetch useEffect(() => { // showTable이 true일 때만 fetch (최초 렌더 방지) @@ -246,31 +328,66 @@ const SearchModal: React.FC = ({ const fetchFilteredData = async () => { setIsLoading(true); // 로딩 시작 try { - const queryParams = new URLSearchParams({ - lyrTypeNm: basicType, - page: `${curPage - 1}`, - size: '10', - sort: 'string', - }); - console.log('basicType', basicType); - let cqlFilters: string[] = []; if (activeTab === 'basic') { + const queryParams = new URLSearchParams({ + lyrTypeNm: basicType, + page: `${curPage - 1}`, + size: '10', + sort: 'string', + }); + console.log('basicType', basicType); + if (basicType === 'tb_ms_swage_prcs_zone') cqlFilters = zoneCqlFilters(); // 하수처리구역 else if (basicType === 'tb_il_swage_prcs_fclt') cqlFilters = facilityCqlFilters(); // 하수처리시설 else if (basicType === 'tb_ms_swage_ppl') cqlFilters = pplCqlFilters(); // 하수관로 else if (basicType === 'tb_ms_swage_mhl') cqlFilters = mhCqlFilters(); // 하수맨홀 else if (basicType === 'tb_ms_swage_pmstn') cqlFilters = psmtnCqlFilters(); // 하수펌프장 else if (basicType === 'tb_ms_stofcbr') cqlFilters = otflCqlFilters(); // 우수토실 + + if (cqlFilters.length > 0) queryParams.append('cqlFiter', cqlFilters.join(' and ')); + + console.log('API URL:', `${API_URL}/v1/fclts?${queryParams.toString()}`); + const res = await axios.get(`${API_URL}/v1/fclts?${queryParams.toString()}`); + console.log('필터링된 API 결과(개수):', res.data.count); + console.log('필터링된 API 결과(데이터):', res.data.data); + setTableData(res.data.data || []); + setTableCount(res.data.count || []); + console.log('tableCount 상태 업데이트 후:', res.data.count); // tableCount 로그 추가 + } else if (activeTab === 'operation') { - cqlFilters = zoneCqlFilters(); - } else { - cqlFilters = reportCqlFilters(); - } + const RequestDTO: Record = { + page: `${curPage - 1}`, + size: '5', + }; + if (변수1) RequestDTO.bizNm = 변수1; + if (변수2) RequestDTO.bizTyCd = 변수2; + // 수행기간 범위 + const startDate = getDateString( + yearFilter.시작, + 가동개시_시작_월, + 가동개시_시작_일, + "19000101", + ); + const endDate = getDateString( + yearFilter.종료, + 가동개시_종료_월, + 가동개시_종료_일, + `${todayYear}${todayMonth}${todayDate}`, + ); + RequestDTO.fromflfmtEndYmd = startDate; + RequestDTO.toflfmtEndYmd = endDate; - if (cqlFilters.length > 0) queryParams.append('cqlFiter', cqlFilters.join(' and ')); + const params = new URLSearchParams(RequestDTO).toString(); - if (activeTab === 'report') { + console.log('API URL:', `/v1/bizInfo?${params}`); + const res = await getData(`v1/bizInfo?${params}`); + console.log('필터링된 API 결과(개수):', res.totalElements); + console.log('필터링된 API 결과(데이터):', res.content); + setTableData(res.content || []); + setTableCount(res.totalElements || 0); + + } else if (activeTab === 'report') { //const reportOriginData = await getDcTree('경기도'); const reportData = flattenFolders(reportOriginData); let filterReportData = reportData; @@ -304,14 +421,6 @@ const SearchModal: React.FC = ({ setTableData(filterReportData || []); }); setTableData(filterReportData || []); - } else { - console.log('API URL:', `${API_URL}/v1/fclts?${queryParams.toString()}`); - const res = await axios.get(`${API_URL}/v1/fclts?${queryParams.toString()}`); - console.log('필터링된 API 결과(개수):', res.data.count); - console.log('필터링된 API 결과(데이터):', res.data.data); - setTableData(res.data.data || []); - setTableCount(res.data.count || []); - console.log('tableCount 상태 업데이트 후:', res.data.count); // tableCount 로그 추가 } setShowTable(true); @@ -330,7 +439,6 @@ const SearchModal: React.FC = ({ if (변수1) cqlFilters.push(`usg_cd='${변수1}'`); if (변수2) cqlFilters.push(`mqlt_cd='${변수2}'`); if (변수3) cqlFilters.push(`pbadms_emd_cd='${변수3}'`); - // if (변수4) cqlFilters.push(`경과년도='${변수4}'`); // 설치년도 범위 const startDate = getDateString( yearFilter.시작, @@ -358,7 +466,6 @@ const SearchModal: React.FC = ({ return cqlFilters; }; - // 하수처리시설용 CQL 필터 생성 const facilityCqlFilters = () => { const cqlFilters: string[] = []; @@ -392,7 +499,6 @@ const SearchModal: React.FC = ({ if (변수1) cqlFilters.push(`swtrmt_fclt_nm ILIKE '%${변수1}%'`); return cqlFilters; }; - // 하수처리구역용 CQL 필터 생성 const zoneCqlFilters = () => { const cqlFilters: string[] = []; @@ -402,7 +508,6 @@ const SearchModal: React.FC = ({ if (변수2) cqlFilters.push(`swtrmt_fclt_nm ILIKE '%${변수2}%'`); return cqlFilters; }; - // 하수맨홀용 CQL 필터 생성 const mhCqlFilters = () => { const cqlFilters: string[] = []; @@ -430,7 +535,6 @@ const SearchModal: React.FC = ({ return cqlFilters; }; - // 하수펌프장용 CQL 필터 생성 const psmtnCqlFilters = () => { const cqlFilters: string[] = []; @@ -450,7 +554,6 @@ const SearchModal: React.FC = ({ cqlFilters.push( `instl_ymd >= '${startDate}' and instl_ymd <= '${endDate}'`, ); - // if (변수1) cqlFilters.push(`경과년도='${변수1}'`); // 일일처리용량 범위 if (시작1 && 종료1) cqlFilters.push(`daily_prcs_cpct BETWEEN ${시작1} AND ${종료1}`); @@ -464,7 +567,6 @@ const SearchModal: React.FC = ({ return cqlFilters; }; - // 우수토실용 CQL 필터 생성 const otflCqlFilters = () => { const cqlFilters: string[] = []; @@ -484,45 +586,6 @@ const SearchModal: React.FC = ({ cqlFilters.push( `instl_ymd >= '${startDate}' and instl_ymd <= '${endDate}'`, ); - // if (변수1) cqlFilters.push(`경과년도='${변수1}'`); - // if (변수2) cqlFilters.push(`하천명 ILIKE '%${변수1}%'`); - // 계획방류량 범위 - // if (시작1 && 종료1) - // cqlFilters.push(`계획방류량 BETWEEN ${시작1} AND ${종료1}`); - // else if (시작1) cqlFilters.push(`계획방류량 >= ${시작1}`); - // else if (종료1) cqlFilters.push(`계획방류량 <= ${종료1}`); - - return cqlFilters; - }; - - // 운영정보용 CQL 필터 생성 - const operationCqlFilters = () => { - const cqlFilters: string[] = []; - // 설치년도 범위 - const startDate = getDateString( - yearFilter.시작, - 가동개시_시작_월, - 가동개시_시작_일, - "19000101", - ); - const endDate = getDateString( - yearFilter.종료, - 가동개시_종료_월, - 가동개시_종료_일, - `${todayYear}${todayMonth}${todayDate}`, - ); - cqlFilters.push( - `설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`, - ); - return cqlFilters; - }; - - // 하수도정비기본계획보고서용 CQL 필터 생성 - const reportCqlFilters = () => { - const cqlFilters: string[] = []; - // 설치년도 범위 - if (ctpvCd) cqlFilters.push(`ctpv_cd='${ctpvCd}'`); - if (sigungu) cqlFilters.push(`sgg_cd='${sigungu}'`); return cqlFilters; }; @@ -530,18 +593,18 @@ const SearchModal: React.FC = ({ const renderBody = () => ( <> {/* 탭 영역 */} - ({ value: tab.val, - label: tab.text, - onClick: () => setActiveTab(tab.val), + label: tab.text }))} + onValueChange={(value: string) => setActiveTab(value)} > {/* 각각의 탭 영역 */} {/* 기본정보 탭 */} {activeTab === 'basic' && ( -
+
{/* 구분 */}
@@ -575,26 +638,9 @@ const SearchModal: React.FC = ({ startLabel="설치년도" endLabel="" /> - - {/* 경과년도 */} - {/*
- - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ""); - setYearFilter({ ...yearFilter, 경과년도: val }); - }} - /> -
*/} {/* 용도 */} = ({ set변수2(String(val)); }} /> -
-
- {/* 행정읍면동코드 */} - {/* - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ""); - set변수3(val); - }} - /> */} {/* 관경 */} { @@ -646,7 +676,7 @@ const SearchModal: React.FC = ({ /> ~ { @@ -660,7 +690,7 @@ const SearchModal: React.FC = ({ 연장(m) { @@ -671,7 +701,7 @@ const SearchModal: React.FC = ({ /> ~ { @@ -680,12 +710,16 @@ const SearchModal: React.FC = ({ set종료2(val); }} /> + {/* 조회 버튼 */} +
+ +
)} {/* 분기처리: 하수처리시설 */} {basicType === "tb_il_swage_prcs_fclt" && ( -
+
{/* 가동개시일자 */}
= ({ }) } startLabel="가동개시일자" - endLabel=" " + endLabel="" /> {/* 시설용량 */} - + { @@ -717,7 +749,7 @@ const SearchModal: React.FC = ({ /> ~ { @@ -726,14 +758,10 @@ const SearchModal: React.FC = ({ set종료1(val); }} /> -
-
{/* 처리구역 면적 */} - + { @@ -744,7 +772,7 @@ const SearchModal: React.FC = ({ /> ~ { @@ -754,9 +782,7 @@ const SearchModal: React.FC = ({ }} /> {/* 하수처리시설명 */} - + = ({ set변수1(e.target.value); }} /> + {/* 조회 버튼 */} +
+ +
)} @@ -803,6 +833,10 @@ const SearchModal: React.FC = ({ set변수2(e.target.value); }} /> + {/* 조회 버튼 */} +
+ +
)} @@ -824,23 +858,9 @@ const SearchModal: React.FC = ({ startLabel="설치년도" endLabel="" /> - {/* 경과년도 */} - {/* - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ""); - setYearFilter({ ...yearFilter, 경과년도: val }); - }} - /> */} {/* 용도 */} = ({ set종료1(val); }} /> + {/* 조회 버튼 */} +
+ +
)} @@ -889,20 +913,8 @@ const SearchModal: React.FC = ({ startLabel="설치년도" endLabel="" /> - {/* 경과년도 */} - {/* - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); - setYearFilter({ ...yearFilter, 경과년도: val }); - }} - /> */} {/* 일일처리용량 - 오수맨홀 */} -