import { useEffect, useRef, useState } from 'react'; type Props = { url?: string; locale?: 'ru' | 'en'; theme?: 'light' | 'dark' | 'auto'; services?: string[]; className?: string; }; type WidgetStatus = 'operational' | 'degraded' | 'down' | 'unknown' | 'maintenance'; /** Embed the public RideBus status without sharing app sessions or API keys. */ export default function StatusWidget({ url, locale = 'ru', theme = 'auto', services = [], className }: Props) { const frame = useRef(null); const [ready, setReady] = useState(false); const [status, setStatus] = useState('unknown'); let source = '', origin = '', destination = ''; try { if (url) { const target = new URL(url); if (!['https:', 'http:'].includes(target.protocol) || target.username || target.password) throw new Error('Invalid status URL'); origin = target.origin; destination = new URL(`/?lang=${locale}`, origin).href; const embed = new URL('/embed', origin); embed.searchParams.set('lang', locale); embed.searchParams.set('theme', theme); if (services.length) embed.searchParams.set('services', services.join(',')); source = embed.href; } } catch { /* An unset or invalid deployment URL leaves the widget disabled. */ } const title = locale === 'ru' ? 'Статус сервисов RideBus' : 'RideBus service status'; const fallback = locale === 'ru' ? 'Статус не получен' : 'Status unavailable'; const labels: Record = locale === 'ru' ? { operational: 'Сервисы работают', degraded: 'Есть перебои', down: 'Сервисы недоступны', unknown: 'Нет свежих данных', maintenance: 'Плановые работы' } : { operational: 'Services operational', degraded: 'Service disruption', down: 'Services unavailable', unknown: 'No fresh status data', maintenance: 'Scheduled maintenance' }; useEffect(() => { setReady(false); if (!source) return; let lastUpdate = 0; const request = () => frame.current?.contentWindow?.postMessage({ type: 'ridebus-status-widget-request' }, origin); function receive(event: MessageEvent) { if (event.origin !== origin || event.source !== frame.current?.contentWindow || event.data?.type !== 'ridebus-status-widget' || event.data.version !== 1 || !['operational', 'degraded', 'down', 'unknown', 'maintenance'].includes(event.data.status)) return; lastUpdate = Date.now(); setStatus(event.data.status); setReady(true); } function visible() { if (!document.hidden) { if (Date.now() - lastUpdate >= 90000) setReady(false); request(); } } const timer = setInterval(() => { if (lastUpdate && Date.now() - lastUpdate >= 90000) setReady(false); }, 5000); window.addEventListener('message', receive); window.addEventListener('online', request); document.addEventListener('visibilitychange', visible); request(); return () => { clearInterval(timer); window.removeEventListener('message', receive); window.removeEventListener('online', request); document.removeEventListener('visibilitychange', visible); }; }, [source, origin]); if (!source) return null; return