Internal Operations · React 18.3 · CRA + CRACO

Admin Dashboard
Internal Control Panel

Internal operating platform for KioskGaming team — Manage users, approve withdrawals, handle support tickets and monitor all platform transactions in real time.

30+
Functional routes
5
Admin roles
3
Cash withdrawal approval step
:3000
Dev port (CRA)
TS 4.9
TypeScript
🎯
Section 01
Professional purpose
ℹ️
Admin Dashboardis the internal operations center — where the finance, operations and administration teams monitor and control all operations of the KioskGaming platform. Not a product aimed at players, this is a professional tool for businesses to operate daily gaming kiosks.
πŸ’ΌProblem solved
  • Browse manual withdrawals:Finance team reviews, approves and confirms completion of bank/crypto transfer
  • User Control:Ban violating accounts, change status, view entire wallet history
  • Handling support requests:Respond to tickets, update status, close resolved tickets
  • Transaction monitoring:Track all deposit/withdrawal transactions across all payment providers
  • Executive overview:Dashboard stats — The leadership grasped the situation immediately
⚑Technical stack
React 18.3 CRA CRACO 7 TypeScript 4.9 React Router v6 React Query v3 Zustand 5 Radix UI + shadcn @kioskgaming/ui Axios Tailwind CSS 3 Playwright E2E Turnstile CAPTCHA
🏒Who operates this system?
  • Finance Team:Handle withdrawal requests daily, verify transfers
  • Operations Team:Manage user accounts, handle support tickets
  • Super Admin:Full visibility, management of admin accounts
πŸ—ΊοΈNavigation flow — React Router v6
Route Component Permission Guard Describe
/login LoginPage.tsx Public Login admin (email + password + OTP)
/dashboard Dashboard.tsx Authenticated Overview of stats, quick actions
/users UsersManagement userManagement List + search + filter users
/users/:id UserDetailPage userManagement User details, wallet, transaction history, modal ban
/transactions TransactionsManagement transactionManagement All payment transactions platform
/withdrawal-requests WithdrawalManagement withdrawalManagement Approve / Complete / Reject withdrawals (3-step)
/tickets TicketManagement ticketManagement Support ticket list + reply thread + status update
/flagged-withdrawals FlaggedWithdrawalsManagement withdrawalManagement Withdrawals flagged as fraud β€” separate review
/manual-game-deposits ManualGameDepositsManagement manualGameDepositManagement Browse manual game deposit (manual deposit)
/usd-wallets UsdWalletsManagement transactionManagement USD wallet ledger & activity
/credit-wallets CreditWalletsManagement transactionManagement Credit wallet management
/cash-transactions CashTransactionsManagement transactionManagement Cash transactions at shop/cashier
/agents Β· /shops Β· /cashiers Agent/Shop/Cashier Mgmt agentManagement Manage agent hierarchy + shops
/broadcasts Β· /in-app-popups Broadcast / Popup Mgmt super_admin only Platform-wide notifications + in-app popups
/integration-logs IntegrationLogsManagement super_admin only API integration logs
/vfx-config ScheduleManagement vfxConfigManagement VFX/background kiosk configuration
/transaction-limits TransactionLimitsManagement transactionLimitsManagement Trading Limits & fraud flags
/domains DomainsManagement domainManagement Manage kiosk domains
/wallets GameWalletsManagement walletManagement Game wallets (implemented)
/admins AdminManagement adminManagement CRUD admin accounts (implemented)
πŸ”
Section 02
Subject & Decentralization
πŸ”‘
RBAC decentralized system viaconfig/permissions.ts: roles system_admin, super_admin, platform_admin, finance_admin, support_admin. AuthProvider(React Context) wrap app;ProtectedRoutecheck permissions; permissions resolve from APIpermissionObjectsor role map.
πŸ‘‘
Super Admin
role: admin
βœ“ userManagement
βœ“ walletManagement
βœ“ transactionManagement
βœ“ withdrawalManagement
βœ“ ticketManagement
βœ“ adminManagement
βœ“ financeManagement
✦ Full access β€” unlimited
πŸ’°
Finance Admin
role: finance
βœ— userManagement
βœ“ walletManagement
βœ“ transactionManagement
βœ“ withdrawalManagement
βœ— ticketManagement
βœ— adminManagement
βœ“ financeManagement
✦ Financial centralization: wallet, transactions, withdrawals
πŸ› οΈ
Operation Admin
role: planned
βœ“ userManagement
βœ— walletManagement
βœ— transactionManagement
βœ— withdrawalManagement
βœ“ ticketManagement
⚠ Not yet implemented in useAuth.ts
πŸ”§
Platform Admin
role: planned
~Limited rights
~Depending on configuration
⚠ Not defined in the codebase
πŸ”’Authentication mechanism & Authorization
// useAuth.ts β€” hasPermission logic if (user.profile?.role === 'admin') { return true; // Full access to all routes } if (user.profile?.role === 'finance') { const financePerms = [ 'walletManagement', 'transactionManagement', 'withdrawalManagement', 'financeManagement', ]; return financePerms.includes(permission); } return false;
// ProtectedRoute.tsx β€” route guard if (!isAuthenticated) { return <Navigate to="/login" state={{ from: location }} />; } if (requiredPermission && !hasPermission(requiredPermission)) { return <Navigate to="/dashboard" />; } return <>{children}</>;
⚠️
Important note:Authorization currently only checks the client side. Every API call backend must have a JWT token and the backend performs independent authorization. Client-side guards are just for UX — not the only security layer.
πŸ’Έ
Section 03
Withdrawal Approval Module
🚨
The most important profession— The 3-step withdrawal approval process protects users and ensures the finance team confirms the actual transfer before marking it complete. Each action is performed through a separate modal to avoid mistaken operations.
πŸ”„3-step processing flow — Withdrawal Workflow
Step 1
Pending
The user submits a withdrawal request from the player app. The system creates a withdrawal request with statuspending.
pending
Step 2
Approve
Finance admin reviews information, checks balances, opensApproveWithdrawalModaland confirm with optional admin notes.
approved
Step 3A
Complete
After the actual transfer (bank / crypto), finance admin opensCompleteWithdrawalModalto mark complete.
completed
Step 3B
Reject
From any state, admin can openRejectWithdrawalModalfor obvious reasons. The amount is refunded to the user's wallet.
rejected
Withdraw Types are supported
🏦 Bank Transfer
Fields: bankCode, accountNumber, accountName, routingNumber. Finance team makes manual bank transfer.
β‚Ώ Bitcoin Transfer
Field: bitcoinAddress, bitcoinNetwork. Finance team sends crypto manually to the wallet address.
3 Modal Actions
  • ApproveWithdrawalModal:Confirm approval, have admin notes field (max 1000 chars). POST/admin/withdrawal/:id/approve
  • CompleteWithdrawalModal:Confirm the transfer has been completed, with admin notes. POST/admin/withdrawal/:id/complete
  • RejectWithdrawalModal:Enter reason for refusal (required). POST/admin/withdrawal/:id/reject
