- Add Expo Router with bottom tabs (Home, Scan, Proforma, Payments, Profile) - Home: earnings summary, quick actions, invoice list with Waiting/Paid filters - Scan: placeholder for camera flow, recent scans list - Proforma: list of proforma requests with send-to-contacts CTA - Payments: pending match and reconciled list - Profile: account info, about, logout - Apply Yaltopia theme: primary orange (#ea580c), dark navbar/tabs (#2d2d2d) - Add mock data (invoices, proforma, payments, user) in lib/mock-data.ts - Root layout: GestureHandler, SafeArea, PortalHost; tab bar dark with orange active Co-authored-by: Cursor <cursoragent@cursor.com>
103 lines
4.9 KiB
TypeScript
103 lines
4.9 KiB
TypeScript
import { View, ScrollView, Pressable } from 'react-native';
|
|
import { Text } from '@/components/ui/text';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { EARNINGS_SUMMARY, MOCK_INVOICES, MOCK_USER } from '@/lib/mock-data';
|
|
import { router } from 'expo-router';
|
|
|
|
const statusColor: Record<string, string> = {
|
|
Waiting: 'bg-amber-500/20 text-amber-700',
|
|
Paid: 'bg-emerald-500/20 text-emerald-700',
|
|
Draft: 'bg-gray-200 text-gray-700',
|
|
Unpaid: 'bg-red-500/20 text-red-700',
|
|
};
|
|
|
|
export default function HomeScreen() {
|
|
return (
|
|
<ScrollView className="flex-1 bg-[#f5f5f5]" contentContainerStyle={{ padding: 16, paddingBottom: 32 }}>
|
|
<View className="mb-4">
|
|
<Text className="text-2xl font-bold text-gray-900">Hi {MOCK_USER.name},</Text>
|
|
<Text className="text-muted-foreground mt-1">Take a look at your last activity.</Text>
|
|
</View>
|
|
|
|
<Card className="mb-4 overflow-hidden border-0">
|
|
<View className="bg-primary/10 p-4">
|
|
<Text className="text-muted-foreground text-sm">Earnings balance</Text>
|
|
<Text className="text-2xl font-bold text-gray-900">${EARNINGS_SUMMARY.balance.toLocaleString()}</Text>
|
|
</View>
|
|
<CardContent className="flex-row border-t border-border">
|
|
<Pressable className="flex-1 py-3" onPress={() => router.push('/(tabs)/payments')}>
|
|
<Text className="text-muted-foreground text-xs">Waiting for pay</Text>
|
|
<Text className="font-semibold text-gray-900">${EARNINGS_SUMMARY.waitingAmount.toLocaleString()}</Text>
|
|
<Text className="text-muted-foreground text-xs">{EARNINGS_SUMMARY.waitingCount} Waiting invoice</Text>
|
|
</Pressable>
|
|
<View className="w-px bg-border" />
|
|
<Pressable className="flex-1 py-3">
|
|
<Text className="text-muted-foreground text-xs">Paid this month</Text>
|
|
<Text className="font-semibold text-gray-900">${EARNINGS_SUMMARY.paidThisMonth.toLocaleString()}</Text>
|
|
<Text className="text-muted-foreground text-xs">{EARNINGS_SUMMARY.paidCount} Paid invoice</Text>
|
|
</Pressable>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<View className="mb-4 flex-row gap-3">
|
|
<Button className="flex-1 bg-primary" onPress={() => router.push('/(tabs)/scan')}>
|
|
<Text className="text-primary-foreground font-medium">Scan invoice</Text>
|
|
</Button>
|
|
<Button variant="outline" className="flex-1" onPress={() => router.push('/(tabs)/proforma')}>
|
|
<Text className="font-medium">Send proforma</Text>
|
|
</Button>
|
|
</View>
|
|
|
|
<View className="mb-2 flex-row gap-2">
|
|
{['All', 'Draft', 'Waiting', 'Paid', 'Unpaid'].map((filter) => (
|
|
<View
|
|
key={filter}
|
|
className={`rounded-full px-3 py-1.5 ${filter === 'Waiting' ? 'bg-primary' : 'bg-muted'}`}
|
|
>
|
|
<Text className={filter === 'Waiting' ? 'text-primary-foreground text-sm font-medium' : 'text-muted-foreground text-sm'}>
|
|
{filter}
|
|
</Text>
|
|
</View>
|
|
))}
|
|
</View>
|
|
|
|
<Text className="text-muted-foreground mb-2 text-sm">Today</Text>
|
|
{MOCK_INVOICES.filter((i) => i.status === 'Waiting').map((inv) => (
|
|
<Card key={inv.id} className="mb-2">
|
|
<CardContent className="flex-row items-center justify-between py-3">
|
|
<View className="flex-1">
|
|
<Text className="font-semibold text-gray-900">{inv.recipient}</Text>
|
|
<Text className="text-muted-foreground text-sm">Invoice #{inv.invoiceNumber} - Due {inv.dueDate}</Text>
|
|
</View>
|
|
<View className="items-end">
|
|
<Text className="font-semibold text-gray-900">${inv.amount.toLocaleString()}</Text>
|
|
<View className={`mt-1 rounded-full px-2 py-0.5 ${statusColor[inv.status]}`}>
|
|
<Text className="text-xs font-medium">{inv.status}</Text>
|
|
</View>
|
|
</View>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
|
|
<Text className="text-muted-foreground mb-2 mt-4 text-sm">Yesterday</Text>
|
|
{MOCK_INVOICES.filter((i) => i.status === 'Paid').map((inv) => (
|
|
<Card key={inv.id} className="mb-2">
|
|
<CardContent className="flex-row items-center justify-between py-3">
|
|
<View className="flex-1">
|
|
<Text className="font-semibold text-gray-900">{inv.recipient}</Text>
|
|
<Text className="text-muted-foreground text-sm">Invoice #{inv.invoiceNumber} - {inv.dueDate}</Text>
|
|
</View>
|
|
<View className="items-end">
|
|
<Text className="font-semibold text-gray-900">${inv.amount.toLocaleString()}</Text>
|
|
<View className={`mt-1 rounded-full px-2 py-0.5 ${statusColor[inv.status]}`}>
|
|
<Text className="text-xs font-medium">{inv.status}</Text>
|
|
</View>
|
|
</View>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</ScrollView>
|
|
);
|
|
}
|