import React, { useCallback, useEffect, useRef } from 'react'; import { View, Text, ScrollView, TouchableOpacity, Alert, Switch, InteractionManager, } from 'react-native'; import { useAppTheme, borderRadius, spacing, shadow, typography } from '@theme'; import { PrimaryButton } from '@components'; import { BellIcon, PersonIcon, WalletIcon, ClipboardIcon } from '@icons'; import { useAppDispatch, useAppSelector } from '@store'; import { setOnlineStatus } from '@store/commonReducers/auth'; import { useNavigation } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { AppStackParamList } from '@navigation/navigationTypes'; import { RouteNames, JobStatus } from '@utils/constants'; import { formatCurrency } from '@utils/formatters'; import { getStyles } from './dashboardScreen.styles'; import { toggleStatus, updateDeliveryPartnerLocation } from './thunk'; import { getCurrentLocationWithAddress, showPermissionDeniedAlert, socketService, } from '@services'; export const DashboardScreen: React.FC = () => { const { colors } = useAppTheme(); const styles = getStyles(colors); const dispatch = useAppDispatch(); const navigation = useNavigation>(); // Derive online status from API response stored in dashboard slice. // Falls back to auth.isOnline during the initial load before any toggle API call. const { availabiltyStatus, loading: toggleLoading } = useAppSelector( state => state.dashboard, ); const { user } = useAppSelector(state => state.auth); const authIsOnline = useAppSelector(state => state.auth.isOnline); const isOnline = availabiltyStatus ? availabiltyStatus.availabilityStatus === 'ONLINE' : authIsOnline; const { todayEarnings, completedCount, onlineMinutes, weeklyData } = useAppSelector(state => state.earnings); const { jobStatus, activeJob } = useAppSelector(state => state.job); const locationIntervalRef = useRef | null>( null, ); const sendLocationUpdate = useCallback(async () => { try { const result = await getCurrentLocationWithAddress(); const coords = result.coords; dispatch( updateDeliveryPartnerLocation({ latitude: coords.latitude, longitude: coords.longitude, accuracyMeters: coords.accuracy ?? 0, speedKph: coords.speed ? coords.speed * 3.6 : 0, // convert m/s -> km/h if needed heading: coords.heading ?? 0, }), ); } catch (err) { console.log('--------location update error------', err); } }, [dispatch]); useEffect(() => { if (isOnline) { // Fire one immediately on going online, then every 15s sendLocationUpdate(); locationIntervalRef.current = setInterval(sendLocationUpdate, 15000); } else { if (locationIntervalRef.current) { clearInterval(locationIntervalRef.current); locationIntervalRef.current = null; } } return () => { if (locationIntervalRef.current) { clearInterval(locationIntervalRef.current); locationIntervalRef.current = null; } }; }, [isOnline, sendLocationUpdate]); // Notify the socket server when online/offline status changes useEffect(() => { if (isOnline) { socketService.goOnline(); } else { socketService.goOffline(); } }, [isOnline]); const handleToggleOnline = () => { const newStatus = isOnline ? 'OFFLINE' : 'ONLINE'; // Optimistically update the auth flag so the timer and UI react immediately dispatch(setOnlineStatus(!isOnline)); dispatch(toggleStatus({ availabilityStatus: newStatus })) .unwrap() .then(response => { // Confirm state from server — setOnlineStatus stays in sync const isNowOnline = response.availabilityStatus === 'ONLINE'; dispatch(setOnlineStatus(isNowOnline)); }) .catch(() => { // Revert the optimistic update on API failure dispatch(setOnlineStatus(isOnline)); Alert.alert( 'Status Update Failed', 'Could not update your availability. Please try again.', ); }); }; const handleActiveJobBannerPress = () => { // Navigate back to the screen corresponding to the current job step switch (jobStatus) { case JobStatus.NewRequest: navigation.navigate(RouteNames.NewJobRequest); break; case JobStatus.Accepted: navigation.navigate(RouteNames.OrderAccepted); break; case JobStatus.ArrivedAtStore: navigation.navigate(RouteNames.ConfirmPickup); break; case JobStatus.PickedUp: navigation.navigate(RouteNames.OrderPickedUp); break; case JobStatus.EnRoute: navigation.navigate(RouteNames.LiveTracking); break; case JobStatus.ArrivedAtCustomer: navigation.navigate(RouteNames.DeliverOrder); break; default: Alert.alert('Status Error', 'Unknown active delivery state.'); } }; const formatOnlineTime = (mins: number) => { const hours = Math.floor(mins / 60); const remainingMins = mins % 60; return `${hours}h ${ remainingMins < 10 ? `0${remainingMins}` : remainingMins }m`; }; // Helper to render chart bar heights dynamically based on amounts const maxWeeklyAmount = Math.max(...weeklyData.map(d => d.amount), 1); return ( {/* Header Section */} Good Morning ☀️ {user?.name} {isOnline ? 'Online' : 'Offline'} {/* Offline Warning Banner */} {!isOnline && ( You are offline. Go online to start receiving orders. )} {/* Today's Summary Card */} Today's Summary {formatCurrency(isOnline ? todayEarnings : 0)} Earnings {isOnline ? completedCount : 0} Completed {formatOnlineTime(isOnline ? onlineMinutes : 0)} Online Time {/* Conditional Layout for Online vs Offline */} {isOnline ? ( <> {/* Performance Stats */} Your Performance 4.8 ★ Rating 95% Acceptance 98% Completion {/* Weekly Earnings Chart (Styled SVG/Flex columns) */} Weekly Overview {weeklyData.map((data, index) => { // Bar height percent const heightPercent = `${ (data.amount / maxWeeklyAmount) * 85 }%`; return ( ₹{data.amount} {data.day} ); })} ) : ( Go Online to start receiving delivery requests Make sure you are in a high-demand delivery zone to maximize your earnings. )} {/* Help & Support Cards at bottom */} Help & Support Alert.alert( 'Emergency SOS', 'Calling nearest security/emergency dispatch...', ) } > Emergency SOS Immediate Assistance navigation.navigate(RouteNames.BottomTabs, { screen: RouteNames.Profile, }) } > FAQ Center Help & Guides Alert.alert( 'Support Chat', 'Initiating live helpdesk agent chat...', ) } > Live Support 24/7 Chat Help {/* Active Job Floating Bottom Banner */} {jobStatus !== JobStatus.Idle && jobStatus !== JobStatus.NewRequest && activeJob && ( Order {activeJob.orderId} {jobStatus === JobStatus.Accepted && 'Heading to pickup store...'} {jobStatus === JobStatus.ArrivedAtStore && 'At pickup store, check items...'} {jobStatus === JobStatus.PickedUp && 'Order picked up, routing to customer...'} {jobStatus === JobStatus.EnRoute && 'On the way to customer...'} {jobStatus === JobStatus.ArrivedAtCustomer && 'Arrived at customer location...'} View )} ); }; // export default DashboardScreen;