From 525ed45b2397649404add57b54b8abd7c4cbe609 Mon Sep 17 00:00:00 2001 From: Tamojit Biswas Date: Tue, 21 Jul 2026 18:27:32 +0530 Subject: [PATCH] feat: implement onboarding stack and various feature screens for OTP, bank details, and profile management. --- app/features/screens/OtpScreen/OtpScreen.tsx | 4 +- .../bankDetailsScreen/bankDetailsScreen.tsx | 4 +- .../screens/completeProfileScreen/reducer.ts | 3 + .../documentsScreen/documentsScreen.tsx | 4 +- .../screens/earningsScreen/earningsScreen.tsx | 94 ++++++++++++++----- .../screens/profileScreen/profileScreen.tsx | 5 - app/navigation/onBoardingStack.tsx | 12 ++- 7 files changed, 88 insertions(+), 38 deletions(-) diff --git a/app/features/screens/OtpScreen/OtpScreen.tsx b/app/features/screens/OtpScreen/OtpScreen.tsx index b12bd9d..b6ca3d8 100644 --- a/app/features/screens/OtpScreen/OtpScreen.tsx +++ b/app/features/screens/OtpScreen/OtpScreen.tsx @@ -56,7 +56,9 @@ export const OtpScreen: React.FC<{ route: any }> = ({ route }) => { await dispatch( verifyOtp({ phone, code: otp, role: 'DELIVERY' }), ).unwrap(); - navigation.navigate('OnBoarding', { screen: RouteNames.CompleteProfile }); + // Navigation is handled automatically by rootNavigator's conditional + // rendering: once accessToken is set, the Auth stack unmounts and + // OnBoarding or App stack mounts based on user.status. } catch (error) { Alert.alert('Error', error as string); } diff --git a/app/features/screens/bankDetailsScreen/bankDetailsScreen.tsx b/app/features/screens/bankDetailsScreen/bankDetailsScreen.tsx index 89ed361..0008c15 100644 --- a/app/features/screens/bankDetailsScreen/bankDetailsScreen.tsx +++ b/app/features/screens/bankDetailsScreen/bankDetailsScreen.tsx @@ -12,10 +12,8 @@ import { WalletIcon, CheckCircleIcon, ClipboardIcon } from '@icons'; import { useNavigation } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { AppStackParamList } from '@navigation/navigationTypes'; -import { RouteNames } from '@utils/constants'; -import { BankAccount } from '@interfaces'; import { getStyles } from './bankDetailsScreen.styles'; -import { formatDate, maskAccountNumber } from '@utils'; +import { formatDate, maskAccountNumber, RouteNames } from '@utils'; import { fetchBankAccounts } from '../addBankDetailsScreen'; import { useAppDispatch, useAppSelector } from '@store'; diff --git a/app/features/screens/completeProfileScreen/reducer.ts b/app/features/screens/completeProfileScreen/reducer.ts index 67f06a5..55561a5 100644 --- a/app/features/screens/completeProfileScreen/reducer.ts +++ b/app/features/screens/completeProfileScreen/reducer.ts @@ -8,6 +8,7 @@ export interface completeProfileState { error: string | null; submitError: string | null; userProfile: UserProfile | null; + alreadyNavigate: boolean; } const initialState: completeProfileState = { @@ -15,6 +16,7 @@ const initialState: completeProfileState = { error: null, submitError: null, userProfile: null, + alreadyNavigate: false, }; export const completeProfileReducer = createReducer(initialState, builder => { @@ -26,6 +28,7 @@ export const completeProfileReducer = createReducer(initialState, builder => { .addCase(completeOnboard.fulfilled, (state, action) => { state.isLoading = false; state.userProfile = action.payload; + state.alreadyNavigate = true; }) .addCase(completeOnboard.rejected, (state, action) => { state.isLoading = false; diff --git a/app/features/screens/documentsScreen/documentsScreen.tsx b/app/features/screens/documentsScreen/documentsScreen.tsx index ea8fcdc..bb616ab 100644 --- a/app/features/screens/documentsScreen/documentsScreen.tsx +++ b/app/features/screens/documentsScreen/documentsScreen.tsx @@ -198,7 +198,7 @@ export const DocumentsScreen: React.FC = () => { statusBarTranslucent onRequestClose={() => setSelectedDoc(null)} > - + {/* Modal Header */} @@ -259,7 +259,7 @@ export const DocumentsScreen: React.FC = () => { ) )} - + ); diff --git a/app/features/screens/earningsScreen/earningsScreen.tsx b/app/features/screens/earningsScreen/earningsScreen.tsx index b74fd31..bff5deb 100644 --- a/app/features/screens/earningsScreen/earningsScreen.tsx +++ b/app/features/screens/earningsScreen/earningsScreen.tsx @@ -10,35 +10,75 @@ export const EarningsScreen: React.FC = () => { const { colors } = useAppTheme(); const styles = getStyles(colors); - const { todayEarnings, completedCount, onlineMinutes } = useAppSelector((state) => state.earnings); - const { jobHistory } = useAppSelector((state) => state.job); + const { todayEarnings, completedCount, onlineMinutes } = useAppSelector( + state => state.earnings, + ); + const { jobHistory } = useAppSelector(state => state.job); // Default mock jobs history if none completed yet - const defaultHistory: { orderId: string; time: string; amount: number; paymentType: 'online' | 'cod'; }[] = [ - { orderId: '#ORD125487', time: '12:35 PM', amount: 78.0, paymentType: 'online' }, - { orderId: '#ORD125422', time: '11:15 AM', amount: 65.0, paymentType: 'cod' }, - { orderId: '#ORD125389', time: '09:40 AM', amount: 120.0, paymentType: 'online' }, - { orderId: '#ORD125310', time: 'Yesterday', amount: 85.0, paymentType: 'online' }, + const defaultHistory: { + orderId: string; + time: string; + amount: string; + paymentType: 'online' | 'cod'; + }[] = [ + { + orderId: '#ORD125487', + time: '12:35 PM', + amount: '78.0', + paymentType: 'online', + }, + { + orderId: '#ORD125422', + time: '11:15 AM', + amount: '65.0', + paymentType: 'cod', + }, + { + orderId: '#ORD125389', + time: '09:40 AM', + amount: '120.0', + paymentType: 'online', + }, + { + orderId: '#ORD125310', + time: 'Yesterday', + amount: '85.0', + paymentType: 'online', + }, ]; - const displayHistory = jobHistory.length > 0 - ? jobHistory.map(job => ({ - orderId: job.orderId, - time: job.deliveredAt ? new Date(job.deliveredAt).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}) : 'Delivered', - amount: job.amount, - paymentType: job.paymentType, - })).concat(defaultHistory) - : defaultHistory; + const displayHistory = + jobHistory.length > 0 + ? jobHistory + .map(job => ({ + orderId: job.orderId, + time: job.deliveredAt + ? new Date(job.deliveredAt).toLocaleTimeString([], { + hour: '2-digit', + minute: '2-digit', + }) + : 'Delivered', + amount: job.amount, + paymentType: job.paymentType, + })) + .concat(defaultHistory) + : defaultHistory; const formatOnlineTime = (mins: number) => { const hours = Math.floor(mins / 60); const remainingMins = mins % 60; - return `${hours}h ${remainingMins < 10 ? `0${remainingMins}` : remainingMins}m`; + return `${hours}h ${ + remainingMins < 10 ? `0${remainingMins}` : remainingMins + }m`; }; return ( - + Earnings @@ -46,8 +86,10 @@ export const EarningsScreen: React.FC = () => { {/* Total Earnings Card */} Today's Earnings - {formatCurrency(todayEarnings)} - + + {formatCurrency(todayEarnings)} + + {completedCount} @@ -57,7 +99,9 @@ export const EarningsScreen: React.FC = () => { - {formatOnlineTime(onlineMinutes)} + + {formatOnlineTime(onlineMinutes)} + Online Time @@ -73,7 +117,7 @@ export const EarningsScreen: React.FC = () => { {/* Recent Deliveries List */} Recent Deliveries - + {displayHistory.map((item, index) => ( @@ -87,9 +131,13 @@ export const EarningsScreen: React.FC = () => { - +{formatCurrency(item.amount)} + + +{formatCurrency(Number(item.amount))} + - {item.paymentType.toUpperCase()} + + {item.paymentType.toUpperCase()} + diff --git a/app/features/screens/profileScreen/profileScreen.tsx b/app/features/screens/profileScreen/profileScreen.tsx index e25fbf9..6c10c7d 100644 --- a/app/features/screens/profileScreen/profileScreen.tsx +++ b/app/features/screens/profileScreen/profileScreen.tsx @@ -19,11 +19,6 @@ export const ProfileScreen: React.FC = () => { const { profile } = useAppSelector(state => state.accountInfo); const menuItems = [ - { - id: 'personal', - title: 'Personal Info', - icon: , - }, { id: 'vehicle', title: 'Vehicle Info', diff --git a/app/navigation/onBoardingStack.tsx b/app/navigation/onBoardingStack.tsx index d316dcd..1ce0f09 100644 --- a/app/navigation/onBoardingStack.tsx +++ b/app/navigation/onBoardingStack.tsx @@ -8,20 +8,24 @@ import { KycScreen, } from '@features/screens'; import { RouteNames } from '@utils/constants'; +import { useAppSelector } from '@store'; const Stack = createNativeStackNavigator(); const onBoardingStack: React.FC = () => { + const { alreadyNavigate } = useAppSelector(state => state.onboard); return ( {/* */} - + {!alreadyNavigate && ( + + )}