/** * ExplainButton Component * Reusable inline "Explain" button for configs, logs, and errors * Shows modal/popover with LLM-powered explanation */ import React, { useState } from 'react'; const ExplainButton = ({ type = 'config', // config, log, error, scan_result content, context = {}, size = 'small', style = {} }) => { const [isLoading, setIsLoading] = useState(false); const [showModal, setShowModal] = useState(false); const [explanation, setExplanation] = useState(null); const [error, setError] = useState(null); const handleExplain = async () => { setIsLoading(true); setError(null); setShowModal(true); try { const response = await fetch('/api/explain', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ type, content, context }) }); if (!response.ok) { throw new Error('Failed to get explanation'); } const data = await response.json(); setExplanation(data); } catch (err) { console.error('Error getting explanation:', err); setError('Failed to load explanation. Please try again.'); } finally { setIsLoading(false); } }; const closeModal = () => { setShowModal(false); setExplanation(null); setError(null); }; const buttonSizes = { small: { padding: '4px 8px', fontSize: '12px' }, medium: { padding: '6px 12px', fontSize: '14px' }, large: { padding: '8px 16px', fontSize: '16px' } }; const buttonStyle = { ...buttonSizes[size], backgroundColor: '#3498DB', color: 'white', border: 'none', borderRadius: '4px', cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: '4px', transition: 'background-color 0.2s', ...style }; const renderExplanation = () => { if (error) { return (
{explanation.current_value}
{explanation.description}
{explanation.example}
{explanation.plain_english}
{explanation.explanation}