Skip to content

feat(meetings): load the viewer's own rsvp on the v2 page - #3344

Merged
nunoeufrasio merged 4 commits into
feat/meeting-details-v2from
feat/issue-2880
Oct 7, 2026
Merged

nunoeufrasio merged 4 commits into
feat/meeting-details-v2from
feat/issue-2880

Conversation

@nunoeufrasio

@nunoeufrasio nunoeufrasio commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Closes #2880 · epic #1765 · targets the integration branch feat/meeting-details-v2

Summary

E2-04 loads the viewer's own RSVP on the V2 page (FR-023). The public payload doesn't carry it.

MeetingDetailsStateService.myRsvp holds the viewer's answer for the selected occurrence:

  • RsvpResponse once answered, null when not answered yet, undefined while unknown.
  • It's fetched only for a signed-in viewer on the invite list of an upcoming or live meeting with RSVP tracking on.
  • It's scoped to the selected occurrence through resolveRsvpOccurrenceId, as V1 scopes it.

It feeds three places:

  • Status pill and identity bar (resolveMeetingStatus): going / maybe / cant-attend, or awaiting-rsvp when not answered.
  • Header data-my-rsvp (testid contract): accepted / maybe / declined / none, and absent while unknown.
  • The rsvp slot's line: until E2-05's card replaces it, it names the answer ("You're going.", "You replied maybe.", "You can't attend.", "…You haven't replied yet."). It carries the same data-my-rsvp.

