157 lines
4.8 KiB
TypeScript
157 lines
4.8 KiB
TypeScript
"use client";
|
||
|
||
import { useMemo, useState } from "react";
|
||
import {
|
||
formatFloodArea,
|
||
formatFloodDepth,
|
||
type FldngHstryItem,
|
||
} from "./fldngHstryTypes";
|
||
|
||
type Props = {
|
||
detail: FldngHstryItem;
|
||
onClose: () => void;
|
||
position: {
|
||
left: number;
|
||
top: number;
|
||
};
|
||
};
|
||
|
||
type DetailTab = "year" | "disaster" | "rainfall";
|
||
|
||
const renderRows = (rows: Array<[string, string]>) => (
|
||
<table className="w-full table-fixed border-collapse">
|
||
<colgroup>
|
||
<col className="w-[42%]" />
|
||
<col className="w-[58%]" />
|
||
</colgroup>
|
||
<tbody>
|
||
{rows.map(([label, value], index) => (
|
||
<tr key={`${label}-${index}`}>
|
||
<th className="border border-border bg-secondary px-3 py-[7px] text-left text-[1.02rem] font-semibold text-label">
|
||
{label}
|
||
</th>
|
||
<td className="border border-border bg-background px-3 py-[7px] text-[1.02rem] text-foreground">
|
||
{value}
|
||
</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
);
|
||
|
||
export default function FldngHstryDetailPanel({
|
||
detail,
|
||
onClose,
|
||
position,
|
||
}: Props) {
|
||
// 지도에서 침수흔적도 polygon을 클릭했을 때, 상세정보는 업무 의미 기준으로 3개 탭에 나눠 보여준다.
|
||
const [activeTab, setActiveTab] = useState<DetailTab>("year");
|
||
|
||
const yearRows = useMemo(
|
||
() =>
|
||
[
|
||
["침수심", `${detail.floodDepthM.toFixed(2)} m`],
|
||
["침수면적", formatFloodArea(detail.floodAreaHa)],
|
||
["침수년도", `${detail.floodYear}년`],
|
||
["등급", detail.gradeLabel],
|
||
["침수구역", detail.districtName],
|
||
] as Array<[string, string]>,
|
||
[detail],
|
||
);
|
||
|
||
const disasterRows = useMemo(
|
||
() =>
|
||
[
|
||
["침수재해명", detail.disasterName],
|
||
["침수면적", formatFloodArea(detail.floodAreaHa)],
|
||
["침수원인상세명", detail.causeDetailName],
|
||
["침수시작년월일", detail.startDate],
|
||
["침수종료년월일", detail.endDate],
|
||
["침수시작시간", detail.startTime],
|
||
] as Array<[string, string]>,
|
||
[detail],
|
||
);
|
||
|
||
const rainfallRows = useMemo(
|
||
() =>
|
||
[
|
||
["침수시작일자", detail.startDate],
|
||
["침수종료일자", detail.endDate],
|
||
["침수시작시간", detail.startTime],
|
||
["침수종료시간", detail.endTime],
|
||
["침수시간", detail.floodHour],
|
||
["강우시작시간", detail.rainStartTime],
|
||
["강우종료시간", detail.rainEndTime],
|
||
["총강우량(mm)", `${detail.totalRainfallMm.toFixed(0)}`],
|
||
["강우강도(mm/hr)", `${detail.rainfallIntensityMmHr.toFixed(0)}`],
|
||
["침수시간", detail.floodHour],
|
||
["침수원인상세코드", detail.causeDetailCode],
|
||
["피해금액", detail.damageAmount],
|
||
] as Array<[string, string]>,
|
||
[detail],
|
||
);
|
||
|
||
const currentRows =
|
||
activeTab === "year"
|
||
? yearRows
|
||
: activeTab === "disaster"
|
||
? disasterRows
|
||
: rainfallRows;
|
||
|
||
return (
|
||
<div
|
||
className="absolute z-[70] w-[248px] overflow-hidden rounded-[8px] border border-border bg-background shadow-blur"
|
||
style={{
|
||
left: `${position.left}px`,
|
||
top: `${position.top}px`,
|
||
}}
|
||
>
|
||
<div className="flex h-[28px] items-center justify-between border-b border-border bg-secondary px-[10px]">
|
||
<div className="text-[10px] font-bold tracking-[-0.01em] text-label">
|
||
상세정보
|
||
</div>
|
||
<button
|
||
type="button"
|
||
className="rounded-[4px] px-[4px] text-[13px] leading-none text-muted-foreground transition hover:bg-accent hover:text-accent-foreground"
|
||
onClick={onClose}
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
|
||
<div className="border-b border-border bg-secondary px-[6px] pt-[6px]">
|
||
<div className="flex gap-[4px]">
|
||
{[
|
||
["year", "년도탭"],
|
||
["disaster", "재해명탭"],
|
||
["rainfall", "침수발생강우탭"],
|
||
].map(([tabId, label]) => {
|
||
const isActive = activeTab === tabId;
|
||
|
||
return (
|
||
<button
|
||
key={tabId}
|
||
type="button"
|
||
className={`h-[24px] flex-1 rounded-t-[6px] border px-[6px] text-[9px] font-semibold leading-none transition ${
|
||
isActive
|
||
? "border-primary border-b-background bg-background text-primary"
|
||
: "border-border bg-secondary text-muted-foreground hover:bg-accent"
|
||
}`}
|
||
onClick={() => setActiveTab(tabId as DetailTab)}
|
||
>
|
||
{label}
|
||
</button>
|
||
);
|
||
})}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="bg-background p-[6px]">
|
||
<div className="overflow-hidden rounded-[6px] border border-border bg-background">
|
||
{renderRows(currentRows)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|