"use client"; import { useCallback, useEffect, useMemo, useState } from "react"; import { Plus } from "lucide-react"; import ConfirmDialog from "@/components/common/ConfirmDialog"; import SearchInput from "@/components/common/SearchInput"; import { Button } from "@/components/ui/button"; import UserFormDialog from "@/components/users/UserFormDialog"; import UserTable from "@/components/users/UserTable"; import { api } from "@/lib/api"; import type { User, UserPayload, UserRole } from "@/types/user"; const pageSize = 10; type StatusFilter = "all" | "active" | "inactive"; function getErrorMessage(error: unknown) { if (typeof error === "object" && error !== null && "response" in error) { const response = (error as { response?: { data?: { detail?: string } } }).response; return response?.data?.detail ?? "Aktion konnte nicht abgeschlossen werden"; } return "Aktion konnte nicht abgeschlossen werden"; } function getSortableValue(user: User, key: string) { const value = user[key as keyof User]; return typeof value === "string" ? value.toLowerCase() : value; } export default function UsersPage() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); const [formError, setFormError] = useState(""); const [deleteError, setDeleteError] = useState(""); const [pending, setPending] = useState(false); const [search, setSearch] = useState(""); const [roleFilter, setRoleFilter] = useState("all"); const [statusFilter, setStatusFilter] = useState("all"); const [sortKey, setSortKey] = useState("created_at"); const [sortDirection, setSortDirection] = useState<"asc" | "desc">("desc"); const [page, setPage] = useState(1); const [formOpen, setFormOpen] = useState(false); const [selectedUser, setSelectedUser] = useState(null); const [deleteUser, setDeleteUser] = useState(null); const loadUsers = useCallback(async () => { try { const response = await api.get("/users"); setUsers(response.data); } catch (err) { setError(getErrorMessage(err)); } finally { setLoading(false); } }, []); useEffect(() => { queueMicrotask(() => { void loadUsers(); }); }, [loadUsers]); const filteredUsers = useMemo(() => { const term = search.trim().toLowerCase(); return users .filter((user) => { if (!term) { return true; } return [ user.first_name, user.last_name, user.username, user.email, user.role, ].some((value) => value.toLowerCase().includes(term)); }) .filter((user) => roleFilter === "all" || user.role === roleFilter) .filter((user) => { if (statusFilter === "all") { return true; } return statusFilter === "active" ? user.is_active : !user.is_active; }) .sort((first, second) => { const firstValue = getSortableValue(first, sortKey); const secondValue = getSortableValue(second, sortKey); if (firstValue === secondValue) { return 0; } const result = firstValue > secondValue ? 1 : -1; return sortDirection === "asc" ? result : -result; }); }, [roleFilter, search, sortDirection, sortKey, statusFilter, users]); const pageCount = Math.max(1, Math.ceil(filteredUsers.length / pageSize)); const currentPage = Math.min(page, pageCount); const pageUsers = filteredUsers.slice( (currentPage - 1) * pageSize, currentPage * pageSize, ); function handleSort(key: string) { if (sortKey === key) { setSortDirection((current) => (current === "asc" ? "desc" : "asc")); return; } setSortKey(key); setSortDirection("asc"); } function openCreateDialog() { setSelectedUser(null); setFormError(""); setFormOpen(true); } function openEditDialog(user: User) { setSelectedUser(user); setFormError(""); setFormOpen(true); } async function saveUser(payload: UserPayload) { setPending(true); setFormError(""); try { if (selectedUser) { const response = await api.put(`/users/${selectedUser.id}`, payload); setUsers((current) => current.map((user) => ( user.id === selectedUser.id ? response.data : user ))); } else { const response = await api.post("/users", payload); setUsers((current) => [response.data, ...current]); } setFormOpen(false); } catch (err) { setFormError(getErrorMessage(err)); } finally { setPending(false); } } async function confirmDelete() { if (!deleteUser) { return; } setPending(true); setDeleteError(""); try { await api.delete(`/users/${deleteUser.id}`); setUsers((current) => current.filter((user) => user.id !== deleteUser.id)); setDeleteUser(null); } catch (err) { setDeleteError(getErrorMessage(err)); } finally { setPending(false); } } return (

Benutzer

{filteredUsers.length} von {users.length} Benutzern

{ setSearch(value); setPage(1); }} placeholder="Benutzer suchen" />
Seite {currentPage} von {pageCount}
{ if (!open) { setDeleteUser(null); setDeleteError(""); } }} onConfirm={confirmDelete} > {deleteUser && (
Benutzername
{deleteUser.username}
E-Mail
{deleteUser.email}
Rolle
{deleteUser.role}
{deleteError &&

{deleteError}

}
)}
); }