Repository: SimformSolutionsPvtLtd/flutter_calendar_view

Issue:
day and week view dont show events that end at midnight
if i create an event that ends at midnight, it doesn't show on the day or week view, how can i fix this, is this possible currently? 


Discussion: bump
bump
It show a error if we add day break shift in the week view. Are you getting the same error?
@mac066 yes i am getting the same error

Fix patch:
diff --git a/example/lib/widgets/add_event_form.dart b/example/lib/widgets/add_event_form.dart
index ef6f08d3..3e8b4107 100644
--- a/example/lib/widgets/add_event_form.dart
+++ b/example/lib/widgets/add_event_form.dart
@@ -32,6 +32,7 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
   List<bool> _selectedDays = List.filled(7, false);
   RepeatFrequency? _selectedFrequency = RepeatFrequency.doNotRepeat;
   RecurrenceEnd? _selectedRecurrenceEnd = RecurrenceEnd.never;
+  bool _isRecurring = false;
 
   Color _color = Colors.blue;
 
@@ -92,6 +93,43 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
           SizedBox(
             height: 15,
           ),
+          Row(
+            children: [
+              Text(
+                'Recurring Event',
+                style: TextStyle(
+                  color: AppColors.black,
+                  fontSize: 16,
+                ),
+              ),
+              SizedBox(width: 20),
+              Switch(
+                value: _isRecurring,
+                onChanged: (value) {
+                  setState(() {
+                    _isRecurring = value;
+                    if (_isRecurring) {
+                      // If recurring is turned on, set end date same as start date
+                      _endDate = _startDate;
+                      if (mounted) {
+                        WidgetsBinding.instance.addPostFrameCallback((_) {
+                          setState(() {});
+                        });
+                      }
+                      _selectedFrequency =
+                          RepeatFrequency.daily; // Default to daily
+                    } else {
+                      _selectedFrequency = RepeatFrequency.doNotRepeat;
+                    }
+                  });
+                },
+                activeColor: Colors.blue,
+              ),
+            ],
+          ),
+          SizedBox(
+            height: 15,
+          ),
           Row(
             children: [
               Expanded(
@@ -107,6 +145,15 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
                     }
 
                     _startDate = date.withoutTime;
+                    if (_isRecurring) {
+                      _endDate = _startDate;
+
+                      if (mounted) {
+                        WidgetsBinding.instance.addPostFrameCallback((_) {
+                          setState(() {});
+                        });
+                      }
+                    }
                     updateWeekdaysSelection();
 
                     if (mounted) {
@@ -134,23 +181,29 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
                   initialDateTime: _endDate,
                   decoration: AppConstants.inputDecoration.copyWith(
                     labelText: "End Date",
+                    // Add a disabled style when recurring is true
+                    filled: _isRecurring,
+                    fillColor: _isRecurring ? Colors.grey[200] : null,
                   ),
-                  onSelect: (date) {
-                    if (date.withoutTime.withoutTime
-                        .isBefore(_startDate.withoutTime)) {
-                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
-                        content: Text('End date occurs before start date.'),
-                      ));
-                    } else {
-                      _endDate = date.withoutTime;
-                      _recurrenceEndDate = _endDate;
-                      updateWeekdaysSelection();
-                    }
-
-                    if (mounted) {
-                      setState(() {});
-                    }
-                  },
+                  onSelect: _isRecurring
+                      ? null
+                      : (date) {
+                          if (date.withoutTime.withoutTime
+                              .isBefore(_startDate.withoutTime)) {
+                            ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+                              content:
+                                  Text('End date occurs before start date.'),
+                            ));
+                          } else {
+                            _endDate = date.withoutTime;
+                            _recurrenceEndDate = _endDate;
+                            updateWeekdaysSelection();
+                          }
+
+                          if (mounted) {
+                            setState(() {});
+                          }
+                        },
                   validator: (value) {
                     if (value == null || value == "") {
                       return "Please select end date.";
@@ -159,10 +212,11 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
                     return null;
                   },
                   textStyle: TextStyle(
-                    color: AppColors.black,
+                    color: _isRecurring ? Colors.grey : AppColors.black,
                     fontSize: 17.0,
                   ),
-                  onSave: (date) => _endDate = date ?? _endDate,
+                  onSave: (date) =>
+                      _endDate = _isRecurring ? _startDate : (date ?? _endDate),
                   type: DateTimeSelectionType.date,
                 ),
               ),
@@ -205,7 +259,12 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
                   ),
                   initialDateTime: _endTime,
                   onSelect: (date) {
+                    // If start and end dates are different, any end time is valid
+                    // Only validate time if both events are on the same day
                     if (_startTime != null &&
+                        _startDate.year == _endDate.year &&
+                        _startDate.month == _endDate.month &&
+                        _startDate.day == _endDate.day &&
                         date.getTotalMinutes < _startTime!.getTotalMinutes) {
                       ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                         content: Text('End time is less then start time.'),
@@ -253,264 +312,250 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
               hintText: "Event Description",
             ),
           ),
