151 lines
6.2 KiB
TypeScript
151 lines
6.2 KiB
TypeScript
import { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';
|
|
import { isProductionEnvironment } from '@/lib/config/env';
|
|
import { Result } from '@/lib/contracts/Result';
|
|
import { Service, type DomainError } from '@/lib/contracts/services/Service';
|
|
import { LeaguesApiClient } from '@/lib/gateways/api/leagues/LeaguesApiClient';
|
|
import { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';
|
|
import { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';
|
|
import type { LeagueRosterJoinRequestDTO } from '@/lib/types/generated/LeagueRosterJoinRequestDTO';
|
|
import type { LeagueRosterMemberDTO } from '@/lib/types/generated/LeagueRosterMemberDTO';
|
|
import { LeagueMemberViewModel } from '@/lib/view-models/LeagueMemberViewModel';
|
|
import { injectable, unmanaged } from 'inversify';
|
|
|
|
export interface LeagueRosterAdminData {
|
|
leagueId: string;
|
|
members: LeagueRosterMemberDTO[];
|
|
joinRequests: LeagueRosterJoinRequestDTO[];
|
|
}
|
|
|
|
@injectable()
|
|
export class LeagueMembershipService implements Service {
|
|
private apiClient: LeaguesApiClient;
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
private static cachedMemberships = new Map<string, any[]>();
|
|
|
|
constructor(@unmanaged() apiClient?: LeaguesApiClient) {
|
|
if (apiClient) {
|
|
this.apiClient = apiClient;
|
|
} else {
|
|
const baseUrl = getWebsiteApiBaseUrl();
|
|
const logger = new ConsoleLogger();
|
|
const errorReporter = new EnhancedErrorReporter(logger, {
|
|
showUserNotifications: false,
|
|
logToConsole: true,
|
|
reportToExternal: isProductionEnvironment(),
|
|
});
|
|
this.apiClient = new LeaguesApiClient(baseUrl, errorReporter, logger);
|
|
}
|
|
}
|
|
|
|
async getLeagueMemberships(leagueId: string, currentUserId: string): Promise<any[]> {
|
|
const res = await this.apiClient.getMemberships(leagueId);
|
|
const members = (res as any).members || res;
|
|
return members.map((m: any) => new LeagueMemberViewModel({ ...m, currentUserId }, currentUserId as any));
|
|
}
|
|
|
|
async removeMember(leagueId: string, performerDriverId: string, targetDriverId: string): Promise<any> {
|
|
const res = await this.apiClient.removeMember(leagueId, performerDriverId, targetDriverId);
|
|
return (res as any).value || res;
|
|
}
|
|
|
|
async removeRosterMember(leagueId: string, targetDriverId: string): Promise<Result<{ success: boolean }, DomainError>> {
|
|
try {
|
|
const res = await this.apiClient.removeRosterMember(leagueId, targetDriverId);
|
|
const dto = (res as any).value || res;
|
|
return Result.ok({ success: dto.success });
|
|
} catch (error: unknown) {
|
|
return Result.err({ type: 'serverError', message: (error as Error).message || 'Failed to remove member' });
|
|
}
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
static getMembership(leagueId: string, driverId: string): any | null {
|
|
const members = this.cachedMemberships.get(leagueId);
|
|
if (!members) return null;
|
|
return members.find(m => m.driverId === driverId) || null;
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
static getLeagueMembers(leagueId: string): any[] {
|
|
return this.cachedMemberships.get(leagueId) || [];
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
static getAllMembershipsForDriver(driverId: string): any[] {
|
|
const allMemberships: any[] = [];
|
|
for (const [leagueId, members] of this.cachedMemberships.entries()) {
|
|
const membership = members.find(m => m.driverId === driverId);
|
|
if (membership) {
|
|
allMemberships.push({ ...membership, leagueId });
|
|
}
|
|
}
|
|
return allMemberships;
|
|
}
|
|
|
|
async fetchLeagueMemberships(leagueId: string): Promise<void> {
|
|
try {
|
|
const members = await this.apiClient.getMemberships(leagueId);
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
LeagueMembershipService.cachedMemberships.set(leagueId, (members as any).members || []);
|
|
} catch (error) {
|
|
console.error('Failed to fetch memberships', error);
|
|
}
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
getMembership(leagueId: string, driverId: string): any | null {
|
|
return LeagueMembershipService.getMembership(leagueId, driverId);
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
getLeagueMembers(leagueId: string): any[] {
|
|
return LeagueMembershipService.getLeagueMembers(leagueId);
|
|
}
|
|
|
|
async joinLeague(_: string, __: string): Promise<Result<void, DomainError>> {
|
|
return Result.err({ type: 'notImplemented', message: 'joinLeague' });
|
|
}
|
|
|
|
async leaveLeague(_: string, __: string): Promise<Result<void, DomainError>> {
|
|
return Result.err({ type: 'notImplemented', message: 'leaveLeague' });
|
|
}
|
|
|
|
async getRosterAdminData(leagueId: string): Promise<Result<LeagueRosterAdminData, DomainError>> {
|
|
try {
|
|
const [members, joinRequests] = await Promise.all([
|
|
this.apiClient.getAdminRosterMembers(leagueId),
|
|
this.apiClient.getAdminRosterJoinRequests(leagueId),
|
|
]);
|
|
|
|
return Result.ok({
|
|
leagueId,
|
|
members,
|
|
joinRequests,
|
|
});
|
|
} catch (error: unknown) {
|
|
console.error('LeagueMembershipService.getRosterAdminData failed:', error);
|
|
return Result.err({ type: 'serverError', message: (error as Error).message || 'Failed to fetch roster data' });
|
|
}
|
|
}
|
|
|
|
async approveJoinRequest(leagueId: string, joinRequestId: string): Promise<Result<{ success: boolean }, DomainError>> {
|
|
try {
|
|
const res = await this.apiClient.approveRosterJoinRequest(leagueId, joinRequestId);
|
|
const dto = (res as any).value || res;
|
|
return Result.ok({ success: dto.success });
|
|
} catch (error: unknown) {
|
|
return Result.err({ type: 'serverError', message: (error as Error).message || 'Failed to approve join request' });
|
|
}
|
|
}
|
|
|
|
async rejectJoinRequest(leagueId: string, joinRequestId: string): Promise<Result<{ success: boolean }, DomainError>> {
|
|
try {
|
|
const res = await this.apiClient.rejectRosterJoinRequest(leagueId, joinRequestId);
|
|
const dto = (res as any).value || res;
|
|
return Result.ok({ success: dto.success });
|
|
} catch (error: unknown) {
|
|
return Result.err({ type: 'serverError', message: (error as Error).message || 'Failed to reject join request' });
|
|
}
|
|
}
|
|
}
|