// Klyvio — Report v5 // Niveau 1 : p3 dans AgentsCard, disclaimer ROI 3 scénarios, benchmark sourcé // Niveau 2 : explication score (2 dimensions qui tirent vers le bas) sous ScoreDial // Niveau 3 : description agents enrichie avec verbatim p3 // Niveau 4 (v5) : commercialSignals intégrés // - ReportHeader : intro adaptée si budget alloué (o8) ou projet en cours (o7) // - AgentsCard : encart v8 (idée concrète) en complément de p3 // - BookingCTA : label CTA affiné selon urgence (r7) et profil function Report({ company, answers, onBookCall, onAdmin, onRestart }) { const data = useMemo(() => { const result = window.KLYVIO_COMPUTE.compute(answers); return { ...result, roadmap: result.road }; }, [answers, company]); const [tab, setTab] = useState("overview"); const [simHoursPct, setSimHoursPct] = useState(100); const [simStaffPct, setSimStaffPct] = useState(100); const tabs = [ { id: "overview", label: "Vue d'ensemble", icon: "target" }, { id: "painpoints", label: "Problèmes", icon: "alert" }, { id: "automations", label: "Automatisations", icon: "workflow" }, { id: "roi", label: "Simulateur ROI", icon: "euro" }, { id: "roadmap", label: "Roadmap", icon: "compass" }, { id: "benchmark", label: "Benchmark", icon: "barChart" }, ]; const levelLabel = data.global < 30 ? "Découverte" : data.global < 50 ? "Exploration" : data.global < 70 ? "Développement" : data.global < 85 ? "Maturité" : "Leader"; return (
{tabs.map(t => ( ))}
{tab === "overview" && } {tab === "painpoints" && } {tab === "automations" && } {tab === "roi" && } {tab === "roadmap" && } {tab === "benchmark" && }
); } // ───────────────────────────────────────────────────────────── // HELPERS // ───────────────────────────────────────────────────────────── const C3_LABELS = [ "trouver et fidéliser des clients", "gérer la croissance sans recruter", "réduire les coûts et améliorer les marges", "fidéliser et manager les équipes", "se différencier de la concurrence", "gagner du temps pour se concentrer sur la stratégie", "remplacer des départs sans alourdir la masse salariale", ]; const P1_LABELS = [ "la ressaisie d'informations", "la recherche de documents", "la rédaction d'emails répétitifs", "la production de rapports manuels", "les réponses aux mêmes questions clients", "les relances commerciales", "la préparation de devis", "la planification et coordination", "le classement et l'archivage", "la gestion des congés et plannings", "la saisie et correction dans plusieurs outils", "la rédaction de comptes-rendus de réunion", ]; function getC3Label(answers) { const c3 = answers?.c3; if (Array.isArray(c3) && c3.length > 0) { const labels = c3.map(i => C3_LABELS[i]).filter(Boolean); if (labels.length === 0) return null; if (labels.length === 1) return labels[0]; return `${labels[0]} et ${labels[1]}`; } if (typeof c3 === "number" && C3_LABELS[c3]) return C3_LABELS[c3]; return null; } function getTop2Irritants(answers) { const p1 = Array.isArray(answers?.p1) ? answers.p1 : []; return p1.slice(0, 2).map(i => P1_LABELS[i]).filter(Boolean); } function getP3(answers) { const p3 = answers?.p3; return (typeof p3 === "string" && p3.trim().length > 3) ? p3.trim() : null; } function getV8(answers) { const v8 = answers?.v8; return (typeof v8 === "string" && v8.trim().length > 10) ? v8.trim() : null; } // ───────────────────────────────────────────────────────────── // NIVEAU 2 — Explication du score global // ───────────────────────────────────────────────────────────── function getScoreExplanation(scores, global) { const sorted = [...scores].sort((a, b) => a.value - b.value); const bottom2 = sorted.slice(0, 2); const DIM_IMPACT = { readiness: "votre capacité à déployer rapidement", org: "votre capacité à faire adopter les changements", data: "la qualité et la circulation de vos informations", processes: "le temps perdu sur des tâches répétitives", usage: "l'adoption de l'IA par vos équipes", context: "la clarté de votre vision IA", vision: "vos objectifs et votre ambition sur le sujet", }; const parts = bottom2.map(d => DIM_IMPACT[d.id] || d.fullLabel); return `Score influencé principalement par ${parts.join(" et ")}.`; } // ───────────────────────────────────────────────────────────── // INTRO CONTEXTUELLE — v5 // Adapte le texte d'intro selon les signaux commerciaux // Priorité : budget alloué > projet en cours > profil dirigeant > fallback // ───────────────────────────────────────────────────────────── function buildIntroText(profile, roiDetail, commercial) { const p2 = roiDetail?.hoursLostWk || 10; // Budget validé + projet en cours → on peut aller vite if (commercial?.hasBudget && commercial?.hasActiveProject) { return "Vous avez déjà un budget et un projet en cours — c'est le meilleur point de départ. Ce rapport vous montre précisément comment accélérer et sur quoi concentrer l'effort en premier."; } // Budget alloué mais pas encore de projet structuré if (commercial?.hasBudget && !commercial?.hasActiveProject) { return "Votre budget est alloué — il reste à cibler les bons cas d'usage. Ce rapport vous donne les priorités claires pour démarrer avec un impact immédiat."; } // Projet en cours mais pas encore de budget formalisé if (commercial?.hasActiveProject && !commercial?.hasBudget) { return "Vous avez déjà engagé une réflexion — c'est une longueur d'avance. Ce rapport structure ce qui manque encore pour transformer cette exploration en résultats concrets."; } // Urgence identifiée sans budget ni projet if (commercial?.isUrgent) { return `Une échéance approche — chaque semaine compte. Vos équipes passent ${p2} h/sem sur des tâches automatisables. Ce rapport montre ce qu'on peut déployer en moins de 30 jours.`; } // Fallback — profil dirigeant if (profile?.emphasis) return profile.emphasis; return `Vos équipes passent en moyenne ${p2} h/sem sur des tâches répétitives. Ce rapport montre où récupérer ce temps et ce que ça représente concrètement pour votre activité.`; } // ───────────────────────────────────────────────────────────── // REPORT HEADER // ───────────────────────────────────────────────────────────── function ReportHeader({ company, data, levelLabel, onBookCall, onRestart, answers }) { const profile = data.profile; const commercial = data.commercial || {}; const scoreExplanation = getScoreExplanation(data.scores, data.global); const introText = buildIntroText(profile, data.roiDetail, commercial); // Badge contextuel dans le header selon signal fort function getContextBadge() { if (commercial.hasBudget && commercial.hasActiveProject) { return { label: "Projet & budget prêts", color: "#10B981", bg: "rgba(16,185,129,0.1)", border: "rgba(16,185,129,0.3)" }; } if (commercial.hasBudget) { return { label: "Budget alloué", color: "#10B981", bg: "rgba(16,185,129,0.1)", border: "rgba(16,185,129,0.3)" }; } if (commercial.hasActiveProject) { return { label: "Projet en cours", color: "#F59E0B", bg: "rgba(245,158,11,0.1)", border: "rgba(245,158,11,0.3)" }; } if (commercial.isUrgent) { return { label: "Urgence identifiée", color: "#EF4444", bg: "rgba(239,68,68,0.1)", border: "rgba(239,68,68,0.3)" }; } return null; } const contextBadge = getContextBadge(); return (
Rapport prêt Généré le {new Date().toLocaleDateString("fr-FR", { day: "numeric", month: "long", year: "numeric" })} {/* Badge profil dirigeant */} {profile && ( {profile.label} )} {/* Badge contextuel — signal commercial fort */} {contextBadge && ( {contextBadge.label} )}
Audit de maturité IA · {company?.name || "Votre entreprise"} · {data.sectorLabel}

