import { useEffect, useState } from 'react'; import { Box, Typography, Alert, IconButton, Tooltip, Dialog, DialogTitle, DialogContent, DialogActions, TextField, Button, CircularProgress, Stack, Snackbar, Select, MenuItem, FormControl, InputLabel, } from '@mui/material'; import { DataGrid } from '@mui/x-data-grid'; import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; import LockResetIcon from '@mui/icons-material/LockReset'; import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline'; import axiosInstance from '../api/axiosInstance'; export default function UsersPage() { const [rows, setRows] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [editUser, setEditUser] = useState(null); const [editForm, setEditForm] = useState({}); const [saving, setSaving] = useState(false); const [saveError, setSaveError] = useState(''); const [resetting, setResetting] = useState(null); const [snackbar, setSnackbar] = useState(''); const [deleteUser, setDeleteUser] = useState(null); const [deleting, setDeleting] = useState(false); useEffect(() => { axiosInstance.get('/users') .then(({ data }) => setRows(data)) .catch(() => setError('Fehler beim Laden der Nutzer')) .finally(() => setLoading(false)); }, []); const handleEditOpen = (user) => { setEditUser(user); setEditForm({ email: user.email ?? '', nickname: user.nickname ?? '', role: user.role?.replace('ROLE_', '') ?? '', }); setSaveError(''); }; const handleEditClose = () => { setEditUser(null); setEditForm({}); }; const handleFormChange = (e) => { const { name, value } = e.target; setEditForm((prev) => ({ ...prev, [name]: value })); }; const handleSave = async () => { setSaving(true); setSaveError(''); try { const { data } = await axiosInstance.put(`/users/${editUser.id}`, editForm); setRows((prev) => prev.map((r) => r.id === editUser.id ? { ...r, ...data } : r)); setSnackbar(`Änderungen an ${editUser.nickname} erfolgreich gespeichert.`); handleEditClose(); } catch (err) { setSaveError(err.response?.data?.message ?? 'Speichern fehlgeschlagen'); } finally { setSaving(false); } }; const handlePasswordReset = async (user) => { setResetting(user.id); try { await axiosInstance.post(`/users/${user.id}/reset-password`); setSnackbar(`Passwort für ${user.nickname} wurde zurückgesetzt — E-Mail wurde versendet.`); } catch (err) { setSnackbar(err.response?.data?.message ?? 'Zurücksetzen fehlgeschlagen'); } finally { setResetting(null); } }; const handleDeleteConfirm = async () => { setDeleting(true); try { await axiosInstance.delete(`/users/${deleteUser.id}`); setRows((prev) => prev.filter((r) => r.id !== deleteUser.id)); setSnackbar(`Nutzer ${deleteUser.nickname} wurde gelöscht.`); setDeleteUser(null); } catch (err) { setSnackbar(err.response?.data?.message ?? 'Löschen fehlgeschlagen'); } finally { setDeleting(false); } }; const columns = [ { field: 'id', headerName: 'ID', width: 80 }, { field: 'nickname', headerName: 'Anzeigename', flex: 1 }, { field: 'email', headerName: 'E-Mail', flex: 1.5 }, { field: 'role', headerName: 'Berechtigung', flex: 1.5 }, { field: 'accountCreated', headerName: 'Registriert', flex: 1, valueFormatter: (value) => value ? new Date(value).toLocaleDateString('de-DE') : '—', }, { field: 'actions', headerName: '', width: 130, sortable: false, renderCell: ({ row }) => ( handleEditOpen(row)}> handlePasswordReset(row)} disabled={resetting === row.id} > {resetting === row.id ? : } setDeleteUser(row)}> ), }, ]; return ( Nutzer {error && {error}} {/* Edit Dialog */} Nutzer bearbeiten {saveError && {saveError}} Berechtigung {/* Delete Bestätigungs-Dialog */} setDeleteUser(null)} maxWidth="xs" fullWidth> Nutzer löschen Soll {deleteUser?.nickname} ({deleteUser?.email}) wirklich gelöscht werden? Diese Aktion kann nicht rückgängig gemacht werden. {/* Snackbar */} setSnackbar('')} message={snackbar} anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} /> ); }