/** * Active ride & match state store. * * Tracks the currently active ride and match (if any), plus * the search/loading state for ride matching. */ import { create } from 'zustand'; import { immer } from 'zustand/middleware/immer'; import type { Ride } from '../types/ride'; import type { Match } from '../types/match'; // ─── State Shape ───────────────────────────────────────────────────────────── interface RideState { /** The ride the user is currently involved in (as rider or passenger) */ activeRide: Ride | null; /** The current match for the active ride */ activeMatch: Match | null; /** Whether the app is currently searching for ride matches */ isSearching: boolean; /** Error message from the last failed operation */ error: string | null; } // ─── Actions ───────────────────────────────────────────────────────────────── interface RideActions { /** Set the active ride */ setActiveRide: (ride: Ride | null) => void; /** Set the active match */ setActiveMatch: (match: Match | null) => void; /** Toggle the searching state */ setSearching: (value: boolean) => void; /** Set an error message */ setError: (error: string | null) => void; /** Clear the active ride, match, and search state */ clearActiveRide: () => void; /** Update ride status (convenience) */ updateRideStatus: (status: Ride['status']) => void; /** Update match status (convenience) */ updateMatchStatus: (status: Match['status']) => void; } // ─── Store ─────────────────────────────────────────────────────────────────── export const useRideStore = create()( immer((set) => ({ // Initial state activeRide: null, activeMatch: null, isSearching: false, error: null, // Actions setActiveRide: (ride) => set((state) => { state.activeRide = ride; }), setActiveMatch: (match) => set((state) => { state.activeMatch = match; }), setSearching: (value) => set((state) => { state.isSearching = value; if (value) { state.error = null; } }), setError: (error) => set((state) => { state.error = error; }), clearActiveRide: () => set((state) => { state.activeRide = null; state.activeMatch = null; state.isSearching = false; state.error = null; }), updateRideStatus: (status) => set((state) => { if (state.activeRide) { state.activeRide.status = status; } }), updateMatchStatus: (status) => set((state) => { if (state.activeMatch) { state.activeMatch.status = status; } }), })), ); // ─── Selectors ─────────────────────────────────────────────────────────────── export const selectHasActiveRide = (state: RideState) => state.activeRide !== null && state.activeMatch !== null; export const selectRideId = (state: RideState) => state.activeRide?.id ?? null; export const selectMatchId = (state: RideState) => state.activeMatch?.id ?? null; export const selectRideType = (state: RideState) => state.activeRide?.type ?? null;