Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add off day support #47

Merged
merged 3 commits into from
Nov 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/extensions/date.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
extension DateTimeGeneral on DateTime {
List<int> ymd() => [year, month, day];

List<DateTime> dateRange(DateTime endDate) => List.generate(
endDate.difference(this).inDays + 1,
(i) => add(
Duration(days: i),
),
);
}
15 changes: 12 additions & 3 deletions lib/extensions/string.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,26 @@ extension StringDateTime on String {
}

extension StringRegExp on String {
String slugify() =>
replaceAll(RegExp('[^A-Za-z0-9]'), "",).replaceAll(" ", "-").toLowerCase();
String slugify() => replaceAll(
RegExp('[^A-Za-z0-9]'),
"",
).replaceAll(" ", "-").toLowerCase();
}

// Source: https://stackoverflow.com/a/29629114/7313822
extension StringCasingExtension on String {
String toCapitalized() =>
length > 0 ? '${this[0].toUpperCase()}${substring(1).toLowerCase()}' : '';

String toTitleCase() => replaceAll(RegExp(' +'), ' ')
.split(' ')
.map((str) => str.toCapitalized())
.join(' ');
}

extension StringDate on String {
DateTime toDate() {
List<int> newDate = split("-").toList().map(int.parse).toList();
return DateTime(newDate[0], newDate[1], newDate[2]);
}
}
148 changes: 89 additions & 59 deletions lib/screens/schedule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -261,68 +261,98 @@ class _ScheduleScreenState extends State<ScheduleScreen> {
),
sliver: SliverToBoxAdapter(
key: ValueKey(_reloadKey),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
child: schedule.currentPeriodExists
? Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StackedCard(
header: schedule.currentPeriod!.name,
content: schedule.timeRemaining,
),
const SizedBox(height: 10),
],
)
: const SizedBox.shrink(),
),
Container(
child: schedule.nextPeriodExists
? StackedCard(
header: schedule.nextPeriod!.name,
content:
schedule.nextPeriod!.times.start.convertTime(
_hour24Enabled,
),
)
: const SizedBox.shrink(),
),
Container(
child: !schedule.nextPeriodExists &&
!schedule.currentPeriodExists
? Container(
margin: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 5,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
"No Active Period",
style: TextStyle(
fontWeight: FontWeight.w900,
fontSize: 36,
child: schedule.activeOffDay == null
? Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
child: schedule.currentPeriodExists
? Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StackedCard(
header: schedule.currentPeriod!.name,
content: schedule.timeRemaining,
),
const SizedBox(height: 10),
],
)
: const SizedBox.shrink(),
),
Container(
child: schedule.nextPeriodExists
? StackedCard(
header: schedule.nextPeriod!.name,
content: schedule.nextPeriod!.times.start
.convertTime(
_hour24Enabled,
),
)
: const SizedBox.shrink(),
),
Container(
child: !schedule.nextPeriodExists &&
!schedule.currentPeriodExists
? Container(
margin: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 5,
),
),
SizedBox(height: 10),
Text(
"This schedule does not have any periods listed for the current time",
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: 18,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: const [
Text(
"No Active Period",
style: TextStyle(
fontWeight: FontWeight.w900,
fontSize: 36,
),
),
SizedBox(height: 10),
Text(
"This schedule does not have any periods listed for the current time",
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: 18,
),
),
],
),
),
],
)
: const SizedBox.shrink(),
),
],
)
: Container(
margin: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 5,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
schedule.activeOffDay!.name,
style: const TextStyle(
fontWeight: FontWeight.w900,
fontSize: 36,
),
)
: const SizedBox.shrink(),
),
],
),
),
const SizedBox(height: 10),
Text(
schedule.activeOffDay!.endDate == null
? "Enjoy your day off!"
: "Enjoy your break! It ends on ${DateFormat.yMMMMd().format(schedule.activeOffDay!.endDate!)}.",
style: const TextStyle(
fontWeight: FontWeight.w400,
fontSize: 18,
),
),
],
),
),
),
)
],
Expand Down
42 changes: 41 additions & 1 deletion lib/utils/schedule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../extensions/date.dart';
import '../extensions/string.dart';
import '../notification_constants.dart';
import 'notification_service.dart';
Expand Down Expand Up @@ -185,7 +186,7 @@ class Schedule {
if (currentPeriodExists) {
int currentPeriodIndex = daySchedulePeriods.indexWhere(
(period) => currentPeriod!.originalName == period.originalName);

return daySchedulePeriods.length - 1 == currentPeriodIndex
? null
: daySchedulePeriods.elementAt(
Expand All @@ -196,6 +197,24 @@ class Schedule {
return null;
}

List<OffDay> get offDays {
List<OffDay> offDays = [];

for (MapEntry offDay in schedule["offDays"].entries) {
offDays.add(
OffDay(
offDay.key,
offDay.value[0].toString().toDate(),
offDay.value.length == 2 ? offDay.value[1].toString().toDate() : null,
),
);
}

return offDays;
}

OffDay? get activeOffDay => offDays.firstWhere((offDay) => offDay.inEffect);

bool get currentPeriodExists =>
currentPeriod.runtimeType.toString().toLowerCase() != "null";

Expand Down Expand Up @@ -472,3 +491,24 @@ class PeriodTimes {
return "PeriodTimes(\"$start\", \"$end\")";
}
}

class OffDay {
String name;
DateTime startDate;
DateTime? endDate;

OffDay(this.name, this.startDate, this.endDate);

List<DateTime> get dateRange =>
endDate != null ? startDate.dateRange(endDate!) : [startDate];

bool get inEffect {
List<int> ymd = DateTime.now().ymd();
Function eq = const ListEquality().equals;

return dateRange
.map((date) => date.ymd())
.where((date) => eq(date, ymd))
.isNotEmpty;
}
}