Skip to content

Conversation

@andrest50
Copy link
Contributor

@andrest50 andrest50 commented Oct 28, 2025

Summary

Add comprehensive RSVP support for meetings with the following features:

  • RSVP buttons (Yes/Maybe/No) in meeting cards with visual state indication
  • Scope selection modal for recurring meetings (this/all/following occurrences)
  • Dynamic RSVP count calculation respecting scope rules and recency precedence
  • Backend endpoints for creating and fetching RSVPs
  • RSVP calculator utility handling occurrence-specific logic
  • Token-based user identification (backend derives user from bearer token)

Implementation Details

Frontend Changes

  • Added RSVP buttons to meeting cards (dashboard and project views)
  • Created RSVP scope modal component for recurring meeting selections
  • Implemented dynamic RSVP count calculation with signals
  • Added visual feedback for user's current RSVP status

Backend Changes

  • Created endpoints: POST /api/meetings/:uid/rsvp, GET /api/meetings/:uid/rsvp, GET /api/meetings/:uid/rsvps
  • Simplified user identification using bearer token (no username/email in request body)
  • Added RSVP fetching for count calculations

Shared Utilities

  • Created rsvp-calculator.util.ts with comprehensive scope handling logic
  • Added interfaces for RSVP operations
  • Properly handles precedence: most recent applicable RSVP per user wins

RSVP System Logic

The RSVP system correctly handles:

  • Non-recurring meetings: Simple scope, one RSVP per user
  • Recurring meetings: Occurrence-specific RSVPs with three scope types:
    • this (single): Applies only to the selected occurrence
    • all (entire series): Applies to all occurrences in the series
    • following (future): Applies to this occurrence and all future ones
  • Precedence: Most recent RSVP that applies to an occurrence takes priority
  • Count calculation: Dynamically calculates counts from actual RSVP records, respecting scope rules

Test Plan

  • Create RSVP for non-recurring meeting
  • Create RSVP for recurring meeting with different scopes
  • Verify RSVP counts display correctly
  • Verify most recent RSVP takes precedence
  • Test scope modal displays for recurring meetings only
  • Verify visual feedback for current user's RSVP status

Ticket

LFXV2-684

🤖 Generated with Claude Code

Add comprehensive RSVP support for meetings with the following features:
- RSVP buttons (Yes/Maybe/No) in meeting cards with visual state
- Scope selection modal for recurring meetings (this/all/following)
- Dynamic RSVP count calculation respecting scope rules and recency
- Backend endpoints for creating and fetching RSVPs
- RSVP calculator utility handling occurrence-specific logic
- Token-based user identification (backend derives user from bearer token)

The RSVP system correctly handles:
- Non-recurring meetings with simple scope
- Recurring meetings with occurrence-specific RSVPs
- Precedence by most recent applicable RSVP per user
- Scope types: 'this' (single), 'all' (entire series), 'following' (future)

