import { useAuth } from "@/_core/hooks/useAuth"; import { trpc } from "@/lib/trpc"; import { Button } from "@/components/ui/button"; import { useLocation } from "wouter"; import { getLoginUrl } from "@/const"; import { Users, Building2, BarChart3, CreditCard, ChevronRight, Clock, TrendingUp, Activity, Plus, LogOut, Loader2, HelpCircle, Sparkles, QrCode } from "lucide-react"; export default function Dashboard() { const { user, isAuthenticated, loading, logout } = useAuth(); const [, navigate] = useLocation(); const clinicsQuery = trpc.clinic.list.useQuery(undefined, { enabled: isAuthenticated }); const subQuery = trpc.subscription.get.useQuery(undefined, { enabled: isAuthenticated }); const analyticsQuery = trpc.analytics.getAll.useQuery({ days: 7 }, { enabled: isAuthenticated }); if (loading) { return (
); } if (!isAuthenticated) { return (

Espace Médecin

Connectez-vous pour accéder à votre tableau de bord.

); } const sub = subQuery.data; const clinics = clinicsQuery.data ?? []; const analytics = analyticsQuery.data ?? []; const totalPatients = analytics.reduce((sum, a) => sum + a.totalPatients, 0); const avgWait = analytics.length > 0 ? Math.round(analytics.reduce((sum, a) => sum + a.avgWait, 0) / analytics.length) : 0; const isTrialing = sub?.status === "trialing"; const trialDaysLeft = sub?.trialEndsAt ? Math.max(0, Math.ceil((new Date(sub.trialEndsAt).getTime() - Date.now()) / 86400000)) : 0; return (
{/* Background */}
{/* Header */}
QueueMed
{user?.name}
{/* Welcome + trial banner */}

Bonjour, {user?.name?.split(" ")[0] ?? "Docteur"}

Gérez vos files d'attente en temps réel

{isTrialing && (
7 ? "bg-teal-500/10 border-teal-500/30 text-teal-300" : "bg-amber-500/10 border-amber-500/30 text-amber-300"}`}> {trialDaysLeft > 0 ? `Essai gratuit : ${trialDaysLeft} jour${trialDaysLeft > 1 ? "s" : ""} restant${trialDaysLeft > 1 ? "s" : ""}` : "Essai expiré"} {trialDaysLeft <= 7 && ( )}
)}
{/* Stats */}
{[ { label: "Cabinets actifs", value: clinics.length, icon: Building2, color: "text-teal-400" }, { label: "Patients (7j)", value: totalPatients, icon: Users, color: "text-orange-400" }, { label: "Attente moy.", value: `${avgWait} min`, icon: Clock, color: "text-cyan-400" }, { label: "Plan", value: sub?.plan ?? "—", icon: CreditCard, color: "text-violet-400" }, ].map((stat) => (
{stat.value}
{stat.label}
))}
{/* Clinics quick access */}

Vos cabinets

{clinicsQuery.isLoading ? (
) : clinics.length === 0 ? (

Bienvenue sur QueueMed !

Configurez votre premier cabinet en 2 minutes avec notre assistant de démarrage.

) : (
{clinics.map((clinic) => (
navigate(`/dashboard/queue/${clinic.id}`)}>
{clinic.isQueueOpen ? "Ouvert" : "Fermé"}

{clinic.name}

{clinic.address &&

{clinic.address}

}
~{clinic.avgConsultationMinutes} min/patient
))}
)}
{/* Quick links */}
{[ { icon: BarChart3, label: "Analytics", desc: "Statistiques et prédictions", path: "/dashboard/analytics", color: "text-pink-400" }, { icon: TrendingUp, label: "Abonnement", desc: "Gérer votre plan", path: "/dashboard/subscription", color: "text-violet-400" }, { icon: Activity, label: "Affichage", desc: "Écran salle d'attente", path: clinics[0] ? `/display/${clinics[0].id}` : "/dashboard", color: "text-cyan-400" }, { icon: HelpCircle, label: "Aide", desc: "Centre d'aide & FAQ", path: "/help", color: "text-amber-400" }, ].map((item) => ( ))}
); }