mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-19 13:13:44 +02:00
feat: add calendar view without interaction
This commit is contained in:
parent
fa1d9504f5
commit
bb01592f54
5 changed files with 452 additions and 5 deletions
|
@ -16,6 +16,7 @@ class AvailabilityOptions {
|
||||||
this.primaryButtonBuilder = DefaultPrimaryButton.builder,
|
this.primaryButtonBuilder = DefaultPrimaryButton.builder,
|
||||||
this.textButtonBuilder = DefaultTextButton.builder,
|
this.textButtonBuilder = DefaultTextButton.builder,
|
||||||
this.spacing = const AvailabilitySpacing(),
|
this.spacing = const AvailabilitySpacing(),
|
||||||
|
this.colors = const AvailabilityColors(),
|
||||||
AvailabilityDataInterface? dataInterface,
|
AvailabilityDataInterface? dataInterface,
|
||||||
}) : dataInterface = dataInterface ?? LocalAvailabilityDataInterface();
|
}) : dataInterface = dataInterface ?? LocalAvailabilityDataInterface();
|
||||||
|
|
||||||
|
@ -40,6 +41,9 @@ class AvailabilityOptions {
|
||||||
|
|
||||||
/// The spacing between elements
|
/// The spacing between elements
|
||||||
final AvailabilitySpacing spacing;
|
final AvailabilitySpacing spacing;
|
||||||
|
|
||||||
|
/// The colors used in the userstory
|
||||||
|
final AvailabilityColors colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All configurable paddings and whitespaces withing the userstory
|
/// All configurable paddings and whitespaces withing the userstory
|
||||||
|
@ -57,6 +61,46 @@ class AvailabilitySpacing {
|
||||||
final double sidePadding;
|
final double sidePadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Contains all the customizable colors for the availability userstory
|
||||||
|
///
|
||||||
|
/// If colors are not provided the colors will be taken from the theme
|
||||||
|
class AvailabilityColors {
|
||||||
|
/// Constructor for the AvailabilityColors
|
||||||
|
///
|
||||||
|
/// If a color is not provided the color will be taken from the theme
|
||||||
|
const AvailabilityColors({
|
||||||
|
this.selectedDayColor,
|
||||||
|
this.blankDayColor,
|
||||||
|
this.outsideMonthTextColor,
|
||||||
|
this.textDarkColor,
|
||||||
|
this.textLightColor,
|
||||||
|
this.templateColors,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// The color of the text for the days that are not in the current month
|
||||||
|
final Color? outsideMonthTextColor;
|
||||||
|
|
||||||
|
/// The background color of the days that are selected in the calendar
|
||||||
|
final Color? selectedDayColor;
|
||||||
|
|
||||||
|
/// The background color of the days in the current month
|
||||||
|
/// that have no availability and are not selected
|
||||||
|
final Color? blankDayColor;
|
||||||
|
|
||||||
|
/// The color of the text in the calendar when the background has a dark color
|
||||||
|
/// This is used to make sure the text is readable on dark backgrounds
|
||||||
|
/// If not provided the text color will be white
|
||||||
|
final Color? textLightColor;
|
||||||
|
|
||||||
|
/// The color of the text in the calendar when the background has a light
|
||||||
|
/// color. This is used to make sure the text is readable on light backgrounds
|
||||||
|
/// If not provided the text color will be the theme's text color
|
||||||
|
final Color? textDarkColor;
|
||||||
|
|
||||||
|
/// The colors that are used for the templates
|
||||||
|
final List<Color>? templateColors;
|
||||||
|
}
|
||||||
|
|
||||||
/// Builder definition for providing a base screen surrounding each page
|
/// Builder definition for providing a base screen surrounding each page
|
||||||
typedef BaseScreenBuilder = Widget Function(
|
typedef BaseScreenBuilder = Widget Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
import "package:flutter/material.dart";
|
||||||
|
|
||||||
/// Class that holds all translatable strings for the availability userstory
|
/// Class that holds all translatable strings for the availability userstory
|
||||||
class AvailabilityTranslations {
|
class AvailabilityTranslations {
|
||||||
/// AvailabilityTranslations constructor where everything is required.
|
/// AvailabilityTranslations constructor where everything is required.
|
||||||
|
@ -14,6 +16,8 @@ class AvailabilityTranslations {
|
||||||
required this.templateLegendTitle,
|
required this.templateLegendTitle,
|
||||||
required this.overviewScreenTitle,
|
required this.overviewScreenTitle,
|
||||||
required this.createTemplateButton,
|
required this.createTemplateButton,
|
||||||
|
required this.monthYearFormatter,
|
||||||
|
required this.weekDayAbbreviatedFormatter,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// AvailabilityTranslations constructor where everything is optional.
|
/// AvailabilityTranslations constructor where everything is optional.
|
||||||
|
@ -24,6 +28,8 @@ class AvailabilityTranslations {
|
||||||
this.templateLegendTitle = "Templates",
|
this.templateLegendTitle = "Templates",
|
||||||
this.createTemplateButton = "Create a new template",
|
this.createTemplateButton = "Create a new template",
|
||||||
this.overviewScreenTitle = "Availability",
|
this.overviewScreenTitle = "Availability",
|
||||||
|
this.monthYearFormatter = _defaultMonthYearFormatter,
|
||||||
|
this.weekDayAbbreviatedFormatter = _defaultWeekDayAbbreviatedFormatter,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The title shown above the calendar
|
/// The title shown above the calendar
|
||||||
|
@ -40,4 +46,51 @@ class AvailabilityTranslations {
|
||||||
|
|
||||||
/// The label on the button to go to the tempalte creation page
|
/// The label on the button to go to the tempalte creation page
|
||||||
final String createTemplateButton;
|
final String createTemplateButton;
|
||||||
|
|
||||||
|
/// Gets the month and year formatted as a string
|
||||||
|
///
|
||||||
|
/// The default implementation is `MonthName Year` in english
|
||||||
|
final String Function(BuildContext, DateTime) monthYearFormatter;
|
||||||
|
|
||||||
|
/// Gets the abbreviated name of a weekday
|
||||||
|
///
|
||||||
|
/// The default implementation is the first 2 letters of
|
||||||
|
/// the weekday in english
|
||||||
|
final String Function(BuildContext, DateTime) weekDayAbbreviatedFormatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _defaultWeekDayAbbreviatedFormatter(
|
||||||
|
BuildContext context,
|
||||||
|
DateTime date,
|
||||||
|
) =>
|
||||||
|
_getWeekDayAbbreviation(date.weekday);
|
||||||
|
|
||||||
|
String _defaultMonthYearFormatter(BuildContext context, DateTime date) =>
|
||||||
|
"${_getMonthName(date.month)} ${date.year}";
|
||||||
|
|
||||||
|
String _getWeekDayAbbreviation(int weekday) => switch (weekday) {
|
||||||
|
1 => "Mo",
|
||||||
|
2 => "Tu",
|
||||||
|
3 => "We",
|
||||||
|
4 => "Th",
|
||||||
|
5 => "Fr",
|
||||||
|
6 => "Sa",
|
||||||
|
7 => "Su",
|
||||||
|
_ => "",
|
||||||
|
};
|
||||||
|
|
||||||
|
String _getMonthName(int month) => switch (month) {
|
||||||
|
1 => "January",
|
||||||
|
2 => "February",
|
||||||
|
3 => "March",
|
||||||
|
4 => "April",
|
||||||
|
5 => "May",
|
||||||
|
6 => "June",
|
||||||
|
7 => "July",
|
||||||
|
8 => "August",
|
||||||
|
9 => "September",
|
||||||
|
10 => "October",
|
||||||
|
11 => "November",
|
||||||
|
12 => "December",
|
||||||
|
_ => "",
|
||||||
|
};
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter_availability/src/ui/widgets/calendar.dart";
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
|
||||||
///
|
///
|
||||||
class AvailabilityOverview extends StatelessWidget {
|
class AvailabilityOverview extends StatefulWidget {
|
||||||
///
|
///
|
||||||
const AvailabilityOverview({
|
const AvailabilityOverview({
|
||||||
required this.onEditDateRange,
|
required this.onEditDateRange,
|
||||||
|
@ -20,6 +21,13 @@ class AvailabilityOverview extends StatelessWidget {
|
||||||
/// Callback invoked when a user attempts to go back
|
/// Callback invoked when a user attempts to go back
|
||||||
final VoidCallback onBack;
|
final VoidCallback onBack;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AvailabilityOverview> createState() => _AvailabilityOverviewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AvailabilityOverviewState extends State<AvailabilityOverview> {
|
||||||
|
DateTime _selectedDate = DateTime.now();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
|
@ -35,9 +43,13 @@ class AvailabilityOverview extends StatelessWidget {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const calendar = SizedBox(
|
var calendar = CalendarView(
|
||||||
height: 320,
|
month: _selectedDate,
|
||||||
child: Placeholder(),
|
onMonthChanged: (month) {
|
||||||
|
setState(() {
|
||||||
|
_selectedDate = month;
|
||||||
|
});
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const templateLegend = SizedBox(
|
const templateLegend = SizedBox(
|
||||||
|
@ -48,7 +60,9 @@ class AvailabilityOverview extends StatelessWidget {
|
||||||
var startEditButton = options.primaryButtonBuilder(
|
var startEditButton = options.primaryButtonBuilder(
|
||||||
context,
|
context,
|
||||||
() {
|
() {
|
||||||
onEditDateRange(DateTimeRange(start: DateTime(1), end: DateTime(2)));
|
widget.onEditDateRange(
|
||||||
|
DateTimeRange(start: DateTime(1), end: DateTime(2)),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
Text(translations.editAvailabilityButton),
|
Text(translations.editAvailabilityButton),
|
||||||
);
|
);
|
||||||
|
|
107
packages/flutter_availability/lib/src/ui/widgets/calendar.dart
Normal file
107
packages/flutter_availability/lib/src/ui/widgets/calendar.dart
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter_availability/src/ui/widgets/calendar_grid.dart";
|
||||||
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
|
||||||
|
///
|
||||||
|
class CalendarView extends StatelessWidget {
|
||||||
|
///
|
||||||
|
const CalendarView({
|
||||||
|
required this.month,
|
||||||
|
required this.onMonthChanged,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
///
|
||||||
|
final DateTime month;
|
||||||
|
|
||||||
|
///
|
||||||
|
final void Function(DateTime month) onMonthChanged;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
|
var options = availabilityScope.options;
|
||||||
|
var translations = options.translations;
|
||||||
|
|
||||||
|
var monthDateSelector = Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.chevron_left),
|
||||||
|
onPressed: () {
|
||||||
|
onMonthChanged(DateTime(month.year, month.month - 1));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(width: 44),
|
||||||
|
Text(
|
||||||
|
translations.monthYearFormatter(context, month),
|
||||||
|
style: theme.textTheme.bodyLarge,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 44),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.chevron_right),
|
||||||
|
onPressed: () {
|
||||||
|
onMonthChanged(DateTime(month.year, month.month + 1));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
var calendarGrid = CalendarGrid(
|
||||||
|
month: month,
|
||||||
|
days: [
|
||||||
|
CalendarDay(
|
||||||
|
date: DateTime(month.year, month.month, 3),
|
||||||
|
isSelected: false,
|
||||||
|
color: Colors.red,
|
||||||
|
templateDeviation: false,
|
||||||
|
),
|
||||||
|
CalendarDay(
|
||||||
|
date: DateTime(month.year, month.month, 4),
|
||||||
|
isSelected: false,
|
||||||
|
color: Colors.red,
|
||||||
|
templateDeviation: true,
|
||||||
|
),
|
||||||
|
CalendarDay(
|
||||||
|
date: DateTime(month.year, month.month, 10),
|
||||||
|
isSelected: false,
|
||||||
|
color: Colors.blue,
|
||||||
|
templateDeviation: false,
|
||||||
|
),
|
||||||
|
CalendarDay(
|
||||||
|
date: DateTime(month.year, month.month, 11),
|
||||||
|
isSelected: false,
|
||||||
|
color: Colors.black,
|
||||||
|
templateDeviation: true,
|
||||||
|
),
|
||||||
|
CalendarDay(
|
||||||
|
date: DateTime(month.year, month.month, 12),
|
||||||
|
isSelected: false,
|
||||||
|
color: Colors.white,
|
||||||
|
templateDeviation: true,
|
||||||
|
),
|
||||||
|
CalendarDay(
|
||||||
|
date: DateTime(month.year, month.month, 13),
|
||||||
|
isSelected: true,
|
||||||
|
color: Colors.green,
|
||||||
|
templateDeviation: false,
|
||||||
|
),
|
||||||
|
CalendarDay(
|
||||||
|
date: DateTime(month.year, month.month, 14),
|
||||||
|
isSelected: true,
|
||||||
|
color: Colors.green,
|
||||||
|
templateDeviation: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
monthDateSelector,
|
||||||
|
const Divider(),
|
||||||
|
calendarGrid,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,229 @@
|
||||||
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter_availability/flutter_availability.dart";
|
||||||
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
|
||||||
|
///
|
||||||
|
class CalendarGrid extends StatelessWidget {
|
||||||
|
///
|
||||||
|
const CalendarGrid({
|
||||||
|
required this.month,
|
||||||
|
required this.days,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// The current month to display
|
||||||
|
final DateTime month;
|
||||||
|
|
||||||
|
/// A list of days that need to be displayed differently
|
||||||
|
final List<CalendarDay> days;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
var textTheme = theme.textTheme;
|
||||||
|
var colorScheme = theme.colorScheme;
|
||||||
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
|
var options = availabilityScope.options;
|
||||||
|
var colors = options.colors;
|
||||||
|
var translations = options.translations;
|
||||||
|
var calendarDays = _generateCalendarDays(month, days, colors, colorScheme);
|
||||||
|
|
||||||
|
// get the names of the days of the week
|
||||||
|
var dayNames = List.generate(7, (index) {
|
||||||
|
var day = DateTime(2024, 7, 8 + index); // this is a monday
|
||||||
|
return translations.weekDayAbbreviatedFormatter(context, day);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: dayNames
|
||||||
|
.map(
|
||||||
|
(day) => Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
day,
|
||||||
|
style: textTheme.bodyLarge,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4.0),
|
||||||
|
GridView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount: calendarDays.length,
|
||||||
|
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: 7,
|
||||||
|
crossAxisSpacing: 12,
|
||||||
|
mainAxisSpacing: 12,
|
||||||
|
),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
var day = calendarDays[index];
|
||||||
|
var textColor = day.outsideMonth
|
||||||
|
? colors.outsideMonthTextColor ?? colorScheme.onSurface
|
||||||
|
: _getTextColor(
|
||||||
|
day.color,
|
||||||
|
colors.textLightColor ?? Colors.white,
|
||||||
|
colors.textDarkColor,
|
||||||
|
);
|
||||||
|
var textStyle = textTheme.bodyLarge?.copyWith(color: textColor);
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
// Handle day tap here
|
||||||
|
},
|
||||||
|
child: DecoratedBox(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: day.outsideMonth ? Colors.transparent : day.color,
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
border: Border.all(
|
||||||
|
color: day.isSelected
|
||||||
|
? colorScheme.primary
|
||||||
|
: Colors.transparent,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Center(
|
||||||
|
child: Text(day.date.day.toString(), style: textStyle),
|
||||||
|
),
|
||||||
|
if (day.templateDeviation) ...[
|
||||||
|
Positioned(
|
||||||
|
right: 4,
|
||||||
|
child: Text("*", style: textStyle),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A Special day in the calendar that needs to be displayed differently
|
||||||
|
class CalendarDay {
|
||||||
|
///
|
||||||
|
const CalendarDay({
|
||||||
|
required this.date,
|
||||||
|
required this.isSelected,
|
||||||
|
required this.color,
|
||||||
|
required this.templateDeviation,
|
||||||
|
this.outsideMonth = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// The date of the day
|
||||||
|
final DateTime date;
|
||||||
|
|
||||||
|
/// Whether the day is selected or not
|
||||||
|
final bool isSelected;
|
||||||
|
|
||||||
|
/// The color of the day
|
||||||
|
final Color color;
|
||||||
|
|
||||||
|
/// Whether there is an availability on this day and it deviates from the
|
||||||
|
/// used template
|
||||||
|
final bool templateDeviation;
|
||||||
|
|
||||||
|
/// Whether the day is outside of the current month
|
||||||
|
final bool outsideMonth;
|
||||||
|
|
||||||
|
/// Creates a copy of the current day with the provided values
|
||||||
|
CalendarDay copyWith({
|
||||||
|
DateTime? date,
|
||||||
|
bool? isSelected,
|
||||||
|
Color? color,
|
||||||
|
bool? templateDeviation,
|
||||||
|
bool? outsideMonth,
|
||||||
|
}) =>
|
||||||
|
CalendarDay(
|
||||||
|
date: date ?? this.date,
|
||||||
|
isSelected: isSelected ?? this.isSelected,
|
||||||
|
color: color ?? this.color,
|
||||||
|
templateDeviation: templateDeviation ?? this.templateDeviation,
|
||||||
|
outsideMonth: outsideMonth ?? this.outsideMonth,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CalendarDay> _generateCalendarDays(
|
||||||
|
DateTime month,
|
||||||
|
List<CalendarDay> days,
|
||||||
|
AvailabilityColors colors,
|
||||||
|
ColorScheme colorScheme,
|
||||||
|
) {
|
||||||
|
var firstDayOfMonth = DateTime(month.year, month.month, 1);
|
||||||
|
var lastDayOfMonth = DateTime(month.year, month.month + 1, 0);
|
||||||
|
var daysInMonth = lastDayOfMonth.day;
|
||||||
|
var startWeekday = firstDayOfMonth.weekday;
|
||||||
|
var endWeekday = lastDayOfMonth.weekday;
|
||||||
|
|
||||||
|
var calendarDays = <CalendarDay>[];
|
||||||
|
|
||||||
|
// Add days from the previous month
|
||||||
|
for (var i = 0; i < startWeekday - 1; i++) {
|
||||||
|
var prevDay =
|
||||||
|
firstDayOfMonth.subtract(Duration(days: startWeekday - 1 - i));
|
||||||
|
calendarDays.add(
|
||||||
|
CalendarDay(
|
||||||
|
date: prevDay,
|
||||||
|
isSelected: false,
|
||||||
|
color: Colors.transparent,
|
||||||
|
templateDeviation: false,
|
||||||
|
outsideMonth: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add days of the current month
|
||||||
|
for (var i = 1; i <= daysInMonth; i++) {
|
||||||
|
var day = DateTime(month.year, month.month, i);
|
||||||
|
var specialDay = days.firstWhere(
|
||||||
|
(d) =>
|
||||||
|
d.date.day == i &&
|
||||||
|
d.date.month == month.month &&
|
||||||
|
d.date.year == month.year,
|
||||||
|
orElse: () => CalendarDay(
|
||||||
|
date: day,
|
||||||
|
isSelected: false,
|
||||||
|
color: colors.blankDayColor ?? colorScheme.surfaceDim,
|
||||||
|
templateDeviation: false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// if the day is selected we need to change the color
|
||||||
|
specialDay = specialDay.copyWith(
|
||||||
|
color: specialDay.isSelected
|
||||||
|
? colors.selectedDayColor ?? colorScheme.primaryFixedDim
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
calendarDays.add(specialDay);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add days from the next month
|
||||||
|
for (var i = endWeekday; i < 7; i++) {
|
||||||
|
var nextDay = lastDayOfMonth.add(Duration(days: i - endWeekday + 1));
|
||||||
|
calendarDays.add(
|
||||||
|
CalendarDay(
|
||||||
|
date: nextDay,
|
||||||
|
isSelected: false,
|
||||||
|
color: Colors.transparent,
|
||||||
|
templateDeviation: false,
|
||||||
|
outsideMonth: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return calendarDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color? _getTextColor(
|
||||||
|
Color backgroundColor,
|
||||||
|
Color lightColor,
|
||||||
|
Color? darkColor,
|
||||||
|
) =>
|
||||||
|
backgroundColor.computeLuminance() > 0.5 ? darkColor : lightColor;
|
Loading…
Reference in a new issue