import React, { useState, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { useUsers, useCreateUser, useUpdateUser, useDeleteUser, useRoles } from '@/api/hooks'; import { Button } from '@/components/ui/Button'; import { Card } from '@/components/ui/Card'; import { Badge } from '@/components/ui/Badge'; import { Input } from '@/components/ui/Input'; import { Select } from '@/components/ui/Select'; import { EmptyState } from '@/components/ui/EmptyState'; import { Skeleton } from '@/components/ui/Skeleton'; import { Avatar } from '@/components/ui/Avatar'; import { Modal } from '@/components/ui/Modal'; import { ConfirmDialog } from '@/components/ui/ConfirmDialog'; import { useToast } from '@/components/ui/Toast'; const LEGACY_ROLES = [ { value: 'admin', label: 'Administrator' }, { value: 'manager', label: 'Manager' }, { value: 'user', label: 'Mitarbeiter' }, { value: 'guest', label: 'Gast' }, { value: 'viewer', label: 'Viewer' }, ]; export function SettingsUsersPage() { const { t } = useTranslation(); const toast = useToast(); const { data, isLoading } = useUsers(1, 100); const { data: rolesData } = useRoles(); const createUserMutation = useCreateUser(); const updateUserMutation = useUpdateUser(); const deleteUserMutation = useDeleteUser(); const [inviteOpen, setInviteOpen] = useState(false); const [inviteEmail, setInviteEmail] = useState(''); const [inviteName, setInviteName] = useState(''); const [invitePassword, setInvitePassword] = useState(''); const [inviteRoleId, setInviteRoleId] = useState(''); const [confirmDeactivate, setConfirmDeactivate] = useState(null); const [confirmDelete, setConfirmDelete] = useState(null); const users = data?.items ?? []; const customRoles = rolesData?.items ?? []; const roleOptions = useMemo(() => { const options = [...LEGACY_ROLES]; for (const role of customRoles) { options.push({ value: `role_id:${role.id}`, label: role.name }); } return options; }, [customRoles]); const roleLabelMap = useMemo(() => { const map = new Map(); for (const opt of roleOptions) { map.set(opt.value, opt.label); } return map; }, [roleOptions]); const getRoleValueForUser = (user: any): string => { if (user.role_id) { const key = `role_id:${user.role_id}`; if (roleLabelMap.has(key)) return key; } if (user.role) { const legacy = LEGACY_ROLES.find((r) => r.value === user.role); if (legacy) return legacy.value; } return 'viewer'; }; const handleInvite = async () => { if (!inviteEmail.trim() || !inviteName.trim() || !invitePassword.trim()) { toast.error(t('validation.required')); return; } if (invitePassword.length < 8) { toast.error(t('auth.passwordTooShort')); return; } try { const payload: any = { email: inviteEmail.trim(), name: inviteName.trim(), password: invitePassword, is_active: true, }; if (inviteRoleId.startsWith('role_id:')) { payload.role_id = inviteRoleId.substring('role_id:'.length); payload.role = 'viewer'; } else { payload.role = inviteRoleId || 'viewer'; } await createUserMutation.mutateAsync(payload); toast.success(t('settings.userInvited')); setInviteEmail(''); setInviteName(''); setInvitePassword(''); setInviteRoleId(''); setInviteOpen(false); } catch (err: any) { toast.error(err.message || t('common.error')); } }; const handleRoleChange = async (userId: string, newRoleValue: string) => { try { const data: any = {}; if (newRoleValue.startsWith('role_id:')) { data.role_id = newRoleValue.substring('role_id:'.length); data.role = 'viewer'; } else { data.role = newRoleValue; data.role_id = null; } await updateUserMutation.mutateAsync({ id: userId, data }); toast.success(t('settings.assignRole') + ' — OK'); } catch (err: any) { toast.error(err.message || t('common.error')); } }; const handleToggleActive = async () => { if (!confirmDeactivate) return; try { if (confirmDeactivate.is_active === false) { await updateUserMutation.mutateAsync({ id: confirmDeactivate.id, data: { is_active: true } }); toast.success(t('settings.userActivated')); } else { await updateUserMutation.mutateAsync({ id: confirmDeactivate.id, data: { is_active: false } }); toast.success(t('settings.userDeactivated')); } setConfirmDeactivate(null); } catch (err: any) { toast.error(err.message || t('common.error')); } }; const handleDeleteUser = async () => { if (!confirmDelete) return; try { await deleteUserMutation.mutateAsync(confirmDelete.id); toast.success(t('settings.userDeleted')); setConfirmDelete(null); } catch (err: any) { toast.error(err.message || t('common.error')); } }; if (isLoading) { return (
); } return (

{t('settings.users')}

{users.length === 0 ? ( setInviteOpen(true)}>{t('settings.inviteUser')}} /> ) : (
{users.map((user: any) => (

{user.name}

{user.email}

{user.is_active === false ? t('common.inactive') : t('common.active')}
setInviteName(e.target.value)} placeholder={t('settings.name')} data-testid="invite-name" /> setInviteEmail(e.target.value)} placeholder="neu.mitarbeiter@firma.de" data-testid="invite-email" /> setInvitePassword(e.target.value)} placeholder="********" data-testid="invite-password" />