feat: refactor agent manager, media library, and player UX

- Split admin users page into player/tier-1/tier-2 tabs with affiliation labels and context-specific create dialogs

- Add media library with uploaded_files migration, list/delete unused files API, and admin nav route

- Enforce player username format (alphanumeric 3-32) on frontend and backend via shared package

- Improve admin dialog/panel styling; refine player parlay and match bet card kickoff display

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-09 17:56:28 +08:00
parent d5e7c8edb3
commit df20444be9
27 changed files with 2136 additions and 563 deletions

View File

@@ -1,4 +1,5 @@
import { FormValidationError } from '../../i18n/form-validation';
import { assertPlayerUsername } from '../user-form';
export interface AgentPlayerCreateForm {
username: string;
@@ -65,7 +66,7 @@ export function emptyAgentPlayerCreateForm(): AgentPlayerCreateForm {
}
export function buildAgentCreatePlayerPayload(form: AgentPlayerCreateForm) {
if (!form.username.trim()) throw new FormValidationError('err.username_required');
assertPlayerUsername(form.username);
if (form.password.length < 8) throw new FormValidationError('err.password_min');
if (form.password !== form.confirmPassword) throw new FormValidationError('err.password_mismatch');
if (form.initialDeposit < 0) throw new FormValidationError('err.amount_negative');
@@ -119,7 +120,7 @@ export function editFormFromAgentDetail(d: AgentPlayerDetail): AgentPlayerEditFo
}
export function buildAgentUpdatePlayerPayload(form: AgentPlayerEditForm) {
if (!form.username.trim()) throw new FormValidationError('err.username_required');
assertPlayerUsername(form.username);
if (form.newPassword && form.newPassword.length < 8) {
throw new FormValidationError('err.password_min');
}