diff --git a/src/pages/AdminPage.tsx b/src/pages/AdminPage.tsx index 4107f86..c5700bb 100644 --- a/src/pages/AdminPage.tsx +++ b/src/pages/AdminPage.tsx @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react'; -import { Users, Mail, Plus, Trash2, Copy, Check, KeyRound } from 'lucide-react'; +import { Users, Mail, Plus, Trash2, Copy, Check, X, KeyRound, ChevronRight, Shield, ShieldAlert } from 'lucide-react'; import { api } from '@/lib/api'; import { useAuthStore } from '@/stores/auth'; import type { User, Invite } from '@/types'; @@ -12,6 +12,9 @@ export default function AdminPage() { const [isLoading, setIsLoading] = useState(true); const [activeTab, setActiveTab] = useState<'users' | 'invites'>('users'); + // User detail panel + const [selectedUser, setSelectedUser] = useState(null); + // Invite form const [showInviteForm, setShowInviteForm] = useState(false); const [inviteEmail, setInviteEmail] = useState(''); @@ -21,8 +24,7 @@ export default function AdminPage() { const [inviteUrl, setInviteUrl] = useState(''); const [copied, setCopied] = useState(false); - // Password reset - const [resetUserId, setResetUserId] = useState(null); + // Password reset (in detail panel) const [resetUrl, setResetUrl] = useState(''); const [resetCopied, setResetCopied] = useState(false); const [resetLoading, setResetLoading] = useState(false); @@ -69,7 +71,11 @@ export default function AdminPage() { const handleChangeRole = async (userId: string, role: 'admin' | 'user') => { try { await api.updateUserRole(userId, role); - setUsers(users.map(u => u.id === userId ? { ...u, role } : u)); + const updated = users.map(u => u.id === userId ? { ...u, role } : u); + setUsers(updated); + if (selectedUser?.id === userId) { + setSelectedUser({ ...selectedUser, role }); + } } catch (error) { console.error('Failed to update role:', error); } @@ -79,7 +85,6 @@ export default function AdminPage() { setResetLoading(true); try { const result = await api.createPasswordReset(userId); - setResetUserId(userId); setResetUrl(result.resetUrl); } catch (error) { console.error('Failed to generate reset link:', error); @@ -94,8 +99,8 @@ export default function AdminPage() { setTimeout(() => setResetCopied(false), 2000); }; - const dismissReset = () => { - setResetUserId(null); + const closeUserPanel = () => { + setSelectedUser(null); setResetUrl(''); setResetCopied(false); }; @@ -105,6 +110,7 @@ export default function AdminPage() { try { await api.deleteUser(userId); setUsers(users.filter(u => u.id !== userId)); + if (selectedUser?.id === userId) closeUserPanel(); } catch (error) { console.error('Failed to delete user:', error); } @@ -179,77 +185,31 @@ export default function AdminPage() { Email Role Joined - + {users.map((user) => ( - + setSelectedUser(user)} + className="border-b border-slate-100 last:border-0 cursor-pointer hover:bg-slate-50 transition-colors" + > {user.name} {user.email} - {user.id === currentUser?.id ? ( - - {user.role} - - ) : ( - - )} + + {user.role} + {user.createdAt ? new Date(user.createdAt).toLocaleDateString() : '—'} - {user.id !== currentUser?.id && ( -
- {resetUserId === user.id ? ( -
- ✓ Link ready - - -
- ) : ( - <> - - - - )} -
- )} + ))} @@ -419,6 +379,152 @@ export default function AdminPage() { )} + + {/* User Detail Slide-Over Panel */} + {selectedUser && ( + <> + {/* Backdrop */} +
+ {/* Panel */} +
+ {/* Header */} +
+

User Settings

+ +
+ + {/* Content */} +
+ {/* User info */} +
+
+ {selectedUser.name?.charAt(0).toUpperCase() || '?'} +
+
+

{selectedUser.name}

+

{selectedUser.email}

+
+
+ + {/* Details */} +
+
+ +

+ {selectedUser.createdAt ? new Date(selectedUser.createdAt).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }) : '—'} +

+
+ + {/* Role */} +
+ + {selectedUser.id === currentUser?.id ? ( +
+ + {selectedUser.role} + + (your account) +
+ ) : ( +
+ + +
+ )} +
+
+ + {/* Actions — only for non-self users */} + {selectedUser.id !== currentUser?.id && ( +
+

Actions

+ + {/* Password Reset */} +
+
+ + Password Reset +
+ {resetUrl ? ( +
+

✓ Reset link generated

+
+ + +
+
+ ) : ( + + )} +
+ + {/* Delete User */} +
+
+ + Danger Zone +
+

Permanently delete this user and all their data.

+ +
+
+ )} +
+
+ + )}
); }