import { useState, useEffect } from 'react' import { useParams } from 'react-router-dom' import { CheckCircle, XCircle, AlertCircle, FileText, Image as ImageIcon, Film, Sparkles, Globe, User } from 'lucide-react' import { useLanguage } from '../i18n/LanguageContext' import { useToast } from '../components/ToastContainer' import Modal from '../components/Modal' const STATUS_ICONS = { copy: FileText, design: ImageIcon, video: Film, other: Sparkles, } export default function PublicReview() { const { token } = useParams() const { t } = useLanguage() const toast = useToast() const [artefact, setArtefact] = 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 [selectedLanguage, setSelectedLanguage] = useState(0) const [pendingAction, setPendingAction] = useState(null) useEffect(() => { loadArtefact() }, [token]) const loadArtefact = async () => { try { const res = await fetch(`/api/public/review/${token}`) if (!res.ok) { const err = await res.json() setError(err.error || t('review.loadFailed')) setLoading(false) return } const data = await res.json() setArtefact(data) // Auto-set reviewer name if there's exactly one approver 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 = (action) => { if (!reviewerName.trim()) { toast.error(t('review.enterName')) return } if (action === 'revision' && !feedback.trim()) { toast.error(t('review.feedbackRequired')) return } if (action === 'approve' || action === 'reject') { setPendingAction(action) return } executeAction(action) } const executeAction = async (action) => { setSubmitting(true) try { const res = await fetch(`/api/public/review/${token}/${action}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ approved_by_name: reviewerName, feedback: feedback || undefined, }), }) if (!res.ok) { const err = await res.json() setError(err.error || t('review.actionFailed')) setSubmitting(false) return } const data = await res.json() setSuccess(data.message || t('review.actionCompleted')) setTimeout(() => { loadArtefact() }, 1500) } catch (err) { setError(t('review.actionFailed')) } finally { setSubmitting(false) } } const extractDriveFileId = (url) => { const patterns = [ /\/file\/d\/([^\/]+)/, /id=([^&]+)/, /\/d\/([^\/]+)/, ] for (const pattern of patterns) { const match = url.match(pattern) if (match) return match[1] } return null } const getDriveEmbedUrl = (url) => { const fileId = extractDriveFileId(url) return fileId ? `https://drive.google.com/file/d/${fileId}/preview` : url } if (loading) { return (
) } if (error) { return (

{t('review.notAvailable')}

{error}

) } if (success) { return (

{t('review.thankYou')}

{success}

) } if (!artefact) return null const TypeIcon = STATUS_ICONS[artefact.type] || Sparkles const isImage = (url) => /\.(jpg|jpeg|png|gif|webp)$/i.test(url) return (
{/* Header */}

{t('review.contentReview')}

Samaya Digital Hub

{/* Artefact Info */}

{artefact.title}

{artefact.description && (

{artefact.description}

)}
{artefact.type} {artefact.brand_name && • {artefact.brand_name}} {artefact.version_number && • {t('review.version')} {artefact.version_number}}
{/* COPY TYPE: Multilingual Content */} {artefact.type === 'copy' && artefact.texts && artefact.texts.length > 0 && (

{t('review.contentLanguages')}

{/* Language tabs */}
{artefact.texts.map((text, idx) => ( ))}
{/* Selected language content */}
{artefact.texts[selectedLanguage].language_label} {t('review.content')}
{artefact.texts[selectedLanguage].content}
)} {/* Legacy content field (for backward compatibility) */} {artefact.content && (!artefact.texts || artefact.texts.length === 0) && (

{t('review.content')}

                    {artefact.content}
                  
)} {/* DESIGN TYPE: Image Gallery */} {artefact.type === 'design' && artefact.attachments && artefact.attachments.length > 0 && (

{t('review.designFiles')}

{artefact.attachments.map((att, idx) => ( {att.original_name {att.original_name && (

{att.original_name}

)}
))}
)} {/* VIDEO TYPE: Video Player or Drive Embed */} {artefact.type === 'video' && artefact.attachments && artefact.attachments.length > 0 && (

{t('review.videos')}

{artefact.attachments.map((att, idx) => (
{att.drive_url ? (
{t('review.googleDriveVideo')}