feat: 하수도정비기본계획 보고서 모달 형식으로 개발

This commit is contained in:
swcho
2025-08-04 18:44:48 +09:00
parent f6885be384
commit b494fdd1a6
3 changed files with 204 additions and 291 deletions
@@ -1,88 +1,62 @@
'use client'
import React, { useState,useEffect } from 'react'
import Modal from '@/components/ui/modal';
import React, { useState } from 'react'
import { VerticalTable } from '@/components/ui/verticalTable';
import { UiTable } from '@common/business_components/ui';
import { UiModal } from '@common/business_components/ui';
import { Button } from '@common/components/ui';
import { useDcTree, flattenFolders, getFileDownload, addFileName, type FlattenedFolder} from '../../searchModal/searchModalReportApi';
import ReportTab from '../../searchModal/reportTab';
// 하수처리시설
const headList = [
{ id: "title", title: "하수도정비 기본계획보고서" },
];
const modalHeadList = [
{ id: "no", title: "번호" },
{ id: "year", title: "승인연도" },
{ id: "cad", title: '평면도' },
{ id: "fileNm", title: "파일명" },
{ id: "date", title: "입력시간" },
]
const SwtrmtFclt = ({ gisObject }: { gisObject: any }) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const [modalTitle, setModalTitle] = useState<string>('');
const [dcDataOne, setDcDataOne] = useState<FlattenedFolder|undefined>({});
const openModal = (title: string) => {
setIsModalOpen(true);
setModalTitle(title)
};
const closeModal = () => {
setIsModalOpen(false);
};
const ctpvNm = gisObject?.ctpv_nm;
//const reportOriginData = useDcTree(ctpvNm);
const reportOriginData = useDcTree("강원특별자치도");
useEffect(() => {
const fetch = async () => {
if (!reportOriginData || reportOriginData.length === 0) {
return;
}
const reportData = flattenFolders(reportOriginData);
let filterReportData = [...reportData];
if (gisObject && gisObject.sgg_nm !== undefined && gisObject.sgg_nm !== "") { // 시군구검색
//const sggNm = gisObject?.sgg_nm;
const sggNm = "강릉시";
filterReportData = filterReportData.filter(item => item.sigungu === sggNm);
}
addFileName(filterReportData).then(data => {
filterReportData = data.filter(item => item.filePath !== undefined && item.filePath !== "");
if (filterReportData !== undefined && filterReportData.length > 0) {
setDcDataOne(filterReportData[0]);
}
});
console.log("filterReportData", filterReportData);
};
fetch();
}, [reportOriginData]);
// 하수도정비기본계획 filedownload 핸들러
const handleFileDownloadClick = () => {
if (dcDataOne && dcDataOne !== undefined && dcDataOne.fileSn !== undefined && dcDataOne.fileSn !== ""
&& dcDataOne.filePath !== undefined && dcDataOne.filePath !== "" && dcDataOne.fileName !== undefined && dcDataOne.fileName !== "" ) {
console.log("dcDataOne", dcDataOne);
getFileDownload(String(dcDataOne.fileSn), String(dcDataOne.fileName), String(dcDataOne.filePath));
}
};
//cad: <Button onClick={() => openModal('하수도대장 평면도')}>평면도</Button>,
const ctpvNm = gisObject?.ctpv_nm;
const sggNm = gisObject?.sgg_nm;
return (
<div>
<VerticalTable
children={{
title: <Button className="gray" onClick={() => handleFileDownloadClick()}>다운로드</Button>
}} headName='디지털 자료관 연계정보' tableData={[]} headlist={headList} pageSize={20} total={0} cellClick={undefined} isEditable={true} onPageChange={function (page: number): void {
throw new Error("Function not implemented.");
}}></VerticalTable>
{/* <Modal isModalOpen={isModalOpen} setIsModalOpen={setIsModalOpen} closeModal={closeModal}>
<div className='grid grid-col-2'>
<UiTable headName={modalTitle} tableData={[]} headlist={modalHeadList} pageSize={20} total={0} cellClick={undefined} onPageChange={function (page: number): void {
throw new Error("Function not implemented.");
}
}></UiTable>
</div>
</Modal> */}
</div>
<VerticalTable
children={{
title: <Button className="gray" onClick={() => setIsModalOpen(true)}>조회</Button>
}}
headName='디지털 자료관 연계정보'
tableData={[]}
headlist={headList}
pageSize={20}
total={0}
cellClick={undefined}
isEditable={true}
onPageChange={function (page: number): void {
throw new Error("Function not implemented.");
}}
/>
<UiModal
open={isModalOpen}
onOpenChange={setIsModalOpen}
headerTitle="하수도정비 기본계획보고서"
headerTitleClass="text-3xl font-semibold text-gray-700"
bodyClass={`
h-[100vh]
w-[60vw]
max-w-[60vw]
max-h-[100vh]
overflow-hidden
z-[101]
`}
body={
<ReportTab
open={isModalOpen}
isSearch={false}
ctpvNm={ctpvNm}
sggNm={sggNm}
/>
}
useDirectRender={true}
/>
</div >
)
}
@@ -4,9 +4,9 @@ import { Button, Label } from '@common/components';
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { SelectBox, UiTable } from '@common/business_components/ui';
import LoadingOverlay from '@/components/ui/LoadingBar';
import { addFileName, flattenFolders, getFileDownload, useCityCd, useDcTree, useSggCd, reportGubuns } from './searchModalReportApi';
import { type SelectDataType } from '../commonStore';
import { addFileName, flattenFolders, getFileDownload, getDcTree, useDcTree, reportGubuns } from './searchModalReportApi';
import useStore from '../../../store/useStore';
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
// 하수도정비 기본계획 보고서
@@ -15,18 +15,19 @@ export const reportTableHeadlist = [
{ id: "sido", title: "시도" },
{ id: "sigungu", title: "시군구" },
{ id: "approvalYear", title: "승인년도" },
{ id: "plantZoneGugun", title: "구분" },
{ id: "plantZoneGubun", title: "구분" },
{ id: "reportGubun", title: "보고서구분" },
{ id: "fileName", title: "파일명" },
{ id: "regDate", title: "등록일자" },
];
interface BasicTabProps {
interface ReportTabProps {
open?: boolean;
isSearch?: boolean;
ctpvNm?: string;
sggNm?: string;
}
const ReportTab: React.FC<BasicTabProps> = ({ open }) => {
const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sggNm }) => {
const [isLoading, setIsLoading] = useState(false);
const [isResetPage, setIsResetPage] = useState<boolean>(false);
@@ -36,24 +37,20 @@ const ReportTab: React.FC<BasicTabProps> = ({ open }) => {
const [tableCount, setTableCount] = useState(0);
const [curPage, setCurPage] = useState(1);
const [yearFilter, setYearFilter] = useState({ start: "", end: "" });
const [ctpvCd, setCtpvCd] = useState('0'); // 하수정비기본계획 report
const [sigungu, setSigungu] = useState('0'); // 하수정비기본계획 report
const [filteredSiguns, setFilteredSiguns] = useState<SelectDataType[]>([{ val: '0', text: '전체', sido: '0' }]);
const [gubun, setGubun] = useState(""); // 하수정비기본계획 report
const [reportGubun, setReportGubun] = useState("0"); // 하수정비기본계획 report
const [ctpvCd, setCtpvCd] = useState(0);
const [sggCd, setSggCd] = useState(0);
const [reportGubun, setReportGubun] = useState("0");
// const [gubun, setGubun] = useState("");
const { ctpv, sgg } = useStore();
// 하수정비기본계획 report
const sidos = useCityCd();
const siguns = useSggCd();
const reportOriginData = useDcTree(""); //:Folder[]
const dynamicHeadlist: { id: string, title: string }[] = reportTableHeadlist;
useEffect(() => {
// filterParams 초기화
setCtpvCd('0');
setSigungu('0');
setCtpvCd(0);
setSggCd(0);
setReportGubun('0');
setYearFilter({ start: "", end: "" });
setShowTable(false);
@@ -64,27 +61,39 @@ const ReportTab: React.FC<BasicTabProps> = ({ open }) => {
setIsResetSelection(true); // 선택 초기화
}, [open]);
useEffect(() => {
let newCtpvCd = ctpv.find((n) => n.name === ctpvNm)?.id || 0;
let newSggCd = sgg.find((n) => n.name === sggNm)?.id || 0;
setCtpvCd(newCtpvCd);
setSggCd(newSggCd);
}, [ctpvNm, sggNm]);
// ctpvCd, sggCd가 업데이트된 후에 fetchFilteredData 실행
useEffect(() => {
if (!isSearch && ctpvCd && sggCd) {
fetchFilteredData();
}
}, [reportOriginData, ctpvCd, sggCd, isSearch]);
// 페이지 변경 시마다 데이터 fetch
useEffect(() => {
// showTable이 true일 때만 fetch (최초 렌더 방지)
setIsResetPage(false);
setIsResetSelection(true); // 선택 초기화
if (showTable) fetchFilteredData();
}, [curPage]);
const handleCtpvCdChange = (val: string | number) => { // 하수도정비기본계획.시도
const sidoOption = sidos.find((n) => n.val === val);
setCtpvCd(String(val));
if (val !== '0') {
const filterSiguns = siguns.filter(item => item.sido === sidoOption?.text);
filterSiguns.unshift({ val: '0', text: '전체', sido: '0' });
setFilteredSiguns(filterSiguns);
}
setSigungu("0");
setGubun("");
setYearFilter({ start: "", end: "", });
}
setIsResetSelection(true);
if (showTable) fetchFilteredData();
setIsResetSelection(false);
}, [curPage]);
const handleCtpvCdChange = (sidoId: number) => {
setCtpvCd(sidoId);
setSggCd(0);
setReportGubun('0');
setYearFilter({ start: "", end: "", });
// setGubun("");
}
// 조회 버튼 클릭 시 1페이지로 이동 및 데이터 초기화
const handleSearch = () => {
@@ -96,7 +105,7 @@ const ReportTab: React.FC<BasicTabProps> = ({ open }) => {
};
// 하수도정비기본계획 테이블 cellClick 핸들러
const handleReportCellClick = (index: number | undefined ) => {
const handleReportCellClick = (index: number | undefined) => {
console.log(index);
if (typeof index === "number" && tableData[index]) {
const reportData = tableData[index];
@@ -107,23 +116,23 @@ const ReportTab: React.FC<BasicTabProps> = ({ open }) => {
}
}
};
// 검색 API 호출 함수
const fetchFilteredData = async () => {
setIsLoading(true); // 로딩 시작
setIsResetSelection(true); // 선택 초기화
try {
//const reportOriginData = await getDcTree('경기도');
const reportData = flattenFolders(reportOriginData);
let filterReportData = reportData;
if (ctpvCd !== "0") { // 시도검색
const sidoOption = sidos.find((n) => n.val === ctpvCd);
filterReportData = filterReportData.filter(item => item.sido === sidoOption?.text);
if (ctpvCd !== 0) { // 시도검색
const sidoOption = ctpv.find((n) => n.id === ctpvCd);
filterReportData = filterReportData.filter(item => item.sido === sidoOption?.name);
}
if (sigungu !== "0") { // 시군구검색
const sigunguOption = filteredSiguns.find((n) => n.val === sigungu);
filterReportData = filterReportData.filter(item => item.sigungu === sigunguOption?.text);
if (sggCd !== 0) { // 시군구검색
const sigunguOption = sgg.find((n) => n.id === sggCd);
filterReportData = filterReportData.filter(item => item.sigungu === sigunguOption?.name);
}
if (reportGubun !== "0") { // 보고서구분검색
const reportGubunOption = reportGubuns.find((n) => n.val === reportGubun);
@@ -139,14 +148,16 @@ const ReportTab: React.FC<BasicTabProps> = ({ open }) => {
return (item.approvalYear) ? item.approvalYear >= yearFilter.start + "년" && item.approvalYear <= yearFilter.end + "년" : null;
});
}
if (gubun !== "") { // 구분검색
filterReportData = filterReportData.filter(item => (item.plantZoneGugun) ? String(item.plantZoneGugun).includes(String(gubun)) : null);
}
// if (gubun !== "") { // 구분검색 (추후 사용할 수도 있을 것 같아 남겨둠)
// filterReportData = filterReportData.filter(item => (item.plantZoneGubun) ? String(item.plantZoneGubun).includes(String(gubun)) : null);
// }
console.log('report count:', filterReportData.length);
setTableCount(filterReportData.length || 0);
filterReportData = filterReportData.slice((curPage - 1) * 10, curPage * 10); // paging
filterReportData = filterReportData?.map((item, index) => ({ ...item, no: (curPage - 1) * 10 + index + 1 }));
//const fileList = await getDcFile("CLS20250530000041");
addFileName(filterReportData).then(data => {
filterReportData = data;
setTableData(filterReportData || []);
@@ -159,69 +170,70 @@ const ReportTab: React.FC<BasicTabProps> = ({ open }) => {
setTableData([]);
} finally {
setIsLoading(false); // 로딩 종료
setIsResetSelection(false);
}
};
return (
<>
<div className="relative flex flex-col border rounded-lg p-5 w-full h-[10vh]">
<div className="flex items-center mb-3">
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">시도</Label>
<SelectBox className="w-60 mr-8"
selectClass="rounded-lg bg-white"
label="" selectArray={sidos}
value={ctpvCd} onSelectValue={handleCtpvCdChange}
selectContentClass="z-[101]"
/>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">시군구</Label>
<SelectBox className="w-48"
selectClass="w-48 rounded-lg bg-white truncate"
label="" selectArray={filteredSiguns}
value={sigungu} onSelectValue={val => setSigungu(String(val))}
selectContentClass="z-[101]"
/>
</div>
<div className="flex items-center mb-6">
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">보고서 구분</Label>
<SelectBox className="w-44 mr-8"
selectClass="rounded-lg bg-white"
label="" selectArray={[...reportGubuns]}
value={reportGubun} onSelectValue={val => setReportGubun(String(val))}
selectContentClass="z-[101]" labelClass='whitespace-nowrap text-xl text-gray-600 pr-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 className={`relative flex flex-col border rounded-lg p-5 w-full ${isSearch ? "h-[10vh]" : "h-[6vh]"}`}>
{isSearch && (
<>
<div className="flex items-center mb-3">
<CtpvSggPrcsFcltSelectBox
sido={ctpvCd}
sigungu={sggCd}
onSidoChange={(sidoId: number) => { handleCtpvCdChange(sidoId) }}
onSigunguChange={setSggCd}
setIsLoading={setIsLoading}
/>
</div>
</>
)}
<div className="flex items-center mb-6">
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">보고서 구분</Label>
<SelectBox className="w-44 mr-8"
selectClass="rounded-lg bg-white"
label=""
selectArray={[...reportGubuns]}
value={reportGubun} onSelectValue={val => setReportGubun(String(val))}
selectContentClass="z-[101]" labelClass='whitespace-nowrap text-xl text-gray-600 pr-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>
</div>
</div>
</div>
<div className="h-[79vh] w-full overflow-hidden rounded-lg border">
{/* 테이블2 영역 (가로/세로 스크롤 가능) */}
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<UiTable
headName={(() => {
return (<>조회 결과 ({tableCount.toLocaleString('ko-KR')})건</>);
})()
}
tableData={tableData}
headlist={dynamicHeadlist}
pageSize={10}
total={tableCount}
cellClick={handleReportCellClick}
onPageChange={setCurPage}
resetPageNo={isResetPage}
resetSelection={isResetSelection}
/>
<div className="h-[79vh] w-full overflow-hidden rounded-lg border">
{/* 테이블2 영역 (가로/세로 스크롤 가능) */}
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<UiTable
headName={(() => {
return (<>조회 결과 ({tableCount.toLocaleString('ko-KR')})건</>);
})()
}
tableData={tableData}
headlist={reportTableHeadlist}
pageSize={10}
total={tableCount}
cellClick={handleReportCellClick}
onPageChange={setCurPage}
resetPageNo={isResetPage}
resetSelection={isResetSelection}
/>
</div>
</div>
</div>
</>
);
};
@@ -1,39 +1,35 @@
import {useState, useEffect} from 'react';
import { useState, useEffect } from 'react';
import { getDcData } from '@/components/lib/api';
const ADDR_URL = process.env.NEXT_PUBLIC_ADDR_URL;
export type Folder = {
clsfSystmSn: string;
upClsfSystmSn: string;
clsfSystmNm: string;
children: Folder[];
};
clsfSystmSn: string;
upClsfSystmSn: string;
clsfSystmNm: string;
children: Folder[];
};
export type FlattenedFolder = {
[key: string]: string|number|undefined;
};
type SelectDataType = {
text: string;
val: string;
sido?: string; // 시도 코드 (선택 사항)
[key: string]: string | number | undefined;
};
export type SelectDataType = {
text: string;
val: string;
sido?: string; // 시도 코드 (선택 사항)
}
type ReportDataFile = {
no : number;
fileTitle : string;
regDt : string;
fileSn : string;
filePath : string;
no: number;
fileTitle: string;
regDt: string;
fileSn: string;
filePath: string;
}
const isYear = (value: string): boolean => {
return /^[0-9]{4}년$/.test(value);
};
export const reportGubuns = [{ val: '0', text: '전체' }, { val: '1', text: '보고서' }
, { val: '2', text: '요약보고서' }, { val: '3', text: '부록' }, { val: '4', text: '기타' }];
export const reportGubuns = [{val: '0', text: '전체'}, {val: '1', text: '보고서'}
, {val: '2', text: '요약보고서'} , {val: '3', text: '부록'}, {val: '4', text: '기타'}];
/**
* Flatten a hierarchical folder structure into a flat array.
* @param data - The hierarchical folder data to flatten.
@@ -41,18 +37,20 @@ export const reportGubuns = [{val: '0', text: '전체'}, {val: '1', text: '보
*/
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" };
const exceptNodeNm = ["부분", "통합", "전체"];
const addNodeNm = ["보고서", "요약보고서", "부록", "기타"]; // level5
const columnNms: { [key: number]: string } = {
0: "root", 1: "sido", 2: "sigungu", 3: "approvalYear"
, 4: "plantZoneGubun", 5: "reportGubun", 7: "fileName", 8: "regDate"
};
function traverse(
node: Folder,
path: { [key: string]: string| number },
path: { [key: string]: string | number },
level: number
) {
if (level === 2 && isYear(node.clsfSystmNm)) {
level++;
level++;
}
if (level === 4 && addNodeNm.includes(node.clsfSystmNm)) {
level++; // 레벨을 증가시켜 하위값에 추가되도록 함.
@@ -79,7 +77,7 @@ export function flattenFolders(data: Folder[]): FlattenedFolder[] {
}
}
if (data && data.length > 0 && data[0].clsfSystmNm == "기본계획") { // data가 비어있지 않고 children이 있는 경우에만 처리
if (data && data.length > 0 && data[0]?.clsfSystmNm == "기본계획") { // data가 비어있지 않고 children이 있는 경우에만 처리
data.forEach((root) => traverse(root, {}, 0));
} else {
data.forEach((root) => traverse(root, {}, 1));
@@ -87,11 +85,11 @@ export function flattenFolders(data: Folder[]): FlattenedFolder[] {
return result;
}
export const getDcTree = async (clsfSystmNm:string) => {
export const getDcTree = async (clsfSystmNm: string) => {
const result = await getDcData("/api/v1/dc/clsf?clsfSystmNm=" + clsfSystmNm);
return result;
};
export const useDcTree = (clsfSystmNm:string) => {
export const useDcTree = (clsfSystmNm: string) => {
const [data, setData] = useState([]);
useEffect(() => {
@@ -109,31 +107,31 @@ export const useDcTree = (clsfSystmNm:string) => {
return data;
};
export const getDcFile = async (clsfSystmSn:string) => {
const queryString = 'clsfSystmSn='+clsfSystmSn;
export const getDcFile = async (clsfSystmSn: string) => {
const queryString = 'clsfSystmSn=' + clsfSystmSn;
const result = await getDcData(`/api/v1/dc/file${queryString ? `?${queryString}` : ''}`);
return result;
};
export const addFileName = async (data:FlattenedFolder[]) => {
export const addFileName = async (data: FlattenedFolder[]) => {
const fileReportData = await Promise.all(
data.map(async (item) => {
const filenameArr:ReportDataFile[] = await getDcFile(String(item.clsfSystmSn));
const filenameArr: ReportDataFile[] = await getDcFile(String(item.clsfSystmSn));
const f = filenameArr[0];
const result = {...item, fileName:f?.fileTitle, regDate:f?.regDt, fileSn:f?.fileSn, filePath:f?.filePath};
const result = { ...item, fileName: f?.fileTitle, regDate: f?.regDt, fileSn: f?.fileSn, filePath: f?.filePath };
return result;
})
);
return fileReportData;
};
export const getDcFileprcs = async (fileSn:string) => {
const queryString = 'fileSn='+fileSn;
export const getDcFileprcs = async (fileSn: string) => {
const queryString = 'fileSn=' + fileSn;
const result = await getDcData(`/api/v1/dc/fileprcs${queryString ? `?${queryString}` : ''}`);
return result;
};
export const getDcFileDownload = async (filePath:string) => {
const queryString = 'filePath='+ encodeURIComponent(filePath);
export const getDcFileDownload = async (filePath: string) => {
const queryString = 'filePath=' + encodeURIComponent(filePath);
const response = await fetch(`/dc-service/api/v1/dc/file/download?${queryString}`, {
method: 'GET',
});
@@ -143,7 +141,7 @@ export const getDcFileDownload = async (filePath:string) => {
const blob = await response.blob(); // PDF, image 등은 blob으로 받아야 함
return blob;
};
export const fileDownload = (data:Blob, fileName:string) => { // Blob데이터 임시link로 연결
export const fileDownload = (data: Blob, fileName: string) => { // Blob데이터 임시link로 연결
const url = window.URL.createObjectURL(data);
const link = document.createElement('a');
link.href = url;
@@ -153,80 +151,9 @@ export const fileDownload = (data:Blob, fileName:string) => { // Blob데이터
link.remove();
window.URL.revokeObjectURL(url);
}
export const getFileDownload = async (fileSn:string, fileName:string, filePath:string) => {
if (filePath === "") alert("filePath 정보 없으므로 다운로드 불가:filesn"+ fileSn);
export const getFileDownload = async (fileSn: string, fileName: string, filePath: string) => {
if (filePath === "") alert("filePath 정보 없으므로 다운로드 불가:filesn" + fileSn);
const blobData = await getDcFileDownload(filePath); // 실제 다운로드 API
fileDownload(blobData, fileName);
}
// 시도 데이터
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;
let citys:SelectDataType[] = city.map((item: {adstDstrCd:string, sido:string}) => ({
val: item.adstDstrCd,
text: item.sido,
}));
citys = citys.sort((a:SelectDataType, b:SelectDataType) => a.text.localeCompare(b.text));
citys.unshift({ val: '0', text: '전체' });
return citys;
} catch (error) {
console.error('시도 데이터를 가져오는데 실패했습니다:', error);
return [{ val: '0', text: '전체', sido: '0' }];
}
};
export const useSggCd = () => {
const [data, setData] = useState<SelectDataType[]>([]);
useEffect(() => {
const fetch = async () => {
const result = await getSggCd();
if (result) {
setData(result);
}
console.log("useSggCd호출");
};
fetch();
}, []);
return data;
};
// 시군구 데이터
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: {adstDstrCd:string, sido:string, gugun:string}) => ({
val: item.adstDstrCd,
sido: item.sido,
text: item.gugun,
}));
sggCd.unshift({ val: '0', text: '전체' }); // "전체" 옵션 추가
return sggCd;
} catch (error) {
console.error('시군구 데이터를 가져오는데 실패했습니다:', error);
return [{ val: '0', text: '전체', sido: '0' }];
}
};
export const useCityCd = () => {
const [data, setData] = useState<SelectDataType[]>([]);
useEffect(() => {
const fetch = async () => {
const result = await getCityCd();
if (result) {
setData(result);
}
console.log("useCityCd호출");
};
fetch();
}, []);
return data;
};