This commit is contained in:
2025-12-06 00:17:24 +01:00
parent 78c85a429c
commit 70d5f5689e
54 changed files with 826 additions and 210 deletions

View File

@@ -4,7 +4,7 @@ import { useState, FormEvent } from 'react';
import { useRouter } from 'next/navigation';
import Input from '../ui/Input';
import Button from '../ui/Button';
import { Driver } from '@gridpilot/racing/domain/entities/Driver';
import { Driver } from '@gridpilot/racing';
import { getDriverRepository } from '../../lib/di-container';
interface FormErrors {

View File

@@ -1,8 +1,12 @@
'use client';
import Image from 'next/image';
import { useRef } from 'react';
import { useScrollProgress } from '@/hooks/useScrollProgress';
const discordUrl = process.env.NEXT_PUBLIC_DISCORD_URL || 'https://discord.gg/gridpilot';
const xUrl = process.env.NEXT_PUBLIC_X_URL || '#';
export default function Footer() {
return (
<footer className="relative bg-deep-graphite">
@@ -30,6 +34,15 @@ export default function Footer() {
transform: 'translateY(0)'
}}
>
<div className="mb-2 flex justify-center">
<Image
src="/images/logos/icon-square-dark.svg"
alt="GridPilot"
width={40}
height={40}
className="h-8 w-auto md:h-10"
/>
</div>
<p className="text-[9px] md:text-xs lg:text-sm text-gray-300 mb-1 md:mb-2">
🏁 Built by a sim racer, for sim racers
</p>
@@ -47,11 +60,17 @@ export default function Footer() {
}}
>
<a
href="https://discord.gg/gridpilot"
href={discordUrl}
className="text-[9px] md:text-xs text-primary-blue hover:text-neon-aqua transition-colors font-medium inline-flex items-center justify-center min-h-[44px] min-w-[44px] px-3 py-2 active:scale-95 transition-transform"
>
💬 Join Discord
</a>
<a
href={xUrl}
className="text-[9px] md:text-xs text-gray-300 hover:text-neon-aqua transition-colors font-medium inline-flex items-center justify-center min-h-[44px] min-w-[44px] px-3 py-2 active:scale-95 transition-transform"
>
𝕏 Follow on X
</a>
</div>
{/* Development status */}

View File

@@ -226,7 +226,7 @@ export default function LeagueAdmin({ league, onLeagueUpdate }: LeagueAdminProps
if (!activeRejectRequest) {
setRejectReason('');
}
}, [activeRejectRequest?.id]);
}, [activeRejectRequest, setRejectReason]);
const isRejectModalOpen = modal === 'reject-request' && !!activeRejectRequest;

View File

@@ -104,7 +104,7 @@ function InfoFlyout({ isOpen, onClose, title, children, anchorRef }: InfoFlyoutP
);
}
function InfoButton({ onClick, buttonRef }: { onClick: () => void; buttonRef: React.RefObject<HTMLButtonElement | null> }) {
function InfoButton({ onClick, buttonRef }: { onClick: () => void; buttonRef: React.RefObject<HTMLButtonElement> }) {
return (
<button
ref={buttonRef}

View File

@@ -1,6 +1,6 @@
'use client';
import { useState, useEffect } from 'react';
import { useState, useEffect, useCallback } from 'react';
import { useRouter } from 'next/navigation';
import { Race } from '@gridpilot/racing/domain/entities/Race';
import {
@@ -25,11 +25,7 @@ export default function LeagueSchedule({ leagueId }: LeagueScheduleProps) {
const currentDriverId = useEffectiveDriverId();
useEffect(() => {
loadRaces();
}, [leagueId]);
const loadRaces = async () => {
const loadRaces = useCallback(async () => {
setLoading(true);
try {
const raceRepo = getRaceRepository();
@@ -59,7 +55,12 @@ export default function LeagueSchedule({ leagueId }: LeagueScheduleProps) {
} finally {
setLoading(false);
}
};
}, [leagueId, currentDriverId]);
useEffect(() => {
loadRaces();
}, [loadRaces]);
const handleRegister = async (race: Race, e: React.MouseEvent) => {
e.stopPropagation();

View File

@@ -117,7 +117,7 @@ function InfoFlyout({ isOpen, onClose, title, children, anchorRef }: InfoFlyoutP
);
}
function InfoButton({ onClick, buttonRef }: { onClick: () => void; buttonRef: React.RefObject<HTMLButtonElement | null> }) {
function InfoButton({ onClick, buttonRef }: { onClick: () => void; buttonRef: React.RefObject<HTMLButtonElement> }) {
return (
<button
ref={buttonRef}

View File

@@ -433,7 +433,7 @@ function YearCalendarPreview({
}
return view;
}, [raceDates, seasonStart, seasonEnd]);
}, [raceDates, seasonStart, seasonEnd, months, isSeasonStartDate, isSeasonEndDate]);
// Calculate season stats
const firstRace = raceDates[0];