Votre niveau : {levelLabel}.

{introText}

{/* Métriques clés */}
Position
Top {100 - data.bench.percentile}%
vs {data.sectorLabel}
{/* Niveau 2 — explication du score */}
{scoreExplanation}
Retour sur invest.
{data.roi.payback} mois
pour rentabiliser
{data.roiDetail?.offerName || data.offer?.name || `${data.tier === "starter" ? "1" : data.tier === "duo" ? "2" : "3"} agents autonomes`}
{formatEur(data.roi.totalInvest)} la 1ère année
puis {formatEur(data.roiDetail?.subscription || (data.roi.totalInvest - (data.roiDetail?.setup || 0)))}/an
); } function MetricTile({ eyebrow, value, sub, color = "var(--accent-300)" }) { return (
{eyebrow}
{value}
{sub}
); } // ───────────────────────────────────────────────────────────── // REPORT OVERVIEW // ───────────────────────────────────────────────────────────── function ReportOverview({ data, levelLabel, company, answers, onNav }) { const top3 = data.autos.slice(0, 3); const highPains = data.pains.filter(p => p.severity === "high").slice(0, 3); const defi = getC3Label(answers); const irritants = getTop2Irritants(answers); const usageScore = (data.scores.find(s => s.id === "usage") || { value: 50 }).value; const p2 = data.roiDetail?.hoursLostWk || 10; const syntheseIntro = [ company?.name ? `${company.name} se situe` : "Votre entreprise se situe", `au niveau ${levelLabel.toLowerCase()}.`, defi ? (Array.isArray(answers?.c3) && answers.c3.length > 1 ? `Vos deux défis prioritaires — ${defi} —` : `Votre défi principal — ${defi} —`) : "Vos priorités", "sont directement adressables par l'IA.", ].join(" "); const syntheseBody = [ `Vos équipes consacrent en moyenne ${p2} h/sem à des tâches répétitives,`, irritants.length > 0 ? `notamment ${irritants.join(" et ")}.` : "notamment des emails, devis et reporting.", "Sur 12 mois, le potentiel de gain net est de", `${formatEur(data.roi.net12m)} pour un investissement estimé à ${formatEur(data.roi.totalInvest)}.`, ].join(" "); return (
{/* Synthèse */}
Synthèse

