import { useState } from 'preact/hooks'; import { ChevronLeft, ChevronRight, Clipboard, Plus, RefreshCw, Trash2, UserCheck, UserX } from 'lucide-preact'; import { copyTextToClipboard } from '@/lib/clipboard'; import LoadingState from '@/components/LoadingState'; import type { AdminInvite, AdminUser } from '@/lib/types'; import { t } from '@/lib/i18n'; interface AdminPageProps { currentUserId: string; users: AdminUser[]; invites: AdminInvite[]; loading: boolean; error: string; onRefresh: () => void; onCreateInvite: (hours: number) => Promise; onDeleteAllInvites: () => Promise; onToggleUserStatus: (userId: string, currentStatus: 'active' | 'banned') => Promise; onDeleteUser: (userId: string) => Promise; onRevokeInvite: (code: string) => Promise; } export default function AdminPage(props: AdminPageProps) { const [inviteHours, setInviteHours] = useState(168); const [page, setPage] = useState(1); const pageSize = 20; const formatExpiresAt = (x?: string) => (x ? new Date(x).toLocaleString() : t('txt_dash')); const totalPages = Math.max(1, Math.ceil(props.invites.length / pageSize)); const safePage = Math.min(page, totalPages); const pagedInvites = props.invites.slice((safePage - 1) * pageSize, safePage * pageSize); const roleText = (role: string) => { const normalized = String(role || '').toLowerCase(); if (normalized === 'admin') return t('txt_role_admin'); if (normalized === 'user') return t('txt_role_user'); return role || '-'; }; const statusText = (status: string) => { const normalized = String(status || '').toLowerCase(); if (normalized === 'active') return t('txt_status_active'); if (normalized === 'banned') return t('txt_status_banned'); if (normalized === 'inactive') return t('txt_status_inactive'); return status || '-'; }; const normalizeToggleableStatus = (status: string): 'active' | 'banned' | null => { const normalized = String(status || '').toLowerCase(); if (normalized === 'active' || normalized === 'banned') return normalized; return null; }; return (
{!!props.error && (
{props.error}
)}

{t('txt_users')}

{props.users.map((user) => { const toggleableStatus = normalizeToggleableStatus(user.status); return ( ); })} {props.loading && !props.users.length && ( )} {!props.loading && !props.users.length && ( )}
{t('txt_email')} {t('txt_name')} {t('txt_role')} {t('txt_status')} {t('txt_actions')}
{user.email} {user.name || t('txt_dash')} {roleText(user.role)} {statusText(user.status)}
{user.role !== 'admin' && ( )}
{t('txt_no_users_found')}

{t('txt_invites')}

{pagedInvites.map((invite) => ( ))} {props.loading && !props.invites.length && ( )} {!props.loading && !props.invites.length && ( )}
{t('txt_code')} {t('txt_status')} {t('txt_expires_at')} {t('txt_actions')}
{invite.code} {statusText(invite.status)} {formatExpiresAt(invite.expiresAt)}
{invite.status === 'active' && ( )}
{t('txt_no_invites_found')}
{safePage} / {totalPages}
); }