feat(calendar): implement Create Event modal and wire to API#39935
feat(calendar): implement Create Event modal and wire to API#39935VedantGupta-DTU wants to merge 1 commit intoRocketChat:developfrom
Conversation
|
Looks like this PR is not ready to merge, because of the following issues:
Please fix the issues and try again If you have any trouble, please check the PR guidelines |
|
WalkthroughA new Changes
Sequence DiagramsequenceDiagram
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ 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. Comment |
There was a problem hiding this comment.
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')} |
There was a problem hiding this comment.
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>
There was a problem hiding this comment.
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
📒 Files selected for processing (2)
apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsxapps/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.tsxapps/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.tsxapps/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
wrapperFunctionfor 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
imperativeModalfrom@rocket.chat/ui-clientand the newCreateEventModalcomponent.Also applies to: 19-19
| type CreateEventModalProps = { | ||
| onClose: () => void; | ||
| }; | ||
|
|
||
| type CreateEventFormValues = { | ||
| subject: string; | ||
| description?: string; | ||
| startTime: string; | ||
| endTime?: string; | ||
| meetingUrl?: string; | ||
| reminderMinutesBeforeStart?: string; | ||
| busy: boolean; | ||
| }; |
There was a problem hiding this comment.
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.
| 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.
| 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 }); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Two issues in the submit handler.
-
Line 63: Sending
undefinedfordescriptionwill fail API validation sincedescriptionis required per the schema (required: ['startTime', 'subject', 'description']). -
Line 75: Passing the raw
errorobject todispatchToastMessagemay not display correctly. Themessageproperty 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.
| <Field mbe={24}> | ||
| <FieldLabel>{t('Description')}</FieldLabel> | ||
| <FieldRow> | ||
| <TextAreaInput | ||
| rows={3} | ||
| {...register('description')} | ||
| /> | ||
| </FieldRow> | ||
| </Field> |
There was a problem hiding this comment.
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).
Description
This PR implements a missing UI component to interface with the existing
/v1/calendar-events.createAPI. Users can now natively create new calendar events directly from the Rocket.Chat client.Key Changes:
CreateEventModal.tsxutilizing@rocket.chat/fuselagecomponents for a native layout (Modal,TextInput,TextAreaInput,Select,ToggleSwitch).react-hook-formto ensure required fields likeSubjectandStartTimeare provided before submission.views/calendardirectory instead of Outlook-specific files, paving the way for the GSoC multi-calendar architecture.OutlookEventsListsidebar..createAPI endpoint, fires a success/error toast viauseToastMessageDispatch, 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
Summary by CodeRabbit