mobileapp / src /store /useAuthStore.ts
Antaram Dev Bot
feat: complete ANTARAM.ORG ride-sharing app frontend
5c876be
/**
* 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<User>) => 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<AuthState & AuthActions>()(
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;