62 lines
2.0 KiB
TypeScript
62 lines
2.0 KiB
TypeScript
import React from 'react';
|
|
import { Location, useLocation, useNavigate } from 'react-router-dom';
|
|
import { Button } from '@/components/ui/button';
|
|
import AppearanceToggleDropdown from '@/components/appearance-dropdown';
|
|
import { useAuth } from '../auth/context';
|
|
|
|
interface LocationState {
|
|
from?: Location;
|
|
}
|
|
|
|
export default function LoginPage() {
|
|
const { status, login } = useAuth();
|
|
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', { 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';
|
|
}, [location.state]);
|
|
|
|
return (
|
|
<div className="mx-auto flex min-h-screen max-w-sm flex-col justify-center p-6">
|
|
<div className="mb-6 flex items-center justify-between">
|
|
<h1 className="text-lg font-semibold">Tenant Admin</h1>
|
|
<AppearanceToggleDropdown />
|
|
</div>
|
|
<div className="space-y-4 text-sm text-muted-foreground">
|
|
<p>
|
|
Melde dich mit deinem Fotospiel-Account an. Du wirst zur sicheren OAuth-Anmeldung weitergeleitet und danach
|
|
wieder zur Admin-Oberfläche gebracht.
|
|
</p>
|
|
{oauthError && (
|
|
<div className="rounded border border-red-300 bg-red-50 p-2 text-sm text-red-700">
|
|
Anmeldung fehlgeschlagen: {oauthError}
|
|
</div>
|
|
)}
|
|
<Button
|
|
className="w-full"
|
|
disabled={status === 'loading'}
|
|
onClick={() => login(redirectTarget)}
|
|
>
|
|
{status === 'loading' ? 'Bitte warten …' : 'Mit Tenant-Account anmelden'}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|