/** * AIDisclosure, selo "Gerado por IA" + canal de contestação (art. 20 LGPD) * ===================================================================== * Skill: lgpd-compliance (Parte 3) * Cole em: components/transparencia/AIDisclosure.tsx * * Usar SEMPRE que o app exibir output de IA ao usuário. * - Variante , selo compacto inline * - Variante , card completo com modelo, disclaimer, feedback, contestação * * Cumpre: * - EU AI Act Article 50 (transparência de chatbot/synthetic) * - PL 2338 (Marco Legal IA, quando virar lei) * - LGPD art. 20 (direito de revisão de decisão automatizada) */ 'use client'; import { useState } from 'react'; import { Sparkles, AlertCircle, ThumbsUp, ThumbsDown, MessageSquare } from 'lucide-react'; import Link from 'next/link'; // ========================================================================= // Tipos // ========================================================================= type AIModelo = { provedor: 'anthropic' | 'openai' | 'google' | 'mistral' | 'proprio' | string; modelo: string; versao?: string; }; type AIDisclosureProps = { modelo: AIModelo; /** Indica que esta é uma decisão que afeta o usuário (art. 20 LGPD) */ decisaoAutomatizada?: boolean; /** ID da decisão pra log de contestação */ decisaoId?: string; /** Texto do disclaimer customizado (override do default) */ disclaimer?: string; }; // ========================================================================= // Variante 1: Badge compacto inline // ========================================================================= export function AIBadge({ modelo }: { modelo: AIModelo }) { return ( Gerado por IA ); } // ========================================================================= // Variante 2: Card completo // ========================================================================= export function AIDisclosure({ modelo, decisaoAutomatizada = false, decisaoId, disclaimer, }: AIDisclosureProps) { const [feedback, setFeedback] = useState<'up' | 'down' | null>(null); const disclaimerText = disclaimer ?? 'Esta resposta foi gerada automaticamente e pode conter imprecisões. Confirme informações importantes em fontes oficiais.'; return (
{/* Linha de identificação */}
Gerado por IA · {modelo.provedor} {modelo.modelo} {modelo.versao ? ` (${modelo.versao})` : ''}
Como funciona?
{/* Disclaimer */}

{disclaimerText}

{/* Feedback */}
Esta resposta foi útil? {/* Decisão automatizada, botão de contestação (art. 20 LGPD) */} {decisaoAutomatizada && decisaoId && ( Contestar esta decisão )}
); } // ========================================================================= // Helpers // ========================================================================= async function postFeedback(payload: { rating: 'up' | 'down'; decisaoId?: string }) { try { await fetch('/api/ai/feedback', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), keepalive: true, }); } catch { // silencioso, feedback não é crítico } }