import React, { useState, useEffect, useCallback, useMemo } from "react"; import { View, Text, StyleSheet, ScrollView, RefreshControl, TouchableOpacity, Linking, Alert, useWindowDimensions, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { spacing, fontSize, borderRadius } from "../../theme"; import { shadows } from "../../theme/shadows"; import { useTheme } from "../../context/ThemeContext"; import { useAuth } from "../../auth/AuthContext"; import { getAllCommands, getAllClients, getAvailableDeliveryPersons, getCommandCountByStatus, getAdminTelegramStatus, generateAdminLinkToken, unlinkAdminTelegram, } from "../../api/api_admin"; import LoadingSpinner from "../../components/ui/LoadingSpinner"; interface StatCard { label: string; value: number; icon: keyof typeof Ionicons.glyphMap; color: string; } export default function DashboardScreen() { const { colors } = useTheme(); const { username } = useAuth(); const { width: screenWidth } = useWindowDimensions(); const [stats, setStats] = useState([]); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const [tgLinked, setTgLinked] = useState(false); const [tgEnabled, setTgEnabled] = useState(false); const [tgLoading, setTgLoading] = useState(false); const loadStats = useCallback(async () => { try { const [allCmd, pending, enRoute, completed, clients, livreurs] = await Promise.all([ getAllCommands().then((r) => r.count), getCommandCountByStatus("pending"), getCommandCountByStatus("en_route"), getCommandCountByStatus("approved"), getAllClients() .then((c) => c.length) .catch(() => 0), getAvailableDeliveryPersons() .then((r) => r.count) .catch(() => 0), ]); setStats([ { label: "Total commandes", value: allCmd, icon: "receipt-outline", color: colors.accent, }, { label: "En attente", value: pending, icon: "time-outline", color: colors.warning, }, { label: "En route", value: enRoute, icon: "navigate-outline", color: colors.info, }, { label: "Terminées", value: completed, icon: "checkmark-circle-outline", color: colors.success, }, { label: "Clients", value: clients, icon: "people-outline", color: colors.accentLight, }, { label: "Livreurs", value: livreurs, icon: "bicycle-outline", color: colors.categoryGros, }, ]); } catch { /* ignore */ } setLoading(false); }, [colors]); useEffect(() => { loadStats(); getAdminTelegramStatus().then((s) => { setTgLinked(s.linked); setTgEnabled(s.enabled); }); }, [loadStats]); const handleLinkTelegram = async () => { setTgLoading(true); const res = await generateAdminLinkToken(); setTgLoading(false); if (res.error || !res.link_url) { Alert.alert("Erreur", res.error || "Service Telegram non disponible"); return; } Linking.openURL(res.link_url); }; const handleUnlinkTelegram = () => { Alert.alert("Délier Telegram", "Vous ne recevrez plus de notifications Telegram.", [ { text: "Annuler", style: "cancel" }, { text: "Délier", style: "destructive", onPress: async () => { await unlinkAdminTelegram(); setTgLinked(false); } }, ]); }; const onRefresh = async () => { setRefreshing(true); await loadStats(); setRefreshing(false); }; const styles = useMemo( () => StyleSheet.create({ container: { flex: 1, backgroundColor: colors.bgPrimary, padding: screenWidth < 380 ? spacing.m : spacing.l, }, welcome: { fontSize: screenWidth < 380 ? fontSize.lg : fontSize.xl, fontWeight: "bold", color: colors.textWhite, marginBottom: spacing.xs, }, subtitle: { fontSize: screenWidth < 380 ? fontSize.sm : fontSize.md, color: colors.textSecondary, marginBottom: spacing.l, }, grid: { flexDirection: "row", flexWrap: "wrap", gap: screenWidth < 380 ? spacing.s : spacing.m, }, card: { width: screenWidth < 360 ? "100%" : "47%", backgroundColor: colors.bgCard, borderRadius: borderRadius.md, padding: screenWidth < 380 ? spacing.m : spacing.l, borderWidth: 1, borderColor: colors.borderLight, alignItems: "center", }, iconCircle: { width: screenWidth < 380 ? 40 : 48, height: screenWidth < 380 ? 40 : 48, borderRadius: screenWidth < 380 ? 20 : 24, justifyContent: "center", alignItems: "center", marginBottom: spacing.s, }, cardValue: { fontSize: screenWidth < 380 ? fontSize.xl : fontSize.xxl, fontWeight: "bold", color: colors.textWhite, }, cardLabel: { fontSize: screenWidth < 380 ? fontSize.xs : fontSize.sm, color: colors.textSecondary, marginTop: spacing.xs, textAlign: "center", }, }), [colors, screenWidth], ); if (loading) return ; return ( } > Bonjour, {username} Vue d'ensemble {stats.map((s, i) => ( {s.value} {s.label} ))} {tgEnabled && ( Notifications Telegram {tgLinked ? ( Compte Telegram lié Délier Telegram ) : ( {tgLoading ? "Génération..." : "Lier Telegram"} )} )} ); }