Anurag
version-2 initial version
5306da4
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import { authApi, LoginCredentials, SignupCredentials, AuthResponse } from '../../api/authApi';
// Define the auth state interface
interface AuthState {
user: AuthResponse['user'] | null;
token: string | null;
isAuthenticated: boolean;
isLoading: boolean;
error: string | null;
}
// Initial state
const initialState: AuthState = {
user: null,
token: localStorage.getItem('authToken'),
isAuthenticated: !!localStorage.getItem('authToken'),
isLoading: false,
error: null,
};
// Async thunks
export const loginUser = createAsyncThunk(
'auth/login',
async (credentials: LoginCredentials, { rejectWithValue }) => {
try {
const response = await authApi.login(credentials);
// Store the token in localStorage
localStorage.setItem('authToken', response.token);
return response;
} catch (error: any) {
return rejectWithValue(error.response?.data?.message || 'Login failed');
}
}
);
export const signupUser = createAsyncThunk(
'auth/signup',
async (credentials: SignupCredentials, { rejectWithValue }) => {
try {
const response = await authApi.signup(credentials);
// Store the token in localStorage
localStorage.setItem('authToken', response.token);
return response;
} catch (error: any) {
return rejectWithValue(error.response?.data?.message || 'Signup failed');
}
}
);
export const logoutUser = createAsyncThunk(
'auth/logout',
async (_, { rejectWithValue }) => {
try {
await authApi.logout();
localStorage.removeItem('authToken');
return;
} catch (error: any) {
return rejectWithValue(error.response?.data?.message || 'Logout failed');
}
}
);
export const getCurrentUser = createAsyncThunk(
'auth/getCurrentUser',
async (_, { rejectWithValue }) => {
try {
const user = await authApi.getCurrentUser();
return user;
} catch (error: any) {
return rejectWithValue(error.response?.data?.message || 'Failed to fetch user');
}
}
);
// Auth slice
const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
resetAuthErrors: (state) => {
state.error = null;
},
},
extraReducers: (builder) => {
// Login cases
builder
.addCase(loginUser.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(loginUser.fulfilled, (state, action: PayloadAction<AuthResponse>) => {
state.isLoading = false;
state.isAuthenticated = true;
state.user = action.payload.user;
state.token = action.payload.token;
})
.addCase(loginUser.rejected, (state, action) => {
state.isLoading = false;
state.error = action.payload as string;
})
// Signup cases
.addCase(signupUser.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(signupUser.fulfilled, (state, action: PayloadAction<AuthResponse>) => {
state.isLoading = false;
state.isAuthenticated = true;
state.user = action.payload.user;
state.token = action.payload.token;
})
.addCase(signupUser.rejected, (state, action) => {
state.isLoading = false;
state.error = action.payload as string;
})
// Logout cases
.addCase(logoutUser.fulfilled, (state) => {
state.isAuthenticated = false;
state.user = null;
state.token = null;
})
// Get current user cases
.addCase(getCurrentUser.pending, (state) => {
state.isLoading = true;
})
.addCase(getCurrentUser.fulfilled, (state, action) => {
state.isLoading = false;
state.user = action.payload;
state.isAuthenticated = true;
})
.addCase(getCurrentUser.rejected, (state) => {
state.isLoading = false;
state.isAuthenticated = false;
state.user = null;
state.token = null;
});
},
});
export const { resetAuthErrors } = authSlice.actions;
export default authSlice.reducer;