'use client' import { useState } from 'react' import { motion, AnimatePresence } from 'motion/react' import { Wrench, TrendingUp, Users, ThumbsDown, Sun, Loader2, ChevronDown, ChevronUp, X, Copy, CheckCircle, Sparkles, } from 'lucide-react' import { cn } from '@/lib/utils' import { MarkdownContent } from '@/components/markdown-content' // ── Personas definition ────────────────────────────────────────────────────── const PERSONAS = [ { id: 'engineer', label: 'Ingénieur', sublabel: 'Faisabilité · Risques tech', icon: Wrench, color: 'text-blue-600', bg: 'bg-blue-50 dark:bg-blue-950/30', border: 'border-blue-200 dark:border-blue-800/50', hoverBorder: 'hover:border-blue-400/60', activeBg: 'bg-blue-600', }, { id: 'financial', label: 'Financier', sublabel: 'ROI · Coûts · Viabilité', icon: TrendingUp, color: 'text-emerald-600', bg: 'bg-emerald-50 dark:bg-emerald-950/30', border: 'border-emerald-200 dark:border-emerald-800/50', hoverBorder: 'hover:border-emerald-400/60', activeBg: 'bg-emerald-600', }, { id: 'customer', label: 'Client', sublabel: 'UX · Valeur · Besoins', icon: Users, color: 'text-violet-600', bg: 'bg-violet-50 dark:bg-violet-950/30', border: 'border-violet-200 dark:border-violet-800/50', hoverBorder: 'hover:border-violet-400/60', activeBg: 'bg-violet-600', }, { id: 'skeptic', label: 'Sceptique', sublabel: 'Points faibles · Angles morts', icon: ThumbsDown, color: 'text-rose-600', bg: 'bg-rose-50 dark:bg-rose-950/30', border: 'border-rose-200 dark:border-rose-800/50', hoverBorder: 'hover:border-rose-400/60', activeBg: 'bg-rose-600', }, { id: 'optimist', label: 'Optimiste', sublabel: 'Opportunités · Potentiel', icon: Sun, color: 'text-amber-600', bg: 'bg-amber-50 dark:bg-amber-950/30', border: 'border-amber-200 dark:border-amber-800/50', hoverBorder: 'hover:border-amber-400/60', activeBg: 'bg-amber-600', }, ] as const type PersonaId = (typeof PERSONAS)[number]['id'] interface PersonaResult { personaId: PersonaId personaLabel: string analysis: string } interface PersonasPanelProps { noteTitle?: string noteContent?: string } // ── Component ───────────────────────────────────────────────────────────────── export function PersonasPanel({ noteTitle, noteContent }: PersonasPanelProps) { const [loadingId, setLoadingId] = useState(null) const [results, setResults] = useState>(new Map()) const [expanded, setExpanded] = useState(null) const [copied, setCopied] = useState(null) const handlePersona = async (personaId: PersonaId) => { if (loadingId) return // Toggle off if already showing if (expanded === personaId && results.has(personaId)) { setExpanded(null) return } // If we already have the result, just expand it if (results.has(personaId)) { setExpanded(personaId) return } if (!noteContent || noteContent.replace(/<[^>]+>/g, '').trim().split(/\s+/).length < 5) { return } setLoadingId(personaId) try { const res = await fetch('/api/ai/personas', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: noteContent, title: noteTitle, personaId }), }) const data = await res.json() if (!res.ok) throw new Error(data.error || 'Erreur') setResults(prev => new Map(prev).set(personaId, data)) setExpanded(personaId) } catch { // silent error — user can retry } finally { setLoadingId(null) } } const handleCopy = (personaId: PersonaId) => { const result = results.get(personaId) if (!result) return navigator.clipboard.writeText(result.analysis).catch(() => {}) setCopied(personaId) setTimeout(() => setCopied(null), 2000) } const handleClear = (personaId: PersonaId) => { setResults(prev => { const next = new Map(prev) next.delete(personaId) return next }) if (expanded === personaId) setExpanded(null) } return (
{/* Header */}

Prismes IA

Réinterprétez vos notes à travers différents prismes d'analyse.

{/* Persona buttons */}
{PERSONAS.map((persona) => { const Icon = persona.icon const isLoading = loadingId === persona.id const hasResult = results.has(persona.id) const isExpanded = expanded === persona.id const result = results.get(persona.id) return (
{/* Persona row */} {/* Expanded result */} {isExpanded && result && (
)}
) })}
) }