Location in the system
Super Agent is the highest level in the distribution chain. Every agent is created and managed by a super agent.
- Create / Suspend / Terminate agent
- Move shop between agents
- Move player between shops
- Allocate credits to agent
- Configure game provider per-agent
- View entire sub-hierarchy
- Own shops only
- Players in own shops
- Cannot create another agent
- Cannot move shop to another SA
- Cannot see SA credit balance
Login via
Private Endpoint — separate from/agent-auth
Compare with Agent Portal
Superagent Portal inherits all the features of Agent Portal and adds multi-level management capabilities.
| Feature | Agent Portal | Superagent Portal | Notes |
|---|---|---|---|
| Dashboard & Analytics | ✔ | ✔ | Same DashboardPage, but SA sees full-hierarchy summary |
| Manage Shops | ✔ (own shops) | ✔ (all shops) | SA sees shops of EVERY sub-agent |
| Manage Players | ✔ (own players) | ✔ (all players) | SA sees players in every shop |
| Create new Agent | ✗ | ✔ +SA | createManagedAgent() |
| Suspend / Terminate Agent | ✗ | ✔ +SA | 3 states: active → suspended → terminated |
| Move Shop to another Agent | ✗ | ✔ +SA | moveManagedShop(shopId, targetAgentId) |
| Move Player to another Shop | ✗ | ✔ +SA | moveManagedPlayer(playerId, targetShopId) |
| Allocate Credits to Agent | ✗ | ✔ +SA | SuperAgentAgentCreditTrigger |
| Allocate Credits to Shop | ✔ | ✔ | SellCreditsCashToAgentTrigger (shared) |
| Configure Game Provider per-Agent | ✗ | ✔ +SA | putManagedAgentGameMappings() |
| Edit Agent Cost Rate | ✗ | ✔ +SA | updateManagedAgentRate() |
| Xem Hierarchy Tree | ~ (1 tier: shops) | ✔ (2 tiers: agents+shops) | SA: HierarchyMiniTree · Agent: AgentHierarchyMiniTree |
| Transactions History | ✔ | ✔ | AgentTransactionsPage shared |
| Credit Purchase | ✔ | ✔ | PurchaseCheckoutPage removed — purchase via shared CreditPurchaseModal |
| Broadcast / Popup | ✔ | ✔ | SendBroadcastPage, SendShopPopupPage shared |
| PWA Service Worker | ✗ | ✔ +SA | Workbox, StaleWhileRevalidate, precache |
Dealer Management
SuperAgentManagementPage.tsx— central page with 3 tabs:agents | shops | players. Route /agents, /shops, /playersUse the same component as propsection.
Form modal collects complete information and submitsPOST /super-agent/agents.
- Minimum 8 characters (PASSWORD_MIN = 8)
- Must contain at least 1 uppercase letter
- Must contain at least 1 lowercase letter
- Must contain at least 1 digit
- Input value: 0 – 100 (percent)
- Convert: toRate(percent) → 0–1
- When editing: must be greater than SA's own cost rate
- can_create_shop_popup — Agent can send popup/broadcast to shops/players
- can_manage_shop_popup_permission — Agent can toggle popup permission per shop
- default_shop_can_create_player_popup — Default: new shops created by this agent can send popups to players
Trong tab shops, each row has a "Move" button. SA selects target agent (target agent ≠ current agent), confirm →moveManagedShop(shopId, targetAgentId).
Trong tab players, each row has a "Move" button. SA selects the target shop (target shop ≠ current shop), confirm →moveManagedPlayer(playerId, targetShopId).
- Search by name / email / phone
- useMemo: filteredAgents
- Search by name / email / phone
- Filter by agent (dropdown)
- useMemo: filteredShops
- Search by username / email / phone
- Filter by shop (dropdown)
- useMemo: filteredPlayers
Agent Details — ManagedAgentDetailPage
Route /agents/:agentId. The page has 4 tabs:Info · Games · Shops · Players. Tabs are managed via URL search param?tab=....
- Name, email, status badge (active/suspended/terminated)
- Credit balance of agent (agent.credit_balance)
- Button Suspend / Unsuspend / Terminate
- SuperAgentAgentCreditTrigger — distribute credits
- Edit Cost Rate inline (edit → enter → save)
- Guard: new cost rate must exceed SA's own rate
- Fetch fetchManagedAgentGameMappings(agentId)
- Fetch fetchPublicGameProviders()
- parentGamePool: SA's current game set (filter)
- 2 modes: All (inherit SA pool) or Selected
- Checkbox list — select specific game providers
- Save → putManagedAgentGameMappings(agentId, ids[])
- Empty array = "all" (inherit SA pool)
- Stat: Total shops / Active shops
- Table: shop name, email, status
- Filter: show only this agent's shops (s.agent?.id === agentId)
- Stat: Total players / Active players
- Table: username/email/phone, shop, status
- Filter: p.agent_id === agentId
Configure Game Provider per-Agent
The SA can limit or expand the game providers that each agent has access to. Inherited and overridden logic from SA pool to agent pool.
parentGamePool[]
for each Agent
inherit entire SA pool
in agent pool
Credits Distribution
SA distributes credits to agents — a completely new mechanism compared to Agent Portal (which only distributes credits to shops).
Component SuperAgentAgentCreditTrigger.tsx in components/credits/. Appears inManagedAgentDetailPageInfo tab, next to the govern agent buttons.
- Click "Credit" button → open modal
- Load SA's own balance (fetchDashboard())
- Show agent name + current cost rate
- Enter amount (credits)
- Preview: credits → cash equivalent
- Submit → distributeCreditsToManagedAgent()
- Close → callback onSuccess()
Multilevel Visibility — HierarchyMiniTree
Component HierarchyMiniTree.tsx in components/dashboard/. Display 2 levels: SA → Agents → Shops. Unlike Agent Portal, there is only 1 level (Agent → Shops).
- Expandable tree — root SA node expand/collapse
- Each Agent can expand/collapse independently to view shops
- StatusDot per-node (green=active, amber=suspended, gray=terminated)
- Shops displayed as card grid (1-3 cols by viewport)
- Each shop card links to /agents/{id}
- Date range filter (from/to) — period statistics
- Summary row: total deposits, withdrawals, new users, total users
- Stats per-shop: deposits, withdrawals, new users, total users
- API: fetchSuperAgentShopHierarchyStats({from, to})
- Default range: last 30 days
PWA Capability — Service Worker
Superagent Portal is the only repo in the ecosystem that has a Service Worker — geared towards mobile usability and working when the network is unstable.
precacheAndRoute(self.__WB_MANIFEST)— cache all static assets (JS, CSS, fonts) at install time. Automatically updated when new builds.
createHandlerBoundToURL('/index.html')— intercept navigate requests, returnedindex.html for React Router handle client-side.
StaleWhileRevalidate strategy for .pngfiles. Cache name "images", max 100 entries. Display cached images immediately, revalidate implicitly.
clientsClaim()— The new SA is activated immediately after installation, no need to wait for the tab to close/open. Guaranteed quick updates.
SA portal has a Service Worker suggested for use on mobile (tablet/phone) — suitable for the role of mobile "regional manager", needing access anytime, anywhere.
Useworkbox-core, workbox-routing, workbox-strategies, workbox-expiration, workbox-precaching.
Superagent Portal Routes
React Router v6 structure — all routes are wrappedProtectedRoute(apart from/login).
| Path | Component | SA exclusive? | Description |
|---|---|---|---|
| /dashboard | DashboardPage | Dashboard with HierarchyMiniTree (2 tiers) | |
| /agents | SuperAgentManagementPage (section="agents") | SA Only | Agent list + create new + govern |
| /agents/:agentId | ManagedAgentDetailPage | SA Only | Agent detail: Info/Games/Shops/Players |
| /shops | SuperAgentManagementPage (section="shops") | All shops + filter by agent + move | |
| /players | SuperAgentManagementPage (section="players") | All players + filter by shop + move | |
| /transactions | AgentTransactionsPage | Transaction history (shared) | |
| /purchase/checkout | PurchaseCheckoutPage removed — purchase via CreditPurchaseModal | Purchase credits (shared) | |
| /payment/return | AgentPaymentReturnPage | Payment result (shared) | |
| /login | LoginPage | Call POST /super-agent-auth/login |
Technical Stack & Architecture
- @kioskgaming/page-loading — PageLoadingIndicator variant="page" and variant="inline"
- @kioskgaming/ui — shared UI components
Aggregated Endpoints API
All endpoints under prefix/super-agent/and/super-agent-auth/.
| Method | Endpoint | Function | Purpose |
|---|---|---|---|
| POST | /super-agent-auth/login | loginWithEmailPassword() | SA login |
| GET | /super-agent/agents | fetchManagedAgents() | Sub-agent list |
| POST | /super-agent/agents | createManagedAgent() | Create new agent |
| PUT | /super-agent/agents/{id}/suspend | suspendManagedAgent() | Suspend agent |
| PUT | /super-agent/agents/{id}/unsuspend | unsuspendManagedAgent() | Unsuspend agent |
| POST | /super-agent/agents/{id}/terminate | terminateManagedAgent() | Terminate agent (irreversible) |
| PUT | /super-agent/agents/{id}/rate | updateManagedAgentRate() | Edit agent cost rate |
| POST | /super-agent/agents/{id}/credits | distributeCreditsToManagedAgent() | Allocate credits to agent |
| GET | /super-agent/agents/{id}/game-mappings | fetchManagedAgentGameMappings() | Agent game mappings |
| PUT | /super-agent/agents/{id}/game-mappings | putManagedAgentGameMappings() | Update game access |
| GET | /super-agent/shops | fetchManagedShops() | All shops |
| PUT | /super-agent/shops/{id}/move | moveManagedShop() | Move shop to another agent |
| GET | /super-agent/players | fetchManagedPlayers() | All players |
| PUT | /super-agent/players/{id}/move | moveManagedPlayer() | Move player to another shop |
| GET | /super-agent/shop-hierarchy-stats | fetchSuperAgentShopHierarchyStats() | Stats hierarchy (deposits, withdrawals, users) |