+
+
+
Feature-Benutzer
+
Verwalten Sie Benutzerzugriffe auf Feature-Instanzen
+
+
+
+ {/* Selectors */}
+
+
+
+
+
+
+ {selectedMandateId && (
+
+
+
+
+ )}
+
+ {selectedInstanceId && (
+
+
+
+
+ )}
+
+
+ {/* Info box when instance is selected */}
+ {selectedInstance && instanceRoles.length > 0 && (
+
+
+ Verfügbare Rollen:
+ {instanceRoles.map((r, i) => (
+
+ {i > 0 && ', '}
+ {r.roleLabel}
+
+ ))}
+
+ )}
+
+ {/* Warning if no roles available */}
+ {selectedInstance && instanceRoles.length === 0 && !usersLoading && (
+
+ ⚠️
+ Diese Instanz hat noch keine Rollen. Bitte synchronisieren Sie die Rollen zuerst unter "Feature-Instanzen".
+
+ )}
+
+ {/* Content */}
+ {!selectedMandateId ? (
+
+
+
Kein Mandant ausgewählt
+
+ Wählen Sie einen Mandanten aus, um dessen Feature-Instanzen zu sehen.
+
+
+ ) : !selectedInstanceId ? (
+
+
+
Keine Feature-Instanz ausgewählt
+
+ {instances.length === 0
+ ? 'Dieser Mandant hat noch keine Feature-Instanzen.'
+ : 'Wählen Sie eine Feature-Instanz aus, um deren Benutzer zu verwalten.'}
+
+
+ ) : usersLoading && instanceUsers.length === 0 ? (
+
+ ) : instanceUsers.length === 0 ? (
+
+
+
Keine Benutzer
+
+ Dieser Feature-Instanz sind noch keine Benutzer zugewiesen.
+
+
+
+ ) : (
+
+ {
+ // Find user by FeatureAccess ID to get userId for API call
+ const user = instanceUsers.find(u => u.id === featureAccessId);
+ if (user) {
+ const result = await removeUserFromInstance(selectedMandateId, selectedInstanceId, user.userId);
+ return result.success;
+ }
+ return false;
+ },
+ }}
+ emptyMessage="Keine Benutzer gefunden"
+ />
+
+ )}
+
+ {/* Add User Modal */}
+ {showAddModal && (
+
setShowAddModal(false)}>
+
e.stopPropagation()}>
+
+
Benutzer zur Feature-Instanz hinzufügen
+
+
+
+ {availableUsers.length === 0 ? (
+
Alle Benutzer haben bereits Zugriff auf diese Feature-Instanz.
+ ) : instanceRoles.length === 0 ? (
+
Diese Feature-Instanz hat keine Rollen. Bitte synchronisieren Sie zuerst die Rollen.
+ ) : (
+
setShowAddModal(false)}
+ submitButtonText="Hinzufügen"
+ cancelButtonText="Abbrechen"
+ />
+ )}
+
+
+
+ )}
+
+ {/* Edit Roles Modal */}
+ {editingUser && (
+
setEditingUser(null)}>
+
e.stopPropagation()}>
+
+
Rollen bearbeiten: {editingUser.username}
+
+
+
+ setEditingUser(null)}
+ submitButtonText="Speichern"
+ cancelButtonText="Abbrechen"
+ />
+
+
+
+ )}
+
+ );
+};
+
+export default AdminFeatureInstanceUsersPage;
diff --git a/src/pages/admin/AdminInvitationsPage.tsx b/src/pages/admin/AdminInvitationsPage.tsx
index bbeed51..20e1fcb 100644
--- a/src/pages/admin/AdminInvitationsPage.tsx
+++ b/src/pages/admin/AdminInvitationsPage.tsx
@@ -5,8 +5,8 @@
* Allows creating, viewing, and revoking invitations.
*/
-import React, { useState, useEffect, useMemo } from 'react';
-import { useInvitations, type Invitation, type InvitationCreate } from '../../hooks/useInvitations';
+import React, { useState, useEffect, useMemo, useCallback } from 'react';
+import { useInvitations, type Invitation, type InvitationCreate, type PaginationParams } from '../../hooks/useInvitations';
import { useUserMandates, type Mandate, type Role } from '../../hooks/useUserMandates';
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
import { FormGeneratorForm, type AttributeDefinition } from '../../components/FormGenerator/FormGeneratorForm';
@@ -19,6 +19,7 @@ export const AdminInvitationsPage: React.FC = () => {
invitations,
loading,
error,
+ pagination,
fetchInvitations,
createInvitation,
revokeInvitation,
@@ -353,7 +354,8 @@ export const AdminInvitationsPage: React.FC = () => {
]}
onDelete={handleRevokeInvitation}
hookData={{
- refetch: () => fetchInvitations(selectedMandateId, { includeExpired: showExpired, includeUsed: showUsed }),
+ refetch: fetchInvitations,
+ pagination,
}}
emptyMessage="Keine Einladungen gefunden"
/>
diff --git a/src/pages/admin/AdminMandateRolesPage.tsx b/src/pages/admin/AdminMandateRolesPage.tsx
index a931f45..d6f167e 100644
--- a/src/pages/admin/AdminMandateRolesPage.tsx
+++ b/src/pages/admin/AdminMandateRolesPage.tsx
@@ -5,8 +5,8 @@
* Allows creating, viewing, editing, and deleting mandate-level roles.
*/
-import React, { useState, useEffect, useMemo } from 'react';
-import { useMandateRoles, type Role, type RoleCreate, type RoleUpdate } from '../../hooks/useMandateRoles';
+import React, { useState, useEffect, useMemo, useCallback } from 'react';
+import { useMandateRoles, type Role, type RoleCreate, type RoleUpdate, type PaginationParams } from '../../hooks/useMandateRoles';
import { useUserMandates, type Mandate } from '../../hooks/useUserMandates';
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
import { FormGeneratorForm, type AttributeDefinition } from '../../components/FormGenerator/FormGeneratorForm';
@@ -19,6 +19,7 @@ export const AdminMandateRolesPage: React.FC = () => {
roles,
loading,
error,
+ pagination,
fetchRoles,
createRole,
updateRole,
@@ -60,7 +61,16 @@ export const AdminMandateRolesPage: React.FC = () => {
}
}, [selectedMandateId, fetchRoles]);
+ // Refetch wrapper that accepts pagination params from FormGeneratorTable
+ const refetchWithPagination = useCallback(async (paginationParams?: PaginationParams) => {
+ if (!selectedMandateId) return;
+ // Pass pagination params to fetchRoles
+ return fetchRoles(paginationParams || {});
+ }, [selectedMandateId, fetchRoles]);
+
// Filter roles based on selection and add scopeType field
+ // Note: This client-side filtering is still needed for the roleFilter dropdown
+ // Backend pagination handles page/sort/search, but roleFilter is UI-specific
const filteredRoles = useMemo(() => {
if (!selectedMandateId) return [];
@@ -433,7 +443,8 @@ export const AdminMandateRolesPage: React.FC = () => {
]}
onDelete={handleDeleteRole}
hookData={{
- refetch: () => fetchRoles(selectedMandateId),
+ refetch: refetchWithPagination,
+ pagination: pagination,
handleDelete: handleDeleteRole,
}}
emptyMessage="Keine Rollen gefunden"
diff --git a/src/pages/admin/AdminUserMandatesPage.tsx b/src/pages/admin/AdminUserMandatesPage.tsx
index f517963..cfa5b8d 100644
--- a/src/pages/admin/AdminUserMandatesPage.tsx
+++ b/src/pages/admin/AdminUserMandatesPage.tsx
@@ -5,8 +5,8 @@
* Allows assigning users to mandates and managing their roles within mandates.
*/
-import React, { useState, useEffect, useMemo } from 'react';
-import { useUserMandates, type MandateUser, type Mandate, type Role } from '../../hooks/useUserMandates';
+import React, { useState, useEffect, useMemo, useCallback } from 'react';
+import { useUserMandates, type MandateUser, type Mandate, type Role, type PaginationParams } from '../../hooks/useUserMandates';
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
import { FormGeneratorForm, type AttributeDefinition } from '../../components/FormGenerator/FormGeneratorForm';
import { FaPlus, FaSync, FaUsers, FaBuilding } from 'react-icons/fa';
@@ -18,6 +18,7 @@ export const AdminUserMandatesPage: React.FC = () => {
users,
loading,
error,
+ pagination,
fetchMandateUsers,
addUserToMandate,
removeUserFromMandate,
@@ -356,17 +357,18 @@ export const AdminUserMandatesPage: React.FC = () => {
]}
onDelete={handleRemoveUser}
hookData={{
- refetch: () => fetchMandateUsers(selectedMandateId),
- handleDelete: async (userId: string) => {
- const user = users.find(u => u.userId === userId);
+ refetch: fetchMandateUsers,
+ pagination,
+ handleDelete: async (userMandateId: string) => {
+ // Find user by UserMandate ID to get userId for API call
+ const user = users.find(u => u.id === userMandateId);
if (user) {
- const result = await removeUserFromMandate(selectedMandateId, userId);
+ const result = await removeUserFromMandate(selectedMandateId, user.userId);
return result.success;
}
return false;
},
}}
- idField="userId"
emptyMessage="Keine Mitglieder gefunden"
/>
diff --git a/src/pages/admin/index.ts b/src/pages/admin/index.ts
index f896a5d..67215b4 100644
--- a/src/pages/admin/index.ts
+++ b/src/pages/admin/index.ts
@@ -10,4 +10,5 @@ export { AdminRolesPage } from './AdminRolesPage';
export { AdminUserMandatesPage } from './AdminUserMandatesPage';
export { AdminFeatureAccessPage } from './AdminFeatureAccessPage';
export { AdminInvitationsPage } from './AdminInvitationsPage';
-export { AdminMandateRolesPage } from './AdminMandateRolesPage';
\ No newline at end of file
+export { AdminMandateRolesPage } from './AdminMandateRolesPage';
+export { AdminFeatureInstanceUsersPage } from './AdminFeatureInstanceUsersPage';
\ No newline at end of file