diff --git a/lib/screens/account/me/event_calendar.dart b/lib/screens/account/me/event_calendar.dart index d613721..4e28013 100644 --- a/lib/screens/account/me/event_calendar.dart +++ b/lib/screens/account/me/event_calendar.dart @@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/activity.dart'; @@ -13,11 +14,24 @@ import 'package:styled_widget/styled_widget.dart'; import 'package:table_calendar/table_calendar.dart'; part 'event_calendar.g.dart'; +part 'event_calendar.freezed.dart'; + +@freezed +abstract class EventCalendarQuery with _$EventCalendarQuery { + const factory EventCalendarQuery({ + required String? uname, + required int year, + required int month, + }) = _EventCalendarQuery; +} @riverpod -Future> myselfAccountEventCalendar(Ref ref) async { +Future> accountEventCalendar( + Ref ref, + EventCalendarQuery query, +) async { final client = ref.watch(apiClientProvider); - final resp = await client.get('/accounts/me/calendar'); + final resp = await client.get('/accounts/${query.uname ?? 'me'}/calendar'); return resp.data .map((e) => SnEventCalendarEntry.fromJson(e)) .cast() @@ -30,10 +44,21 @@ class MyselfEventCalendarScreen extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final events = ref.watch(myselfAccountEventCalendarProvider); + final selectedMonth = useState(DateTime.now().month); + final selectedYear = useState(DateTime.now().year); final selectedDay = useState(DateTime.now()); + final events = ref.watch( + accountEventCalendarProvider( + EventCalendarQuery( + uname: 'me', + year: selectedYear.value, + month: selectedMonth.value, + ), + ), + ); + return AppScaffold( appBar: AppBar( leading: const PageBackButton(), @@ -41,64 +66,62 @@ class MyselfEventCalendarScreen extends HookConsumerWidget { ), body: Column( children: [ - SizedBox( - height: 340, - child: events.when( - data: (events) { - return TableCalendar( - locale: EasyLocalization.of(context)!.locale.toString(), - firstDay: DateTime.utc(2010, 10, 16), - lastDay: DateTime.utc(2030, 3, 14), - focusedDay: DateTime.now(), - calendarFormat: CalendarFormat.month, - selectedDayPredicate: (day) { - return isSameDay(selectedDay.value, day); - }, - onDaySelected: (value, _) { - selectedDay.value = value; - }, - eventLoader: (day) { - return events - .where((e) => isSameDay(e.date, day)) - .expand((e) => [...e.statuses, e.checkInResult]) - .where((e) => e != null) - .toList(); - }, - calendarBuilders: CalendarBuilders( - dowBuilder: (context, day) { - final text = DateFormat.EEEEE().format(day); - return Center(child: Text(text)); - }, - markerBuilder: (context, day, events) { - var checkInResult = - events.whereType().firstOrNull; - if (checkInResult != null) { - return Positioned( - top: 32, - child: Text( - ['大凶', '凶', '中平', '吉', '大吉'][checkInResult.level], - style: TextStyle( - fontSize: 9, - color: - isSameDay(selectedDay.value, day) - ? Theme.of(context).colorScheme.onPrimary - : Theme.of(context).colorScheme.onSurface, - ), - ), - ); - } - return null; - }, - ), - ); + TableCalendar( + locale: EasyLocalization.of(context)!.locale.toString(), + firstDay: DateTime.now().add(Duration(days: -3650)), + lastDay: DateTime.now().add(Duration(days: 3650)), + focusedDay: DateTime.utc( + selectedYear.value, + selectedMonth.value, + DateTime.now().day, + ), + calendarFormat: CalendarFormat.month, + selectedDayPredicate: (day) { + return isSameDay(selectedDay.value, day); + }, + onDaySelected: (value, _) { + selectedDay.value = value; + }, + onPageChanged: (focusedDay) { + selectedMonth.value = focusedDay.month; + selectedYear.value = focusedDay.year; + }, + eventLoader: (day) { + return events.value + ?.where((e) => isSameDay(e.date, day)) + .expand((e) => [...e.statuses, e.checkInResult]) + .where((e) => e != null) + .toList() ?? + []; + }, + calendarBuilders: CalendarBuilders( + dowBuilder: (context, day) { + final text = DateFormat.EEEEE().format(day); + return Center(child: Text(text)); + }, + markerBuilder: (context, day, events) { + var checkInResult = + events.whereType().firstOrNull; + if (checkInResult != null) { + return Positioned( + top: 32, + child: Text( + ['大凶', '凶', '中平', '吉', '大吉'][checkInResult.level], + style: TextStyle( + fontSize: 9, + color: + isSameDay(selectedDay.value, day) + ? Theme.of(context).colorScheme.onPrimary + : Theme.of(context).colorScheme.onSurface, + ), + ), + ); + } + return null; }, - loading: () => const Center(child: CircularProgressIndicator()), - error: - (error, stack) => - Center(child: Text('Error loading calendar: $error')), ), ), - const Divider(height: 1), + const Divider(height: 1).padding(top: 8), AnimatedSwitcher( duration: const Duration(milliseconds: 300), child: Builder( @@ -107,30 +130,27 @@ class MyselfEventCalendarScreen extends HookConsumerWidget { events.value ?.where((e) => isSameDay(e.date, selectedDay.value)) .firstOrNull; - if (event == null) { - return Center(child: Text('eventCalanderEmpty').tr()); - } return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text(DateFormat.EEEE().format(event.date)) + Text(DateFormat.EEEE().format(selectedDay.value)) .fontSize(16) .bold() .textColor( Theme.of(context).colorScheme.onSecondaryContainer, ), - Text(DateFormat.yMd().format(event.date)) + Text(DateFormat.yMd().format(selectedDay.value)) .fontSize(12) .textColor( Theme.of(context).colorScheme.onSecondaryContainer, ), const Gap(16), - if (event.checkInResult != null) + if (event?.checkInResult != null) Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( - 'checkInResultLevel${event.checkInResult!.level}', + 'checkInResultLevel${event!.checkInResult!.level}', ).tr().fontSize(16).bold(), for (final tip in event.checkInResult!.tips) Row( @@ -156,7 +176,8 @@ class MyselfEventCalendarScreen extends HookConsumerWidget { ).padding(top: 8), ], ), - if (event.checkInResult == null && event.statuses.isEmpty) + if (event?.checkInResult == null && + (event?.statuses.isEmpty ?? true)) Text('eventCalanderEmpty').tr(), ], ).padding(vertical: 24, horizontal: 24); diff --git a/lib/screens/account/me/event_calendar.freezed.dart b/lib/screens/account/me/event_calendar.freezed.dart new file mode 100644 index 0000000..023e078 --- /dev/null +++ b/lib/screens/account/me/event_calendar.freezed.dart @@ -0,0 +1,148 @@ +// dart format width=80 +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'event_calendar.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$EventCalendarQuery { + + String? get uname; int get year; int get month; +/// Create a copy of EventCalendarQuery +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$EventCalendarQueryCopyWith get copyWith => _$EventCalendarQueryCopyWithImpl(this as EventCalendarQuery, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is EventCalendarQuery&&(identical(other.uname, uname) || other.uname == uname)&&(identical(other.year, year) || other.year == year)&&(identical(other.month, month) || other.month == month)); +} + + +@override +int get hashCode => Object.hash(runtimeType,uname,year,month); + +@override +String toString() { + return 'EventCalendarQuery(uname: $uname, year: $year, month: $month)'; +} + + +} + +/// @nodoc +abstract mixin class $EventCalendarQueryCopyWith<$Res> { + factory $EventCalendarQueryCopyWith(EventCalendarQuery value, $Res Function(EventCalendarQuery) _then) = _$EventCalendarQueryCopyWithImpl; +@useResult +$Res call({ + String? uname, int year, int month +}); + + + + +} +/// @nodoc +class _$EventCalendarQueryCopyWithImpl<$Res> + implements $EventCalendarQueryCopyWith<$Res> { + _$EventCalendarQueryCopyWithImpl(this._self, this._then); + + final EventCalendarQuery _self; + final $Res Function(EventCalendarQuery) _then; + +/// Create a copy of EventCalendarQuery +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? uname = freezed,Object? year = null,Object? month = null,}) { + return _then(_self.copyWith( +uname: freezed == uname ? _self.uname : uname // ignore: cast_nullable_to_non_nullable +as String?,year: null == year ? _self.year : year // ignore: cast_nullable_to_non_nullable +as int,month: null == month ? _self.month : month // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// @nodoc + + +class _EventCalendarQuery implements EventCalendarQuery { + const _EventCalendarQuery({required this.uname, required this.year, required this.month}); + + +@override final String? uname; +@override final int year; +@override final int month; + +/// Create a copy of EventCalendarQuery +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$EventCalendarQueryCopyWith<_EventCalendarQuery> get copyWith => __$EventCalendarQueryCopyWithImpl<_EventCalendarQuery>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _EventCalendarQuery&&(identical(other.uname, uname) || other.uname == uname)&&(identical(other.year, year) || other.year == year)&&(identical(other.month, month) || other.month == month)); +} + + +@override +int get hashCode => Object.hash(runtimeType,uname,year,month); + +@override +String toString() { + return 'EventCalendarQuery(uname: $uname, year: $year, month: $month)'; +} + + +} + +/// @nodoc +abstract mixin class _$EventCalendarQueryCopyWith<$Res> implements $EventCalendarQueryCopyWith<$Res> { + factory _$EventCalendarQueryCopyWith(_EventCalendarQuery value, $Res Function(_EventCalendarQuery) _then) = __$EventCalendarQueryCopyWithImpl; +@override @useResult +$Res call({ + String? uname, int year, int month +}); + + + + +} +/// @nodoc +class __$EventCalendarQueryCopyWithImpl<$Res> + implements _$EventCalendarQueryCopyWith<$Res> { + __$EventCalendarQueryCopyWithImpl(this._self, this._then); + + final _EventCalendarQuery _self; + final $Res Function(_EventCalendarQuery) _then; + +/// Create a copy of EventCalendarQuery +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? uname = freezed,Object? year = null,Object? month = null,}) { + return _then(_EventCalendarQuery( +uname: freezed == uname ? _self.uname : uname // ignore: cast_nullable_to_non_nullable +as String?,year: null == year ? _self.year : year // ignore: cast_nullable_to_non_nullable +as int,month: null == month ? _self.month : month // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/lib/screens/account/me/event_calendar.g.dart b/lib/screens/account/me/event_calendar.g.dart index 489809e..01d8726 100644 --- a/lib/screens/account/me/event_calendar.g.dart +++ b/lib/screens/account/me/event_calendar.g.dart @@ -6,26 +6,155 @@ part of 'event_calendar.dart'; // RiverpodGenerator // ************************************************************************** -String _$myselfAccountEventCalendarHash() => - r'd3faad342d5104e87ff6597ab459e65cb5f4ef97'; +String _$accountEventCalendarHash() => + r'57405caaf53a83d121b6bb4b70540134fb581525'; -/// See also [myselfAccountEventCalendar]. -@ProviderFor(myselfAccountEventCalendar) -final myselfAccountEventCalendarProvider = - AutoDisposeFutureProvider>.internal( - myselfAccountEventCalendar, - name: r'myselfAccountEventCalendarProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') - ? null - : _$myselfAccountEventCalendarHash, - dependencies: null, - allTransitiveDependencies: null, +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// See also [accountEventCalendar]. +@ProviderFor(accountEventCalendar) +const accountEventCalendarProvider = AccountEventCalendarFamily(); + +/// See also [accountEventCalendar]. +class AccountEventCalendarFamily + extends Family>> { + /// See also [accountEventCalendar]. + const AccountEventCalendarFamily(); + + /// See also [accountEventCalendar]. + AccountEventCalendarProvider call(EventCalendarQuery query) { + return AccountEventCalendarProvider(query); + } + + @override + AccountEventCalendarProvider getProviderOverride( + covariant AccountEventCalendarProvider provider, + ) { + return call(provider.query); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'accountEventCalendarProvider'; +} + +/// See also [accountEventCalendar]. +class AccountEventCalendarProvider + extends AutoDisposeFutureProvider> { + /// See also [accountEventCalendar]. + AccountEventCalendarProvider(EventCalendarQuery query) + : this._internal( + (ref) => accountEventCalendar(ref as AccountEventCalendarRef, query), + from: accountEventCalendarProvider, + name: r'accountEventCalendarProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$accountEventCalendarHash, + dependencies: AccountEventCalendarFamily._dependencies, + allTransitiveDependencies: + AccountEventCalendarFamily._allTransitiveDependencies, + query: query, + ); + + AccountEventCalendarProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.query, + }) : super.internal(); + + final EventCalendarQuery query; + + @override + Override overrideWith( + FutureOr> Function( + AccountEventCalendarRef provider, + ) + create, + ) { + return ProviderOverride( + origin: this, + override: AccountEventCalendarProvider._internal( + (ref) => create(ref as AccountEventCalendarRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + query: query, + ), ); + } + + @override + AutoDisposeFutureProviderElement> createElement() { + return _AccountEventCalendarProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is AccountEventCalendarProvider && other.query == query; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, query.hashCode); + + return _SystemHash.finish(hash); + } +} @Deprecated('Will be removed in 3.0. Use Ref instead') // ignore: unused_element -typedef MyselfAccountEventCalendarRef = - AutoDisposeFutureProviderRef>; +mixin AccountEventCalendarRef + on AutoDisposeFutureProviderRef> { + /// The parameter `query` of this provider. + EventCalendarQuery get query; +} + +class _AccountEventCalendarProviderElement + extends AutoDisposeFutureProviderElement> + with AccountEventCalendarRef { + _AccountEventCalendarProviderElement(super.provider); + + @override + EventCalendarQuery get query => + (origin as AccountEventCalendarProvider).query; +} + // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package