refactor
This commit is contained in:
@@ -22,21 +22,10 @@ import {
|
||||
import Card from '@/components/ui/Card';
|
||||
import Button from '@/components/ui/Button';
|
||||
import Breadcrumbs from '@/components/layout/Breadcrumbs';
|
||||
import {
|
||||
getGetRaceProtestsUseCase,
|
||||
getGetRacePenaltiesUseCase,
|
||||
getRaceRepository,
|
||||
getLeagueRepository,
|
||||
getLeagueMembershipRepository,
|
||||
} from '@/lib/di-container';
|
||||
import { apiClient } from '@/lib/apiClient';
|
||||
import { useEffectiveDriverId } from '@/lib/currentDriver';
|
||||
import { isLeagueAdminOrHigherRole } from '@/lib/leagueRoles';
|
||||
import { RaceProtestsPresenter } from '@/lib/presenters/RaceProtestsPresenter';
|
||||
import { RacePenaltiesPresenter } from '@/lib/presenters/RacePenaltiesPresenter';
|
||||
import type { RaceProtestViewModel } from '@core/racing/application/presenters/IRaceProtestsPresenter';
|
||||
import type { RacePenaltyViewModel } from '@core/racing/application/presenters/IRacePenaltiesPresenter';
|
||||
import type { League } from '@core/racing/domain/entities/League';
|
||||
import type { Race } from '@core/racing/domain/entities/Race';
|
||||
import type { RaceProtestsViewModel, RacePenaltiesViewModel } from '@/lib/apiClient';
|
||||
|
||||
export default function RaceStewardingPage() {
|
||||
const params = useParams();
|
||||
@@ -44,12 +33,10 @@ export default function RaceStewardingPage() {
|
||||
const raceId = params.id as string;
|
||||
const currentDriverId = useEffectiveDriverId();
|
||||
|
||||
const driversById: Record<string, { name?: string }> = {};
|
||||
|
||||
const [race, setRace] = useState<Race | null>(null);
|
||||
const [league, setLeague] = useState<League | null>(null);
|
||||
const [protests, setProtests] = useState<RaceProtestViewModel[]>([]);
|
||||
const [penalties, setPenalties] = useState<RacePenaltyViewModel[]>([]);
|
||||
const [race, setRace] = useState<any>(null); // TODO: Define proper race type
|
||||
const [league, setLeague] = useState<any>(null); // TODO: Define proper league type
|
||||
const [protestsData, setProtestsData] = useState<RaceProtestsViewModel | null>(null);
|
||||
const [penaltiesData, setPenaltiesData] = useState<RacePenaltiesViewModel | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [isAdmin, setIsAdmin] = useState(false);
|
||||
const [activeTab, setActiveTab] = useState<'pending' | 'resolved' | 'penalties'>('pending');
|
||||
@@ -58,39 +45,24 @@ export default function RaceStewardingPage() {
|
||||
async function loadData() {
|
||||
setLoading(true);
|
||||
try {
|
||||
const raceRepo = getRaceRepository();
|
||||
const leagueRepo = getLeagueRepository();
|
||||
const membershipRepo = getLeagueMembershipRepository();
|
||||
const protestsUseCase = getGetRaceProtestsUseCase();
|
||||
const penaltiesUseCase = getGetRacePenaltiesUseCase();
|
||||
// Get race detail for basic info
|
||||
const raceDetail = await apiClient.races.getDetail(raceId, currentDriverId);
|
||||
setRace(raceDetail.race);
|
||||
setLeague(raceDetail.league);
|
||||
|
||||
const raceData = await raceRepo.findById(raceId);
|
||||
if (!raceData) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
setRace(raceData);
|
||||
|
||||
const leagueData = await leagueRepo.findById(raceData.leagueId);
|
||||
setLeague(leagueData);
|
||||
|
||||
if (leagueData) {
|
||||
const membership = await membershipRepo.getMembership(
|
||||
leagueData.id,
|
||||
currentDriverId,
|
||||
);
|
||||
setIsAdmin(membership ? isLeagueAdminOrHigherRole(membership.role) : false);
|
||||
if (raceDetail.league) {
|
||||
// TODO: Implement admin check via API
|
||||
setIsAdmin(true);
|
||||
}
|
||||
|
||||
const protestsPresenter = new RaceProtestsPresenter();
|
||||
await protestsUseCase.execute({ raceId }, protestsPresenter);
|
||||
const protestsViewModel = protestsPresenter.getViewModel();
|
||||
setProtests(protestsViewModel?.protests ?? []);
|
||||
// Get protests and penalties
|
||||
const [protestsData, penaltiesData] = await Promise.all([
|
||||
apiClient.races.getProtests(raceId),
|
||||
apiClient.races.getPenalties(raceId),
|
||||
]);
|
||||
|
||||
const penaltiesPresenter = new RacePenaltiesPresenter();
|
||||
await penaltiesUseCase.execute({ raceId }, penaltiesPresenter);
|
||||
const penaltiesViewModel = penaltiesPresenter.getViewModel();
|
||||
setPenalties(penaltiesViewModel?.penalties ?? []);
|
||||
setProtestsData(protestsData);
|
||||
setPenaltiesData(penaltiesData);
|
||||
} catch (err) {
|
||||
console.error('Failed to load data:', err);
|
||||
} finally {
|
||||
@@ -101,15 +73,15 @@ export default function RaceStewardingPage() {
|
||||
loadData();
|
||||
}, [raceId, currentDriverId]);
|
||||
|
||||
const pendingProtests = protests.filter(
|
||||
const pendingProtests = protestsData?.protests.filter(
|
||||
(p) => p.status === 'pending' || p.status === 'under_review',
|
||||
);
|
||||
const resolvedProtests = protests.filter(
|
||||
) ?? [];
|
||||
const resolvedProtests = protestsData?.protests.filter(
|
||||
(p) =>
|
||||
p.status === 'upheld' ||
|
||||
p.status === 'dismissed' ||
|
||||
p.status === 'withdrawn',
|
||||
);
|
||||
) ?? [];
|
||||
|
||||
const getStatusBadge = (status: string) => {
|
||||
switch (status) {
|
||||
@@ -247,7 +219,7 @@ export default function RaceStewardingPage() {
|
||||
<Gavel className="w-4 h-4" />
|
||||
<span className="text-xs font-medium uppercase">Penalties</span>
|
||||
</div>
|
||||
<div className="text-2xl font-bold text-white">{penalties.length}</div>
|
||||
<div className="text-2xl font-bold text-white">{penaltiesData?.penalties.length ?? 0}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
@@ -306,8 +278,8 @@ export default function RaceStewardingPage() {
|
||||
</Card>
|
||||
) : (
|
||||
pendingProtests.map((protest) => {
|
||||
const protester = driversById[protest.protestingDriverId];
|
||||
const accused = driversById[protest.accusedDriverId];
|
||||
const protester = protestsData?.driverMap[protest.protestingDriverId];
|
||||
const accused = protestsData?.driverMap[protest.accusedDriverId];
|
||||
const daysSinceFiled = Math.floor(
|
||||
(Date.now() - new Date(protest.filedAt).getTime()) / (1000 * 60 * 60 * 24)
|
||||
);
|
||||
@@ -393,8 +365,8 @@ export default function RaceStewardingPage() {
|
||||
</Card>
|
||||
) : (
|
||||
resolvedProtests.map((protest) => {
|
||||
const protester = driversById[protest.protestingDriverId];
|
||||
const accused = driversById[protest.accusedDriverId];
|
||||
const protester = protestsData?.driverMap[protest.protestingDriverId];
|
||||
const accused = protestsData?.driverMap[protest.accusedDriverId];
|
||||
|
||||
return (
|
||||
<Card key={protest.id}>
|
||||
@@ -455,8 +427,8 @@ export default function RaceStewardingPage() {
|
||||
</p>
|
||||
</Card>
|
||||
) : (
|
||||
penalties.map((penalty) => {
|
||||
const driver = driversById[penalty.driverId];
|
||||
penaltiesData?.penalties.map((penalty) => {
|
||||
const driver = penaltiesData?.driverMap[penalty.driverId];
|
||||
return (
|
||||
<Card key={penalty.id}>
|
||||
<div className="flex items-center gap-4">
|
||||
|
||||
Reference in New Issue
Block a user