📱 Dashboard supports mobile
This commit is contained in:
@@ -9,6 +9,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:island/pods/chat/chat_room.dart';
|
import 'package:island/pods/chat/chat_room.dart';
|
||||||
import 'package:island/pods/event_calendar.dart';
|
import 'package:island/pods/event_calendar.dart';
|
||||||
import 'package:island/screens/chat/chat.dart';
|
import 'package:island/screens/chat/chat.dart';
|
||||||
|
import 'package:island/services/responsive.dart';
|
||||||
import 'package:island/widgets/account/fortune_graph.dart';
|
import 'package:island/widgets/account/fortune_graph.dart';
|
||||||
import 'package:island/widgets/account/friends_overview.dart';
|
import 'package:island/widgets/account/friends_overview.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
@@ -36,10 +37,15 @@ class DashboardGrid extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final isWide = isWideScreen(context);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: math.min(640, MediaQuery.sizeOf(context).height * 0.65),
|
maxHeight: isWide
|
||||||
|
? math.min(640, MediaQuery.sizeOf(context).height * 0.65)
|
||||||
|
: MediaQuery.sizeOf(context).height,
|
||||||
),
|
),
|
||||||
|
padding: isWide ? null : EdgeInsets.only(top: 24),
|
||||||
child: Column(
|
child: Column(
|
||||||
spacing: 16,
|
spacing: 16,
|
||||||
children: [
|
children: [
|
||||||
@@ -56,66 +62,104 @@ class DashboardGrid extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Align(
|
child: SingleChildScrollView(
|
||||||
alignment: Alignment.centerLeft,
|
padding: isWide
|
||||||
child: SingleChildScrollView(
|
? const EdgeInsets.symmetric(horizontal: 24)
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
: const EdgeInsets.only(bottom: 64),
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: isWide ? Axis.horizontal : Axis.vertical,
|
||||||
child: Row(
|
child: isWide ? _DashboardGridWide() : _DashboardGridNarrow(),
|
||||||
spacing: 16,
|
).clipRRect(topLeft: 12, topRight: 12).padding(horizontal: 24),
|
||||||
children: [
|
),
|
||||||
SizedBox(
|
],
|
||||||
width: 400,
|
),
|
||||||
child: Column(
|
);
|
||||||
spacing: 16,
|
}
|
||||||
children: [
|
}
|
||||||
CheckInWidget(
|
|
||||||
margin: EdgeInsets.zero,
|
class _DashboardGridWide extends HookConsumerWidget {
|
||||||
checkInOnly: true,
|
const _DashboardGridWide();
|
||||||
),
|
|
||||||
Card(
|
@override
|
||||||
margin: EdgeInsets.zero,
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
child: FortuneGraphWidget(
|
return Row(
|
||||||
events: ref.watch(
|
spacing: 16,
|
||||||
eventCalendarProvider(
|
children: [
|
||||||
EventCalendarQuery(
|
SizedBox(
|
||||||
uname: 'me',
|
width: 400,
|
||||||
year: DateTime.now().year,
|
child: Column(
|
||||||
month: DateTime.now().month,
|
spacing: 16,
|
||||||
),
|
children: [
|
||||||
),
|
CheckInWidget(margin: EdgeInsets.zero, checkInOnly: true),
|
||||||
),
|
Card(
|
||||||
),
|
margin: EdgeInsets.zero,
|
||||||
),
|
child: FortuneGraphWidget(
|
||||||
Expanded(child: FortuneCard()),
|
events: ref.watch(
|
||||||
],
|
eventCalendarProvider(
|
||||||
|
EventCalendarQuery(
|
||||||
|
uname: 'me',
|
||||||
|
year: DateTime.now().year,
|
||||||
|
month: DateTime.now().month,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 400, child: FeaturedPostCard()),
|
),
|
||||||
SizedBox(
|
),
|
||||||
width: 400,
|
),
|
||||||
child: Column(
|
Expanded(child: FortuneCard()),
|
||||||
spacing: 16,
|
],
|
||||||
children: [
|
),
|
||||||
FriendsOverviewWidget(),
|
),
|
||||||
Expanded(child: NotificationsCard()),
|
SizedBox(width: 400, child: FeaturedPostCard()),
|
||||||
],
|
SizedBox(
|
||||||
),
|
width: 400,
|
||||||
),
|
child: Column(
|
||||||
SizedBox(
|
spacing: 16,
|
||||||
width: 400,
|
children: [
|
||||||
child: Column(
|
FriendsOverviewWidget(),
|
||||||
spacing: 16,
|
Expanded(child: NotificationsCard()),
|
||||||
children: [Expanded(child: ChatListCard())],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
SizedBox(
|
||||||
|
width: 400,
|
||||||
|
child: Column(
|
||||||
|
spacing: 16,
|
||||||
|
children: [Expanded(child: ChatListCard())],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DashboardGridNarrow extends HookConsumerWidget {
|
||||||
|
const _DashboardGridNarrow();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
return Column(
|
||||||
|
spacing: 16,
|
||||||
|
children: [
|
||||||
|
CheckInWidget(margin: EdgeInsets.zero, checkInOnly: true),
|
||||||
|
FortuneCard(),
|
||||||
|
SizedBox(height: 400, child: FeaturedPostCard()),
|
||||||
|
FriendsOverviewWidget(),
|
||||||
|
NotificationsCard(),
|
||||||
|
ChatListCard(),
|
||||||
|
Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
child: FortuneGraphWidget(
|
||||||
|
events: ref.watch(
|
||||||
|
eventCalendarProvider(
|
||||||
|
EventCalendarQuery(
|
||||||
|
uname: 'me',
|
||||||
|
year: DateTime.now().year,
|
||||||
|
month: DateTime.now().month,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,37 +388,35 @@ class NotificationsCard extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 16, vertical: 12),
|
).padding(horizontal: 16, vertical: 12),
|
||||||
Expanded(
|
notifications.when(
|
||||||
child: notifications.when(
|
loading: () => const SkeletonNotificationTile(),
|
||||||
loading: () => const SkeletonNotificationTile(),
|
error: (error, stack) => Center(child: Text('Error: $error')),
|
||||||
error: (error, stack) => Center(child: Text('Error: $error')),
|
data: (notificationList) {
|
||||||
data: (notificationList) {
|
if (notificationList.isEmpty) {
|
||||||
if (notificationList.isEmpty) {
|
return const Center(child: Text('No notifications yet'));
|
||||||
return const Center(child: Text('No notifications yet'));
|
}
|
||||||
}
|
// Get the most recent notification (first in the list)
|
||||||
// Get the most recent notification (first in the list)
|
final recentNotification = notificationList.first;
|
||||||
final recentNotification = notificationList.first;
|
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Most Recent',
|
'Most Recent',
|
||||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
),
|
|
||||||
).padding(horizontal: 16),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
NotificationTile(
|
|
||||||
notification: recentNotification,
|
|
||||||
compact: true,
|
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
avatarRadius: 16.0,
|
|
||||||
),
|
),
|
||||||
],
|
).padding(horizontal: 16),
|
||||||
);
|
const SizedBox(height: 8),
|
||||||
},
|
NotificationTile(
|
||||||
),
|
notification: recentNotification,
|
||||||
|
compact: true,
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
avatarRadius: 16.0,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'Tap to view all notifications',
|
'Tap to view all notifications',
|
||||||
@@ -424,34 +466,33 @@ class ChatListCard extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 16, vertical: 16),
|
).padding(horizontal: 16, vertical: 16),
|
||||||
Expanded(
|
chatRooms.when(
|
||||||
child: chatRooms.when(
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
error: (error, stack) => Center(child: Text('Error: $error')),
|
||||||
error: (error, stack) => Center(child: Text('Error: $error')),
|
data: (rooms) {
|
||||||
data: (rooms) {
|
if (rooms.isEmpty) {
|
||||||
if (rooms.isEmpty) {
|
return const Center(child: Text('No chat rooms available'));
|
||||||
return const Center(child: Text('No chat rooms available'));
|
}
|
||||||
}
|
// Take only the first 5 rooms
|
||||||
// Take only the first 5 rooms
|
final recentRooms = rooms.take(5).toList();
|
||||||
final recentRooms = rooms.take(5).toList();
|
return ListView.builder(
|
||||||
return ListView.builder(
|
shrinkWrap: true,
|
||||||
itemCount: recentRooms.length,
|
itemCount: recentRooms.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final room = recentRooms[index];
|
final room = recentRooms[index];
|
||||||
return ChatRoomListTile(
|
return ChatRoomListTile(
|
||||||
room: room,
|
room: room,
|
||||||
isDirect: room.type == 1,
|
isDirect: room.type == 1,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.pushNamed(
|
context.pushNamed(
|
||||||
'chatRoom',
|
'chatRoom',
|
||||||
pathParameters: {'id': room.id},
|
pathParameters: {'id': room.id},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -514,6 +555,6 @@ class FortuneCard extends HookWidget {
|
|||||||
Text(fortune['author']!).bold(),
|
Text(fortune['author']!).bold(),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24),
|
).padding(horizontal: 24),
|
||||||
);
|
).height(48);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user