Ce que votre audit révèle.

{syntheseIntro}

{usageScore > 55 ? "Vos équipes sont plutôt ouvertes à ces outils — c'est un atout." : "Vos équipes ont besoin d'un cadre clair pour adopter ces outils efficacement." }{" "}{syntheseBody}

{/* Top 3 */}
Top 3 automatisations

Par où commencer

{top3.map((a, i) => (
{i + 1}
{a.label}
{a.applicableStaff} collaborateurs · {a.weeklyHoursSaved} h/sem économisées
{a.type}
{formatEur(a.annualGain)}
/ an
))}
{/* Points bloquants */}
À traiter en priorité

Vos principaux points bloquants

{highPains.map((p, i) => (
Critique
{p.title}
{p.impact}
))}
{/* Encart agents */} {data.agents && data.agents.length > 0 && ( )}
{/* Colonne droite — Radar */}
Profil détaillé

Vos 7 dimensions

Dimensions — détail
{[...data.scores].sort((a, b) => b.value - a.value).map(s => (
{s.label}
{Math.round(s.value)}
))}
); } // ───────────────────────────────────────────────────────────── // ENCART AGENTS — v5 : p3 + v8 (idée concrète) // ───────────────────────────────────────────────────────────── function AgentsCard({ data, answers, onNav }) { const { agents, offer, profile } = data; const ctaText = profile?.cta || "Voir ce qu'on ferait ensemble"; const agentColors = ["var(--accent-500)", "#8B5CF6", "#10B981"]; const p3 = getP3(answers); const v8 = getV8(answers); // Description du premier agent — enrichie avec p3 ou v8 function agentDesc(agent, i) { if (i === 0 && p3) { return `Il prend en charge "${p3}" — et plus généralement, il ${agent.focus}.`; } if (i === 0 && v8) { return `Il peut démarrer par "${v8}" — et plus généralement, il ${agent.focus}.`; } return `Il ${agent.focus}.`; } // Encart à afficher : p3 prioritaire sur v8 const highlightText = p3 || v8; const highlightLabel = p3 ? "Votre priorité n°1" : "Votre idée de départ"; const highlightSub = p3 ? "C'est exactement ce type de tâche que prend en charge le premier agent déployé." : "C'est un cas d'usage concret — on peut partir de là pour le premier déploiement."; return (
Ce qu'on ferait ensemble

{offer?.name || "Agents recommandés"}

Recommandé
{/* Encart verbatim — p3 ou v8 */} {highlightText && (
{highlightLabel}
"{highlightText}"
{highlightSub}
)}
{agents.map((agent, i) => (
{agent.name}
{agentDesc(agent, i)}
))}
{/* Section outils — statut intégration */} {data.integration && data.integration.summary.total > 0 && ( )}
); } // ───────────────────────────────────────────────────────────── // BLOC INTÉGRATION OUTILS — affiché dans AgentsCard // ───────────────────────────────────────────────────────────── function ToolsIntegrationBlock({ integration }) { const { byDomain, summary, level } = integration; const domainLabels = { rh: "RH & plannings", compta: "Comptabilité", ventes: "Commercial", client: "Relation client" }; const statusMeta = { api: { label: "API native", color: "#10B981", icon: "check" }, connector: { label: "Via connecteur", color: "#F59E0B", icon: "plug" }, none: { label: "Pas d'API connue", color: "#EF4444", icon: "x" }, unknown: { label: "À vérifier", color: "#64748B", icon: "info" }, }; const levelMeta = { green: { label: "Intégration globalement facile", color: "#10B981", bg: "rgba(16,185,129,0.08)", border: "rgba(16,185,129,0.2)" }, orange: { label: "Quelques ajustements nécessaires", color: "#F59E0B", bg: "rgba(245,158,11,0.08)", border: "rgba(245,158,11,0.2)" }, red: { label: "Points complexes à anticiper", color: "#EF4444", bg: "rgba(239,68,68,0.08)", border: "rgba(239,68,68,0.2)" }, }; const lm = levelMeta[level] || levelMeta.orange; return (
Vos outils actuels
{/* Niveau global */}
{lm.label}
{/* Détail par domaine */}
{Object.entries(byDomain).map(([domain, info]) => { if (!info.raw) return null; const meta = statusMeta[info.status] || statusMeta.unknown; return (
{domainLabels[domain]}
{info.name}
{meta.label}
); })}
{/* Note si outils non répertoriés */} {summary.complex > 0 && (
⚠ Un ou plusieurs outils nécessitent une vérification manuelle avant de confirmer la faisabilité de l'intégration.
)}
); } // ───────────────────────────────────────────────────────────── // STICKY CTA — v5 : label affiné selon urgence r7 et profil // ───────────────────────────────────────────────────────────── function BookingCTA({ onBookCall, data, answers }) { const profile = data?.profile; const commercial = data?.commercial || {}; // Priorité : urgence calendaire > profil dirigeant > défaut const ctaLabel = commercial.isUrgent ? "Démarrer maintenant — j'ai une échéance" : profile?.id === "urgent" ? "Parler de votre problème maintenant" : profile?.id === "skeptical" ? "Poser vos questions à un expert" : commercial.hasBudget ? "Cadrer le projet — budget disponible" : commercial.hasIdentifiedProcess ? "Voir comment automatiser ce processus" : "Prendre rendez-vous"; const subLabel = commercial.isUrgent ? "Votre échéance approche — 30 min pour prioriser." : commercial.hasBudget ? "Votre budget est alloué — définissons le périmètre." : "30 min offertes pour prioriser votre roadmap."; return (
{["#4F52E5", "#8B5CF6", "#0EA5A3"].map((c, i) => (
{["R", "A", "T"][i]}
))}
Besoin d'un avis humain ?
{subLabel}
); } window.Report = Report;