File size: 4,171 Bytes
5306da4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
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;
|