import api from '@common/services/api'; // ============================================================ // 백엔드 API 응답 타입 // ============================================================ export interface IncidentListItem { acdntSn: number; acdntCd: string; acdntNm: string; acdntTpCd: string; acdntSttsCd: string; lat: number; lng: number; locDc: string; occrnDtm: string; regionNm: string; officeNm: string; svrtCd: string | null; vesselTp: string | null; phaseCd: string; analystNm: string | null; oilTpCd: string | null; spilQty: number | null; spilUnitCd: string | null; fcstHr: number | null; mediaCnt: number; } export interface PredExecItem { predExecSn: number; algoCd: string; execSttsCd: string; bgngDtm: string | null; cmplDtm: string | null; reqdSec: number | null; } export interface WeatherInfo { locNm: string; obsDtm: string; icon: string; temp: string; weatherDc: string; wind: string; wave: string; humid: string; vis: string; sst: string; tide: string; highTide: string; lowTide: string; forecast: Array<{ hour: string; icon: string; temp: string }>; impactDc: string; } export interface MediaInfo { photoCnt: number; videoCnt: number; satCnt: number; cctvCnt: number; photoMeta: Record | null; droneMeta: Record | null; satMeta: Record | null; cctvMeta: Record | null; } export interface IncidentDetail extends IncidentListItem { predictions: PredExecItem[]; weather: WeatherInfo | null; media: MediaInfo | null; } // ============================================================ // 프론트 호환 타입 // ============================================================ export interface IncidentCompat { id: string; name: string; status: 'active' | 'investigating' | 'closed'; date: string; time: string; region: string; office: string; location: { lat: number; lon: number }; causeType?: string; oilType?: string; prediction?: string; vesselName?: string; mediaCount?: number; } function toCompat(item: IncidentListItem): IncidentCompat { const dt = new Date(item.occrnDtm); const statusMap: Record = { ACTIVE: 'active', INVESTIGATING: 'investigating', CLOSED: 'closed', }; return { id: String(item.acdntSn), name: item.acdntNm, status: statusMap[item.acdntSttsCd] ?? 'active', date: dt.toISOString().slice(0, 10), time: dt.toTimeString().slice(0, 5), region: item.regionNm, office: item.officeNm, location: { lat: item.lat, lon: item.lng }, causeType: item.acdntTpCd, oilType: item.oilTpCd ?? undefined, prediction: item.fcstHr ? '예측완료' : undefined, mediaCount: item.mediaCnt, }; } // ============================================================ // API 호출 함수 // ============================================================ export async function fetchIncidentsRaw(): Promise { const { data } = await api.get('/incidents'); return data; } export async function fetchIncidents(filters?: { status?: string; region?: string; search?: string; startDate?: string; endDate?: string; }): Promise { const params = new URLSearchParams(); if (filters?.status) params.set('status', filters.status); if (filters?.region) params.set('region', filters.region); if (filters?.search) params.set('search', filters.search); if (filters?.startDate) params.set('startDate', filters.startDate); if (filters?.endDate) params.set('endDate', filters.endDate); const query = params.toString(); const url = query ? `/incidents?${query}` : '/incidents'; const { data } = await api.get(url); return data.map(toCompat); } export async function fetchIncidentDetail(sn: number): Promise { const { data } = await api.get(`/incidents/${sn}`); return data; } export async function fetchIncidentWeather(sn: number): Promise { try { const { data } = await api.get(`/incidents/${sn}/weather`); return data; } catch { return null; } } export async function fetchIncidentMedia(sn: number): Promise { try { const { data } = await api.get(`/incidents/${sn}/media`); return data; } catch { return null; } } export async function fetchIncidentPredictions(sn: number): Promise { const { data } = await api.get(`/incidents/${sn}/predictions`); return data; }