-          Align(
-            alignment: Alignment.centerLeft,
-            child: Text(
-              'Repeat',
-              style: TextStyle(
-                color: AppColors.black,
-                fontWeight: FontWeight.w500,
-                fontSize: 17,
-              ),
-            ),
-          ),
-          Row(
-            children: [
-              Radio(
-                value: RepeatFrequency.doNotRepeat,
-                groupValue: _selectedFrequency,
-                onChanged: (value) {
-                  setState(
-                    () => _selectedFrequency = value,
-                  );
-                },
-              ),
-              Text(
-                'Do not repeat',
-                style: TextStyle(
-                  color: AppColors.black,
-                  fontSize: 17,
-                ),
-              ),
-            ],
-          ),
-          Row(
-            children: [
-              Radio(
-                value: RepeatFrequency.daily,
-                groupValue: _selectedFrequency,
-                onChanged: (value) {
-                  setState(
-                    () => _selectedFrequency = value,
-                  );
-                },
-              ),
-              Text(
-                'Daily',
+          // Only show repeat settings if the event is recurring
+          if (_isRecurring) ...[
+            SizedBox(height: 15),
+            Align(
+              alignment: Alignment.centerLeft,
+              child: Text(
+                'Repeat',
                 style: TextStyle(
                   color: AppColors.black,
+                  fontWeight: FontWeight.w500,
                   fontSize: 17,
                 ),
-              )
-            ],
-          ),
-          Row(
-            children: [
-              Radio(
-                value: RepeatFrequency.weekly,
-                groupValue: _selectedFrequency,
-                onChanged: (value) {
-                  setState(
-                    () => _selectedFrequency = value,
-                  );
-                },
               ),
-              Text(
-                'Weekly',
-                style: TextStyle(
-                  color: AppColors.black,
-                  fontSize: 17,
+            ),
+            Row(
+              children: [
+                Radio(
+                  value: RepeatFrequency.daily,
+                  groupValue: _selectedFrequency,
+                  onChanged: (value) {
+                    setState(
+                      () => _selectedFrequency = value,
+                    );
+                  },
                 ),
-              ),
-            ],
-          ),
-          Row(
-            children: [
-              Radio(
-                value: RepeatFrequency.monthly,
-                groupValue: _selectedFrequency,
-                onChanged: (value) {
-                  setState(
-                    () => _selectedFrequency = value,
-                  );
-                },
-              ),
-              Text(
-                'Monthly',
-                style: TextStyle(
-                  color: AppColors.black,
-                  fontSize: 17,
+                Text(
+                  'Daily',
+                  style: TextStyle(
+                    color: AppColors.black,
+                    fontSize: 17,
+                  ),
+                )
+              ],
+            ),
+            Row(
+              children: [
+                Radio(
+                  value: RepeatFrequency.weekly,
+                  groupValue: _selectedFrequency,
+                  onChanged: (value) {
+                    setState(
+                      () => _selectedFrequency = value,
+                    );
+                  },
                 ),
-              ),
-            ],
-          ),
-          Row(
-            children: [
-              Radio(
-                value: RepeatFrequency.yearly,
-                groupValue: _selectedFrequency,
-                onChanged: (value) {
-                  setState(
-                    () => _selectedFrequency = value,
-                  );
-                },
-              ),
-              Text(
-                'Yearly',
-                style: TextStyle(
-                  color: AppColors.black,
-                  fontSize: 17,
+                Text(
+                  'Weekly',
+                  style: TextStyle(
+                    color: AppColors.black,
+                    fontSize: 17,
+                  ),
                 ),
-              ),
-            ],
-          ),
-          if (_selectedFrequency == RepeatFrequency.weekly) ...[
-            Wrap(
-              children: List.generate(AppConstants.weekTitles.length, (index) {
-                return ChoiceChip(
-                  label: Text(AppConstants.weekTitles[index]),
-                  showCheckmark: false,
-                  selected: _selectedDays[index],
-                  onSelected: (selected) {
-                    setState(() {
-                      _selectedDays[index] = selected;
-                      if (!_selectedDays.contains(true)) {
-                        _selectedDays[_startDate.weekday - 1] = true;
-                      }
-                    });
+              ],
+            ),
+            Row(
+              children: [
+                Radio(
+                  value: RepeatFrequency.monthly,
+                  groupValue: _selectedFrequency,
+                  onChanged: (value) {
+                    setState(
+                      () => _selectedFrequency = value,
+                    );
                   },
-                  shape: CircleBorder(),
-                );
-              }).toList(),
+                ),
+                Text(
+                  'Monthly',
+                  style: TextStyle(
+                    color: AppColors.black,
+                    fontSize: 17,
+                  ),
+                ),
+              ],
             ),
-          ],
-          SizedBox(height: 15),
-          if (_selectedFrequency != RepeatFrequency.doNotRepeat)
-            Column(
-              crossAxisAlignment: CrossAxisAlignment.start,
+            Row(
               children: [
+                Radio(
+                  value: RepeatFrequency.yearly,
+                  groupValue: _selectedFrequency,
+                  onChanged: (value) {
+                    setState(
+                      () => _selectedFrequency = value,
+                    );
+                  },
+                ),
                 Text(
-                  'Reoccurrence ends on: ',
+                  'Yearly',
                   style: TextStyle(
                     color: AppColors.black,
-                    fontWeight: FontWeight.w500,
                     fontSize: 17,
                   ),
                 ),
-                Row(
-                  children: [
-                    Radio(
-                      value: RecurrenceEnd.never,
-                      groupValue: _selectedRecurrenceEnd,
-                      onChanged: (value) => setState(
-                        () => _selectedRecurrenceEnd = value,
-                      ),
+              ],
+            ),
+            if (_selectedFrequency == RepeatFrequency.weekly) ...[
+              Wrap(
+                children:
+                    List.generate(AppConstants.weekTitles.length, (index) {
+                  return ChoiceChip(
+                    label: Text(AppConstants.weekTitles[index]),
+                    showCheckmark: false,
+                    selected: _selectedDays[index],
+                    onSelected: (selected) {
+                      setState(() {
+                        _selectedDays[index] = selected;
+                        if (!_selectedDays.contains(true)) {
+                          _selectedDays[_startDate.weekday - 1] = true;
+                        }
+                      });
+                    },
+                    shape: CircleBorder(),
+                  );
+                }).toList(),
+              ),
+            ],
+            SizedBox(height: 15),
+            if (_selectedFrequency != RepeatFrequency.doNotRepeat)
+              Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  Text(
+                    'Reoccurrence ends on: ',
+                    style: TextStyle(
+                      color: AppColors.black,
+                      fontWeight: FontWeight.w500,
+                      fontSize: 17,
                     ),
-                    Text(
-                      'Never',
-                      style: TextStyle(
-                        color: AppColors.black,
-                        fontSize: 17,
+                  ),
+                  Row(
+                    children: [
+                      Radio(
+                        value: RecurrenceEnd.never,
+                        groupValue: _selectedRecurrenceEnd,
+                        onChanged: (value) => setState(
+                          () => _selectedRecurrenceEnd = value,
+                        ),
                       ),
-                    ),
-                  ],
-                ),
-                Row(
-                  children: [
-                    Radio(
-                      value: RecurrenceEnd.onDate,
-                      groupValue: _selectedRecurrenceEnd,
-                      onChanged: (value) => setState(
-                        () => _selectedRecurrenceEnd = value,
+                      Text(
+                        'Never',
+                        style: TextStyle(
+                          color: AppColors.black,
+                          fontSize: 17,
+                        ),
                       ),
-                    ),
-                    Text(
-                      'On',
-                      style: TextStyle(
-                        color: AppColors.black,
-                        fontSize: 17,
+                    ],
+                  ),
+                  Row(
+                    children: [
+                      Radio(
+                        value: RecurrenceEnd.onDate,
+                        groupValue: _selectedRecurrenceEnd,
+                        onChanged: (value) => setState(
+                          () => _selectedRecurrenceEnd = value,
+                        ),
                       ),
-                    )
-                  ],
-                ),
-                Row(
-                  children: [
-                    Radio(
-                      value: RecurrenceEnd.after,
-                      groupValue: _selectedRecurrenceEnd,
-                      onChanged: (value) => setState(
-                        () => _selectedRecurrenceEnd = value,
+                      Text(
+                        'On',
+                        style: TextStyle(
+                          color: AppColors.black,
+                          fontSize: 17,
+                        ),
+                      )
+                    ],
+                  ),
+                  Row(
+                    children: [
+                      Radio(
+                        value: RecurrenceEnd.after,
+                        groupValue: _selectedRecurrenceEnd,
+                        onChanged: (value) => setState(
+                          () => _selectedRecurrenceEnd = value,
+                        ),
                       ),
-                    ),
-                    Text(
-                      'After',
-                      style: TextStyle(
-                        color: AppColors.black,
-                        fontSize: 17,
+                      Text(
+                        'After',
+                        style: TextStyle(
+                          color: AppColors.black,
+                          fontSize: 17,
+                        ),
                       ),
-                    ),
-                  ],
-                ),
-              ],
-            ),
-          SizedBox(height: 15),
-          if (_selectedRecurrenceEnd == RecurrenceEnd.onDate)
-            DateTimeSelectorFormField(
-              initialDateTime: _recurrenceEndDate,
-              decoration: AppConstants.inputDecoration.copyWith(
-                labelText: 'Ends on',
-              ),
-              onSelect: (date) {
-                if (date.withoutTime.isBefore(_endDate.withoutTime)) {
-                  ScaffoldMessenger.of(context).showSnackBar(SnackBar(
-                    content: Text('Recurrence ends after end date'),
-                  ));
-                } else {
-                  _recurrenceEndDate = date.withoutTime;
-                }
-
-                if (mounted) {
-                  setState(() {});
-                }
-              },
-              validator: (value) {
-                if (value == null || value == "") {
-                  return 'Please select end date.';
-                }
-
-                // TODO(Shubham): Add validation of end occurrence >= end date
-                return null;
-              },
-              textStyle: TextStyle(
-                color: AppColors.black,
-                fontSize: 17.0,
+                    ],
+                  ),
+                ],
               ),
-              onSave: (date) => _recurrenceEndDate = date ?? _recurrenceEndDate,
-              type: DateTimeSelectionType.date,
-            ),
-          if (_selectedRecurrenceEnd == RecurrenceEnd.after)
-            TextFormField(
-              controller: _occurrenceController,
-              style: TextStyle(
-                color: AppColors.black,
-                fontSize: 17.0,
+            SizedBox(height: 15),
+            if (_selectedRecurrenceEnd == RecurrenceEnd.onDate)
+              DateTimeSelectorFormField(
+                initialDateTime: _recurrenceEndDate,
+                decoration: AppConstants.inputDecoration.copyWith(
+                  labelText: 'Ends on',
+                ),
+                onSelect: (date) {
+                  if (date.withoutTime.isBefore(_endDate.withoutTime)) {
+                    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+                      content: Text('Recurrence ends after end date'),
+                    ));
+                  } else {
+                    _recurrenceEndDate = date.withoutTime;
+                  }
+
+                  if (mounted) {
+                    setState(() {});
+                  }
+                },
+                validator: (value) {
+                  if (value == null || value == "") {
+                    return 'Please select end date.';
+                  }
+
+                  // TODO(Shubham): Add validation of end occurrence >= end date
+                  return null;
+                },
+                textStyle: TextStyle(
+                  color: AppColors.black,
+                  fontSize: 17.0,
+                ),
+                onSave: (date) =>
+                    _recurrenceEndDate = date ?? _recurrenceEndDate,
+                type: DateTimeSelectionType.date,
               ),
-              keyboardType: TextInputType.number,
-              minLines: 1,
-              maxLength: 3,
-              validator: (value) {
-                if (value == null || value.trim() == '') {
-                  return 'Please specify occurrences';
-                }
-
-                return null;
-              },
-              decoration: AppConstants.inputDecoration.copyWith(
-                hintText: '30',
-                suffixText: 'Occurrences',
-                counterText: '',
+            if (_selectedRecurrenceEnd == RecurrenceEnd.after)
+              TextFormField(
+                controller: _occurrenceController,
+                style: TextStyle(
+                  color: AppColors.black,
+                  fontSize: 17.0,
+                ),
+                keyboardType: TextInputType.number,
+                minLines: 1,
+                maxLength: 3,
+                validator: (value) {
+                  if (value == null || value.trim() == '') {
+                    return 'Please specify occurrences';
+                  }
+
+                  return null;
+                },
+                decoration: AppConstants.inputDecoration.copyWith(
+                  hintText: '30',
+                  suffixText: 'Occurrences',
+                  counterText: '',
+                ),
               ),
-            ),
+          ],
           SizedBox(
             height: 15.0,
           ),
@@ -548,44 +593,67 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
     if (!(_form.currentState?.validate() ?? true)) return;
 
     _form.currentState?.save();
-    var occurrences = int.tryParse(_occurrenceController.text);
-    DateTime? endDate;
-
-    // On event edit recurrence end is selected "Never"
-    // Remove any previous end date & occurrences stored.
-    if (_selectedRecurrenceEnd == RecurrenceEnd.never) {
-      endDate = null;
-      occurrences = null;
+
+    DateTime? combinedStartTime;
+    DateTime? combinedEndTime;
+
+    if (_startTime != null) {
+      // Create a proper DateTime that combines the start date with start time
+      combinedStartTime = DateTime(_startDate.year, _startDate.month,
+          _startDate.day, _startTime!.hour, _startTime!.minute);
     }
 
-    if (_selectedRecurrenceEnd == RecurrenceEnd.onDate) {
-      endDate = _recurrenceEndDate;
+    if (_endTime != null) {
+      // Create a proper DateTime that combines the end date with end time
+      combinedEndTime = DateTime(_endDate.year, _endDate.month, _endDate.day,
+          _endTime!.hour, _endTime!.minute);
     }
 
-    final recurrenceSettings = RecurrenceSettings.withCalculatedEndDate(
-      startDate: _startDate,
-      endDate: endDate,
-      frequency: _selectedFrequency ?? RepeatFrequency.daily,
-      weekdays: _toWeekdayInIndices,
-      occurrences: occurrences,
-      recurrenceEndOn: _selectedRecurrenceEnd ?? RecurrenceEnd.never,
-    );
+    // Only create recurrence settings if not using the default "Do not repeat" option
+    RecurrenceSettings? recurrence;
+    if (_selectedFrequency != null &&
+        _selectedFrequency != RepeatFrequency.doNotRepeat) {
+      var occurrences = int.tryParse(_occurrenceController.text);
+      DateTime? endDate;
+
+      // On event edit recurrence end is selected "Never"
+      // Remove any previous end date & occurrences stored.
+      if (_selectedRecurrenceEnd == RecurrenceEnd.never) {
+        endDate = null;
+        occurrences = null;
+      }
+
+      if (_selectedRecurrenceEnd == RecurrenceEnd.onDate) {
+        endDate = _recurrenceEndDate;
+      }
+
+      recurrence = RecurrenceSettings.withCalculatedEndDate(
+        startDate: _startDate,
+        endDate: endDate,
+        frequency: _selectedFrequency ?? RepeatFrequency.daily,
+        weekdays: _toWeekdayInIndices,
+        occurrences: occurrences,
+        recurrenceEndOn: _selectedRecurrenceEnd ?? RecurrenceEnd.never,
+      );
+    }
 
     // Determine the appropriate endDate based on whether this is a recurring event
     final DateTime eventEndDate =
-        (_selectedFrequency != RepeatFrequency.doNotRepeat)
-            ? _startDate.withoutTime
-            : _endDate;
+        (_selectedFrequency == RepeatFrequency.doNotRepeat)
+            ? _endDate
+            : _endDate.isAtSameMomentAs(_startDate)
+                ? _startDate
+                : _endDate;
 
     final event = CalendarEventData(
       date: _startDate,
-      endTime: _endTime,
-      startTime: _startTime,
       endDate: eventEndDate,
+      endTime: combinedEndTime,
+      startTime: combinedStartTime,
       color: _color,
       title: _titleController.text.trim(),
       description: _descriptionController.text.trim(),
-      recurrenceSettings: recurrenceSettings,
+      recurrenceSettings: recurrence,
     );
 
     widget.onEventAdd?.call(event);
@@ -635,18 +703,40 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
     _endTime = event.endTime ?? _endTime;
     _titleController.text = event.title;
     _descriptionController.text = event.description ?? '';
-    _selectedFrequency = event.recurrenceSettings?.frequency;
-    _selectedRecurrenceEnd =
-        event.recurrenceSettings?.recurrenceEndOn ?? RecurrenceEnd.never;
-    _recurrenceEndDate = event.recurrenceSettings?.endDate ?? _startDate;
-    _occurrenceController.text =
-        (event.recurrenceSettings?.occurrences ?? 0).toString();
-    event.recurrenceSettings?.weekdays
-        .forEach((index) => _selectedDays[index] = true);
+    _color = event.color; // Set the event color
+
+    // Handle recurrence settings
+    if (event.recurrenceSettings != null &&
+        event.recurrenceSettings!.frequency != RepeatFrequency.doNotRepeat) {
+      _isRecurring = true;
+      _selectedFrequency = event.recurrenceSettings!.frequency;
+      _selectedRecurrenceEnd = event.recurrenceSettings!.recurrenceEndOn;
+      _recurrenceEndDate = event.recurrenceSettings!.endDate ?? _startDate;
+
+      // Handle occurrences for "After" recurrence end type
+      if (_selectedRecurrenceEnd == RecurrenceEnd.after) {
+        _occurrenceController.text =
+            (event.recurrenceSettings!.occurrences ?? 1).toString();
+      }
+
+      // Clear weekdays selection and then set the selected days
+      _selectedDays = List.filled(7, false);
+      event.recurrenceSettings!.weekdays
+          .forEach((index) => _selectedDays[index] = true);
+    } else {
+      _isRecurring = false;
+      _selectedFrequency = RepeatFrequency.doNotRepeat;
+      updateWeekdaysSelection();
+    }
   }
 
   void _resetForm() {
     _form.currentState?.reset();
+
+    _titleController.text = '';
+    _descriptionController.text = '';
+    _occurrenceController.text = '';
+
     _startDate = DateTime.now().withoutTime;
     _endDate = DateTime.now().withoutTime;
     _startTime = null;
@@ -656,6 +746,7 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
     _selectedDays.fillRange(0, _selectedDays.length, true);
     _selectedFrequency = RepeatFrequency.doNotRepeat;
     _selectedRecurrenceEnd = RecurrenceEnd.never;
+    _isRecurring = false;
 
     if (mounted) {
       setState(() {});
diff --git a/example/lib/widgets/date_time_selector.dart b/example/lib/widgets/date_time_selector.dart
index 008d5666..913bf365 100644
--- a/example/lib/widgets/date_time_selector.dart
+++ b/example/lib/widgets/date_time_selector.dart
@@ -75,7 +75,8 @@ class _DateTimeSelectorFormFieldState extends State<DateTimeSelectorFormField> {
       _textEditingController = widget.controller ?? TextEditingController();
     }
 
-    if (_selectedDate != oldWidget.initialDateTime ||
+    if (widget.initialDateTime != oldWidget.initialDateTime ||
+        _selectedDate != oldWidget.initialDateTime ||
         widget.minimumDateTime != oldWidget.minimumDateTime) {
       _setDates();
     }
@@ -104,7 +105,7 @@ class _DateTimeSelectorFormFieldState extends State<DateTimeSelectorFormField> {
   @override
   Widget build(BuildContext context) {
     return GestureDetector(
-      onTap: _showSelector,
+      onTap: widget.onSelect == null ? null : _showSelector,
       child: TextFormField(
         focusNode: _focusNode,
         style: widget.textStyle,
diff --git a/lib/src/components/_internal_components.dart b/lib/src/components/_internal_components.dart
index c5369086..f412faa3 100644
--- a/lib/src/components/_internal_components.dart
+++ b/lib/src/components/_internal_components.dart
@@ -385,12 +385,13 @@ class EventGenerator<T extends Object?> extends StatelessWidget {
   /// of events and [eventTileBuilder] to display events.
   List<Widget> _generateEvents(BuildContext context) {
     final events = eventArranger.arrange(
-        events: this.events,
-        height: height,
-        width: width,
-        heightPerMinute: heightPerMinute,
-        startHour: startHour);
-
+      events: this.events,
+      height: height,
+      width: width,
+      heightPerMinute: heightPerMinute,
+      startHour: startHour,
+      calendarViewDate: date,
+    );
     return List.generate(events.length, (index) {
       return Positioned(
         top: events[index].top,
diff --git a/lib/src/event_arrangers/event_arrangers.dart b/lib/src/event_arrangers/event_arrangers.dart
index 96f2c853..bff8fb48 100644
--- a/lib/src/event_arrangers/event_arrangers.dart
+++ b/lib/src/event_arrangers/event_arrangers.dart
@@ -37,6 +37,7 @@ abstract class EventArranger<T extends Object?> {
     required double width,
     required double heightPerMinute,
     required int startHour,
+    required DateTime calendarViewDate,
   });
 }
 
@@ -63,6 +64,9 @@ class OrganizedCalendarEventData<T extends Object?> {
   /// End duration of event/event list.
   final DateTime endDuration;
 
+  /// DateTime of the calendar view date.
+  final DateTime calendarViewDate;
+
   /// Provides event data with its [left], [right], [top], and [bottom]
   /// boundary.
   OrganizedCalendarEventData({
@@ -73,6 +77,7 @@ class OrganizedCalendarEventData<T extends Object?> {
     required this.left,
     required this.right,
     required this.events,
+    required this.calendarViewDate,
   });
 
   OrganizedCalendarEventData.empty()
@@ -82,7 +87,8 @@ class OrganizedCalendarEventData<T extends Object?> {
         left = 0,
         events = const [],
         top = 0,
-        bottom = 0;
+        bottom = 0,
+        calendarViewDate = DateTime.now();
 
   OrganizedCalendarEventData<T> getWithUpdatedRight(double right) =>
       OrganizedCalendarEventData<T>(
@@ -93,5 +99,6 @@ class OrganizedCalendarEventData<T extends Object?> {
         left: left,
         right: right,
         startDuration: startDuration,
+        calendarViewDate: calendarViewDate,
       );
 }
diff --git a/lib/src/event_arrangers/merge_event_arranger.dart b/lib/src/event_arrangers/merge_event_arranger.dart
index 4e7c8c47..59dfed4a 100644
--- a/lib/src/event_arrangers/merge_event_arranger.dart
+++ b/lib/src/event_arrangers/merge_event_arranger.dart
@@ -32,11 +32,13 @@ class MergeEventArranger<T extends Object?> extends EventArranger<T> {
     required double width,
     required double heightPerMinute,
     required int startHour,
+    required DateTime calendarViewDate,
   }) {
     // TODO: Right now all the events that are passed in this function must be
     // sorted in ascending order of the start time.
     //
     final arrangedEvents = <OrganizedCalendarEventData<T>>[];
+    final startHourInMinutes = startHour * 60;
 
     //Checking if startTime and endTime are correct
     for (final event in events) {
@@ -46,7 +48,8 @@ class MergeEventArranger<T extends Object?> extends EventArranger<T> {
       }
 
       // Checks if an event has valid start and end time.
-      if (event.endTime!.getTotalMinutes <= event.startTime!.getTotalMinutes) {
+      if (event.endDate.millisecondsSinceEpoch <
+          event.date.millisecondsSinceEpoch) {
         if (!(event.endTime!.getTotalMinutes == 0 &&
             event.startTime!.getTotalMinutes > 0)) {
           assert(() {
@@ -67,13 +70,51 @@ class MergeEventArranger<T extends Object?> extends EventArranger<T> {
       final startTime = event.startTime!;
       final endTime = event.endTime!;
 
-      // startTime.getTotalMinutes returns the number of minutes from 00h00 to the beginning of the event
-      // But the first hour to be displayed (startHour) could be 06h00, so we have to substract
-      // The number of minutes from 00h00 to startHour which is equal to startHour * 60
-      final eventStart = startTime.getTotalMinutes - (startHour * 60);
-      final eventEnd = endTime.getTotalMinutes - (startHour * 60) == 0
-          ? Constants.minutesADay - (startHour * 60)
-          : endTime.getTotalMinutes - (startHour * 60);
+      int eventStart;
+      int eventEnd;
+
+      if (event.isRangingEvent) {
+        // Handle multi-day events differently based on which day is currently being viewed
+        final isStartDate =
+            calendarViewDate.isAtSameMomentAs(event.date.withoutTime);
+        final isEndDate =
+            calendarViewDate.isAtSameMomentAs(event.endDate.withoutTime);
+
+        if (isStartDate && isEndDate) {
+          // Single day event with start and end time
+          eventStart = startTime.getTotalMinutes - (startHourInMinutes);
+          eventEnd = endTime.getTotalMinutes - (startHourInMinutes) <= 0
+              ? Constants.minutesADay - (startHourInMinutes)
+              : endTime.getTotalMinutes - (startHourInMinutes);
+        } else if (isStartDate) {
+          // First day - show from start time to end of day
+          eventStart = startTime.getTotalMinutes - (startHourInMinutes);
+          eventEnd = Constants.minutesADay;
+        } else if (isEndDate) {
+          // Last day - show from start of day to end time
+          eventStart = 0;
+          eventEnd = endTime.getTotalMinutes - (startHourInMinutes) <= 0
+              ? Constants.minutesADay - (startHourInMinutes)
+              : endTime.getTotalMinutes - (startHourInMinutes);
+        } else {
+          // Middle days - show full day
+          eventStart = 0;
+          eventEnd = Constants.minutesADay;
+        }
+      } else {
+        // Single day event - use normal start/end times
+        eventStart = startTime.getTotalMinutes - (startHourInMinutes);
+        eventEnd = endTime.getTotalMinutes - (startHourInMinutes) <= 0
+            ? Constants.minutesADay - (startHourInMinutes)
+            : endTime.getTotalMinutes - (startHourInMinutes);
+      }
+
+      // Ensure values are within valid range
+      eventStart = math.max(0, eventStart);
+      eventEnd = math.min(
+        Constants.minutesADay - (startHourInMinutes),
+        eventEnd,
+      );
 
       final arrangeEventLen = arrangedEvents.length;
 
@@ -97,8 +138,13 @@ class MergeEventArranger<T extends Object?> extends EventArranger<T> {
 
       if (eventIndex == -1) {
         final top = eventStart * heightPerMinute;
-        final bottom = eventEnd * heightPerMinute == height
-            ? 0.0
+
+        // Calculate visibleMinutes (the total minutes displayed in the view)
+        final visibleMinutes = Constants.minutesADay - (startHourInMinutes);
+
+        // Check if event ends at or beyond the visible area
+        final bottom = eventEnd >= visibleMinutes
+            ? 0.0 // Event extends to bottom of view
             : height - eventEnd * heightPerMinute;
 
         final newEvent = OrganizedCalendarEventData<T>(
@@ -109,6 +155,7 @@ class MergeEventArranger<T extends Object?> extends EventArranger<T> {
           startDuration: startTime.copyFromMinutes(eventStart),
           endDuration: endTime.copyFromMinutes(eventEnd),
           events: [event],
+          calendarViewDate: calendarViewDate,
         );
 
         arrangedEvents.add(newEvent);
@@ -126,8 +173,13 @@ class MergeEventArranger<T extends Object?> extends EventArranger<T> {
         final endDuration = math.max(eventEnd, arrangedEventEnd);
 
         final top = startDuration * heightPerMinute;
-        final bottom = endDuration * heightPerMinute == height
-            ? 0.0
+
+        // Calculate visibleMinutes (the total minutes displayed in the view)
+        final visibleMinutes = Constants.minutesADay - (startHourInMinutes);
+
+        // Check if event ends at or beyond the visible area
+        final bottom = endDuration >= visibleMinutes
+            ? 0.0 // Event extends to bottom of view
             : height - endDuration * heightPerMinute;
 
         final newEvent = OrganizedCalendarEventData<T>(
@@ -140,6 +192,7 @@ class MergeEventArranger<T extends Object?> extends EventArranger<T> {
           endDuration:
               arrangedEventData.endDuration.copyFromMinutes(endDuration),
           events: arrangedEventData.events..add(event),
+          calendarViewDate: calendarViewDate,
         );
 
         arrangedEvents[eventIndex] = newEvent;
diff --git a/lib/src/event_arrangers/side_event_arranger.dart b/lib/src/event_arrangers/side_event_arranger.dart
index 5c0283c9..e960421b 100644
--- a/lib/src/event_arrangers/side_event_arranger.dart
+++ b/lib/src/event_arrangers/side_event_arranger.dart
@@ -38,8 +38,10 @@ class SideEventArranger<T extends Object?> extends EventArranger<T> {
     required double width,
     required double heightPerMinute,
     required int startHour,
+    required DateTime calendarViewDate,
   }) {
     final totalWidth = width;
+    final startHourInMinutes = startHour * 60;
 
     List<_SideEventConfigs<T>> _categorizedColumnedEvents(
         List<CalendarEventData<T>> events) {
@@ -49,6 +51,7 @@ class SideEventArranger<T extends Object?> extends EventArranger<T> {
         width: width,
         heightPerMinute: heightPerMinute,
         startHour: startHour,
+        calendarViewDate: calendarViewDate,
       );
 
       final arranged = <_SideEventConfigs<T>>[];
@@ -117,27 +120,71 @@ class SideEventArranger<T extends Object?> extends EventArranger<T> {
             final startTime = e.startTime!;
             final endTime = e.endTime!;
 
-            // startTime.getTotalMinutes returns the number of minutes from 00h00 to the beginning hour of the event
-            // But the first hour to be displayed (startHour) could be 06h00, so we have to substract
-            // The number of minutes from 00h00 to startHour which is equal to startHour * 60
+            int eventStart;
+            int eventEnd;
+
+            if (e.isRangingEvent) {
+              // Handle multi-day events differently based on which day is currently being viewed
+              final isStartDate =
+                  calendarViewDate.isAtSameMomentAs(e.date.withoutTime);
+              final isEndDate =
+                  calendarViewDate.isAtSameMomentAs(e.endDate.withoutTime);
+
+              if (isStartDate && isEndDate) {
+                // Single day event with start and end time
+                eventStart = startTime.getTotalMinutes - (startHourInMinutes);
+                eventEnd = endTime.getTotalMinutes - (startHourInMinutes) <= 0
+                    ? Constants.minutesADay - (startHourInMinutes)
+                    : endTime.getTotalMinutes - (startHourInMinutes);
+              } else if (isStartDate) {
+                // First day - show from start time to end of day
+                eventStart = startTime.getTotalMinutes - (startHourInMinutes);
+                eventEnd = Constants.minutesADay - (startHourInMinutes);
+              } else if (isEndDate) {
+                // Last day - show from start of day to end time
+                eventStart = 0;
+                eventEnd = endTime.getTotalMinutes - (startHourInMinutes) <= 0
+                    ? Constants.minutesADay - (startHourInMinutes)
+                    : endTime.getTotalMinutes - (startHourInMinutes);
+              } else {
+                // Middle days - show full day
+                eventStart = 0;
+                eventEnd = Constants.minutesADay - (startHourInMinutes);
+              }
+            } else {
+              // Single day event - use normal start/end times
+              eventStart = startTime.getTotalMinutes - (startHourInMinutes);
+              eventEnd = endTime.getTotalMinutes - (startHourInMinutes) <= 0
+                  ? Constants.minutesADay - (startHourInMinutes)
+                  : endTime.getTotalMinutes - (startHourInMinutes);
+            }
+
+            // Ensure values are within valid range
+            eventStart = math.max(0, eventStart);
+            eventEnd = math.min(
+              Constants.minutesADay - (startHourInMinutes),
+              eventEnd,
+            );
+
+            final top = eventStart * heightPerMinute;
 
-            final bottom = height -
-                (endTime.getTotalMinutes - (startHour * 60) == 0
-                        ? Constants.minutesADay - (startHour * 60)
-                        : endTime.getTotalMinutes - (startHour * 60)) *
-                    heightPerMinute;
+            // Calculate visibleMinutes (the total minutes displayed in the view)
+            final visibleMinutes = Constants.minutesADay - (startHourInMinutes);
 
-            final top = (startTime.getTotalMinutes - (startHour * 60)) *
-                heightPerMinute;
+            // Check if event ends at or beyond the visible area
+            final bottom = eventEnd >= visibleMinutes
+                ? 0.0 // Event extends to bottom of view
+                : height - eventEnd * heightPerMinute;
 
             return OrganizedCalendarEventData<T>(
               left: offset,
               right: totalWidth - (offset + slotWidth),
               top: top,
               bottom: bottom,
-              startDuration: startTime,
-              endDuration: endTime,
+              startDuration: startTime.copyFromMinutes(eventStart),
+              endDuration: endTime.copyFromMinutes(eventEnd),
               events: [e],
+              calendarViewDate: calendarViewDate,
             );
           }));
         }
diff --git a/lib/src/event_controller.dart b/lib/src/event_controller.dart
index f67c4b3a..c4c33f47 100644
--- a/lib/src/event_controller.dart
+++ b/lib/src/event_controller.dart
@@ -570,6 +570,13 @@ class CalendarData<T extends Object?> {
         .where((event) => (!event.isFullDayEvent && !event.isRangingEvent))
         .toList();
     events.addAll(recurringEvents);
+
+    // Inside event arranger we require all the events to be sorted
+    // based on start time.
+    //If not sorted it will create overlapping events in the arranger.
+    events.sort((a, b) =>
+        (a.startTime?.getTotalMinutes ?? 0) -
+        (b.startTime?.getTotalMinutes ?? 0));
     return events;
   }
 


Test patch:
diff --git a/test/event_arranger_test/merge_event_arranger_test.dart b/test/event_arranger_test/merge_event_arranger_test.dart
index 1e32e186..0d9f71cd 100644
--- a/test/event_arranger_test/merge_event_arranger_test.dart
+++ b/test/event_arranger_test/merge_event_arranger_test.dart
@@ -55,11 +55,13 @@ void main() {
       ];
 
       final mergedEvents = MergeEventArranger().arrange(
-          events: events,
-          height: height,
-          width: width,
-          heightPerMinute: heightPerMinute,
-          startHour: startHour);
+        events: events,
+        height: height,
+        width: width,
+        heightPerMinute: heightPerMinute,
+        startHour: startHour,
+        calendarViewDate: now,
+      );
 
       expect(mergedEvents.length, events.length);
     });
@@ -84,11 +86,13 @@ void main() {
       ];
 
       final mergedEvents = MergeEventArranger().arrange(
-          events: events,
-          height: height,
-          width: width,
-          heightPerMinute: heightPerMinute,
-          startHour: startHour);
+        events: events,
+        height: height,
+        width: width,
+        heightPerMinute: heightPerMinute,
+        startHour: startHour,
+        calendarViewDate: now,
+      );
 
       expect(mergedEvents.length, 1);
     });
@@ -113,11 +117,13 @@ void main() {
       ];
 
       final mergedEvents = MergeEventArranger().arrange(
-          events: events,
-          height: height,
-          width: width,
-          heightPerMinute: heightPerMinute,
-          startHour: startHour);
+        events: events,
+        height: height,
+        width: width,
+        heightPerMinute: heightPerMinute,
+        startHour: startHour,
+        calendarViewDate: now,
+      );
 
       expect(mergedEvents.length, 1);
     });
@@ -142,11 +148,13 @@ void main() {
       ];
 
       final mergedEvents = MergeEventArranger().arrange(
-          events: events,
-          height: height,
-          width: width,
-          heightPerMinute: heightPerMinute,
-          startHour: startHour);
+        events: events,
+        height: height,
+        width: width,
+        heightPerMinute: heightPerMinute,
+        startHour: startHour,
+        calendarViewDate: now,
+      );
 
       expect(mergedEvents.length, 1);
     });
@@ -171,11 +179,13 @@ void main() {
       ];
 
       final mergedEvents = MergeEventArranger().arrange(
-          events: events,
-          height: height,
-          width: width,
-          heightPerMinute: heightPerMinute,
-          startHour: startHour);
+        events: events,
+        height: height,
+        width: width,
+        heightPerMinute: heightPerMinute,
+        startHour: startHour,
+        calendarViewDate: now,
+      );
 
       expect(mergedEvents.length, 1);
     });
@@ -200,11 +210,13 @@ void main() {
       ];
 
       final mergedEvents = MergeEventArranger().arrange(
-          events: events,
-          height: height,
-          width: width,
-          heightPerMinute: heightPerMinute,
-          startHour: startHour);
+        events: events,
+        height: height,
+        width: width,
+        heightPerMinute: heightPerMinute,
+        startHour: startHour,
+        calendarViewDate: now,
+      );
 
       expect(mergedEvents.length, 1);
     });
@@ -261,11 +273,13 @@ void main() {
       ];
 
       final mergedEvents = MergeEventArranger().arrange(
-          events: events,
-          height: height,
-          width: width,
-          heightPerMinute: heightPerMinute,
-          startHour: startHour);
+        events: events,
+        height: height,
+        width: width,
+        heightPerMinute: heightPerMinute,
+        startHour: startHour,
+        calendarViewDate: now,
+      );
 
       expect(mergedEvents.length, 4);
     });
@@ -322,14 +336,16 @@ void main() {
       ];
 
       final mergedEvents = MergeEventArranger().arrange(
-          events: events
-            ..sort((e1, e2) =>
-                (e1.startTime?.getTotalMinutes ?? 0) -
-                (e2.startTime?.getTotalMinutes ?? 0)),
-          height: height,
-          width: width,
-          heightPerMinute: heightPerMinute,
-          startHour: startHour);
+        events: events
+          ..sort((e1, e2) =>
+              (e1.startTime?.getTotalMinutes ?? 0) -
+              (e2.startTime?.getTotalMinutes ?? 0)),
+        height: height,
+        width: width,
+        heightPerMinute: heightPerMinute,
+        startHour: startHour,
+        calendarViewDate: now,
+      );
 
       expect(mergedEvents.length, 1);
     });
@@ -356,14 +372,16 @@ void main() {
         ];
 
         final mergedEvents = MergeEventArranger(includeEdges: false).arrange(
-            events: events
-              ..sort((e1, e2) =>
-                  (e1.startTime?.getTotalMinutes ?? 0) -
-                  (e2.startTime?.getTotalMinutes ?? 0)),
-            height: height,
-            width: width,
-            heightPerMinute: heightPerMinute,
-            startHour: startHour);
+          events: events
+            ..sort((e1, e2) =>
+                (e1.startTime?.getTotalMinutes ?? 0) -
+                (e2.startTime?.getTotalMinutes ?? 0)),
+          height: height,
+          width: width,
+          heightPerMinute: heightPerMinute,
+          startHour: startHour,
+          calendarViewDate: now,
+        );
 
         expect(mergedEvents.length, 2);
       });
@@ -389,14 +407,16 @@ void main() {
         ];
 
         final mergedEvents = MergeEventArranger(includeEdges: false).arrange(
-            events: events
-              ..sort((e1, e2) =>
-                  (e1.startTime?.getTotalMinutes ?? 0) -
-                  (e2.startTime?.getTotalMinutes ?? 0)),
-            height: height,
-            width: width,
-            heightPerMinute: heightPerMinute,
-            startHour: startHour);
+          events: events
+            ..sort((e1, e2) =>
+                (e1.startTime?.getTotalMinutes ?? 0) -
+                (e2.startTime?.getTotalMinutes ?? 0)),
+          height: height,
+          width: width,
+          heightPerMinute: heightPerMinute,
+          startHour: startHour,
+          calendarViewDate: now,
+        );
 
         expect(mergedEvents.length, 2);
       });
@@ -423,14 +443,16 @@ void main() {
         ];
 
         final mergedEvents = MergeEventArranger(includeEdges: true).arrange(
-            events: events
-              ..sort((e1, e2) =>
-                  (e1.startTime?.getTotalMinutes ?? 0) -
-                  (e2.startTime?.getTotalMinutes ?? 0)),
-            height: height,
-            width: width,
-            heightPerMinute: heightPerMinute,
-            startHour: startHour);
+          events: events
+            ..sort((e1, e2) =>
+                (e1.startTime?.getTotalMinutes ?? 0) -
+                (e2.startTime?.getTotalMinutes ?? 0)),
+          height: height,
+          width: width,
+          heightPerMinute: heightPerMinute,
+          startHour: startHour,
+          calendarViewDate: now,
+        );
 
         expect(mergedEvents.length, 1);
       });
@@ -456,14 +478,16 @@ void main() {
         ];
 
         final mergedEvents = MergeEventArranger(includeEdges: true).arrange(
-            events: events
-              ..sort((e1, e2) =>
-                  (e1.startTime?.getTotalMinutes ?? 0) -
-                  (e2.startTime?.getTotalMinutes ?? 0)),
-            height: height,
-            width: width,
-            heightPerMinute: heightPerMinute,
-            startHour: startHour);
+          events: events
+            ..sort((e1, e2) =>
+                (e1.startTime?.getTotalMinutes ?? 0) -
+                (e2.startTime?.getTotalMinutes ?? 0)),
+          height: height,
+          width: width,
+          heightPerMinute: heightPerMinute,
+          startHour: startHour,
+          calendarViewDate: now,
+        );
 
         expect(mergedEvents.length, 1);
       });