Event Calander

This commit is contained in:
LittleSheep 2025-05-09 01:40:56 +08:00
parent ec2233fbaf
commit 50fb25ef12
11 changed files with 508 additions and 74 deletions

View File

@ -113,5 +113,7 @@
"checkInResultLevel1": "Bad Luck",
"checkInResultLevel2": "A Normal Day",
"checkInResultLevel3": "Good Luck",
"checkInResultLevel4": "Best Luck"
"checkInResultLevel4": "Best Luck",
"eventCalander": "Event Calander",
"eventCalanderEmpty": "No events on that day."
}

View File

@ -51,3 +51,15 @@ abstract class SnFortuneTip with _$SnFortuneTip {
factory SnFortuneTip.fromJson(Map<String, dynamic> json) =>
_$SnFortuneTipFromJson(json);
}
@freezed
abstract class SnEventCalendarEntry with _$SnEventCalendarEntry {
const factory SnEventCalendarEntry({
required DateTime date,
required SnCheckInResult? checkInResult,
required List<dynamic> statuses,
}) = _SnEventCalendarEntry;
factory SnEventCalendarEntry.fromJson(Map<String, dynamic> json) =>
_$SnEventCalendarEntryFromJson(json);
}

View File

@ -513,4 +513,173 @@ as String,
}
/// @nodoc
mixin _$SnEventCalendarEntry {
DateTime get date; SnCheckInResult? get checkInResult; List<dynamic> get statuses;
/// Create a copy of SnEventCalendarEntry
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$SnEventCalendarEntryCopyWith<SnEventCalendarEntry> get copyWith => _$SnEventCalendarEntryCopyWithImpl<SnEventCalendarEntry>(this as SnEventCalendarEntry, _$identity);
/// Serializes this SnEventCalendarEntry to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnEventCalendarEntry&&(identical(other.date, date) || other.date == date)&&(identical(other.checkInResult, checkInResult) || other.checkInResult == checkInResult)&&const DeepCollectionEquality().equals(other.statuses, statuses));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,date,checkInResult,const DeepCollectionEquality().hash(statuses));
@override
String toString() {
return 'SnEventCalendarEntry(date: $date, checkInResult: $checkInResult, statuses: $statuses)';
}
}
/// @nodoc
abstract mixin class $SnEventCalendarEntryCopyWith<$Res> {
factory $SnEventCalendarEntryCopyWith(SnEventCalendarEntry value, $Res Function(SnEventCalendarEntry) _then) = _$SnEventCalendarEntryCopyWithImpl;
@useResult
$Res call({
DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses
});
$SnCheckInResultCopyWith<$Res>? get checkInResult;
}
/// @nodoc
class _$SnEventCalendarEntryCopyWithImpl<$Res>
implements $SnEventCalendarEntryCopyWith<$Res> {
_$SnEventCalendarEntryCopyWithImpl(this._self, this._then);
final SnEventCalendarEntry _self;
final $Res Function(SnEventCalendarEntry) _then;
/// Create a copy of SnEventCalendarEntry
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? date = null,Object? checkInResult = freezed,Object? statuses = null,}) {
return _then(_self.copyWith(
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
as SnCheckInResult?,statuses: null == statuses ? _self.statuses : statuses // ignore: cast_nullable_to_non_nullable
as List<dynamic>,
));
}
/// Create a copy of SnEventCalendarEntry
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnCheckInResultCopyWith<$Res>? get checkInResult {
if (_self.checkInResult == null) {
return null;
}
return $SnCheckInResultCopyWith<$Res>(_self.checkInResult!, (value) {
return _then(_self.copyWith(checkInResult: value));
});
}
}
/// @nodoc
@JsonSerializable()
class _SnEventCalendarEntry implements SnEventCalendarEntry {
const _SnEventCalendarEntry({required this.date, required this.checkInResult, required final List<dynamic> statuses}): _statuses = statuses;
factory _SnEventCalendarEntry.fromJson(Map<String, dynamic> json) => _$SnEventCalendarEntryFromJson(json);
@override final DateTime date;
@override final SnCheckInResult? checkInResult;
final List<dynamic> _statuses;
@override List<dynamic> get statuses {
if (_statuses is EqualUnmodifiableListView) return _statuses;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_statuses);
}
/// Create a copy of SnEventCalendarEntry
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$SnEventCalendarEntryCopyWith<_SnEventCalendarEntry> get copyWith => __$SnEventCalendarEntryCopyWithImpl<_SnEventCalendarEntry>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$SnEventCalendarEntryToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnEventCalendarEntry&&(identical(other.date, date) || other.date == date)&&(identical(other.checkInResult, checkInResult) || other.checkInResult == checkInResult)&&const DeepCollectionEquality().equals(other._statuses, _statuses));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,date,checkInResult,const DeepCollectionEquality().hash(_statuses));
@override
String toString() {
return 'SnEventCalendarEntry(date: $date, checkInResult: $checkInResult, statuses: $statuses)';
}
}
/// @nodoc
abstract mixin class _$SnEventCalendarEntryCopyWith<$Res> implements $SnEventCalendarEntryCopyWith<$Res> {
factory _$SnEventCalendarEntryCopyWith(_SnEventCalendarEntry value, $Res Function(_SnEventCalendarEntry) _then) = __$SnEventCalendarEntryCopyWithImpl;
@override @useResult
$Res call({
DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses
});
@override $SnCheckInResultCopyWith<$Res>? get checkInResult;
}
/// @nodoc
class __$SnEventCalendarEntryCopyWithImpl<$Res>
implements _$SnEventCalendarEntryCopyWith<$Res> {
__$SnEventCalendarEntryCopyWithImpl(this._self, this._then);
final _SnEventCalendarEntry _self;
final $Res Function(_SnEventCalendarEntry) _then;
/// Create a copy of SnEventCalendarEntry
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? date = null,Object? checkInResult = freezed,Object? statuses = null,}) {
return _then(_SnEventCalendarEntry(
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
as SnCheckInResult?,statuses: null == statuses ? _self._statuses : statuses // ignore: cast_nullable_to_non_nullable
as List<dynamic>,
));
}
/// Create a copy of SnEventCalendarEntry
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnCheckInResultCopyWith<$Res>? get checkInResult {
if (_self.checkInResult == null) {
return null;
}
return $SnCheckInResultCopyWith<$Res>(_self.checkInResult!, (value) {
return _then(_self.copyWith(checkInResult: value));
});
}
}
// dart format on

