♻️ Convert the activity calandar screen to sheet

This commit is contained in:
2025-10-13 00:34:16 +08:00
parent 389fa515ba
commit 7e0e7c20d7
7 changed files with 91 additions and 44 deletions

View File

@@ -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<GoRouter>((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(

View File

@@ -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),
),

View File

@@ -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),
],
),
),
);
);
}
}
}

View File

@@ -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);
}

View File

@@ -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,
),
),
);
},
),

View File

@@ -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,
),
),
);
}
},