diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index 55cd5dbe..055b2469 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -171,8 +171,8 @@ "checkInResultLevel3": "Good Luck", "checkInResultLevel4": "Best Luck", "checkInActivityTitle": "{} checked in on {} and got a {}", - "eventCalander": "Event Calander", - "eventCalanderEmpty": "No events on that day.", + "eventCalendar": "Event Calendar", + "eventCalendarEmpty": "No events on that day.", "fortuneGraph": "Fortune Trend", "noFortuneData": "No fortune data available for this month.", "creatorHub": "Creator Hub", diff --git a/lib/route.dart b/lib/route.dart index 55dc87ec..19ccc77b 100644 --- a/lib/route.dart +++ b/lib/route.dart @@ -58,7 +58,6 @@ import 'package:island/screens/settings.dart'; import 'package:island/screens/realm/realms.dart'; import 'package:island/screens/realm/realm_form.dart'; import 'package:island/screens/realm/realm_detail.dart'; -import 'package:island/screens/account/event_calendar.dart'; import 'package:island/screens/discovery/realms.dart'; import 'package:island/screens/reports/report_detail.dart'; import 'package:island/screens/reports/report_list.dart'; @@ -138,14 +137,6 @@ final routerProvider = Provider((ref) { path: '/logs', builder: (context, state) => TalkerScreen(talker: talker), ), - GoRoute( - name: 'accountCalendar', - path: '/account/:name/calendar', - builder: (context, state) { - final name = state.pathParameters['name']!; - return EventCalanderScreen(name: name); - }, - ), // Web articles GoRoute( diff --git a/lib/screens/account/profile.dart b/lib/screens/account/profile.dart index 7fc1c262..ecfc7c72 100644 --- a/lib/screens/account/profile.dart +++ b/lib/screens/account/profile.dart @@ -97,9 +97,7 @@ class _AccountBasicInfo extends StatelessWidget { IconButton( onPressed: () { SharePlus.instance.share( - ShareParams( - uri: Uri.parse('https://solian.app/@${data.name}'), - ), + ShareParams(uri: Uri.parse('https://solian.app/@${data.name}')), ); }, icon: const Icon(Symbols.share), @@ -879,7 +877,7 @@ class AccountProfileScreen extends HookConsumerWidget { child: Card( child: FortuneGraphWidget( events: accountEvents, - eventCalanderUser: data.name, + eventCalandarUser: data.name, margin: EdgeInsets.zero, ), ), @@ -1004,7 +1002,7 @@ class AccountProfileScreen extends HookConsumerWidget { child: Card( child: FortuneGraphWidget( events: accountEvents, - eventCalanderUser: data.name, + eventCalandarUser: data.name, ), ).padding(horizontal: 4), ), diff --git a/lib/screens/account/event_calendar.dart b/lib/widgets/account/event_calendar_content.dart similarity index 71% rename from lib/screens/account/event_calendar.dart rename to lib/widgets/account/event_calendar_content.dart index 44da56ba..24830157 100644 --- a/lib/screens/account/event_calendar.dart +++ b/lib/widgets/account/event_calendar_content.dart @@ -1,4 +1,3 @@ -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:gap/gap.dart'; @@ -6,14 +5,24 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/pods/event_calendar.dart'; import 'package:island/screens/account/profile.dart'; import 'package:island/widgets/account/account_nameplate.dart'; -import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/account/event_calendar.dart'; import 'package:island/widgets/account/fortune_graph.dart'; import 'package:styled_widget/styled_widget.dart'; -class EventCalanderScreen extends HookConsumerWidget { +/// A reusable content widget for event calendar that can be used in screens or sheets +/// This widget manages the calendar state and displays the calendar and fortune graph +class EventCalendarContent extends HookConsumerWidget { + /// Username to fetch calendar for, null means current user ('me') final String name; - const EventCalanderScreen({super.key, required this.name}); + + /// Whether this is being displayed in a sheet (affects layout) + final bool isSheet; + + const EventCalendarContent({ + super.key, + required this.name, + this.isSheet = false, + }); @override Widget build(BuildContext context, WidgetRef ref) { @@ -45,13 +54,37 @@ class EventCalanderScreen extends HookConsumerWidget { selectedDay.value = day; } - return AppScaffold( - isNoBackground: false, - appBar: AppBar( - leading: const PageBackButton(), - title: Text('eventCalander').tr(), - ), - body: SingleChildScrollView( + if (isSheet) { + // Sheet layout - simplified, no app bar, scrollable content + return SingleChildScrollView( + child: Column( + children: [ + // Use the reusable EventCalendarWidget + EventCalendarWidget( + events: events, + initialDate: now, + showEventDetails: true, + onMonthChanged: onMonthChanged, + onDaySelected: onDaySelected, + ), + + // Add the fortune graph widget + const Divider(height: 1), + FortuneGraphWidget( + events: events, + onPointSelected: onDaySelected, + ).padding(horizontal: 8, vertical: 4), + + // Show user profile if viewing someone else's calendar + if (name != 'me' && user.value != null) + AccountNameplate(name: name), + Gap(MediaQuery.of(context).padding.bottom + 16), + ], + ), + ); + } else { + // Screen layout - with responsive design + return SingleChildScrollView( child: MediaQuery.of(context).size.width > 480 ? ConstrainedBox( @@ -111,7 +144,7 @@ class EventCalanderScreen extends HookConsumerWidget { Gap(MediaQuery.of(context).padding.bottom + 16), ], ), - ), - ); + ); + } } } diff --git a/lib/widgets/account/event_details_widget.dart b/lib/widgets/account/event_details_widget.dart index 3dc47032..3f549c25 100644 --- a/lib/widgets/account/event_details_widget.dart +++ b/lib/widgets/account/event_details_widget.dart @@ -76,10 +76,17 @@ class EventDetailsWidget extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if ((getActivityTitle(status.label, status.meta) ?? status.label).isNotEmpty) - Text(getActivityTitle(status.label, status.meta) ?? status.label), + if ((getActivityTitle(status.label, status.meta) ?? + status.label) + .isNotEmpty) + Text( + getActivityTitle(status.label, status.meta) ?? + status.label, + ), if (getActivitySubtitle(status.meta) != null) - Text(getActivitySubtitle(status.meta)!).fontSize(11).opacity(0.8), + Text( + getActivitySubtitle(status.meta)!, + ).fontSize(11).opacity(0.8), Text( '${status.createdAt.formatSystem()} - ${status.clearedAt?.formatSystem() ?? 'present'.tr()}', ).fontSize(11).opacity(0.8), @@ -92,7 +99,7 @@ class EventDetailsWidget extends StatelessWidget { ], ), if (event?.checkInResult == null && (event?.statuses.isEmpty ?? true)) - Text('eventCalanderEmpty').tr(), + Text('eventCalandarEmpty').tr(), ], ).padding(vertical: 24, horizontal: 24); } diff --git a/lib/widgets/account/fortune_graph.dart b/lib/widgets/account/fortune_graph.dart index b9675666..6a0eff3e 100644 --- a/lib/widgets/account/fortune_graph.dart +++ b/lib/widgets/account/fortune_graph.dart @@ -1,9 +1,10 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/activity.dart'; +import 'package:island/widgets/account/event_calendar_content.dart'; +import 'package:island/widgets/content/sheet.dart'; import 'package:styled_widget/styled_widget.dart'; /// A widget that displays a graph of fortune levels over time @@ -24,7 +25,7 @@ class FortuneGraphWidget extends HookConsumerWidget { /// Callback when a point is selected final void Function(DateTime)? onPointSelected; - final String? eventCalanderUser; + final String? eventCalandarUser; final EdgeInsets? margin; @@ -35,7 +36,7 @@ class FortuneGraphWidget extends HookConsumerWidget { this.maxWidth = double.infinity, this.height = 180, this.onPointSelected, - this.eventCalanderUser, + this.eventCalandarUser, this.margin, }); @@ -59,7 +60,7 @@ class FortuneGraphWidget extends HookConsumerWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('fortuneGraph').tr().fontSize(18).bold(), - if (eventCalanderUser != null) + if (eventCalandarUser != null) IconButton( icon: const Icon(Icons.calendar_month, size: 20), visualDensity: const VisualDensity( @@ -69,9 +70,17 @@ class FortuneGraphWidget extends HookConsumerWidget { padding: EdgeInsets.zero, constraints: const BoxConstraints(), onPressed: () { - context.pushNamed( - 'accountCalendar', - pathParameters: {'name': eventCalanderUser!}, + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: + (context) => SheetScaffold( + titleText: 'eventCalendar'.tr(), + child: EventCalendarContent( + name: eventCalandarUser!, + isSheet: true, + ), + ), ); }, ), diff --git a/lib/widgets/check_in.dart b/lib/widgets/check_in.dart index afd43d2f..4acf0f6f 100644 --- a/lib/widgets/check_in.dart +++ b/lib/widgets/check_in.dart @@ -5,7 +5,6 @@ import 'package:dio/dio.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:go_router/go_router.dart'; import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/activity.dart'; @@ -14,6 +13,8 @@ import 'package:island/pods/userinfo.dart'; import 'package:island/screens/auth/captcha.dart'; import 'package:island/widgets/alert.dart'; import 'package:island/widgets/content/cloud_files.dart'; +import 'package:island/widgets/content/sheet.dart'; +import 'package:island/widgets/account/event_calendar_content.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:slide_countdown/slide_countdown.dart'; @@ -256,9 +257,17 @@ class CheckInWidget extends HookConsumerWidget { if (todayResult.valueOrNull == null) { checkIn(); } else { - context.pushNamed( - 'accountCalendar', - pathParameters: {'name': 'me'}, + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: + (context) => SheetScaffold( + titleText: 'eventCalendar'.tr(), + child: EventCalendarContent( + name: 'me', + isSheet: true, + ), + ), ); } },