/** * Admin Page * * User management + app settings page. * - useUsers for listing all users * - setRole for changing user roles * - Admin-only settings collection * - useQuery with admin permissions */ import { useState, useMemo } from 'react' import { useUser } from 'deepspace' import { useUsers } from 'deepspace' import { useQuery } from 'deepspace' import { useMutations } from 'deepspace' import { Button, Badge, Avatar, AvatarFallback, useToast, type BadgeProps } from '@/components/ui' import { ROLES, ROLE_CONFIG, type Role } from 'deepspace' // ============================================================================ // Types // ============================================================================ interface Setting { key: string value: string } // ============================================================================ // Main Page // ============================================================================ export default function AdminPage() { const { user } = useUser() const isAdmin = user?.role === 'admin' const { users, setRole } = useUsers() const [activeTab, setActiveTab] = useState<'users' | 'settings'>('users') const toast = useToast() // Security: Don't render admin content if not an admin if (!isAdmin) { return (

Access Denied

You don't have permission to view this page.

) } return (
{/* Header */}

Admin Panel

Manage users and settings

{/* Tabs */}
{/* Content */}
{activeTab === 'users' ? ( { setRole(userId, role) toast.success('Role updated successfully') }} /> ) : ( )}
) } // ============================================================================ // Users Panel // ============================================================================ interface UsersPanelProps { users: Array<{ id: string email?: string name: string imageUrl?: string role: string lastSeenAt?: string }> currentUserId?: string onSetRole: (userId: string, role: string) => void } function UsersPanel({ users, currentUserId, onSetRole }: UsersPanelProps) { // Sort users by last seen const sortedUsers = useMemo(() => { return [...users].sort((a, b) => new Date(b.lastSeenAt ?? '').getTime() - new Date(a.lastSeenAt ?? '').getTime() ) }, [users]) return (
{sortedUsers.map(user => { const roleConfig = ROLE_CONFIG[user.role as Role] ?? ROLE_CONFIG[ROLES.VIEWER] const isCurrentUser = user.id === currentUserId return (
{user.name?.[0]?.toUpperCase() ?? '?'}
{user.name} {isCurrentUser && ( (you) )}

{user.email}

Last seen: {user.lastSeenAt ? new Date(user.lastSeenAt).toLocaleDateString() : '—'}

{roleConfig.title}
) })}
{users.length === 0 && (

No users found

)}
) } // ============================================================================ // Settings Panel // ============================================================================ interface SettingsPanelProps { toast: ReturnType } function SettingsPanel({ toast }: SettingsPanelProps) { const [newKey, setNewKey] = useState('') const [newValue, setNewValue] = useState('') // Query settings (admin-only collection) const { records: settings, status } = useQuery('settings') const { create, remove } = useMutations('settings') const handleCreate = async () => { if (!newKey.trim() || !newValue.trim()) return await create({ key: newKey.trim(), value: newValue.trim() }) setNewKey('') setNewValue('') toast.success('Setting created') } const handleDelete = async (id: string) => { if (confirm('Are you sure you want to delete this setting?')) { await remove(id) toast.success('Setting deleted') } } return (
{/* Add new setting */}

Add New Setting

setNewKey(e.target.value)} placeholder="Key" className="flex-1 px-3 py-2 bg-transparent border border-border rounded-lg text-sm text-foreground placeholder-muted-foreground focus:outline-none focus:ring-ring" /> setNewValue(e.target.value)} placeholder="Value" className="flex-1 px-3 py-2 bg-transparent border border-border rounded-lg text-sm text-foreground placeholder-muted-foreground focus:outline-none focus:ring-ring" />
{/* Settings list */}
{status === 'loading' ? (
) : settings.length === 0 ? (

No settings configured

) : (
{settings.map(setting => (
{setting.data.key} = {setting.data.value}
))}
)}
) }