A failed fetch reads as unknown, never as "not answered" (#2880: "degrades to no chip"):

  • The pill shows the time state, not "Awaiting your RSVP".
  • MeetingService.getMeetingRsvpForCurrentUser turns failures into null, so this PR adds a strict sibling, getMeetingRsvpForCurrentUserOrFail, that logs and rethrows.
  • The original keeps its exact behaviour (log, then null) by delegating to it, so V1 and the RSVP button group are unchanged. Specs pin both behaviours.
  • BFF (added in review): the server's getMeetingRsvpForCurrentUser used to catch every failure and answer 200 null, which made failures indistinguishable from "not answered" before they ever reached the client.
    • It now lets a failed registrant or RSVP lookup propagate to apiErrorHandler, which returns an error status.
    • null still means no identity or no registrant row.
    • Its only caller is the /rsvp/me controller. V1's client still reads any error as null, so V1 is unchanged.

setMyRsvp(meetingId, occurrenceId, rsvp) is for E2-05's card to apply a just-saved RSVP ahead of the indexer:

  • It switches out any fetch in flight. V1's rsvpUpdateCounter guarded the same race, but inside a switchMap its filter could never fire, so it isn't ported.
  • The request key is deduplicated, so the 30s clock tick and re-lookups never refetch over the saved answer.
  • A save that lands after the page moved to another occurrence or meeting is dropped. This is checked synchronously against the route.
  • A failed fetch is retried once at once, then on each 30s clock tick until it succeeds.

V1's "bind (rsvpChanged) on the attendee branch" maps to setMyRsvp, which E2-05's card will call. No other component has to wire it.

Validation

  • Tests: V2 page specs 215 (meetings 931 before the review fixes); MeetingService 20. yarn build, a forced check-types, lint:check (0 errors) and format:check are green.
  • New coverage:
    • each answer → status and attribute;
    • occurrence scoping;
    • failure → unknown;
    • no fetch for outsiders, tracking off, anonymous, or ended;
    • a saved answer beats an in-flight fetch and survives a re-lookup;
    • changing the occurrence refetches;
    • stale saves are dropped.
  • Pre-PR review: one round with the general, repo-code and learnings reviewers. Fixed in 372b79e:
    • setMyRsvp scoped to the meeting and occurrence the RSVP was saved for;
    • dedupe and refetch tests;
    • the slot attribute assertion.
  • /lfx-self-serve-pr-readiness (against the integration branch) READY; /preflight passes.

🤖 Generated with Claude Code

Closes #2880

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>
Refs #2880

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>
@nunoeufrasio
nunoeufrasio requested a review from a team as a code owner October 7, 2026 09:21
@cursor

cursor Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes BFF /rsvp/me error handling and meeting-details state/fetch logic; V1 keeps the tolerant client path, but V2 status and RSVP messaging depend on the new strict contract.

Overview
Loads the signed-in invitee's own RSVP on the V2 meeting details page (E2-04 / FR-023), since the public meeting payload does not include it.

MeetingDetailsStateService now fetches /rsvp/me (occurrence-scoped for series), exposes myRsvp / myRsvpAttr, feeds resolveMeetingStatus (going / maybe / awaiting-rsvp, etc.), and adds setMyRsvp for E2-05 optimistic saves with deduped requests, retries on failure, and stale-save guards when the route or occurrence changes. Fetch failures stay unknown (undefined) so the status pill does not show "Awaiting your RSVP".

The header pill and rsvp action slot bind data-my-rsvp and show confirmation copy ("You're going.", etc.) until the RSVP card lands in E2-05.

API semantics: client getMeetingRsvpForCurrentUserOrFail rethrows after logging; the lenient method still returns null on error for V1/RSVP buttons. The BFF getMeetingRsvpForCurrentUser no longer swallows lookup failures as 200 null—errors propagate so V2 can distinguish load failure from no answer—and uses a strict raw RSVP page walk.

Specs and testid-contract.md document the attribute behavior.

Reviewed by Cursor Bugbot for commit 1d272fe. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 298b0e45-de3f-4531-88d6-fba462b3965a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@nunoeufrasio
nunoeufrasio requested review from MRashad26 and dealako and a balanced review from Copilot October 7, 2026 09:21

dealako commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

@nunoeufrasio I'm starting review 1 of this pull request now (started 2026-10-07 09:25 UTC). This usually takes a few minutes — I'll update this comment with the summary when I'm done.


Hi @nunoeufrasio, thanks for this PR.

The change loads the viewer's own RSVP on the V2 meeting page and feeds it to the status pill, the header and the rsvp slot. A failed fetch reads as unknown rather than "not answered". The strict OrFail sibling keeps V1 behaviour unchanged. setMyRsvp is scoped to the meeting and occurrence, and a save beats an in-flight fetch. The new specs cover each of these paths.

⚪ Nit: 1 issue: A failed RSVP fetch is never retried

✅ Approved

➡️ This auto-review agent is a preview. Please send feedback to @dealako.

@dealako dealako left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review found no blocking, security or privacy issues; one nit is inline. Approving.


Generated by Claude Code

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

BFF failures still collapse into “not answered,” and stale saves can briefly update a newly selected view.

Review effort: Balanced
Findings: 2 High severity

Open (2)
What changed in this PR

Adds viewer-specific RSVP state to the V2 meeting details page.

Changes:

  • Fetches occurrence-scoped RSVP state and exposes status attributes/messages.
  • Adds optimistic RSVP updates and failure handling.
  • Expands unit tests and the test-ID contract.
File Description
specs/​011-meeting-details-redesign/​testid-contract.md Documents RSVP attributes.
apps/​lfx-one/​src/​app/​shared/​services/​meeting.service.ts Adds strict RSVP retrieval.
apps/​lfx-one/​src/​app/​shared/​services/​meeting.service.spec.ts Tests retrieval behavior.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-page/​meeting-details-state.service.ts Manages viewer RSVP state.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-page/​meeting-details-state.service.spec.ts Tests RSVP state transitions.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-page/​components/​header/​header.component.ts Exposes RSVP header attribute.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-page/​components/​header/​header.component.spec.ts Tests header attributes.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-page/​components/​action-slot/​action-slot.component.ts Produces RSVP messaging.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-page/​components/​action-slot/​action-slot.component.spec.ts Tests RSVP messages.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-page/​components/​action-slot/​action-slot.component.html Renders RSVP state.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/lfx-one/src/app/shared/services/meeting.service.ts
…lures

Refs #2880

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 7, 2026 09:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Lookup failures can still become successful empty responses, and a retry can overwrite a saved RSVP.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
Resolved since last review (2)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Use strict registrant lookup to detect partial fetch failures

apps/​lfx-one/​src/​server/​services/​meeting.service.ts:1720

This registrant lookup is still partial-tolerant: getMeetingRegistrantsForUser calls fetchAllQueryResources without failOnPartial: true. Because this path intentionally supports multiple occurrence-specific/re-registration rows, a later-page failure can omit the row carrying the applicable RSVP and return 200 with null or an older answer instead of the required unknown/error state. Add a strict option/sibling for this complete-set lookup and use it here.

Comment thread apps/lfx-one/src/server/services/meeting.service.ts Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b76a16b. Configure here.

Refs #2880

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 7, 2026 09:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The registrant lookup can still collapse a later-page upstream failure into a successful null response.

Review effort: Balanced
Findings: None

Resolved since last review (2)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Enforce strict failure handling for paginated registrant lookup

apps/​lfx-one/​src/​server/​services/​meeting.service.ts:1720

This registrant lookup is still partial-tolerant: getMeetingRegistrantsForUser calls fetchAllQueryResources without failOnPartial: true, so a later-page failure returns a partial prefix instead of rejecting. That can make this endpoint return 200 null or select an RSVP from an incomplete registrant-ID set—the exact failure/“not answered” ambiguity this strict path is intended to remove. Add a strict option to getMeetingRegistrantsForUser, enable it here, and cover a second-page registrant failure.

@nunoeufrasio
nunoeufrasio merged commit 94a0b36 into feat/meeting-details-v2 Oct 7, 2026
10 checks passed
@nunoeufrasio
nunoeufrasio deleted the feat/issue-2880 branch October 7, 2026 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants