import { useState, useEffect, useCallback } from "react"; import { useNavigate } from "react-router-dom"; import { User, Shield, Truck, Store, Search, XCircle, Phone, TrendingUp, AlertCircle, Filter, Eye, Leaf, Wind, } from "lucide-react"; import "./UserManagement.css"; import SidebarCabine from "../../components/SidebarCabine"; import { getAllUsers, getAllClients } from "../../api/api_admin"; import { isCabineAuthenticated } from "../../api/api_cabine"; // ⭐ AJOUT import type { AdminResponse } from "../../api/api_admin_types"; import type { ClientResponse } from "../../api/api_admin"; // ============================================ // TYPES & INTERFACES // ============================================ interface UserStats { totalUsers: number; totalCabines: number; totalLivreurs: number; } type UserRole = "admin" | "cabine" | "livreur" | "client"; type RoleFilter = "all" | "cabine" | "livreur"; interface RoleConfig { color: string; label: string; icon: React.ComponentType<{ size: number }>; } // ============================================ // CONSTANTS // ============================================ const ROLE_CONFIG: Record = { admin: { color: "red", label: "Administrateur", icon: Shield }, cabine: { color: "purple", label: "Cabine", icon: Store }, livreur: { color: "blue", label: "Livreur", icon: Truck }, client: { color: "green", label: "Client", icon: User }, }; // ============================================ // MAIN COMPONENT // ============================================ function UsersManagement() { const navigate = useNavigate(); // État des utilisateurs const [users, setUsers] = useState([]); const [filteredUsers, setFilteredUsers] = useState([]); const [stats, setStats] = useState({ totalUsers: 0, totalCabines: 0, totalLivreurs: 0, }); // État des clients const [clients, setClients] = useState([]); const [filteredClients, setFilteredClients] = useState( [], ); const [totalClients, setTotalClients] = useState(0); // État des filtres et recherche const [searchTerm, setSearchTerm] = useState(""); const [clientSearchTerm, setClientSearchTerm] = useState(""); const [roleFilter, setRoleFilter] = useState("all"); // État du modal const [selectedClient, setSelectedClient] = useState( null, ); const [showClientModal, setShowClientModal] = useState(false); // État de chargement const [loading, setLoading] = useState(true); // ============================================ // 🔐 VÉRIFICATION INITIALE DE L'AUTHENTIFICATION // ============================================ useEffect(() => { const checkAuth = () => { if (!isCabineAuthenticated()) { console.log( "❌ [UserManagement] Cabine non authentifié, redirection vers /login-cabine/cabine", ); navigate("/login-cabine/cabine", { replace: true }); } }; checkAuth(); }, [navigate]); // ============================================ // 🔐 VÉRIFICATION CONTINUE (toutes les 5 secondes) // ============================================ useEffect(() => { const authInterval = setInterval(() => { if (!isCabineAuthenticated()) { console.log( "❌ [UserManagement] Session cabine expirée, redirection vers /login-cabine/cabine", ); navigate("/login-cabine/cabine", { replace: true }); } }, 5000); return () => clearInterval(authInterval); }, [navigate]); // ============================================ // FETCH DATA // ============================================ const fetchUsers = useCallback(async () => { // ✅ Vérifier l'auth avant de charger if (!isCabineAuthenticated()) { console.log("❌ [fetchUsers] Cabine non authentifié"); navigate("/login-cabine/cabine", { replace: true }); return; } try { console.log("👥 [USERS_MANAGEMENT] Chargement des utilisateurs..."); setLoading(true); const usersData = await getAllUsers(); console.log( "✅ [USERS_MANAGEMENT] Utilisateurs récupérés:", usersData, ); // Exclure les admins de la liste const filteredUsersData = usersData.filter( (u) => u.role !== "admin", ); setUsers(filteredUsersData); // Calculer les statistiques const newStats: UserStats = { totalUsers: filteredUsersData.length, totalCabines: filteredUsersData.filter( (u) => u.role === "cabine", ).length, totalLivreurs: filteredUsersData.filter( (u) => u.role === "livreur", ).length, }; setStats(newStats); console.log("📊 [USERS_MANAGEMENT] Stats:", newStats); } catch (error) { console.error("❌ [USERS_MANAGEMENT] Erreur chargement:", error); if (error instanceof Error && error.message.includes("401")) { console.log("🔓 [UserManagement] Token invalide"); sessionStorage.removeItem("admin_token"); sessionStorage.removeItem("admin_username"); navigate("/login-cabine/cabine", { replace: true }); return; } alert("Erreur lors du chargement des utilisateurs"); } finally { setLoading(false); } }, [navigate]); const fetchClients = useCallback(async () => { // ✅ Vérifier l'auth avant de charger if (!isCabineAuthenticated()) { console.log("❌ [fetchClients] Cabine non authentifié"); navigate("/login-cabine/cabine", { replace: true }); return; } try { console.log("👥 [CLIENTS_MANAGEMENT] Chargement des clients..."); setLoading(true); const clientData = await getAllClients(); console.log( "✅ [CLIENTS_MANAGEMENT] Clients récupérés:", clientData, ); if (clientData && clientData.length > 0) { const firstClient = clientData[0]; console.log("🔍 [DEBUG] Premier client:", { username: firstClient.username, points_weed: firstClient.point, points_zipette: firstClient.points_zipette, }); } setClients(clientData); setTotalClients(clientData.length); } catch (error) { console.error("❌ [CLIENTS_MANAGEMENT] Erreur:", error); if (error instanceof Error && error.message.includes("401")) { console.log("🔓 [UserManagement] Token invalide"); sessionStorage.removeItem("admin_token"); sessionStorage.removeItem("admin_username"); navigate("/login-cabine/cabine", { replace: true }); return; } alert("Erreur lors du chargement des clients"); } finally { setLoading(false); } }, [navigate]); // ============================================ // FILTERS // ============================================ const filterUsers = useCallback(() => { let filtered = [...users]; if (searchTerm) { filtered = filtered.filter((user) => user.username.toLowerCase().includes(searchTerm.toLowerCase()), ); } if (roleFilter !== "all") { filtered = filtered.filter((user) => user.role === roleFilter); } setFilteredUsers(filtered); }, [users, searchTerm, roleFilter]); const filterClients = useCallback(() => { let filtered = [...clients]; if (clientSearchTerm) { const searchLower = clientSearchTerm.toLowerCase(); filtered = filtered.filter( (client) => client.nom.toLowerCase().includes(searchLower) || client.prenom.toLowerCase().includes(searchLower) || client.username.toLowerCase().includes(searchLower) || client.telephone.includes(clientSearchTerm), ); } setFilteredClients(filtered); }, [clients, clientSearchTerm]); // ============================================ // HANDLERS // ============================================ const handleViewClient = useCallback((client: ClientResponse) => { setSelectedClient(client); setShowClientModal(true); }, []); const handleCloseModal = useCallback(() => { setShowClientModal(false); setSelectedClient(null); }, []); const handleRoleFilterChange = useCallback((filter: RoleFilter) => { setRoleFilter(filter); }, []); // ============================================ // EFFECTS // ============================================ useEffect(() => { fetchUsers(); fetchClients(); }, [fetchUsers, fetchClients]); useEffect(() => { filterUsers(); }, [filterUsers]); useEffect(() => { filterClients(); }, [filterClients]); // ============================================ // RENDER HELPERS // ============================================ const getRoleConfig = (role: string): RoleConfig => { return ROLE_CONFIG[role as UserRole] || ROLE_CONFIG.client; }; const getRoleIcon = (role: string): React.ReactElement => { const config = getRoleConfig(role); const IconComponent = config.icon; return ; }; // ============================================ // LOADING STATE // ============================================ if (loading) { return (

Chargement des utilisateurs...

); } // ============================================ // MAIN RENDER // ============================================ return ( <>
{showClientModal && selectedClient && ( )}
); } // ============================================ // SUB-COMPONENTS (identiques à l'original) // ============================================ function Header() { return (

Gestion des Utilisateurs

Visualiser et gérer tous les comptes système

); } interface StatsGridProps { stats: UserStats; totalClients: number; } function StatsGrid({ stats, totalClients }: StatsGridProps) { const statsCards = [ { icon: User, color: "blue", label: "Total Utilisateurs", value: stats.totalUsers, }, { icon: Store, color: "purple", label: "Cabines", value: stats.totalCabines, }, { icon: Truck, color: "blue", label: "Livreurs", value: stats.totalLivreurs, }, { icon: User, color: "green", label: "Clients", value: totalClients, }, ]; return (
{statsCards.map((card, index) => ( ))}
); } interface StatCardProps { icon: React.ComponentType<{ size: number }>; color: string; label: string; value: number; } function StatCard({ icon: Icon, color, label, value }: StatCardProps) { return (

{label}

{value}

); } interface FiltersSectionProps { searchTerm: string; setSearchTerm: (term: string) => void; roleFilter: RoleFilter; onRoleFilterChange: (filter: RoleFilter) => void; stats: UserStats; usersCount: number; } function FiltersSection({ searchTerm, setSearchTerm, roleFilter, onRoleFilterChange, stats, usersCount, }: FiltersSectionProps) { const filters = [ { value: "all" as RoleFilter, icon: Filter, label: "Tous", count: usersCount, }, { value: "cabine" as RoleFilter, icon: Store, label: "Cabines", count: stats.totalCabines, }, { value: "livreur" as RoleFilter, icon: Truck, label: "Livreurs", count: stats.totalLivreurs, }, ]; return (
setSearchTerm(e.target.value)} />
{filters.map((filter) => { const IconComponent = filter.icon; return ( ); })}
); } interface UsersListProps { filteredUsers: AdminResponse[]; getRoleIcon: (role: string) => React.ReactElement; getRoleConfig: (role: string) => RoleConfig; } function UsersList({ filteredUsers, getRoleIcon, getRoleConfig, }: UsersListProps) { return (

Utilisateurs Système ({filteredUsers.length})

{filteredUsers.length === 0 ? ( ) : ( filteredUsers.map((user) => ( )) )}
); } interface UserCardProps { user: AdminResponse; getRoleIcon: (role: string) => React.ReactElement; getRoleConfig: (role: string) => RoleConfig; } function UserCard({ user, getRoleIcon, getRoleConfig }: UserCardProps) { const roleConfig = getRoleConfig(user.role); return (
{getRoleIcon(user.role)}
{user.username} ID: {user.id}
{getRoleIcon(user.role)} {roleConfig.label}
); } interface ClientsSectionProps { clients: ClientResponse[]; filteredClients: ClientResponse[]; clientSearchTerm: string; setClientSearchTerm: (term: string) => void; onViewClient: (client: ClientResponse) => void; } function ClientsSection({ clients, filteredClients, clientSearchTerm, setClientSearchTerm, onViewClient, }: ClientsSectionProps) { return (

Clients Enregistrés ({clients.length})

setClientSearchTerm(e.target.value)} />
{filteredClients.length === 0 ? ( ) : ( filteredClients.map((client) => ( )) )}
); } interface ClientCardProps { client: ClientResponse; onViewClient: (client: ClientResponse) => void; } function ClientCard({ client, onViewClient }: ClientCardProps) { return (
{client.prenom} {client.nom} @{client.username}
Client
1 ? "s" : ""}`} />
); } interface InfoItemProps { icon: React.ComponentType<{ size: number }>; text: string; } function InfoItem({ icon: Icon, text }: InfoItemProps) { return (
{text}
); } interface ClientModalProps { client: ClientResponse; onClose: () => void; } function ClientModal({ client, onClose }: ClientModalProps) { const handleBackdropClick = (e: React.MouseEvent) => { if (e.target === e.currentTarget) { onClose(); } }; return (
e.stopPropagation()} >

Détails du Client

1 ? "s" : ""}`} /> {client.last_penalty_reason && ( )}
); } interface DetailSectionProps { title: string; children: React.ReactNode; } function DetailSection({ title, children }: DetailSectionProps) { return (

{title}

{children}
); } interface DetailItemProps { icon: React.ComponentType<{ size: number }>; label: string; value: string; fullWidth?: boolean; } function DetailItem({ icon: Icon, label, value, fullWidth }: DetailItemProps) { return (

{value}

); } interface EmptyStateProps { icon: React.ComponentType<{ size: number }>; title: string; message: string; } function EmptyState({ icon: Icon, title, message }: EmptyStateProps) { return (

{title}

{message}

); } export default UsersManagement;