wip
This commit is contained in:
@@ -6,6 +6,7 @@ import Button from '@/components/ui/Button';
|
||||
import Card from '@/components/ui/Card';
|
||||
import JoinLeagueButton from '@/components/leagues/JoinLeagueButton';
|
||||
import LeagueActivityFeed from '@/components/leagues/LeagueActivityFeed';
|
||||
import EndRaceModal from '@/components/leagues/EndRaceModal';
|
||||
import DriverIdentity from '@/components/drivers/DriverIdentity';
|
||||
import DriverSummaryPill from '@/components/profile/DriverSummaryPill';
|
||||
import SponsorInsightsCard, {
|
||||
@@ -68,6 +69,7 @@ export default function LeagueDetailPage() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [refreshKey, setRefreshKey] = useState(0);
|
||||
const [endRaceModalRaceId, setEndRaceModalRaceId] = useState<string | null>(null);
|
||||
|
||||
const currentDriverId = useEffectiveDriverId();
|
||||
const membership = getMembership(leagueId, currentDriverId);
|
||||
@@ -347,22 +349,7 @@ export default function LeagueDetailPage() {
|
||||
{membership?.role === 'admin' && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={async () => {
|
||||
const confirmed = window.confirm(
|
||||
'Are you sure you want to end this race and process results?\n\nThis will mark the race as completed and calculate final standings.'
|
||||
);
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
try {
|
||||
const completeRace = getCompleteRaceUseCase();
|
||||
await completeRace.execute({ raceId: race.id });
|
||||
// Reload league data to reflect the completed race
|
||||
await loadLeagueData();
|
||||
} catch (err) {
|
||||
alert(err instanceof Error ? err.message : 'Failed to complete race');
|
||||
}
|
||||
}}
|
||||
onClick={() => setEndRaceModalRaceId(race.id)}
|
||||
className="border-performance-green/50 text-performance-green hover:bg-performance-green/10"
|
||||
>
|
||||
End Race & Process Results
|
||||
@@ -684,6 +671,28 @@ export default function LeagueDetailPage() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* End Race Modal */}
|
||||
{endRaceModalRaceId && (() => {
|
||||
const race = runningRaces.find(r => r.id === endRaceModalRaceId);
|
||||
return race ? (
|
||||
<EndRaceModal
|
||||
raceId={race.id}
|
||||
raceName={race.track}
|
||||
onConfirm={async () => {
|
||||
try {
|
||||
const completeRace = getCompleteRaceUseCase();
|
||||
await completeRace.execute({ raceId: race.id });
|
||||
await loadLeagueData();
|
||||
setEndRaceModalRaceId(null);
|
||||
} catch (err) {
|
||||
alert(err instanceof Error ? err.message : 'Failed to complete race');
|
||||
}
|
||||
}}
|
||||
onCancel={() => setEndRaceModalRaceId(null)}
|
||||
/>
|
||||
) : null;
|
||||
})()}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import Link from 'next/link';
|
||||
import Card from '@/components/ui/Card';
|
||||
import Button from '@/components/ui/Button';
|
||||
import { ReviewProtestModal } from '@/components/leagues/ReviewProtestModal';
|
||||
import QuickPenaltyModal from '@/components/leagues/QuickPenaltyModal';
|
||||
import PenaltyFAB from '@/components/leagues/PenaltyFAB';
|
||||
import {
|
||||
getRaceRepository,
|
||||
getProtestRepository,
|
||||
@@ -43,11 +45,13 @@ export default function LeagueStewardingPage() {
|
||||
const [protestsByRace, setProtestsByRace] = useState<Record<string, Protest[]>>({});
|
||||
const [penaltiesByRace, setPenaltiesByRace] = useState<Record<string, Penalty[]>>({});
|
||||
const [driversById, setDriversById] = useState<Record<string, DriverDTO>>({});
|
||||
const [allDrivers, setAllDrivers] = useState<DriverDTO[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [isAdmin, setIsAdmin] = useState(false);
|
||||
const [activeTab, setActiveTab] = useState<'pending' | 'history'>('pending');
|
||||
const [selectedProtest, setSelectedProtest] = useState<Protest | null>(null);
|
||||
const [expandedRaces, setExpandedRaces] = useState<Set<string>>(new Set());
|
||||
const [showQuickPenaltyModal, setShowQuickPenaltyModal] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
async function checkAdmin() {
|
||||
@@ -110,6 +114,7 @@ export default function LeagueStewardingPage() {
|
||||
}
|
||||
});
|
||||
setDriversById(byId);
|
||||
setAllDrivers(Object.values(byId));
|
||||
|
||||
// Auto-expand races with pending protests
|
||||
const racesWithPending = new Set<string>();
|
||||
@@ -495,6 +500,10 @@ export default function LeagueStewardingPage() {
|
||||
)}
|
||||
</Card>
|
||||
|
||||
{activeTab === 'history' && (
|
||||
<PenaltyFAB onClick={() => setShowQuickPenaltyModal(true)} />
|
||||
)}
|
||||
|
||||
{selectedProtest && (
|
||||
<ReviewProtestModal
|
||||
protest={selectedProtest}
|
||||
@@ -503,6 +512,15 @@ export default function LeagueStewardingPage() {
|
||||
onReject={handleRejectProtest}
|
||||
/>
|
||||
)}
|
||||
|
||||
{showQuickPenaltyModal && (
|
||||
<QuickPenaltyModal
|
||||
drivers={allDrivers}
|
||||
onClose={() => setShowQuickPenaltyModal(false)}
|
||||
adminId={currentDriverId}
|
||||
races={races.map(r => ({ id: r.id, track: r.track, scheduledAt: r.scheduledAt }))}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user