From 8fd8999e9e6d3a03865316682c8e13abe1f08cd5 Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Tue, 9 Dec 2025 23:00:51 +0100 Subject: [PATCH] wip --- apps/website/app/leagues/create/page.tsx | 3 ++- .../leagues/LeagueStewardingSection.tsx | 13 ++++++++++++- .../notifications/NotificationProvider.tsx | 16 +++++++++++++++- apps/website/lib/leagueWizardService.ts | 6 ++++-- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/apps/website/app/leagues/create/page.tsx b/apps/website/app/leagues/create/page.tsx index af458ecf5..8ecd4e7ca 100644 --- a/apps/website/app/leagues/create/page.tsx +++ b/apps/website/app/leagues/create/page.tsx @@ -5,7 +5,7 @@ import CreateLeagueWizard from '@/components/leagues/CreateLeagueWizard'; import Section from '@/components/ui/Section'; import Container from '@/components/ui/Container'; -type StepName = 'basics' | 'visibility' | 'structure' | 'schedule' | 'scoring' | 'review'; +type StepName = 'basics' | 'visibility' | 'structure' | 'schedule' | 'scoring' | 'stewarding' | 'review'; function normalizeStepName(raw: string | null): StepName { switch (raw) { @@ -14,6 +14,7 @@ function normalizeStepName(raw: string | null): StepName { case 'structure': case 'schedule': case 'scoring': + case 'stewarding': case 'review': return raw; default: diff --git a/apps/website/components/leagues/LeagueStewardingSection.tsx b/apps/website/components/leagues/LeagueStewardingSection.tsx index 115d7e57f..99e3c9633 100644 --- a/apps/website/components/leagues/LeagueStewardingSection.tsx +++ b/apps/website/components/leagues/LeagueStewardingSection.tsx @@ -61,7 +61,18 @@ export function LeagueStewardingSection({ onChange, readOnly = false, }: LeagueStewardingSectionProps) { - const stewarding = form.stewarding; + // Provide default stewarding settings if not present + const stewarding = form.stewarding ?? { + decisionMode: 'admin_only' as const, + requiredVotes: 2, + requireDefense: false, + defenseTimeLimit: 48, + voteTimeLimit: 72, + protestDeadlineHours: 48, + stewardingClosesHours: 168, + notifyAccusedOnProtest: true, + notifyOnVoteRequired: true, + }; const updateStewarding = (updates: Partial) => { onChange({ diff --git a/apps/website/components/notifications/NotificationProvider.tsx b/apps/website/components/notifications/NotificationProvider.tsx index e969352a6..55073d028 100644 --- a/apps/website/components/notifications/NotificationProvider.tsx +++ b/apps/website/components/notifications/NotificationProvider.tsx @@ -52,7 +52,11 @@ export default function NotificationProvider({ children }: NotificationProviderP // Check for new notifications that need toast/modal display allNotifications.forEach((notification) => { - if (notification.isUnread() && !seenNotificationIds.has(notification.id)) { + // Check both unread and action_required status for modals + const shouldDisplay = (notification.isUnread() || notification.isActionRequired()) && + !seenNotificationIds.has(notification.id); + + if (shouldDisplay) { // Mark as seen to prevent duplicate displays setSeenNotificationIds((prev) => new Set([...prev, notification.id])); @@ -79,6 +83,16 @@ export default function NotificationProvider({ children }: NotificationProviderP return () => clearInterval(interval); }, [currentDriverId, seenNotificationIds]); + // Prevent body scroll when modal is open + useEffect(() => { + if (modalNotification) { + document.body.style.overflow = 'hidden'; + return () => { + document.body.style.overflow = ''; + }; + } + }, [modalNotification]); + const markAsRead = useCallback(async (notification: Notification) => { try { const markRead = getMarkNotificationReadUseCase(); diff --git a/apps/website/lib/leagueWizardService.ts b/apps/website/lib/leagueWizardService.ts index 2fb8ef0ea..d7acb0e0f 100644 --- a/apps/website/lib/leagueWizardService.ts +++ b/apps/website/lib/leagueWizardService.ts @@ -13,7 +13,7 @@ import { LeagueName } from '@gridpilot/racing/domain/value-objects/LeagueName'; import { LeagueDescription } from '@gridpilot/racing/domain/value-objects/LeagueDescription'; import { GameConstraints } from '@gridpilot/racing/domain/value-objects/GameConstraints'; -export type WizardStep = 1 | 2 | 3 | 4 | 5 | 6; +export type WizardStep = 1 | 2 | 3 | 4 | 5 | 6 | 7; export interface WizardErrors { basics?: { @@ -153,7 +153,9 @@ export function validateLeagueWizardStep( } } - // Step 6: Review - no validation needed, it's just review + // Step 6: Stewarding - no validation needed currently (all fields have defaults) + + // Step 7: Review - no validation needed, it's just review return errors; }