Interested Events Tab

Branch: feat/interested-events-tab Merged into: develop Date: March 2026

Overview

Added a dedicated “Interested” tab to EventsScreen, completing the read side of the RSVP feature. Users who star events as “Interested” can now browse all their starred events in one place, alongside the existing “Attending” and “My Events” tabs.

Why It Was Built

The previous iteration added the ability to mark events as “Interested” from the event details page. However, without a list view, users had no way to revisit which events they had starred. This iteration closes the CRUD loop: write (mark interested) → read (view the list).

The feature directly corresponds to roadmap item: “Attendee lists with privacy controls — Event reminders” and supports the broader goal of keeping users engaged with events they haven’t committed to yet.

What Changed

API Layer (event_api_service.dart)

Added getInterestedEvents({int page}) — queries the event_attendees table filtered by status = 'interested' for the current user, joining with events and profiles (organizer). Returns a list of fully mapped Event objects with isUserInterested = true pre-set.

event_attendees (user_id = me, status = 'interested')
  └── events (*, profiles!events_organizer_id_fkey(*))

Repository (event_repository.dart)

  • Added getInterestedEvents({int page}) wrapper

State & Logic (event_notifier.dart)

  • Added interestedEvents list to EventState (with copyWith support)
  • Added loadInterestedEvents({bool refresh}) method
  • Updated markInterested() to optimistically add the event to interestedEvents immediately (no reload needed)
  • Updated unmarkInterested() to optimistically remove the event from interestedEvents

UI (events_screen.dart)

  • Expanded TabController from 4 → 5 tabs
  • Added “Interested” tab between “Attending” and “Map”
  • Loads loadInterestedEvents(refresh: true) on screen init alongside existing loads
  • Contextual empty-state message guides users: “Nessun evento salvato. Segna ‘Interessato’ sugli eventi che vuoi ricordare!”
  • _buildEventsList now accepts an optional emptyMessage parameter
  • _buildEmptyState wraps text in a Padding + textAlign: center for multi-line messages

Optimistic Updates Pattern

Rather than refetching the full list after each mark/unmark action, the notifier updates the in-memory interestedEvents list immediately. This means:

  • Tab badge/count updates instantly
  • No loading spinner after tapping “Interested”
  • If the server call fails, the error is surfaced via state.error but the UI has already moved

This trade-off is appropriate here: the failure rate for a simple upsert is near zero, and the UX cost of a spinner outweighs the risk.