πŸ–₯️ Approve Withdrawal Modal — Preview Layout
πŸ“‹ WithdrawalList — Filters & Columns
Filters are available
  • status: pending / approved / completed / rejected
  • withdrawalType: bank_transfer / bitcoin_transfer
  • dateFrom / dateTo: Date range picker
  • sortBy: createdAt / amount / status
  • sortOrder: ASC / DESC
  • page / limit: Pagination (default 20/page)
Columns displays
  • Transaction ID β€” unique identifier
  • User β€” firstName + lastName + email
  • Type β€” Bank / Bitcoin badge
  • Amount + Currency
  • Status badge β€” color-coded
  • Created At
  • Actions β€” View / Approve / Complete / Reject
πŸ‘₯
Section 04
User Management
πŸ“‹UserList — List of users
  • Search:Search by email (debounced input)
  • Filter status: active / inactive / suspended
  • Filter banned:Show/hide banned accounts
  • Sort: created_at / email / status / banned
  • Pagination:20 users/page by default
  • Click row:Navigate to/users/:id
active inactive suspended banned
πŸ‘€UserDetailPage — User details
  • Info section: ID, email, email_verified, last_login_at, created_at
  • Stats section: totalDeposits, totalWithdrawals, walletBalance, totalTransactions
  • WalletSection:Wallet balance, locked balance, manual credit/debit
  • WalletTransactionTable:Wallet transaction history with filter & pagination
  • Action buttons: Ban User / Unban / Update Status
🚫BanUserModal — Accounts board
⚠ The action cannot be undone immediately
  • reason field:Required to enter reason for ban (record audit trail)
  • Record:banned_at, banned_by (admin ID), ban_reason
  • Unban: Separate modal to confirm account unlocking
