66 lines
2.8 KiB
TypeScript
66 lines
2.8 KiB
TypeScript
import { View, Text, ScrollView, RefreshControl, ActivityIndicator } from 'react-native';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { api } from '../../services/api';
|
|
import { useAuthStore } from '../../stores/authStore';
|
|
|
|
function KpiCard({ label, value, color }: { label: string; value: string | number; color: string }) {
|
|
return (
|
|
<View className="bg-white rounded-2xl p-4 flex-1 mx-1 shadow-sm border border-gray-100">
|
|
<Text className="text-gray-500 text-xs mb-1">{label}</Text>
|
|
<Text className={`text-2xl font-bold`} style={{ color }}>{value}</Text>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
export default function DashboardScreen() {
|
|
const { user } = useAuthStore();
|
|
const { data, isLoading, refetch, isRefetching } = useQuery({
|
|
queryKey: ['dashboard'],
|
|
queryFn: () => api.get('/api/v1/dashboard/summary').then(r => r.data),
|
|
});
|
|
|
|
return (
|
|
<ScrollView
|
|
className="flex-1 bg-gray-50"
|
|
refreshControl={<RefreshControl refreshing={isRefetching} onRefresh={refetch} />}
|
|
>
|
|
<View className="px-4 pt-14 pb-4 bg-primary">
|
|
<Text className="text-white text-sm opacity-80">Welcome back,</Text>
|
|
<Text className="text-white text-xl font-bold">{user?.firstName ?? 'Field Staff'}</Text>
|
|
</View>
|
|
|
|
{isLoading ? (
|
|
<View className="flex-1 items-center justify-center py-20">
|
|
<ActivityIndicator color="#2563EB" />
|
|
</View>
|
|
) : (
|
|
<View className="px-3 py-4">
|
|
<Text className="text-gray-700 font-semibold mb-3 px-1">Overview</Text>
|
|
<View className="flex-row mb-3">
|
|
<KpiCard label="Total Clients" value={data?.totalClients ?? 0} color="#2563EB" />
|
|
<KpiCard label="Active Subs" value={data?.activeSubscriptions ?? 0} color="#16A34A" />
|
|
</View>
|
|
<View className="flex-row mb-6">
|
|
<KpiCard label="Overdue" value={data?.overdueInvoices ?? 0} color="#DC2626" />
|
|
<KpiCard label="Today Collections" value={`₱${(data?.todayCollections ?? 0).toLocaleString()}`} color="#D97706" />
|
|
</View>
|
|
|
|
<Text className="text-gray-700 font-semibold mb-3 px-1">Recent Tickets</Text>
|
|
{(data?.recentTickets ?? []).length === 0 ? (
|
|
<View className="bg-white rounded-2xl p-6 items-center border border-gray-100">
|
|
<Text className="text-gray-400">No recent tickets</Text>
|
|
</View>
|
|
) : (
|
|
(data?.recentTickets ?? []).map((t: any) => (
|
|
<View key={t.id} className="bg-white rounded-xl p-4 mb-2 border border-gray-100">
|
|
<Text className="font-medium text-gray-900">{t.subject}</Text>
|
|
<Text className="text-gray-500 text-sm mt-1">{t.clientName} · {t.status}</Text>
|
|
</View>
|
|
))
|
|
)}
|
|
</View>
|
|
)}
|
|
</ScrollView>
|
|
);
|
|
}
|