Generated with [Claude Code](https://claude.ai/code)

Signed-off-by: Andres Tobon <andrest2455@gmail.com>
Copilot AI review requested due to automatic review settings October 28, 2025 21:13
@andrest50 andrest50 requested a review from jordane as a code owner October 28, 2025 21:13
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Conventional Commits FTW!

@andrest50 andrest50 changed the title [LFXV2-684] feat(meetings): add rsvp functionality with dynamic count calculation feat(meetings): add meeting rsvp functionality with dynamic count calculation Oct 28, 2025
@coderabbitai
Copy link

coderabbitai bot commented Oct 28, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This PR adds RSVP functionality to meeting management, including new API endpoints for creating meeting RSVPs and retrieving user and meeting RSVPs. New types and interfaces define RSVP responses and scope patterns. The getMeetingRegistrants method now optionally enriches registrants with associated RSVP data through an include_rsvp flag.

Changes

Cohort / File(s) Summary
Shared Types & Interfaces
packages/shared/src/interfaces/meeting.interface.ts
Added RsvpResponse, RsvpScope, RsvpCounts, MeetingRsvp, and CreateMeetingRsvpRequest types/interfaces. Extended MeetingRegistrant with optional rsvp field and MeetingRegistrantWithState with rsvpStatus field.
RSVP Calculator Utility
packages/shared/src/utils/rsvp-calculator.util.ts
New utility module exporting calculateRsvpCounts function and helper getApplicableRsvp to tally RSVP responses with scope-based logic for recurring vs. non-recurring meetings.
Utils Barrel Export
packages/shared/src/utils/index.ts
Added re-export of rsvp-calculator.util module to public API.
Frontend Meeting Service
apps/lfx-one/src/app/shared/services/meeting.service.ts
Added three RSVP endpoints: createMeetingRsvp, getUserMeetingRsvp, getMeetingRsvps. Extended getMeetingRegistrants with optional includeRsvp flag.
Backend Meeting Service
apps/lfx-one/src/server/services/meeting.service.ts
Implemented three RSVP service methods matching frontend signatures. Enhanced getMeetingRegistrants to fetch and attach RSVP data to registrants when includeRsvp is true.
Meeting Controller
apps/lfx-one/src/server/controllers/meeting.controller.ts
Added three RSVP endpoint handlers: createMeetingRsvp, getUserMeetingRsvp, getMeetingRsvps. Modified getMeetingRegistrants to read include_rsvp query param and pass to service.
Meeting Routes
apps/lfx-one/src/server/routes/meetings.route.ts
Added three RSVP routes: POST /:uid/rsvp, GET /:uid/rsvp, GET /:uid/rsvps mapped to controller methods.
Meeting Registrants Component
apps/lfx-one/src/app/modules/project/meetings/components/meeting-registrants/meeting-registrants.component.ts
Updated getMeetingRegistrants call to pass false as second argument for includeRsvp parameter.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Component
    participant Controller
    participant MeetingService as Backend Service
    participant API as Microservice

    Client->>Component: Load meeting registrants
    Component->>Controller: GET /meetings/:uid/registrants?include_rsvp=true
    Controller->>MeetingService: getMeetingRegistrants(uid, includeRsvp=true)
    MeetingService->>API: GET /registrants
    API-->>MeetingService: registrants[]
    alt includeRsvp is true
        MeetingService->>API: GET /rsvps?filter=meeting_uid
        API-->>MeetingService: rsvps[]
        MeetingService->>MeetingService: Enrich registrants with RSVP by username
    end
    MeetingService-->>Controller: registrants[]{rsvp?}
    Controller-->>Component: 200 registrants[]{rsvp?}
    Component-->>Client: Display registrants with RSVP data
Loading
sequenceDiagram
    participant Client
    participant Component
    participant Controller
    participant MeetingService as Backend Service
    participant API as Microservice

    Client->>Component: Submit RSVP for meeting
    Component->>Controller: POST /meetings/:uid/rsvp {scope, response}
    Controller->>MeetingService: createMeetingRsvp(uid, payload, userContext)
    MeetingService->>API: POST /meetings/:uid/rsvp
    API-->>MeetingService: MeetingRsvp
    MeetingService-->>Controller: MeetingRsvp
    Controller-->>Component: 201 MeetingRsvp
    Component-->>Client: RSVP confirmed
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Duplicated RSVP methods in frontend service: The summary notes that createMeetingRsvp, getUserMeetingRsvp, and getMeetingRsvps appear twice in meeting.service.ts, both with take(1) and catchError patterns—verify whether this is intentional or requires deduplication.
  • RSVP Calculator scope logic: The getApplicableRsvp helper implements scope-based RSVP selection ('all', 'single', 'following') that needs careful validation of occurrence matching and timestamp comparisons.
  • Registrant enrichment integration: Verify username-based matching between registrants and RSVPs handles edge cases (missing usernames, duplicate usernames) correctly.
  • Parameter propagation chain: Confirm the include_rsvp query parameter is correctly parsed and threaded through all layers (controller → service → API calls).

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes check ❓ Inconclusive The summary notes duplicated RSVP-related methods in the frontend service and an unexplained change passing false to getMeetingRegistrants; unclear if these represent intentional code patterns or unintended duplications. Review and clarify whether the duplicated RSVP methods in meeting.service.ts and the false parameter in meeting-registrants.component.ts are intentional.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main feature addition: RSVP functionality with dynamic count calculation for meetings.
Description check ✅ Passed The description comprehensively details the implementation across frontend, backend, and shared utilities, clearly explaining RSVP features, system logic, and test coverage.
Linked Issues check ✅ Passed All coding requirements from LFXV2-684 are met: endpoint for responding to meeting invites (POST /api/meetings/:uid/rsvp, GET /api/meetings/:uid/rsvp, GET /api/meetings/:uid/rsvps), RSVP data returned for status display and count aggregation.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch andrest50/meeting-rsvp

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

@github-actions
Copy link

github-actions bot commented Oct 28, 2025

🚀 Deployment Status

Your branch has been deployed to: https://ui-pr-135.dev.v2.cluster.linuxfound.info

Deployment Details:

  • Environment: Development
  • Namespace: ui-pr-135
  • ArgoCD App: ui-pr-135

The deployment will be automatically removed when this PR is closed.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements a new RSVP (Répondez s'il vous plaît) feature for meetings, allowing users to respond to meeting invitations with "accepted," "maybe," or "declined" status. The feature supports both non-recurring and recurring meetings with scope-based responses.

Key changes:

  • Added RSVP data models and API endpoints for creating and retrieving RSVPs
  • Implemented RSVP calculation logic that handles different scopes (this, all, following) for recurring meetings
  • Enhanced the UI with RSVP buttons in meeting cards and a scope selection modal for recurring meetings

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packages/shared/src/interfaces/meeting.interface.ts Added RSVP-related TypeScript interfaces and types
packages/shared/src/utils/rsvp-calculator.util.ts New utility for calculating RSVP counts based on scope and occurrence
packages/shared/src/utils/index.ts Exported the new RSVP calculator utility
apps/lfx-one/src/server/services/meeting.service.ts Added three new methods for RSVP operations (create, get user RSVP, get all RSVPs)
apps/lfx-one/src/server/controllers/meeting.controller.ts Added controller methods for RSVP API endpoints
apps/lfx-one/src/server/routes/meetings.route.ts Added three new RSVP routes
apps/lfx-one/src/server/utils/auth-helper.ts Enhanced username extraction logic for better token handling
apps/lfx-one/src/server/server.ts Added debug console.log and removed auth scope
apps/lfx-one/src/app/shared/services/meeting.service.ts Added client-side service methods for RSVP operations
apps/lfx-one/src/app/shared/components/rsvp-scope-modal/* New modal component for selecting RSVP scope
apps/lfx-one/src/app/shared/components/dashboard-meeting-card/* Added RSVP UI buttons and interaction logic
apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/* Integrated RSVP counts display using the calculator utility

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (2)
apps/lfx-one/src/server/utils/auth-helper.ts (1)

27-28: Consider breaking the long line for improved readability.

Line 28 is quite long (~170+ characters) and contains repeated property access patterns. While functionally correct, it could be more readable if split across multiple lines or refactored.

Optional refactor example:

-  // For non-authelia tokens, try LFX SSO claim first
-  return req.oidc?.user?.['https://sso.linuxfoundation.org/claims/username'] || req.oidc?.user?.['username'] || req.oidc?.user?.['preferred_username'] || null;
+  // For non-authelia tokens, try LFX SSO claim first
+  const user = req.oidc?.user;
+  return (
+    user?.['https://sso.linuxfoundation.org/claims/username'] ||
+    user?.['username'] ||
+    user?.['preferred_username'] ||
+    null
+  );
apps/lfx-one/src/server/services/meeting.service.ts (1)

698-702: Consider logging errors before returning null.

The catch block at Lines 698-701 silently returns null for any error, which could hide important issues like network failures, authorization problems, or malformed responses. While returning null may be appropriate for a "not found" case, other errors should be visible.

Consider enhancing the error handling to distinguish between expected "not found" cases and unexpected errors:

     } catch (error) {
       Logger.error(req, 'get_user_meeting_rsvp', Date.now(), error);
+      // Consider: Only return null for specific "not found" errors
+      // Re-throw or handle other error types appropriately
       return null;
     }

The same consideration applies to getMeetingRsvps (Lines 731-733) which returns an empty array on any error.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 42e9854 and 6b9f23f.

📒 Files selected for processing (15)
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.html (2 hunks)
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts (5 hunks)
  • apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.html (1 hunks)
  • apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts (4 hunks)
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.html (1 hunks)
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.ts (1 hunks)
  • apps/lfx-one/src/app/shared/services/meeting.service.ts (2 hunks)
  • apps/lfx-one/src/server/controllers/meeting.controller.ts (2 hunks)
  • apps/lfx-one/src/server/routes/meetings.route.ts (1 hunks)
  • apps/lfx-one/src/server/server.ts (2 hunks)
  • apps/lfx-one/src/server/services/meeting.service.ts (2 hunks)
  • apps/lfx-one/src/server/utils/auth-helper.ts (1 hunks)
  • packages/shared/src/interfaces/meeting.interface.ts (1 hunks)
  • packages/shared/src/utils/index.ts (1 hunks)
  • packages/shared/src/utils/rsvp-calculator.util.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/lfx-one/src/**/*.html

📄 CodeRabbit inference engine (CLAUDE.md)

apps/lfx-one/src/**/*.html: Always add data-testid attributes when creating new Angular components for reliable test targeting
Use data-testid naming convention [section]-[component]-[element]

Files:

  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.html
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.html
  • apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.html
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Include required license headers on all source files

Files:

  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.html
  • packages/shared/src/utils/index.ts
  • apps/lfx-one/src/server/utils/auth-helper.ts
  • apps/lfx-one/src/server/server.ts
  • apps/lfx-one/src/server/routes/meetings.route.ts
  • packages/shared/src/interfaces/meeting.interface.ts
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.html
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • packages/shared/src/utils/rsvp-calculator.util.ts
  • apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.html
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
  • apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts
**/index.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Do not use barrel exports; always use direct imports for standalone components

Files:

  • packages/shared/src/utils/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript interfaces instead of union types for better maintainability
When defining PrimeNG-related types, reference the official PrimeNG component interfaces

Files:

  • packages/shared/src/utils/index.ts
  • apps/lfx-one/src/server/utils/auth-helper.ts
  • apps/lfx-one/src/server/server.ts
  • apps/lfx-one/src/server/routes/meetings.route.ts
  • packages/shared/src/interfaces/meeting.interface.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • packages/shared/src/utils/rsvp-calculator.util.ts
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
  • apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • packages/shared/src/utils/index.ts
  • apps/lfx-one/src/server/utils/auth-helper.ts
  • apps/lfx-one/src/server/server.ts
  • apps/lfx-one/src/server/routes/meetings.route.ts
  • packages/shared/src/interfaces/meeting.interface.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
  • packages/shared/src/utils/rsvp-calculator.util.ts
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.ts
  • apps/lfx-one/src/app/shared/services/meeting.service.ts
  • apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts
packages/shared/src/interfaces/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Place all TypeScript interfaces in the shared package at packages/shared/src/interfaces

Files:

  • packages/shared/src/interfaces/meeting.interface.ts
🧬 Code graph analysis (7)
apps/lfx-one/src/server/controllers/meeting.controller.ts (2)
packages/shared/src/interfaces/meeting.interface.ts (1)
  • CreateMeetingRsvpRequest (732-743)
apps/lfx-one/src/server/errors/index.ts (1)
  • ServiceValidationError (7-7)
packages/shared/src/utils/rsvp-calculator.util.ts (1)
packages/shared/src/interfaces/meeting.interface.ts (2)
  • MeetingOccurrence (156-167)
  • MeetingRsvp (707-726)
apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.ts (2)
packages/shared/src/interfaces/meeting.interface.ts (1)
  • RsvpScope (701-701)
apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts (1)
  • Component (23-247)
apps/lfx-one/src/app/shared/services/meeting.service.ts (1)
packages/shared/src/interfaces/meeting.interface.ts (2)
  • CreateMeetingRsvpRequest (732-743)
  • MeetingRsvp (707-726)
apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts (1)
packages/shared/src/interfaces/meeting.interface.ts (6)
  • Meeting (75-150)
  • MeetingOccurrence (156-167)
  • MeetingRsvp (707-726)
  • RsvpResponse (695-695)
  • RsvpScope (701-701)
  • CreateMeetingRsvpRequest (732-743)
apps/lfx-one/src/server/services/meeting.service.ts (3)
packages/shared/src/interfaces/meeting.interface.ts (2)
  • CreateMeetingRsvpRequest (732-743)
  • MeetingRsvp (707-726)
apps/lfx-one/src/server/utils/auth-helper.ts (1)
  • getUsernameFromAuth (10-29)
packages/shared/src/interfaces/api.interface.ts (1)
  • QueryServiceResponse (58-61)
apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts (2)
packages/shared/src/interfaces/meeting.interface.ts (1)
  • MeetingRsvp (707-726)
packages/shared/src/utils/rsvp-calculator.util.ts (2)
  • RsvpCounts (6-11)
  • calculateRsvpCounts (22-67)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-push
🔇 Additional comments (21)
apps/lfx-one/src/server/server.ts (1)

164-164: Scope removal is safe and appropriate for this codebase architecture.

After verifying the codebase, the removal of update:current_user_metadata from the OIDC authorization scope is safe and does not break existing functionality.

The application uses a NATS-based microservices architecture where:

  • The OIDC access token is used only as a bearer token for authentication between frontend and backend
  • The backend auth-service handles all user metadata updates via NATS messaging
  • Backend uses machine-to-machine (M2M) credentials for any Auth0 Management API calls, not the user's OIDC token

No code in the repository calls Auth0 Management API directly using the OIDC access token, so this scope was never required. Removing it follows security best practice by requesting only necessary scopes.

packages/shared/src/interfaces/meeting.interface.ts (1)

690-743: LGTM! Well-structured RSVP types with clear documentation.

The RSVP type definitions are clean and well-documented. The use of union types for RsvpResponse and RsvpScope is appropriate for string literal enums. The optional fields in CreateMeetingRsvpRequest correctly align with the backend design where user context is derived from the bearer token.

packages/shared/src/utils/index.ts (1)

8-8: LGTM! Follows the existing barrel export pattern for utilities.

This addition is consistent with the other utility exports in this file. The coding guideline about barrel exports specifically applies to Angular standalone components, not shared utility modules.

apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.ts (1)

1-59: LGTM! Clean modal component implementation.

The component is well-structured with proper use of Angular signals and DynamicDialogRef. The scope options are clearly defined with descriptive labels and the modal flow is straightforward.

apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.html (1)

94-141: LGTM! Well-implemented RSVP UI with proper accessibility and state management.

The RSVP section is cleanly integrated with:

  • Clear visual feedback for the current user's RSVP state
  • Proper loading state handling
  • All required data-testid attributes for testing
  • Good UX with compact inline buttons
apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.html (1)

150-180: LGTM! Consistent migration to computed RSVP counts.

The changes correctly replace direct registrant count references with the computed rsvpCounts() values, ensuring the UI reflects the new RSVP-based calculation logic.

apps/lfx-one/src/server/routes/meetings.route.ts (1)

51-54: LGTM! RESTful RSVP routes properly integrated.

The three RSVP endpoints follow the existing routing patterns and RESTful conventions. The routes are clearly grouped with a comment header for maintainability.

apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.html (1)

1-30: LGTM! Well-structured modal template with good accessibility.

The template is clean and accessible with:

  • Proper button types and disabled states
  • Comprehensive data-testid attributes for testing
  • Clear visual feedback for option selection
  • Appropriate use of Angular control flow (@for)
apps/lfx-one/src/server/services/meeting.service.ts (1)

635-735: LGTM! RSVP service methods well-structured with proper logging.

The three RSVP methods follow the established patterns in this service with appropriate use of the microservice proxy and comprehensive logging. The createMeetingRsvp method correctly strips optional fields to let the backend derive user context from the bearer token.

apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts (2)

623-637: LGTM: Well-structured RSVP count calculation.

The method correctly:

  • Returns zero counts for past meetings
  • Delegates to the shared calculateRsvpCounts utility for upcoming meetings
  • Passes all required parameters (occurrence, RSVPs, meeting start time)

639-652: LGTM: Correctly integrated RSVP counts.

The attendance percentage calculation now uses rsvpCounts().accepted instead of the deprecated meeting.registrants_accepted_count, properly reflecting the new RSVP-based counting system.

apps/lfx-one/src/app/shared/services/meeting.service.ts (3)

443-451: LGTM: Consistent implementation.

The createMeetingRsvp method follows the established patterns in this service:

  • Uses take(1) for single emission
  • Proper error handling with catchError and throwError
  • Console logging for debugging

453-460: LGTM: Appropriate error handling for optional data.

The getUserMeetingRsvp method correctly returns null on error using of(null), which is appropriate for optional user RSVP data that may not exist.


462-469: LGTM: Appropriate error handling for list operations.

The getMeetingRsvps method correctly returns an empty array on error using of([]), which is appropriate for list operations and prevents downstream null-pointer issues.

packages/shared/src/utils/rsvp-calculator.util.ts (1)

22-67: LGTM: Well-structured RSVP counting logic.

The function correctly:

  • Groups RSVPs by username to handle multiple responses per user
  • Uses getApplicableRsvp to determine which RSVP applies to each occurrence
  • Counts responses by type (accepted/declined/maybe)
  • Handles empty RSVP lists gracefully
apps/lfx-one/src/server/controllers/meeting.controller.ts (3)

727-781: LGTM: Well-structured controller method.

The createMeetingRsvp method follows controller best practices:

  • Validates required parameters (UID, response, scope)
  • Uses consistent logging (start, success, error)
  • Proper error handling with next(error)
  • Follows established patterns in this controller

783-819: LGTM: Consistent with existing patterns.

The getUserMeetingRsvp method follows the established controller patterns with proper validation, logging, and error handling.


821-853: LGTM: Proper list endpoint implementation.

The getMeetingRsvps method correctly:

  • Validates the meeting UID
  • Logs the count of RSVPs returned
  • Follows error handling conventions
apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts (3)

194-212: LGTM: Proper modal flow for recurring meetings.

The method correctly:

  • Shows scope selection modal for recurring meetings
  • Uses 'this' scope directly for non-recurring meetings
  • Handles the modal response appropriately

Note: The onClose subscription is automatically cleaned up by PrimeNG's DialogService when the dialog closes.


214-246: LGTM: Well-implemented RSVP submission.

The method properly:

  • Manages loading state
  • Provides user feedback via MessageService
  • Handles errors gracefully with fallback
  • Updates local state on success

156-158: LGTM: Clean recurring meeting detection.

The computed signal correctly determines if a meeting is recurring by checking if recurrence is not null.

…roach

- Convert RSVP loading from effects to signal-based reactive streams
- Add occurrence_id field to MeetingRsvp interface for proper typing
- Improve RSVP matching logic with case-insensitive comparison
- Add RSVP refresh coordination across occurrence cards
- Display meeting context in RSVP scope modal
- Change RsvpScope from 'this' to 'single' for clarity
- Fix nested ternary expression for better readability
- Remove debug console.log statements
- Add username validation in getUserMeetingRsvp

🤖 Generated with [Claude Code](https://claude.ai/code)

Signed-off-by: Andres Tobon <andrest2455@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts (1)

187-212: Memory leak: Manual subscription still needs cleanup.

The subscription created in the constructor lacks cleanup, causing a memory leak when the component is destroyed. Although this is no longer in an effect (as flagged in the previous review), the subscription still persists without a cleanup mechanism.

Apply this fix:

+import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
+
 public constructor() {
   // Convert meeting input signal to observable and create reactive attachment stream
   const meeting$ = toObservable(this.meeting);
   const attachments$ = meeting$.pipe(
     switchMap((meeting) => {
       if (meeting.uid) {
         return this.meetingService.getMeetingAttachments(meeting.uid).pipe(catchError(() => of([])));
       }
       return of([]);
     })
   );

   this.attachments = toSignal(attachments$, { initialValue: [] });

   // Create signal-based RSVP loading that handles both initial load and refresh
   const rsvpFetchTrigger = computed(() => ({
     meetingUid: this.meeting()?.uid,
     refreshTrigger: this.refreshTrigger(),
     skipUid: this.skipRefreshMeetingUid(),
   }));

   const rsvpFetchTrigger$ = toObservable(rsvpFetchTrigger);

   // Fetch RSVP when meeting changes or when explicitly refreshed
   rsvpFetchTrigger$
     .pipe(
+      takeUntilDestroyed(),
       map(({ meetingUid, refreshTrigger, skipUid }) => {
         // Don't fetch if no meeting
         if (!meetingUid) return null;

         // Skip refresh if this is the card that was just updated (but allow initial load)
         if (refreshTrigger > 0 && skipUid && meetingUid === skipUid) {
           return null;
         }

         // Return meeting UID to trigger fetch (include refreshTrigger to force new fetch on refresh)
         return refreshTrigger === 0 ? meetingUid : `${meetingUid}-${refreshTrigger}`;
       }),
       switchMap((fetchKey) => {
         if (!fetchKey) return of(null);

         // Extract meeting UID (handle both "uid" and "uid-trigger" formats)
         const meetingUid = fetchKey.split('-')[0];

         return this.meetingService.getUserMeetingRsvp(meetingUid).pipe(catchError(() => of(null)));
       })
     )
     .subscribe((rsvp) => {
       this.userRsvp.set(rsvp);
     });
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6b9f23f and 4882af7.

📒 Files selected for processing (15)
  • apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.html (2 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.ts (3 hunks)
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts (6 hunks)
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-registrants/meeting-registrants.component.ts (2 hunks)
  • apps/lfx-one/src/app/modules/project/meetings/components/registrant-card/registrant-card.component.html (1 hunks)
  • apps/lfx-one/src/app/modules/project/meetings/components/registrant-card/registrant-card.component.ts (2 hunks)
  • apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts (4 hunks)
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.html (1 hunks)
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.ts (1 hunks)
  • apps/lfx-one/src/server/controllers/meeting.controller.ts (2 hunks)
  • apps/lfx-one/src/server/server.ts (1 hunks)
  • apps/lfx-one/src/server/services/meeting.service.ts (2 hunks)
  • packages/shared/src/interfaces/meeting.interface.ts (2 hunks)
  • packages/shared/src/utils/index.ts (1 hunks)
  • packages/shared/src/utils/rsvp-calculator.util.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/lfx-one/src/server/server.ts
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.html
  • packages/shared/src/utils/index.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript interfaces instead of union types for better maintainability
When defining PrimeNG-related types, reference the official PrimeNG component interfaces

Files:

  • apps/lfx-one/src/app/modules/project/meetings/components/registrant-card/registrant-card.component.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • packages/shared/src/utils/rsvp-calculator.util.ts
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.ts
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.ts
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-registrants/meeting-registrants.component.ts
  • apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • packages/shared/src/interfaces/meeting.interface.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Include required license headers on all source files

Files:

  • apps/lfx-one/src/app/modules/project/meetings/components/registrant-card/registrant-card.component.ts
  • apps/lfx-one/src/app/modules/project/meetings/components/registrant-card/registrant-card.component.html
  • apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.html
  • apps/lfx-one/src/server/services/meeting.service.ts
  • packages/shared/src/utils/rsvp-calculator.util.ts
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.ts
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.ts
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-registrants/meeting-registrants.component.ts
  • apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • packages/shared/src/interfaces/meeting.interface.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • apps/lfx-one/src/app/modules/project/meetings/components/registrant-card/registrant-card.component.ts
  • apps/lfx-one/src/server/services/meeting.service.ts
  • packages/shared/src/utils/rsvp-calculator.util.ts
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.ts
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.ts
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-registrants/meeting-registrants.component.ts
  • apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
  • packages/shared/src/interfaces/meeting.interface.ts
  • apps/lfx-one/src/server/controllers/meeting.controller.ts
apps/lfx-one/src/**/*.html

📄 CodeRabbit inference engine (CLAUDE.md)

apps/lfx-one/src/**/*.html: Always add data-testid attributes when creating new Angular components for reliable test targeting
Use data-testid naming convention [section]-[component]-[element]

Files:

  • apps/lfx-one/src/app/modules/project/meetings/components/registrant-card/registrant-card.component.html
  • apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.html
packages/shared/src/interfaces/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Place all TypeScript interfaces in the shared package at packages/shared/src/interfaces

Files:

  • packages/shared/src/interfaces/meeting.interface.ts
🧠 Learnings (3)
📚 Learning: 2025-10-21T21:19:13.599Z
Learnt from: andrest50
PR: linuxfoundation/lfx-v2-ui#125
File: apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts:345-350
Timestamp: 2025-10-21T21:19:13.599Z
Learning: In the Angular meeting card component (apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts), when selecting between `summary.summary_data.edited_content` and `summary.summary_data.content`, the logical OR operator (`||`) is intentionally used instead of nullish coalescing (`??`) because empty string edited_content should fall back to the original content rather than being displayed as empty.

Applied to files:

  • apps/lfx-one/src/app/modules/project/meetings/components/registrant-card/registrant-card.component.html
  • apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.html
  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.ts
  • apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.ts
  • apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts
📚 Learning: 2025-09-16T03:32:46.518Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-ui#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-16T03:32:46.518Z
Learning: Applies to **/*.{ts,tsx} : When defining PrimeNG-related types, reference the official PrimeNG component interfaces

Applied to files:

  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-registrants/meeting-registrants.component.ts
📚 Learning: 2025-09-16T03:32:46.518Z
Learnt from: CR
PR: linuxfoundation/lfx-v2-ui#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-16T03:32:46.518Z
Learning: All PrimeNG components are wrapped in LFX components to keep UI library independence

Applied to files:

  • apps/lfx-one/src/app/modules/project/meetings/components/meeting-registrants/meeting-registrants.component.ts
🧬 Code graph analysis (8)
apps/lfx-one/src/server/services/meeting.service.ts (3)
packages/shared/src/interfaces/meeting.interface.ts (2)
  • CreateMeetingRsvpRequest (736-747)
  • MeetingRsvp (709-730)
apps/lfx-one/src/server/utils/auth-helper.ts (1)
  • getUsernameFromAuth (10-22)
packages/shared/src/interfaces/api.interface.ts (1)
  • QueryServiceResponse (58-61)
packages/shared/src/utils/rsvp-calculator.util.ts (1)
packages/shared/src/interfaces/meeting.interface.ts (2)
  • MeetingOccurrence (156-167)
  • MeetingRsvp (709-730)
apps/lfx-one/src/app/modules/project/meetings/components/meeting-card/meeting-card.component.ts (2)
packages/shared/src/interfaces/meeting.interface.ts (1)
  • MeetingRsvp (709-730)
packages/shared/src/utils/rsvp-calculator.util.ts (2)
  • RsvpCounts (6-11)
  • calculateRsvpCounts (22-67)
apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.ts (1)
packages/shared/src/interfaces/meeting.interface.ts (2)
  • RsvpResponse (697-697)
  • RsvpScope (703-703)
apps/lfx-one/src/app/shared/components/rsvp-scope-modal/rsvp-scope-modal.component.ts (2)
packages/shared/src/interfaces/meeting.interface.ts (3)
  • RsvpScope (703-703)
  • Meeting (75-150)
  • MeetingOccurrence (156-167)
apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts (1)
  • Component (23-278)
apps/lfx-one/src/app/modules/project/meetings/components/meeting-registrants/meeting-registrants.component.ts (2)
packages/shared/src/interfaces/meeting.interface.ts (4)
  • MeetingRegistrant (262-303)
  • RegistrantState (362-362)
  • MeetingRegistrantWithState (368-377)
  • MeetingRsvp (709-730)
packages/shared/src/utils/form.utils.ts (1)
  • generateTempId (9-11)
apps/lfx-one/src/app/shared/components/dashboard-meeting-card/dashboard-meeting-card.component.ts (1)
packages/shared/src/interfaces/meeting.interface.ts (6)
  • Meeting (75-150)
  • MeetingOccurrence (156-167)
  • RsvpResponse (697-697)
  • RsvpScope (703-703)
  • MeetingRsvp (709-730)
  • CreateMeetingRsvpRequest (736-747)
apps/lfx-one/src/server/controllers/meeting.controller.ts (1)
packages/shared/src/interfaces/meeting.interface.ts (1)
  • CreateMeetingRsvpRequest (736-747)

- Change skip logic from meetingUid to composite key (meetingUid:occurrenceId)
- Fix RSVP refresh to only skip the specific occurrence that was clicked
- Update event payload to include occurrenceId
- Fix rsvpFetchTrigger to return structured data instead of string concatenation
- Prevent UUID corruption from hyphen-based string splitting

This ensures all occurrence cards properly update their RSVP status when
scope is "all" or "following", except the specific occurrence that was
just clicked.

🤖 Generated with [Claude Code](https://claude.ai/code)

Signed-off-by: Andres Tobon <andrest2455@gmail.com>
state: state,
originalData: state === 'existing' ? { ...registrant } : undefined,
tempId: state === 'new' ? generateTempId() : undefined,
rsvpStatus: rsvpStatus as any,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this casted as any?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed it to rsvpStatus: rsvpStatus as RsvpResponse | undefined unless that isn't what you meant.

Comment on lines 154 to 157
// Clear the skip UID after a short delay
setTimeout(() => {
this.skipRefreshMeetingUid.set(null);
}, 1000);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we have to wait for a set time to clear this?

<lfx-badge value="Invited" severity="secondary" size="small" styleClass="inline-flex items-center"> </lfx-badge>
<!-- RSVP status badge (invited/accepted/declined/maybe) -->
<lfx-badge [value]="rsvpBadge().label" [severity]="rsvpBadge().severity" size="small" styleClass="inline-flex items-center gap-1">
<i [class]="rsvpBadge().icon + ' text-xs'"></i>
Copy link
Contributor

Choose a reason for hiding this comment

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

Use ngClass instead of string concat

type="button"
(click)="handleRsvpClick('accepted')"
[disabled]="rsvpLoading()"
[class]="
Copy link
Contributor

Choose a reason for hiding this comment

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

Use ngclass - we want to avoid the use of js in the html as much as possible and using ternary operations isn't ideal

type="button"
(click)="handleRsvpClick('maybe')"
[disabled]="rsvpLoading()"
[class]="
Copy link
Contributor

Choose a reason for hiding this comment

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

use ngclass

Comment on lines 10 to 14
interface ScopeOption {
value: RsvpScope;
label: string;
description: string;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Interface should live in shared package

templateUrl: './rsvp-scope-modal.component.html',
})
export class RsvpScopeModalComponent {
private readonly ref = inject(DynamicDialogRef);
Copy link
Contributor

Choose a reason for hiding this comment

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

rename to dialogRef

Comment on lines 57 to 71
{
value: 'single',
label: 'This occurrence only',
description: 'Apply this RSVP to only this specific meeting',
},
{
value: 'all',
label: 'All occurrences',
description: 'Apply this RSVP to all occurrences in the series',
},
{
value: 'following',
label: 'This and following occurrences',
description: 'Apply this RSVP to this meeting and all future occurrences',
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Move to shared constants for meetings

}),
})
),
rsvps: this.meetingService.getMeetingRsvps(uid).pipe(
Copy link
Contributor

Choose a reason for hiding this comment

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

We can chat about it in our call, but wondering if this is best done on the getMeetingRegistrants as a flag to call and mapping server side as well instead of duplicating the call here and calculating/mapping client side.

Comment on lines 6 to 11
export interface RsvpCounts {
accepted: number;
declined: number;
maybe: number;
total: number;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Interface should live in the interfaces folder

…ed package

- Move RsvpScopeOption interface to shared package for reusability
- Move RsvpCounts interface to shared package interfaces
- Add RSVP_SCOPE_OPTIONS constant to shared package constants
- Update RSVP scope modal to use shared constants and interfaces
- Update dashboard meeting card to use ngClass for RSVP buttons
- Add pipe(take(1)) to dialog close subscription to prevent memory leaks
- Remove unnecessary DialogService provider from dashboard meeting card
- Simplify skip refresh key logic in my-meetings component
- Fix max-len linting error in meeting-registrants component
- Update registrant card to use ngClass for icon styling
- Improve type safety with proper RsvpResponse type annotation

Generated with [Claude Code](https://claude.ai/code)

Signed-off-by: Andres Tobon <andrest2455@gmail.com>
…nt fetching

- Add optional include_rsvp query parameter to GET /meetings/:uid/registrants endpoint
- Backend service fetches and attaches RSVP data when include_rsvp=true
- Add optional rsvp field to MeetingRegistrant interface
- Optimize meeting-registrants component to use single API call with include_rsvp=true
- Remove forkJoin pattern and complex RSVP matching logic from frontend
- Reduce code complexity by ~70 lines in meeting-registrants component
- Improve performance by reducing network requests from 2 to 1
- Update frontend service to accept includeRsvp parameter (defaults to false)
- Add comprehensive error handling and logging for RSVP fetching
- Maintain backward compatibility with existing API consumers

Generated with [Claude Code](https://claude.ai/code)

Signed-off-by: Andres Tobon <andrest2455@gmail.com>
Remove the ability to submit RSVPs directly from the dashboard meeting cards.
This functionality will be refactored and reimplemented in a future iteration.

Changes:
- Remove RSVP buttons (Yes/Maybe/No) from dashboard meeting cards
- Delete RSVP scope modal component
- Remove RSVP submission handlers and refresh logic
- Clean up unused inputs (refreshTrigger, skipRefreshKey)
- Remove isRecurringMeeting computed signal
- Add update:current_user_metadata scope for future user profile updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: Andres Tobon <andrest2455@gmail.com>
Remove the ability to submit RSVPs directly from the dashboard meeting cards.
This functionality will be refactored and reimplemented in a future iteration.

Changes:
- Remove RSVP buttons (Yes/Maybe/No) from dashboard meeting cards
- Delete RSVP scope modal component
- Remove RSVP submission handlers and refresh logic
- Clean up unused inputs (refreshTrigger, skipRefreshKey)
- Remove isRecurringMeeting computed signal
- Add update:current_user_metadata scope for future user profile updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: Andres Tobon <andrest2455@gmail.com>
Signed-off-by: Andres Tobon <andrest2455@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c80e61b and 7cb7053.

📒 Files selected for processing (1)
  • packages/shared/src/interfaces/meeting.interface.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
packages/shared/src/interfaces/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Place all TypeScript interfaces in the shared package at packages/shared/src/interfaces

Files:

  • packages/shared/src/interfaces/meeting.interface.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript interfaces instead of union types for better maintainability
When defining PrimeNG-related types, reference the official PrimeNG component interfaces

Files:

  • packages/shared/src/interfaces/meeting.interface.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Include required license headers on all source files

Files:

  • packages/shared/src/interfaces/meeting.interface.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • packages/shared/src/interfaces/meeting.interface.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-push

Comment on lines +749 to +764
/**
* Request payload for creating a meeting RSVP
* @description Data required to create or update a meeting RSVP
*/
export interface CreateMeetingRsvpRequest {
/** User's registrant ID (optional - backend derives from username if not provided) */
registrant_id?: string;
/** User's username (optional - backend derives from authenticated user if not provided) */
username?: string;
/** User's email (optional - backend derives from authenticated user if not provided) */
email?: string;
/** Scope of the RSVP */
scope: RsvpScope;
/** User's RSVP response */
response: RsvpResponse;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Add occurrence_id field for single-scope RSVPs.

When scope is 'single', the RSVP applies to a specific occurrence of a recurring meeting. However, this request interface lacks an occurrence_id field to specify which occurrence the user is RSVPing to. The response interface MeetingRsvp includes this field (line 742), but the request does not.

Apply this diff to add the missing field:

 export interface CreateMeetingRsvpRequest {
   /** User's registrant ID (optional - backend derives from username if not provided) */
   registrant_id?: string;
   /** User's username (optional - backend derives from authenticated user if not provided) */
   username?: string;
   /** User's email (optional - backend derives from authenticated user if not provided) */
   email?: string;
   /** Scope of the RSVP */
   scope: RsvpScope;
   /** User's RSVP response */
   response: RsvpResponse;
+  /** Occurrence ID (required when scope is 'single') */
+  occurrence_id?: string;
 }
🤖 Prompt for AI Agents
In packages/shared/src/interfaces/meeting.interface.ts around lines 749 to 764,
the CreateMeetingRsvpRequest interface is missing an occurrence_id needed when
scope === 'single'; add an optional occurrence_id?: string field (with a brief
JSDoc comment like "ID of the specific occurrence when scope is 'single'") to
the interface so clients can target a specific meeting occurrence while keeping
it optional for other scopes.

@asithade asithade merged commit bb81511 into main Nov 4, 2025
6 checks passed
@asithade asithade deleted the andrest50/meeting-rsvp branch November 4, 2025 19:33
@github-actions
Copy link

github-actions bot commented Nov 4, 2025

🧹 Deployment Removed

The deployment for PR #135 has been removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants