import { useState, useEffect } from 'react'; import { useParams, Link } from 'react-router-dom'; import { Video, User, Lock, Shield, ArrowRight, Loader2, Users, Radio, AlertCircle, FileText } from 'lucide-react'; import BrandLogo from '../components/BrandLogo'; import api from '../services/api'; import toast from 'react-hot-toast'; import { useLanguage } from '../contexts/LanguageContext'; import { useAuth } from '../contexts/AuthContext'; import { useBranding } from '../contexts/BrandingContext'; export default function GuestJoin() { const { uid } = useParams(); const { t } = useLanguage(); const { user } = useAuth(); const { imprintUrl, privacyUrl } = useBranding(); const isLoggedIn = !!user; const [roomInfo, setRoomInfo] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [joining, setJoining] = useState(false); const [name, setName] = useState(user?.name || ''); const [accessCode, setAccessCode] = useState(''); const [moderatorCode, setModeratorCode] = useState(''); const [status, setStatus] = useState({ running: false }); const [recordingConsent, setRecordingConsent] = useState(false); useEffect(() => { const fetchRoom = async () => { try { const res = await api.get(`/rooms/${uid}/public`); setRoomInfo(res.data.room); setStatus({ running: res.data.running }); } catch (err) { const status = err.response?.status; if (status === 403) { setError(t('room.guestAccessNotEnabled')); } else if (status === 404) { setError(t('room.guestRoomNotFound')); } else { setError(t('room.guestRoomNotFound')); } } finally { setLoading(false); } }; fetchRoom(); const interval = setInterval(async () => { try { const res = await api.get(`/rooms/${uid}/status`); setStatus(res.data); } catch { // ignore } }, 10000); return () => clearInterval(interval); }, [uid]); const handleJoin = async (e) => { e.preventDefault(); if (!name.trim()) { toast.error(t('room.guestNameRequired')); return; } if (roomInfo?.allow_recording && !recordingConsent) { toast.error(t('room.guestRecordingConsent')); return; } setJoining(true); try { const res = await api.post(`/rooms/${uid}/guest-join`, { name: name.trim(), access_code: accessCode || undefined, moderator_code: moderatorCode || undefined, }); if (res.data.joinUrl) { window.location.href = res.data.joinUrl; } } catch (err) { const status = err.response?.status; if (status === 403) { toast.error(t('room.guestWrongAccessCode')); } else if (status === 400) { toast.error(t('room.guestWaitingMessage')); } else { toast.error(t('room.guestJoinFailed')); } } finally { setJoining(false); } }; if (loading) { return (
); } if (error) { return (

{t('room.guestAccessDenied')}

{error}

{t('auth.login')}
); } return (
{/* Animated background */}
{/* Join card */}
{/* Logo */}
{/* Room info */}

{roomInfo.name}

{t('room.guestCreatedBy')} {roomInfo.owner_name}

{status.running ? : } {status.running ? t('room.guestMeetingRunning') : t('room.guestMeetingNotStarted')}
{/* Join form */}
!isLoggedIn && setName(e.target.value)} readOnly={isLoggedIn} className={`input-field pl-11 ${isLoggedIn ? 'opacity-70 cursor-not-allowed' : ''}`} placeholder={t('room.guestNamePlaceholder')} required autoFocus={!isLoggedIn} />
{roomInfo.has_access_code && (
setAccessCode(e.target.value)} className="input-field pl-11" placeholder={t('room.guestAccessCodePlaceholder')} />
)}
setModeratorCode(e.target.value)} className="input-field pl-11" placeholder={t('room.guestModeratorPlaceholder')} />
{/* Recording consent notice */} {roomInfo.allow_recording && (

{t('room.guestRecordingNotice')}

)} {!status.running && (

{t('room.guestWaitingMessage')}

)}
{!isLoggedIn && (
{t('room.guestHasAccount')} {t('room.guestSignIn')}
)} {(imprintUrl || privacyUrl) && (
{imprintUrl && ( {t('nav.imprint')} )} {imprintUrl && privacyUrl && ( ยท )} {privacyUrl && ( {t('nav.privacy')} )}
)}
); }