Files
gridpilot.gg/apps/website/lib/services/admin/AdminService.ts
2026-01-14 02:02:24 +01:00

108 lines
3.6 KiB
TypeScript

import { AdminApiClient } from '@/lib/api/admin/AdminApiClient';
import type { UserDto, DashboardStats, UserListResponse, ListUsersQuery } from '@/lib/api/admin/AdminApiClient';
import { Result } from '@/lib/contracts/Result';
import { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';
import { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';
import { DomainError } from '@/lib/contracts/services/Service';
/**
* Admin Service - DTO Only
*
* Returns raw API DTOs. No ViewModels or UX logic.
* All client-side presentation logic must be handled by presenters/templates.
* @server-safe
*/
export class AdminService {
private apiClient: AdminApiClient;
constructor() {
const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3001';
const logger = new ConsoleLogger();
const errorReporter = new EnhancedErrorReporter(logger, {
showUserNotifications: false,
logToConsole: true,
reportToExternal: process.env.NODE_ENV === 'production',
});
this.apiClient = new AdminApiClient(baseUrl, errorReporter, logger);
}
/**
* Get dashboard statistics
*/
async getDashboardStats(): Promise<Result<DashboardStats, DomainError>> {
try {
const result = await this.apiClient.getDashboardStats();
return Result.ok(result);
} catch (error) {
console.error('AdminService.getDashboardStats failed:', error);
if (error instanceof Error) {
if (error.message.includes('403') || error.message.includes('401')) {
return Result.err({ type: 'notFound', message: 'Access denied' });
}
}
return Result.err({ type: 'serverError', message: 'Failed to fetch dashboard stats' });
}
}
/**
* List users with filtering and pagination
*/
async listUsers(query: ListUsersQuery = {}): Promise<Result<UserListResponse, DomainError>> {
try {
const result = await this.apiClient.listUsers(query);
return Result.ok(result);
} catch (error) {
console.error('AdminService.listUsers failed:', error);
if (error instanceof Error) {
if (error.message.includes('403') || error.message.includes('401')) {
return Result.err({ type: 'notFound', message: 'Access denied' });
}
}
return Result.err({ type: 'serverError', message: 'Failed to fetch users' });
}
}
/**
* Update user status
*/
async updateUserStatus(userId: string, status: string): Promise<Result<UserDto, DomainError>> {
try {
const result = await this.apiClient.updateUserStatus(userId, status);
return Result.ok(result);
} catch (error) {
console.error('AdminService.updateUserStatus failed:', error);
if (error instanceof Error) {
if (error.message.includes('403') || error.message.includes('401')) {
return Result.err({ type: 'forbidden', message: 'Insufficient permissions' });
}
}
return Result.err({ type: 'serverError', message: 'Failed to update user status' });
}
}
/**
* Delete a user (soft delete)
*/
async deleteUser(userId: string): Promise<Result<void, DomainError>> {
try {
await this.apiClient.deleteUser(userId);
return Result.ok(undefined);
} catch (error) {
console.error('AdminService.deleteUser failed:', error);
if (error instanceof Error) {
if (error.message.includes('403') || error.message.includes('401')) {
return Result.err({ type: 'forbidden', message: 'Insufficient permissions' });
}
}
return Result.err({ type: 'serverError', message: 'Failed to delete user' });
}
}
}