- Add COI_REASSIGNED and MANUAL_REASSIGNED notification types with distinct
email templates, icons, and priorities
- COI declaration dialog now shows a confirmation step warning that the
project will be reassigned before submitting
- reassignAfterCOI now checks historical assignments (all rounds, audit logs)
to never assign the same project to a juror twice, and prefers jurors with
incomplete evaluations over those who have finished all their work
- Admin transfer (transferAssignments) sends per-juror MANUAL_REASSIGNED
notifications with actual project names instead of generic batch emails
- docker-entrypoint syncs notification settings on every deploy via upsert
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rewrite ctaButton to use td-background pattern (works in all clients
including Outlook, Gmail, Yahoo, Apple Mail) instead of VML/conditional
comments that broke link clicking in Outlook desktop
- Add plaintext fallback URL below every CTA button so users always have
a working link even if the button fails
- Add getBaseUrl() and ensureAbsoluteUrl() helpers in email.ts to
guarantee all email links are absolute https:// URLs
- Apply ensureAbsoluteUrl safety net in sendStyledNotificationEmail and
sendNotificationEmail so relative paths can never reach email templates
- Standardize all NEXTAUTH_URL fallbacks to https://portal.monaco-opc.com
(was inconsistently http://localhost:3000 or https://monaco-opc.com)
- Fix legacy notification.ts: wrong argument order in
sendJuryInvitationEmail (URL was passed as name parameter)
- Fix legacy notification.ts: missing NEXTAUTH_URL fallback for
evaluation reminder URL construction
- Change tooltip styling from red bg to white bg with black text
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Award shortlist:
- Expandable reasoning text (click to toggle, hover hint)
- Bulk select/deselect all checkbox in header
- Top N projects highlighted with amber background
- New bulkToggleShortlisted backend mutation
Invite link expiry:
- New "Invitation Link Expiry (hours)" field in Security Settings
- Reads from systemSettings `invite_link_expiry_hours` (default 72h / 3 days)
- Email template dynamically shows "X hours" or "X days" based on setting
- All 3 invite paths (bulk create, single invite, bulk resend) use setting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Jury dashboard: collapse zero-assignment state into single welcome card
with inline quick actions; merge completion bar into stats row; tighten spacing
- Manual assignment: replace tiny Dialog modal with inline collapsible section
featuring searchable juror combobox and multi-select project list with bulk assign
- Fix applicant invite URL path (/auth/accept-invite -> /accept-invite)
- Add APPLICANT role redirect to /my-submission from root page
- Add Applicant label to accept-invite role display
- Fix a/an grammar in invitation emails and accept-invite page
- Set-password page: use MOPC logo instead of lock icon
- Notification bell: remove filter tabs, always show all notifications
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 15+ styled email templates matching existing invite email design
- Wire up notification triggers in all routers (assignment, round, project, mentor, application, onboarding)
- Add test email button for each notification type in admin settings
- Add round-attached notifications: admins can configure which notification to send when projects enter a round
- Fall back to status-based notifications when round has no configured notification
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Email settings: Add separate sender display name field
- Rounds page: Drag-and-drop reordering with visible order numbers
- Round creation: Auto-assign projects to filtering rounds, auto-activate if voting started
- Round detail: Fix incorrect "voting period ended" message for draft rounds
- Projects page: Add delete option with confirmation dialog
- AI filtering: Add configurable batch size and parallel request settings
- Filtering results: Fix duplicate criteria display
- Add seed scripts for notification settings and MOPC onboarding form
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move notification bell to sidebar header next to logo (desktop)
- Keep bell in mobile header bar (already well-placed)
- Change email sender name from 'MOPC Platform' to 'MOPC Portal'
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
- Implement background job system for AI filtering to avoid HTTP timeouts
- Add FilteringJob model to track progress of long-running filtering operations
- Add real-time progress polling for filtering operations on round details page
- Create custom DateTimePicker component with calendar popup (no year picker hassle)
- Fix round date persistence bug (refetchOnWindowFocus was resetting form state)
- Integrate filtering controls into round details page for filtering rounds
- Display AI reasoning for flagged/filtered projects in results table
- Add onboarding system scaffolding (schema, routes, basic UI)
- Allow setting round dates in the past for manual overrides
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix MinIO port parsing bug: use protocol-appropriate defaults (443/80)
instead of hardcoded 9000 fallback, enabling public URL endpoint
- Remove unused SMTP server config from NextAuth EmailProvider to prevent
connection errors (sendVerificationRequest is fully overridden)
- Replace extra_hosts with DNS config (8.8.8.8) so container resolves
mail.monaco-opc.com to public IP instead of host loopback
- Add invite token auth: single-click accept-invite flow replacing broken
two-email invitation process
- Auto-send invitation emails on bulk user creation
- Update email template expiry text from 24 hours to 7 days
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Read SMTP settings from database (admin panel) with env var fallback
- Cache transporter and rebuild when settings change
- Remove dark blue footer from emails; use single white content box
with logo and tagline at the bottom separated by a subtle border
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add universal /settings/profile page accessible to all roles with
avatar upload, bio, phone, password change, and account deletion
- Expand updateProfile endpoint to accept bio (metadataJson), phone,
and notification preference
- Add deleteAccount endpoint with password confirmation
- Add Profile Settings link to all nav components (admin, jury, mentor,
observer)
- Add /admin/mentors list page and /admin/mentors/[id] detail page for
mentor management
- Add Mentors nav item to admin sidebar
- Update email logo URLs to S3 (s3.monaco-opc.com/public/)
- Add ocean.png background image to email wrapper
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Full Next.js 15 platform with tRPC, Prisma, PostgreSQL, NextAuth.
Includes production Dockerfile (multi-stage, port 7600), docker-compose
with registry-based image pull, Gitea Actions CI workflow, nginx config
for portal.monaco-opc.com, deployment scripts, and DEPLOYMENT.md guide.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>