chore: go to course settings tab after archiving activity, show check over completed activites (#3913)
This commit is contained in:
parent
ad2e0e26db
commit
2d6e075707
6 changed files with 154 additions and 88 deletions
3
assets/pangea/check.svg
Normal file
3
assets/pangea/check.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M23.7203 42.6667L5.81818 26.6667L0 32L23.2727 64L64 5.33333V0L23.7203 42.6667Z" fill="#03A514"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 209 B |
|
|
@ -36,9 +36,9 @@ class ActivityFinishedStatusMessage extends StatelessWidget {
|
|||
},
|
||||
);
|
||||
|
||||
if (navigate == true) {
|
||||
if (navigate == true && controller.room.courseParent != null) {
|
||||
context.go(
|
||||
"/rooms/analytics?mode=activities",
|
||||
"/rooms/spaces/${controller.room.courseParent!.id}/details?tab=course",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import 'package:fluffychat/pangea/common/widgets/url_image_widget.dart';
|
|||
|
||||
class ActivitySuggestionCard extends StatelessWidget {
|
||||
final ActivityPlanModel activity;
|
||||
final VoidCallback onPressed;
|
||||
final double width;
|
||||
final double height;
|
||||
|
||||
|
|
@ -18,7 +17,6 @@ class ActivitySuggestionCard extends StatelessWidget {
|
|||
const ActivitySuggestionCard({
|
||||
super.key,
|
||||
required this.activity,
|
||||
required this.onPressed,
|
||||
required this.width,
|
||||
required this.height,
|
||||
this.fontSize,
|
||||
|
|
@ -29,87 +27,81 @@ class ActivitySuggestionCard extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: onPressed,
|
||||
child: SizedBox(
|
||||
height: height,
|
||||
width: width,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.surfaceContainer,
|
||||
return SizedBox(
|
||||
height: height,
|
||||
width: width,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.surfaceContainer,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
ImageByUrl(
|
||||
imageUrl: activity.imageURL,
|
||||
width: width,
|
||||
borderRadius: const BorderRadius.all(Radius.zero),
|
||||
replacement: SizedBox(height: width),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
ImageByUrl(
|
||||
imageUrl: activity.imageURL,
|
||||
width: width,
|
||||
borderRadius: const BorderRadius.all(Radius.zero),
|
||||
replacement: SizedBox(height: width),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
activity.title,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
),
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 8.0,
|
||||
children: [
|
||||
Text(
|
||||
activity.title,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
),
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 8.0,
|
||||
children: [
|
||||
if (activity.req.mode.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Text(
|
||||
activity.req.mode,
|
||||
style: fontSizeSmall != null
|
||||
? TextStyle(fontSize: fontSizeSmall)
|
||||
: theme.textTheme.labelSmall,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 4.0,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.group_outlined,
|
||||
size: iconSize ?? 12.0,
|
||||
),
|
||||
Text(
|
||||
"${activity.req.numberOfParticipants}",
|
||||
style: fontSizeSmall != null
|
||||
? TextStyle(fontSize: fontSizeSmall)
|
||||
: theme.textTheme.labelSmall,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (activity.req.mode.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Text(
|
||||
activity.req.mode,
|
||||
style: fontSizeSmall != null
|
||||
? TextStyle(fontSize: fontSizeSmall)
|
||||
: theme.textTheme.labelSmall,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 4.0,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.group_outlined,
|
||||
size: iconSize ?? 12.0,
|
||||
),
|
||||
Text(
|
||||
"${activity.req.numberOfParticipants}",
|
||||
style: fontSizeSmall != null
|
||||
? TextStyle(fontSize: fontSizeSmall)
|
||||
: theme.textTheme.labelSmall,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'package:matrix/matrix.dart';
|
|||
import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_role_model.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_roles_model.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/bot/utils/bot_name.dart';
|
||||
import 'package:fluffychat/pangea/chat/constants/default_power_level.dart';
|
||||
import 'package:fluffychat/pangea/chat_settings/constants/pangea_room_types.dart';
|
||||
|
|
@ -32,6 +33,15 @@ extension CoursePlanRoomExtension on Room {
|
|||
|
||||
CourseUserState? get _ownCourseState => _courseUserState(client.userID!);
|
||||
|
||||
bool hasCompletedActivity(
|
||||
String userID,
|
||||
String activityID,
|
||||
) {
|
||||
final state = _courseUserState(userID);
|
||||
if (state == null) return false;
|
||||
return state.hasCompletedActivity(activityID);
|
||||
}
|
||||
|
||||
bool _hasCompletedTopic(
|
||||
String userID,
|
||||
String topicID,
|
||||
|
|
@ -90,6 +100,17 @@ extension CoursePlanRoomExtension on Room {
|
|||
int ownCurrentTopicIndex(CoursePlanModel course) =>
|
||||
currentTopicIndex(client.userID!, course);
|
||||
|
||||
String? activeActivityRoomId(String activityId) {
|
||||
for (final child in spaceChildren) {
|
||||
if (child.roomId == null) continue;
|
||||
final room = client.getRoomById(child.roomId!);
|
||||
if (room?.activityId == activityId && !room!.isHiddenActivityRoom) {
|
||||
return room.id;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<Map<String, List<User>>> topicsToUsers(CoursePlanModel course) async {
|
||||
final Map<String, List<User>> topicUserMap = {};
|
||||
final users = await requestParticipants(
|
||||
|
|
|
|||
|
|
@ -21,6 +21,14 @@ class CourseUserState {
|
|||
return _completedActivities[topicID] ?? [];
|
||||
}
|
||||
|
||||
bool hasCompletedActivity(
|
||||
String activityID,
|
||||
) {
|
||||
return _completedActivities.values.any(
|
||||
(activities) => activities.contains(activityID),
|
||||
);
|
||||
}
|
||||
|
||||
factory CourseUserState.fromJson(Map<String, dynamic> json) {
|
||||
final Map<String, List<String>> activities = {};
|
||||
final activityEntry =
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
|
|
@ -164,24 +165,65 @@ class CourseSettings extends StatelessWidget {
|
|||
),
|
||||
if (unlocked)
|
||||
SizedBox(
|
||||
height: 210.0,
|
||||
height: isColumnMode ? 290.0 : 210.0,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: topic.loadedActivities.length,
|
||||
itemBuilder: (context, index) {
|
||||
final activityId =
|
||||
topic.loadedActivities[index].activityId;
|
||||
|
||||
final complete = room.hasCompletedActivity(
|
||||
room.client.userID!,
|
||||
activityId,
|
||||
);
|
||||
|
||||
final activityRoomId = room.activeActivityRoomId(
|
||||
activityId,
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 24.0),
|
||||
child: ActivitySuggestionCard(
|
||||
activity: topic.loadedActivities[index],
|
||||
// TODO: go to activity start page
|
||||
onPressed: () => context.go(
|
||||
"/rooms/spaces/${room.id}/activity/${topic.loadedActivities[index].activityId}",
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: () => context.go(
|
||||
activityRoomId != null
|
||||
? "/rooms/spaces/${room.id}/$activityRoomId"
|
||||
: "/rooms/spaces/${room.id}/activity/$activityId",
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
ActivitySuggestionCard(
|
||||
activity: topic.loadedActivities[index],
|
||||
width: isColumnMode ? 160.0 : 120.0,
|
||||
height: isColumnMode ? 280.0 : 200.0,
|
||||
fontSize: isColumnMode ? 20.0 : 12.0,
|
||||
fontSizeSmall:
|
||||
isColumnMode ? 12.0 : 8.0,
|
||||
iconSize: isColumnMode ? 12.0 : 8.0,
|
||||
),
|
||||
if (complete)
|
||||
Container(
|
||||
width: isColumnMode ? 160.0 : 120.0,
|
||||
height: isColumnMode ? 280.0 : 200.0,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius:
|
||||
BorderRadius.circular(12.0),
|
||||
color: theme.colorScheme.surface
|
||||
.withAlpha(180),
|
||||
),
|
||||
child: Center(
|
||||
child: SvgPicture.asset(
|
||||
"assets/pangea/check.svg",
|
||||
width: 48.0,
|
||||
height: 48.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
width: 120.0,
|
||||
height: 200.0,
|
||||
fontSize: 12.0,
|
||||
fontSizeSmall: 8.0,
|
||||
iconSize: 8.0,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue