Skip to content

feat(calendar): implement Create Event modal and wire to API#39935

Open
VedantGupta-DTU wants to merge 1 commit intoRocketChat:developfrom
VedantGupta-DTU:feat/calendar-create-event-modal
Open

feat(calendar): implement Create Event modal and wire to API#39935
VedantGupta-DTU wants to merge 1 commit intoRocketChat:developfrom
VedantGupta-DTU:feat/calendar-create-event-modal

Conversation

@VedantGupta-DTU
Copy link
Copy Markdown

@VedantGupta-DTU VedantGupta-DTU commented Mar 28, 2026

Description

This PR implements a missing UI component to interface with the existing /v1/calendar-events.create API. Users can now natively create new calendar events directly from the Rocket.Chat client.

Key Changes:

  • New Component: Built CreateEventModal.tsx utilizing @rocket.chat/fuselage components for a native layout (Modal, TextInput, TextAreaInput, Select, ToggleSwitch).
  • Form State Validation: Managed input state with react-hook-form to ensure required fields like Subject and StartTime are provided before submission.
  • Provider-Agnostic Setup: Kept the modal inside the generic views/calendar directory instead of Outlook-specific files, paving the way for the GSoC multi-calendar architecture.
  • UI Action Integration: Wired the modal to open via a generic "Create Event" button added tightly into the OutlookEventsList sidebar.
  • Sync/Invalidation: Form submission securely dispatches to the .create API endpoint, fires a success/error toast via useToastMessageDispatch, and aggressively invalidates the ['calendar', 'list'] React Query cache so the UI magically refreshes to show the new event.

Related Issue

Solves the gap of missing event-creation UI for the calendar integration.

How to test

  1. Open the Outlook Calendar sidebar.
  2. Click the new Create Event button.
  3. Fill out the form (e.g., Subject, Start Time, Description, Meeting URL).
  4. Save the event and note the Success Toast message.
  5. Verify that the event successfully fetches and populates within your sidebar!

Summary by CodeRabbit

  • New Features
    • Added a modal dialog for creating new calendar events with form fields for event subject, start/end times, meeting URLs, descriptions, and reminder settings.
    • Added action button in Outlook calendar view to open the event creation modal.
    • Events creation includes validation feedback and success/error notifications.

@VedantGupta-DTU VedantGupta-DTU requested a review from a team as a code owner March 28, 2026 20:20
@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot bot commented Mar 28, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 28, 2026

⚠️ No Changeset found

Latest commit: 8b384aa

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 28, 2026

Walkthrough

A new CreateEventModal component was added to enable calendar event creation through a modal dialog with form validation. The OutlookEventsList component was updated to include a button that opens this modal when authentication is enabled.

Changes

Cohort / File(s) Summary
Calendar Event Creation Modal
apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx
New component implementing a modal-based event creation form with fields for subject, start/end times, meeting URL, description, reminder timing, and busy status. Handles form submission with POST request to calendar API, success/error notifications, and cache invalidation.
Outlook Calendar Integration
apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx
Added import and footer action button to open the new CreateEventModal imperatively when authentication is enabled, passing the modal close handler as a prop.

Sequence Diagram

sequenceDiagram
    actor User
    participant Modal as CreateEventModal
    participant Form as React Hook Form
    participant API as /v1/calendar-events.create
    participant Cache as Query Cache
    participant Toast as Toast Notifier

    User->>Modal: Clicks "Create Event" button
    Modal->>Form: Initialize form with validation
    User->>Form: Enters event details (subject, times, etc.)
    Form->>Form: Validates on change
    User->>Form: Clicks Save
    Form->>API: POST with converted ISO dates
    API-->>Form: Success response
    Form->>Cache: Invalidate calendar list query
    Cache-->>Modal: Cache cleared
    Form->>Toast: Display success notification
    Toast-->>User: Show confirmation
    Modal->>Modal: Call onClose callback
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

type: feature

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: implementing a CreateEventModal component and integrating it with the calendar API endpoint.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai bot added the type: feature Pull requests that introduces new feature label Mar 28, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx">

<violation number="1" location="apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx:124">
P2: `endTime` is accepted without validating it is after `startTime`, allowing invalid event ranges to be submitted and stored.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

<FieldRow>
<TextInput
type='datetime-local'
{...register('endTime')}
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 28, 2026

Choose a reason for hiding this comment

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

P2: endTime is accepted without validating it is after startTime, allowing invalid event ranges to be submitted and stored.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx, line 124:

<comment>`endTime` is accepted without validating it is after `startTime`, allowing invalid event ranges to be submitted and stored.</comment>

<file context>
@@ -0,0 +1,189 @@
+					<FieldRow>
+						<TextInput
+							type='datetime-local'
+							{...register('endTime')}
+						/>
+					</FieldRow>
</file context>
Fix with Cubic

Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (1)
apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx (1)

91-91: Consider extracting the click handler for readability.

The inline handler is functional but verbose. Extracting it improves readability and makes it easier to extend (e.g., adding analytics tracking).

Proposed refactor
+	const handleOpenCreateEventModal = () => {
+		imperativeModal.open({ component: CreateEventModal, props: { onClose: imperativeModal.close } });
+	};
+
 	return (
 		<ContextualbarDialog>
 			...
-					{authEnabled && <Button onClick={() => imperativeModal.open({ component: CreateEventModal, props: { onClose: imperativeModal.close } })}>{t('Create_Event')}</Button>}
+					{authEnabled && <Button onClick={handleOpenCreateEventModal}>{t('Create_Event')}</Button>}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx`
at line 91, The inline onClick handler in the OutlookEventsList JSX (currently
invoking imperativeModal.open with CreateEventModal) should be extracted into a
named function for readability and future extension: create a handler like
handleCreateEventClick (preferably memoized with useCallback inside the
OutlookEventsList component) that calls imperativeModal.open({ component:
CreateEventModal, props: { onClose: imperativeModal.close } }) and then replace
the inline lambda on the Button with onClick={handleCreateEventClick}; this
makes it easier to add analytics or additional logic later.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx`:
- Around line 26-38: The CreateEventFormValues type marks description optional
but the API (CalendarEventCreateProps) requires description; update the
CreateEventFormValues type so description is a required string (remove the ?),
and ensure any form initialization or validation logic that constructs
CreateEventFormValues (e.g., default values or formik/React Hook Form
initialValues) provides a non-empty description value and validation rule so
submissions include description.
- Around line 140-148: The Description textarea (registered as
register('description') inside CreateEventModal) is missing required validation
and a UI required indicator; update the FieldLabel to show required (e.g.,
append '*' or set a required prop) and add validation to the form registration
for 'description' (make it required with an appropriate message), then surface
validation errors near TextAreaInput (use the form's errors for 'description' to
show feedback and prevent submission when empty).
- Around line 59-77: The submit handler onSubmit must send a valid description
and a string message on error: ensure you always provide description when
calling createEvent (e.g., use data.description ?? '' or validate/require it
before calling) so it doesn't send undefined (createEvent / API schema requires
description), and change the error toast to pass a string (e.g., error.message
or String(error)) to dispatchToastMessage so the message displays correctly;
update the createEvent call and the catch block in onSubmit accordingly.

---

Nitpick comments:
In
`@apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx`:
- Line 91: The inline onClick handler in the OutlookEventsList JSX (currently
invoking imperativeModal.open with CreateEventModal) should be extracted into a
named function for readability and future extension: create a handler like
handleCreateEventClick (preferably memoized with useCallback inside the
OutlookEventsList component) that calls imperativeModal.open({ component:
CreateEventModal, props: { onClose: imperativeModal.close } }) and then replace
the inline lambda on the Button with onClick={handleCreateEventClick}; this
makes it easier to add analytics or additional logic later.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9f4f6278-d9f3-4197-b3e9-53b5ec15ad00

📥 Commits

Reviewing files that changed from the base of the PR and between 4235cd9 and 8b384aa.

📒 Files selected for processing (2)
  • apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx
  • apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx
📜 Review details
⏰ 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: cubic · AI code reviewer
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx
  • apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx
🧠 Learnings (1)
📚 Learning: 2026-03-27T14:52:56.865Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 39892
File: apps/meteor/client/views/room/contextualBar/Threads/Thread.tsx:150-155
Timestamp: 2026-03-27T14:52:56.865Z
Learning: In Rocket.Chat, there are two different `ModalBackdrop` components with different prop APIs. During review, confirm the import source: (1) `rocket.chat/fuselage` `ModalBackdrop` uses `ModalBackdropProps` based on `BoxProps` (so it supports `onClick` and other Box/DOM props) and does not have an `onDismiss` prop; (2) `rocket.chat/ui-client` `ModalBackdrop` uses a narrower props interface like `{ children?: ReactNode; onDismiss?: () => void }` and handles Escape keypress and outside mouse-up, and it does not forward arbitrary DOM props such as `onClick`. Flag mismatched props (e.g., `onDismiss` passed to the fuselage component or `onClick` passed to the ui-client component) and ensure the usage matches the correct component being imported.

Applied to files:

  • apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx
  • apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx
🔇 Additional comments (7)
apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx (6)

1-24: LGTM!

Imports are well-organized and include all necessary components from fuselage and hooks from ui-contexts.


79-86: LGTM!

Reminder options are well-structured with string values for the Select component, properly converted to integers on submit.


88-93: LGTM!

The modal structure with wrapperFunction for form submission is a valid pattern for fuselage modals.


95-127: LGTM!

Subject, Start Time, and End Time fields are properly implemented with appropriate validation for required fields.


150-175: LGTM!

Reminder and busy toggle fields use Controller correctly for controlled components.


177-186: LGTM!

Footer buttons properly handle submission state with loading and disabled props.

apps/meteor/client/views/outlookCalendar/OutlookEventsList/OutlookEventsList.tsx (1)

12-12: LGTM!

Imports are correctly added for imperativeModal from @rocket.chat/ui-client and the new CreateEventModal component.

Also applies to: 19-19

Comment on lines +26 to +38
type CreateEventModalProps = {
onClose: () => void;
};

type CreateEventFormValues = {
subject: string;
description?: string;
startTime: string;
endTime?: string;
meetingUrl?: string;
reminderMinutesBeforeStart?: string;
busy: boolean;
};
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 | 🟠 Major

Form type has description as optional, but the API requires it.

According to CalendarEventCreateProps, description is in the required array alongside startTime and subject. The form type marks it optional (description?: string), which will lead to API validation failures when users submit without a description.

Proposed fix
 type CreateEventFormValues = {
 	subject: string;
-	description?: string;
+	description: string;
 	startTime: string;
 	endTime?: string;
 	meetingUrl?: string;
 	reminderMinutesBeforeStart?: string;
 	busy: boolean;
 };
