하수정비기본계획 목록조회
This commit is contained in:
@@ -10,11 +10,16 @@ import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
|
||||
import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox';
|
||||
import { MsSwagePplCol2, SwtrmtFcltCol2, SwtrmtPrcsZoneCol2, MsSwageMhlCol2, ExclnSewagePumpCol2, stofcbrCol2 } from './components/common/table';
|
||||
import LoadingOverlay from '@/components/ui/LoadingBar';
|
||||
import { GovSidoSigunguSearchForm } from '@/components/ui/govSidoSigunguSearchForm';
|
||||
import { getDcTree, buildTreeTopDown, sidoList } from './components/searchModalReportApi';
|
||||
//import { useDcTree, flattenFolders, useSggCd, useCityCd } from './components/searchModalReportApi';
|
||||
import { getDcTree,flattenFolders, useSggCd, useCityCd } from './components/searchModalReportApi';
|
||||
|
||||
const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}`;
|
||||
|
||||
type SelectDataType = {
|
||||
text: string;
|
||||
val: string;
|
||||
sido?: string; // 시도 코드 (선택 사항)
|
||||
}
|
||||
// 탭
|
||||
const TABS = [
|
||||
{ val: "basic", text: "기본정보" },
|
||||
@@ -56,9 +61,9 @@ const reportTableHeadlist = [
|
||||
{ id: "sido", title: "시도" },
|
||||
{ id: "sigungu", title: "시군구" },
|
||||
{ id: "approvalYear", title: "승인년도" },
|
||||
{ id: "treatmentPlantZone", title: "처리장,구역" },
|
||||
{ id: "reportCount", title: "보고서(00건)" },
|
||||
{ id: "planMapCount", title: "하수도대장 평면도(00건)" },
|
||||
{ id: "plantZoneGugun", title: "구분" },
|
||||
{ id: "reportGubun", title: "보고서구분" },
|
||||
{ id: "fileName", title: "파일명" },
|
||||
{ id: "regDate", title: "등록일자" },
|
||||
];
|
||||
|
||||
@@ -100,8 +105,8 @@ const SearchModal: React.FC<SearchModalProps> = ({
|
||||
const [tableCount, setTableCount] = useState<number>(0);
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
const [basicType, setBasicType] = useState(BASIC_TYPES[0]?.val ?? "");
|
||||
const [ctpvCd, setCtpvCd] = useState(0);
|
||||
const [sigungu, setSigungu] = useState(0);
|
||||
const [ctpvCd, setCtpvCd] = useState(0);
|
||||
const [sigungu, setSigungu] = useState(0);
|
||||
const [swageProcessingZone, set처리구역] = useState("");
|
||||
// 날짜 상태 선언
|
||||
const [시작1, set시작1] = useState("");
|
||||
@@ -131,6 +136,14 @@ const SearchModal: React.FC<SearchModalProps> = ({
|
||||
// 상세 정보 조회를 위한 상태 추가
|
||||
const [popupFeature, setPopupFeature] = useState<any>(null);
|
||||
|
||||
const sidos = useCityCd();
|
||||
const siguns = useSggCd();
|
||||
// const reportOriginData = getDcTree('경기도').then(data => {
|
||||
// console.log('reportOriginData:', data);
|
||||
// return data;
|
||||
// });
|
||||
//const reportData = flattenFolders(reportOriginData);
|
||||
|
||||
// 오늘 날짜 구하기
|
||||
const today = new Date();
|
||||
const todayYear = today.getFullYear().toString();
|
||||
@@ -148,6 +161,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
|
||||
else if (basicType === 'tb_ms_swage_pmstn') dynamicHeadlist = ExclnSewagePumpCol2; // 하수펌프장
|
||||
else if (basicType === 'tb_ms_stofcbr') dynamicHeadlist = stofcbrCol2; // 우수토실
|
||||
|
||||
|
||||
// 조회 버튼 클릭 시 1페이지로 이동하도록 수정
|
||||
const handleSearch = () => {
|
||||
setCurPage(1); // 페이지를 1로 초기화
|
||||
@@ -232,8 +246,8 @@ const SearchModal: React.FC<SearchModalProps> = ({
|
||||
|
||||
if (activeTab === 'report') {
|
||||
const reportOriginData = await getDcTree('경기도');
|
||||
const reportData = buildTreeTopDown(reportOriginData, '경기도');
|
||||
console.log('dcTree:', reportData);
|
||||
const reportData = flattenFolders(reportOriginData);
|
||||
console.log('report count:', reportData.length);
|
||||
setTableData(reportData || []);
|
||||
setTableCount(reportData.length || 0);
|
||||
} else {
|
||||
@@ -1023,15 +1037,9 @@ const SearchModal: React.FC<SearchModalProps> = ({
|
||||
<div className="relative flex flex-col border rounded-lg p-6 mb-4 w-full h-[23vh]">
|
||||
{/* 시도, 시군구, 하수처리구역 한 줄 */}
|
||||
<div className="mb-6 flex items-center">
|
||||
<SidoSigunguSelectBox
|
||||
sido={ctpvCd}
|
||||
sigungu={sigungu}
|
||||
onSidoChange={(sidoId) => {
|
||||
setCtpvCd(sidoId);
|
||||
setSigungu(0);
|
||||
}}
|
||||
onSigunguChange={setSigungu}
|
||||
/>
|
||||
<div className={`flex items-center justify-center mr-8`}>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<div className="flex items-center gap-4">
|
||||
|
||||
@@ -78,7 +78,6 @@ const InfilChart = ({ pplMngNo }: ModalOpenProp) => {
|
||||
|
||||
// API 호출
|
||||
try {
|
||||
const dcData = fn.getDcTree();
|
||||
const data = await fn.selectInftwtAnls(selectedValue);
|
||||
setInftwtAnlss(data ?? []);
|
||||
setInftwtAnlsInfos(fn.getOptionsInftwtAnlsInfo(data));
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
import {useState, useEffect} from 'react';
|
||||
import { getDcData } from '@/components/lib/api';
|
||||
import { json } from 'stream/consumers';
|
||||
|
||||
const ADDR_URL = process.env.NEXT_PUBLIC_ADDR_URL;
|
||||
type Node = {
|
||||
clsfSystmSn: string;
|
||||
upClsfSystmSn: string;
|
||||
clsfSystmNm: string;
|
||||
sortSeq: string;
|
||||
droppAble: boolean;
|
||||
}
|
||||
|
||||
type OutputNode = {
|
||||
sido: string;
|
||||
sigungu: string;
|
||||
approvalYear: string;
|
||||
level4: string;
|
||||
treatmentPlantZone: string;
|
||||
level6: string;
|
||||
level6_clsfSystmSn: string;
|
||||
no? : number;
|
||||
}
|
||||
type Folder = {
|
||||
clsfSystmSn: string;
|
||||
upClsfSystmSn: string;
|
||||
clsfSystmNm: string;
|
||||
children: Folder[];
|
||||
};
|
||||
|
||||
type FlattenedFolder = {
|
||||
[key: string]: string|number;
|
||||
};
|
||||
|
||||
type SelectDataType = {
|
||||
text: string;
|
||||
val: string;
|
||||
sigungu?: string; // 시도 코드 (선택 사항)
|
||||
sido?: string; // 시도 코드 (선택 사항)
|
||||
}
|
||||
|
||||
export const sidoList: { id: number, name: string }[] = [
|
||||
{ id: 0, name: '전체' },
|
||||
{ id: 26, name: '부산광역시' },
|
||||
{ id: 28, name: '인천광역시' },
|
||||
{ id: 30, name: '대전광역시' },
|
||||
{ id: 41, name: '경기도' },
|
||||
{ id: 42, name: '강원도' },
|
||||
{ id: 44, name: '충청남도' },
|
||||
{ id: 45, name: '전라북도' },
|
||||
{ id: 46, name: '전라남도' },
|
||||
{ id: 47, name: '경상북도' },
|
||||
{ id: 48, name: '경상남도' },
|
||||
];
|
||||
// 시군구 데이터
|
||||
const getSggCd = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const response = await fetch(`${ADDR_URL}/api/v1/addr/sgg`, { method: "GET", headers: { accept: "application/json" } });
|
||||
if (!response.ok) throw new Error(`시군구 데이터 오류: ${response.status}`);
|
||||
const res = await response.json();
|
||||
const sgg = res.data;
|
||||
const sggCd = sgg.map((item: any) => ({
|
||||
// 시군구 데이터
|
||||
export const getSggCd = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const response = await fetch(`${ADDR_URL}/api/v1/addr/sgg`, { method: "GET", headers: { accept: "application/json" } });
|
||||
if (!response.ok) throw new Error(`시군구 데이터 오류: ${response.status}`);
|
||||
const res = await response.json();
|
||||
const sgg = res.data;
|
||||
const sggCd = sgg.map((item: any) => ({
|
||||
val: item.adstDstrCd,
|
||||
sigungu: item.sigungu,
|
||||
sido: item.sido,
|
||||
text: item.gugun,
|
||||
}));
|
||||
sggCd.unshift({ val: '0', text: '전체' }); // "전체" 옵션 추가
|
||||
return sggCd;
|
||||
} catch (error) {
|
||||
console.error('시군구 데이터를 가져오는데 실패했습니다:', error);
|
||||
return [{ val: '0', text: '전체', sigungu: '0' }];
|
||||
}
|
||||
};
|
||||
}));
|
||||
sggCd.unshift({ val: '0', text: '전체' }); // "전체" 옵션 추가
|
||||
return sggCd;
|
||||
} catch (error) {
|
||||
console.error('시군구 데이터를 가져오는데 실패했습니다:', error);
|
||||
return [{ val: '0', text: '전체', sido: '0' }];
|
||||
}
|
||||
};
|
||||
|
||||
// 시도 데이터
|
||||
export const getCityCd = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const response = await fetch(`${ADDR_URL}/api/v1/addr/city`, { method: "GET", headers: { accept: "application/json" } });
|
||||
if (!response.ok) throw new Error(`시도 데이터 오류: ${response.status}`);
|
||||
const res = await response.json();
|
||||
const city = res.data;
|
||||
const cityCd = city.map((item: any) => ({
|
||||
val: item.adstDstrCd,
|
||||
text: item.sido,
|
||||
}));
|
||||
cityCd.unshift({ val: '0', text: '전체' });
|
||||
return cityCd;
|
||||
} catch (error) {
|
||||
console.error('시도 데이터를 가져오는데 실패했습니다:', error);
|
||||
return [{ val: '0', text: '전체', sido: '0' }];
|
||||
}
|
||||
};
|
||||
|
||||
export const useSggCd = () => {
|
||||
const [data, setData] = useState<SelectDataType[]>([]);
|
||||
@@ -75,69 +75,94 @@ export const useSggCd = () => {
|
||||
|
||||
return data;
|
||||
};
|
||||
export const useCityCd = () => {
|
||||
const [data, setData] = useState<SelectDataType[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetch = async () => {
|
||||
const result = await getSggCd();
|
||||
if (result) {
|
||||
setData(result);
|
||||
}
|
||||
};
|
||||
fetch();
|
||||
}, []);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
const isYear = (value: string): boolean => {
|
||||
return /^[0-9]{4}년$/.test(value);
|
||||
};
|
||||
|
||||
export function buildTreeTopDown(treeData: Node[], topNodeNm : string): OutputNode[] {
|
||||
const level6Names = ["보고서", "요약보고서", "부록", "기타"];
|
||||
const childrenMap = new Map<string, Node[]>();
|
||||
export function flattenFolders(data: Folder[]): FlattenedFolder[] {
|
||||
const result: FlattenedFolder[] = [];
|
||||
const exceptNodeNm = ["부분","통합","전체"];
|
||||
const addNodeNm = ["보고서","요약보고서","부록","기타"]; // level5
|
||||
const columnNms: { [key: number]: string } = { 0: "root", 1:"sido", 2:"sigungu", 3:"approvalYear"
|
||||
,4:"plantZoneGugun", 5:"reportGubun", 7:"fileName", 8:"regDate" };
|
||||
|
||||
// 1. 부모 → 자식 연결 테이블 구성
|
||||
treeData.forEach((node) => {
|
||||
if (!childrenMap.has(node.upClsfSystmSn)) {
|
||||
childrenMap.set(node.upClsfSystmSn, []);
|
||||
}
|
||||
childrenMap.get(node.upClsfSystmSn)!.push(node);
|
||||
});
|
||||
const result: OutputNode[] = [];
|
||||
|
||||
// 2. Top-down recursive 탐색 함수
|
||||
function traverse(path: string[], currentSn: string) {
|
||||
const children = childrenMap.get(currentSn) || [];
|
||||
|
||||
for (const child of children) {
|
||||
const newPath = [...path, child.clsfSystmNm];
|
||||
if (level6Names.includes(child.clsfSystmNm)) {
|
||||
const sido = newPath[0] || "";
|
||||
let [sigungu="", approvalYear="", level4="", treatmentPlantZone = ""] = newPath.slice(1, 5);
|
||||
if (isYear(sigungu)) {
|
||||
treatmentPlantZone = level4; level4 = approvalYear; approvalYear = sigungu; sigungu = "";
|
||||
}
|
||||
if (level6Names.includes(treatmentPlantZone)) treatmentPlantZone = "";
|
||||
result.push({
|
||||
sido,
|
||||
sigungu,
|
||||
approvalYear,
|
||||
level4,
|
||||
treatmentPlantZone,
|
||||
level6: child.clsfSystmNm,
|
||||
level6_clsfSystmSn: child.clsfSystmSn,
|
||||
});
|
||||
} else {
|
||||
traverse(newPath, child.clsfSystmSn);
|
||||
function traverse(
|
||||
node: Folder,
|
||||
path: { [key: string]: string| number },
|
||||
level: number
|
||||
) {
|
||||
if (level === 2 && isYear(node.clsfSystmNm)) {
|
||||
level++;
|
||||
}
|
||||
} // for
|
||||
if (level === 4 && addNodeNm.includes(node.clsfSystmNm)) {
|
||||
level++; // 레벨을 증가시켜 하위값에 추가되도록 함.
|
||||
}
|
||||
|
||||
const newPath = {
|
||||
...path,
|
||||
[`${columnNms[level]}`]: node.clsfSystmNm,
|
||||
};
|
||||
|
||||
if (node.children.length === 0) {
|
||||
newPath.no = result.length + 1;
|
||||
newPath.clsfSystmSn = node.clsfSystmSn; // 파일 조회를 위한 고유번호
|
||||
result.push(newPath);
|
||||
} else {
|
||||
if (level === 4) {
|
||||
if (exceptNodeNm.includes(node.clsfSystmNm)) {
|
||||
level--; // 제외할 노드 이름인 경우, 현재의 레벨에 하위값이 써지도록 함.
|
||||
}
|
||||
}
|
||||
node.children.forEach((child) => {
|
||||
traverse(child, newPath, level + 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
data.forEach((root) => traverse(root, {}, 0));
|
||||
console.log(result.slice(0, 10));
|
||||
return result;
|
||||
}
|
||||
|
||||
// 3. topNodeNm에서 시작
|
||||
const topNode = treeData.find((n) => n.clsfSystmNm === topNodeNm);
|
||||
if (topNode) {
|
||||
traverse([topNode.clsfSystmNm], topNode.clsfSystmSn);
|
||||
}
|
||||
const numberedResult = result.map((item, index) => ({
|
||||
...item,
|
||||
no: index + 1,
|
||||
}));
|
||||
|
||||
return numberedResult;
|
||||
}
|
||||
|
||||
export const getDcTree = async (clsfSystmNm:string) => {
|
||||
const queryString = 'clsfSystmNm='+clsfSystmNm;
|
||||
const result = await getDcData(`/api/v1/dc/clsf${queryString ? `?${queryString}` : ''}`);
|
||||
const cityName = encodeURIComponent(clsfSystmNm);
|
||||
const queryString = 'clsfSystmNm='+cityName;
|
||||
console.log("getDcTree queryString:", queryString);
|
||||
//const result = await getDcData(`/api/v1/dc/clsf${queryString ? `?${queryString}` : ''}`);
|
||||
const result = await getDcData("/api/v1/dc/clsf?clsfSystmNm=" + clsfSystmNm);
|
||||
return result;
|
||||
};
|
||||
export const useDcTree = (clsfSystmNm:string) => {
|
||||
const [data, setData] = useState<SelectDataType[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetch = async () => {
|
||||
const result = await getDcTree(clsfSystmNm);
|
||||
if (result) {
|
||||
setData(result);
|
||||
}
|
||||
};
|
||||
fetch();
|
||||
}, [clsfSystmNm]);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user