Create Organisation Fix

This commit is contained in:
2026-10-20 12:47:06 +02:00
parent 28a821ae91
commit d7a168c9fa
17 changed files with 527 additions and 155 deletions
@@ -35,11 +35,13 @@ import {
Hash,
ChevronDown,
ChevronRight,
ChevronLeft,
User as UserIcon,
RotateCcw,
} from 'lucide-react';
import { CreateUserModal } from '../components/users/CreateUserModal';
import { UserSecurityModal } from '../components/users/UserSecurityModal';
import { ObfuscatedIdNumber } from '../components/ui/ObfuscatedIdNumber';
import { useRbac } from '../auth/rbac';
import {
getUsers,
@@ -127,6 +129,13 @@ export const SettingsPage: React.FC = () => {
const [isUserDetailModalOpen, setIsUserDetailModalOpen] = useState(false);
const [isCreateUserModalOpen, setIsCreateUserModalOpen] = useState(false);
const [userPage, setUserPage] = useState(1);
const [userPageSize, setUserPageSize] = useState(10);
React.useEffect(() => {
setUserPage(1);
}, [userEmailSearch, userStatusFilter, userRoleFilter]);
const userFilter: UserFilterRequest = {
email: userEmailSearch.trim() || undefined,
status: userStatusFilter !== 'all' ? userStatusFilter : undefined,
@@ -145,7 +154,7 @@ export const SettingsPage: React.FC = () => {
refetch: refetchUsers,
} = useQuery({
queryKey: ['users', userStatusFilter, userEmailSearch],
queryFn: () => getUsers(1, 100, userFilter),
queryFn: () => getUsers(1, 1000, userFilter),
});
const filteredUsers = useMemo(() => {
@@ -489,6 +498,13 @@ export const SettingsPage: React.FC = () => {
role: (u: User) => getUserRoleBadge(u.role).label,
});
const totalUsers = sortedUsers.length;
const totalPages = Math.max(1, Math.ceil(totalUsers / userPageSize));
const paginatedUsers = React.useMemo(() => {
const start = (userPage - 1) * userPageSize;
return sortedUsers.slice(start, start + userPageSize);
}, [sortedUsers, userPage, userPageSize]);
const {
sortedData: sortedInvites,
sortColumn: inviteSortCol,
@@ -842,7 +858,7 @@ export const SettingsPage: React.FC = () => {
</td>
</tr>
) : (
sortedUsers.map((u) => {
paginatedUsers.map((u) => {
const badge = getActivityStatusBadge(u.status);
return (
<tr key={u.id} className="hover:bg-slate-800/40 transition-colors">
@@ -853,7 +869,7 @@ export const SettingsPage: React.FC = () => {
{u.id}
</td>
<td className="py-3.5 px-4 font-mono text-slate-300 text-[11px]">
{u.idNumber || <span className="text-slate-600">—</span>}
<ObfuscatedIdNumber idNumber={u.idNumber} />
</td>
<td className="py-3.5 px-4">
<UserRoleBadge role={u.role} />
@@ -915,6 +931,64 @@ export const SettingsPage: React.FC = () => {
</tbody>
</table>
</div>
{/* Pagination Controls */}
{totalUsers > 0 && (
<div className="flex flex-col sm:flex-row items-center justify-between gap-3 px-5 py-3 border-t border-slate-800/80 bg-slate-900/40 text-xs text-slate-400">
<div className="flex items-center gap-2">
<span>
Showing <strong className="text-white font-mono">{Math.min((userPage - 1) * userPageSize + 1, totalUsers)}</strong> to{' '}
<strong className="text-white font-mono">{Math.min(userPage * userPageSize, totalUsers)}</strong> of{' '}
<strong className="text-white font-mono">{totalUsers}</strong> users
</span>
</div>
<div className="flex items-center gap-3">
<div className="flex items-center gap-1.5">
<span className="text-slate-400">Per page:</span>
<select
value={userPageSize}
onChange={(e) => {
setUserPageSize(Number(e.target.value));
setUserPage(1);
}}
className="bg-slate-900 border border-slate-700/80 rounded-lg px-2 py-1 text-xs text-white focus:outline-none focus:ring-1 focus:ring-blue-500"
>
<option value={10}>10</option>
<option value={25}>25</option>
<option value={50}>50</option>
<option value={100}>100</option>
</select>
</div>
<div className="flex items-center gap-1">
<button
type="button"
onClick={() => setUserPage((p) => Math.max(1, p - 1))}
disabled={userPage <= 1}
className="p-1 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 hover:bg-slate-800 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
title="Previous page"
>
<ChevronLeft className="w-4 h-4" />
</button>
<span className="px-2 font-mono text-slate-300">
{userPage} / {totalPages}
</span>
<button
type="button"
onClick={() => setUserPage((p) => Math.min(totalPages, p + 1))}
disabled={userPage >= totalPages}
className="p-1 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 hover:bg-slate-800 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
title="Next page"
>
<ChevronRight className="w-4 h-4" />
</button>
</div>
</div>
</div>
)}
</div>
</div>
)}