sn: 침수흔적깊이 정보 추가

This commit is contained in:
2026-08-28 16:08:47 +09:00
parent 36549e7281
commit be46bcbd17
3 changed files with 98 additions and 33 deletions
@@ -52,8 +52,7 @@ const resolveFldngHstryMapFeatureFid = (row: FldngHstryTableRow) => {
if (fid.startsWith(`${FLOOD_HISTORY_LAYER_TYPE}.`)) return fid;
if (fid) return `${FLOOD_HISTORY_LAYER_TYPE}.${fid}`;
const mapFid = String(row.fldngMapFid ?? "").trim();
return mapFid || "";
return "";
};
const buildDownloadRows = (rows: FldngHstryTableRow[]) =>
@@ -123,6 +122,7 @@ export default function FldngHstryPopupPage() {
const fldngYearOptions = useMemo(() => buildFldngHstryYearOptions(), []);
const sggOptions = useMemo(
() =>
filters.ctpvCd === "0"
@@ -295,7 +295,7 @@ export default function FldngHstryPopupPage() {
시도
</span>
<select
className="h-[3.2rem] w-[16rem] rounded-md border border-input bg-field px-3 text-[1.3rem]"
className="h-[3.2rem] w-[12rem] rounded-md border border-input bg-field px-3 text-[1.3rem]"
value={filters.ctpvCd}
onChange={(event) =>
setFilters((current) => ({
@@ -342,7 +342,7 @@ export default function FldngHstryPopupPage() {
침수발생년도
</span>
<select
className="h-[3.2rem] w-[14rem] rounded-md border border-input bg-field px-3 text-[1.3rem]"
className="h-[3.2rem] w-[8rem] rounded-md border border-input bg-field px-3 text-[1.3rem]"
value={filters.floodYear}
onChange={(event) =>
setFilters((current) => ({
@@ -360,6 +360,24 @@ export default function FldngHstryPopupPage() {
</select>
</label>
<label className="flex items-center gap-2">
<span className="whitespace-nowrap text-[1.3rem] text-label">강우시작일</span>
<Input
className="w-[11rem]"
type="date"
value={filters.rainStartDate}
min={filters.floodYear ? `${filters.floodYear}-01-01` : undefined}
max={filters.floodYear ? `${filters.floodYear}-12-31` : undefined}
disabled={!filters.floodYear}
onChange={(event) => setFilters((current) => ({ ...current, rainStartDate: event.target.value }))}
/>
</label>
<label className="flex items-center gap-2">
<span className="whitespace-nowrap text-[1.3rem] text-label">침수지구명</span>
<Input type="text" value={filters.districtName} onChange={(event) => setFilters((current) => ({ ...current, districtName: event.target.value }))} onKeyDown={(event) => { if (event.key === "Enter") void handleSearch(1); }} />
</label>
<label className="flex items-center gap-2">
<span className="whitespace-nowrap text-[1.3rem] text-label">
침수재해명
@@ -17,6 +17,8 @@ export type FldngHstryFilters = {
sggCd: string;
floodYear: string;
disasterName: string;
rainStartDate: string;
districtName: string;
};
export type FldngHstryDepthZone = {
@@ -108,6 +110,8 @@ export const FLDNG_HSTRY_DEFAULT_FILTERS: FldngHstryFilters = {
sggCd: "0",
floodYear: "",
disasterName: "",
rainStartDate: "",
districtName: "",
};
export const FLDNG_HSTRY_DEPTH_LEGEND_ITEMS = [
@@ -350,6 +354,8 @@ export const normalizeFldngHstryFilters = (
.replace(/[^0-9]/g, "")
.slice(0, 4),
disasterName: String(filters.disasterName ?? "").trim(),
rainStartDate: String(filters.rainStartDate ?? "").trim(),
districtName: String(filters.districtName ?? "").trim(),
});
export const buildFldngHstryYearOptions = () => {
@@ -375,6 +381,8 @@ export const buildFldngHstryListQueryString = (
if (normalized.floodYear) params.set("fldngYr", normalized.floodYear);
if (normalized.disasterName)
params.set("fldngDstrNm", normalized.disasterName);
if (normalized.rainStartDate) params.set("rainBgngTm", normalized.rainStartDate);
if (normalized.districtName) params.set("fldngDstrctNm", normalized.districtName);
return params.toString();
};
@@ -64,6 +64,7 @@ import {
isInvalidInstallYmd,
} from "../agedPipe/agedPipeUtils";
import { openWindowPopup } from "@/features/windowPopup/lib/openWindowPopup";
import { WINDOW_POPUP_MESSAGE_TYPE } from "@/features/windowPopup/model/types";
import { useAlertStore } from "@/shared/lib";
import { useConfirm } from "@frontend-opensource/use-react-hooks";
import useStore from "@/store/useStore";
@@ -777,6 +778,9 @@ const FeatureClickEventPopup = ({
}
if (selectedLayerName === "침수흔적수위" && featureId) {
const depthLookupKey = normalizeFldngWtlvMapApiFid(featureId);
setFloodDepthRows([]);
setSelectedFloodDepthYear(null);
try {
const normalizedFloodMapFid =
normalizeFldngWtlvMapApiFid(featureId);
@@ -794,27 +798,27 @@ const FeatureClickEventPopup = ({
setFetchData(mergedData);
setTableData(mergedData);
}
const depthDataSn = Number(
data?.data_sn ?? data?.dataSn ?? formattedData?.data_sn ?? formattedData?.dataSn,
);
if (Number.isFinite(depthDataSn)) {
} catch (rainError) {
console.warn("침수강우분석 조회 실패:", rainError);
}
try {
if (depthLookupKey) {
const depthRows = await getData(
`v1/fldng/hstry/depth-map/${encodeURIComponent(String(depthDataSn))}`,
`v1/fldng/hstry/depth-map/${encodeURIComponent(depthLookupKey)}`,
);
const normalizedDepthRows = Array.isArray(depthRows)
? depthRows.filter((row) => row && typeof row === "object")
const depthPayload = depthRows?.data ?? depthRows;
const normalizedDepthRows = Array.isArray(depthPayload)
? depthPayload.filter((row) => row && typeof row === "object")
: [];
setFloodDepthRows(normalizedDepthRows);
const years = normalizedDepthRows
.map((row) => String(row.fldng_yr ?? row.fldngYr ?? row.yr ?? "").trim())
.filter(Boolean);
setSelectedFloodDepthYear(years[0] ?? null);
} else {
setFloodDepthRows([]);
// 최초에는 연도를 선택하지 않고 목록만 표시한다.
setSelectedFloodDepthYear(null);
}
} catch (rainError) {
console.warn("침수강우분석 조회 실패:", rainError);
} catch (depthError) {
console.warn("침수깊이지도 조회 실패:", depthError);
}
}
} catch (error) {
@@ -1066,7 +1070,27 @@ const FeatureClickEventPopup = ({
<button
key={year}
type="button"
onClick={() => setSelectedFloodDepthYear(year)}
onClick={() => {
setSelectedFloodDepthYear(year);
const selectedDepthRow = floodDepthRows.find(
(row) => String(row.fldng_yr ?? row.fldngYr ?? row.yr ?? "").trim() === year,
);
const depthFid = String(
selectedDepthRow?.fldng_dpth_map_sn ?? selectedDepthRow?.fid ?? "",
).trim();
if (depthFid) {
window.opener?.postMessage(
{
type: WINDOW_POPUP_MESSAGE_TYPE.MAP_SEARCH_SELECT_FEATURE,
payload: {
layerNm: "tb_ms_fldng_dpth_map",
fid: `tb_ms_fldng_dpth_map.${depthFid.replace(/^tb_ms_fldng_dpth_map\./, "")}`,
},
},
window.location.origin,
);
}
}}
className={`rounded-full border px-3 py-1 text-sm ${selectedFloodDepthYear === year ? "border-blue-600 bg-blue-600 text-white" : "border-blue-400 bg-transparent text-blue-600"}`}
>
{year}
@@ -1075,22 +1099,37 @@ const FeatureClickEventPopup = ({
</div>
<button type="button" aria-label="다음 연도" className="shrink-0 px-1 text-blue-600" onClick={() => floodDepthYearListRef.current?.scrollBy({ left: 120, behavior: "smooth" })}>›</button>
</div>
<div className="max-h-64 overflow-auto">
<table className="w-full border-collapse text-sm">
<tbody>
{Object.entries(
floodDepthRows.find((row) => String(row.fldng_yr ?? row.fldngYr ?? row.yr ?? "").trim() === selectedFloodDepthYear) ?? {},
)
.filter(([key]) => !key.toLowerCase().includes("geom"))
.map(([key, value]) => (
<tr key={key}>
<th className="border border-border bg-secondary px-2 py-1 text-left">{key}</th>
<td className="border border-border px-2 py-1">{String(value ?? "-")}</td>
</tr>
))}
</tbody>
</table>
</div>
{selectedFloodDepthYear && (
<>
<div className="mb-2 flex items-center justify-between border-b border-border pb-2">
<span className="text-sm font-semibold text-label">침수흔적깊이 정보</span>
<button
type="button"
aria-label="침수흔적깊이 정보 닫기"
className="rounded px-2 text-lg leading-none text-muted-foreground hover:bg-accent"
onClick={() => setSelectedFloodDepthYear(null)}
>
×
</button>
</div>
<div className="max-h-64 overflow-auto">
<table className="w-full border-collapse text-sm">
<tbody>
{Object.entries(
floodDepthRows.find((row) => String(row.fldng_yr ?? row.fldngYr ?? row.yr ?? "").trim() === selectedFloodDepthYear) ?? {},
)
.filter(([key]) => !key.toLowerCase().includes("geom"))
.map(([key, value]) => (
<tr key={key}>
<th className="border border-border bg-secondary px-2 py-1 text-left">{key}</th>
<td className="border border-border px-2 py-1">{String(value ?? "-")}</td>
</tr>
))}
</tbody>
</table>
</div>
</>
)}
</div>
)}
{ContentComponent && (