website refactor

This commit is contained in:
2026-01-16 01:00:03 +01:00
parent ce7be39155
commit a98e3e3166
286 changed files with 5522 additions and 5261 deletions

View File

@@ -5,7 +5,7 @@ import { ActivityFeedItem } from '@/components/feed/ActivityFeedItem';
import { Icon } from '@/ui/Icon';
import { Text } from '@/ui/Text';
import { Stack } from '@/ui/Stack';
import { processLeagueActivities } from '@/lib/services/league/LeagueActivityService';
import { LeagueActivityService } from '@/lib/services/league/LeagueActivityService';
export type LeagueActivity =
| { type: 'race_completed'; raceId: string; raceName: string; timestamp: Date }
@@ -37,8 +37,10 @@ export function LeagueActivityFeed({ leagueId, limit = 10 }: LeagueActivityFeedP
const { data: raceList = [], isLoading } = useLeagueRaces(leagueId);
const activities = useMemo(() => {
if (isLoading || raceList.length === 0) return [];
return processLeagueActivities(raceList, limit);
if (isLoading || !Array.isArray(raceList) || raceList.length === 0) return [];
const service = new LeagueActivityService();
const result = service.processLeagueActivities(raceList, limit);
return result.isOk() ? result.unwrap() : [];
}, [raceList, isLoading, limit]);
if (isLoading) {

View File

@@ -24,7 +24,6 @@ interface LeagueMemberRowProps {
export function LeagueMemberRow({
driver,
driverId,
isCurrentUser,
isTopPerformer,
role,

View File

@@ -44,16 +44,17 @@ export function LeagueMembers({
const membershipData = leagueMembershipService.getLeagueMembers(leagueId);
setMembers(membershipData);
const uniqueDriverIds = Array.from(new Set(membershipData.map((m) => m.driverId)));
const uniqueDriverIds = Array.from(new Set(membershipData.map((m: LeagueMembership) => m.driverId)));
if (uniqueDriverIds.length > 0) {
const driverDtos = await driverService.findByIds(uniqueDriverIds);
const byId: Record<string, DriverViewModel> = {};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
for (const dto of driverDtos as any[]) {
byId[dto.id] = new DriverViewModel({ ...dto, avatarUrl: dto.avatarUrl ?? null });
const result = await driverService.findByIds(uniqueDriverIds);
if (result.isOk()) {
const driverDtos = result.unwrap();
const byId: Record<string, DriverViewModel> = {};
for (const dto of driverDtos) {
byId[dto.id] = new DriverViewModel({ ...dto, avatarUrl: dto.avatarUrl ?? null });
}
setDriversById(byId);
}
setDriversById(byId);
} else {
setDriversById({});
}

View File

@@ -50,8 +50,9 @@ export function LeagueSponsorshipsSection({
const [tempPrice, setTempPrice] = useState<string>('');
// Load season ID if not provided
const { data: seasons = [] } = useLeagueSeasons(leagueId);
const activeSeason = seasons.find((s) => s.status === 'active') ?? seasons[0];
const { data: seasonsResult } = useLeagueSeasons(leagueId);
const seasons = seasonsResult?.isOk() ? seasonsResult.unwrap() : [];
const activeSeason = seasons.find((s: any) => s.status === 'active') ?? seasons[0];
const seasonId = propSeasonId || activeSeason?.seasonId;
// Load pending sponsorship requests

View File

@@ -2,7 +2,6 @@
import { DriverViewModel } from "@/lib/view-models/DriverViewModel";
import { ProtestViewModel } from "@/lib/view-models/ProtestViewModel";
import { RaceViewModel } from "@/lib/view-models/RaceViewModel";
import { Box } from "@/ui/Box";
import { Card } from "@/ui/Card";
import { ProtestListItem } from "./ProtestListItem";
@@ -12,17 +11,13 @@ import { Flag } from "lucide-react";
interface PendingProtestsListProps {
protests: ProtestViewModel[];
races: Record<string, RaceViewModel>;
drivers: Record<string, DriverViewModel>;
leagueId: string;
onReviewProtest: (protest: ProtestViewModel) => void;
onProtestReviewed: () => void;
}
export function PendingProtestsList({
protests,
drivers,
leagueId,
onReviewProtest,
}: PendingProtestsListProps) {

View File

@@ -57,10 +57,10 @@ export function ReviewProtestModal({
const [submitting, setSubmitting] = useState(false);
const [showConfirmation, setShowConfirmation] = useState(false);
const { data: penaltyTypesReference, isLoading: penaltyTypesLoading } = usePenaltyTypesReference();
const { data: penaltyTypesReferenceResult, isLoading: penaltyTypesLoading } = usePenaltyTypesReference();
const penaltyOptions = useMemo(() => {
const refs = penaltyTypesReference?.penaltyTypes ?? [];
const refs = penaltyTypesReferenceResult?.isOk() ? penaltyTypesReferenceResult.unwrap().penaltyTypes : [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return refs.map((ref: any) => ({
type: ref.type as PenaltyType,
@@ -71,7 +71,7 @@ export function ReviewProtestModal({
Icon: getPenaltyIcon(ref.type),
colorClass: getPenaltyColor(ref.type),
}));
}, [penaltyTypesReference]);
}, [penaltyTypesReferenceResult]);
const selectedPenalty = useMemo(() => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -99,7 +99,7 @@ export function ReviewProtestModal({
}
};
const getPenaltyIcon = (type: PenaltyType) => {
function getPenaltyIcon(type: PenaltyType) {
switch (type) {
case "time_penalty":
return Clock;
@@ -122,9 +122,9 @@ export function ReviewProtestModal({
default:
return AlertCircle;
}
};
}
const getPenaltyName = (type: PenaltyType) => {
function getPenaltyName(type: PenaltyType) {
switch (type) {
case "time_penalty":
return "Time Penalty";
@@ -147,9 +147,9 @@ export function ReviewProtestModal({
default:
return type.replaceAll("_", " ");
}
};
}
const getPenaltyValueLabel = (valueKind: PenaltyValueKindDTO): string => {
function getPenaltyValueLabel(valueKind: PenaltyValueKindDTO): string {
switch (valueKind) {
case "seconds":
return "seconds";
@@ -162,9 +162,9 @@ export function ReviewProtestModal({
case "none":
return "";
}
};
}
const getPenaltyDefaultValue = (type: PenaltyType, valueKind: PenaltyValueKindDTO): number => {
function getPenaltyDefaultValue(type: PenaltyType, valueKind: PenaltyValueKindDTO): number {
if (type === "license_points") return 2;
if (type === "race_ban") return 1;
switch (valueKind) {
@@ -179,9 +179,9 @@ export function ReviewProtestModal({
case "none":
return 0;
}
};
}
const getPenaltyColor = (type: PenaltyType) => {
function getPenaltyColor(type: PenaltyType) {
switch (type) {
case "time_penalty":
return "text-blue-400 bg-blue-500/10 border-blue-500/30";
@@ -204,7 +204,7 @@ export function ReviewProtestModal({
default:
return "text-warning-amber bg-warning-amber/10 border-warning-amber/30";
}
};
}
if (showConfirmation) {
return (
@@ -351,7 +351,6 @@ export function ReviewProtestModal({
</Box>
)}
</Stack>
<Box borderTop borderColor="border-gray-800" pt={6}>
<Stack gap={4}>
<Heading level={3} fontSize="lg" weight="semibold" color="text-white">Stewarding Decision</Heading>
@@ -471,4 +470,4 @@ export function ReviewProtestModal({
</Stack>
</Modal>
);
}
}