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"}
)}
)}
);
}