import { FormEvent, useEffect, useMemo, useState } from 'react'; import type { ReactNode } from 'react'; import { Head, useForm, usePage } from '@inertiajs/react'; import { useTranslation } from 'react-i18next'; import InputError from '@/components/input-error'; import TextLink from '@/components/text-link'; import { Button } from '@/components/ui/button'; import { Checkbox } from '@/components/ui/checkbox'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import AuthLayout from '@/layouts/auth-layout'; import AppLayout from '@/layouts/app/AppLayout'; import { request } from '@/routes/password'; import { useLocalizedRoutes } from '@/hooks/useLocalizedRoutes'; import { LoaderCircle } from 'lucide-react'; import toast from 'react-hot-toast'; interface LoginProps { status?: string; canResetPassword: boolean; } export default function Login({ status, canResetPassword }: LoginProps) { const [hasTriedSubmit, setHasTriedSubmit] = useState(false); const [rawReturnTo, setRawReturnTo] = useState(null); const [isRedirectingToGoogle, setIsRedirectingToGoogle] = useState(false); const [isRedirectingToFacebook, setIsRedirectingToFacebook] = useState(false); const { t } = useTranslation('auth'); const page = usePage<{ flash?: { verification?: { status: string; title?: string; message?: string } } }>(); const verificationFlash = page.props.flash?.verification; const { localizedPath } = useLocalizedRoutes(); const { data, setData, post, processing, errors, clearErrors } = useForm({ login: '', password: '', remember: false, return_to: '', }); const submit = (e: FormEvent) => { e.preventDefault(); setHasTriedSubmit(true); post(window.location.pathname, { preserveScroll: true, }); }; const errorKeys = Object.keys(errors); const hasErrors = errorKeys.length > 0; useEffect(() => { if (typeof window === 'undefined') { return; } const searchParams = new URLSearchParams(window.location.search); setRawReturnTo(searchParams.get('return_to')); if (searchParams.get('verified') === '1') { toast.success(t('verification.toast_success', 'Email verified successfully.')); searchParams.delete('verified'); const nextQuery = searchParams.toString(); const nextUrl = `${window.location.pathname}${nextQuery ? `?${nextQuery}` : ''}`; window.history.replaceState({}, '', nextUrl); } }, [t]); useEffect(() => { setData('return_to', rawReturnTo ?? ''); }, [rawReturnTo, setData]); useEffect(() => { if (!hasTriedSubmit) { return; } const keys = Object.keys(errors); if (keys.length === 0) { return; } const field = document.querySelector(`[name="${keys[0]}"]`); if (field) { field.scrollIntoView({ behavior: 'smooth', block: 'center' }); field.focus(); } }, [errors, hasTriedSubmit]); const googleHref = useMemo(() => { if (!rawReturnTo) { return '/event-admin/auth/google'; } const params = new URLSearchParams({ return_to: rawReturnTo, }); return `/event-admin/auth/google?${params.toString()}`; }, [rawReturnTo]); const facebookHref = useMemo(() => { if (!rawReturnTo) { return '/event-admin/auth/facebook'; } const params = new URLSearchParams({ return_to: rawReturnTo, }); return `/event-admin/auth/facebook?${params.toString()}`; }, [rawReturnTo]); const handleGoogleLogin = () => { if (typeof window === 'undefined') { return; } setIsRedirectingToGoogle(true); window.location.href = googleHref; }; const handleFacebookLogin = () => { if (typeof window === 'undefined') { return; } setIsRedirectingToFacebook(true); window.location.href = facebookHref; }; return (
{ setData('login', e.target.value); if (errors.login) { clearErrors('login'); } }} className="h-12 rounded-xl border-gray-200/80 bg-white/90 px-4 text-base shadow-inner shadow-gray-200/40 focus-visible:ring-[#ff8bb1]/40 dark:border-gray-800/70 dark:bg-gray-900/60 dark:text-gray-100" />
{canResetPassword && ( {t('login.forgot')} )}
{ setData('password', e.target.value); if (errors.password) { clearErrors('password'); } }} className="h-12 rounded-xl border-gray-200/80 bg-white/90 px-4 text-base shadow-inner shadow-gray-200/40 focus-visible:ring-[#ff8bb1]/40 dark:border-gray-800/70 dark:bg-gray-900/60 dark:text-gray-100" />
setData('remember', Boolean(checked))} />
{status && (
{status}
)} {verificationFlash && (
{verificationFlash.title ?? ''}
{verificationFlash.message}
)} {hasErrors && (
{Object.values(errors).join(' ')}
)}
{t('login.oauth_divider', 'oder')}

{t('login.google_helper', 'Nutze dein Google-Konto, um dich sicher bei der Eventverwaltung anzumelden.')}

{t('login.facebook_helper', 'Melde dich schnell mit deinem Facebook-Konto an.')}

{t('login.no_account')}{' '} {t('login.sign_up')}
); } Login.layout = (page: ReactNode) => }>{page}; function GoogleIcon({ className }: { className?: string }) { return ( ); } function FacebookIcon({ className }: { className?: string }) { return ( ); }