Page body
What this page shows
Players / Leads is the lead-management variant of the shared PlayersTable surface. It uses userType="lead", so the page loads only rows where the backend treats the user as a lead record.
The page combines:
- the shared player-style list and filter surface
- lead-only permission gating
- CSV export of the filtered lead result set
- a permission-gated
Import leads CSVdialog with preview, mapping, validation, import, and progress polling
When to use it
Use this page when you need to:
- review imported lead contacts in the same grid or card layout used for players
- search or segment lead rows before downstream conversion work
- import a CSV file of leads
- decide whether duplicate lead emails should be skipped or updated
- apply bulk tags, including the optional
Trustedtag, during import
How it differs from the player list
- The page runs
PlayersTablewithuserType="lead". - Backend reads still come through
GET /api/admin/get-users, but the service forcesisLead = truefor this surface. - The lead list keeps the player-table filters, table view, grid view, sorting, pagination, and CSV export behavior.
- The primary row action does not open a lead-edit page. Both the table row action and the grid-card footer deliberately show that lead edit is unavailable.
- Quick KYC tabs (
All Players,Pending KYC,Verified,Rejected) are not rendered in lead mode.
CSV import flow
The Import leads CSV action is shown only when the operator is:
- original super-admin, or
- allowed to
CreateorUpdateLeads
The dialog flow is:
Select CSVCheck CSV- optional field mapping review and correction
- optional
Validate Mapping - optional global tags and
Trustedtag toggle - choose how existing lead emails should be handled
- run
Import Leads - monitor in-memory progress until completion
The import dialog requires:
Emailmapping
Optional mapping fields are:
CountryFirst NameLast NameNameTagsPIDLocale
Existing lead strategy
The import flow supports two duplicate-email strategies for existing lead rows:
Skip existing leadUpdate existing lead from CSV
Important behavior:
updateis allowed only when the operator has lead update permission- if the existing email belongs to a non-lead player, the row is skipped as
duplicatePlayer - imported rows are always tagged with
Lead - optional global tags are appended to every imported row
- enabling
Trustedadds the literalTrustedtag to every imported row
Progress and completion
During import, the dialog polls /api/admin/lead-csv-import-progress every 2 seconds using a generated progressSessionId.
The visible progress state includes:
- status (
initializing,processing,completed,failed) - total rows
- processed rows
- created count
- updated count
- skipped count
- failed count
- percentage
- ETA when available
- status message
Completed or failed sessions are retained in the in-memory progress store for a short time, then expire.
Known caveats
- This surface intentionally has no dedicated lead detail or edit page.
- Lead reads, filters, sorting, and CSV export all reuse the shared
get-usersbackend path. - When a normal text search is used, the FE hook forces
startDateto2022-01-01before requesting the dataset. - Import progress is held in memory, not in a persistent table. Old or stale sessions expire from the store.
- The import flow can create or update CRM lead rows, add tags, write user activity, and trigger downstream newsletter / marketing sync side effects.
Verification status
- status:
verified_backend - last verified:
2026-04-18 - note: FE permission gates, shared player-table lead mode, preview/import/progress controllers, and lead import services are traced through
UserControllerand the lead CSV service set.