- subcable entity 생성 (타입 정의 + 데이터 로딩 hook) - MapLibre 레이어: 케이블 라인 + 호버 하이라이트 + 라벨 - 지도 표시 설정에 해저케이블 토글 추가 - 클릭 시 우측 정보 패널 (길이, 개통, 운영사, landing points) - Map3D + DashboardPage 통합 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
53 lines
1.5 KiB
TypeScript
53 lines
1.5 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import type { SubcableGeoJson, SubcableDetailsIndex, SubcableDetail } from '../model/types';
|
|
|
|
interface SubcableData {
|
|
geo: SubcableGeoJson;
|
|
details: Map<string, SubcableDetail>;
|
|
}
|
|
|
|
export function useSubcables(
|
|
geoUrl = '/data/subcables/cable-geo.json',
|
|
detailsUrl = '/data/subcables/cable-details.min.json',
|
|
) {
|
|
const [data, setData] = useState<SubcableData | null>(null);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
|
|
async function run() {
|
|
try {
|
|
setError(null);
|
|
const [geoRes, detailsRes] = await Promise.all([
|
|
fetch(geoUrl),
|
|
fetch(detailsUrl),
|
|
]);
|
|
if (!geoRes.ok) throw new Error(`Failed to load subcable geo: ${geoRes.status}`);
|
|
if (!detailsRes.ok) throw new Error(`Failed to load subcable details: ${detailsRes.status}`);
|
|
|
|
const geo = (await geoRes.json()) as SubcableGeoJson;
|
|
const detailsJson = (await detailsRes.json()) as SubcableDetailsIndex;
|
|
if (cancelled) return;
|
|
|
|
const details = new Map<string, SubcableDetail>();
|
|
for (const [id, detail] of Object.entries(detailsJson.by_id)) {
|
|
details.set(id, detail);
|
|
}
|
|
|
|
setData({ geo, details });
|
|
} catch (e) {
|
|
if (cancelled) return;
|
|
setError(e instanceof Error ? e.message : String(e));
|
|
}
|
|
}
|
|
|
|
void run();
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [geoUrl, detailsUrl]);
|
|
|
|
return { data, error };
|
|
}
|