import { useEffect, useState } from 'react'; import { useApp } from '../context/AppContext.js'; import PageShell from '../components/study/PageShell.jsx'; import { buildExportHtml } from '../utils/bibleUtils.jsx'; import { adminListUsers, adminListProjects, adminDeleteUser, adminDeleteProject, adminGetProject, adminResetPassword, } from '../syncService.js'; export default function AdminPage() { const { authUser, goHome } = useApp(); const [adminTab, setAdminTab] = useState('users'); // 'users' | 'projects' const [adminUsers, setAdminUsers] = useState([]); const [adminProjects, setAdminProjects] = useState([]); const [adminLoading, setAdminLoading] = useState(false); const [adminError, setAdminError] = useState(''); const [adminViewProject, setAdminViewProject] = useState(null); // full project data being previewed const [adminResetResult, setAdminResetResult] = useState(null); // { email, temporaryPassword } shown once const loadAdminData = () => { setAdminLoading(true); setAdminError(''); Promise.all([adminListUsers(), adminListProjects()]).then(([usersResult, projectsResult]) => { setAdminLoading(false); if (!usersResult.ok || !projectsResult.ok) { setAdminError(usersResult.error ?? projectsResult.error ?? 'Failed to load admin data.'); return; } setAdminUsers(usersResult.data); setAdminProjects(projectsResult.data); }); }; useEffect(() => { if (authUser?.isAdmin) loadAdminData(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [authUser?.isAdmin]); const handleDeleteUserAdmin = async (id, email) => { if (!window.confirm(`Delete account "${email}"? Their projects are kept, not deleted, but become inaccessible until reassigned.`)) return; const result = await adminDeleteUser(id); if (result.ok) loadAdminData(); else alert(result.error ?? 'Failed to delete user.'); }; const handleDeleteProjectAdmin = async (id, title) => { if (!window.confirm(`Permanently delete project "${title}"? This cannot be undone.`)) return; const result = await adminDeleteProject(id); if (result.ok) loadAdminData(); else alert(result.error ?? 'Failed to delete project.'); }; const handleViewProjectAdmin = async (id) => { const result = await adminGetProject(id); if (result.ok) setAdminViewProject(result.data); else alert(result.error ?? 'Failed to load project.'); }; const handleResetPasswordAdmin = async (id, email) => { if (!window.confirm(`Reset the password for "${email}"? They'll be signed out everywhere and need the new temporary password to log back in.`)) return; const result = await adminResetPassword(id); if (result.ok) setAdminResetResult({ email, temporaryPassword: result.data.temporaryPassword }); else alert(result.error ?? 'Failed to reset password.'); }; return (
{adminLoading &&

Loading…

} {adminError &&

{adminError}

} {!adminLoading && !adminError && adminTab === 'users' && (
{adminUsers.map((u) => ( ))}
Email Joined 2FA Projects
{u.email}{u.id === authUser.id && (you)} {new Date(u.createdAt).toLocaleDateString()} {u.totpEnabled ? '✓' : '—'} {u.projectCount} {u.id !== authUser.id && (
)}
)} {!adminLoading && !adminError && adminTab === 'projects' && (
{adminProjects.map((p) => ( ))}
Title Owner Passage Last edited Shared
{p.title} {p.ownerEmail ?? orphaned} {p.chapterSummary} {new Date(p.lastEdited).toLocaleDateString()} {p.shareToken ? '🔗' : '—'}
)}
{adminViewProject && (
setAdminViewProject(null)}>
e.stopPropagation()}>

{adminViewProject.title}