import { createAction, createReducer } from '@reduxjs/toolkit'; import { User, Location } from '../../../interfaces'; import { loginWithPhone, verifyOtp, updateProfile, logoutUser } from './thunk'; // ─── State ─────────────────────────────────────────────────────────────────── export interface AuthState { user: User | null; isAuthenticated: boolean; isLoading: boolean; onboardingComplete: boolean; error: string | null; } const initialState: AuthState = { user: null, isAuthenticated: false, isLoading: false, onboardingComplete: false, error: null, }; // ─── Sync Actions ──────────────────────────────────────────────────────────── export const setUser = createAction('auth/setUser'); export const setLocation = createAction('auth/setLocation'); export const completeProfile = createAction<{ name: string; email: string; locationLabels: string[]; }>('auth/completeProfile'); export const completeOnboarding = createAction('auth/completeOnboarding'); export const logout = createAction('auth/logout'); export const clearError = createAction('auth/clearError'); // ─── Reducer ───────────────────────────────────────────────────────────────── const authReducer = createReducer(initialState, builder => { builder // ── Sync Actions ─────────────────────────────────────────────────────── .addCase(setUser, (state, action) => { state.user = action.payload; }) .addCase(setLocation, (state, _action) => { if (state.user) { state.user = { ...state.user }; } }) .addCase(completeProfile, (state, action) => { if (state.user) { state.user = { ...state.user, name: action.payload.name, email: action.payload.email, locationLabels: action.payload.locationLabels, }; } }) .addCase(completeOnboarding, state => { state.onboardingComplete = true; }) .addCase(logout, state => { state.user = null; state.isAuthenticated = false; state.onboardingComplete = false; state.error = null; }) .addCase(clearError, state => { state.error = null; }) // ── loginWithPhone ───────────────────────────────────────────────────── .addCase(loginWithPhone.pending, state => { state.isLoading = true; state.error = null; }) .addCase(loginWithPhone.fulfilled, state => { state.isLoading = false; }) .addCase(loginWithPhone.rejected, (state, action) => { state.isLoading = false; state.error = (action.payload as string) || 'Login failed'; }) // ── verifyOtp ────────────────────────────────────────────────────────── .addCase(verifyOtp.pending, state => { state.isLoading = true; state.error = null; }) .addCase(verifyOtp.fulfilled, (state, action) => { state.isLoading = false; state.isAuthenticated = true; state.user = action.payload.user; }) .addCase(verifyOtp.rejected, (state, action) => { state.isLoading = false; state.error = (action.payload as string) || 'OTP verification failed'; }) // ── updateProfile ────────────────────────────────────────────────────── .addCase(updateProfile.pending, state => { state.isLoading = true; state.error = null; }) .addCase(updateProfile.fulfilled, (state, action) => { state.isLoading = false; state.user = action.payload.user; }) .addCase(updateProfile.rejected, (state, action) => { state.isLoading = false; state.error = (action.payload as string) || 'Profile update failed'; }) // ── logoutUser ───────────────────────────────────────────────────────── .addCase(logoutUser.fulfilled, state => { state.user = null; state.isAuthenticated = false; state.onboardingComplete = false; state.error = null; }) .addCase(logoutUser.rejected, state => { // Still clear state even if API fails (tokens already cleared in thunk) state.user = null; state.isAuthenticated = false; state.onboardingComplete = false; state.error = null; }); }); export default authReducer;