149 lines
4.6 KiB
TypeScript

import { createReducer, createAction, PayloadAction } from '@reduxjs/toolkit';
import { PartnerProfile, PartnerLocation } from '@app-types/index';
import {
getProfileThunk,
updateProfileThunk,
loginWithPhone,
verifyOtp,
} from './thunk';
import { LoginResponse, User } from '@interfaces';
import { getDashboard } from '@features/screens/onboardingCompleteScreen/thunk';
export interface AuthState {
isAuthenticated: boolean;
loginData: LoginResponse | null;
user: User | null;
accessToken: string | null;
refreshToken: string | null;
isNewUser: boolean | null;
hasCompletedOnboarding: boolean;
isOnline: boolean;
token: string | null;
partnerId: string | null;
partnerProfile: PartnerProfile | null;
requestId: string | null;
loading: boolean;
error: string | null;
}
const initialState: AuthState = {
isAuthenticated: false,
user: null,
accessToken: null,
refreshToken: null,
isNewUser: null,
hasCompletedOnboarding: false,
isOnline: false,
token: null,
partnerId: null,
partnerProfile: null,
requestId: null,
loading: false,
error: null,
loginData: null,
};
export const setAuthenticated = createAction<{
token: string;
partnerId: string;
}>('auth/setAuthenticated');
export const setRequestId = createAction<string>('auth/setRequestId');
export const setOnboardingComplete = createAction('auth/setOnboardingComplete');
export const setOnlineStatus = createAction<boolean>('auth/setOnlineStatus');
export const setProfile = createAction<PartnerProfile>('auth/setProfile');
export const setLocation = createAction<PartnerLocation>('auth/setLocation');
export const logout = createAction('auth/logout');
export const authReducer = createReducer(initialState, builder => {
builder
// Sync Actions
.addCase(setAuthenticated, (state, action) => {
state.isAuthenticated = true;
state.token = action.payload.token;
state.partnerId = action.payload.partnerId;
})
.addCase(setRequestId, (state, action) => {
state.requestId = action.payload;
})
.addCase(setOnboardingComplete, state => {
state.hasCompletedOnboarding = true;
})
.addCase(setOnlineStatus, (state, action) => {
state.isOnline = action.payload;
})
.addCase(setProfile, (state, action) => {
state.partnerProfile = action.payload;
})
.addCase(setLocation, (state, action) => {
if (state.partnerProfile) {
state.partnerProfile.location = action.payload;
}
})
.addCase(logout, () => initialState)
// Async Thunks
// Login
.addCase(loginWithPhone.pending, state => {
state.loading = true;
state.error = null;
})
.addCase(loginWithPhone.fulfilled, (state, action) => {
state.loginData = action.payload;
state.loading = false;
state.error = null;
})
.addCase(loginWithPhone.rejected, (state, action) => {
state.loading = false;
state.error = action.payload as string;
})
// Verify OTP
.addCase(verifyOtp.pending, state => {
state.loading = true;
state.error = null;
})
.addCase(verifyOtp.fulfilled, (state, action) => {
const { user, accessToken, refreshToken, isNewUser } = action.payload;
state.user = user;
state.accessToken = accessToken;
state.refreshToken = refreshToken;
state.isNewUser = isNewUser;
state.loading = false;
state.error = null;
})
.addCase(verifyOtp.rejected, (state, action) => {
state.loading = false;
state.error = action.payload as string;
})
.addCase(getProfileThunk.pending, state => {
state.loading = true;
state.error = null;
})
.addCase(getProfileThunk.fulfilled, (state, action) => {
state.loading = false;
state.partnerProfile = action.payload;
})
.addCase(getProfileThunk.rejected, (state, action) => {
state.loading = false;
state.error = action.payload as string;
})
.addCase(updateProfileThunk.pending, state => {
state.loading = true;
state.error = null;
})
.addCase(updateProfileThunk.fulfilled, (state, action) => {
state.loading = false;
state.partnerProfile = action.payload;
})
.addCase(updateProfileThunk.rejected, (state, action) => {
state.loading = false;
state.error = action.payload as string;
})
// When dashboard is fetched, sync user.status so rootNavigator
// automatically swaps from OnBoardingStack → AppStack
.addCase(getDashboard.fulfilled, (state, action) => {
const serverStatus = action.payload?.deliveryPartner?.user?.status;
if (state.user && serverStatus) {
state.user.status = serverStatus as User['status'];
}
});
});