mirror of
https://github.com/Myzel394/quid_faciam_hodie.git
synced 2025-06-18 23:35:25 +02:00
185 lines
5.6 KiB
Dart
185 lines
5.6 KiB
Dart
import 'dart:math';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_calendar_widget/flutter_calendar_widget.dart';
|
|
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
|
import 'package:quid_faciam_hodie/constants/values.dart';
|
|
import 'package:quid_faciam_hodie/extensions/date.dart';
|
|
import 'package:quid_faciam_hodie/screens/timeline_screen.dart';
|
|
import 'package:quid_faciam_hodie/widgets/delay_render.dart';
|
|
import 'package:quid_faciam_hodie/widgets/fade_and_move_in_animation.dart';
|
|
|
|
class MonthCalendarBuilder extends CalendarBuilder {
|
|
@override
|
|
Widget buildDayOfWeek(DateTime dateTime, String weekdayString) {
|
|
return const SizedBox.shrink();
|
|
}
|
|
|
|
@override
|
|
Widget buildHeader(VoidCallback onLeftTap, VoidCallback onRightTap,
|
|
DateTime dateTime, String locale) {
|
|
final month = DateFormat.yMMMM(locale).format(dateTime);
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: MEDIUM_SPACE),
|
|
child: Text(month, style: textStyle.headerTextStyle),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget buildDate(DateTime dateTime, DateType type, List events) {
|
|
final backgroundPercentage = () {
|
|
if (events.isEmpty) {
|
|
return 0.0;
|
|
}
|
|
|
|
final highestAmountOfEvents = events[0];
|
|
final amount = events[1];
|
|
return amount / highestAmountOfEvents;
|
|
}();
|
|
|
|
final delay = Duration(
|
|
microseconds: Random().nextInt(CALENDAR_DATE_IN_MAX_DELAY.inMicroseconds),
|
|
);
|
|
|
|
return DelayRender(
|
|
delay: delay,
|
|
child: FadeAndMoveInAnimation(
|
|
opacityDuration:
|
|
DEFAULT_OPACITY_DURATION * CALENDAR_DATE_IN_DURATION_MULTIPLIER,
|
|
translationDuration:
|
|
DEFAULT_TRANSLATION_DURATION * CALENDAR_DATE_IN_DURATION_MULTIPLIER,
|
|
translationOffset: const Offset(0.0, -MEDIUM_SPACE),
|
|
child: Opacity(
|
|
opacity: () {
|
|
if (type.isOutSide) {
|
|
return 0.0;
|
|
}
|
|
|
|
if (dateTime.isAfter(DateTime.now())) {
|
|
return 0.4;
|
|
}
|
|
|
|
return 1.0;
|
|
}(),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(TINY_SPACE),
|
|
child: ClipRRect(
|
|
borderRadius: BorderRadius.circular(SMALL_SPACE),
|
|
child: Stack(
|
|
alignment: style.dayAlignment,
|
|
children: [
|
|
SizedBox(
|
|
child: Container(
|
|
color: textStyle.selectedDayTextColor
|
|
.withOpacity(backgroundPercentage),
|
|
),
|
|
),
|
|
Container(
|
|
alignment: Alignment.center,
|
|
child: Text(
|
|
dateTime.day.toString(),
|
|
style: TextStyle(
|
|
color: backgroundPercentage > .5
|
|
? textStyle.focusedDayTextColor
|
|
: textStyle.dayTextColor,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class CalendarMonth extends StatelessWidget {
|
|
final Map<DateTime, int> dayAmountMap;
|
|
final int year;
|
|
final int month;
|
|
|
|
const CalendarMonth({
|
|
Key? key,
|
|
required this.dayAmountMap,
|
|
required this.year,
|
|
required this.month,
|
|
}) : super(key: key);
|
|
|
|
int get highestAmount =>
|
|
dayAmountMap.values.isEmpty ? 0 : dayAmountMap.values.reduce(max);
|
|
DateTime get firstDate => DateTime(year, month, 1);
|
|
DateTime get lastDate =>
|
|
DateTime(year, month, DateUtils.getDaysInMonth(year, month));
|
|
bool doesDateExist(final DateTime date) =>
|
|
dayAmountMap.keys.contains(date.asNormalizedDate());
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return FlutterCalendar(
|
|
focusedDate: firstDate,
|
|
selectionMode: CalendarSelectionMode.single,
|
|
calendarBuilder: MonthCalendarBuilder(),
|
|
events: EventList(events: {
|
|
DateTime(1990, 1, 1): [
|
|
highestAmount,
|
|
],
|
|
...Map.fromEntries(
|
|
dayAmountMap.entries.map((entry) {
|
|
return MapEntry(
|
|
entry.key,
|
|
[highestAmount, entry.value],
|
|
);
|
|
}),
|
|
),
|
|
}),
|
|
minDate: firstDate,
|
|
maxDate: lastDate,
|
|
startingDayOfWeek: DayOfWeek.mon,
|
|
onDayPressed: (date) {
|
|
if (!doesDateExist(date)) {
|
|
return;
|
|
}
|
|
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => TimelineScreen(date: date),
|
|
),
|
|
);
|
|
},
|
|
style: const CalendarStyle(
|
|
calenderMargin: EdgeInsets.symmetric(vertical: MEDIUM_SPACE),
|
|
),
|
|
textStyle: CalendarTextStyle(
|
|
headerTextStyle: platformThemeData(
|
|
context,
|
|
material: (data) => data.textTheme.subtitle1!,
|
|
cupertino: (data) => data.textTheme.navTitleTextStyle,
|
|
),
|
|
dayTextColor: platformThemeData(
|
|
context,
|
|
material: (data) => data.textTheme.bodyText1!.color!,
|
|
cupertino: (data) => data.textTheme.textStyle.color!,
|
|
),
|
|
// Background color
|
|
selectedDayTextColor: platformThemeData(
|
|
context,
|
|
material: (data) => data.textTheme.bodyText1!.color!,
|
|
cupertino: (data) => data.textTheme.textStyle.color!,
|
|
),
|
|
// Foreground color
|
|
focusedDayTextColor: platformThemeData(
|
|
context,
|
|
material: (data) => data.dialogBackgroundColor,
|
|
cupertino: (data) => data.barBackgroundColor,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|