feat(admin): super-admin user detail dashboard
Add a read-only User Detail dashboard for super admins, reachable by clicking a user name in the admin users list. Backend: new `admin` module aggregating existing domain services (no new entities). ADMIN-only endpoints under /api/v1/admin: overview (profile, account status, wallet balance, revenue, summary counts), wallet transactions, applications (incl. deleted/docked with restore eligibility), build/deploy errors, tickets with conversation, and a composite activity timeline. Adds BillingService.getRevenueSummary and guards against a wallet get-or-create race in the overview reads. Frontend: tabbed detail page (overview/applications/activity/errors/ tickets) with lazy per-tab queries; user names in the admin list link to it (admin only); fa/en i18n keys and response types. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+137
-1
@@ -172,7 +172,7 @@ export type DeploymentStatus =
|
||||
| 'stopped'
|
||||
| 'deleting';
|
||||
|
||||
export type AppLifecycleStatus = 'active' | 'suspended' | 'pending_deletion' | 'deleted';
|
||||
export type AppLifecycleStatus = 'active' | 'suspended' | 'pending_deletion' | 'docked' | 'deleted';
|
||||
|
||||
export interface ResourceCredit {
|
||||
id: string;
|
||||
@@ -432,6 +432,142 @@ export interface AdminUser extends User {
|
||||
appCount?: number;
|
||||
}
|
||||
|
||||
// ─── Admin User Detail dashboard ────────────────────
|
||||
|
||||
export interface AdminUserProfile {
|
||||
id: string;
|
||||
phone?: string | null;
|
||||
email: string | null;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
role: 'user' | 'admin' | 'technical' | 'sales';
|
||||
isActive: boolean;
|
||||
phoneVerified?: boolean;
|
||||
namespace?: string;
|
||||
createdAt: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export interface AdminUserCounts {
|
||||
appsTotal: number;
|
||||
appsActive: number;
|
||||
appsDeleted: number;
|
||||
managedServices: number;
|
||||
optionalServices: number;
|
||||
deployments: number;
|
||||
ticketsTotal: number;
|
||||
ticketsOpen: number;
|
||||
}
|
||||
|
||||
export interface AdminRevenueSummary {
|
||||
/** What the user actually spent on services (platform income). */
|
||||
revenue: number;
|
||||
/** Total topped up into the wallet. */
|
||||
charged: number;
|
||||
refunded: number;
|
||||
}
|
||||
|
||||
export interface AdminUserTransaction {
|
||||
id: string;
|
||||
type: TransactionType;
|
||||
amount: number;
|
||||
balanceAfter: number;
|
||||
description?: string | null;
|
||||
applicationId?: string | null;
|
||||
invoiceId?: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface AdminUserOverview {
|
||||
profile: AdminUserProfile;
|
||||
wallet: { balance: number };
|
||||
revenue: AdminRevenueSummary;
|
||||
counts: AdminUserCounts;
|
||||
recentTransactions: AdminUserTransaction[];
|
||||
}
|
||||
|
||||
export type RestoreEligibility = 'restorable' | 'recoverable' | 'none';
|
||||
|
||||
export interface AdminUserApplication {
|
||||
id: string;
|
||||
name: string;
|
||||
productType?: ProductType;
|
||||
runtime: string;
|
||||
databaseType: string;
|
||||
lifecycleStatus?: AppLifecycleStatus;
|
||||
billingCycle?: BillingCycle | null;
|
||||
subdomain?: string | null;
|
||||
customDomain?: string | null;
|
||||
enableRedis: boolean;
|
||||
enableRabbitmq: boolean;
|
||||
enableElasticsearch: boolean;
|
||||
cpuLimit: string;
|
||||
memoryLimit: string;
|
||||
replicas: number;
|
||||
createdAt: string;
|
||||
planExpiresAt?: string | null;
|
||||
scheduledDeletionAt?: string | null;
|
||||
dockedAt?: string | null;
|
||||
restorable: RestoreEligibility;
|
||||
latestDeployment?: { id: string; status: DeploymentStatus; createdAt: string } | null;
|
||||
}
|
||||
|
||||
export interface AdminUserError {
|
||||
deploymentId: string;
|
||||
applicationId: string;
|
||||
applicationName: string;
|
||||
status: DeploymentStatus;
|
||||
errorMessage?: string | null;
|
||||
createdAt: string;
|
||||
finishedAt?: string | null;
|
||||
resolved: boolean;
|
||||
}
|
||||
|
||||
export interface AdminDeploymentLogs {
|
||||
id: string;
|
||||
status: DeploymentStatus;
|
||||
errorMessage?: string | null;
|
||||
buildLog?: string | null;
|
||||
deployLog?: string | null;
|
||||
createdAt: string;
|
||||
finishedAt?: string | null;
|
||||
}
|
||||
|
||||
export interface AdminUserTicketMessage {
|
||||
id: string;
|
||||
message: string;
|
||||
senderRole: 'user' | 'admin' | 'technical' | 'sales';
|
||||
senderName?: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface AdminUserTicket {
|
||||
id: string;
|
||||
subject: string;
|
||||
department: TicketDepartment;
|
||||
status: TicketStatus;
|
||||
priority: TicketPriority;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
closedAt?: string | null;
|
||||
messageCount: number;
|
||||
messages: AdminUserTicketMessage[];
|
||||
}
|
||||
|
||||
export interface AdminActivityEvent {
|
||||
type:
|
||||
| 'app_created'
|
||||
| 'app_docked'
|
||||
| 'app_deleted'
|
||||
| 'deployment'
|
||||
| 'transaction'
|
||||
| 'ticket'
|
||||
| string;
|
||||
title: string;
|
||||
at: string;
|
||||
meta: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface ClusterNode {
|
||||
name: string;
|
||||
status: string;
|
||||
|
||||
Reference in New Issue
Block a user