diff --git a/frontend/src/hooks/useUsers.ts b/frontend/src/hooks/useUsers.ts new file mode 100644 index 0000000..a5e75b5 --- /dev/null +++ b/frontend/src/hooks/useUsers.ts @@ -0,0 +1,33 @@ +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' +import api from '@/services/api' +import type { UserResponse, CreateUserPayload, UpdateUserPayload } from '@/types' + +export function useUsers() { + return useQuery({ + queryKey: ['users'], + queryFn: () => + api.get('/admin/users', { params: { skip: 0, limit: 200 } }).then(r => r.data), + }) +} + +export function useCreateUser() { + const queryClient = useQueryClient() + return useMutation({ + mutationFn: (payload: CreateUserPayload) => + api.post('/admin/users', payload).then(r => r.data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['users'] }) + }, + }) +} + +export function useUpdateUser() { + const queryClient = useQueryClient() + return useMutation({ + mutationFn: ({ id, payload }: { id: number; payload: UpdateUserPayload }) => + api.put(`/admin/users/${id}`, payload).then(r => r.data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['users'] }) + }, + }) +} diff --git a/frontend/src/pages/AdminUsersPage.tsx b/frontend/src/pages/AdminUsersPage.tsx index 89cf99f..809ec2b 100644 --- a/frontend/src/pages/AdminUsersPage.tsx +++ b/frontend/src/pages/AdminUsersPage.tsx @@ -1,6 +1,6 @@ -import { useState, useEffect } from 'react' +import { useState } from 'react' import { Plus, Pencil, Loader2 } from 'lucide-react' -import api from '@/services/api' +import { useUsers, useCreateUser, useUpdateUser } from '@/hooks/useUsers' import type { UserResponse, CreateUserPayload, UpdateUserPayload } from '@/types' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' @@ -20,51 +20,36 @@ import { Skeleton } from '@/components/ui/skeleton' import { Alert, AlertDescription } from '@/components/ui/alert' export function AdminUsersPage() { - const [users, setUsers] = useState([]) - const [loading, setLoading] = useState(true) + const { data: users = [], isLoading: loading } = useUsers() + const createMutation = useCreateUser() + const updateMutation = useUpdateUser() // Create dialog const [createOpen, setCreateOpen] = useState(false) const [createForm, setCreateForm] = useState({ username: '', email: '', password: '', role: 'dak_mitarbeiter', }) - const [creating, setCreating] = useState(false) const [createError, setCreateError] = useState('') // Edit dialog const [editOpen, setEditOpen] = useState(false) const [editUser, setEditUser] = useState(null) const [editForm, setEditForm] = useState({}) - const [editing, setEditing] = useState(false) const [editError, setEditError] = useState('') - // Fetch users - useEffect(() => { - fetchUsers() - }, []) - - const fetchUsers = () => { - setLoading(true) - api.get('/admin/users', { params: { skip: 0, limit: 200 } }) - .then((res) => setUsers(res.data)) - .catch(() => setUsers([])) - .finally(() => setLoading(false)) - } + const creating = createMutation.isPending + const editing = updateMutation.isPending // Create user const handleCreate = async () => { - setCreating(true) setCreateError('') try { - await api.post('/admin/users', createForm) + await createMutation.mutateAsync(createForm) setCreateOpen(false) setCreateForm({ username: '', email: '', password: '', role: 'dak_mitarbeiter' }) - fetchUsers() } catch (err: unknown) { const msg = (err as { response?: { data?: { detail?: string } } })?.response?.data?.detail setCreateError(msg || 'Fehler beim Erstellen des Benutzers.') - } finally { - setCreating(false) } } @@ -78,18 +63,14 @@ export function AdminUsersPage() { const handleEdit = async () => { if (!editUser) return - setEditing(true) setEditError('') try { - await api.put(`/admin/users/${editUser.id}`, editForm) + await updateMutation.mutateAsync({ id: editUser.id, payload: editForm }) setEditOpen(false) setEditUser(null) - fetchUsers() } catch (err: unknown) { const msg = (err as { response?: { data?: { detail?: string } } })?.response?.data?.detail setEditError(msg || 'Fehler beim Aktualisieren des Benutzers.') - } finally { - setEditing(false) } }