import { useState, useEffect } from 'react'; import { Users, Mail, Plus, Trash2, Copy, Check, KeyRound } from 'lucide-react'; import { api } from '@/lib/api'; import { useAuthStore } from '@/stores/auth'; import type { User, Invite } from '@/types'; import { cn } from '@/lib/utils'; export function AdminPage() { const { user: currentUser } = useAuthStore(); const [users, setUsers] = useState([]); const [invites, setInvites] = useState([]); const [isLoading, setIsLoading] = useState(true); const [activeTab, setActiveTab] = useState<'users' | 'invites'>('users'); // Invite form const [showInviteForm, setShowInviteForm] = useState(false); const [inviteEmail, setInviteEmail] = useState(''); const [inviteName, setInviteName] = useState(''); const [inviteRole, setInviteRole] = useState<'admin' | 'user'>('user'); const [inviteError, setInviteError] = useState(''); const [inviteUrl, setInviteUrl] = useState(''); const [copied, setCopied] = useState(false); useEffect(() => { loadData(); }, []); const loadData = async () => { setIsLoading(true); try { const [usersData, invitesData] = await Promise.all([ api.getUsers(), api.getInvites(), ]); setUsers(usersData); setInvites(invitesData); } catch (error) { console.error('Failed to load admin data:', error); } finally { setIsLoading(false); } }; const handleCreateInvite = async (e: React.FormEvent) => { e.preventDefault(); setInviteError(''); try { const result = await api.createInvite({ email: inviteEmail, name: inviteName, role: inviteRole }); setInviteUrl(result.setupUrl); setInvites([result, ...invites]); // Keep form open to show the URL } catch (error) { setInviteError(error instanceof Error ? error.message : 'Failed to create invite'); } }; const handleCopyUrl = () => { navigator.clipboard.writeText(inviteUrl); setCopied(true); setTimeout(() => setCopied(false), 2000); }; const handleChangeRole = async (userId: string, role: 'admin' | 'user' | 'service') => { try { await api.updateUserRole(userId, role); setUsers(users.map(u => u.id === userId ? { ...u, role } : u)); } catch (error) { console.error('Failed to update role:', error); } }; const [resetUserId, setResetUserId] = useState(null); const [resetUrl, setResetUrl] = useState(''); const [resetCopied, setResetCopied] = useState(false); const [resetLoading, setResetLoading] = useState(false); const handleGenerateResetLink = async (userId: string) => { setResetLoading(true); try { const result = await api.createPasswordReset(userId); setResetUserId(userId); setResetUrl(result.resetUrl); } catch (error) { console.error('Failed to generate reset link:', error); } finally { setResetLoading(false); } }; const handleCopyResetUrl = () => { navigator.clipboard.writeText(resetUrl); setResetCopied(true); setTimeout(() => setResetCopied(false), 2000); }; const dismissReset = () => { setResetUserId(null); setResetUrl(''); setResetCopied(false); }; const handleDeleteUser = async (userId: string) => { if (!confirm('Are you sure you want to delete this user?')) return; try { await api.deleteUser(userId); setUsers(users.filter(u => u.id !== userId)); } catch (error) { console.error('Failed to delete user:', error); } }; const handleDeleteInvite = async (inviteId: string) => { try { await api.deleteInvite(inviteId); setInvites(invites.filter(i => i.id !== inviteId)); } catch (error) { console.error('Failed to delete invite:', error); } }; const resetInviteForm = () => { setShowInviteForm(false); setInviteEmail(''); setInviteName(''); setInviteRole('user'); setInviteError(''); setInviteUrl(''); }; if (currentUser?.role !== 'admin') { return (

Access denied. Admin only.

); } return (

Admin

{/* Tabs */}
{isLoading ? (
Loading...
) : activeTab === 'users' ? ( /* Users list */
{users.map((user) => ( ))}
Name Email Role Joined
{user.name} {user.email} {user.id === currentUser?.id || user.role === 'service' ? ( {user.role} ) : ( )} {new Date(user.createdAt).toLocaleDateString()}
{user.id !== currentUser?.id && ( <> {resetUserId === user.id ? (
✓ Link generated!
) : ( )} {user.role !== 'service' && resetUserId !== user.id && ( )} )}
) : ( /* Invites */
{/* Create invite button/form */} {!showInviteForm ? ( ) : (

Invite New User

{inviteUrl ? (

✓ Invite created! Share this link:

) : (
{inviteError && (

{inviteError}

)}
setInviteName(e.target.value)} required className="input" placeholder="John Doe" />
setInviteEmail(e.target.value)} required className="input" placeholder="john@example.com" />
)}
)} {/* Invites list */}
{invites.length === 0 ? ( ) : ( invites.map((invite) => ( )) )}
Name Email Status Expires
No invites yet
{invite.name} {invite.email} {invite.status} {new Date(invite.expiresAt).toLocaleDateString()} {invite.status === 'pending' && ( )}
)}
); }