import React, { useEffect, useMemo, useState } from "react"; import { Box, Button, Checkbox, FormControlLabel, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, } from "@mui/material"; import { api } from "../api"; import { useToast } from "../toast"; type UserDto = { id: string; email?: string | null; userName?: string | null; emailConfirmed: boolean; roles: string[]; }; export default function AdminUsersPage() { const { toast } = useToast(); const [users, setUsers] = useState([]); const [loading, setLoading] = useState(false); const [newEmail, setNewEmail] = useState(""); const [newPassword, setNewPassword] = useState(""); const [newIsAdmin, setNewIsAdmin] = useState(false); const [testEmailTo, setTestEmailTo] = useState(""); const [testEmailSubject, setTestEmailSubject] = useState("Job Tracker SMTP test"); const [testEmailMessage, setTestEmailMessage] = useState("This is a test email from the Job Tracker admin panel."); const [sendingTestEmail, setSendingTestEmail] = useState(false); async function load() { setLoading(true); try { const res = await api.get("/users"); setUsers(res.data ?? []); } catch { setUsers([]); } finally { setLoading(false); } } useEffect(() => { void load(); }, []); const canCreate = useMemo(() => newEmail.trim().length > 3 && newPassword.length >= 6, [newEmail, newPassword]); const setAdminRole = async (u: UserDto, isAdmin: boolean) => { try { await api.put(`/users/${u.id}/roles`, { roles: isAdmin ? ["Admin"] : [] }); toast("Roles updated.", "success"); await load(); } catch (e: any) { const msg = e?.response?.data || e?.message || "Failed to update roles."; toast(String(msg), "error"); } }; const sendReset = async (u: UserDto) => { try { await api.post(`/users/${u.id}/send-password-reset`); toast("Password reset email sent.", "success"); } catch (e: any) { const msg = e?.response?.data || e?.message || "Failed to send reset."; toast(String(msg), "error"); } }; const sendTestEmail = async () => { setSendingTestEmail(true); try { await api.post("/users/send-test-email", { toEmail: testEmailTo.trim() || null, subject: testEmailSubject.trim() || null, message: testEmailMessage.trim() || null, }); toast("Test email sent.", "success"); } catch (e: any) { const msg = e?.response?.data || e?.message || "Failed to send test email."; toast(String(msg), "error"); } finally { setSendingTestEmail(false); } }; const remove = async (u: UserDto) => { if (!confirmAction(`Delete user ${u.email || u.userName || u.id}?`)) return; try { await api.delete(`/users/${u.id}`); toast("User deleted.", "info"); await load(); } catch { toast("Failed to delete user.", "error"); } }; return ( Users Admin-only user management. SMTP test email Send a quick delivery check using the configured SMTP settings. Leave the recipient blank to use your admin email. setTestEmailTo(e.target.value)} placeholder="Uses your admin email if left blank" /> setTestEmailSubject(e.target.value)} /> setTestEmailMessage(e.target.value)} sx={{ gridColumn: { xs: "1 / -1", md: "1 / -1" } }} /> Create user setNewEmail(e.target.value)} /> setNewPassword(e.target.value)} /> setNewIsAdmin(e.target.checked)} />} label="Admin" /> Email Username Roles Confirmed Actions {users.map((u) => { const isAdmin = (u.roles || []).includes("Admin"); return ( {u.email || ""} {u.userName || ""} {u.roles?.length ? u.roles.join(", ") : "-"} {u.emailConfirmed ? "Yes" : "No"} ); })} {!loading && users.length === 0 ? ( No users. ) : null}
); }