import React, { useState } from 'react'; import { Shield, Users, Phone, ChevronRight, ChevronLeft, Check, Eye, BarChart3, User, Home, LogOut, Bell, Plus, X, Star, Lock, Stethoscope, ClipboardList, Building, ArrowRight, ArrowUp, ArrowDown, MessageCircle, ChevronDown, Menu, Sparkles, FileText, Database, Code, Download, AlertTriangle, CheckCircle, Clock, Info, Scale, FileCheck, ShieldCheck, Globe, BookOpen, ExternalLink, Filter, Search, Settings, UserCog, Award, Activity, Trash2, Edit, UserPlus } from 'lucide-react'; // === DONNÉES === const ratings = { outstanding: { label: 'Exemplaire', bg: 'bg-emerald-500', text: 'text-emerald-600', light: 'bg-emerald-50', stars: 5 }, good: { label: 'Satisfaisant', bg: 'bg-teal-500', text: 'text-teal-600', light: 'bg-teal-50', stars: 4 }, requires_improvement: { label: 'À améliorer', bg: 'bg-amber-500', text: 'text-amber-600', light: 'bg-amber-50', stars: 3 }, inadequate: { label: 'Insuffisant', bg: 'bg-rose-500', text: 'text-rose-600', light: 'bg-rose-50', stars: 2 }, }; const institutions = [ { id: 1, name: 'HUG', fullName: 'Hôpitaux Universitaires de Genève', type: 'Hôpital universitaire', city: 'Genève', rating: 'good', reports: 89, verified: 71, contested: 3, avgDays: 3.8, trend: 'up', reliability: 94 }, { id: 2, name: 'CHUV', fullName: 'Centre Hospitalier Universitaire Vaudois', type: 'Hôpital universitaire', city: 'Lausanne', rating: 'good', reports: 56, verified: 48, contested: 1, avgDays: 4.2, trend: 'stable', reliability: 96 }, { id: 3, name: 'Hôpital de la Tour', fullName: 'Hôpital de la Tour', type: 'Clinique privée', city: 'Meyrin', rating: 'outstanding', reports: 12, verified: 11, contested: 0, avgDays: 2.1, trend: 'up', reliability: 98 }, { id: 4, name: 'Unisanté', fullName: 'Unisanté', type: 'Centre universitaire', city: 'Lausanne', rating: 'outstanding', reports: 23, verified: 21, contested: 0, avgDays: 2.8, trend: 'up', reliability: 97 }, { id: 5, name: 'Hôpital du Valais', fullName: 'Hôpital du Valais - Sion', type: 'Hôpital cantonal', city: 'Sion', rating: 'requires_improvement', reports: 34, verified: 22, contested: 5, avgDays: 6.2, trend: 'down', reliability: 85 }, { id: 6, name: 'Hôpital Riviera-Chablais', fullName: 'Hôpital Riviera-Chablais', type: 'Hôpital régional', city: 'Rennaz', rating: 'inadequate', reports: 67, verified: 28, contested: 12, avgDays: 9.4, trend: 'down', reliability: 78 }, ]; const dmsQuestions = [ { id: 1, text: "On vous traite avec moins de courtoisie que les autres personnes.", category: 'respect' }, { id: 2, text: "On vous traite avec moins de respect que les autres personnes.", category: 'respect' }, { id: 3, text: "Vous recevez un service de moins bonne qualité que les autres.", category: 'equity' }, { id: 4, text: "Un médecin ou une infirmière agit comme s'il ou elle pensait que vous n'étiez pas intelligent(e).", category: 'stereotypes' }, { id: 5, text: "Un médecin ou une infirmière agit comme s'il ou elle avait peur de vous.", category: 'stereotypes' }, { id: 6, text: "Un médecin ou une infirmière agit comme s'il ou elle était supérieur(e) à vous.", category: 'respect' }, { id: 7, text: "Vous avez l'impression qu'un médecin ou une infirmière n'écoute pas ce que vous dites.", category: 'listening' }, ]; const incidentTypes = [ 'Propos discriminatoires ou racistes', 'Refus de soins injustifié', 'Traitement différencié', 'Moqueries ou remarques déplacées', 'Attitude condescendante', 'Manque de respect', 'Non-écoute ou minimisation des symptômes', 'Stéréotypes ou préjugés', 'Temps d\'attente excessif', 'Autre' ]; const services = [ 'Urgences', 'Consultation externe', 'Hospitalisation', 'Maternité', 'Pédiatrie', 'Chirurgie', 'Radiologie', 'Laboratoire', 'Accueil', 'Psychiatrie', 'Oncologie', 'Hématologie', 'Cardiologie', 'Gynécologie', 'Neurologie', 'Médecine interne', 'Gériatrie', 'Autre' ]; const resourceOrgs = [ { id: 1, name: 'FAANG', fullName: 'Fédération des Associations Afrodescendant.e.x.s de Genève', services: ['Médiation', 'Accompagnement'], phone: '+41 22 301 16 50' }, { id: 2, name: 'ASPR-GE', fullName: 'Association des Professionnel·le·s de Santé Racisé·e·s de Genève', services: ['Pair-aidance', 'Formation'], phone: '+41 78 xxx xx xx' }, { id: 3, name: 'Suisse Drépano', fullName: 'Association Suisse Drépanocytose', services: ['Soutien patients', 'Advocacy'], phone: '+41 79 128 63 68' }, { id: 4, name: 'Centre LAVI', fullName: 'Centre de consultation pour victimes', services: ['Aide juridique', 'Soutien'], phone: '+41 22 320 01 02' }, ]; const healthcarePros = [ { id: 1, name: 'Dr. Aminata Koné', specialty: 'Médecine générale', institution: 'HUG', languages: ['Français', 'Bambara'], rating: 4.8 }, { id: 2, name: 'Dr. Jean-Pierre Müller', specialty: 'Hématologie', institution: 'CHUV', languages: ['Français', 'Allemand'], rating: 4.9 }, { id: 3, name: 'Sophie Ndongo', specialty: 'Infirmière spécialisée', institution: 'Unisanté', languages: ['Français', 'Wolof'], rating: 4.7 }, ]; const stats = { total: 318, verified: 251, avgDays: 4.1, institutions: 6, reliability: 89 }; // === COMPOSANTS UTILITAIRES === const RatingBadge = ({ r, size = 'sm' }) => { const rt = ratings[r]; const sizes = { xs: 'px-1.5 py-0.5 text-xs', sm: 'px-2 py-1 text-xs', md: 'px-3 py-1.5 text-sm' }; return {rt.label}; }; const Stars = ({ r }) => { const rt = ratings[r]; return (
{[...Array(5)].map((_, i) => ( ))}
); }; const ReliabilityBadge = ({ score }) => { const color = score >= 90 ? 'emerald' : score >= 75 ? 'amber' : 'rose'; return (
{score}% fiable
); }; // === COMPOSANT FORMULAIRE SIGNALEMENT (EXTRAIT) === const NewReportForm = ({ step, setStep, data, setData, dmsAnswers, setDmsAnswers, onSubmit, onComplete }) => { const steps = ['Vérification', 'Rôle', 'Lieu', 'Incident', 'Questionnaire', 'Détails', 'Confirmation']; const [code, setCode] = useState(null); const genCode = () => { const c = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; let r = 'CW'; for (let i = 0; i < 6; i++) r += c[Math.floor(Math.random() * c.length)]; return r; }; const submit = () => { const c = genCode(); setCode(c); onSubmit(c); setStep(6); }; return (
{/* Progress */}
{steps.map((s, i) => (
{i < step ? : i + 1}
{i < steps.length - 1 &&
}
))}

