import React from 'react'; import { Location, useLocation, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Sparkles, ShieldCheck, Images, ArrowRight, Loader2 } from 'lucide-react'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import { Button } from '@/components/ui/button'; import AppearanceToggleDropdown from '@/components/appearance-dropdown'; import AppLogoIcon from '@/components/app-logo-icon'; import { useAuth } from '../auth/context'; import { ADMIN_HOME_PATH } from '../constants'; interface LocationState { from?: Location; } const featureIcons = [Sparkles, ShieldCheck, Images]; export default function LoginPage(): JSX.Element { const { status, login } = useAuth(); const { t } = useTranslation('auth'); const location = useLocation(); const navigate = useNavigate(); const searchParams = React.useMemo(() => new URLSearchParams(location.search), [location.search]); const oauthError = searchParams.get('error'); React.useEffect(() => { if (status === 'authenticated') { navigate(ADMIN_HOME_PATH, { replace: true }); } }, [status, navigate]); const redirectTarget = React.useMemo(() => { const state = location.state as LocationState | null; if (state?.from) { const from = state.from; const search = from.search ?? ''; const hash = from.hash ?? ''; return `${from.pathname}${search}${hash}`; } return ADMIN_HOME_PATH; }, [location.state]); const featureList = React.useMemo(() => { const raw = t('login.features', { returnObjects: true }) as unknown; if (!Array.isArray(raw)) { return [] as Array<{ text: string; Icon: typeof Sparkles }>; } return (raw as string[]).map((entry, index) => ({ text: entry, Icon: featureIcons[index % featureIcons.length], })); }, [t]); const heroTagline = t('login.hero_tagline', 'Stay in control, stay relaxed'); const heroTitle = t('login.hero_title', 'Your cockpit for every Fotospiel event'); const heroSubtitle = t('login.hero_subtitle', 'Moderation, uploads, and communication come together in one calm workspace — on desktop and mobile.'); const panelTitle = t('login.panel_title', t('login.title', 'Event Admin')); const leadCopy = t('login.lead', 'Use our secure OAuth login and land directly in the event dashboard.'); const panelCopy = t('login.panel_copy', 'Sign in with your Fotospiel admin access. OAuth 2.1 and clear role permissions keep your account protected.'); const supportCopy = t('login.support', "Need access? Contact your event team or email support@fotospiel.de — we're happy to help."); const isLoading = status === 'loading'; return (

{t('login.badge', 'Fotospiel Event Admin')}

Fotospiel

{heroTagline}

{heroTitle}

{heroSubtitle}

{heroTagline}

{heroTitle}

{heroSubtitle}

{featureList.length ? (
    {featureList.map(({ text, Icon }, index) => (
  • {text}

  • ))}
) : null}

{leadCopy}

{t('login.badge', 'Fotospiel Event Admin')}

{panelTitle}

{panelCopy}

{oauthError ? ( {t('login.oauth_error_title')} {t('login.oauth_error', { message: oauthError })} ) : null}

{leadCopy}

{supportCopy}

{featureList.length ? (
{featureList.map(({ text, Icon }, index) => (

{text}

))}
) : null}
); }