Implement comprehensive topup billing system with user history viewing and admin management capabilities.
## Features Added
### Frontend
- Add topup history modal with paginated billing records
- Display order details: trade number, payment method, amount, money, status, create time
- Implement empty state with proper illustrations
- Add payment method column with localized display (Stripe, Alipay, WeChat)
- Add admin manual completion feature for pending orders
- Add Coins icon for recharge amount display
- Integrate "Bills" button in RechargeCard header
- Optimize code quality by using shared utility functions (isAdmin)
- Extract constants for status and payment method mappings
- Use React.useMemo for performance optimization
### Backend
- Create GET `/api/user/topup/self` endpoint for user topup history with pagination
- Create POST `/api/user/topup/complete` endpoint for admin manual order completion
- Add `payment_method` field to TopUp model for tracking payment types
- Implement `GetUserTopUps` method with proper pagination and ordering
- Implement `ManualCompleteTopUp` with transaction safety and row-level locking
- Add application-level mutex locks to prevent concurrent order processing
- Record payment method in Epay and Stripe payment flows
- Ensure idempotency and data consistency with proper error handling
### Internationalization
- Add i18n keys for Chinese (zh), English (en), and French (fr)
- Support for billing-related UI text and status messages
## Technical Improvements
- Use database transactions with FOR UPDATE row-level locking
- Implement sync.Map-based mutex for order-level concurrency control
- Proper error handling and user-friendly toast notifications
- Follow existing codebase patterns for empty states and modals
- Maintain code quality with extracted render functions and constants
## Files Changed
- Backend: controller/topup.go, controller/topup_stripe.go, model/topup.go, router/api-router.go
- Frontend: web/src/components/topup/modals/TopupHistoryModal.jsx (new), web/src/components/topup/RechargeCard.jsx, web/src/components/topup/index.jsx
- i18n: web/src/i18n/locales/{zh,en,fr}.json
- Ran: bun run eslint:fix && bun run lint:fix
- Inserted AGPL license header via eslint-plugin-header
- Enforced no-multiple-empty-lines and other lint rules
- Formatted code using Prettier v3 (@so1ve/prettier-config)
- No functional changes; formatting-only baseline across JS/JSX files
- Rename React components/pages/utilities that contain JSX to `.jsx` across `web/src`
- Update import paths and re-exports to match new `.jsx` extensions
- Fix Vite entry by switching `web/index.html` from `/src/index.js` to `/src/index.jsx`
- Verified remaining `.js` files are plain JS (hooks/helpers/constants) and do not require JSX
- No runtime behavior changes; extension and reference alignment only
Context: Resolves the Vite pre-transform error caused by the stale `/src/index.js` entry after migrating to `.jsx`.
Fix pagination component flickering issue across multiple table views
by initializing count states to 0 instead of ITEMS_PER_PAGE. This
prevents the pagination component from briefly appearing and then
disappearing when tables are empty.
Changes:
- usage-logs: logCount initial value 0 (was ITEMS_PER_PAGE)
- users: userCount initial value 0 (was ITEMS_PER_PAGE)
- tokens: tokenCount initial value 0 (was ITEMS_PER_PAGE)
- channels: channelCount initial value 0 (was ITEMS_PER_PAGE)
- redemptions: tokenCount initial value 0 (was ITEMS_PER_PAGE)
The createCardProPagination function already handles total <= 0 by
returning null, so this ensures consistent behavior across all table
components and improves user experience by eliminating visual flicker.
Affected files:
- web/src/hooks/usage-logs/useUsageLogsData.js
- web/src/hooks/users/useUsersData.js
- web/src/hooks/tokens/useTokensData.js
- web/src/hooks/channels/useChannelsData.js
- web/src/hooks/redemptions/useRedemptionsData.js
Users table (UsersColumnDefs.js)
• Merged “Status” into the “Statistics” tag: unified text-color logic, removed duplicate renderStatus / renderOverallStatus helpers.
• Switch now disabled for deleted users.
• Replaced dropdown “More” menu with explicit action buttons (Edit / Promote / Demote / Delete) and set column width to 200 px.
• Deleted unused Dropdown & IconMore imports and tidied redundant code.
Users filters & hooks
• UsersFilters.jsx – store formApi in a ref; reset button clears form then reloads data after 100 ms.
• useUsersData.js – call setLoading(true) at the start of loadUsers so the Query button shows loading on reset / reload.
TokensFilters.jsx & RedemptionsFilters.jsx
• Same ref-based reset pattern with 100 ms debounce to restore working “Reset” buttons.
Other clean-ups
• Removed repeated status strings and unused helper functions.
• Updated import lists to reflect component changes.
Result
– Reset buttons now reliably clear filters and reload data with proper loading feedback.
– Users table shows concise status information and all operation buttons without extra clicks.
Summary of changes
1. UI clean-up
• Removed all `prefixIcon` props from `Tag` components in `UsersColumnDefs.js`.
• Corrected i18n string in invite info (`${t('邀请人')}: …`).
2. “Statistics” column overhaul
• Added a Switch (enable / disable) and quota Progress bar, mirroring the Tokens table design.
• Moved enable / disable action out of the “More” dropdown; user status is now toggled directly via the Switch.
• Disabled the Switch for deleted (注销) users.
• Restored column title to “Statistics” to avoid duplication.
3. State consistency / refresh
• Updated `manageUser` in `useUsersData.js` to:
– set `loading` while processing actions;
– update users list immutably (new objects & array) to trigger React re-render.
4. Imports / plumbing
• Added `Progress` and `Switch` to UI imports in `UsersColumnDefs.js`.
These changes streamline the user table’s appearance, align interaction patterns with the token table, and ensure immediate visual feedback after user status changes.
BREAKING CHANGE: Removed standalone user edit routes (/console/user/edit, /console/user/edit/:id)
- Decompose 673-line monolithic UsersTable.js into 8 specialized components
- Extract column definitions to UsersColumnDefs.js with render functions
- Create dedicated UsersActions.jsx for action buttons
- Create UsersFilters.jsx for search and filtering logic
- Create UsersDescription.jsx for description area
- Extract all data management logic to useUsersData.js hook
- Move AddUser.js and EditUser.js to users/modals/ folder as modal components
- Create 4 new confirmation modal components (Promote, Demote, EnableDisable, Delete)
- Implement pure UsersTable.jsx component for table rendering only
- Create main container component users/index.jsx to compose all subcomponents
- Update import paths in pages/User/index.js to use new modular structure
- Remove obsolete EditUser imports and routes from App.js
- Delete original monolithic files: UsersTable.js, AddUser.js, EditUser.js
The new architecture follows the same modular pattern as tokens and redemptions modules:
- Consistent file organization across all table modules
- Better separation of concerns and maintainability
- Enhanced reusability and testability
- Unified modal management approach
All existing functionality preserved with improved code organization.