// BanUserRequest type interface BanUserRequest { reason?: string; } // Response records the full audit data: { userId: string; banned: true; banned_at: string; // ISO timestamp ban_reason?: string; }
πŸ”„ UpdateUserStatusModal
3 updatable statuses:
active Account operating normally
inactive Account inactive / not verified
suspended Suspended (less severe than ban)
πŸ’° WalletSection Admin Actions
  • Credit Wallet:Add money manually (amount + reason + description)
  • Debit Wallet:Manual deduction (amount + reason + description)
  • Xem: balance, lockedBalance, currency
🎫
Section 05
Customer Support — Ticket Management
🎫
Operations team processes support tickets from players through the ticket system. Each ticket has a full replies thread, distinguishing between admin replies and user replies. Admins can mark internal notes that only internal teams can see.
πŸ”„ Ticket Status Flow
pending β†’ in_progress β†’ resolved β†’ closed
done β€” Special status: admin marks complete (with resolvedAt + resolvedBy)
πŸ“‹ TicketList
  • Filter status: pending / in_progress / resolved / closed / done
  • Pagination: 20 tickets/trang
  • Display: ticketNumber, email, phoneNumber, category, status badge, createdAt
  • Click:Open the TicketDetails panel
SupportTicket fields11 fields
Category typesDynamic from API
Reply typesadmin / user
πŸ’¬ TicketDetails & Reply System
  • Thread view:Displays the entire conversation history in chronological order
  • Reply distinguish:Admin replies have adminName, user replies have email
  • Internal notes: isInternal: true— Only admin can see
  • ReplyTicketModal: Text area + checkbox internal note
  • UpdateTicketStatusModal:Dropdown select new status + write notes
  • Mark as Done:Record resolvedAt + resolvedBy automatically
πŸ“Š Support Stats (Dashboard data)
total
Total tickets
open
Waiting for processing
progress
Processing
today
Resolved today
πŸ’³
Section 06
Transaction Monitoring
πŸ“‹TransactionList — Full filter
  • search:Search by transactionId / userId
  • type: deposit / withdrawal
  • status: pending / completed / failed / cancelled
  • paymentMethod: Filter by payment provider
  • dateFrom / dateTo: Date range
  • sortBy: created_at / amount / status / type
  • Pagination:20/page default
πŸ”TransactionDetails — Transaction details
  • Core fields: transactionId, userId, type, amount, currency, status
  • Payment info: paymentMethod, description, paymentResult (raw JSON)
  • Admin fields: adminNotes, approvedAt, approvedBy
  • Stats: processingTime, relatedTransactions, userTransactionCount
  • Raw data: linkMePayRequest payload (debug)
πŸ”„ UpdateTransactionStatusModal & Transaction Stats
Status transitions allow:
pending β†’ Pending
completed β†’ Completed successfully
failed β†’ Transaction failed
cancelled β†’ Cancelled
Transaction Stats API response:
  • overview: totalTransactions, totalAmount, completed/pending/failed counts
  • byType: totalDeposits vs totalWithdrawals
  • byMethod: breakdown by payment provider (deposits + withdrawals)
βš™οΈ
Section 07
Engineering — Architecture & Patterns
πŸ”„ React Query Data Fetching
// hooks/useApi.ts β€” Query patterns const { data, isLoading, error, refetch } = useWithdrawals(filters); // React Query v3 config const queryClient = new QueryClient({ defaultOptions: { queries: { retry: 1, refetchOnWindowFocus: false, }, }, });
  • useWithdrawals(filters): Pagination + filter state β†’ query key
  • useApproveWithdrawal():Mutation β†’ onSuccess calls refetch()
  • useDashboardStats():Single query for all stats
  • Cache invalidation:After each mutation callrefetch() parent query
πŸͺŸ Modal Architecture Pattern
// Withdrawal Management pattern const [showApproveModal, setShowApproveModal] = useState(false); const [selectedWithdrawal, setSelected...] = useState<WithdrawalRequest | null>(null); // Open modal: set target + show flag const handleApprove = (w) => { setSelectedWithdrawal(w); setShowApproveModal(true); };
  • Modal isolation:Each action (approve/reject/complete/ban) has its own modal
  • Confirmation pattern:Prevent accidental operations on sensitive data
  • Toast feedback:react-hot-toast after each successful/failed action
  • Error parsing:Parse word errorerror.response.data.message
