탐지 화면 3개: - GearDetection: gearStore 더미 → fetchGroups() API (GEAR_IN/OUT_ZONE) - DarkVesselDetection: vesselStore 더미 → fetchVesselAnalysis() + filterDarkVessels() - 패턴 자동 분류 (완전차단/장기소실/MMSI변조/간헐송출) - ChinaFishing: inline 더미 → fetchVesselAnalysis() + mmsi 412* 필터 - 센서 카운터 동적 계산, 위험도 분포 도넛 차트 함정/단속계획: - patrol.ts: 스텁 → GET /api/patrol-ships 실제 호출 - patrolStore: API 기반 (routes/scenarios는 mock 유지) - EnforcementPlan: GET /api/enforcement/plans 연결 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
69 lines
1.9 KiB
TypeScript
69 lines
1.9 KiB
TypeScript
import { create } from 'zustand';
|
|
import type {
|
|
PatrolShip,
|
|
PatrolRoute,
|
|
PatrolScenario,
|
|
CoverageZone,
|
|
} from '@data/mock/patrols';
|
|
import { getPatrolShips, toLegacyPatrolShip } from '@/services/patrol';
|
|
|
|
interface PatrolStore {
|
|
ships: PatrolShip[];
|
|
routes: Record<string, PatrolRoute>;
|
|
scenarios: PatrolScenario[];
|
|
coverage: CoverageZone[];
|
|
fleetRoutes: Record<string, [number, number][]>;
|
|
selectedShipId: string | null;
|
|
loaded: boolean;
|
|
loading: boolean;
|
|
error: string | null;
|
|
load: () => Promise<void>;
|
|
selectShip: (id: string | null) => void;
|
|
}
|
|
|
|
export const usePatrolStore = create<PatrolStore>((set, get) => ({
|
|
ships: [],
|
|
routes: {},
|
|
scenarios: [],
|
|
coverage: [],
|
|
fleetRoutes: {},
|
|
selectedShipId: null,
|
|
loaded: false,
|
|
loading: false,
|
|
error: null,
|
|
|
|
load: async () => {
|
|
if (get().loaded && !get().error) return;
|
|
|
|
set({ loading: true, error: null });
|
|
try {
|
|
// 함정 목록은 API에서, 나머지(routes/scenarios/coverage)는 mock 유지
|
|
const [apiShips, mockModule] = await Promise.all([
|
|
getPatrolShips(),
|
|
get().routes && Object.keys(get().routes).length > 0
|
|
? Promise.resolve(null)
|
|
: import('@data/mock/patrols').then((m) => ({
|
|
routes: m.MOCK_PATROL_ROUTES,
|
|
scenarios: m.MOCK_PATROL_SCENARIOS,
|
|
coverage: m.MOCK_COVERAGE_ZONES,
|
|
fleetRoutes: m.MOCK_FLEET_ROUTES,
|
|
})),
|
|
]);
|
|
|
|
set({
|
|
ships: apiShips.map(toLegacyPatrolShip),
|
|
routes: mockModule?.routes ?? get().routes,
|
|
scenarios: mockModule?.scenarios ?? get().scenarios,
|
|
coverage: mockModule?.coverage ?? get().coverage,
|
|
fleetRoutes: mockModule?.fleetRoutes ?? get().fleetRoutes,
|
|
loaded: true,
|
|
loading: false,
|
|
});
|
|
} catch (err) {
|
|
set({ error: err instanceof Error ? err.message : String(err), loading: false });
|
|
}
|
|
},
|
|
|
|
selectShip: (id) => set({ selectedShipId: id }),
|
|
}));
|