Add modal for user creation in Admin Panel

A modal was implemented to simplify user creation in the Admin Panel. It features a cleaner UI with input fields for email, password, and roles, along with reset and close functionalities. Existing form reset logic was refactored for reuse, and styles were added for the modal.
This commit is contained in:
2026-02-03 08:52:17 +01:00
parent 8838ca1755
commit 87057e6e1c

View File

@@ -21,6 +21,8 @@ function cycleTag(tag) {
function AdminPanel() {
const [users, setUsers] = useState([]);
const [open, setOpen] = useState(false);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [role, setRole] = useState("user");
@@ -35,6 +37,12 @@ function AdminPanel() {
loadUsers().catch(() => {});
}, []);
const resetForm = () => {
setEmail("");
setPassword("");
setRole("user");
};
const createUser = async () => {
setMsg("");
try {
@@ -42,26 +50,59 @@ function AdminPanel() {
method: "POST",
body: JSON.stringify({ email, password, role }),
});
setEmail("");
setPassword("");
setRole("user");
setMsg("✅ User erstellt.");
await loadUsers();
resetForm();
setOpen(false);
} catch (e) {
setMsg("❌ Fehler: " + (e?.message || "unknown"));
}
};
const closeModal = () => {
setOpen(false);
setMsg("");
// optional: resetForm(); // wenn du beim Schließen leeren willst
};
return (
<div style={styles.adminWrap}>
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10 }}>
<div style={styles.adminTitle}>Admin Dashboard</div>
<button onClick={() => setOpen(true)} style={styles.primaryBtn}>
+ User anlegen
</button>
</div>
<div style={styles.adminGrid}>
<div style={{ marginTop: 12, fontWeight: 900, color: "#20140c" }}>Vorhandene User</div>
<div style={{ marginTop: 8, display: "grid", gap: 8 }}>
{users.map((u) => (
<div key={u.id} style={styles.userRow}>
<div>{u.email}</div>
<div style={{ textAlign: "center", fontWeight: 900 }}>{u.role}</div>
<div style={{ textAlign: "center", opacity: 0.85 }}>
{u.disabled ? "disabled" : "active"}
</div>
</div>
))}
</div>
{/* Modal */}
{open && (
<div style={styles.modalOverlay} onMouseDown={closeModal}>
<div style={styles.modalCard} onMouseDown={(e) => e.stopPropagation()}>
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10 }}>
<div style={{ fontWeight: 1000, color: "#20140c" }}>Neuen User anlegen</div>
<button onClick={closeModal} style={styles.secondaryBtn}>Schließen</button>
</div>
<div style={{ marginTop: 12, display: "grid", gap: 10 }}>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
style={styles.input}
autoFocus
/>
<input
value={password}
@@ -74,27 +115,30 @@ function AdminPanel() {
<option value="user">user</option>
<option value="admin">admin</option>
</select>
<button onClick={createUser} style={styles.primaryBtn}>User anlegen</button>
{msg && <div style={{ opacity: 0.9 }}>{msg}</div>}
<div style={{ display: "flex", gap: 8, justifyContent: "flex-end", marginTop: 4 }}>
<button onClick={() => { resetForm(); setMsg(""); }} style={styles.secondaryBtn}>
Leeren
</button>
<button onClick={createUser} style={styles.primaryBtn}>
User erstellen
</button>
</div>
{msg && <div style={{ marginTop: 10, opacity: 0.9 }}>{msg}</div>}
<div style={{ marginTop: 14, fontWeight: 900, color: "#20140c" }}>Vorhandene User</div>
<div style={{ marginTop: 8, display: "grid", gap: 8 }}>
{users.map((u) => (
<div key={u.id} style={styles.userRow}>
<div>{u.email}</div>
<div style={{ textAlign: "center", fontWeight: 900 }}>{u.role}</div>
<div style={{ textAlign: "center", opacity: 0.85 }}>
{u.disabled ? "disabled" : "active"}
<div style={{ fontSize: 12, opacity: 0.75 }}>
Tipp: Am Handy ist das Modal leichter zu bedienen als die Grid-Zeile.
</div>
</div>
))}
</div>
</div>
)}
</div>
);
}
export default function App() {
const [me, setMe] = useState(null);
const [loginEmail, setLoginEmail] = useState("admin@local");
@@ -445,4 +489,24 @@ const styles = {
background: "rgba(255,255,255,0.55)",
border: "1px solid rgba(0,0,0,0.10)",
},
modalOverlay: {
position: "fixed",
inset: 0,
background: "rgba(0,0,0,0.45)",
display: "flex",
alignItems: "center",
justifyContent: "center",
padding: 16,
zIndex: 9999,
},
modalCard: {
width: "100%",
maxWidth: 520,
borderRadius: 18,
border: "1px solid rgba(0,0,0,0.25)",
background: "linear-gradient(180deg, rgba(255,255,255,0.72), rgba(255,255,255,0.42))",
boxShadow: "0 18px 50px rgba(0,0,0,0.35)",
padding: 14,
backdropFilter: "blur(6px)",
},
};