import { Copy, Link2, Trash2, UserPlus, Ticket } from 'lucide-react' import type { TranslationFn } from '../../../types' import type { useAdmin } from '../../../pages/admin/useAdmin' import { inviteMeta, inviteStatus } from '../../../pages/admin/adminModel' import MAdminPermissionsPanel from './MAdminPermissionsPanel' import MSheet from '../../components/MSheet' import MChip from '../../components/MChip' import MConfirmSheet from '../settings/MConfirmSheet' import { MAdminButton, MAdminCard, MAdminField, MAdminSheetFrame } from './MAdminUi' interface MAdminUsersSectionProps { admin: ReturnType t: TranslationFn locale: string } const INVITE_USES = [1, 2, 3, 4, 5, 0] const INVITE_EXPIRY: { value: number | ''; label: string }[] = [ { value: 1, label: '1d' }, { value: 3, label: '3d' }, { value: 7, label: '7d' }, { value: 14, label: '14d' }, { value: '', label: '∞' }, ] // Users section: user list with role badges (design §6.4), invite links and the // permissions matrix. Rows open the edit sheet; Create opens the create sheet. export default function MAdminUsersSection({ admin, t, locale }: MAdminUsersSectionProps) { const { currentUser, users, isLoading, setShowCreateUser, handleEditUser, invites, inviteTrips, showCreateInvite, setShowCreateInvite, inviteForm, setInviteForm, copyInviteLink, handleCreateInvite, handleDeleteInvite, inviteToDelete, setInviteToDelete, } = admin return (
{t('admin.tabs.users')} {users.length} {t('admin.stats.users', { count: users.length })} setShowCreateUser(true)}> {t('mobileAdmin.create')}
{isLoading ? (
) : ( users.map((u) => ( )) )}
{t('admin.invite.title')}
{t('admin.invite.subtitle')}
setShowCreateInvite(true)}>{t('admin.invite.create')}
{invites.length === 0 ? (
{t('admin.invite.empty')}
) : ( invites.map((inv) => { const { isActive, labelKey } = inviteStatus(inv) return (
{inv.token.slice(0, 12)}… {t(labelKey)}
{inviteMeta(inv, t, locale)}
{isActive && ( )}
) }) )}
{/* Delete invite confirm */} setInviteToDelete(null)} title={t('admin.invite.deleteTitle')} message={t('admin.invite.deleteConfirm')} confirmLabel={t('common.delete')} cancelLabel={t('common.cancel')} danger onConfirm={() => inviteToDelete !== null && handleDeleteInvite(inviteToDelete)} /> {/* Create invite sheet */} setShowCreateInvite(false)} ariaLabel={t('admin.invite.create')}> } title={t('admin.invite.create')} onClose={() => setShowCreateInvite(false)} footer={ <> setShowCreateInvite(false)}> {t('common.cancel')} {t('admin.invite.createAndCopy')} } >
{INVITE_USES.map((n) => ( setInviteForm((f) => ({ ...f, max_uses: n }))} > {n === 0 ? '∞' : `${n}×`} ))}
{INVITE_EXPIRY.map((opt) => ( setInviteForm((f) => ({ ...f, expires_in_days: opt.value }))} > {opt.label} ))}
{inviteTrips.length > 0 && ( )}
) }