/** * Authentication & user state store. * * Manages the current user session, authentication status, and * onboarding completion. Uses Zustand v5 with immer middleware * for ergonomic partial updates. */ import { create } from 'zustand'; import { immer } from 'zustand/middleware/immer'; import type { User, UserRole } from '../types/user'; // ─── State Shape ───────────────────────────────────────────────────────────── interface AuthState { /** Whether the user has a valid auth session */ isAuthenticated: boolean; /** The currently logged-in user (null when logged out) */ user: User | null; /** Whether the user has completed the onboarding flow */ isOnboarded: boolean; /** Whether auth state is currently being restored (e.g., on app launch) */ isRestoring: boolean; } // ─── Actions ───────────────────────────────────────────────────────────────── interface AuthActions { /** Mark the user as authenticated with their full profile */ setAuth: (user: User) => void; /** Set / replace the user object (e.g., after profile update) */ setUser: (user: User) => void; /** Mark onboarding as completed */ setOnboarded: (value: boolean) => void; /** Log out: clear all auth state */ logout: () => void; /** Apply partial updates to the current user */ updateUser: (partial: Partial) => void; /** Set the restoring flag (shown during app startup) */ setRestoring: (value: boolean) => void; /** Check authentication state (e.g., on app launch from persisted data) */ checkAuth: () => void; } // ─── Store ─────────────────────────────────────────────────────────────────── export const useAuthStore = create()( immer((set) => ({ // Initial state isAuthenticated: false, user: null, isOnboarded: false, isRestoring: true, // Actions setAuth: (user) => set((state) => { state.isAuthenticated = true; state.user = user; state.isRestoring = false; }), setUser: (user) => set((state) => { state.user = user; }), setOnboarded: (value) => set((state) => { state.isOnboarded = value; }), logout: () => set((state) => { state.isAuthenticated = false; state.user = null; state.isOnboarded = false; state.isRestoring = false; }), updateUser: (partial) => set((state) => { if (state.user) { Object.assign(state.user, partial); } }), setRestoring: (value) => set((state) => { state.isRestoring = value; }), checkAuth: () => set((state) => { // In a real app this would check SQLite / SecureStore for a persisted // user session. For now we simply mark restoring as complete. state.isRestoring = false; }), })), ); // ─── Selectors ─────────────────────────────────────────────────────────────── export const selectIsRider = (state: AuthState) => state.user?.currentRole === 'rider'; export const selectIsPassenger = (state: AuthState) => state.user?.currentRole === 'passenger'; export const selectUserDisplayName = (state: AuthState) => state.user?.displayName ?? ''; export const selectUserAvatar = (state: AuthState) => state.user?.avatarUrl ?? null; export const selectUserId = (state: AuthState) => state.user?.id ?? null;