import { useState, useCallback, useEffect } from 'react'; import type { ScatSegment, ScatDetail } from './scatTypes'; import { fetchSections, fetchSectionDetail, fetchZones } from '../services/scatApi'; import type { ApiZoneItem } from '../services/scatApi'; import ScatLeftPanel from './ScatLeftPanel'; import ScatMap from './ScatMap'; import ScatTimeline from './ScatTimeline'; import ScatPopup from './ScatPopup'; import ScatRightPanel from './ScatRightPanel'; // ═══ Main PreScatView ═══ export function PreScatView() { const [segments, setSegments] = useState([]); const [zones, setZones] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [selectedSeg, setSelectedSeg] = useState(null); const [jurisdictionFilter, setJurisdictionFilter] = useState('전체 (제주도)'); const [areaFilter, setAreaFilter] = useState('전체'); const [phaseFilter, setPhaseFilter] = useState('Pre-SCAT (사전조사)'); const [statusFilter, setStatusFilter] = useState('전체'); const [searchTerm, setSearchTerm] = useState(''); const [popupData, setPopupData] = useState(null); const [panelDetail, setPanelDetail] = useState(null); const [panelLoading, setPanelLoading] = useState(false); const [timelineIdx, setTimelineIdx] = useState(6); // API에서 구역 및 구간 데이터 로딩 useEffect(() => { let cancelled = false; async function loadData() { try { setLoading(true); const [zonesData, sectionsData] = await Promise.all([fetchZones(), fetchSections()]); if (cancelled) return; setZones(zonesData); setSegments(sectionsData); if (sectionsData.length > 0) { setSelectedSeg(sectionsData[0]); } } catch (err) { console.error('[SCAT] 데이터 로딩 오류:', err); if (!cancelled) setError('데이터를 불러오지 못했습니다.'); } finally { if (!cancelled) setLoading(false); } } loadData(); return () => { cancelled = true; }; }, []); // 선택 구간 변경 시 우측 패널 상세 로딩 useEffect(() => { if (!selectedSeg) { setPanelDetail(null); return; } let cancelled = false; setPanelLoading(true); fetchSectionDetail(selectedSeg.id) .then(detail => { if (!cancelled) setPanelDetail(detail); }) .catch(err => console.error('[SCAT] 패널 상세 로딩 오류:', err)) .finally(() => { if (!cancelled) setPanelLoading(false); }); return () => { cancelled = true; }; }, [selectedSeg]); // 관할 기반 세그먼트 필터링 const filteredSegments = segments.filter((s) => { if (jurisdictionFilter === '서귀포해양경비안전서') return s.jurisdiction === '서귀포'; if (jurisdictionFilter === '제주해양경비안전서') return s.jurisdiction === '제주'; return true; // 전체 }); const handleOpenPopup = useCallback(async (sn: number) => { try { const detail = await fetchSectionDetail(sn); setPopupData(detail); } catch (err) { console.error('[SCAT] 상세 데이터 로딩 오류:', err); } }, []); const handleClosePopup = useCallback(() => { setPopupData(null); }, []); const handleTimelineSeek = useCallback( (idx: number) => { if (idx === -1) { // advance signal from play setTimelineIdx((prev) => { const next = (prev + 1) % Math.min(filteredSegments.length, 12); if (filteredSegments[next]) setSelectedSeg(filteredSegments[next]); return next; }); } else { setTimelineIdx(idx); if (filteredSegments[idx]) setSelectedSeg(filteredSegments[idx]); } }, [filteredSegments], ); if (error) { return (
{error}
); } if (loading || !selectedSeg) { return (
SCAT 데이터 로딩 중...
); } return (
{popupData && ( )}
); }