Skip to content

Commit

Permalink
♻️ Refactor RecurrenceSettings
Browse files Browse the repository at this point in the history
  • Loading branch information
shubham-jitiya-simform committed Nov 25, 2024
1 parent 0df874c commit 0b345a6
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 43 deletions.
1 change: 0 additions & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ List<CalendarEventData> _events = [
date: _now.subtract(Duration(days: 3)),
recurrenceSettings: RecurrenceSettings.withCalculatedEndDate(
startDate: _now.subtract(Duration(days: 3)),
endDate: _now.subtract(Duration(days: 3)),
frequency: RepeatFrequency.daily,
recurrenceEndOn: RecurrenceEnd.after,
occurrences: 5,
Expand Down
2 changes: 1 addition & 1 deletion example/lib/widgets/add_event_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class AddOrEditEventForm extends StatefulWidget {
class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
late DateTime _startDate = DateTime.now().withoutTime;
late DateTime _endDate = DateTime.now().withoutTime;
late DateTime _recurrenceEndDate = DateTime.now().withoutTime;
DateTime? _recurrenceEndDate;

DateTime? _startTime;
DateTime? _endTime;
Expand Down
66 changes: 25 additions & 41 deletions lib/src/modals.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ class LiveTimeIndicatorSettings {
///
/// [weekdays]: Contains list of weekdays to repeat starting from 0 index.
/// By default selected weekday is the start date of an event.
///
/// Note: Use constructor .withCalculatedEndDate to calculate
/// end date of recurring event automatically.
class RecurrenceSettings {
RecurrenceSettings({
required this.startDate,
Expand All @@ -112,22 +115,25 @@ class RecurrenceSettings {

// Set by calculating end date for daily
// Ex. If current date is 11-11-24 and interval is 5 then new end date will be
// 15-11-24. Interval - 1 is added because event has been already occurred
// once on start date.
// 15-11-24.

// Set by calculating end date for weekly
// Ex. If current date is 1-11-24 and interval is 5 then new end date
// will be 29-11-24.
/// If recurrence event does not have an end date it will calculate end date
/// from the start date.
///
/// Specify `endDate` to end an event on specific date.
RecurrenceSettings.withCalculatedEndDate({
required this.startDate,
required DateTime endDate,
DateTime? endDate,
this.occurrences,
this.frequency = RepeatFrequency.weekly,
this.recurrenceEndOn = RecurrenceEnd.never,
this.excludeDates,
List<int>? weekdays,
}) : weekdays = weekdays ?? [startDate.weekday] {
this.endDate = _getEndDate(endDate);
this.endDate = endDate ?? _getEndDate(startDate);
}

final DateTime startDate;
Expand All @@ -138,6 +144,9 @@ class RecurrenceSettings {
final List<int> weekdays;
final List<DateTime>? excludeDates;

// As one event has been already added on event start date it is subtracted.
int get _occurrences => (occurrences ?? 1) - 1;

/// Calculates the end date for a monthly recurring event
/// based on the start date and the number of occurrences.
///
Expand Down Expand Up @@ -204,26 +213,9 @@ class RecurrenceSettings {

// Calculate the number of full weeks and remaining occurrences
final fullWeeks = (targetOccurrence - 1) ~/ totalWeekdays;
final remainingOccurrences = (targetOccurrence - 1) % totalWeekdays;

// Calculate the base date from full weeks
var resultDate = startDate.add(Duration(days: fullWeeks * 7));

// Find the weekday for the remaining occurrences
if (remainingOccurrences >= 0) {
final startWeekdayIndex =
sortedWeekdays.indexWhere((day) => day >= resultDate.weekday);
final weekdayIndex = startWeekdayIndex == -1
? 0 + remainingOccurrences
: (startWeekdayIndex + remainingOccurrences) % totalWeekdays;

final targetWeekday = sortedWeekdays[weekdayIndex];
final daysToAdd = (targetWeekday - resultDate.weekday + 7) % 7;

resultDate = resultDate.add(Duration(days: daysToAdd));
}

return resultDate;
return startDate.add(Duration(days: fullWeeks * 7));
}

/// Calculate end date for yearly recurring event
Expand Down Expand Up @@ -264,39 +256,31 @@ class RecurrenceSettings {
/// `RepeatFrequency` & `RecurrenceEnd`.
///
/// Returns null if the end date is not applicable.
/// For example: An event that does not repeat and event that never ends.
/// For example: An event that "does not repeat" and event that "never ends".
DateTime? _getEndDate(DateTime endDate) {
if (frequency == RepeatFrequency.doNotRepeat ||
recurrenceEndOn == RecurrenceEnd.never) {
return null;
}

// TODO(Shubham): May not required to check all OR conditions verify that.
if (recurrenceEndOn == RecurrenceEnd.onDate &&
(frequency == RepeatFrequency.daily ||
frequency == RepeatFrequency.weekly ||
frequency == RepeatFrequency.monthly ||
frequency == RepeatFrequency.yearly)) {
} else if (recurrenceEndOn == RecurrenceEnd.onDate) {
return endDate;
}

if (recurrenceEndOn == RecurrenceEnd.after) {
} else if (recurrenceEndOn == RecurrenceEnd.after) {
return _handleOccurrence(endDate);
} else {
return null;
}
return null;
}

// Finds the end date to repeat and event for the given number of occurrences
/// Calculates the end date to repeat the event for the given number of
/// occurrences.
DateTime? _handleOccurrence(DateTime endDate) {
final occurrence = occurrences ?? 1;
if (occurrence <= 1) {
if (_occurrences < 1) {
return endDate;
}
switch (frequency) {
case RepeatFrequency.doNotRepeat:
return null;
case RepeatFrequency.daily:
return endDate.add(Duration(days: occurrence - 1));
return endDate.add(Duration(days: _occurrences));
case RepeatFrequency.weekly:
return _endDateWeekly ?? endDate;
case RepeatFrequency.monthly:
Expand All @@ -320,7 +304,7 @@ class RecurrenceSettings {
RecurrenceSettings copyWith({
DateTime? startDate,
DateTime? endDate,
int? interval,
int? occurrences,
RepeatFrequency? frequency,
RecurrenceEnd? recurrenceEndOn,
List<int>? weekdays,
Expand All @@ -329,7 +313,7 @@ class RecurrenceSettings {
return RecurrenceSettings(
startDate: startDate ?? this.startDate,
endDate: endDate ?? this.endDate,
occurrences: interval ?? this.occurrences,
occurrences: occurrences ?? this.occurrences,
frequency: frequency ?? this.frequency,
recurrenceEndOn: recurrenceEndOn ?? this.recurrenceEndOn,
weekdays: weekdays ?? this.weekdays,
Expand Down

0 comments on commit 0b345a6

Please sign in to comment.