import { Button, Input, Loader, Select } from "@cloudflare/kumo"; import { useLingui } from "@lingui/react/macro"; import { MagnifyingGlass, UserPlus, Prohibit, CheckCircle } from "@phosphor-icons/react"; import * as React from "react"; import type { UserListItem } from "../../lib/api"; import { cn } from "../../lib/utils"; import { RoleBadge } from "./RoleBadge"; import { useRolesConfig } from "./useRolesConfig.js"; export interface UserListProps { users: UserListItem[]; isLoading?: boolean; hasMore?: boolean; searchQuery: string; roleFilter: number | undefined; onSearchChange: (query: string) => void; onRoleFilterChange: (role: number | undefined) => void; onSelectUser: (id: string) => void; onInviteUser: () => void; onLoadMore?: () => void; } /** * User list component with search, filter, and table display */ export function UserList({ users, isLoading, hasMore, searchQuery, roleFilter, onSearchChange, onRoleFilterChange, onSelectUser, onInviteUser, onLoadMore, }: UserListProps) { const { t } = useLingui(); const { roles, roleLabels } = useRolesConfig(); const roleFilterSelectItems = React.useMemo( () => ({ all: t`All roles`, ...roleLabels }), [t, roleLabels], ); const roleFilterSelectOptions = React.useMemo( () => [{ value: "all", label: t`All roles` }, ...roles], [t, roles], ); return (
{/* Header */}

{t`Users`}

{/* Filters */}
{/* Table */}
{users.length === 0 && !isLoading ? ( ) : ( users.map((user) => ( onSelectUser(user.id)} /> )) )} {isLoading && ( )}
{t`User`} {t`Role`} {t`Status`} {t`Last Login`} {t`Passkeys`}
{searchQuery || roleFilter !== undefined ? ( <> {t`No users found matching your filters.`}{" "} ) : ( <> {t`No users yet.`}{" "} )}
{t`Loading...`}
{/* Load more */} {hasMore && !isLoading && (
)}
); } interface UserListRowProps { user: UserListItem; onSelect: () => void; } function UserListRow({ user, onSelect }: UserListRowProps) { const displayName = user.name || user.email; const { t } = useLingui(); const lastLogin = user.lastLogin ? new Date(user.lastLogin).toLocaleDateString() : t`Never`; return (
{/* Avatar */} {user.avatarUrl ? ( ) : (
{(user.name || user.email)?.[0]?.toUpperCase() ?? "?"}
)}
{displayName}
{user.name &&
{user.email}
}
{user.disabled ? ( ) : ( )} {lastLogin} {user.credentialCount} ); } /** Loading skeleton for user list */ export function UserListSkeleton() { return (
{/* Header skeleton */}
{/* Filters skeleton */}
{/* Table skeleton */}
{Array.from({ length: 5 }, (_, i) => (
))}
); }