'use client'; import { Button } from '@/ui/Button'; import { Icon } from '@/ui/Icon'; import { Modal } from '@/ui/Modal'; import { Text } from '@/ui/Text'; import { Box } from '@/ui/Box'; import { Grid } from '@/ui/Grid'; import { Surface } from '@/ui/Surface'; import { NotificationStat, NotificationDeadline } from '@/ui/NotificationContent'; import { AlertCircle, AlertTriangle, Bell, Clock, Flag, Medal, Shield, Star, Trophy, Users, Vote, } from 'lucide-react'; import React from 'react'; import type { Notification, NotificationAction } from './notificationTypes'; interface ModalNotificationProps { notification: Notification; onAction: (notification: Notification, actionId?: string) => void; onDismiss?: (notification: Notification) => void; onNavigate?: (href: string) => void; } const notificationIcons: Record = { protest_filed: AlertTriangle, protest_defense_requested: Shield, protest_vote_required: Vote, penalty_issued: AlertTriangle, race_results_posted: Trophy, race_performance_summary: Medal, race_final_results: Star, league_invite: Users, race_reminder: Flag, }; export function ModalNotification({ notification, onAction, onDismiss, onNavigate, }: ModalNotificationProps) { const handleAction = (action: NotificationAction) => { onAction(notification, action.id); if (action.href && onNavigate) { onNavigate(action.href); } }; const handlePrimaryAction = () => { onAction(notification, 'primary'); if (notification.actionUrl && onNavigate) { onNavigate(notification.actionUrl); } }; const NotificationIcon = notificationIcons[notification.type] || AlertCircle; const data: Record = notification.data ?? {}; const getNumber = (value: unknown): number | null => { if (typeof value === 'number' && Number.isFinite(value)) return value; if (typeof value === 'string') { const parsed = Number(value); if (Number.isFinite(parsed)) return parsed; } return null; }; const getString = (value: unknown): string | null => { if (typeof value === 'string') return value; if (typeof value === 'number' && Number.isFinite(value)) return String(value); return null; }; const isValidDate = (value: unknown): value is Date => value instanceof Date && !Number.isNaN(value.getTime()); const deadlineValue = data.deadline; const deadline: Date | null = isValidDate(deadlineValue) ? deadlineValue : typeof deadlineValue === 'string' || typeof deadlineValue === 'number' ? new Date(deadlineValue) : null; const hasDeadline = !!deadline && !Number.isNaN(deadline.getTime()); const isRaceNotification = notification.type.startsWith('race_'); const provisionalRatingChange = getNumber(data.provisionalRatingChange) ?? 0; const finalRatingChange = getNumber(data.finalRatingChange) ?? 0; const ratingChange = provisionalRatingChange || finalRatingChange; const protestId = getString(data.protestId); return ( onDismiss(notification) : undefined} title={notification.title} description={isRaceNotification ? 'Race Update' : 'Action Required'} icon={} footer={ {notification.actions && notification.actions.length > 0 ? ( notification.actions.map((action, index) => ( )) ) : ( isRaceNotification ? ( <> ) : ( ) )} } > {notification.message} {isRaceNotification && ( = 0 ? '+' : ''}${ratingChange}`} intent={ratingChange >= 0 ? 'success' : 'critical'} /> )} {hasDeadline && !isRaceNotification && ( )} {protestId && ( PROTEST ID {protestId} )} {notification.requiresResponse && !isRaceNotification && ( This action is required to continue )} ); }