geraete/components/auth/LoginForm.tsx
2025-11-24 08:59:14 +01:00

156 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// components/auth/LoginForm.tsx
'use client';
import * as React from 'react';
import Button from '@/components/ui/Button';
type LoginValues = {
identifier: string;
password: string;
};
export interface LoginFormProps {
title?: string;
subtitle?: string;
onSubmit?: (values: LoginValues) => void | Promise<void>;
isSubmitting?: boolean;
errorMessage?: string | null;
}
const LoginForm: React.FC<LoginFormProps> = ({
title = 'Bitte melde dich an',
subtitle,
onSubmit,
isSubmitting,
errorMessage,
}) => {
const [form, setForm] = React.useState<LoginValues>({
identifier: '',
password: '',
});
const handleChange =
(field: keyof LoginValues) =>
(e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setForm((prev) => ({ ...prev, [field]: value }));
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!onSubmit) return;
await onSubmit(form);
};
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
{/* Header */}
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<img
alt="Your Company"
src="https://tailwindcss.com/plus-assets/img/logos/mark.svg?color=indigo&shade=600"
className="mx-auto h-10 w-auto dark:hidden"
/>
<img
alt="Your Company"
src="https://tailwindcss.com/plus-assets/img/logos/mark.svg?color=indigo&shade=500"
className="mx-auto h-10 w-auto not-dark:hidden"
/>
<h2 className="mt-6 text-center text-2xl/9 font-bold tracking-tight text-gray-900 dark:text-white">
{title}
</h2>
{subtitle && (
<p className="mt-2 text-center text-sm text-gray-500 dark:text-gray-400">
{subtitle}
</p>
)}
</div>
{/* Card */}
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-[480px]">
<div className="bg-white px-6 py-12 shadow-sm sm:rounded-lg sm:px-12 dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
<form className="space-y-6" onSubmit={handleSubmit}>
{/* Benutzername / E-Mail */}
<div>
<label
htmlFor="identifier"
className="block text-sm/6 font-medium text-gray-900 dark:text-white"
>
NW-Kennung oder E-Mail
</label>
<div className="mt-2">
<input
id="identifier"
name="identifier"
type="text"
required
autoComplete="username"
value={form.identifier}
onChange={handleChange('identifier')}
className="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6 dark:bg-white/5 dark:text-white dark:outline-white/10 dark:placeholder:text-gray-500 dark:focus:outline-indigo-500"
/>
</div>
</div>
{/* Passwort */}
<div>
<label
htmlFor="password"
className="block text-sm/6 font-medium text-gray-900 dark:text-white"
>
Passwort
</label>
<div className="mt-2">
<input
id="password"
name="password"
type="password"
required
autoComplete="current-password"
value={form.password}
onChange={handleChange('password')}
className="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6 dark:bg-white/5 dark:text-white dark:outline-white/10 dark:placeholder:text-gray-500 dark:focus:outline-indigo-500"
/>
</div>
</div>
{/* Optional: Passwort vergessen Link kannst du lassen oder entfernen */}
<div className="flex items-center justify-end">
<div className="text-sm/6">
<a
href="#"
className="font-semibold text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300"
>
Passwort vergessen?
</a>
</div>
</div>
{/* Error */}
{errorMessage && (
<p className="text-sm text-red-600 dark:text-red-400">
{errorMessage}
</p>
)}
{/* Submit */}
<div>
<Button
type="submit"
variant="primary"
size="lg"
className="w-full justify-center"
disabled={isSubmitting}
>
{isSubmitting ? 'Wird angemeldet…' : 'Anmelden'}
</Button>
</div>
</form>
</div>
</div>
</div>
);
};
export default LoginForm;