/** * Device location state store. * * Tracks the user's current GPS location and its human-readable address. * Updated periodically by a foreground location service. */ import { create } from 'zustand'; import { immer } from 'zustand/middleware/immer'; // ─── State Shape ───────────────────────────────────────────────────────────── interface LocationState { /** Current GPS coordinates (null when location is unavailable) */ currentLocation: { lat: number; lng: number } | null; /** Reverse-geocoded address string for the current location */ locationAddress: string | null; /** Most recent location error, if any */ locationError: string | null; /** Whether location services are currently tracking */ isTracking: boolean; } // ─── Actions ───────────────────────────────────────────────────────────────── interface LocationActions { /** Update the current GPS coordinates */ setLocation: (lat: number, lng: number) => void; /** Update the reverse-geocoded address */ setAddress: (address: string | null) => void; /** Set a location error */ setError: (error: string | null) => void; /** Clear all location state (e.g., on logout) */ clearLocation: () => void; /** Toggle the tracking flag */ setTracking: (value: boolean) => void; } // ─── Store ─────────────────────────────────────────────────────────────────── export const useLocationStore = create()( immer((set) => ({ // Initial state currentLocation: null, locationAddress: null, locationError: null, isTracking: false, // Actions setLocation: (lat, lng) => set((state) => { state.currentLocation = { lat, lng }; state.locationError = null; }), setAddress: (address) => set((state) => { state.locationAddress = address; }), setError: (error) => set((state) => { state.locationError = error; }), clearLocation: () => set((state) => { state.currentLocation = null; state.locationAddress = null; state.locationError = null; state.isTracking = false; }), setTracking: (value) => set((state) => { state.isTracking = value; }), })), ); // ─── Selectors ─────────────────────────────────────────────────────────────── export const selectHasLocation = (state: LocationState) => state.currentLocation !== null; export const selectFormattedLocation = (state: LocationState) => { if (!state.currentLocation) return null; const { lat, lng } = state.currentLocation; return { lat, lng, address: state.locationAddress ?? `${lat.toFixed(6)}, ${lng.toFixed(6)}`, }; };