import { useState } from "react"; import { useLocation } from "wouter"; import { trpc } from "@/lib/trpc"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { toast } from "sonner"; import { Building2, Clock, QrCode, CheckCircle2, ChevronRight, ChevronLeft, Stethoscope, Loader2 } from "lucide-react"; const STEPS = [ { id: 1, title: "Votre cabinet", description: "Commençons par les informations de base de votre cabinet médical.", icon: Building2, }, { id: 2, title: "Paramètres de la file", description: "Configurez le comportement de votre salle d'attente virtuelle.", icon: Clock, }, { id: 3, title: "Votre QR code est prêt", description: "Tout est configuré ! Voici comment démarrer.", icon: QrCode, }, ]; export default function Onboarding() { const [, navigate] = useLocation(); const [step, setStep] = useState(1); const [clinicId, setClinicId] = useState(null); // Form state const [name, setName] = useState(""); const [address, setAddress] = useState(""); const [phone, setPhone] = useState(""); const [avgConsultation, setAvgConsultation] = useState(15); const [maxQueue, setMaxQueue] = useState(30); const [qrRotation, setQrRotation] = useState(60); const createClinic = trpc.clinic.create.useMutation({ onSuccess: (data) => { setClinicId(data.id); setStep(3); toast.success("Cabinet créé avec succès !"); }, onError: (e) => toast.error(e.message), }); const handleNext = () => { if (step === 1) { if (!name.trim()) { toast.error("Le nom du cabinet est requis."); return; } setStep(2); } else if (step === 2) { createClinic.mutate({ name: name.trim(), address: address.trim() || undefined, phone: phone.trim() || undefined, avgConsultationMinutes: avgConsultation, maxQueueSize: maxQueue, qrRotationMinutes: qrRotation, }); } }; const currentStep = STEPS.find(s => s.id === step)!; const StepIcon = currentStep.icon; return (
{/* Background blobs */}
{/* Header */}
QueueMed

Configuration initiale

Configurez votre premier cabinet en 2 minutes

{/* Step indicators */}
{STEPS.map((s, i) => (
{s.id < step ? : s.id}
{i < STEPS.length - 1 && (
)}
))}
{/* Card */}
{/* Step header */}

{currentStep.title}

{currentStep.description}

{/* Step 1 — Cabinet info */} {step === 1 && (
setName(e.target.value)} className="bg-muted/50 border-border/60 focus:border-primary" onKeyDown={e => e.key === "Enter" && handleNext()} />
setAddress(e.target.value)} className="bg-muted/50 border-border/60 focus:border-primary" />
setPhone(e.target.value)} className="bg-muted/50 border-border/60 focus:border-primary" />
)} {/* Step 2 — Queue settings */} {step === 2 && (
setAvgConsultation(Number(e.target.value))} className="flex-1 accent-primary" /> {avgConsultation} min

Utilisé pour estimer le temps d'attente des patients.

setMaxQueue(Number(e.target.value))} className="flex-1 accent-primary" /> {maxQueue} patients

Au-delà, les nouveaux patients ne peuvent plus rejoindre.

{[0, 30, 60, 120, 240].map(v => ( ))}

Le QR code change de token automatiquement pour éviter les partages frauduleux.

)} {/* Step 3 — Success */} {step === 3 && (

Cabinet créé !

Votre cabinet "{name}" est configuré. Voici les prochaines étapes pour démarrer.

{[ { num: "1", text: "Imprimez ou affichez le QR code à l'accueil", color: "text-primary" }, { num: "2", text: "Ouvrez la file d'attente depuis le tableau de bord", color: "text-primary" }, { num: "3", text: "Configurez l'écran d'affichage sur votre tablette", color: "text-primary" }, ].map(item => (
{item.num} {item.text}
))}
)} {/* Actions */}
{step > 1 && step < 3 && ( )} {step < 3 ? ( ) : (
)}
{/* Skip link */} {step < 3 && (

)}
); }