View File

@ -79,3 +79,24 @@ Map<String, dynamic> _$SnFortuneTipToJson(_SnFortuneTip instance) =>
'title': instance.title,
'content': instance.content,
};
_SnEventCalendarEntry _$SnEventCalendarEntryFromJson(
Map<String, dynamic> json,
) => _SnEventCalendarEntry(
date: DateTime.parse(json['date'] as String),
checkInResult:
json['check_in_result'] == null
? null
: SnCheckInResult.fromJson(
json['check_in_result'] as Map<String, dynamic>,
),
statuses: json['statuses'] as List<dynamic>,
);
Map<String, dynamic> _$SnEventCalendarEntryToJson(
_SnEventCalendarEntry instance,
) => <String, dynamic>{
'date': instance.date.toIso8601String(),
'check_in_result': instance.checkInResult?.toJson(),
'statuses': instance.statuses,
};

View File

@ -22,6 +22,10 @@ class AppRouter extends RootStackRouter {
AutoRoute(page: LoginRoute.page, path: '/auth/login'),
AutoRoute(page: CreateAccountRoute.page, path: '/auth/create-account'),
AutoRoute(page: MyselfProfileRoute.page, path: '/account/me'),
AutoRoute(
page: MyselfEventCalendarRoute.page,
path: '/account/me/calendar',
),
AutoRoute(page: UpdateProfileRoute.page, path: '/account/me/update'),
AutoRoute(page: ManagedPublisherRoute.page, path: '/account/me/publishers'),
AutoRoute(page: NewPublisherRoute.page, path: '/account/me/publishers/new'),

View File

@ -12,42 +12,26 @@
import 'package:auto_route/auto_route.dart' as _i18;
import 'package:flutter/material.dart' as _i19;
import 'package:island/models/post.dart' as _i20;
import 'package:island/screens/account.dart' as _i3;
import 'package:island/screens/account.dart' as _i2;
import 'package:island/screens/account/me.dart' as _i12;
import 'package:island/screens/account/me/event_calendar.dart' as _i1;
import 'package:island/screens/account/me/publishers.dart' as _i8;
import 'package:island/screens/account/me/event_calendar.dart' as _i11;
import 'package:island/screens/account/me/publishers.dart' as _i7;
import 'package:island/screens/account/me/update.dart' as _i17;
import 'package:island/screens/account/profile.dart' as _i2;
import 'package:island/screens/auth/create_account.dart' as _i7;
import 'package:island/screens/auth/login.dart' as _i11;
import 'package:island/screens/account/profile.dart' as _i1;
import 'package:island/screens/auth/create_account.dart' as _i6;
import 'package:island/screens/auth/login.dart' as _i10;
import 'package:island/screens/auth/tabs.dart' as _i16;
import 'package:island/screens/chat/chat.dart' as _i5;
import 'package:island/screens/chat/room.dart' as _i6;
import 'package:island/screens/chat/room_detail.dart' as _i4;
import 'package:island/screens/explore.dart' as _i10;
import 'package:island/screens/chat/chat.dart' as _i4;
import 'package:island/screens/chat/room.dart' as _i5;
import 'package:island/screens/chat/room_detail.dart' as _i3;
import 'package:island/screens/explore.dart' as _i9;
import 'package:island/screens/posts/compose.dart' as _i13;
import 'package:island/screens/posts/detail.dart' as _i14;
import 'package:island/screens/realm/detail.dart' as _i15;
import 'package:island/screens/realm/realms.dart' as _i9;
import 'package:island/screens/realm/realms.dart' as _i8;
/// generated route for
/// [_i1.AccountEventCalendar]
class AccountEventCalendar extends _i18.PageRouteInfo<void> {
const AccountEventCalendar({List<_i18.PageRouteInfo>? children})
: super(AccountEventCalendar.name, initialChildren: children);
static const String name = 'AccountEventCalendar';
static _i18.PageInfo page = _i18.PageInfo(
name,
builder: (data) {
return const _i1.AccountEventCalendar();
},
);
}
/// generated route for
/// [_i2.AccountProfileScreen]
/// [_i1.AccountProfileScreen]
class AccountProfileRoute extends _i18.PageRouteInfo<AccountProfileRouteArgs> {
AccountProfileRoute({
_i19.Key? key,
@ -70,7 +54,7 @@ class AccountProfileRoute extends _i18.PageRouteInfo<AccountProfileRouteArgs> {
orElse:
() => AccountProfileRouteArgs(name: pathParams.getString('name')),
);
return _i2.AccountProfileScreen(key: args.key, name: args.name);
return _i1.AccountProfileScreen(key: args.key, name: args.name);
},
);
}
@ -89,7 +73,7 @@ class AccountProfileRouteArgs {
}
/// generated route for
/// [_i3.AccountScreen]
/// [_i2.AccountScreen]
class AccountRoute extends _i18.PageRouteInfo<void> {
const AccountRoute({List<_i18.PageRouteInfo>? children})
: super(AccountRoute.name, initialChildren: children);
@ -99,13 +83,13 @@ class AccountRoute extends _i18.PageRouteInfo<void> {
static _i18.PageInfo page = _i18.PageInfo(
name,
builder: (data) {
return const _i3.AccountScreen();
return const _i2.AccountScreen();
},
);
}
/// generated route for
/// [_i4.ChatDetailScreen]
/// [_i3.ChatDetailScreen]
class ChatDetailRoute extends _i18.PageRouteInfo<ChatDetailRouteArgs> {
ChatDetailRoute({
_i19.Key? key,
@ -127,7 +111,7 @@ class ChatDetailRoute extends _i18.PageRouteInfo<ChatDetailRouteArgs> {
final args = data.argsAs<ChatDetailRouteArgs>(
orElse: () => ChatDetailRouteArgs(id: pathParams.getInt('id')),
);
return _i4.ChatDetailScreen(key: args.key, id: args.id);
return _i3.ChatDetailScreen(key: args.key, id: args.id);
},
);
}
@ -146,7 +130,7 @@ class ChatDetailRouteArgs {
}
/// generated route for
/// [_i5.ChatListScreen]
/// [_i4.ChatListScreen]
class ChatListRoute extends _i18.PageRouteInfo<void> {
const ChatListRoute({List<_i18.PageRouteInfo>? children})
: super(ChatListRoute.name, initialChildren: children);
@ -156,13 +140,13 @@ class ChatListRoute extends _i18.PageRouteInfo<void> {
static _i18.PageInfo page = _i18.PageInfo(
name,
builder: (data) {
return const _i5.ChatListScreen();
return const _i4.ChatListScreen();
},
);
}
/// generated route for
/// [_i6.ChatRoomScreen]
/// [_i5.ChatRoomScreen]
class ChatRoomRoute extends _i18.PageRouteInfo<ChatRoomRouteArgs> {
ChatRoomRoute({
_i19.Key? key,
@ -184,7 +168,7 @@ class ChatRoomRoute extends _i18.PageRouteInfo<ChatRoomRouteArgs> {
final args = data.argsAs<ChatRoomRouteArgs>(
orElse: () => ChatRoomRouteArgs(id: pathParams.getInt('id')),
);
return _i6.ChatRoomScreen(key: args.key, id: args.id);
return _i5.ChatRoomScreen(key: args.key, id: args.id);
},
);
}
@ -203,7 +187,7 @@ class ChatRoomRouteArgs {
}
/// generated route for
/// [_i7.CreateAccountScreen]
/// [_i6.CreateAccountScreen]
class CreateAccountRoute extends _i18.PageRouteInfo<void> {
const CreateAccountRoute({List<_i18.PageRouteInfo>? children})
: super(CreateAccountRoute.name, initialChildren: children);
@ -213,13 +197,13 @@ class CreateAccountRoute extends _i18.PageRouteInfo<void> {
static _i18.PageInfo page = _i18.PageInfo(
name,
builder: (data) {
return const _i7.CreateAccountScreen();
return const _i6.CreateAccountScreen();
},
);
}
/// generated route for
/// [_i5.EditChatScreen]
/// [_i4.EditChatScreen]
class EditChatRoute extends _i18.PageRouteInfo<EditChatRouteArgs> {
EditChatRoute({_i19.Key? key, int? id, List<_i18.PageRouteInfo>? children})
: super(
@ -238,7 +222,7 @@ class EditChatRoute extends _i18.PageRouteInfo<EditChatRouteArgs> {
final args = data.argsAs<EditChatRouteArgs>(
orElse: () => EditChatRouteArgs(id: pathParams.optInt('id')),
);
return _i5.EditChatScreen(key: args.key, id: args.id);
return _i4.EditChatScreen(key: args.key, id: args.id);
},
);
}
@ -257,7 +241,7 @@ class EditChatRouteArgs {
}
/// generated route for
/// [_i8.EditPublisherScreen]
/// [_i7.EditPublisherScreen]
class EditPublisherRoute extends _i18.PageRouteInfo<EditPublisherRouteArgs> {
EditPublisherRoute({
_i19.Key? key,
@ -279,7 +263,7 @@ class EditPublisherRoute extends _i18.PageRouteInfo<EditPublisherRouteArgs> {
final args = data.argsAs<EditPublisherRouteArgs>(
orElse: () => EditPublisherRouteArgs(name: pathParams.optString('id')),
);
return _i8.EditPublisherScreen(key: args.key, name: args.name);
return _i7.EditPublisherScreen(key: args.key, name: args.name);
},
);
}
@ -298,7 +282,7 @@ class EditPublisherRouteArgs {
}
/// generated route for
/// [_i9.EditRealmScreen]
/// [_i8.EditRealmScreen]
class EditRealmRoute extends _i18.PageRouteInfo<EditRealmRouteArgs> {
EditRealmRoute({
_i19.Key? key,
@ -320,7 +304,7 @@ class EditRealmRoute extends _i18.PageRouteInfo<EditRealmRouteArgs> {
final args = data.argsAs<EditRealmRouteArgs>(
orElse: () => EditRealmRouteArgs(slug: pathParams.optString('slug')),
);
return _i9.EditRealmScreen(key: args.key, slug: args.slug);
return _i8.EditRealmScreen(key: args.key, slug: args.slug);
},
);
}
@ -339,7 +323,7 @@ class EditRealmRouteArgs {
}
/// generated route for
/// [_i10.ExploreScreen]
/// [_i9.ExploreScreen]
class ExploreRoute extends _i18.PageRouteInfo<void> {
const ExploreRoute({List<_i18.PageRouteInfo>? children})
: super(ExploreRoute.name, initialChildren: children);
@ -349,13 +333,13 @@ class ExploreRoute extends _i18.PageRouteInfo<void> {
static _i18.PageInfo page = _i18.PageInfo(
name,
builder: (data) {
return const _i10.ExploreScreen();
return const _i9.ExploreScreen();
},
);
}
/// generated route for
/// [_i11.LoginScreen]
/// [_i10.LoginScreen]
class LoginRoute extends _i18.PageRouteInfo<void> {
const LoginRoute({List<_i18.PageRouteInfo>? children})
: super(LoginRoute.name, initialChildren: children);
@ -365,13 +349,13 @@ class LoginRoute extends _i18.PageRouteInfo<void> {
static _i18.PageInfo page = _i18.PageInfo(
name,
builder: (data) {
return const _i11.LoginScreen();
return const _i10.LoginScreen();
},
);
}
/// generated route for
/// [_i8.ManagedPublisherScreen]
/// [_i7.ManagedPublisherScreen]
class ManagedPublisherRoute extends _i18.PageRouteInfo<void> {
const ManagedPublisherRoute({List<_i18.PageRouteInfo>? children})
: super(ManagedPublisherRoute.name, initialChildren: children);
@ -381,7 +365,23 @@ class ManagedPublisherRoute extends _i18.PageRouteInfo<void> {
static _i18.PageInfo page = _i18.PageInfo(
name,
builder: (data) {
return const _i8.ManagedPublisherScreen();
return const _i7.ManagedPublisherScreen();
},
);
}
/// generated route for
/// [_i11.MyselfEventCalendarScreen]
class MyselfEventCalendarRoute extends _i18.PageRouteInfo<void> {
const MyselfEventCalendarRoute({List<_i18.PageRouteInfo>? children})
: super(MyselfEventCalendarRoute.name, initialChildren: children);
static const String name = 'MyselfEventCalendarRoute';
static _i18.PageInfo page = _i18.PageInfo(
name,
builder: (data) {
return const _i11.MyselfEventCalendarScreen();
},
);
}
@ -403,7 +403,7 @@ class MyselfProfileRoute extends _i18.PageRouteInfo<void> {
}
/// generated route for
/// [_i5.NewChatScreen]
/// [_i4.NewChatScreen]
class NewChatRoute extends _i18.PageRouteInfo<void> {
const NewChatRoute({List<_i18.PageRouteInfo>? children})
: super(NewChatRoute.name, initialChildren: children);
@ -413,13 +413,13 @@ class NewChatRoute extends _i18.PageRouteInfo<void> {
static _i18.PageInfo page = _i18.PageInfo(
name,
builder: (data) {
return const _i5.NewChatScreen();
return const _i4.NewChatScreen();
},
);
}
/// generated route for
/// [_i8.NewPublisherScreen]
/// [_i7.NewPublisherScreen]
class NewPublisherRoute extends _i18.PageRouteInfo<void> {
const NewPublisherRoute({List<_i18.PageRouteInfo>? children})
: super(NewPublisherRoute.name, initialChildren: children);
@ -429,13 +429,13 @@ class NewPublisherRoute extends _i18.PageRouteInfo<void> {
static _i18.PageInfo page = _i18.PageInfo(
name,
builder: (data) {
return const _i8.NewPublisherScreen();
return const _i7.NewPublisherScreen();
},
);
}
/// generated route for
/// [_i9.NewRealmScreen]
/// [_i8.NewRealmScreen]
class NewRealmRoute extends _i18.PageRouteInfo<void> {
const NewRealmRoute({List<_i18.PageRouteInfo>? children})
: super(NewRealmRoute.name, initialChildren: children);
@ -445,7 +445,7 @@ class NewRealmRoute extends _i18.PageRouteInfo<void> {
static _i18.PageInfo page = _i18.PageInfo(
name,
builder: (data) {
return const _i9.NewRealmScreen();
return const _i8.NewRealmScreen();
},
);
}
@ -616,7 +616,7 @@ class RealmDetailRouteArgs {
}
/// generated route for
/// [_i9.RealmListScreen]
/// [_i8.RealmListScreen]
class RealmListRoute extends _i18.PageRouteInfo<void> {
const RealmListRoute({List<_i18.PageRouteInfo>? children})
: super(RealmListRoute.name, initialChildren: children);
@ -626,7 +626,7 @@ class RealmListRoute extends _i18.PageRouteInfo<void> {
static _i18.PageInfo page = _i18.PageInfo(
name,
builder: (data) {
return const _i9.RealmListScreen();
return const _i8.RealmListScreen();
},
);
}

View File

@ -1,13 +1,172 @@
import 'dart:convert';
import 'package:auto_route/auto_route.dart';
import 'package:flutter/widgets.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/activity.dart';
import 'package:island/pods/network.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:table_calendar/table_calendar.dart';
part 'event_calendar.g.dart';
@riverpod
Future<List<SnEventCalendarEntry>> myselfAccountEventCalendar(Ref ref) async {
final client = ref.watch(apiClientProvider);
final resp = await client.get('/accounts/me/calendar');
return resp.data
.map((e) => SnEventCalendarEntry.fromJson(e))
.cast<SnEventCalendarEntry>()
.toList();
}
@RoutePage()
class AccountEventCalendar extends HookConsumerWidget {
const AccountEventCalendar({super.key});
class MyselfEventCalendarScreen extends HookConsumerWidget {
const MyselfEventCalendarScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
final events = ref.watch(myselfAccountEventCalendarProvider);
final selectedDay = useState(DateTime.now());
return AppScaffold(
appBar: AppBar(
leading: const PageBackButton(),
title: Text('eventCalander').tr(),
),
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<SnCheckInResult>().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),
AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: Builder(
builder: (context) {
final event =
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))
.fontSize(16)
.bold()
.textColor(
Theme.of(context).colorScheme.onSecondaryContainer,
),
Text(DateFormat.yMd().format(event.date))
.fontSize(12)
.textColor(
Theme.of(context).colorScheme.onSecondaryContainer,
),
const Gap(16),
if (event.checkInResult != null)
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'checkInResultLevel${event.checkInResult!.level}',
).tr().fontSize(16).bold(),
for (final tip in event.checkInResult!.tips)
Row(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8,
children: [
Icon(
Symbols.circle,
size: 12,
fill: 1,
).padding(top: 4, right: 4),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(tip.title).bold(),
Text(tip.content),
],
),
),
],
).padding(top: 8),
],
),
if (event.checkInResult == null && event.statuses.isEmpty)
Text('eventCalanderEmpty').tr(),
],
).padding(vertical: 24, horizontal: 24);
},
),
),
],
),
);
}
}

View File

@ -0,0 +1,31 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'event_calendar.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$myselfAccountEventCalendarHash() =>
r'd3faad342d5104e87ff6597ab459e65cb5f4ef97';
/// See also [myselfAccountEventCalendar].
@ProviderFor(myselfAccountEventCalendar)
final myselfAccountEventCalendarProvider =
AutoDisposeFutureProvider<List<SnEventCalendarEntry>>.internal(
myselfAccountEventCalendar,
name: r'myselfAccountEventCalendarProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$myselfAccountEventCalendarHash,
dependencies: null,
allTransitiveDependencies: null,
);
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
typedef MyselfAccountEventCalendarRef =
AutoDisposeFutureProviderRef<List<SnEventCalendarEntry>>;
// 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

View File

@ -1,9 +1,12 @@
import 'package:auto_route/auto_route.dart';
import 'package:dio/dio.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/activity.dart';
import 'package:island/pods/network.dart';
import 'package:island/route.gr.dart';
import 'package:island/widgets/alert.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:styled_widget/styled_widget.dart';
@ -33,6 +36,16 @@ class CheckInWidget extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final todayResult = ref.watch(checkInResultTodayProvider);
Future<void> checkIn() async {
final client = ref.read(apiClientProvider);
try {
await client.post('/accounts/me/check-in');
ref.invalidate(checkInResultTodayProvider);
} catch (err) {
showErrorAlert(err);
}
}
return Card(
margin: EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8),
child: Row(
@ -83,7 +96,7 @@ class CheckInWidget extends HookConsumerWidget {
(e) => '${e.isPositive ? '' : ''} ${e.title}',
)
.join(' · '),
).tr().fontSize(11),
).fontSize(11),
],
);
},
@ -100,7 +113,13 @@ class CheckInWidget extends HookConsumerWidget {
),
),
IconButton.outlined(
onPressed: () {},
onPressed: () {
if (todayResult.valueOrNull == null) {
checkIn();
} else {
context.router.push(MyselfEventCalendarRoute());
}
},
icon: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: todayResult.when(

View File

@ -509,10 +509,10 @@ packages:
dependency: "direct main"
description:
name: file_picker
sha256: "8986dec4581b4bcd4b6df5d75a2ea0bede3db802f500635d05fa8be298f9467f"
sha256: "978be1f602e0695daef8e345a3c597abf72b0c0ca6102fa2665eb549f5406a17"
url: "https://pub.dev"
source: hosted
version: "10.1.2"
version: "10.1.5"
file_selector_linux:
dependency: transitive
description:
@ -727,10 +727,10 @@ packages:
dependency: "direct main"
description:
name: flutter_markdown
sha256: "634622a3a826d67cb05c0e3e576d1812c430fa98404e95b60b131775c73d76ec"
sha256: "08fb8315236099ff8e90cb87bb2b935e0a724a3af1623000a9cec930468e0f27"
url: "https://pub.dev"
source: hosted
version: "0.7.7"
version: "0.7.7+1"
flutter_markdown_latex:
dependency: "direct main"
description:
@ -889,10 +889,10 @@ packages:
dependency: transitive
description:
name: http
sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f
sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
url: "https://pub.dev"
source: hosted
version: "1.3.0"
version: "1.4.0"
http_multi_server:
dependency: transitive
description:
@ -1549,6 +1549,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.0"
simple_gesture_detector:
dependency: transitive
description:
name: simple_gesture_detector
sha256: ba2cd5af24ff20a0b8d609cec3f40e5b0744d2a71804a2616ae086b9c19d19a3
url: "https://pub.dev"
source: hosted
version: "0.2.1"
sky_engine:
dependency: transitive
description: flutter
@ -1738,6 +1746,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.1"
table_calendar:
dependency: "direct main"
description:
name: table_calendar
sha256: b2896b7c86adf3a4d9c911d860120fe3dbe03c85db43b22fd61f14ee78cdbb63
url: "https://pub.dev"
source: hosted
version: "3.1.3"
tencent_rtc_sdk:
dependency: "direct main"
description:
@ -1975,10 +1991,10 @@ packages:
dependency: transitive
description:
name: web_socket
sha256: bfe6f435f6ec49cb6c01da1e275ae4228719e59a6b067048c51e72d9d63bcc4b
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
version: "1.0.1"
web_socket_channel:
dependency: "direct main"
description:

View File

@ -92,6 +92,7 @@ dependencies:
markdown_editor_plus: ^0.2.15
croppy: ^1.3.6
tencent_rtc_sdk: ^12.3.6
table_calendar: ^3.1.3
dev_dependencies:
flutter_test: