import React, { useEffect, useState } from 'react' import { View, Text, StyleSheet, ScrollView, TouchableOpacity, ActivityIndicator, Alert, Switch, } from 'react-native' import { SafeAreaView } from 'react-native-safe-area-context' import { api } from '../lib/api' interface BreakEvenStatus { dailyFee: number deliveriesCompleted: number deliveryRevenue: number tipsEarned: number totalEarned: number netEarnings: number remainingCost: number deliveriesToBreakEven: number hasBreakEven: boolean progressPercent: number nextDeliveryIsProfit: boolean message: string profitAmount: number } export default function DriverDashboardScreen() { const [session, setSession] = useState(null) const [breakEven, setBreakEven] = useState(null) const [earnings, setEarnings] = useState([]) const [isOnline, setIsOnline] = useState(false) const [loading, setLoading] = useState(true) useEffect(() => { loadSession() }, []) const loadSession = async () => { setLoading(true) try { const { data } = await api.get('/drivers/me/session') setSession(data.session) setBreakEven(data.breakEven) setEarnings(data.earnings || []) setIsOnline(data.session?.status === 'active') } catch {} setLoading(false) } const toggleOnline = async (value: boolean) => { try { if (value) { await api.post('/payments/driver/daily-fee') const { data } = await api.post('/drivers/me/session/start') setSession(data.session) setBreakEven(data.breakEven) setIsOnline(true) } else { Alert.alert('Go offline?', 'You will stop receiving new orders.', [ { text: 'Cancel', style: 'cancel' }, { text: 'Go Offline', style: 'destructive', onPress: async () => { await api.post('/drivers/me/session/end') setIsOnline(false) loadSession() }, }, ]) } } catch (err: any) { Alert.alert('Error', err.response?.data?.message || 'Something went wrong') } } if (loading) { return ( ) } return ( {/* Online toggle */} {isOnline ? 'You are online' : 'You are offline'} {isOnline ? 'Receiving delivery requests' : 'Pay $20 to start your day'} {/* Break-even card */} {breakEven ? ( Break-Even Progress {breakEven.progressPercent}% {/* Progress bar */} {/* Stats row */} = 0 ? '+' : ''}$${breakEven.netEarnings.toFixed(2)}`} inverted={breakEven.hasBreakEven} highlight={breakEven.netEarnings >= 0} /> {/* Message */} {breakEven.message} {breakEven.tipsEarned > 0 && ( Tips: ${breakEven.tipsEarned.toFixed(2)} — always 100% yours )} ) : ( Ready to start? Toggle online above to begin your day. )} {/* Today's deliveries */} {earnings.length > 0 && ( Today's Deliveries {earnings.map((e, i) => ( Delivery #{i + 1} {e.is_profit && ( Profit )} ${Number(e.total).toFixed(2)} {e.tip_amount > 0 && ( +${Number(e.tip_amount).toFixed(2)} tip )} ))} )} ) } function StatBox({ label, value, inverted, highlight }: any) { return ( {value} {label} ) } function Row({ label, value, valueColor }: any) { return ( {label} {value} ) } const styles = StyleSheet.create({ safeArea: { flex: 1, backgroundColor: '#0F172A' }, scroll: { flex: 1 }, scrollContent: { padding: 16, gap: 12 }, center: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: '#0F172A' }, onlineCard: { backgroundColor: '#1E293B', borderRadius: 16, padding: 16, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', }, onlineLabel: { color: '#fff', fontWeight: '700', fontSize: 16 }, onlineSub: { color: '#94A3B8', fontSize: 12, marginTop: 2 }, card: { backgroundColor: '#1E293B', borderRadius: 16, padding: 16 }, cardGreen: { backgroundColor: '#15803D' }, cardHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }, cardTitle: { color: '#fff', fontWeight: '700', fontSize: 16 }, percent: { color: '#0D9488', fontWeight: '800', fontSize: 18 }, progressBg: { height: 8, backgroundColor: '#334155', borderRadius: 4, marginBottom: 12, overflow: 'hidden' }, progressFill: { height: '100%', backgroundColor: '#0D9488', borderRadius: 4 }, statsRow: { flexDirection: 'row', gap: 8, marginBottom: 12 }, statBox: { flex: 1, backgroundColor: '#0F172A', borderRadius: 12, padding: 10, alignItems: 'center' }, statBoxInverted: { backgroundColor: 'rgba(255,255,255,0.15)' }, statValue: { color: '#fff', fontWeight: '800', fontSize: 18 }, statLabel: { color: '#94A3B8', fontSize: 11, marginTop: 2 }, messageBadge: { backgroundColor: '#0F172A', borderRadius: 10, padding: 10, marginBottom: 8 }, messageBadgeGreen: { backgroundColor: 'rgba(255,255,255,0.15)' }, messageText: { color: '#94A3B8', fontSize: 13, textAlign: 'center', fontWeight: '600' }, tipsText: { color: '#94A3B8', fontSize: 12, textAlign: 'center' }, textWhite: { color: '#fff' }, textWhiteAlpha: { color: 'rgba(255,255,255,0.7)' }, subtleText: { color: '#64748B', fontSize: 13, marginTop: 4, marginBottom: 12 }, explainer: { gap: 8 }, row: { flexDirection: 'row', justifyContent: 'space-between' }, rowLabel: { color: '#94A3B8', fontSize: 13 }, rowValue: { color: '#fff', fontSize: 13, fontWeight: '600' }, earningRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: '#0F172A', }, earningLabel: { color: '#fff', fontSize: 14, fontWeight: '600' }, earningRight: { alignItems: 'flex-end' }, earningAmount: { color: '#0D9488', fontSize: 16, fontWeight: '700' }, tipLine: { color: '#22C55E', fontSize: 11, marginTop: 2 }, profitBadge: { backgroundColor: '#14532D', borderRadius: 6, paddingHorizontal: 6, paddingVertical: 2, marginTop: 3, alignSelf: 'flex-start' }, profitText: { color: '#22C55E', fontSize: 10, fontWeight: '700' }, })