Skip to content

Add guest management functionality to existing bookings#10

Open
everettbu wants to merge 1 commit into
guest-management-basefrom
guest-management-enhanced
Open

Add guest management functionality to existing bookings#10
everettbu wants to merge 1 commit into
guest-management-basefrom
guest-management-enhanced

Conversation

@everettbu

@everettbu everettbu commented Jul 28, 2025

Copy link
Copy Markdown

Test 10

Summary by CodeRabbit

  • New Features

    • Introduced the ability to add multiple guests to a booking via a new dialog interface.
    • Added support for entering and validating multiple email addresses when inviting guests.
    • Implemented notification emails for organizers, team members, and attendees when new guests are added.
  • Bug Fixes

    • Improved error handling and user feedback for invalid or duplicate email entries.
  • Documentation

    • Added new localization strings for guest management and email validation messages.

* feat: ability to add guests via app.cal.com/bookings

* fix: some update

* fix: minor issue

* fix: final update

* update

* update

* add requested changes

* fix type error

* small update

* final update

* fix type error

* fix location

* update calender event

---------

Co-authored-by: Somay Chauhan <somaychauhan98@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 28, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

This change introduces an "Add Guests" feature for bookings, enabling users to add multiple guest emails to an existing booking via a new dialog interface. The implementation covers UI components, email validation, backend API handler, schema validation, and notification email templates for both organizers and attendees. Localization strings and exports are updated accordingly.

Changes

Cohort / File(s) Change Summary
Booking UI Integration
apps/web/components/booking/BookingListItem.tsx,
apps/web/components/dialog/AddGuestsDialog.tsx
Integrates an "Add Guests" action in booking list items, including a dialog for entering guest emails, email validation, and triggering the backend mutation.
Localization
apps/web/public/static/locales/en/common.json
Adds new localization strings for guest management, email validation, and notification messages.
Email Sending Logic
packages/emails/email-manager.ts
Adds sendAddGuestsEmails function to manage notification emails for new guests, organizers, and team members.
Email Templates (React)
packages/emails/src/templates/AttendeeAddGuestsEmail.tsx,
packages/emails/src/templates/OrganizerAddGuestsEmail.tsx,
packages/emails/src/templates/index.ts
Introduces and exports new React components for attendee and organizer "add guests" email templates.
Email Templates (Payload Classes)
packages/emails/templates/attendee-add-guests-email.ts,
packages/emails/templates/organizer-add-guests-email.ts
Adds new classes for generating and sending "add guests" notification emails to attendees and organizers.
Booking API: Add Guests
packages/trpc/server/routers/viewer/bookings/_router.tsx,
packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts,
packages/trpc/server/routers/viewer/bookings/addGuests.schema.ts
Implements backend mutation, handler, and schema validation for adding guests to a booking, including permission checks, attendee updates, and notification logic.
Multi-Email Input UI
packages/ui/form/MultiEmail.tsx,
packages/ui/form/MultiEmailLazy.tsx,
packages/ui/index.tsx
Adds a reusable multi-email input component with lazy loading, and updates exports for UI package.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant BookingListItem
    participant AddGuestsDialog
    participant TRPC_API
    participant addGuestsHandler
    participant EmailManager

    User->>BookingListItem: Click "Add Guests"
    BookingListItem->>AddGuestsDialog: Open dialog
    User->>AddGuestsDialog: Enter emails, click "Add"
    AddGuestsDialog->>TRPC_API: Call addGuests mutation
    TRPC_API->>addGuestsHandler: Validate and process request
    addGuestsHandler->>addGuestsHandler: Check permissions, filter emails, update booking
    addGuestsHandler->>EmailManager: Send notification emails
    EmailManager-->>addGuestsHandler: Emails sent (async)
    addGuestsHandler->>TRPC_API: Return success
    TRPC_API->>AddGuestsDialog: Mutation result
    AddGuestsDialog->>User: Show success or error
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Poem

🐇
A guest list grows, with emails anew,
Dialogs open, and invites accrue.
Attendees and hosts get notified fast,
With templates and schemas, the system’s recast.
Hopping through code, this rabbit delights—
Welcoming guests to booking nights!
✉️✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch guest-management-enhanced

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai

coderabbitai Bot commented Jul 28, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@everettbu

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions

Copy link
Copy Markdown
Contributor

Hey there and thank you for opening this pull request! 👋🏼

We require pull request titles to follow the Conventional Commits specification and it looks like your proposed title needs to be adjusted.

