BaaS_Driver_Android_App/store/authSlice.ts

220 lines
5.9 KiB
TypeScript

// type PayloadAction<T> = {
// type: string;
// payload: T;
// }
import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit";
import axios from "axios";
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as SecureStore from "expo-secure-store";
import urls, {
STORAGE_KEYS,
MESSAGES,
StatusType,
AUTH_STATUSES,
} from "../constants/config";
interface AuthState {
phone: string | null;
otpId: number | null;
isLoggedIn: boolean;
status: StatusType;
sendOTPError: string | null;
verifyOTPError: string | null;
generalError: string | null;
}
interface SendOTPResponse {
status: boolean;
message: string;
data: {
otpId: number;
};
}
interface VerifyOTPResponse {
status: boolean;
message: string;
token: string;
refreshToken: string;
}
interface SendOTPParams {
phone: string | null;
}
interface VerifyOTPParams {
phone: string | null;
otp: string | null;
otpId: number | 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 {
console.log(urls.BASE_URL, "BASE_URL");
// const response = await axios.post<SendOTPResponse>(
// `${urls.BASE_URL}/send-otp`,
// params
// );
// return response.data;
return {
status: true,
message: "Done",
data: {
otpId: 22,
},
};
// if (!response.data.status) throw new Error(response.data.message);
} catch (error: any) {
return rejectWithValue(error.response?.data?.message || error.message);
}
}
);
export const verifyOTP = createAsyncThunk<VerifyOTPResponse, VerifyOTPParams>(
"auth/verifyOTP",
async (params, { rejectWithValue }) => {
try {
const response = await axios.post<VerifyOTPResponse>(
`${urls.BASE_URL}/verify-otp`,
params
);
if (!response.data.status) throw new Error(response.data.message);
// Store tokens
await AsyncStorage.setItem(STORAGE_KEYS.AUTH_TOKEN, response.data.token);
await SecureStore.setItemAsync(
STORAGE_KEYS.REFRESH_TOKEN,
response.data.refreshToken
);
return response.data;
} catch (error: any) {
return rejectWithValue(MESSAGES.AUTHENTICATION.VERIFICATION_FAILED);
}
}
);
export const logout = createAsyncThunk(
"auth/logout",
async (_, { dispatch }) => {
await AsyncStorage.removeItem(STORAGE_KEYS.AUTH_TOKEN);
await SecureStore.deleteItemAsync(STORAGE_KEYS.REFRESH_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.meta.arg.phone;
state.sendOTPError = null;
})
.addCase(sendOTP.rejected, (state, action) => {
state.status = AUTH_STATUSES.FAILED;
state.sendOTPError = action.error.message || "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.token;
AsyncStorage.setItem(STORAGE_KEYS.AUTH_TOKEN, token).catch((error) => {
console.log("Error storing token", error);
});
const refreshToken = action.payload.refreshToken;
SecureStore.setItemAsync(
STORAGE_KEYS.REFRESH_TOKEN,
refreshToken
).catch((error) => {
console.log("Error storing refresh 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,
} = authSlice.actions;
export default authSlice.reducer;