From 8b384aa41e8a3941644b0cfb9be5cc10e3530589 Mon Sep 17 00:00:00 2001 From: VedantGupta-DTU Date: Sat, 28 Mar 2026 20:17:44 +0000 Subject: [PATCH] feat(calendar): implement Create Event modal and wire to API --- .../CreateEventModal/CreateEventModal.tsx | 189 ++++++++++++++++++ .../OutlookEventsList/OutlookEventsList.tsx | 3 + 2 files changed, 192 insertions(+) create mode 100644 apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx diff --git a/apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx b/apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx new file mode 100644 index 0000000000000..30ec6e8381529 --- /dev/null +++ b/apps/meteor/client/views/calendar/CreateEventModal/CreateEventModal.tsx @@ -0,0 +1,189 @@ +import { + Box, + Button, + ButtonGroup, + Field, + FieldLabel, + FieldRow, + FieldError, + TextInput, + TextAreaInput, + Select, + ToggleSwitch, + Modal, + ModalHeader, + ModalTitle, + ModalClose, + ModalContent, + ModalFooter +} from '@rocket.chat/fuselage'; +import { useTranslation, useEndpoint, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { useQueryClient } from '@tanstack/react-query'; +import type { ReactElement } from 'react'; +import React from 'react'; +import { useForm, Controller } from 'react-hook-form'; + +type CreateEventModalProps = { + onClose: () => void; +}; + +type CreateEventFormValues = { + subject: string; + description?: string; + startTime: string; + endTime?: string; + meetingUrl?: string; + reminderMinutesBeforeStart?: string; + busy: boolean; +}; + +const CreateEventModal = ({ onClose }: CreateEventModalProps): ReactElement => { + const t = useTranslation(); + const dispatchToastMessage = useToastMessageDispatch(); + const queryClient = useQueryClient(); + const createEvent = useEndpoint('POST', '/v1/calendar-events.create'); + + const { + register, + handleSubmit, + control, + formState: { errors, isValid, isSubmitting }, + } = useForm({ + mode: 'onChange', + defaultValues: { + busy: true, + reminderMinutesBeforeStart: '15', + }, + }); + + 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 }); + } + }; + + const reminderOptions: [string, string][] = [ + ['0', t('At_time_of_event')], + ['5', t('5_minutes_before')], + ['10', t('10_minutes_before')], + ['15', t('15_minutes_before')], + ['30', t('30_minutes_before')], + ['60', t('1_hour_before')], + ]; + + return ( +
{wrapper}
}> + + {t('Create_Event')} + + + + + {t('Subject')} + + + + {errors.subject && {errors.subject.message}} + + + + {t('Start_Time')} + + + + {errors.startTime && {errors.startTime.message}} + + + + {t('End_Time')} + + + + + + + {t('Meeting_URL')} + + + + + + + {t('Description')} + + + + + + + {t('Reminder')} + +