- Add resend_attempts and last_resent_at to email_logs schema and migrations
- Add POST /api/emails/logs/:id/resend and emailService.resendFromLog
- Add resendLog API and EmailLog.resendAttempts/lastResentAt
- Add All/Failed sub-tabs, resend button for all emails, re-sent indicator in logs and detail modal
Made-with: Cursor
- Add useStatsPrivacy hook with localStorage persistence for stats visibility
- Single event page: desktop privacy button, hide capacity chip when stats hidden
- Events list: row/card click navigates to event detail; stopPropagation on actions
- Backend GET /tickets: include payment for each ticket (removes N+1)
- Bookings page: use list payment data, show — when payment method unknown
Made-with: Cursor
- Backend: add 'unlisted' to schema enum and Zod validation; allow booking for unlisted events
- Frontend: Event type and guards updated; unlisted events bookable, excluded from public listing/sitemap
- Admin: badge, status dropdown, Make Unlisted / Make Public / Unpublish actions; scanner/emails/tickets include unlisted
Co-authored-by: Cursor <cursoragent@cursor.com>
- Extract shared mobile components (BottomSheet, MoreMenu, Dropdown, etc.) into MobileComponents.tsx
- Make admin pages mobile-friendly: bookings, emails, events, faq, payments, tickets, users
- Redesign homepage Next Event card with banner image, responsive layout, and updated styling
- Fix past events showing on homepage/linktree: use proper Date comparison, auto-unfeature expired events
- Add "Over" tag to admin events list for past events
- Fix backend FRONTEND_URL for cache revalidation
Co-authored-by: Cursor <cursoragent@cursor.com>
- Switch from tag-based caching to cache: no-store for all backend fetches
- Add dynamic = force-dynamic to prevent Next.js static caching
- Ensures llms.txt always reflects the current featured event and FAQ data
Co-authored-by: Cursor <cursoragent@cursor.com>
- Update FRONTEND_URL default from localhost:3002 to localhost:3019 (actual frontend port)
- Reorder systemd service so EnvironmentFile loads before Environment overrides
Co-authored-by: Cursor <cursoragent@cursor.com>
- Extract revalidateFrontendCache() to backend/src/lib/revalidate.ts
- Call revalidation from site-settings when featuredEventId is set/cleared
- Ensures homepage shows updated featured event after admin changes
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add X close button on valid ticket screen to dismiss without check-in
- Rewrite QRScanner: full unmount when leaving Scan tab, stop MediaStream tracks
- Remount scanner via key when tab active; no hidden DOM
- Use 100dvh for mobile height; force layout reflow after camera start
- visibilitychange handler for tab suspend/resume
Co-authored-by: Cursor <cursoragent@cursor.com>
- Backend: Add /events/:eventId/attendees/export and /events/:eventId/tickets/export with q/status; legacy redirect for old export path
- API: exportAttendees q param, new exportTicketsCSV for tickets CSV
- Admin event page: unified tabs+content container, portal dropdowns to fix clipping, separate mobile export/add-ticket sheets (fix double menu), responsive tab bar and card layout
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add in-memory email queue with rate limiting (MAX_EMAILS_PER_HOUR)
- Bulk send to event attendees now queues and returns immediately
- Frontend shows 'Emails are being sent in the background'
- Legal pages, settings, and placeholders updates
Co-authored-by: Cursor <cursoragent@cursor.com>
- SSR next event on homepage; pass initialEvent from server to avoid client-only content
- Add schema.org Event JSON-LD on homepage when next event exists
- Dynamic homepage metadata (description, OG, Twitter) with next event date
- Add dynamic /llms.txt route for AI-friendly plain-text event info
- Revalidation: support next-event tag; backend revalidates sitemap + next-event on event CUD
- Allow /llms.txt in robots.txt
Co-authored-by: Cursor <cursoragent@cursor.com>
- Backend: extend PUT /api/users/:id with email and accountStatus; admin-only for role/email/accountStatus; return isClaimed, rucNumber, accountStatus in user responses
- Frontend: add Edit button and modal on /admin/users to edit name, email, phone, role, language preference, account status
Co-authored-by: Cursor <cursoragent@cursor.com>
- Backend: use calculateAvailableSeats so availableSeats is never negative
- Backend: reject public booking when confirmed >= capacity; admin create/manual bypass capacity
- Frontend: spotsLeft = max(0, capacity - bookedCount), isSoldOut when bookedCount >= capacity
- Frontend: sold-out redirect on booking page, cap quantity by spotsLeft, never show negative
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add option to approve/reject payments without sending notification emails
(checkbox in review popup, default enabled)
- Add payment reminder email template and send functionality
- Track when reminder emails are sent (reminderSentAt field)
- Display reminder sent timestamp in payment review popup
- Make payment review popup scrollable for better UX
- Add payment-reminder template to email system (available in admin emails)
- Add featured_event_id to site_settings (schema + migration)
- Backend: featured event logic in /events/next/upcoming with auto-unset when event ends
- Site settings: PUT supports featuredEventId, add PUT /featured-event for admin
- Admin events: Set as featured checkbox in editor, star toggle in list, featured badge
- Admin settings: Featured Event section with current event and remove/change links
- API: siteSettingsApi.setFeaturedEvent(), Event.isFeatured, SiteSettings.featuredEventId
- Homepage/linktree unchanged: still use getNextUpcoming (now returns featured or fallback)
- Email: formatDate/formatTime use site timezone from settings
- PDF tickets: date/time formatted in site timezone
- Tickets routes: fetch timezone and pass to PDF generation