import { useEffect, useState } from 'react'; import { api } from '../../../api/client'; import { useT, type TranslationKey } from '../../../i18n'; /** Errors the OAuth callback can hand back in the URL. */ const CALLBACK_ERRORS = ['denied', 'invalid_state', 'exchange_failed'] as const; type CallbackError = (typeof CALLBACK_ERRORS)[number]; function readCallbackResult(): CallbackError | 'connected' | null { if (typeof window === 'undefined') return null; const value = new URLSearchParams(window.location.search).get('spotify'); if (value === 'connected') return 'connected'; return CALLBACK_ERRORS.includes(value as CallbackError) ? (value as CallbackError) : null; } export function ConnectionsPanel() { const t = useT(); const [configured, setConfigured] = useState(true); const [connected, setConnected] = useState(false); const [busy, setBusy] = useState(false); const [callbackError, setCallbackError] = useState(null); useEffect(() => { const result = readCallbackResult(); if (result && result !== 'connected') setCallbackError(result); // Drop the parameter so a refresh does not replay the old outcome. if (result && typeof window !== 'undefined') { const url = new URL(window.location.href); url.searchParams.delete('spotify'); window.history.replaceState({}, '', url.toString()); } }, []); useEffect(() => { let cancelled = false; api.spotify.status() .then((s) => { if (!cancelled) { setConfigured(s.configured); setConnected(s.connected); } }) .catch(() => { /* leave the panel in its default state */ }); return () => { cancelled = true; }; }, []); const handleConnect = async () => { setBusy(true); try { const { url } = await api.spotify.authorizeUrl(); window.location.href = url; } catch { setBusy(false); } }; const handleDisconnect = async () => { setBusy(true); try { await api.spotify.disconnect(); setConnected(false); } finally { setBusy(false); } }; return (

{t('connections.title')}

Spotify {connected && ( {t('connections.spotify.connected')} )}

{t('connections.spotify.description')}

{t('connections.spotify.hint')}

{configured && ( )}
{!configured && (

{t('connections.spotify.notConfigured')}

)} {callbackError && (

{t(`connections.spotify.error.${callbackError}` as TranslationKey)}

)}
); }