103 lines
2.8 KiB
TypeScript
103 lines
2.8 KiB
TypeScript
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
|
|
import { User, Location } from '../interfaces';
|
|
import { authService } from '../services/authService';
|
|
|
|
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,
|
|
};
|
|
|
|
export const loginWithPhone = createAsyncThunk(
|
|
'auth/loginWithPhone',
|
|
async (mobileNumber: string) => {
|
|
const response = await authService.login(mobileNumber);
|
|
return response;
|
|
},
|
|
);
|
|
|
|
export const verifyOtp = createAsyncThunk(
|
|
'auth/verifyOtp',
|
|
async ({ mobileNumber, otp }: { mobileNumber: string; otp: string }) => {
|
|
const response = await authService.verifyOtp(mobileNumber, otp);
|
|
return response;
|
|
},
|
|
);
|
|
|
|
const authSlice = createSlice({
|
|
name: 'auth',
|
|
initialState,
|
|
reducers: {
|
|
setUser(state, action: PayloadAction<User>) {
|
|
state.user = action.payload;
|
|
},
|
|
setLocation(state, _action: PayloadAction<Location>) {
|
|
if (state.user) {
|
|
state.user = { ...state.user };
|
|
}
|
|
},
|
|
completeProfile(state, action: PayloadAction<{ name: string; email: string; locationLabels: string[] }>) {
|
|
if (state.user) {
|
|
state.user = {
|
|
...state.user,
|
|
name: action.payload.name,
|
|
email: action.payload.email,
|
|
locationLabels: action.payload.locationLabels,
|
|
};
|
|
}
|
|
},
|
|
completeOnboarding(state) {
|
|
state.onboardingComplete = true;
|
|
},
|
|
logout(state) {
|
|
state.user = null;
|
|
state.isAuthenticated = false;
|
|
state.onboardingComplete = false;
|
|
state.error = null;
|
|
},
|
|
clearError(state) {
|
|
state.error = null;
|
|
},
|
|
},
|
|
extraReducers: (builder) => {
|
|
builder
|
|
.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.error.message || 'Login failed';
|
|
})
|
|
.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.error.message || 'OTP verification failed';
|
|
});
|
|
},
|
|
});
|
|
|
|
export const { setUser, setLocation, completeProfile, completeOnboarding, logout, clearError } = authSlice.actions;
|
|
export default authSlice.reducer;
|