Add notification bell system and MOPC onboarding form

Notification System:
- Add InAppNotification and NotificationEmailSetting database models
- Create notification service with 60+ notification types for all user roles
- Add notification router with CRUD endpoints
- Build NotificationBell UI component with dropdown and unread count
- Integrate bell into admin, jury, mentor, and observer navs
- Add notification email settings admin UI in Settings > Notifications
- Add notification triggers to filtering router (complete/failed)
- Add sendNotificationEmail function to email library
- Add formatRelativeTime utility function

MOPC Onboarding Form:
- Create /apply landing page with auto-redirect for single form
- Create seed script for MOPC 2026 application form (6 steps)
- Create seed script for default notification email settings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-03 21:30:25 +01:00
parent e1968d45df
commit 0277768ed7
18 changed files with 2344 additions and 13 deletions

View File

@@ -17,6 +17,7 @@ import {
HardDrive,
Shield,
Settings as SettingsIcon,
Bell,
} from 'lucide-react'
import { AISettingsForm } from './ai-settings-form'
import { AIUsageCard } from './ai-usage-card'
@@ -25,6 +26,7 @@ import { EmailSettingsForm } from './email-settings-form'
import { StorageSettingsForm } from './storage-settings-form'
import { SecuritySettingsForm } from './security-settings-form'
import { DefaultsSettingsForm } from './defaults-settings-form'
import { NotificationSettingsForm } from './notification-settings-form'
function SettingsSkeleton() {
return (
@@ -108,7 +110,7 @@ export function SettingsContent({ initialSettings }: SettingsContentProps) {
return (
<Tabs defaultValue="ai" className="space-y-6">
<TabsList className="grid w-full grid-cols-2 lg:grid-cols-6">
<TabsList className="grid w-full grid-cols-3 lg:grid-cols-7">
<TabsTrigger value="ai" className="gap-2">
<Bot className="h-4 w-4" />
<span className="hidden sm:inline">AI</span>
@@ -121,6 +123,10 @@ export function SettingsContent({ initialSettings }: SettingsContentProps) {
<Mail className="h-4 w-4" />
<span className="hidden sm:inline">Email</span>
</TabsTrigger>
<TabsTrigger value="notifications" className="gap-2">
<Bell className="h-4 w-4" />
<span className="hidden sm:inline">Notifications</span>
</TabsTrigger>
<TabsTrigger value="storage" className="gap-2">
<HardDrive className="h-4 w-4" />
<span className="hidden sm:inline">Storage</span>
@@ -178,6 +184,20 @@ export function SettingsContent({ initialSettings }: SettingsContentProps) {
</Card>
</TabsContent>
<TabsContent value="notifications">
<Card>
<CardHeader>
<CardTitle>Notification Email Settings</CardTitle>
<CardDescription>
Configure which notification types should also send email notifications
</CardDescription>
</CardHeader>
<CardContent>
<NotificationSettingsForm />
</CardContent>
</Card>
</TabsContent>
<TabsContent value="storage">
<Card>
<CardHeader>