// type PayloadAction = { // 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( "auth/sendOTP", async (params, { rejectWithValue }) => { try { const response = await axios.post( `${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( "auth/verifyOTP", async (params, { rejectWithValue }) => { try { console.log("params", params); const response = await axios.post( `${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) => { 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;