📝 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
type CreateEventModalProps = {
onClose: () => void;
};
type CreateEventFormValues = {
subject: string;
description?: string;
startTime: string;
endTime?: string;
meetingUrl?: string;
reminderMinutesBeforeStart?: string;
busy: boolean;
};
type CreateEventModalProps = {
onClose: () => void;
};
type CreateEventFormValues = {
subject: string;
description: string;
startTime: string;
endTime?: string;
meetingUrl?: string;
reminderMinutesBeforeStart?: string;
busy: boolean;
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx`
around lines 26 - 38, The CreateEventFormValues type marks description optional
but the API (CalendarEventCreateProps) requires description; update the
CreateEventFormValues type so description is a required string (remove the ?),
and ensure any form initialization or validation logic that constructs
CreateEventFormValues (e.g., default values or formik/React Hook Form
initialValues) provides a non-empty description value and validation rule so
submissions include description.

Comment on lines +59 to +77
const onSubmit = async (data: CreateEventFormValues) => {
try {
await createEvent({
subject: data.subject,
description: data.description || undefined,
startTime: new Date(data.startTime).toISOString(),
endTime: data.endTime ? new Date(data.endTime).toISOString() : undefined,
meetingUrl: data.meetingUrl || undefined,
reminderMinutesBeforeStart: data.reminderMinutesBeforeStart ? parseInt(data.reminderMinutesBeforeStart, 10) : undefined,
busy: data.busy,
});

dispatchToastMessage({ type: 'success', message: t('Event_Created_Successfully') });
queryClient.invalidateQueries({ queryKey: ['calendar', 'list'] });
onClose();
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
}
};
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 | 🟠 Major

Two issues in the submit handler.

  1. Line 63: Sending undefined for description will fail API validation since description is required per the schema (required: ['startTime', 'subject', 'description']).

  2. Line 75: Passing the raw error object to dispatchToastMessage may not display correctly. The message property typically expects a string.

Proposed fix
 	const onSubmit = async (data: CreateEventFormValues) => {
 		try {
 			await createEvent({
 				subject: data.subject,
-				description: data.description || undefined,
+				description: data.description,
 				startTime: new Date(data.startTime).toISOString(),
 				endTime: data.endTime ? new Date(data.endTime).toISOString() : undefined,
 				meetingUrl: data.meetingUrl || undefined,
 				reminderMinutesBeforeStart: data.reminderMinutesBeforeStart ? parseInt(data.reminderMinutesBeforeStart, 10) : undefined,
 				busy: data.busy,
 			});

 			dispatchToastMessage({ type: 'success', message: t('Event_Created_Successfully') });
 			queryClient.invalidateQueries({ queryKey: ['calendar', 'list'] });
 			onClose();
 		} catch (error) {
-			dispatchToastMessage({ type: 'error', message: error });
+			dispatchToastMessage({ type: 'error', message: error instanceof Error ? error.message : t('Something_went_wrong') });
 		}
 	};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx`
around lines 59 - 77, The submit handler onSubmit must send a valid description
and a string message on error: ensure you always provide description when
calling createEvent (e.g., use data.description ?? '' or validate/require it
before calling) so it doesn't send undefined (createEvent / API schema requires
description), and change the error toast to pass a string (e.g., error.message
or String(error)) to dispatchToastMessage so the message displays correctly;
update the createEvent call and the catch block in onSubmit accordingly.

Comment on lines +140 to +148
<Field mbe={24}>
<FieldLabel>{t('Description')}</FieldLabel>
<FieldRow>
<TextAreaInput
rows={3}
{...register('description')}
/>
</FieldRow>
</Field>
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 | 🟠 Major

Description field is missing required validation.

The API schema requires description as a mandatory field. The UI should mark this field as required and add validation to prevent form submission without it.

Proposed fix
 				<Field mbe={24}>
-					<FieldLabel>{t('Description')}</FieldLabel>
+					<FieldLabel required>{t('Description')}</FieldLabel>
 					<FieldRow>
 						<TextAreaInput
 							rows={3}
-							{...register('description')}
+							{...register('description', { required: t('Field_required') })}
+							error={errors.description?.message}
 						/>
 					</FieldRow>
+					{errors.description && <FieldError>{errors.description.message}</FieldError>}
 				</Field>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx`
around lines 140 - 148, The Description textarea (registered as
register('description') inside CreateEventModal) is missing required validation
and a UI required indicator; update the FieldLabel to show required (e.g.,
append '*' or set a required prop) and add validation to the form registration
for 'description' (make it required with an appropriate message), then surface
validation errors near TextAreaInput (use the form's errors for 'description' to
show feedback and prevent submission when empty).

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

Labels

community type: feature Pull requests that introduces new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant