dark(ship-gis) 프로젝트의 맵 기반 3대 기능을 API 탐색기에 이관. Feature 폴더 모듈화 구조로 타 프로젝트 재활용 가능하게 구성. Phase 1: vessel-map 공유 모듈 (Deck.gl 9 + Zustand 5 + STOMP) Phase 2: 최근 위치 (30초 폴링 + IconLayer + 선종 필터 + 팝업) Phase 3: 선박 항적 (MMSI 조회 + PathLayer + 타임라인 보간) Phase 4: 뷰포트 리플레이 (STOMP WebSocket 청크 + TripsLayer 애니메이션) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
73 lines
1.9 KiB
TypeScript
73 lines
1.9 KiB
TypeScript
import { create } from 'zustand'
|
|
import type { VesselPosition } from '../../vessel-map'
|
|
|
|
interface PositionState {
|
|
/** MMSI → 위치 맵 */
|
|
positions: Map<string, VesselPosition>
|
|
|
|
/** 선택된 MMSI (팝업 표시용) */
|
|
selectedMmsi: string | null
|
|
|
|
/** 선종별 가시성 필터 */
|
|
kindVisibility: Record<string, boolean>
|
|
|
|
/** 위치 데이터 전체 교체 */
|
|
setPositions: (list: VesselPosition[]) => void
|
|
|
|
/** 선박 선택/해제 */
|
|
selectVessel: (mmsi: string | null) => void
|
|
|
|
/** 특정 선종 토글 */
|
|
toggleKindVisibility: (kindCode: string) => void
|
|
|
|
/** 전체 선종 표시/숨김 */
|
|
setAllKindVisibility: (visible: boolean) => void
|
|
|
|
/** 가시성 필터 적용된 선박 목록 */
|
|
getVisiblePositions: () => VesselPosition[]
|
|
}
|
|
|
|
export const usePositionStore = create<PositionState>((set, get) => ({
|
|
positions: new Map(),
|
|
selectedMmsi: null,
|
|
kindVisibility: {},
|
|
|
|
setPositions: (list) => {
|
|
const map = new Map<string, VesselPosition>()
|
|
for (const p of list) {
|
|
map.set(p.mmsi, p)
|
|
}
|
|
set({ positions: map })
|
|
},
|
|
|
|
selectVessel: (mmsi) => set({ selectedMmsi: mmsi }),
|
|
|
|
toggleKindVisibility: (kindCode) =>
|
|
set((state) => ({
|
|
kindVisibility: {
|
|
...state.kindVisibility,
|
|
[kindCode]: !(state.kindVisibility[kindCode] ?? true),
|
|
},
|
|
})),
|
|
|
|
setAllKindVisibility: (visible) =>
|
|
set((state) => {
|
|
const next: Record<string, boolean> = {}
|
|
for (const code of Object.keys(state.kindVisibility)) {
|
|
next[code] = visible
|
|
}
|
|
return { kindVisibility: next }
|
|
}),
|
|
|
|
getVisiblePositions: () => {
|
|
const { positions, kindVisibility } = get()
|
|
const result: VesselPosition[] = []
|
|
for (const p of positions.values()) {
|
|
const code = p.shipKindCode || ''
|
|
if (kindVisibility[code] === false) continue
|
|
result.push(p)
|
|
}
|
|
return result
|
|
},
|
|
}))
|