Details:

No release type found in pull request title "Add guest management functionality to existing bookings". Add a prefix to indicate what kind of release this pull request corresponds to. For reference, see https://www.conventionalcommits.org/

Available types:
 - feat: A new feature
 - fix: A bug fix
 - docs: Documentation only changes
 - style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
 - refactor: A code change that neither fixes a bug nor adds a feature
 - perf: A code change that improves performance
 - test: Adding missing tests or correcting existing tests
 - build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
 - ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
 - chore: Other changes that don't modify src or test files
 - revert: Reverts a previous commit

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 6

🧹 Nitpick comments (10)
packages/ui/index.tsx (1)

150-154: Confirm path & keep constants immutable

  1. Verify that ./form/MultiEmailLazy actually default-exports the component (case-sensitive path & barrel exports sometimes get out of sync).
  2. If the intention is to make all three lazy-loaded inputs (Address/Phone/MultiEmail) appear as a fixed trio, consider freezing their props rather than leaving the TODO comment indefinitely.
packages/emails/src/templates/index.ts (1)

38-39: Minor: keep exports alphabetised to avoid merge churn

AttendeeAddGuestsEmail should be placed before OrganizerAddGuestsEmail if alphabetical ordering is desired (the rest of the file appears sorted).

apps/web/public/static/locales/en/common.json (4)

1122-1124: Consider tightening message phrasing & capitalisation for consistency

Neighbouring status-type strings use the pattern “Updated – …”.
For similar clarity and parallel wording you might prefer:

-"new_guests_added": "Added - New guests added to your event",
-"guests_added_event_type_subject": "Guests Added: {{eventType}} with {{name}} at {{date}}",
+"new_guests_added": "Updated – New guests have been added to your event",
+"guests_added_event_type_subject": "Updated – Guests added: {{eventType}} with {{name}} at {{date}}",

Purely a copy-deck nitpick – feel free to ignore if this deviates from your style guide.


1136-1137: Minor wording alignment

The UI already has “Add guests” (line 580). To mirror that action/label style, you could drop the past-tense verb here:

-"guests_added": "Guests added",
+"guests_added": "Added guests",

Not critical, just keeps verbs first like other status keys (“Updated”, “Canceled”, etc.).


1139-1139: Tiny punctuation touch-up

Add a trailing period so it reads like other validation sentences:

-"emails_must_be_unique_valid": "Emails must be unique and valid"
+"emails_must_be_unique_valid": "Emails must be unique and valid."

2434-2434: Label capitalisation

Most action labels in this file use sentence-case (“Add guests”, “Add location”). For consistency:

-"add_emails": "Add Emails",
+"add_emails": "Add emails",
packages/trpc/server/routers/viewer/bookings/addGuests.schema.ts (1)

3-6: Consider adding business rule validations.

The schema correctly validates email format but lacks business constraints that might be important:

Consider enhancing the schema with additional validations:

export const ZAddGuestsInputSchema = z.object({
-  bookingId: z.number(),
-  guests: z.array(z.string().email()),
+  bookingId: z.number().int().positive(),
+  guests: z.array(z.string().email()).min(1).max(50), // Prevent empty arrays and limit abuse
});

This would prevent negative/invalid booking IDs and ensure reasonable limits on guest additions.

apps/web/components/dialog/AddGuestsDialog.tsx (2)

26-29: Consider enhancing email uniqueness validation.

The current validation only checks for uniqueness but doesn't filter out empty strings, which could cause issues with the initial state.

Consider refining the validation schema:

const ZAddGuestsInputSchema = z.array(z.string().email()).refine((emails) => {
+  const validEmails = emails.filter(email => email.trim() !== '');
-  const uniqueEmails = new Set(emails);
+  const uniqueEmails = new Set(validEmails);
-  return uniqueEmails.size === emails.length;
+  return uniqueEmails.size === validEmails.length && validEmails.length > 0;
});

This would handle empty strings more gracefully and ensure at least one valid email is provided.


32-32: Consider initializing with empty array instead of array with empty string.

The initial state [""] might cause validation issues and user confusion.

-const [multiEmailValue, setMultiEmailValue] = useState<string[]>([""]);
+const [multiEmailValue, setMultiEmailValue] = useState<string[]>([]);

This would be more consistent with the expectation of an empty state and avoid potential validation edge cases.

packages/ui/form/MultiEmail.tsx (1)

73-75: Remove unnecessary empty fragment.

The empty fragment serves no purpose and can be removed.

         </div>
