import { useState, useEffect } from 'react' import { useParams } from 'react-router-dom' import { CheckCircle, XCircle, AlertCircle, Languages, Globe, User } from 'lucide-react' import { useLanguage } from '../i18n/LanguageContext' import { useToast } from '../components/ToastContainer' import Modal from '../components/Modal' export default function PublicTranslationReview() { const { token } = useParams() const { t } = useLanguage() const toast = useToast() const [translation, setTranslation] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState('') const [submitting, setSubmitting] = useState(false) const [success, setSuccess] = useState('') const [reviewerName, setReviewerName] = useState('') const [feedback, setFeedback] = useState('') const [pendingAction, setPendingAction] = useState(null) useEffect(() => { loadTranslation() }, [token]) const loadTranslation = async () => { try { const res = await fetch(`/api/public/review-translation/${token}`) if (!res.ok) { const err = await res.json() setError(err.error || t('review.loadFailed')) setLoading(false) return } const data = await res.json() setTranslation(data) if (data.approvers?.length === 1 && data.approvers[0].name) { setReviewerName(data.approvers[0].name) } } catch (err) { setError(t('review.loadFailed')) } finally { setLoading(false) } } const handleAction = async (action) => { if (action === 'approve' && !reviewerName.trim()) { toast.error(t('review.nameRequired')) return } if (action === 'reject' && !feedback.trim()) { toast.error(t('review.feedbackRequired')) return } setSubmitting(true) try { const res = await fetch(`/api/public/review-translation/${token}/${action}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ approved_by_name: reviewerName || 'Anonymous', feedback: feedback || '', }), }) if (!res.ok) { const err = await res.json() throw new Error(err.error || 'Action failed') } if (action === 'approve') setSuccess(t('review.approveSuccess')) else if (action === 'reject') setSuccess(t('review.rejectSuccess')) else setSuccess(t('review.revisionSuccess')) setPendingAction(null) } catch (err) { toast.error(err.message) } finally { setSubmitting(false) } } if (loading) { return (
) } if (error) { return (

{t('review.errorTitle')}

{error}

) } if (success) { return (

{success}

{t('review.thankYou')}

) } if (!translation) return null return (
{/* Header */}

{translation.title}

{translation.description && (

{translation.description}

)}
{translation.brand_name && {translation.brand_name}} {translation.creator_name && {t('review.createdBy')} {translation.creator_name}}
{/* Source Content */}

{t('translations.sourceContent')}

{translation.source_language}

{translation.source_content}

{/* Translations */} {translation.texts && translation.texts.length > 0 && (

{t('translations.translationTexts')} ({translation.texts.length})

{translation.texts.map((text, idx) => (
{text.language_label || text.language_code} ({text.language_code})

{text.content}

))}
)} {/* Review Actions */} {translation.status === 'pending_review' && (

{t('review.yourReview')}

{/* Reviewer identity */}
{translation.approvers?.length === 1 ? (
{translation.approvers[0].name}
) : translation.approvers?.length > 1 ? (
) : (
setReviewerName(e.target.value)} className="w-full px-3 py-2 text-sm border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-primary/20" placeholder={t('review.enterYourName')} />
)}
{/* Feedback */}