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 { useTheme } from "../../context/ThemeContext"; import { shadows } from "../../theme/shadows"; import { useAuth } from "../../auth/AuthContext"; import { getCabineCommands, getAllDeliveryPersonsWithDetails, getCabineTelegramStatus, generateCabineLinkToken, unlinkCabineTelegram, } from "../../api/api_cabine"; import LoadingSpinner from "../../components/ui/LoadingSpinner"; export default function DashboardScreen() { const { colors } = useTheme(); const { username } = useAuth(); const { width: screenWidth } = useWindowDimensions(); const [tgLinked, setTgLinked] = useState(false); const [tgEnabled, setTgEnabled] = useState(false); const [tgLoading, setTgLoading] = useState(false); const [stats, setStats] = useState< Array<{ label: string; value: number; icon: keyof typeof Ionicons.glyphMap; color: string; }> >([]); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const loadStats = useCallback(async () => { try { const [allCmd, livreursRes] = await Promise.all([ getCabineCommands(), getAllDeliveryPersonsWithDetails(), ]); const cmds = allCmd.commands; setStats([ { label: "Commandes actives", value: cmds.filter( (c: any) => !["approved", "cancelled"].includes(c.status), ).length, icon: "receipt-outline", color: colors.info, }, { label: "En route", value: cmds.filter((c: any) => c.status === "en_route") .length, icon: "navigate-outline", color: colors.warning, }, { label: "En attente", value: cmds.filter((c: any) => c.status === "pending") .length, icon: "time-outline", color: colors.accent, }, { label: "Livreurs dispo", value: livreursRes.stats.available, icon: "bicycle-outline", color: colors.success, }, { label: "Livreurs occupés", value: livreursRes.stats.busy, icon: "bicycle", color: colors.warning, }, { label: "Total terminées", value: cmds.filter((c: any) => c.status === "approved") .length, icon: "checkmark-circle-outline", color: colors.successDark, }, ]); } catch { /* ignore */ } setLoading(false); }, [colors]); useEffect(() => { loadStats(); getCabineTelegramStatus().then((s) => { setTgLinked(s.linked); setTgEnabled(s.enabled); }); }, [loadStats]); const handleLinkTelegram = async () => { setTgLoading(true); const res = await generateCabineLinkToken(); 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 unlinkCabineTelegram(); 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 ( } > Cabine - {username} Suivi des opérations {stats.map((s, i) => ( {s.value} {s.label} ))} {tgEnabled && ( Notifications Telegram {tgLinked ? ( Compte Telegram lié Délier Telegram ) : ( {tgLoading ? "Génération..." : "Lier Telegram"} )} )} ); }