146 lines
4.3 KiB
TypeScript
146 lines
4.3 KiB
TypeScript
'use client';
|
|
|
|
import type {
|
|
LeagueMembership as DomainLeagueMembership,
|
|
MembershipRole,
|
|
MembershipStatus,
|
|
} from '@gridpilot/racing/domain/entities/LeagueMembership';
|
|
import { leagues, memberships as seedMemberships, drivers } from '@gridpilot/testing-support';
|
|
|
|
/**
|
|
* Lightweight league membership model mirroring the domain type but with
|
|
* a stringified joinedAt for easier UI formatting.
|
|
*/
|
|
export interface LeagueMembership extends Omit<DomainLeagueMembership, 'joinedAt'> {
|
|
joinedAt: string;
|
|
}
|
|
|
|
const leagueMemberships = new Map<string, LeagueMembership[]>();
|
|
|
|
/**
|
|
* Initialize league memberships once from static seed data.
|
|
*
|
|
* - All seeded memberships become active members.
|
|
* - League owners are guaranteed to have an owner membership.
|
|
*/
|
|
(function initializeLeagueMembershipsFromSeed() {
|
|
if (leagueMemberships.size > 0) {
|
|
return;
|
|
}
|
|
|
|
const byLeague = new Map<string, LeagueMembership[]>();
|
|
|
|
for (const membership of seedMemberships) {
|
|
const list = byLeague.get(membership.leagueId) ?? [];
|
|
const joinedAt = new Date().toISOString();
|
|
|
|
list.push({
|
|
leagueId: membership.leagueId,
|
|
driverId: membership.driverId,
|
|
role: 'member',
|
|
status: 'active',
|
|
joinedAt,
|
|
});
|
|
|
|
byLeague.set(membership.leagueId, list);
|
|
}
|
|
|
|
for (const league of leagues) {
|
|
const list = byLeague.get(league.id) ?? [];
|
|
const existingOwner = list.find((m) => m.driverId === league.ownerId);
|
|
|
|
if (existingOwner) {
|
|
existingOwner.role = 'owner';
|
|
} else {
|
|
const joinedAt = new Date().toISOString();
|
|
list.unshift({
|
|
leagueId: league.id,
|
|
driverId: league.ownerId,
|
|
role: 'owner',
|
|
status: 'active',
|
|
joinedAt,
|
|
});
|
|
}
|
|
|
|
byLeague.set(league.id, list);
|
|
}
|
|
|
|
// Seed sample league admins for the primary driver's league (alpha demo)
|
|
const primaryDriverId = drivers[0]?.id ?? 'driver-1';
|
|
const primaryLeagueForAdmins = leagues.find((l) => l.ownerId === primaryDriverId) ?? leagues[0];
|
|
|
|
if (primaryLeagueForAdmins) {
|
|
const adminCandidates = drivers
|
|
.filter((d) => d.id !== primaryLeagueForAdmins.ownerId)
|
|
.slice(0, 2);
|
|
|
|
adminCandidates.forEach((driver) => {
|
|
const list = byLeague.get(primaryLeagueForAdmins.id) ?? [];
|
|
const existing = list.find((m) => m.driverId === driver.id);
|
|
if (existing) {
|
|
if (existing.role !== 'owner') {
|
|
existing.role = 'admin';
|
|
}
|
|
} else {
|
|
const joinedAt = new Date().toISOString();
|
|
list.push({
|
|
leagueId: primaryLeagueForAdmins.id,
|
|
driverId: driver.id,
|
|
role: 'admin',
|
|
status: 'active',
|
|
joinedAt,
|
|
});
|
|
}
|
|
byLeague.set(primaryLeagueForAdmins.id, list);
|
|
});
|
|
}
|
|
|
|
// Seed sample league stewards for the primary driver's league (alpha demo)
|
|
if (primaryLeagueForAdmins) {
|
|
const stewardCandidates = drivers
|
|
.filter((d) => d.id !== primaryLeagueForAdmins.ownerId)
|
|
.slice(2, 5);
|
|
|
|
stewardCandidates.forEach((driver) => {
|
|
const list = byLeague.get(primaryLeagueForAdmins.id) ?? [];
|
|
const existing = list.find((m) => m.driverId === driver.id);
|
|
if (existing) {
|
|
if (existing.role !== 'owner' && existing.role !== 'admin') {
|
|
existing.role = 'steward';
|
|
}
|
|
} else {
|
|
const joinedAt = new Date().toISOString();
|
|
list.push({
|
|
leagueId: primaryLeagueForAdmins.id,
|
|
driverId: driver.id,
|
|
role: 'steward',
|
|
status: 'active',
|
|
joinedAt,
|
|
});
|
|
}
|
|
byLeague.set(primaryLeagueForAdmins.id, list);
|
|
});
|
|
}
|
|
|
|
for (const [leagueId, list] of byLeague.entries()) {
|
|
leagueMemberships.set(leagueId, list);
|
|
}
|
|
})();
|
|
|
|
export function getMembership(leagueId: string, driverId: string): LeagueMembership | null {
|
|
const list = leagueMemberships.get(leagueId);
|
|
if (!list) return null;
|
|
return list.find((m) => m.driverId === driverId) ?? null;
|
|
}
|
|
|
|
export function getLeagueMembers(leagueId: string): LeagueMembership[] {
|
|
return [...(leagueMemberships.get(leagueId) ?? [])];
|
|
}
|
|
|
|
export function isOwnerOrAdmin(leagueId: string, driverId: string): boolean {
|
|
const membership = getMembership(leagueId, driverId);
|
|
if (!membership) return false;
|
|
return membership.role === 'owner' || membership.role === 'admin';
|
|
}
|
|
|
|
export type { MembershipRole, MembershipStatus }; |