import { useState, useEffect, type FormEvent } from 'react'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { Modal } from '../components/Modal'; import api from '../api/client'; interface User { id: string; email: string; firstName: string; lastName: string; role: string; isActive: boolean; lastLogin: string | null; createdAt: string; } interface UserFormModalProps { isOpen: boolean; onClose: () => void; user?: User | null; onSuccess: () => void; } const ROLE_OPTIONS = [ { value: 'USER', label: 'Benutzer' }, { value: 'TENANT_ADMIN', label: 'Mandanten-Admin' }, { value: 'PLATFORM_ADMIN', label: 'Plattform-Admin' }, ]; const ROLE_LABELS: Record = { USER: 'Benutzer', TENANT_ADMIN: 'Mandanten-Admin', PLATFORM_ADMIN: 'Plattform-Admin', }; const inputStyle: React.CSSProperties = { width: '100%', padding: '0.625rem 0.75rem', border: '1px solid var(--color-border)', borderRadius: 'var(--radius-sm)', fontSize: '0.9375rem', outline: 'none', boxSizing: 'border-box', }; const inputDisabledStyle: React.CSSProperties = { ...inputStyle, background: '#f3f4f6', color: 'var(--color-text-muted)', cursor: 'not-allowed', }; const labelStyle: React.CSSProperties = { display: 'block', fontSize: '0.875rem', fontWeight: 500, color: 'var(--color-text)', marginBottom: '0.25rem', }; export function UserFormModal({ isOpen, onClose, user, onSuccess }: UserFormModalProps) { const isEditMode = !!user; const queryClient = useQueryClient(); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); const [role, setRole] = useState('USER'); const [isActive, setIsActive] = useState(true); const [error, setError] = useState(''); const [success, setSuccess] = useState(''); useEffect(() => { if (isOpen) { setError(''); setSuccess(''); if (user) { setEmail(user.email); setFirstName(user.firstName); setLastName(user.lastName); setRole(user.role); setIsActive(user.isActive); setPassword(''); } else { setEmail(''); setPassword(''); setFirstName(''); setLastName(''); setRole('USER'); setIsActive(true); } } }, [isOpen, user]); const createMutation = useMutation({ mutationFn: (data: { email: string; password: string; firstName: string; lastName: string; role: string }) => api.post('/users', data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin', 'users'] }); setSuccess('Benutzer wurde erfolgreich angelegt.'); setTimeout(() => onSuccess(), 1000); }, onError: (err: unknown) => { const message = (err as { response?: { data?: { message?: string } } })?.response?.data?.message; setError(message ?? 'Fehler beim Anlegen des Benutzers.'); }, }); const updateMutation = useMutation({ mutationFn: (data: { firstName: string; lastName: string; isActive: boolean }) => api.patch(`/users/${user!.id}`, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin', 'users'] }); setSuccess('Änderungen wurden gespeichert.'); setTimeout(() => onSuccess(), 1000); }, onError: (err: unknown) => { const message = (err as { response?: { data?: { message?: string } } })?.response?.data?.message; setError(message ?? 'Fehler beim Speichern der Änderungen.'); }, }); const isLoading = createMutation.isPending || updateMutation.isPending; const handleSubmit = (e: FormEvent) => { e.preventDefault(); setError(''); setSuccess(''); if (!firstName.trim() || !lastName.trim()) { setError('Vor- und Nachname sind Pflichtfelder.'); return; } if (isEditMode) { updateMutation.mutate({ firstName: firstName.trim(), lastName: lastName.trim(), isActive }); } else { if (!email.trim()) { setError('E-Mail-Adresse ist ein Pflichtfeld.'); return; } if (password.length < 8) { setError('Passwort muss mindestens 8 Zeichen lang sein.'); return; } createMutation.mutate({ email: email.trim(), password, firstName: firstName.trim(), lastName: lastName.trim(), role, }); } }; return (
{error && (
{error}
)} {success && (
{success}
)}
{/* E-Mail */}
setEmail(e.target.value)} disabled={isEditMode} style={isEditMode ? inputDisabledStyle : inputStyle} placeholder="max.mustermann@beispiel.de" required={!isEditMode} />
{/* Passwort (nur Anlegen) */} {!isEditMode && (
setPassword(e.target.value)} style={inputStyle} placeholder="Mindestens 8 Zeichen" minLength={8} maxLength={128} required />
)} {/* Vorname + Nachname nebeneinander */}
setFirstName(e.target.value)} style={inputStyle} placeholder="Vorname" maxLength={100} required />
setLastName(e.target.value)} style={inputStyle} placeholder="Nachname" maxLength={100} required />
{/* Rolle */}
{isEditMode ? ( ) : ( )}
{/* Aktiv-Status (nur Bearbeiten) */} {isEditMode && (
setIsActive(e.target.checked)} style={{ width: 16, height: 16, cursor: 'pointer' }} />
)}
{/* Buttons */}
); }