-      ) : (
-        <></>
-      )}
+      ) : null}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b004587 and baa9045.

📒 Files selected for processing (15)
  • apps/web/components/booking/BookingListItem.tsx (4 hunks)
  • apps/web/components/dialog/AddGuestsDialog.tsx (1 hunks)
  • apps/web/public/static/locales/en/common.json (3 hunks)
  • packages/emails/email-manager.ts (3 hunks)
  • packages/emails/src/templates/AttendeeAddGuestsEmail.tsx (1 hunks)
  • packages/emails/src/templates/OrganizerAddGuestsEmail.tsx (1 hunks)
  • packages/emails/src/templates/index.ts (1 hunks)
  • packages/emails/templates/attendee-add-guests-email.ts (1 hunks)
  • packages/emails/templates/organizer-add-guests-email.ts (1 hunks)
  • packages/trpc/server/routers/viewer/bookings/_router.tsx (3 hunks)
  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts (1 hunks)
  • packages/trpc/server/routers/viewer/bookings/addGuests.schema.ts (1 hunks)
  • packages/ui/form/MultiEmail.tsx (1 hunks)
  • packages/ui/form/MultiEmailLazy.tsx (1 hunks)
  • packages/ui/index.tsx (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (7)
packages/trpc/server/routers/viewer/bookings/_router.tsx (1)
packages/trpc/server/routers/viewer/bookings/addGuests.schema.ts (1)
  • ZAddGuestsInputSchema (3-6)
packages/emails/email-manager.ts (6)
packages/types/Calendar.d.ts (1)
  • CalendarEvent (157-211)
packages/lib/formatCalendarEvent.ts (1)
  • formatCalEvent (19-27)
packages/emails/src/templates/OrganizerAddGuestsEmail.tsx (1)
  • OrganizerAddGuestsEmail (3-11)
packages/emails/templates/organizer-add-guests-email.ts (1)
  • OrganizerAddGuestsEmail (7-38)
packages/emails/src/templates/AttendeeAddGuestsEmail.tsx (1)
  • AttendeeAddGuestsEmail (3-10)
packages/emails/templates/attendee-add-guests-email.ts (1)
  • AttendeeAddGuestsEmail (5-34)
apps/web/components/dialog/AddGuestsDialog.tsx (3)
packages/lib/hooks/useLocale.ts (1)
  • useLocale (5-22)
packages/trpc/server/routers/viewer/bookings/addGuests.schema.ts (1)
  • ZAddGuestsInputSchema (3-6)
packages/ui/index.tsx (6)
  • showToast (146-146)
  • Dialog (133-133)
  • DialogContent (135-135)
  • DialogHeader (137-137)
  • DialogFooter (136-136)
  • Button (14-14)
packages/emails/src/templates/AttendeeAddGuestsEmail.tsx (2)
packages/emails/src/templates/index.ts (2)
  • AttendeeAddGuestsEmail (39-39)
  • AttendeeScheduledEmail (9-9)
packages/emails/templates/attendee-add-guests-email.ts (1)
  • AttendeeAddGuestsEmail (5-34)
packages/emails/templates/attendee-add-guests-email.ts (2)
packages/emails/src/templates/AttendeeAddGuestsEmail.tsx (1)
  • AttendeeAddGuestsEmail (3-10)
packages/emails/src/templates/index.ts (2)
  • AttendeeAddGuestsEmail (39-39)
  • AttendeeScheduledEmail (9-9)
packages/emails/templates/organizer-add-guests-email.ts (3)
packages/emails/src/templates/OrganizerAddGuestsEmail.tsx (1)
  • OrganizerAddGuestsEmail (3-11)
packages/emails/src/templates/index.ts (2)
  • OrganizerAddGuestsEmail (38-38)
  • OrganizerScheduledEmail (21-21)
packages/lib/constants.ts (1)
  • APP_NAME (26-26)
apps/web/components/booking/BookingListItem.tsx (1)
apps/web/components/dialog/AddGuestsDialog.tsx (1)
  • AddGuestsDialog (24-107)
🔇 Additional comments (16)
packages/ui/form/MultiEmailLazy.tsx (1)

1-6: Tighten the dynamic typing and add a loading fallback

The double as unknown as cast hides type mismatches and loses IntelliSense.
You can keep full typing and supply a tiny fallback component with:

-import dynamic from "next/dynamic";
-
-/** These are like 40kb that not every user needs */
-const MultiEmail = dynamic(() => import("./MultiEmail")) as unknown as typeof import("./MultiEmail").default;
+import dynamic from "next/dynamic";
+
+// ~40 kb UI widget – lazy-loaded to drop initial bundle
+const MultiEmail = dynamic<typeof import("./MultiEmail").default>(
+  () => import(/* webpackChunkName: "multi-email" */ "./MultiEmail"),
+  { ssr: false, loading: () => null } // or a small spinner
+);

[ suggest_essential_refactor ]

packages/emails/src/templates/AttendeeAddGuestsEmail.tsx (1)

3-9: Same prop-override caveat as organizer template

Re-order the spread so callers cannot accidentally change locked fields:

-  <AttendeeScheduledEmail
-    title="new_guests_added"
-    headerType="calendarCircle"
-    subject="guests_added_event_type_subject"
-    {...props}
-  />
+  <AttendeeScheduledEmail
+    {...props}
+    title="new_guests_added"
+    headerType="calendarCircle"
+    subject="guests_added_event_type_subject"
+  />

[ suggest_essential_refactor ]

packages/trpc/server/routers/viewer/bookings/_router.tsx (3)

4-4: LGTM! Proper import addition.

The import follows the established pattern used by other schema imports in the file.


18-18: LGTM! Consistent cache type definition.

The handler cache type definition follows the same pattern as other handlers in the file.


79-95: LGTM! Procedure implementation follows established patterns.

The addGuests procedure implementation is consistent with other procedures in this router:

  • Uses authedProcedure for proper authentication
  • Implements the same lazy loading pattern with UNSTABLE_HANDLER_CACHE
  • Includes the standard error handling for failed handler loading
  • Follows the exact same structure as editLocation and other procedures
packages/emails/email-manager.ts (3)

21-21: LGTM! Proper import addition.

The import follows the established pattern for email template imports.


52-52: LGTM! Consistent import pattern.

The import follows the same pattern as other organizer email template imports.


525-550: LGTM! Well-implemented email notification logic.

The sendAddGuestsEmails function follows the established patterns in this file:

  • Properly formats the calendar event using formatCalEvent
  • Sends notifications to organizer and team members using the new OrganizerAddGuestsEmail template
  • Correctly differentiates between new guests (who get AttendeeScheduledEmail) and existing attendees (who get AttendeeAddGuestsEmail)
  • Uses Promise.all for efficient concurrent email sending, consistent with other functions in the file

The logic for distinguishing new guests vs. existing attendees is sound and the implementation is robust.

apps/web/components/dialog/AddGuestsDialog.tsx (2)

88-96: LGTM! Proper state cleanup on cancel.

The cancel button correctly resets all form state and closes the dialog.


76-85: LGTM! Good error message display.

The error message display with icon and proper styling provides clear feedback to users when email validation fails.

apps/web/components/booking/BookingListItem.tsx (4)

46-46: LGTM! Proper import addition.

The import follows the established pattern for dialog component imports.


193-200: LGTM! Well-integrated action definition.

The "Add Guests" action follows the exact same pattern as other actions in editBookingActions:

  • Consistent ID naming convention
  • Proper translation key usage
  • Appropriate icon choice (user-plus)
  • Follows the same onClick pattern as other dialog triggers

268-268: LGTM! Consistent state management.

The state variable follows the same naming pattern as other dialog states in the component.


357-361: LGTM! Proper dialog integration.

The AddGuestsDialog rendering follows the established pattern used by other dialogs in this component:

  • Consistent prop naming and structure
  • Proper state binding
  • Correct bookingId passing
packages/emails/templates/attendee-add-guests-email.ts (1)

5-34: LGTM! Well-structured email template implementation.

The email template correctly extends AttendeeScheduledEmail and properly implements the notification payload with appropriate iCalendar attachment, localized content, and consistent formatting.

packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts (1)

74-78: Make email comparison consistently case-insensitive.

The email comparison is case-sensitive for existing attendees but case-insensitive for blacklisted emails. This inconsistency could allow duplicate emails with different casing.

   const uniqueGuests = guests.filter(
     (guest) =>
-      !booking.attendees.some((attendee) => guest === attendee.email) &&
-      !blacklistedGuestEmails.includes(guest)
+      !booking.attendees.some((attendee) => guest.toLowerCase() === attendee.email.toLowerCase()) &&
+      !blacklistedGuestEmails.includes(guest.toLowerCase())
   );

Likely an incorrect or invalid review comment.

Comment on lines +48 to +58
const handleAdd = () => {
if (multiEmailValue.length === 0) {
return;
}
const validationResult = ZAddGuestsInputSchema.safeParse(multiEmailValue);
if (validationResult.success) {
addGuestsMutation.mutate({ bookingId, guests: multiEmailValue });
} else {
setIsInvalidEmail(true);
}
};

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.

🛠️ Refactor suggestion

Improve empty state validation logic.

The current check multiEmailValue.length === 0 may not work correctly with the initial state of [""].

const handleAdd = () => {
-  if (multiEmailValue.length === 0) {
+  const validEmails = multiEmailValue.filter(email => email.trim() !== '');
+  if (validEmails.length === 0) {
    return;
  }
-  const validationResult = ZAddGuestsInputSchema.safeParse(multiEmailValue);
+  const validationResult = ZAddGuestsInputSchema.safeParse(validEmails);
  if (validationResult.success) {
-    addGuestsMutation.mutate({ bookingId, guests: multiEmailValue });
+    addGuestsMutation.mutate({ bookingId, guests: validEmails });
  } else {
    setIsInvalidEmail(true);
  }
};

This ensures only non-empty email strings are processed and sent to the server.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleAdd = () => {
if (multiEmailValue.length === 0) {
return;
}
const validationResult = ZAddGuestsInputSchema.safeParse(multiEmailValue);
if (validationResult.success) {
addGuestsMutation.mutate({ bookingId, guests: multiEmailValue });
} else {
setIsInvalidEmail(true);
}
};
const handleAdd = () => {
const validEmails = multiEmailValue.filter(email => email.trim() !== '');
if (validEmails.length === 0) {
return;
}
const validationResult = ZAddGuestsInputSchema.safeParse(validEmails);
if (validationResult.success) {
addGuestsMutation.mutate({ bookingId, guests: validEmails });
} else {
setIsInvalidEmail(true);
}
};
🤖 Prompt for AI Agents
In apps/web/components/dialog/AddGuestsDialog.tsx around lines 48 to 58, the
current empty state check using multiEmailValue.length === 0 does not handle
cases where the array contains empty strings like [""] properly. Update the
validation to filter out empty strings from multiEmailValue before checking if
there are any valid emails to process. Only proceed with mutation if there is at
least one non-empty email string, ensuring that empty or blank emails are not
sent to the server.

Comment on lines +3 to +10
export const OrganizerAddGuestsEmail = (props: React.ComponentProps<typeof OrganizerScheduledEmail>) => (
<OrganizerScheduledEmail
title="new_guests_added"
headerType="calendarCircle"
subject="guests_added_event_type_subject"
callToAction={null}
{...props}
/>

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.

🛠️ Refactor suggestion

Order of spread makes props override your “constants”

{...props} is applied after the hard-coded props, so a caller can change title, subject, etc., defeating the locked-in template.
If these values must remain fixed, move the spread before the explicit props:

-  <OrganizerScheduledEmail
-    title="new_guests_added"
-    headerType="calendarCircle"
-    subject="guests_added_event_type_subject"
-    callToAction={null}
-    {...props}
-  />
+  <OrganizerScheduledEmail
+    {...props}
+    title="new_guests_added"
+    headerType="calendarCircle"
+    subject="guests_added_event_type_subject"
+    callToAction={null}
+  />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const OrganizerAddGuestsEmail = (props: React.ComponentProps<typeof OrganizerScheduledEmail>) => (
<OrganizerScheduledEmail
title="new_guests_added"
headerType="calendarCircle"
subject="guests_added_event_type_subject"
callToAction={null}
{...props}
/>
export const OrganizerAddGuestsEmail = (
props: React.ComponentProps<typeof OrganizerScheduledEmail>,
) => (
<OrganizerScheduledEmail
{...props}
title="new_guests_added"
headerType="calendarCircle"
subject="guests_added_event_type_subject"
callToAction={null}
/>
);
🤖 Prompt for AI Agents
In packages/emails/src/templates/OrganizerAddGuestsEmail.tsx around lines 3 to
10, the spread operator {...props} is placed after the fixed props, allowing
callers to override constants like title and subject. To fix this, move
{...props} before the explicit props so that the hard-coded values cannot be
overridden by incoming props, ensuring the template's fixed values remain locked
in.

Comment on lines +26 to +30
subject: `${this.t("guests_added_event_type_subject", {
eventType: this.calEvent.type,
name: this.calEvent.attendees[0].name,
date: this.getFormattedDate(),
})}`,

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.

⚠️ Potential issue

Add safety check for empty attendees array.

Accessing this.calEvent.attendees[0].name without checking if the array is empty could cause a runtime error.

       subject: `${this.t("guests_added_event_type_subject", {
         eventType: this.calEvent.type,
-        name: this.calEvent.attendees[0].name,
+        name: this.calEvent.attendees[0]?.name || "Guest",
         date: this.getFormattedDate(),
       })}`,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
subject: `${this.t("guests_added_event_type_subject", {
eventType: this.calEvent.type,
name: this.calEvent.attendees[0].name,
date: this.getFormattedDate(),
})}`,
subject: `${this.t("guests_added_event_type_subject", {
eventType: this.calEvent.type,
name: this.calEvent.attendees[0]?.name || "Guest",
date: this.getFormattedDate(),
})}`,
🤖 Prompt for AI Agents
In packages/emails/templates/organizer-add-guests-email.ts around lines 26 to
30, the code accesses this.calEvent.attendees[0].name without verifying if the
attendees array is non-empty, which can cause a runtime error. Add a safety
check to ensure this.calEvent.attendees has at least one element before
accessing the first attendee's name, and provide a fallback value if the array
is empty to prevent errors.

Comment on lines +46 to +48
const isTeamAdminOrOwner =
(await isTeamAdmin(user.id, booking.eventType?.teamId ?? 0)) &&
(await isTeamOwner(user.id, booking.eventType?.teamId ?? 0));

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.

⚠️ Potential issue

Fix incorrect boolean logic for team admin/owner check.

The current logic requires a user to be both admin AND owner, which is incorrect. It should check if the user is either admin OR owner.

   const isTeamAdminOrOwner =
-    (await isTeamAdmin(user.id, booking.eventType?.teamId ?? 0)) &&
-    (await isTeamOwner(user.id, booking.eventType?.teamId ?? 0));
+    (await isTeamAdmin(user.id, booking.eventType?.teamId ?? 0)) ||
+    (await isTeamOwner(user.id, booking.eventType?.teamId ?? 0));
🤖 Prompt for AI Agents
In packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts around
lines 46 to 48, the boolean logic incorrectly requires the user to be both a
team admin and owner by using the AND operator. Change the operator to OR so
that the check passes if the user is either a team admin or a team owner.

Comment on lines +167 to +171
try {
await sendAddGuestsEmails(evt, guests);
} catch (err) {
console.log("Error sending AddGuestsEmails");
}

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.

🛠️ Refactor suggestion

Improve error handling for email sending.

The current error handling only logs a generic message without error details. Consider logging the actual error and potentially notifying the user if email sending fails.

   try {
     await sendAddGuestsEmails(evt, guests);
   } catch (err) {
-    console.log("Error sending AddGuestsEmails");
+    console.error("Error sending AddGuestsEmails:", err);
+    // Consider whether to throw the error or return a warning to the user
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
await sendAddGuestsEmails(evt, guests);
} catch (err) {
console.log("Error sending AddGuestsEmails");
}
try {
await sendAddGuestsEmails(evt, guests);
} catch (err) {
console.error("Error sending AddGuestsEmails:", err);
// Consider whether to throw the error or return a warning to the user
}
🤖 Prompt for AI Agents
In packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts around
lines 167 to 171, the catch block for sendAddGuestsEmails only logs a generic
message without the error details. Update the catch block to log the actual
error object to provide more context. Additionally, consider adding user
notification logic to inform them if the email sending fails.


function MultiEmail({ value, readOnly, label, setValue, placeholder }: MultiEmailProps) {
const { t } = useLocale();
value = value || [];

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.

⚠️ Potential issue

Avoid reassigning function parameters.

Reassigning the value parameter can lead to confusion and is considered an anti-pattern. Use a default parameter or create a new variable instead.

-function MultiEmail({ value, readOnly, label, setValue, placeholder }: MultiEmailProps) {
+function MultiEmail({ value = [], readOnly, label, setValue, placeholder }: MultiEmailProps) {
   const { t } = useLocale();
-  value = value || [];
🤖 Prompt for AI Agents
In packages/ui/form/MultiEmail.tsx at line 14, avoid reassigning the function
parameter `value`. Instead, set a default value for the parameter in the
function signature or assign `value` to a new variable initialized to an empty
array if it is falsy. This prevents confusion and adheres to best practices.

@github-actions

Copy link
Copy Markdown
Contributor

This PR is being marked as stale due to inactivity.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants