import React, { useState, useEffect } from 'react'; import { Globe, Sparkles, RefreshCw, Check, Columns, Scale, FileText, Copy, ChevronDown, ChevronUp } from 'lucide-react'; import { translateLegalClause, getSynchronousTranslation, SUPPORTED_LEGAL_LANGUAGES } from '../services/geminiTranslationService'; interface Props { clauseKey: string; clauseTitle: string; englishContent: React.ReactNode; englishPlainText: string; selectedLanguage: string; showLineNumbers?: boolean; } export const TranslatedLegalClause: React.FC = ({ clauseKey, clauseTitle, englishContent, englishPlainText, selectedLanguage, showLineNumbers = false }) => { const [translatedText, setTranslatedText] = useState(''); const [isTranslating, setIsTranslating] = useState(false); const [viewMode, setViewMode] = useState<'translated' | 'sideBySide' | 'english'>('translated'); const [copied, setCopied] = useState(false); const [modelUsed, setModelUsed] = useState('gemini-3.8-flash'); const currentLang = SUPPORTED_LEGAL_LANGUAGES.find(l => l.code === selectedLanguage) || SUPPORTED_LEGAL_LANGUAGES[0]; const isNonEnglish = selectedLanguage !== 'en'; // Load translation whenever language or clauseKey changes useEffect(() => { if (!isNonEnglish) { setTranslatedText(prev => (prev ? '' : prev)); return; } // Set synchronous preview if cached/canonical const syncText = getSynchronousTranslation(clauseKey, selectedLanguage); if (syncText) { setTranslatedText(prev => (prev !== syncText ? syncText : prev)); } // Trigger async Gemini API translation via server proxy let isCancelled = false; setIsTranslating(true); translateLegalClause(clauseKey, englishPlainText, selectedLanguage, currentLang.name) .then((res) => { if (!isCancelled) { setTranslatedText(prev => (prev !== res.translatedText ? res.translatedText : prev)); setModelUsed(res.model || 'gemini-3.8-flash'); setIsTranslating(false); } }) .catch((err) => { if (!isCancelled) { console.warn('Translation error in clause', clauseKey, err); setIsTranslating(false); } }); return () => { isCancelled = true; }; }, [clauseKey, englishPlainText, selectedLanguage, isNonEnglish, currentLang.name]); const handleCopy = () => { const textToCopy = viewMode === 'english' ? englishPlainText : (translatedText || englishPlainText); navigator.clipboard.writeText(textToCopy); setCopied(true); setTimeout(() => setCopied(false), 2000); }; const handleRefresh = async () => { setIsTranslating(true); try { const res = await translateLegalClause(clauseKey, englishPlainText, selectedLanguage, currentLang.name); setTranslatedText(res.translatedText); setModelUsed(res.model || 'gemini-3.8-flash'); } finally { setIsTranslating(false); } }; // If English is selected, render standard content directly if (!isNonEnglish) { return <>{englishContent}; } return (
{/* Translation Header Bar */}
{currentLang.flag} {clauseTitle} in {currentLang.name}
{modelUsed} • {currentLang.badge} {isTranslating && ( <> • Real-time Translating... )}
{/* View Mode Switcher and Actions */}
{/* Content Body Based on View Mode */}
{viewMode === 'translated' && (
Court-Authenticated Juridical Translation ({currentLang.name})
{translatedText || (
Generating Gemini 3.8 Flash legal translation...
)}
)} {viewMode === 'sideBySide' && (
{/* Left: Original English */}
Original English Master Pleading
{englishContent}
{/* Right: Translated Target */}
{currentLang.name} Translation (Gemini 3.8 Flash)
{translatedText || 'Loading translation...'}
)} {viewMode === 'english' && (
Original English Filing Text
{englishContent}
)}
{/* Verification Footer Safeguard */}
Certified Invariants Protected: $500,000,000.00 Senior Debt • 45,850,000 LEU Shares • 30 Row Homes SSDI/SSI Housing Pool
Bluebook Citations Intact
); };