πŸ›‘οΈ Protected Routes & Auth Flow
  • JWT localStorage:Token + userData stored locally, initialized fromuseEffect
  • ProtectedRoute wrapper:All private routes go through this component
  • requiredPermission prop: Route-level permission check
  • Fallback logic: Not auth β†’ /login, No perm β†’ /dashboard
  • Loading state: isLoading: truewhile restoring auth from localStorage
  • Logout: Clear localStorage + reset state
πŸ“Š Dashboard — Stats & Recharts
  • DashboardStats type: users, wallets, transactions, tickets sections
  • 6 stat cards: Total Users, Active Users, Wallet Balance, Total Transactions, Pending Withdrawals, Open Tickets
  • Quick Actions panel:Links to Managing Users, Approving Withdrawals, Processing Tickets
  • 4 summary cards:Quick Action, Users Statistics, Today's Deals, Support Tickets
  • Recharts: Charts for trends (deposit/withdrawal over time)
  • Lucide icons: Users, Wallet, CreditCard, ArrowUpRight, Activity, AlertCircle, MessageSquare
🎨 Layout & Navigation Architecture
Layout.tsx
Root layout wrapper. Compose Sidebar + Header + main content area. Applied via ProtectedRoute wrapping.
Sidebar.tsx
Left nav with active state detection via React Router useLocation. Menu items are conditional based on permissions.
Header.tsx
Top header with user info, role badge, logout button. Displays the currently logged in admin name.
πŸ—‚οΈ
Section 08
Pages & Component Map
Auth
LoginPage.tsx
Email + password + OTP flow. 2-step: send code then verify
ProtectedRoute.tsx
Route guard β€” checks auth + permission before rendering
useAuth.ts
Central hooks: login, logout, hasPermission, hasRole, updateUser
Layout
Layout.tsx
Root layout wrapper: Sidebar + Header + content
Sidebar.tsx
Left nav with active state, permission-gated menu items
Header.tsx
Top bar: user info, role badge, logout
MenuContainer.tsx
Menu container wrapper
Dashboard
Dashboard.tsx
6 stat cards, 4 summary panels, quick actions. Recharts charts
Users
UserList.tsx
Table with filter, search, sort, pagination
UserDetailPage.tsx
Full user profile + stats + action buttons
WalletSection.tsx
Wallet balance, credit/debit manual actions
WalletTransactionTable.tsx
Wallet transaction history with filter & pagination
BanUserModal.tsx
Ban/unban with reason field. Record audit trails
UpdateUserStatusModal.tsx
Switch active / inactive / suspended
Withdrawal Requests
WithdrawalList.tsx
Table with status/type/date filters. Action buttons per row
WithdrawalDetails.tsx
Full withdrawal info: bankInfo / bitcoinInfo
ApproveWithdrawalModal.tsx
Step 2 — Approve with optional admin notes
CompleteWithdrawalModal.tsx
Step 3A — Confirm the money transfer has been completed
RejectWithdrawalModal.tsx
Step 3B — Refuse for mandatory reasons
Support Tickets
TicketList.tsx
Ticket table with status filter + pagination
TicketDetails.tsx
Full conversation thread (admin + user replies)
ReplyTicketModal.tsx
Textarea + internal note checkbox to reply
UpdateTicketStatusModal.tsx
Dropdown status + notes + mark as done
Transactions
TransactionList.tsx
Full filter: type, status, method, date, sort
TransactionDetails.tsx
Details + raw payload + stats + admin notes
UpdateTransactionStatusModal.tsx
Update status + adminNotes for transaction
Shared UI Components
Card.tsx
Card, CardHeader, CardTitle, CardContent
Badge.tsx
Color-coded status badges
Table.tsx
Table wrapper with consistent styling
Button.tsx
Button variants: default, outline, ghost, sizes: sm/md/lg
Input.tsx
Styled input with consistent form appearance
Loading.tsx
LoadingSpinner + LoadingPage components
Menu.tsx
Dropdown menu component
Services & Types
services/api.ts
Axios instance + interceptors + base URL config
hooks/useApi.ts
React Query hooks for every API endpoint
types/index.ts
700+ lines TypeScript types for every entity
utils/index.ts
formatCurrency, date helpers, misc utils
constants/index.ts
STORAGE_KEYS and app-level constants
βœ…
Clear architecture:Every entity (Withdrawal, User, Transaction, Ticket) has a full TypeScript interface for request, response, filters and pagination. Good separation of concerns between UI components, hooks/queries and types.