import { useEffect, useState } from 'react'
import {
View, Text, ScrollView, TouchableOpacity,
StyleSheet, ActivityIndicator, RefreshControl,
} from 'react-native'
import AsyncStorage from '@react-native-async-storage/async-storage'
import { api } from '../../app/lib/api'
const COLORS = { bg: '#0F172A', card: '#1E293B', teal: '#0D9488', amber: '#F59E0B', green: '#10B981', text: '#F8FAFC', muted: '#94A3B8' }
interface DayEarning {
session_date: string
deliveries_count: number
delivery_revenue: number
tips_earned: number
net_earnings: number
daily_fee: number
fee_paid: boolean
}
function BreakEvenBar({ revenue, fee }: { revenue: number; fee: number }) {
const pct = Math.min(100, (revenue / fee) * 100)
const broke = revenue >= fee
return (
)
}
export default function EarningsScreen() {
const [days, setDays] = useState(7)
const [earnings, setEarnings] = useState([])
const [loading, setLoading] = useState(true)
const [refreshing, setRefreshing] = useState(false)
useEffect(() => { load() }, [days])
const load = async () => {
setLoading(true)
try {
const token = await AsyncStorage.getItem('token')
if (!token) return
const data = await api.get(`/drivers/me/earnings?days=${days}`, token)
setEarnings(data)
} catch { /* silent */ } finally {
setLoading(false)
setRefreshing(false)
}
}
const totals = earnings.reduce(
(acc, d) => ({
deliveries: acc.deliveries + (d.deliveries_count || 0),
gross: acc.gross + Number(d.delivery_revenue || 0),
tips: acc.tips + Number(d.tips_earned || 0),
net: acc.net + Number(d.net_earnings || 0),
daysWorked: acc.daysWorked + 1,
}),
{ deliveries: 0, gross: 0, tips: 0, net: 0, daysWorked: 0 },
)
const avgPerDay = totals.daysWorked > 0 ? totals.net / totals.daysWorked : 0
const avgDeliveries = totals.daysWorked > 0 ? totals.deliveries / totals.daysWorked : 0
const PERIODS = [
{ label: '7d', value: 7 }, { label: '14d', value: 14 },
{ label: '30d', value: 30 }, { label: '90d', value: 90 },
]
return (
{ setRefreshing(true); load() }} tintColor={COLORS.teal} />}
>
{/* Period selector */}
{PERIODS.map(p => (
setDays(p.value)}
style={[styles.periodBtn, days === p.value && styles.periodBtnActive]}
>
{p.label}
))}
{/* Summary cards */}
Net Earnings
${totals.net.toFixed(2)}
after daily fees
Tips
${totals.tips.toFixed(2)}
100% yours
Deliveries
{totals.deliveries}
{totals.daysWorked} days worked
Avg / Day
${avgPerDay.toFixed(2)}
{avgDeliveries.toFixed(1)} deliveries avg
{/* Break-even insight */}
{totals.daysWorked > 0 && (
{avgDeliveries >= 4 ? '✅ Breaking even on average!' : '⚠️ Below break-even average'}
You average {avgDeliveries.toFixed(1)} deliveries/day. Break-even = 4 deliveries ($5 × 4 = $20 fee).
Every delivery past #4 is pure profit.
)}
{/* Day-by-day */}
Daily Breakdown
{loading ? (
) : earnings.length === 0 ? (
No earnings in this period
) : (
earnings.map((day, i) => {
const net = Number(day.net_earnings || 0)
const revenue = Number(day.delivery_revenue || 0)
const fee = Number(day.daily_fee || 20)
const tips = Number(day.tips_earned || 0)
const date = new Date(day.session_date)
const isProfitable = net > 0
return (
0 && { borderTopColor: '#334155', borderTopWidth: 1 }]}>
{date.toLocaleDateString('en-CA', { weekday: 'short', month: 'short', day: 'numeric' })}
{day.deliveries_count} deliveries{tips > 0 ? ` · $${tips.toFixed(2)} tips` : ''}
{isProfitable ? '+' : ''}${net.toFixed(2)}
${revenue.toFixed(2)} − $20
)
})
)}
{/* How it works */}
How Your Pay Works
{[
['Daily access fee', '$20.00'],
['Per delivery', '$5.00 flat'],
['Tips', '100% yours'],
['Commission taken', '$0.00'],
['Break-even at', '4 deliveries'],
].map(([label, val]) => (
{label}
{val}
))}
)
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: COLORS.bg },
periodRow: { flexDirection: 'row', gap: 8, paddingHorizontal: 16, paddingTop: 16, paddingBottom: 8 },
periodBtn: { flex: 1, paddingVertical: 8, backgroundColor: COLORS.card, borderRadius: 8, alignItems: 'center' },
periodBtnActive: { backgroundColor: COLORS.teal },
periodBtnText: { color: COLORS.muted, fontWeight: '600', fontSize: 13 },
cardRow: { flexDirection: 'row', paddingHorizontal: 16, marginBottom: 10 },
card: { backgroundColor: COLORS.card, borderRadius: 12, padding: 14 },
cardLabel: { color: COLORS.muted, fontSize: 12, marginBottom: 4 },
cardValue: { color: COLORS.text, fontSize: 22, fontWeight: 'bold' },
cardSub: { color: COLORS.muted, fontSize: 11, marginTop: 2 },
sectionTitle: { color: COLORS.text, fontWeight: '700', fontSize: 15, marginBottom: 12 },
dayRow: { paddingVertical: 12, flexDirection: 'row', alignItems: 'center' },
barBg: { height: 4, backgroundColor: '#334155', borderRadius: 2, marginTop: 4 },
barFill: { height: 4, borderRadius: 2 },
infoRow: { flexDirection: 'row', justifyContent: 'space-between', paddingVertical: 6, borderBottomColor: '#334155', borderBottomWidth: 1 },
})