import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useRoles, useCreateRole, useUpdateRole, useDeleteRole } from '@/api/hooks'; import { Input } from '@/components/ui/Input'; import { Button } from '@/components/ui/Button'; import { Card } from '@/components/ui/Card'; import { Badge } from '@/components/ui/Badge'; import { EmptyState } from '@/components/ui/EmptyState'; import { Skeleton } from '@/components/ui/Skeleton'; import { useToast } from '@/components/ui/Toast'; import { Modal } from '@/components/ui/Modal'; import { ConfirmDialog } from '@/components/ui/ConfirmDialog'; interface Role { id: string; name: string; permissions: Record; field_permissions?: Record; } const ALL_PERMISSIONS = [ { key: 'companies:read', label: 'Firmen lesen' }, { key: 'companies:write', label: 'Firmen bearbeiten' }, { key: 'contacts:read', label: 'Kontakte lesen' }, { key: 'contacts:write', label: 'Kontakte bearbeiten' }, { key: 'users:read', label: 'Benutzer lesen' }, { key: 'users:write', label: 'Benutzer bearbeiten' }, { key: 'audit:read', label: 'Audit-Log lesen' }, { key: 'settings:write', label: 'Einstellungen bearbeiten' }, ]; function isPermissionGranted(permissions: Record, permKey: string): boolean { if (!permissions) return false; if (typeof permissions === 'boolean') return permissions; if (Array.isArray(permissions)) return permissions.includes(permKey); if (typeof permissions === 'object') { if (permKey in permissions) { const val = permissions[permKey]; return val === true || val === 'true' || val === 1; } if ('all' in permissions && permissions.all === true) return true; } return false; } function togglePermission( permissions: Record, permKey: string ): Record { const current = isPermissionGranted(permissions, permKey); return { ...permissions, [permKey]: !current }; } function getGrantedPermissionKeys(permissions: Record): string[] { if (!permissions) return []; if (Array.isArray(permissions)) return permissions as string[]; if (typeof permissions === 'object') { return Object.keys(permissions).filter( (k) => k !== 'all' && permissions[k] === true ); } return []; } export function SettingsRolesPage() { const { t } = useTranslation(); const toast = useToast(); const { data, isLoading, isError, error, refetch } = useRoles(); const createRoleMutation = useCreateRole(); const updateRoleMutation = useUpdateRole(); const deleteRoleMutation = useDeleteRole(); const [createOpen, setCreateOpen] = useState(false); const [newRoleName, setNewRoleName] = useState(''); const [newRolePermissions, setNewRolePermissions] = useState>({}); const [editingRole, setEditingRole] = useState(null); const [confirmDelete, setConfirmDelete] = useState(null); const roles: Role[] = data?.items ?? []; const handleCreateRole = async () => { if (!newRoleName.trim()) { toast.error(t('validation.required')); return; } try { await createRoleMutation.mutateAsync({ name: newRoleName.trim(), permissions: newRolePermissions, field_permissions: {}, }); toast.success(t('settings.roleCreated')); setNewRoleName(''); setNewRolePermissions({}); setCreateOpen(false); } catch (err: any) { toast.error(err.message || t('common.error')); } }; const handleTogglePermission = (permKey: string, target: 'new' | 'edit') => { if (target === 'new') { setNewRolePermissions((prev) => togglePermission(prev, permKey)); } else if (editingRole) { setEditingRole({ ...editingRole, permissions: togglePermission(editingRole.permissions, permKey), }); } }; const handleSaveRole = async () => { if (!editingRole) return; try { await updateRoleMutation.mutateAsync({ id: editingRole.id, data: { name: editingRole.name, permissions: editingRole.permissions, field_permissions: editingRole.field_permissions || {}, }, }); toast.success(t('settings.roleUpdated')); setEditingRole(null); } catch (err: any) { toast.error(err.message || t('common.error')); } }; const handleDeleteRole = async () => { if (!confirmDelete) return; try { await deleteRoleMutation.mutateAsync(confirmDelete.id); toast.success(t('settings.roleDeleted')); setConfirmDelete(null); } catch (err: any) { toast.error(err.message || t('common.error')); } }; if (isLoading) { return (
); } if (isError) { return (

{t('settings.roles')}

refetch()}>{t('common.reset')}} >

{error?.message || t('common.error')}

); } return (

{t('settings.roles')}

{roles.length === 0 ? ( setCreateOpen(true)}>{t('settings.createRole')}} /> ) : (
{roles.map((role) => { const grantedKeys = getGrantedPermissionKeys(role.permissions); return (

{role.name}

{grantedKeys.length === 0 ? ( ) : ( grantedKeys.map((perm) => { const label = ALL_PERMISSIONS.find((p) => p.key === perm)?.label || perm; return {label}; }) )}
); })}
)} setCreateOpen(false)} title={t('settings.createRole')}>
setNewRoleName(e.target.value)} placeholder="z.B. Vertrieb" data-testid="new-role-name" />
{ALL_PERMISSIONS.map((perm) => ( ))}
setEditingRole(null)} title={t('settings.roles') + ' — ' + (editingRole?.name || '')}> {editingRole && (
setEditingRole({ ...editingRole, name: e.target.value })} />
{ALL_PERMISSIONS.map((perm) => ( ))}
)}
setConfirmDelete(null)} />
); }