import { createSlice, type PayloadAction } from '@reduxjs/toolkit'; import type { AuthState, LoginSuccessPayload } from '@/features/auth/authTypes'; import { STORAGE_KEYS } from '@/utils/storage'; import { clearAuthTokens, getAccessToken, isAccessTokenExpired, storeAuthTokens } from '@/utils/authToken'; const clearPersistedAuthState = () => { localStorage.removeItem(STORAGE_KEYS.accessToken); localStorage.removeItem(STORAGE_KEYS.user); localStorage.removeItem(STORAGE_KEYS.authState); clearAuthTokens(); }; const loadPersistedAuthState = (): AuthState => { const loggedOutState: AuthState = { user: null, accessToken: null, isAuthenticated: false }; const storedAuth = localStorage.getItem(STORAGE_KEYS.authState); const storedAccessToken = getAccessToken(); if (!storedAuth) { return loggedOutState; } try { const parsed = JSON.parse(storedAuth) as AuthState; const accessToken = parsed.accessToken || storedAccessToken; if (accessToken && parsed.user && !isAccessTokenExpired()) { return { user: parsed.user, accessToken, isAuthenticated: true }; } } catch { // fall through to the logged-out default below } clearPersistedAuthState(); return loggedOutState; }; const authSlice = createSlice({ name: 'auth', initialState: loadPersistedAuthState(), reducers: { loginSuccess: (state, action: PayloadAction) => { state.user = action.payload.user; state.accessToken = action.payload.accessToken; state.isAuthenticated = true; localStorage.setItem(STORAGE_KEYS.accessToken, action.payload.accessToken); localStorage.setItem(STORAGE_KEYS.user, JSON.stringify(action.payload.user)); storeAuthTokens({ access_token: action.payload.accessToken, refresh_token: action.payload.refreshToken ?? '', }); localStorage.setItem( STORAGE_KEYS.authState, JSON.stringify({ user: action.payload.user, accessToken: action.payload.accessToken, isAuthenticated: true, }), ); }, logout: (state) => { state.user = null; state.accessToken = null; state.isAuthenticated = false; clearPersistedAuthState(); }, hydrateAuth: () => loadPersistedAuthState(), }, }); export const { loginSuccess, logout, hydrateAuth } = authSlice.actions; export default authSlice.reducer;