{steps[step]}

{/* Step 0: Vérification anti-bashing */} {step === 0 && (

Vérification préalable

Pour garantir la fiabilité des signalements

Pourquoi cette étape ?

Afin de protéger les établissements contre les signalements abusifs et garantir la crédibilité de l'observatoire, nous vérifions certaines informations. Les signalements sont modérés avant publication.

setData({...data, postalCode: e.target.value})} className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-teal-500 outline-none" />

Non publié, utilisé uniquement pour la vérification

{['Oui, j\'ai un document (facture, convocation, ordonnance)', 'Non, mais je peux fournir des détails précis', 'Je préfère rester totalement anonyme'].map(opt => ( ))}
setData({...data, charterAccepted: e.target.checked})} className="mt-1" />
)} {/* Step 1: Rôle */} {step === 1 && (

Vous êtes :

Cette information contextualise votre témoignage

{[ { value: 'victim', icon: User, label: 'Victime directe', desc: 'J\'ai personnellement vécu cette situation' }, { value: 'witness', icon: Eye, label: 'Témoin', desc: 'J\'ai observé une situation envers quelqu\'un' }, { value: 'relative', icon: Users, label: 'Proche', desc: 'Mon proche a subi cette situation' }, { value: 'professional', icon: Stethoscope, label: 'Professionnel·le', desc: 'J\'ai été témoin en tant que soignant·e' }, ].map(r => ( ))}
)} {/* Step 2: Lieu */} {step === 2 && (

Où et quand ?

Précisez l'établissement et le contexte

{data.institution === 'other' && ( setData({...data, otherInstitution: e.target.value})} className="w-full px-4 py-3 rounded-xl border border-gray-200 outline-none" /> )}
setData({...data, date: e.target.value})} className="w-full px-4 py-3 rounded-xl border border-gray-200 outline-none" />
setData({...data, time: e.target.value})} className="w-full px-4 py-3 rounded-xl border border-gray-200 outline-none" />
)} {/* Step 3: Type d'incident */} {step === 3 && (

Type d'incident

Sélectionnez ce qui correspond le mieux

{incidentTypes.map(type => ( ))}
)} {/* Step 4: Questionnaire DMS */} {step === 4 && (

Questionnaire d'expérience

À quelle fréquence avez-vous vécu ces situations ?

{dmsQuestions.map((q, idx) => (

{idx + 1}. {q.text}

{['Jamais', 'Rarement', 'Parfois', 'Souvent', 'Toujours'].map(opt => ( ))}
))}
)} {/* Step 5: Détails */} {step === 5 && (

Détails de l'incident

Décrivez ce qui s'est passé