Merge remote-tracking branch 'origin/iipbs/sn/dev'
This commit is contained in:
@@ -8,6 +8,9 @@ import SwagePrcsZone from './swagePrcsZone';
|
||||
import SwageMhl from './swageMhl';
|
||||
import SwagePmstn from './swagePmstn';
|
||||
import Stofcbr from './stofcbr';
|
||||
import { useSearchModal, type SearchModalProps } from './useSearchModal';
|
||||
import useSearchModalStore from '../../../store/useSearchModalStore';
|
||||
|
||||
|
||||
// 기본정보 '구분' 선택 목록
|
||||
export const BASIC_TYPES = [
|
||||
@@ -19,57 +22,9 @@ export const BASIC_TYPES = [
|
||||
{ val: "tb_ms_stofcbr", text: "우수토실" },
|
||||
];
|
||||
|
||||
interface BasicTabProps {
|
||||
basicType: string;
|
||||
city: string;
|
||||
sgg: string;
|
||||
start1: string;
|
||||
start2: string;
|
||||
end1: string;
|
||||
end2: string;
|
||||
var1: string;
|
||||
var2: string;
|
||||
yearFilter: { start: string; end: string; };
|
||||
handleSearch: () => void;
|
||||
setBasicType: (type: string) => void;
|
||||
setCity: (city: string) => void;
|
||||
setCtpvName: (name: string) => void;
|
||||
setSgg: (sgg: string) => void;
|
||||
setSggName: (name: string) => void;
|
||||
setYearFilter: (filter: { start: string; end: string }) => void;
|
||||
setStart1: (value: string) => void;
|
||||
setStart2: (value: string) => void;
|
||||
setEnd1: (value: string) => void;
|
||||
setEnd2: (value: string) => void;
|
||||
setVar1: (value: string) => void;
|
||||
setVar2: (value: string) => void;
|
||||
}
|
||||
const BasicTab: React.FC<SearchModalProps> = (props) => {
|
||||
const { basicType, setBasicType } = useSearchModalStore();
|
||||
|
||||
const BasicTab: React.FC<BasicTabProps> = ({
|
||||
basicType,
|
||||
city,
|
||||
sgg,
|
||||
start1,
|
||||
start2,
|
||||
end1,
|
||||
end2,
|
||||
var1,
|
||||
var2,
|
||||
yearFilter,
|
||||
handleSearch,
|
||||
setBasicType,
|
||||
setCity,
|
||||
setCtpvName,
|
||||
setSgg,
|
||||
setSggName,
|
||||
setYearFilter,
|
||||
setStart1,
|
||||
setStart2,
|
||||
setEnd1,
|
||||
setEnd2,
|
||||
setVar1,
|
||||
setVar2,
|
||||
}) => {
|
||||
return (
|
||||
<div className="relative border rounded-lg p-5 w-full h-[10vh]">
|
||||
{/* 구분 */}
|
||||
@@ -89,118 +44,13 @@ const BasicTab: React.FC<BasicTabProps> = ({
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* 분기처리: 하수관로 */}
|
||||
{basicType === "tb_ms_swage_ppl" && (
|
||||
<SwagePpl
|
||||
var1={var1}
|
||||
var2={var2}
|
||||
start1={start1}
|
||||
start2={start2}
|
||||
end1={end1}
|
||||
end2={end2}
|
||||
city={city}
|
||||
sgg={sgg}
|
||||
yearFilter={yearFilter}
|
||||
setVar1={setVar1}
|
||||
setVar2={setVar2}
|
||||
setStart1={setStart1}
|
||||
setStart2={setStart2}
|
||||
setEnd1={setEnd1}
|
||||
setEnd2={setEnd2}
|
||||
setCity={setCity}
|
||||
setSgg={setSgg}
|
||||
setYearFilter={setYearFilter}
|
||||
handleSearch={handleSearch}
|
||||
/>
|
||||
)}
|
||||
{/* 분기처리: 하수처리시설 */}
|
||||
{basicType === "tb_il_swage_prcs_fclt" && (
|
||||
<SwagePrcsFclt
|
||||
var1={var1}
|
||||
start1={start1}
|
||||
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}
|
||||
/>
|
||||
)}
|
||||
{/* 분기처리: 하수처리구역 */}
|
||||
{basicType === "tb_ms_swage_prcs_zone" && (
|
||||
<SwagePrcsZone
|
||||
var1={var1}
|
||||
var2={var2}
|
||||
city={city}
|
||||
sgg={sgg}
|
||||
setVar1={setVar1}
|
||||
setVar2={setVar2}
|
||||
setCity={setCity}
|
||||
setSgg={setSgg}
|
||||
handleSearch={handleSearch}
|
||||
/>
|
||||
)}
|
||||
{/* 분기처리: 하수맨홀 */}
|
||||
{basicType === "tb_ms_swage_mhl" && (
|
||||
<SwageMhl
|
||||
var1={var1}
|
||||
start1={start1}
|
||||
end1={end1}
|
||||
city={city}
|
||||
sgg={sgg}
|
||||
yearFilter={yearFilter}
|
||||
setVar1={setVar1}
|
||||
setStart1={setStart1}
|
||||
setEnd1={setEnd1}
|
||||
setCity={setCity}
|
||||
setSgg={setSgg}
|
||||
setYearFilter={setYearFilter}
|
||||
handleSearch={handleSearch}
|
||||
/>
|
||||
)}
|
||||
{/* 분기처리: 하수펌프장 */}
|
||||
{basicType === "tb_ms_swage_pmstn" && (
|
||||
<SwagePmstn
|
||||
start1={start1}
|
||||
start2={start2}
|
||||
end1={end1}
|
||||
end2={end2}
|
||||
city={city}
|
||||
sgg={sgg}
|
||||
yearFilter={yearFilter}
|
||||
setStart1={setStart1}
|
||||
setStart2={setStart2}
|
||||
setEnd1={setEnd1}
|
||||
setEnd2={setEnd2}
|
||||
setCity={setCity}
|
||||
setSgg={setSgg}
|
||||
setYearFilter={setYearFilter}
|
||||
handleSearch={handleSearch}
|
||||
/>
|
||||
)}
|
||||
{/* 분기처리: 우수토실 */}
|
||||
{basicType === "tb_ms_stofcbr" && (
|
||||
<Stofcbr
|
||||
city={city}
|
||||
sgg={sgg}
|
||||
yearFilter={yearFilter}
|
||||
setCity={setCity}
|
||||
setSgg={setSgg}
|
||||
setYearFilter={setYearFilter}
|
||||
handleSearch={handleSearch}
|
||||
/>
|
||||
)}
|
||||
{/* 조회 조건 */}
|
||||
{basicType === "tb_ms_swage_ppl" && (<SwagePpl {...props} />)} {/* 하수관로 */}
|
||||
{basicType === "tb_il_swage_prcs_fclt" && (<SwagePrcsFclt {...props} />)} {/* 하수처리시설 */}
|
||||
{basicType === "tb_ms_swage_prcs_zone" && (<SwagePrcsZone {...props} />)} {/* 하수처리구역 */}
|
||||
{basicType === "tb_ms_swage_mhl" && (<SwageMhl {...props} />)} {/* 하수맨홀 */}
|
||||
{basicType === "tb_ms_swage_pmstn" && (<SwagePmstn {...props} />)} {/* 하수펌프장 */}
|
||||
{basicType === "tb_ms_stofcbr" && (<Stofcbr {...props} />)} {/* 우수토실 */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,8 @@ import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
|
||||
import { SelectBox } from '@common/business_components/ui';
|
||||
import { Button, Input, Label } from '@common/components';
|
||||
import useStore from '../../../store/useStore';
|
||||
import useSearchModalStore from '../../../store/useSearchModalStore';
|
||||
import { useSearchModal, type SearchModalProps } from './useSearchModal';
|
||||
|
||||
// 운영정보 '구분' 선택 목록
|
||||
export const WORK_TYPES = [
|
||||
@@ -65,30 +67,15 @@ export const operationInspectionTableHeadlist = [
|
||||
{ id: "oper_stts_grd", title: "운영적 상태등급" },
|
||||
];
|
||||
|
||||
interface OperationTabProps {
|
||||
workType: string;
|
||||
var1: string;
|
||||
var2: string;
|
||||
yearFilter: { start: string; end: string; };
|
||||
handleSearch: () => void;
|
||||
setWorkType: (type: string) => void;
|
||||
setYearFilter: (filter: { start: string; end: string }) => void;
|
||||
setVar1: (value: string) => void;
|
||||
setVar2: (value: string) => void;
|
||||
}
|
||||
|
||||
const OperationTab: React.FC<OperationTabProps> = ({
|
||||
workType,
|
||||
var1,
|
||||
var2,
|
||||
yearFilter,
|
||||
handleSearch,
|
||||
setWorkType,
|
||||
setVar1,
|
||||
setVar2,
|
||||
setYearFilter,
|
||||
}) => {
|
||||
|
||||
const OperationTab: React.FC<SearchModalProps> = (props) => {
|
||||
const {
|
||||
workType, setWorkType,
|
||||
var1, setVar1, var2, setVar2,
|
||||
yearFilter, setYearFilter,
|
||||
} = useSearchModalStore();
|
||||
const { handleSearch } = useSearchModal(props);
|
||||
|
||||
const { BIZ_TY_CD } = useStore();
|
||||
|
||||
const BIZ_TY_CD_SELECT_ARRAY = BIZ_TY_CD.map(item => ({
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,52 +4,42 @@ import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
|
||||
import { Button } from '@common/components';
|
||||
import React from 'react';
|
||||
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
|
||||
import useSearchModalStore from '../../../store/useSearchModalStore';
|
||||
import { useSearchModal, type SearchModalProps } from './useSearchModal';
|
||||
|
||||
const Stofcbr: React.FC<SearchModalProps> = (props) => {
|
||||
const {
|
||||
ctpvCd, setCtpvCd,
|
||||
sggCd, setSggCd,
|
||||
yearFilter, setYearFilter,
|
||||
} = useSearchModalStore();
|
||||
const { handleSearch } = useSearchModal(props);
|
||||
|
||||
interface StofcbrProps {
|
||||
city: string;
|
||||
sgg: string;
|
||||
yearFilter: { start: string; end: string };
|
||||
setCity: (value: string) => void;
|
||||
setSgg: (value: string) => void;
|
||||
setYearFilter: (filter: { start: string; end: string }) => void;
|
||||
handleSearch: () => void;
|
||||
}
|
||||
|
||||
const Stofcbr: React.FC<StofcbrProps> = ({
|
||||
city,
|
||||
sgg,
|
||||
yearFilter,
|
||||
setCity,
|
||||
setSgg,
|
||||
setYearFilter,
|
||||
handleSearch,
|
||||
}) => {
|
||||
return (
|
||||
<div className="mb-3">
|
||||
<div className="flex items-center mb-2">
|
||||
{/* 시도, 시군구 */}
|
||||
<CtpvSggPrcsFcltSelectBox
|
||||
sido={city}
|
||||
sigungu={sgg}
|
||||
sido={ctpvCd}
|
||||
sigungu={sggCd}
|
||||
onSidoChange={(sidoId: string) => {
|
||||
setCity(sidoId);
|
||||
setSgg("0");
|
||||
setCtpvCd(sidoId);
|
||||
setSggCd("0");
|
||||
}}
|
||||
onSigunguChange={setSgg}
|
||||
onSigunguChange={setSggCd}
|
||||
/>
|
||||
{/* 설치년도 */}
|
||||
<div className="flex items-center mb-2">
|
||||
<YearRangeSelectBox
|
||||
start={yearFilter.start}
|
||||
end={yearFilter.end}
|
||||
onChange={range => setYearFilter({ ...yearFilter, start: range.start, end: range.end })}
|
||||
startLabel="설치년도"
|
||||
endLabel=""
|
||||
/>
|
||||
{/* 조회 버튼 */}
|
||||
<div className="flex-1 flex justify-end">
|
||||
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
|
||||
</div>
|
||||
<YearRangeSelectBox
|
||||
start={yearFilter.start}
|
||||
end={yearFilter.end}
|
||||
onChange={range => setYearFilter({ ...yearFilter, start: range.start, end: range.end })}
|
||||
startLabel="설치년도"
|
||||
endLabel=""
|
||||
/>
|
||||
{/* 조회 버튼 */}
|
||||
<div className="flex-1 flex justify-end">
|
||||
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,56 +1,35 @@
|
||||
// 하수맨홀
|
||||
|
||||
import React from 'react';
|
||||
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
|
||||
import { Button, Input, Label } from '@common/components';
|
||||
import React from 'react';
|
||||
import { MS_SWAGE_MHL_USE_CODES } from '../components/common/table';
|
||||
import { SelectBox } from '@common/business_components/ui';
|
||||
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
|
||||
import useSearchModalStore from '../../../store/useSearchModalStore';
|
||||
import { useSearchModal, type SearchModalProps } from './useSearchModal';
|
||||
|
||||
|
||||
interface SwageMhlProps {
|
||||
var1: string;
|
||||
start1: string;
|
||||
end1: string;
|
||||
city: string;
|
||||
sgg: string;
|
||||
yearFilter: { start: string; end: string };
|
||||
setVar1: (value: string) => void;
|
||||
setStart1: (value: string) => void;
|
||||
setEnd1: (value: string) => void;
|
||||
setCity: (value: string) => void;
|
||||
setSgg: (value: string) => void;
|
||||
setYearFilter: (filter: { start: string; end: string }) => void;
|
||||
handleSearch: () => void;
|
||||
}
|
||||
|
||||
const SwageMhl: React.FC<SwageMhlProps> = ({
|
||||
var1,
|
||||
start1,
|
||||
end1,
|
||||
city,
|
||||
sgg,
|
||||
yearFilter,
|
||||
setVar1,
|
||||
setStart1,
|
||||
setEnd1,
|
||||
setCity,
|
||||
setSgg,
|
||||
setYearFilter,
|
||||
handleSearch,
|
||||
}) => {
|
||||
const SwageMhl: React.FC<SearchModalProps> = (props) => {
|
||||
const {
|
||||
var1, setVar1,
|
||||
start1, setStart1, end1, setEnd1,
|
||||
ctpvCd, setCtpvCd,
|
||||
sggCd, setSggCd,
|
||||
yearFilter, setYearFilter,
|
||||
} = useSearchModalStore();
|
||||
const { handleSearch } = useSearchModal(props);
|
||||
|
||||
return (
|
||||
<div className="mb-3">
|
||||
<div className="mb-2 flex items-center">
|
||||
<CtpvSggPrcsFcltSelectBox
|
||||
sido={city}
|
||||
sigungu={sgg}
|
||||
sido={ctpvCd}
|
||||
sigungu={sggCd}
|
||||
onSidoChange={(sidoId: string) => {
|
||||
setCity(sidoId);
|
||||
setSgg("0");
|
||||
setCtpvCd(sidoId);
|
||||
setSggCd("0");
|
||||
}}
|
||||
onSigunguChange={setSgg}
|
||||
onSigunguChange={setSggCd}
|
||||
/>
|
||||
{/* 설치년도 */}
|
||||
<YearRangeSelectBox
|
||||
|
||||
@@ -4,55 +4,32 @@ import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
|
||||
import { Button, Input, Label } from '@common/components';
|
||||
import React from 'react';
|
||||
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
|
||||
import useSearchModalStore from '../../../store/useSearchModalStore';
|
||||
import { useSearchModal, type SearchModalProps } from './useSearchModal';
|
||||
|
||||
interface SwagePmstnProps {
|
||||
start1: string;
|
||||
start2: string;
|
||||
end1: string;
|
||||
end2: string;
|
||||
city: string;
|
||||
sgg: string;
|
||||
yearFilter: { start: string; end: string };
|
||||
setStart1: (value: string) => void;
|
||||
setStart2: (value: string) => void;
|
||||
setEnd1: (value: string) => void;
|
||||
setEnd2: (value: string) => void;
|
||||
setCity: (value: string) => void;
|
||||
setSgg: (value: string) => void;
|
||||
setYearFilter: (filter: { start: string; end: string }) => void;
|
||||
handleSearch: () => void;
|
||||
}
|
||||
|
||||
const SwagePmstn: React.FC<SwagePmstnProps> = ({
|
||||
start1,
|
||||
start2,
|
||||
end1,
|
||||
end2,
|
||||
city,
|
||||
sgg,
|
||||
yearFilter,
|
||||
setStart1,
|
||||
setStart2,
|
||||
setEnd1,
|
||||
setEnd2,
|
||||
setCity,
|
||||
setSgg,
|
||||
setYearFilter,
|
||||
handleSearch,
|
||||
}) => {
|
||||
const SwagePmstn: React.FC<SearchModalProps> = (props) => {
|
||||
const {
|
||||
start1, setStart1,
|
||||
end1, setEnd1,
|
||||
ctpvCd, setCtpvCd,
|
||||
sggCd, setSggCd,
|
||||
yearFilter, setYearFilter,
|
||||
} = useSearchModalStore();
|
||||
const { handleSearch } = useSearchModal(props);
|
||||
|
||||
return (
|
||||
<div className="mb-3">
|
||||
<div className="flex items-center mb-2">
|
||||
{/* 시도, 시군구 */}
|
||||
<CtpvSggPrcsFcltSelectBox
|
||||
sido={city}
|
||||
sigungu={sgg}
|
||||
sido={ctpvCd}
|
||||
sigungu={sggCd}
|
||||
onSidoChange={(sidoId: string) => {
|
||||
setCity(sidoId);
|
||||
setSgg("0");
|
||||
setCtpvCd(sidoId);
|
||||
setSggCd("0");
|
||||
}}
|
||||
onSigunguChange={setSgg}
|
||||
onSigunguChange={setSggCd}
|
||||
/>
|
||||
{/* 설치년도 */}
|
||||
<YearRangeSelectBox
|
||||
|
||||
@@ -6,62 +6,61 @@ import { Button, Input, Label } from '@common/components';
|
||||
import React from 'react';
|
||||
import { MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_USE_CODES } from '../components/common/table';
|
||||
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
|
||||
import useSearchModalStore from '../../../store/useSearchModalStore';
|
||||
import { useSearchModal, type SearchModalProps } from './useSearchModal';
|
||||
|
||||
interface SwagePplProps {
|
||||
var1: string;
|
||||
var2: string;
|
||||
start1: string;
|
||||
start2: string;
|
||||
end1: string;
|
||||
end2: string;
|
||||
city: string;
|
||||
sgg: 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;
|
||||
setCity: (value: string) => void;
|
||||
setSgg: (value: string) => void;
|
||||
setYearFilter: (filter: { start: string; end: string }) => void;
|
||||
handleSearch: () => void;
|
||||
}
|
||||
// 하수관로용 CQL 필터 생성
|
||||
export const pplCqlFilters = () => {
|
||||
const store = useSearchModalStore();
|
||||
const {
|
||||
todayYear, todayMonth, todayDate,
|
||||
ctpvCd, sggCd,
|
||||
start1, start2, end1, end2,
|
||||
var1, var2,
|
||||
yearFilter, getDateString
|
||||
} = store;
|
||||
|
||||
const SwagePpl: React.FC<SwagePplProps> = ({
|
||||
var1,
|
||||
var2,
|
||||
start1,
|
||||
start2,
|
||||
end1,
|
||||
end2,
|
||||
city,
|
||||
sgg,
|
||||
yearFilter,
|
||||
setVar1,
|
||||
setVar2,
|
||||
setStart1,
|
||||
setStart2,
|
||||
setEnd1,
|
||||
setEnd2,
|
||||
setCity,
|
||||
setSgg,
|
||||
setYearFilter,
|
||||
handleSearch,
|
||||
}) => {
|
||||
const cqlFilters: string[] = [];
|
||||
if (var1) cqlFilters.push(`usg_cd='${var1}'`);
|
||||
if (var2) cqlFilters.push(`mqlt_cd='${var2}'`);
|
||||
if (ctpvCd !== '0' && sggCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${sggCd}%'`);
|
||||
else if (ctpvCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${ctpvCd?.trim()}%'`);
|
||||
// 설치년도 범위
|
||||
const startDate = getDateString(yearFilter.start, '', '', "19000101");
|
||||
const endDate = getDateString(yearFilter.end, '', '', `${todayYear}${todayMonth}${todayDate}`);
|
||||
cqlFilters.push(`instl_ymd >= '${startDate}' and instl_ymd <= '${endDate}'`);
|
||||
// 관경(mm) 범위
|
||||
if (start1 && end1) cqlFilters.push(`pdmt_vl BETWEEN ${start1} AND ${end1}`);
|
||||
else if (start1) cqlFilters.push(`pdmt_vl >= ${start1}`);
|
||||
else if (end1) cqlFilters.push(`pdmt_vl <= ${end1}`);
|
||||
// 연장(m) 범위
|
||||
if (start2 && end2) cqlFilters.push(`prlg_vl BETWEEN ${start2} AND ${end2}`);
|
||||
else if (start2) cqlFilters.push(`prlg_vl >= ${start2}`);
|
||||
else if (end2) cqlFilters.push(`prlg_vl <= ${end2}`);
|
||||
|
||||
return cqlFilters;
|
||||
};
|
||||
|
||||
const SwagePpl: React.FC<SearchModalProps> = (props) => {
|
||||
const {
|
||||
var1, setVar1,
|
||||
start1, setStart1, end1, setEnd1,
|
||||
ctpvCd, setCtpvCd, sggCd, setSggCd,
|
||||
yearFilter, setYearFilter,
|
||||
} = useSearchModalStore();
|
||||
const { handleSearch } = useSearchModal(props);
|
||||
|
||||
return (
|
||||
<div className="mb-6">
|
||||
<div className="mb-2 flex items-center">
|
||||
<CtpvSggPrcsFcltSelectBox
|
||||
sido={city}
|
||||
sigungu={sgg}
|
||||
sido={ctpvCd}
|
||||
sigungu={sggCd}
|
||||
onSidoChange={(sidoId: string) => {
|
||||
setCity(sidoId);
|
||||
setSgg("0");
|
||||
setCtpvCd(sidoId);
|
||||
setSggCd("0");
|
||||
}}
|
||||
onSigunguChange={setSgg}
|
||||
onSigunguChange={setSggCd}
|
||||
/>
|
||||
{/* 설치년도 */}
|
||||
<YearRangeSelectBox
|
||||
@@ -83,7 +82,7 @@ const SwagePpl: React.FC<SwagePplProps> = ({
|
||||
className="w-32 mr-8"
|
||||
selectClass="rounded-lg bg-white text-xl"
|
||||
label=""
|
||||
selectArray={[{val: "0", text: "전체"}, ...MS_SWAGE_PPL_USE_CODES]}
|
||||
selectArray={[{ val: "0", text: "전체" }, ...MS_SWAGE_PPL_USE_CODES]}
|
||||
value={var1}
|
||||
onSelectValue={(val) => {
|
||||
setVar1(String(val));
|
||||
|
||||
@@ -4,57 +4,30 @@ import React from 'react';
|
||||
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
|
||||
import { Button, Input, Label } from '@common/components';
|
||||
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
|
||||
import useSearchModalStore from '../../../store/useSearchModalStore';
|
||||
import { useSearchModal, type SearchModalProps } from './useSearchModal';
|
||||
|
||||
|
||||
interface SwagePrcsFcltProps {
|
||||
var1: string;
|
||||
start1: string;
|
||||
start2: string;
|
||||
end1: string;
|
||||
end2: string;
|
||||
city: string;
|
||||
sgg: string;
|
||||
yearFilter: { start: string; end: string };
|
||||
setVar1: (value: string) => void;
|
||||
setStart1: (value: string) => void;
|
||||
setStart2: (value: string) => void;
|
||||
setEnd1: (value: string) => void;
|
||||
setEnd2: (value: string) => void;
|
||||
setCity: (value: string) => void;
|
||||
setCtpvName: (name: string) => void;
|
||||
setSgg: (value: string) => void;
|
||||
setSggName: (name: string) => void;
|
||||
setYearFilter: (filter: { start: string; end: string }) => void;
|
||||
handleSearch: () => void;
|
||||
}
|
||||
|
||||
const SwagePrcsFclt: React.FC<SwagePrcsFcltProps> = ({
|
||||
start1,
|
||||
end1,
|
||||
city,
|
||||
sgg,
|
||||
yearFilter,
|
||||
setStart1,
|
||||
setEnd1,
|
||||
setCity,
|
||||
setCtpvName,
|
||||
setSgg,
|
||||
setSggName,
|
||||
setYearFilter,
|
||||
handleSearch,
|
||||
}) => {
|
||||
const SwagePrcsFclt: React.FC<SearchModalProps> = (props) => {
|
||||
const {
|
||||
start1, setStart1, end1, setEnd1,
|
||||
ctpvCd, setCtpvCd, setCtpvName,
|
||||
sggCd, setSggCd, setSggName,
|
||||
yearFilter, setYearFilter,
|
||||
} = useSearchModalStore();
|
||||
const { handleSearch } = useSearchModal(props);
|
||||
|
||||
return (
|
||||
<div className="mb-3">
|
||||
<div className="mb-2 flex items-center">
|
||||
<CtpvSggPrcsFcltSelectBox
|
||||
sido={city}
|
||||
sigungu={sgg}
|
||||
sido={ctpvCd}
|
||||
sigungu={sggCd}
|
||||
onSidoChange={(sidoId) => {
|
||||
setCity(sidoId);
|
||||
setSgg("0");
|
||||
setCtpvCd(sidoId);
|
||||
setSggCd("0");
|
||||
}}
|
||||
onSigunguChange={setSgg}
|
||||
onSigunguChange={setSggCd}
|
||||
setCtpvName={setCtpvName}
|
||||
setSggName={setSggName}
|
||||
/>
|
||||
|
||||
@@ -1,44 +1,31 @@
|
||||
// 하수처리구역
|
||||
|
||||
import React from 'react';
|
||||
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
|
||||
import { Button, Input, Label } from '@common/components';
|
||||
import React from 'react';
|
||||
import useSearchModalStore from '../../../store/useSearchModalStore';
|
||||
import { useSearchModal, type SearchModalProps } from './useSearchModal';
|
||||
|
||||
interface swagePrcsZoneProps {
|
||||
var1: string;
|
||||
var2: string;
|
||||
city: string;
|
||||
sgg: string;
|
||||
setVar1: (value: string) => void;
|
||||
setVar2: (value: string) => void;
|
||||
setCity: (value: string) => void;
|
||||
setSgg: (value: string) => void;
|
||||
handleSearch: () => void;
|
||||
}
|
||||
|
||||
const swagePrcsZone: React.FC<swagePrcsZoneProps> = ({
|
||||
var1,
|
||||
var2,
|
||||
city,
|
||||
sgg,
|
||||
setVar1,
|
||||
setVar2,
|
||||
setCity,
|
||||
setSgg,
|
||||
handleSearch,
|
||||
}) => {
|
||||
const swagePrcsZone: React.FC<SearchModalProps> = (props) => {
|
||||
const {
|
||||
var1, setVar1, var2, setVar2,
|
||||
ctpvCd, setCtpvCd,
|
||||
sggCd, setSggCd,
|
||||
} = useSearchModalStore();
|
||||
const { handleSearch } = useSearchModal(props);
|
||||
|
||||
return (
|
||||
<div className="mb-3">
|
||||
<div className="mb-2 flex items-center">
|
||||
<CtpvSggPrcsFcltSelectBox
|
||||
sido={city}
|
||||
sigungu={sgg}
|
||||
sido={ctpvCd}
|
||||
sigungu={sggCd}
|
||||
onSidoChange={(sidoId: string) => {
|
||||
setCity(sidoId);
|
||||
setSgg("0");
|
||||
setCtpvCd(sidoId);
|
||||
setSggCd("0");
|
||||
}}
|
||||
onSigunguChange={setSgg}
|
||||
onSigunguChange={setSggCd}
|
||||
/>
|
||||
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">하수처리시설명</Label>
|
||||
<Input
|
||||
|
||||
@@ -0,0 +1,939 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { downloadExcelWithKoreanHeaders } from '@common/business_components/ui';
|
||||
import axios from 'axios';
|
||||
import {
|
||||
MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_USE_CODES, MS_SWAGE_MHL_CODES, MS_SWAGE_MHL_USE_CODES,
|
||||
MsSwagePplExcelCol, SwtrmtFcltExcelCol, SwtrmtPrcsZoneExcelCol, MsSwageMhlExcelCol, ExclnSewagePumpExcelCol, stofcbrExcelCol
|
||||
} from '../components/common/table';
|
||||
import { getData } from "@/components/lib/api";
|
||||
import { BASIC_TYPES } from './basicTab';
|
||||
import { WORK_TYPES } from './operationTab';
|
||||
import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue';
|
||||
import useStore from '../../../store/useStore';
|
||||
import GisApp from "@common/business_components/ui/map/lib/gis.core";
|
||||
import { confirmToast } from '@/components/ui/toast'
|
||||
import { toast } from "react-hot-toast";
|
||||
import useSearchModalStore from '../../../store/useSearchModalStore';
|
||||
|
||||
const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}`;
|
||||
export const OPERATION_TABLE_SIZE = 5;
|
||||
|
||||
export interface SearchModalProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
onFeatureSelect: (row: any) => void;
|
||||
}
|
||||
|
||||
export function useSearchModal({ open, onOpenChange, onFeatureSelect }: SearchModalProps) {
|
||||
const {
|
||||
activeTab, basicType, workType,
|
||||
showTable,
|
||||
tableData, detailTableData,
|
||||
curPage, detailCurPage,
|
||||
detailBizId,
|
||||
ctpvCd, ctpvName, sggCd, sggName,
|
||||
start1, start2, end1, end2,
|
||||
var1, var2,
|
||||
yearFilter,
|
||||
todayYear, todayMonth, todayDate,
|
||||
setShowTable,
|
||||
setTableData, setDetailTableData,
|
||||
setTableCount, setDetailTableCount,
|
||||
setCurPage, setDetailCurPage,
|
||||
setIsLoading, setIsDetailLoading,
|
||||
setIsResetPage, setIsResetDetailPage,
|
||||
setIsResetSelection, setIsResetDetailSelection,
|
||||
setDetailBizId,
|
||||
resetFilters,
|
||||
getDateString
|
||||
} = useSearchModalStore();
|
||||
const { ctpv, sgg, BIZ_TY_CD } = useStore();
|
||||
|
||||
const TABS = [
|
||||
{ val: "basic", text: "기본정보" },
|
||||
{ val: "operation", text: "운영정보" },
|
||||
{ val: "report", text: "하수도정비기본계획보고서" },
|
||||
];
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
resetFilters();
|
||||
}, [activeTab, basicType, workType]);
|
||||
|
||||
// 페이지 변경 시마다 데이터 fetch
|
||||
useEffect(() => {
|
||||
setIsResetPage(false);
|
||||
setIsResetDetailPage(true);
|
||||
setDetailBizId(0);
|
||||
if (showTable) fetchFilteredData();
|
||||
}, [curPage]);
|
||||
|
||||
// 페이지 변경 시마다 데이터 fetch
|
||||
useEffect(() => {
|
||||
setIsResetDetailSelection(false);
|
||||
if (showTable) handleOperationPageNation(Number(detailBizId));
|
||||
}, [detailCurPage]);
|
||||
|
||||
|
||||
// 검색 API 호출 함수
|
||||
const fetchFilteredData = async () => {
|
||||
setIsLoading(true); // 로딩 시작
|
||||
setIsResetSelection(true); // 선택 초기화
|
||||
setIsResetDetailSelection(true); // 선택 초기화
|
||||
|
||||
try {
|
||||
let cqlFilters: string[] = [];
|
||||
if (activeTab === 'basic') {
|
||||
const queryParams = new URLSearchParams({
|
||||
lyrTypeNm: basicType,
|
||||
page: `${curPage - 1}`,
|
||||
size: '10',
|
||||
sort: 'string',
|
||||
});
|
||||
|
||||
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 '));
|
||||
|
||||
const res = await axios.get(`${API_URL}/v1/fclts?${queryParams.toString()}`);
|
||||
|
||||
// 🎯 각 아이템을 개별적으로 포맷팅하면서 일련번호 추가
|
||||
const dataWithRowNumber = (res.data.data || []).map((item: any, index: number) => {
|
||||
// 🎯 먼저 각 아이템을 포맷팅
|
||||
const formattedItem = formatDisplayData(item);
|
||||
|
||||
let ctpvCd = item?.ctpvNm ?? formattedItem?.ctpvNm ?? '';
|
||||
let sggCd = item?.sggNm ?? formattedItem?.sggNm ?? '';
|
||||
|
||||
if (!ctpvCd || !sggCd) {
|
||||
const code = String(item?.pbadmsEmdCd ?? formattedItem?.pbadmsEmdCd ?? '')?.trim();
|
||||
if (!ctpvCd && code) ctpvCd = code.slice(0, 2);
|
||||
if (!sggCd && code) sggCd = code.slice(0, 5);
|
||||
}
|
||||
|
||||
const matchedMhlCode = MS_SWAGE_MHL_CODES.find(code => code.val === item?.mqltCd?.trim());
|
||||
const matchedMhlUsgCode = MS_SWAGE_MHL_USE_CODES.find(code => code.val === item?.usgCd);
|
||||
const ctpvNm = ctpv.find(code => code.val.trim() === ctpvCd)?.text || ctpvCd;
|
||||
const sggNm = sgg.find(code => code.val.trim() === sggCd)?.text || '-';
|
||||
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim());
|
||||
|
||||
// 추가 처리 및 일련번호 추가
|
||||
return {
|
||||
...formattedItem,
|
||||
rowNumber: (curPage - 1) * 10 + index + 1, // 1부터 시작하는 일련번호 추가
|
||||
scsYn: item.scsYn === null || item.scsYn === undefined ? 'N' : item?.scsYn, // scsYn이 null이면 'N'으로 변경
|
||||
mqltCd: matchedMhlCode ? matchedMhlCode.text : item?.mqltCd,
|
||||
usgCd: matchedMhlUsgCode ? matchedMhlUsgCode.text : (usgCdObj ? usgCdObj.text : item?.usgCd),
|
||||
ctpvNm,
|
||||
sggNm,
|
||||
swtrmt_zone_nm: item.swtrmtZoneNm || item.swtrmt_zone_nm || '-',
|
||||
};
|
||||
});
|
||||
|
||||
setTableData(dataWithRowNumber);
|
||||
setTableCount(res.data.count || []);
|
||||
|
||||
} else if (activeTab === 'operation') {
|
||||
const RequestDTO: Record<string, string> = {
|
||||
page: `${curPage - 1}`,
|
||||
size: `${OPERATION_TABLE_SIZE}`,
|
||||
};
|
||||
if (var1) RequestDTO.bizInfoNm = var1;
|
||||
if (var2 != '0' && var2) RequestDTO.bizTypeCd = var2;
|
||||
// 수행기간 범위
|
||||
const startDate = getDateString(
|
||||
yearFilter.start,
|
||||
'',
|
||||
'',
|
||||
"19000101",
|
||||
);
|
||||
const endDate = getDateString(
|
||||
yearFilter.end,
|
||||
'',
|
||||
'',
|
||||
`${todayYear}${todayMonth}${todayDate}`,
|
||||
);
|
||||
RequestDTO.fromflfmtEndYmd = startDate;
|
||||
RequestDTO.toflfmtEndYmd = endDate;
|
||||
|
||||
// JSON.parse 사용으로 문자열 -> 배열 변환
|
||||
RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"'));
|
||||
|
||||
const params = new URLSearchParams(RequestDTO).toString();
|
||||
|
||||
const res = await getData(`v1/bizInfo?${params}`);
|
||||
|
||||
const mappedContent = (res.content || []).map((item: any, index: number) => {
|
||||
const formattedItem = formatDisplayData(item);
|
||||
const matched = BIZ_TY_CD.find(code => code.lwpoCd === item.bizTypeCd);
|
||||
return {
|
||||
...formattedItem,
|
||||
rowNumber: (curPage - 1) * OPERATION_TABLE_SIZE + index + 1, // 1부터 시작하는 일련번호 추가
|
||||
bizTypeCd: matched ? matched.lwpoCdNm : item.bizTypeCd,
|
||||
};
|
||||
});
|
||||
|
||||
setTableData(mappedContent || []);
|
||||
setTableCount(res.totalElements || 0);
|
||||
setDetailTableData([]);
|
||||
setDetailTableCount(0);
|
||||
}
|
||||
|
||||
setShowTable(true);
|
||||
setIsResetSelection(false);
|
||||
} catch (err) {
|
||||
console.error('API ERROR:', err);
|
||||
setTableData([]);
|
||||
setIsResetSelection(false);
|
||||
} finally {
|
||||
setIsLoading(false); // 로딩 종료
|
||||
setIsResetSelection(false);
|
||||
// setIsResetDetailSelection(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 하수관로용 CQL 필터 생성
|
||||
const pplCqlFilters = () => {
|
||||
const cqlFilters: string[] = [];
|
||||
// 추후 작성 예정
|
||||
if (var1) cqlFilters.push(`usg_cd='${var1}'`);
|
||||
if (var2) cqlFilters.push(`mqlt_cd='${var2}'`);
|
||||
if (ctpvCd !== '0' && sggCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${sggCd}%'`);
|
||||
else if (ctpvCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${ctpvCd?.trim()}%'`);
|
||||
// 설치년도 범위
|
||||
const startDate = getDateString(
|
||||
yearFilter.start,
|
||||
'',
|
||||
'',
|
||||
"19000101",
|
||||
);
|
||||
const endDate = getDateString(
|
||||
yearFilter.end,
|
||||
'',
|
||||
'',
|
||||
`${todayYear}${todayMonth}${todayDate}`,
|
||||
);
|
||||
cqlFilters.push(
|
||||
`instl_ymd >= '${startDate}' and instl_ymd <= '${endDate}'`,
|
||||
);
|
||||
// 관경(mm) 범위
|
||||
if (start1 && end1) cqlFilters.push(`pdmt_vl BETWEEN ${start1} AND ${end1}`);
|
||||
else if (start1) cqlFilters.push(`pdmt_vl >= ${start1}`);
|
||||
else if (end1) cqlFilters.push(`pdmt_vl <= ${end1}`);
|
||||
// 연장(m) 범위
|
||||
if (start2 && end2) cqlFilters.push(`prlg_vl BETWEEN ${start2} AND ${end2}`);
|
||||
else if (start2) cqlFilters.push(`prlg_vl >= ${start2}`);
|
||||
else if (end2) cqlFilters.push(`prlg_vl <= ${end2}`);
|
||||
|
||||
return cqlFilters;
|
||||
};
|
||||
// 하수처리시설용 CQL 필터 생성
|
||||
const facilityCqlFilters = () => {
|
||||
const cqlFilters: string[] = [];
|
||||
// 가동개시일자 범위
|
||||
const startDate = getDateString(
|
||||
yearFilter.start,
|
||||
'',
|
||||
'',
|
||||
"19000101",
|
||||
);
|
||||
const endDate = getDateString(
|
||||
yearFilter.end,
|
||||
'',
|
||||
'',
|
||||
`${todayYear}${todayMonth}${todayDate}`,
|
||||
);
|
||||
cqlFilters.push(
|
||||
`oprtng_strt_ymd >= '${startDate}' and oprtng_strt_ymd <= '${endDate}'`,
|
||||
);
|
||||
// 시설용량 범위
|
||||
if (start1 && end1)
|
||||
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 (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 필터 생성
|
||||
const zoneCqlFilters = () => {
|
||||
const cqlFilters: string[] = [];
|
||||
if (ctpvCd !== '' && ctpvCd !== '0') cqlFilters.push(`ctpv_cd='${ctpvCd?.trim()}'`);
|
||||
if (sggCd !== '' && sggCd !== '0') cqlFilters.push(`sgg_cd='${sggCd}'`);
|
||||
if (var1) cqlFilters.push(`swtrmt_zone_nm ILIKE '%${var1}%'`);
|
||||
if (var2) cqlFilters.push(`swtrmt_fclt_nm ILIKE '%${var2}%'`);
|
||||
return cqlFilters;
|
||||
};
|
||||
// 하수맨홀용 CQL 필터 생성
|
||||
const mhCqlFilters = () => {
|
||||
const cqlFilters: string[] = [];
|
||||
// 시도, 시군구
|
||||
if (ctpvCd !== '0' && sggCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${sggCd}%'`);
|
||||
else if (ctpvCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${ctpvCd?.trim()}%'`);
|
||||
// // 설치년도 범위
|
||||
const startDate = getDateString(
|
||||
yearFilter.start,
|
||||
'',
|
||||
'',
|
||||
"19000101",
|
||||
);
|
||||
const endDate = getDateString(
|
||||
yearFilter.end,
|
||||
'',
|
||||
'',
|
||||
`${todayYear}${todayMonth}${todayDate}`,
|
||||
);
|
||||
cqlFilters.push(
|
||||
`instl_ymd >= '${startDate}' and instl_ymd <= '${endDate}'`,
|
||||
);
|
||||
if (var1) cqlFilters.push(`usg_cd='${var1}'`);
|
||||
// 구경(mm) 범위
|
||||
if (start1 && end1) cqlFilters.push(`swage_mhL_diam_vl BETWEEN ${start1} AND ${end1}`);
|
||||
else if (start1) cqlFilters.push(`swage_mhL_diam_vl >= ${start1}`);
|
||||
else if (end1) cqlFilters.push(`swage_mhL_diam_vl <= ${end1}`);
|
||||
|
||||
return cqlFilters;
|
||||
};
|
||||
// 하수펌프장용 CQL 필터 생성
|
||||
const psmtnCqlFilters = () => {
|
||||
const cqlFilters: string[] = [];
|
||||
// 시도, 시군구
|
||||
if (ctpvCd !== '0' && sggCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${sggCd}%'`);
|
||||
else if (ctpvCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${ctpvCd?.trim()}%'`);
|
||||
// 설치년도 범위
|
||||
const startDate = getDateString(
|
||||
yearFilter.start,
|
||||
'',
|
||||
'',
|
||||
"19000101",
|
||||
);
|
||||
const endDate = getDateString(
|
||||
yearFilter.end,
|
||||
'',
|
||||
'',
|
||||
`${todayYear}${todayMonth}${todayDate}`,
|
||||
);
|
||||
cqlFilters.push(
|
||||
`instl_ymd >= '${startDate}' and instl_ymd <= '${endDate}'`,
|
||||
);
|
||||
// 일일처리용량 범위
|
||||
if (start1 && end1)
|
||||
cqlFilters.push(`daily_prcs_cpct BETWEEN ${start1} AND ${end1}`);
|
||||
else if (start1) cqlFilters.push(`daily_prcs_cpct >= ${start1}`);
|
||||
else if (end1) cqlFilters.push(`daily_prcs_cpct <= ${end1}`);
|
||||
// 양수능력 범위
|
||||
if (start2 && end2)
|
||||
cqlFilters.push(`excln_wpmp_ablt_vl BETWEEN ${start2} AND ${end2}`);
|
||||
else if (start2) cqlFilters.push(`excln_wpmp_ablt_vl >= ${start2}`);
|
||||
else if (end2) cqlFilters.push(`excln_wpmp_ablt_vl <= ${end2}`);
|
||||
|
||||
return cqlFilters;
|
||||
};
|
||||
// 우수토실용 CQL 필터 생성
|
||||
const otflCqlFilters = () => {
|
||||
const cqlFilters: string[] = [];
|
||||
// 시도, 시군구
|
||||
if (ctpvCd !== '0' && sggCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${sggCd}%'`);
|
||||
else if (ctpvCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${ctpvCd?.trim()}%'`);
|
||||
// 설치년도 범위
|
||||
const startDate = getDateString(
|
||||
yearFilter.start,
|
||||
'',
|
||||
'',
|
||||
"19000101",
|
||||
);
|
||||
const endDate = getDateString(
|
||||
yearFilter.end,
|
||||
'',
|
||||
'',
|
||||
`${todayYear}${todayMonth}${todayDate}`,
|
||||
);
|
||||
cqlFilters.push(
|
||||
`instl_ymd >= '${startDate}' and instl_ymd <= '${endDate}'`,
|
||||
);
|
||||
|
||||
return cqlFilters;
|
||||
};
|
||||
|
||||
// 조회 버튼 클릭 시 1페이지로 이동 및 데이터 초기화
|
||||
const handleSearch = () => {
|
||||
setCurPage(1); // 페이지를 1로 초기화
|
||||
fetchFilteredData();
|
||||
setIsResetPage(true); // 페이지를 초기화
|
||||
setIsResetDetailPage(true); // 디테일 페이지를 초기화
|
||||
setIsResetSelection(false); // 선택 초기화
|
||||
setIsResetDetailSelection(false); // 선택 초기화
|
||||
setShowTable(true);
|
||||
};
|
||||
|
||||
// 기본정보 테이블 cellClick 핸들러
|
||||
const handleBasicCellClick = async (index?: number | undefined, headId?: String) => {
|
||||
if (typeof index === "number") {
|
||||
setIsLoading(true);
|
||||
|
||||
const row = tableData[index];
|
||||
const layerNm = row.lyrTypeNm;
|
||||
const fid = row.fid;
|
||||
const core = GisApp.Module.layer as any;
|
||||
await core.showSearchResultsFromGeoJSON(layerNm, fid);
|
||||
setIsLoading(false);
|
||||
onOpenChange(false); // SearchModal 닫기
|
||||
}
|
||||
};
|
||||
// 운영정보 테이블 cellClick 핸들러
|
||||
const handleOperationCellClick = async (index?: number | undefined, headId?: String) => {
|
||||
setIsResetDetailPage(true); // 페이지를 1로 초기화
|
||||
setIsResetDetailSelection(true); // 선택 초기화
|
||||
setIsResetDetailPage(true); // 디테일 페이지를 초기화
|
||||
|
||||
if (typeof index === "number") {
|
||||
setIsDetailLoading(true);
|
||||
setDetailBizId(tableData[index].bizId);
|
||||
setDetailCurPage(1); // 상세 페이지 초기화
|
||||
try {
|
||||
const RequestDTO: Record<string, string> = {
|
||||
page: `${detailCurPage - 1}`,
|
||||
size: `${OPERATION_TABLE_SIZE}`,
|
||||
bizId: tableData[index % OPERATION_TABLE_SIZE].bizId,
|
||||
};
|
||||
|
||||
RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"'));
|
||||
|
||||
const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`);
|
||||
|
||||
const mappedData = (res.data || []).map((item: any, detailIndex: number) => {
|
||||
const formattedItem = formatDisplayData(item);
|
||||
|
||||
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim());
|
||||
const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item?.mqltCd?.trim());
|
||||
return {
|
||||
...formattedItem,
|
||||
rowNumber: (detailCurPage - 1) * OPERATION_TABLE_SIZE + detailIndex + 1,
|
||||
usgCd: usgCdObj ? usgCdObj.text : item.usgCd,
|
||||
mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd,
|
||||
swtrmt_zone_nm: item.swtrmt_zone_nm ? item.swtrmt_zone_nm : '-',
|
||||
};
|
||||
});
|
||||
|
||||
setDetailTableData(mappedData);
|
||||
setDetailTableCount(res.count || 0);
|
||||
} catch (error) {
|
||||
console.error('운영정보 cellClick 에러:', error);
|
||||
} finally {
|
||||
setIsDetailLoading(false);
|
||||
setIsResetDetailPage(false);
|
||||
setIsResetDetailSelection(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
// 운영정보 디테일 테이블 페이지네이션 핸들러
|
||||
const handleOperationPageNation = async (index?: number | undefined) => {
|
||||
if (typeof index === "number") {
|
||||
setIsDetailLoading(true);
|
||||
try {
|
||||
const RequestDTO: Record<string, string> = {
|
||||
page: `${detailCurPage - 1}`,
|
||||
size: `${OPERATION_TABLE_SIZE}`,
|
||||
bizId: String(detailBizId),
|
||||
};
|
||||
const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`);
|
||||
|
||||
const mappedData = (res.data || []).map((item: any, detailIndex: number) => {
|
||||
const formattedItem = formatDisplayData(item);
|
||||
|
||||
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim());
|
||||
const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item?.mqltCd?.trim());
|
||||
return {
|
||||
...formattedItem,
|
||||
rowNumber: (detailCurPage - 1) * OPERATION_TABLE_SIZE + detailIndex + 1,
|
||||
usgCd: usgCdObj ? usgCdObj.text : item.usgCd,
|
||||
mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd,
|
||||
swtrmt_zone_nm: item.swtrmt_zone_nm ? item.swtrmt_zone_nm : '-',
|
||||
};
|
||||
});
|
||||
|
||||
setDetailTableData(mappedData);
|
||||
setDetailTableCount(res.count || 0);
|
||||
} catch (error) {
|
||||
console.error('운영정보 페이지네이션 에러:', error);
|
||||
} finally {
|
||||
setIsDetailLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleOperationResultCellClick = async (index?: number | undefined, headId?: String) => {
|
||||
if (typeof index === "number") {
|
||||
setIsLoading(true);
|
||||
|
||||
const row = detailTableData[index];
|
||||
const layerNm = row.lyrTypeNm;
|
||||
const fid = row.fid;
|
||||
const core = GisApp.Module.layer as any;
|
||||
await core.showSearchResultsFromGeoJSON(layerNm, fid);
|
||||
setIsLoading(false);
|
||||
onOpenChange(false); // SearchModal 닫기
|
||||
}
|
||||
};
|
||||
|
||||
// 기본정보 Excel 다운로드 핸들러
|
||||
const basicExcelDownload = async () => {
|
||||
if (tableData.length === 0) {
|
||||
alert("다운로드 할 Excel 파일이 없습니다.\n조회 후 다시 시도해주세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
toast.dismiss("global-confirm-toast");
|
||||
|
||||
confirmToast(
|
||||
"파일 다운로드에는 2분 내외의 시간이 소요될 수 있습니다.\n파일 다운로드를 진행하시겠습니까?",
|
||||
onAnalysis ?? (() => { }),
|
||||
"text-xl font-medium text-gray-800"
|
||||
);
|
||||
|
||||
async function onAnalysis() {
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const queryParams = new URLSearchParams({
|
||||
lyrTypeNm: basicType,
|
||||
size: '10000',
|
||||
});
|
||||
|
||||
let cqlFilters: string[] = [];
|
||||
let headerMapping: { [key: string]: string } = {};
|
||||
let headerRange: string = "A1:F1";
|
||||
|
||||
switch (basicType) {
|
||||
case 'tb_ms_swage_ppl': {
|
||||
// 하수관로
|
||||
cqlFilters = pplCqlFilters()
|
||||
headerMapping = MsSwagePplExcelCol;
|
||||
headerRange = "A1:M1";
|
||||
break;
|
||||
}
|
||||
case 'tb_il_swage_prcs_fclt': {
|
||||
// 하수처리시설
|
||||
cqlFilters = facilityCqlFilters();
|
||||
headerMapping = SwtrmtFcltExcelCol;
|
||||
headerRange = "A1:J1";
|
||||
break;
|
||||
}
|
||||
case 'tb_ms_swage_prcs_zone': {
|
||||
// 하수처리구역
|
||||
cqlFilters = zoneCqlFilters();
|
||||
headerMapping = SwtrmtPrcsZoneExcelCol;
|
||||
headerRange = "A1:D1";
|
||||
break;
|
||||
}
|
||||
case 'tb_ms_swage_mhl': {
|
||||
// 하수맨홀
|
||||
cqlFilters = mhCqlFilters();
|
||||
headerMapping = MsSwageMhlExcelCol;
|
||||
headerRange = "A1:J1";
|
||||
break;
|
||||
}
|
||||
case 'tb_ms_swage_pmstn': {
|
||||
// 하수펌프장
|
||||
cqlFilters = psmtnCqlFilters();
|
||||
headerMapping = ExclnSewagePumpExcelCol;
|
||||
headerRange = "A1:J1";
|
||||
break;
|
||||
}
|
||||
case 'tb_ms_stofcbr': {
|
||||
// 우수토실
|
||||
cqlFilters = otflCqlFilters();
|
||||
headerMapping = stofcbrExcelCol;
|
||||
headerRange = "A1:H1";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cqlFilters.length > 0) queryParams.append('cqlFiter', cqlFilters.join(' and '));
|
||||
|
||||
const res = await axios.get(`${API_URL}/v1/fclts?${queryParams.toString()}`);
|
||||
|
||||
|
||||
|
||||
|
||||
// const mhlCdMap = new Map(MS_SWAGE_MHL_CODES.map(code => [code.val?.trim(), code.text]));
|
||||
const mhlUsgCdMap = new Map(MS_SWAGE_MHL_USE_CODES.map(code => [code.val?.trim(), code.text]));
|
||||
const pplUsgCdMap = new Map(MS_SWAGE_PPL_USE_CODES.map(code => [code.val?.trim(), code.text]));
|
||||
const ctpvMap = new Map(ctpv.map(code => [code.val?.trim(), code.text]));
|
||||
const sggMap = new Map(sgg.map(code => [code.val?.trim(), code.text]));
|
||||
|
||||
const mappedContent = (res.data.data || []).map((item: any) => {
|
||||
const formattedItem = formatDisplayData(item);
|
||||
|
||||
let ctpvCd = item?.ctpvCd ?? formattedItem?.ctpvCd ?? '';
|
||||
let sggCd = item?.sggCd ?? formattedItem?.sggCd ?? '';
|
||||
|
||||
if (!ctpvCd || !sggCd) {
|
||||
const code = String(item?.pbadmsEmdCd ?? formattedItem?.pbadmsEmdCd ?? '')?.trim();
|
||||
if (!ctpvCd && code) ctpvCd = code.slice(0, 2);
|
||||
if (!sggCd && code) sggCd = code.slice(0, 5);
|
||||
}
|
||||
|
||||
// trim 한 번만 수행
|
||||
const trimmedUsgCd = item?.usgCd?.trim();
|
||||
// const trimmedMqltCd = item?.mqltCd?.trim();
|
||||
|
||||
switch (basicType) {
|
||||
case 'tb_ms_swage_ppl': {
|
||||
// 하수관로
|
||||
return {
|
||||
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '-',
|
||||
instMngNo: formattedItem.instMngNo ?? item.instMngNo ?? '-',
|
||||
ctpvNm: ctpvMap.get(ctpvCd) ?? item.ctpvNm ?? '-',
|
||||
sggNm: sggMap.get(sggCd) ?? item.sggNm ?? '-',
|
||||
swtrmt_zone_nm: formattedItem.swtrmt_zone_nm ?? item.swtrmt_zone_nm ?? '-',
|
||||
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '-',
|
||||
usgCd: pplUsgCdMap.get(trimmedUsgCd) || item.usgCd || formattedItem.usgCd || '-',
|
||||
pdmtVl: formattedItem.pdmtVl ?? item.pdmtVl ?? '-',
|
||||
prlgVl: formattedItem.prlgVl ?? item.prlgVl ?? '-',
|
||||
tmptDpth: formattedItem.tmptDpth ?? item.tmptDpth ?? '-',
|
||||
tmptMhlMngNo: formattedItem.tmptMhlMngNo ?? item.tmptMhlMngNo ?? '-',
|
||||
scendDpth: formattedItem.scendDpth ?? item.scendDpth ?? '-',
|
||||
scendMhlMngNo: formattedItem.scendMhlMngNo ?? item.scendMhlMngNo ?? '-',
|
||||
};
|
||||
}
|
||||
case 'tb_il_swage_prcs_fclt': {
|
||||
// 하수처리시설
|
||||
return {
|
||||
swtrmtFcltNm: formattedItem.swtrmtFcltNm ?? item.swtrmtFcltNm ?? '-',
|
||||
fcltCpct: formattedItem.fcltCpct ?? item.fcltCpct ?? '-',
|
||||
rgnExpln: formattedItem.rgnExpln ?? item.rgnExpln ?? '-',
|
||||
oprtngStrtYmd: formattedItem.oprtngStrtYmd ?? item.oprtngStrtYmd ?? '-',
|
||||
laeNm: formattedItem.laeNm ?? item.laeNm ?? '-',
|
||||
sareaNm: formattedItem.sareaNm ?? item.sareaNm ?? '-',
|
||||
rvrNm: formattedItem.rvrNm ?? item.rvrNm ?? '-',
|
||||
dschgWtstNm: formattedItem.dschgWtstNm ?? item.dschgWtstNm ?? '-',
|
||||
swtrmtPpltnCnt: formattedItem.swtrmtPpltnCnt ?? item.swtrmtPpltnCnt ?? '-',
|
||||
rprsMsrcCn: formattedItem.rprsMsrcCn ?? item.rprsMsrcCn ?? '-'
|
||||
};
|
||||
}
|
||||
case 'tb_ms_swage_prcs_zone': {
|
||||
// 하수처리구역
|
||||
return {
|
||||
swtrmtZoneNm: formattedItem.swtrmtZoneNm ?? item.swtrmtZoneNm ?? '-',
|
||||
ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? '-',
|
||||
sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? '-',
|
||||
swtrmtFcltNm: formattedItem.swtrmtFcltNm ?? item.swtrmtFcltNm ?? '-'
|
||||
};
|
||||
}
|
||||
case 'tb_ms_swage_mhl': {
|
||||
// 하수맨홀
|
||||
return {
|
||||
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '-',
|
||||
ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? '-',
|
||||
sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? '-',
|
||||
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '-',
|
||||
usgCd: mhlUsgCdMap.get(trimmedUsgCd) || item.usgCd || formattedItem.usgCd || '-',
|
||||
swageMhlDiamVl: formattedItem.swageMhlDiamVl ?? item.swageMhlDiamVl ?? '-',
|
||||
wdthLen: formattedItem.wdthLen ?? item.wdthLen ?? '-',
|
||||
vrtcLen: formattedItem.vrtcLen ?? item.vrtcLen ?? '-',
|
||||
altdVl: formattedItem.altdVl ?? item.altdVl ?? '-',
|
||||
dpthlVl: formattedItem.dpthlVl ?? item.dpthlVl ?? '-'
|
||||
};
|
||||
}
|
||||
case 'tb_ms_swage_pmstn': {
|
||||
// 하수펌프장
|
||||
return {
|
||||
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '-',
|
||||
ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? '-',
|
||||
sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? '-',
|
||||
swagePmstnNm: formattedItem.swagePmstnNm ?? item.swagePmstnNm ?? '-',
|
||||
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '-',
|
||||
dailyPrcsCpct: formattedItem.dailyPrcsCpct ?? item.dailyPrcsCpct ?? '-',
|
||||
maxImpndCpct: formattedItem.maxImpndCpct ?? item.maxImpndCpct ?? '-',
|
||||
altdVl: formattedItem.altdVl ?? item.altdVl ?? '-',
|
||||
wtlvVl: formattedItem.wtlvVl ?? item.wtlvVl ?? '-',
|
||||
exclnWpmpAbltVl: formattedItem.exclnWpmpAbltVl ?? item.exclnWpmpAbltVl ?? '-'
|
||||
};
|
||||
}
|
||||
case 'tb_ms_stofcbr': {
|
||||
// 우수토실
|
||||
return {
|
||||
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '-',
|
||||
mapshtNo: formattedItem.mapshtNo ?? item.mapshtNo ?? '-',
|
||||
ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? '-',
|
||||
sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? '-',
|
||||
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '-',
|
||||
worflwWallHgt: formattedItem.worflwWallHgt ?? item.worflwWallHgt ?? '-',
|
||||
swageMhlMngNo: formattedItem.swageMhlMngNo ?? item.swageMhlMngNo ?? '-',
|
||||
drtnAngl: formattedItem.drtnAngl ?? item.drtnAngl ?? '-'
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 선택된 행 데이터를 Excel 다운로드 형식으로 변환
|
||||
const excelData = mappedContent; // 배열로 감싸서 전달
|
||||
|
||||
// 파일명 생성 (분석번호 기반)
|
||||
const label = BASIC_TYPES.find((type) => type.val === basicType)?.text
|
||||
const fileName = `${label} 조회 결과_${todayYear}${todayMonth}${todayDate}`;
|
||||
|
||||
await downloadExcelWithKoreanHeaders({
|
||||
data: excelData as JSON[],
|
||||
fileName: fileName,
|
||||
sheetNameArray: [fileName],
|
||||
headerRange: headerRange,
|
||||
headerMapping: headerMapping
|
||||
});
|
||||
setIsLoading(false);
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
console.error("Excel 다운로드 중 오류 발생:", error);
|
||||
alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 운영정보 Excel 다운로드 핸들러 추가
|
||||
const operationExcelDownload = async () => {
|
||||
if (tableData.length === 0) {
|
||||
alert("다운로드 할 Excel 파일이 없습니다.\n조회 후 다시 시도해주세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
toast.dismiss("global-confirm-toast");
|
||||
|
||||
confirmToast(
|
||||
"파일 다운로드에는 2분 내외의 시간이 소요될 수 있습니다.\n파일 다운로드를 진행하시겠습니까?",
|
||||
onAnalysis ?? (() => { }),
|
||||
"text-xl font-medium text-gray-800"
|
||||
);
|
||||
|
||||
async function onAnalysis() {
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const RequestDTO: Record<string, string> = {
|
||||
size: '10000',
|
||||
};
|
||||
if (var1) RequestDTO.bizInfoNm = var1;
|
||||
if (var2 != '0' && var2) RequestDTO.bizTypeCd = var2;
|
||||
// 수행기간 범위
|
||||
const startDate = getDateString(
|
||||
yearFilter.start,
|
||||
'',
|
||||
'',
|
||||
"19000101",
|
||||
);
|
||||
const endDate = getDateString(
|
||||
yearFilter.end,
|
||||
'',
|
||||
'',
|
||||
`${todayYear}${todayMonth}${todayDate}`,
|
||||
);
|
||||
RequestDTO.fromflfmtEndYmd = startDate;
|
||||
RequestDTO.toflfmtEndYmd = endDate;
|
||||
|
||||
// JSON.parse 사용으로 문자열 -> 배열 변환
|
||||
RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"'));
|
||||
|
||||
const params = new URLSearchParams(RequestDTO).toString();
|
||||
const res = await getData(`v1/bizInfo?${params}`);
|
||||
|
||||
// 헤더 매핑 정의
|
||||
const headerMapping: { [key: string]: string } = {
|
||||
'bizInfoNm': '사업명',
|
||||
'flfmtBgngYmd': '수행시작일자',
|
||||
'flfmtEndYmd': '수행종료일자',
|
||||
'flfmtYr': '수행년도',
|
||||
'bizTypeCd': '사업유형',
|
||||
'bizAmt': '사업금액(원)',
|
||||
};
|
||||
|
||||
const bizTyCdMap = new Map(BIZ_TY_CD.map(code => [code.lwpoCd, code.lwpoCdNm]));
|
||||
|
||||
const mappedContent = (res.content || []).map((item: any) => {
|
||||
const formattedItem = formatDisplayData(item);
|
||||
|
||||
return {
|
||||
bizInfoNm: formattedItem.bizInfoNm ?? item.bizInfoNm ?? '',
|
||||
flfmtBgngYmd: formattedItem.flfmtBgngYmd ?? item.flfmtBgngYmd ?? '',
|
||||
flfmtEndYmd: formattedItem.flfmtEndYmd ?? item.flfmtEndYmd ?? '',
|
||||
flfmtYr: formattedItem.flfmtYr ?? item.flfmtYr ?? '',
|
||||
bizTypeCd: bizTyCdMap.get(item.bizTypeCd) || item.bizTypeCd || formattedItem.bizTypeCd || '',
|
||||
bizAmt: ((v) => (v === 0 || v === '0') ? '0' : (v ?? ''))(formattedItem.bizAmt ?? item.bizAmt),
|
||||
};
|
||||
});
|
||||
|
||||
// 선택된 행 데이터를 Excel 다운로드 형식으로 변환
|
||||
const excelData = mappedContent; // 배열로 감싸서 전달
|
||||
|
||||
// 파일명 생성 (분석번호 기반)
|
||||
const label = WORK_TYPES.find((type) => type.val === workType)?.text
|
||||
const fileName = `${label} 사업 현황_${todayYear}${todayMonth}${todayDate}`;
|
||||
|
||||
await downloadExcelWithKoreanHeaders({
|
||||
data: excelData as JSON[],
|
||||
fileName: fileName,
|
||||
sheetNameArray: [fileName],
|
||||
headerRange: "A1:F1",
|
||||
headerMapping: headerMapping
|
||||
});
|
||||
setIsLoading(false);
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
console.error("Excel 다운로드 중 오류 발생:", error);
|
||||
alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 운영정보 Excel 다운로드 핸들러 추가
|
||||
const operationResultExcelDownload = async () => {
|
||||
if (detailTableData.length === 0) {
|
||||
alert("다운로드 할 Excel 파일이 없습니다.\n조회 후 다시 시도해주세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
toast.dismiss("global-confirm-toast");
|
||||
|
||||
confirmToast(
|
||||
"파일 다운로드에는 2분 내외의 시간이 소요될 수 있습니다.\n파일 다운로드를 진행하시겠습니까?",
|
||||
onAnalysis ?? (() => { }),
|
||||
"text-xl font-medium text-gray-800"
|
||||
);
|
||||
|
||||
async function onAnalysis() {
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const RequestDTO: Record<string, string> = {
|
||||
size: '10000',
|
||||
bizId: String(detailBizId),
|
||||
};
|
||||
|
||||
const apiStartTime = performance.now();
|
||||
const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`);
|
||||
const apiEndTime = performance.now();
|
||||
|
||||
const mappingStartTime = performance.now();
|
||||
// 헤더 매핑 정의
|
||||
const headerMapping: { [key: string]: string } = {
|
||||
'fcltMngNo': '관리번호',
|
||||
'swtrmt_zone_nm': '처리구역',
|
||||
'usgCd': '용도',
|
||||
'mqltCd': '재질',
|
||||
'pdmtVl': '관경(mm)',
|
||||
'prlgVl': '연장(m)',
|
||||
'instlYmd': '설치일자',
|
||||
'strc_stts_grd': '구조적 상태등급',
|
||||
'oper_stts_grd': '운영적 상태등급',
|
||||
};
|
||||
|
||||
const usgCdMap = new Map(MS_SWAGE_PPL_USE_CODES.map(code => [code.val, code.text]));
|
||||
const mqltCdMap = new Map(MS_SWAGE_PPL_CODES.map(code => [code.val, code.text]));
|
||||
|
||||
// 🎯 단일 반복문으로 최적화 - 각 아이템마다 필요한 필드만 직접 매핑
|
||||
const mappedData = (res.data || []).map((item: any) => {
|
||||
const formattedItem = formatDisplayData(item);
|
||||
|
||||
// trim 한 번만 수행
|
||||
const trimmedUsgCd = item?.usgCd?.trim();
|
||||
const trimmedMqltCd = item?.mqltCd?.trim();
|
||||
|
||||
// zone 값 한 번만 계산
|
||||
const zone = item.swtrmtZoneNm ?? formattedItem.swtrmt_zone_nm ?? item.swtrmt_zone_nm ?? '';
|
||||
|
||||
// 직접 매핑 - 반복문 없이 한 번에 객체 생성
|
||||
return {
|
||||
fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '',
|
||||
swtrmt_zone_nm: (zone === null || zone === '') ? '-' : zone,
|
||||
usgCd: usgCdMap.get(trimmedUsgCd) || item.usgCd || formattedItem.usgCd || '',
|
||||
mqltCd: mqltCdMap.get(trimmedMqltCd) || item.mqltCd || formattedItem.mqltCd || '',
|
||||
pdmtVl: formattedItem.pdmtVl ?? item.pdmtVl ?? '',
|
||||
prlgVl: formattedItem.prlgVl ?? item.prlgVl ?? '',
|
||||
instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '',
|
||||
strc_stts_grd: ((v) => (v === 0 || v === '0') ? '0' : (v ?? ''))(formattedItem.strc_stts_grd ?? item.strc_stts_grd),
|
||||
oper_stts_grd: ((v) => (v === 0 || v === '0') ? '0' : (v ?? ''))(formattedItem.oper_stts_grd ?? item.oper_stts_grd),
|
||||
};
|
||||
});
|
||||
|
||||
// 선택된 행 데이터를 Excel 다운로드 형식으로 변환
|
||||
const excelData = mappedData; // 배열로 감싸서 전달
|
||||
|
||||
// 파일명 생성 (분석번호 기반)
|
||||
const label = WORK_TYPES.find((type) => type.val === workType)?.text
|
||||
const fileName = `${label} 결과표_${todayYear}${todayMonth}${todayDate}`;
|
||||
|
||||
await downloadExcelWithKoreanHeaders({
|
||||
data: excelData as JSON[],
|
||||
fileName: fileName,
|
||||
sheetNameArray: [fileName],
|
||||
headerRange: "A1:I1",
|
||||
headerMapping: headerMapping
|
||||
});
|
||||
|
||||
setIsLoading(false);
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
console.error("Excel 다운로드 중 오류 발생:", error);
|
||||
alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 여러 시설 보기
|
||||
const viewMultipleFeature = async () => {
|
||||
if (activeTab === 'basic') {
|
||||
if (!(tableData.length === 0)) {
|
||||
setIsLoading(true);
|
||||
|
||||
const row = tableData[0];
|
||||
const layerNm = row.lyrTypeNm;
|
||||
const fids = tableData.map((item) => item.fid);
|
||||
const core = GisApp.Module.layer as any;
|
||||
await core.showMultipleSearchResultsFromGeoJSON(layerNm, fids);
|
||||
setIsLoading(false);
|
||||
onOpenChange(false);
|
||||
}
|
||||
} else if (activeTab === 'operation') {
|
||||
if (!(detailTableData.length === 0)) {
|
||||
setIsLoading(true);
|
||||
|
||||
const row = detailTableData[0];
|
||||
const layerNm = row.lyrTypeNm;
|
||||
const fids = detailTableData.map((item) => item.fid);
|
||||
const core = GisApp.Module.layer as any;
|
||||
await core.showMultipleSearchResultsFromGeoJSON(layerNm, fids);
|
||||
setIsLoading(false);
|
||||
onOpenChange(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
open, onOpenChange, onFeatureSelect,
|
||||
TABS,
|
||||
getDateString,
|
||||
handleSearch,
|
||||
handleBasicCellClick,
|
||||
handleOperationCellClick,
|
||||
handleOperationPageNation,
|
||||
handleOperationResultCellClick,
|
||||
basicExcelDownload,
|
||||
operationExcelDownload,
|
||||
operationResultExcelDownload,
|
||||
viewMultipleFeature,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,195 @@
|
||||
import { create } from "zustand";
|
||||
import { type SelectDataType } from "@common/business_components";
|
||||
|
||||
|
||||
// 날짜 조합 함수
|
||||
const getDateString = (
|
||||
year: string,
|
||||
month: string,
|
||||
day: string,
|
||||
defaultDate: string,
|
||||
) => {
|
||||
if (!year && !month && !day) return defaultDate;
|
||||
const y = year || defaultDate.slice(0, 4);
|
||||
const m = month || defaultDate.slice(4, 6);
|
||||
const d = day || defaultDate.slice(6, 8);
|
||||
return `${y}${m}${d}`;
|
||||
};
|
||||
|
||||
// 오늘 날짜 계산
|
||||
const today = new Date();
|
||||
const todayYear = today.getFullYear().toString();
|
||||
const todayMonth = (today.getMonth() + 1).toString().padStart(2, "0");
|
||||
const todayDate = today.getDate().toString().padStart(2, "0");
|
||||
|
||||
export interface SearchModalState {
|
||||
// 탭 관련
|
||||
activeTab: string;
|
||||
basicType: string;
|
||||
workType: string;
|
||||
// 최초 렌더 방지 플래그
|
||||
showTable: boolean;
|
||||
// 테이블 데이터
|
||||
tableData: any[];
|
||||
detailTableData: any[];
|
||||
tableCount: number;
|
||||
detailTableCount: number;
|
||||
// 페이지네이션
|
||||
curPage: number;
|
||||
detailCurPage: number;
|
||||
// 로딩 상태
|
||||
isLoading: boolean;
|
||||
isDetailLoading: boolean;
|
||||
// 리셋 플래그
|
||||
isResetPage: boolean;
|
||||
isResetDetailPage: boolean;
|
||||
isResetSelection: boolean;
|
||||
isResetDetailSelection: boolean;
|
||||
// 사업 ID
|
||||
detailBizId: number;
|
||||
// 지역 필터
|
||||
ctpvCd: string;
|
||||
ctpvName: string;
|
||||
sggCd: string;
|
||||
sggName: string;
|
||||
// 범위 필터
|
||||
start1: string;
|
||||
start2: string;
|
||||
end1: string;
|
||||
end2: string;
|
||||
// 변수 필터
|
||||
var1: string;
|
||||
var2: string;
|
||||
// 연도 필터
|
||||
yearFilter: { start: string; end: string };
|
||||
// 날짜 관련
|
||||
today: Date;
|
||||
todayYear: string;
|
||||
todayMonth: string;
|
||||
todayDate: string;
|
||||
getDateString: (year: string, month: string, day: string, defaultDate: string) => string;
|
||||
|
||||
// setters
|
||||
setActiveTab: (tab: string) => void;
|
||||
setBasicType: (type: string) => void;
|
||||
setWorkType: (type: string) => void;
|
||||
setShowTable: (show: boolean) => void;
|
||||
setTableData: (data: any[]) => void;
|
||||
setDetailTableData: (data: any[]) => void;
|
||||
setTableCount: (count: number) => void;
|
||||
setDetailTableCount: (count: number) => void;
|
||||
setCurPage: (page: number) => void;
|
||||
setDetailCurPage: (page: number) => void;
|
||||
setIsLoading: (loading: boolean) => void;
|
||||
setIsDetailLoading: (loading: boolean) => void;
|
||||
setIsResetPage: (reset: boolean) => void;
|
||||
setIsResetDetailPage: (reset: boolean) => void;
|
||||
setIsResetSelection: (reset: boolean) => void;
|
||||
setIsResetDetailSelection: (reset: boolean) => void;
|
||||
setDetailBizId: (id: number) => void;
|
||||
setCtpvCd: (cd: string) => void;
|
||||
setCtpvName: (name: string) => void;
|
||||
setSggCd: (cd: string) => void;
|
||||
setSggName: (name: string) => void;
|
||||
setStart1: (val: string) => void;
|
||||
setStart2: (val: string) => void;
|
||||
setEnd1: (val: string) => void;
|
||||
setEnd2: (val: string) => void;
|
||||
setVar1: (val: string) => void;
|
||||
setVar2: (val: string) => void;
|
||||
setYearFilter: (filter: { start: string; end: string }) => void;
|
||||
// 초기화 액션
|
||||
resetFilters: () => void;
|
||||
}
|
||||
|
||||
const useSearchModalStore = create<SearchModalState>((set) => ({
|
||||
activeTab: "basic",
|
||||
basicType: "tb_ms_swage_ppl",
|
||||
workType: "['200', '201', '204']",
|
||||
showTable: false,
|
||||
tableData: [],
|
||||
detailTableData: [],
|
||||
tableCount: 0,
|
||||
detailTableCount: 0,
|
||||
curPage: 1,
|
||||
detailCurPage: 1,
|
||||
isLoading: false,
|
||||
isDetailLoading: false,
|
||||
isResetPage: false,
|
||||
isResetDetailPage: false,
|
||||
isResetSelection: false,
|
||||
isResetDetailSelection: false,
|
||||
detailBizId: 0,
|
||||
ctpvCd: "0",
|
||||
ctpvName: "",
|
||||
sggCd: "0",
|
||||
sggName: "",
|
||||
start1: "",
|
||||
start2: "",
|
||||
end1: "",
|
||||
end2: "",
|
||||
var1: "",
|
||||
var2: "",
|
||||
yearFilter: { start: "", end: "" },
|
||||
today,
|
||||
todayYear,
|
||||
todayMonth,
|
||||
todayDate,
|
||||
getDateString,
|
||||
setActiveTab: (tab) => set({ activeTab: tab }),
|
||||
setBasicType: (type) => set({ basicType: type }),
|
||||
setWorkType: (type) => set({ workType: type }),
|
||||
setShowTable: (show) => set({ showTable: show }),
|
||||
setTableData: (data) => set({ tableData: data }),
|
||||
setDetailTableData: (data) => set({ detailTableData: data }),
|
||||
setTableCount: (count) => set({ tableCount: count }),
|
||||
setDetailTableCount: (count) => set({ detailTableCount: count }),
|
||||
setCurPage: (page) => set({ curPage: page }),
|
||||
setDetailCurPage: (page) => set({ detailCurPage: page }),
|
||||
setIsLoading: (loading) => set({ isLoading: loading }),
|
||||
setIsDetailLoading: (loading) => set({ isDetailLoading: loading }),
|
||||
setIsResetPage: (reset) => set({ isResetPage: reset }),
|
||||
setIsResetDetailPage: (reset) => set({ isResetDetailPage: reset }),
|
||||
setIsResetSelection: (reset) => set({ isResetSelection: reset }),
|
||||
setIsResetDetailSelection: (reset) => set({ isResetDetailSelection: reset }),
|
||||
setDetailBizId: (id) => set({ detailBizId: id }),
|
||||
setCtpvCd: (cd) => set({ ctpvCd: cd }),
|
||||
setCtpvName: (name) => set({ ctpvName: name }),
|
||||
setSggCd: (cd) => set({ sggCd: cd }),
|
||||
setSggName: (name) => set({ sggName: name }),
|
||||
setStart1: (val) => set({ start1: val }),
|
||||
setStart2: (val) => set({ start2: val }),
|
||||
setEnd1: (val) => set({ end1: val }),
|
||||
setEnd2: (val) => set({ end2: val }),
|
||||
setVar1: (val) => set({ var1: val }),
|
||||
setVar2: (val) => set({ var2: val }),
|
||||
setYearFilter: (filter) => set({ yearFilter: filter }),
|
||||
|
||||
// 초기화 액션
|
||||
resetFilters: () =>
|
||||
set({
|
||||
showTable: false,
|
||||
start1: "",
|
||||
start2: "",
|
||||
end1: "",
|
||||
end2: "",
|
||||
var1: "",
|
||||
var2: "",
|
||||
ctpvCd: "0",
|
||||
sggCd: "0",
|
||||
yearFilter: { start: "", end: "" },
|
||||
tableData: [],
|
||||
detailTableData: [],
|
||||
tableCount: 0,
|
||||
detailTableCount: 0,
|
||||
curPage: 1,
|
||||
detailCurPage: 1,
|
||||
isResetPage: true,
|
||||
isResetDetailPage: true,
|
||||
isResetSelection: true,
|
||||
isResetDetailSelection: true,
|
||||
detailBizId: 0,
|
||||
}),
|
||||
}));
|
||||
|
||||
export default useSearchModalStore;
|
||||
Reference in New Issue
Block a user