BaaS_Driver_Android_App/store/authSlice.ts

206 lines
5.6 KiB
TypeScript

// type PayloadAction<T> = {
// type: string;
// payload: T;
// }
import axios from "axios";
import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { STORAGE_KEYS, MESSAGES, BASE_URL } from "../constants/config";
import { AUTH_STATUSES, StatusType } from "../constants/types";
interface AuthState {
phone: string | null;
otpId: number | null;
isLoggedIn: boolean;
status: StatusType;
sendOTPError: string | null;
verifyOTPError: string | null;
generalError: string | null;
}
interface SendOTPResponse {
success: boolean;
message: string;
data: {
otpId: number;
phone: string;
};
}
interface VerifyOTPResponse {
success: boolean;
message: string;
data: {
success: boolean;
message: string;
token: string;
token_expires_in: string;
};
}
interface SendOTPParams {
phone: string | null;
}
interface VerifyOTPParams {
phone: string | null;
otp: string | null;
otpId: string | null;
}
const initialState: AuthState = {
phone: null,
otpId: null,
isLoggedIn: false,
status: AUTH_STATUSES.IDLE,
sendOTPError: null,
verifyOTPError: null,
generalError: null,
};
//async thunk to send otp
export const sendOTP = createAsyncThunk<SendOTPResponse, SendOTPParams>(
"auth/sendOTP",
async (params, { rejectWithValue }) => {
try {
const response = await axios.post<SendOTPResponse>(
`${BASE_URL}/api/v1/send-otp`,
params
);
return response.data;
// if (!response.data.status) throw new Error(response.data.message);
} catch (error: any) {
const serverMessage = error.response?.data?.message;
return rejectWithValue(serverMessage || "Something went wrong");
}
}
);
export const verifyOTP = createAsyncThunk<VerifyOTPResponse, VerifyOTPParams>(
"auth/verifyOTP",
async (params, { rejectWithValue }) => {
try {
console.log("params", params);
const response = await axios.post<VerifyOTPResponse>(
`${BASE_URL}/api/v1/verify-otp`,
params
);
if (!response.data.success) throw new Error(response.data.message);
// Store tokens
await AsyncStorage.setItem(
STORAGE_KEYS.AUTH_TOKEN,
response.data.data.token
);
return response.data;
} catch (error: any) {
console.log(error.message);
return rejectWithValue(MESSAGES.AUTHENTICATION.VERIFICATION_FAILED);
}
}
);
export const logout = createAsyncThunk(
"auth/logout",
async (_, { dispatch }) => {
await AsyncStorage.removeItem(STORAGE_KEYS.AUTH_TOKEN);
dispatch(authSlice.actions.logout());
}
);
const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
loginRequest: (state) => {
state.status = AUTH_STATUSES.LOADING;
},
loginSuccess: (state, action) => {
state.status = AUTH_STATUSES.SUCCESS;
state.isLoggedIn = true; // Set logged-in state to true
},
setIsLoggedIn: (state, action) => {
state.isLoggedIn = action.payload;
},
loginFailure: (state, action: PayloadAction<string>) => {
state.status = AUTH_STATUSES.FAILED;
state.generalError = action.payload;
},
logout: (state) => {
state.isLoggedIn = false;
},
clearSendOTPError: (state) => {
state.sendOTPError = null;
},
clearVerifyOTPError: (state) => {
state.verifyOTPError = null;
},
clearAllErrors: (state) => {
state.sendOTPError = null;
state.verifyOTPError = null;
state.generalError = null;
},
},
extraReducers: (builder) => {
builder
.addCase(sendOTP.pending, (state) => {
state.status = AUTH_STATUSES.LOADING;
state.sendOTPError = null;
})
.addCase(sendOTP.fulfilled, (state, action) => {
state.status = AUTH_STATUSES.SUCCESS;
state.otpId = action.payload.data.otpId;
state.phone = action.payload.data.phone;
state.sendOTPError = null;
})
.addCase(sendOTP.rejected, (state, action) => {
state.status = AUTH_STATUSES.FAILED;
state.sendOTPError = (action.payload as string) || "Failed to send OTP";
})
.addCase(verifyOTP.pending, (state) => {
state.status = AUTH_STATUSES.LOADING;
state.verifyOTPError = null;
})
.addCase(verifyOTP.fulfilled, (state, action) => {
state.status = AUTH_STATUSES.SUCCESS;
state.isLoggedIn = true;
state.verifyOTPError = null;
const token = action.payload.data.token;
AsyncStorage.setItem(STORAGE_KEYS.AUTH_TOKEN, token).catch((error) => {
console.log("Error storing token", error);
});
})
.addCase(verifyOTP.rejected, (state, action) => {
state.status = AUTH_STATUSES.FAILED;
state.verifyOTPError = action.error.message || "Failed to verify OTP";
})
.addCase(logout.pending, (state) => {
state.status = AUTH_STATUSES.LOADING;
})
.addCase(logout.fulfilled, (state) => {
state.otpId = null;
state.isLoggedIn = false;
state.status = AUTH_STATUSES.IDLE;
state.verifyOTPError = null;
state.generalError = null;
state.sendOTPError = null;
state.phone = null;
})
.addCase(logout.rejected, (state, action) => {
state.status = AUTH_STATUSES.FAILED;
state.generalError = action.error.message || "Failed to log out";
});
},
});
export const {
logout: localLogout,
clearSendOTPError,
clearVerifyOTPError,
clearAllErrors,
setIsLoggedIn,
} = authSlice.actions;
export default authSlice.reducer;