// Klyvio — Booking modal + Admin dashboard (dark theme Klyvio)
function BookingModal({ onClose, company }) {
const [step, setStep] = useState(0);
const [form, setForm] = useState({ date: "", slot: "", email: "", phone: "", topic: "" });
const dates = [
{ d: "28", day: "Lun", month: "avril", slots: ["09:30", "11:00", "14:30", "16:00"] },
{ d: "29", day: "Mar", month: "avril", slots: ["10:00", "11:30", "15:00"] },
{ d: "30", day: "Mer", month: "avril", slots: ["09:00", "10:30", "14:00", "17:00"] },
{ d: "02", day: "Ven", month: "mai", slots: ["11:00", "14:30"] },
];
return (
{step < 2 ? (
{/* Gauche — info consultant */}
30 minutes, 100% utiles.
On revoit votre rapport ensemble, on priorise les 2–3 chantiers à lancer en premier, et on répond à toutes vos questions.
30 minutes
Visio ou téléphone
Offert · sans engagement
{/* Droite — formulaire */}
{step === 0 && (
<>
Choisissez un créneau
{dates.map(d => (
{d.day.toUpperCase()}
{d.d}
{d.day} {d.d} {d.month}
{d.slots.map(s => {
const selected = form.date === d.d && form.slot === s;
return (
setForm({ ...form, date: d.d, slot: s, dateLabel: `${d.day} ${d.d} ${d.month}` })}
style={{
padding: "7px 14px", fontSize: 13, fontWeight: 500,
background: selected ? "var(--accent)" : "rgba(255,255,255,0.03)",
color: selected ? "#000" : "var(--gray)",
border: `1px solid ${selected ? "var(--accent)" : "var(--gray-dim)"}`,
borderRadius: 8, cursor: "pointer",
transition: "all .15s ease",
}}>
{s}
);
})}
))}
setStep(1)}>Continuer
>
)}
{step === 1 && (
<>
Vos coordonnées
{form.dateLabel} à {form.slot}
setStep(0)}>Retour
setStep(2)}>
Confirmer le rendez-vous
>
)}
) : (
Rendez-vous confirmé !
Nous avons envoyé une invitation à {form.email} pour le {form.dateLabel} à {form.slot}.
{form.dateLabel} · {form.slot} · 30 min
Retour au rapport
)}
);
}
/* ———————————————————— ADMIN DASHBOARD ———————————————————— */
function AdminDashboard({ onOpenReport }) {
const [filter, setFilter] = useState("all");
const audits = [
{ id: "A-1042", company: "Atlas Industries", person: "Marie Dupont", sector: "Industrie", size: "42 pers.", score: 62, status: "ready", gain: 184000, date: "il y a 2h", new: true },
{ id: "A-1041", company: "Rosier & Fils", person: "Nicolas Rosier", sector: "BTP", size: "28 pers.", score: 34, status: "ready", gain: 112000, date: "hier" },
{ id: "A-1040", company: "NeoPharm", person: "Claire Berteau", sector: "Santé", size: "85 pers.", score: 71, status: "ready", gain: 320000, date: "hier", flagged: true },
{ id: "A-1039", company: "Mobilio", person: "Samir Benali", sector: "Commerce", size: "15 pers.", score: null, status: "pending", progress: 64, date: "il y a 3h" },
{ id: "A-1038", company: "Cléome Avocats", person: "Juliette Mari", sector: "Services", size: "22 pers.", score: 48, status: "ready", gain: 98000, date: "2 jours" },
{ id: "A-1037", company: "Atelier Bois d'Or", person: "Pierre Leclerc", sector: "Industrie", size: "18 pers.", score: 28, status: "ready", gain: 76000, date: "3 jours" },
{ id: "A-1036", company: "Vivaldi Group", person: "Léa Fontaine", sector: "Services", size: "110 pers.",score: 78, status: "ready", gain: 410000, date: "5 jours" },
{ id: "A-1035", company: "ProxiShop", person: "Karim Osmani", sector: "Commerce", size: "35 pers.", score: null, status: "draft", progress: 22, date: "1 sem." },
];
const filtered = filter === "all" ? audits : audits.filter(a => a.status === filter);
const totals = {
count: audits.length,
ready: audits.filter(a => a.status === "ready").length,
avg: Math.round(audits.filter(a => a.score).reduce((s, a) => s + a.score, 0) / audits.filter(a => a.score).length),
gain: audits.reduce((s, a) => s + (a.gain || 0), 0),
};
return (
Console consultant
Vos audits en cours
Exporter CSV
Lancer un audit
{/* Filtres */}
{[
{ id: "all", label: "Tous" },
{ id: "ready", label: "Rapports prêts" },
{ id: "pending", label: "En cours" },
{ id: "draft", label: "Brouillons" },
].map(f => (
setFilter(f.id)}
style={{
padding: "5px 12px", fontSize: 13, fontWeight: 500,
border: "none", borderRadius: 999, cursor: "pointer",
background: filter === f.id ? "var(--accent)" : "transparent",
color: filter === f.id ? "#000" : "var(--gray)",
transition: "all .15s ease",
}}>{f.label}
))}
{["Entreprise", "Contact", "Secteur", "Taille", "Score", "Gain /an", "Statut", "Date", ""].map((h, i) => (
{h}
))}
{filtered.map(a => (
e.currentTarget.style.background = "rgba(0,174,239,0.04)"}
onMouseLeave={e => e.currentTarget.style.background = "transparent"}
onClick={() => a.status === "ready" && onOpenReport(a)}>
{a.company.split(" ").slice(0, 2).map(w => w[0]).join("").toUpperCase()}
{a.company}
{a.new && NEW }
{a.flagged && }
{a.id}
{a.person}
{a.sector}
{a.size}
{a.score ? (
{a.score}
60 ? "var(--success)" : a.score > 40 ? "var(--warn)" : "var(--danger)", borderRadius: 999 }} />
) :
— }
{a.gain ? formatEur(a.gain) : — }
{a.status === "ready" && Prêt }
{a.status === "pending" && En cours {a.progress}% }
{a.status === "draft" && Brouillon }
{a.date}
{a.status === "ready" && (
{ e.stopPropagation(); onOpenReport(a); }}>
Ouvrir
)}
))}
{/* Insights */}
Insights agrégés · derniers 30 jours
{[
{ label: "Dimension la plus faible", value: "Données", color: "var(--viz-teal)" },
{ label: "Automatisation #1 citée", value: "Support client", color: "var(--viz-violet)" },
{ label: "Secteur le + mature", value: "Tech / édition", color: "var(--accent)" },
].map((item, k) => (
{item.label}
{item.value}
))}
Activité
{[
{ icon: "check", color: "var(--success)", text: "Atlas Industries a terminé son audit", time: "il y a 2h" },
{ icon: "calendar", color: "var(--accent)", text: "RDV confirmé avec NeoPharm · 29 avril 10:30", time: "il y a 5h" },
{ icon: "play", color: "var(--warn)", text: "Mobilio a démarré son audit", time: "il y a 6h" },
].map((a, k) => (
))}
);
}
Object.assign(window, { BookingModal, AdminDashboard });