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>
75 lines
1.5 KiB
TypeScript
75 lines
1.5 KiB
TypeScript
import { create } from 'zustand'
|
|
|
|
type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'error'
|
|
|
|
interface ReplayState {
|
|
/** WebSocket 연결 상태 */
|
|
connectionState: ConnectionState
|
|
|
|
/** 쿼리 진행 중 여부 */
|
|
querying: boolean
|
|
|
|
/** 쿼리 완료 여부 */
|
|
queryCompleted: boolean
|
|
|
|
/** 수신 청크 수 */
|
|
receivedChunks: number
|
|
|
|
/** 예상 전체 청크 수 */
|
|
totalChunks: number
|
|
|
|
/** 연결 상태 업데이트 */
|
|
setConnectionState: (state: ConnectionState) => void
|
|
|
|
/** 쿼리 시작 */
|
|
startQuery: () => void
|
|
|
|
/** 쿼리 진행 업데이트 */
|
|
updateProgress: (received: number, total: number) => void
|
|
|
|
/** 쿼리 완료 */
|
|
completeQuery: () => void
|
|
|
|
/** 전체 초기화 */
|
|
reset: () => void
|
|
}
|
|
|
|
export const useReplayStore = create<ReplayState>((set) => ({
|
|
connectionState: 'disconnected',
|
|
querying: false,
|
|
queryCompleted: false,
|
|
receivedChunks: 0,
|
|
totalChunks: 0,
|
|
|
|
setConnectionState: (connectionState) => set({ connectionState }),
|
|
|
|
startQuery: () =>
|
|
set({
|
|
querying: true,
|
|
queryCompleted: false,
|
|
receivedChunks: 0,
|
|
totalChunks: 0,
|
|
}),
|
|
|
|
updateProgress: (received, total) =>
|
|
set({
|
|
receivedChunks: received,
|
|
totalChunks: total,
|
|
}),
|
|
|
|
completeQuery: () =>
|
|
set({
|
|
querying: false,
|
|
queryCompleted: true,
|
|
}),
|
|
|
|
reset: () =>
|
|
set({
|
|
connectionState: 'disconnected',
|
|
querying: false,
|
|
queryCompleted: false,
|
|
receivedChunks: 0,
|
|
totalChunks: 0,
|
|
}),
|
|
}))
|