This commit is contained in:
2025-12-09 23:00:51 +01:00
parent 3659d25e52
commit 8fd8999e9e
4 changed files with 33 additions and 5 deletions

View File

@@ -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:

View File

@@ -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<LeagueStewardingFormDTO>) => {
onChange({

View File

@@ -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();

View File

@@ -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;
}