Initial commit from template

This commit is contained in:
Lumina
2025-12-23 04:19:57 +01:00
commit b3d8fe8dfe
76 changed files with 10491 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
'use client';
import { useState } from 'react';
import { useAuth } from '@/contexts/AuthContext';
interface LoginFormProps {
onSuccess?: () => void;
redirectTo?: string;
}
export function LoginForm({ onSuccess, redirectTo = '/dashboard' }: LoginFormProps) {
const { signIn, signInWithOAuth } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setError(null);
const { error } = await signIn(email, password);
if (error) {
setError(getErrorMessage(error.message));
setLoading(false);
} else {
onSuccess?.();
window.location.href = redirectTo;
}
};
const handleOAuth = async (provider: 'google' | 'github') => {
setLoading(true);
await signInWithOAuth(provider);
};
return (
<div className="space-y-6 w-full max-w-sm">
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="email" className="block text-sm font-medium mb-1">
Email
</label>
<input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full px-3 py-2 border rounded-md"
required
/>
</div>
<div>
<label htmlFor="password" className="block text-sm font-medium mb-1">
Passwort
</label>
<input
id="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full px-3 py-2 border rounded-md"
required
/>
</div>
{error && (
<p className="text-sm text-red-500">{error}</p>
)}
<button
type="submit"
disabled={loading}
className="w-full py-2 px-4 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50"
>
{loading ? 'Wird geladen...' : 'Anmelden'}
</button>
</form>
<div className="relative">
<div className="absolute inset-0 flex items-center">
<span className="w-full border-t" />
</div>
<div className="relative flex justify-center text-xs uppercase">
<span className="bg-background px-2 text-muted-foreground">
Oder weiter mit
</span>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<button
type="button"
onClick={() => handleOAuth('google')}
disabled={loading}
className="py-2 px-4 border rounded-md hover:bg-muted disabled:opacity-50"
>
Google
</button>
<button
type="button"
onClick={() => handleOAuth('github')}
disabled={loading}
className="py-2 px-4 border rounded-md hover:bg-muted disabled:opacity-50"
>
GitHub
</button>
</div>
</div>
);
}
function getErrorMessage(message: string): string {
const errorMap: Record<string, string> = {
'Invalid login credentials': 'Ungueltige Anmeldedaten',
'Email not confirmed': 'Bitte bestaetigen Sie zuerst Ihre Email',
'Too many requests': 'Zu viele Versuche. Bitte warten Sie einen Moment.',
};
return errorMap[message] || 'Ein Fehler ist aufgetreten';
}