4379 show participants in public courses selection (#4383)

* chore: trip body / icons updates

* chore: display participant count in public courses page, update trip-related copy
This commit is contained in:
ggurdin 2025-10-14 15:28:33 -04:00 committed by GitHub
parent cd2f43c00c
commit 7579b657f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 105 additions and 67 deletions

View file

@ -44,13 +44,13 @@ import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
import 'package:fluffychat/pangea/find_your_people/find_your_people_constants.dart';
import 'package:fluffychat/pangea/guard/p_vguard.dart';
import 'package:fluffychat/pangea/learning_settings/pages/settings_learning.dart';
import 'package:fluffychat/pangea/login/pages/add_course_page.dart';
import 'package:fluffychat/pangea/login/pages/course_code_page.dart';
import 'package:fluffychat/pangea/login/pages/create_pangea_account_page.dart';
import 'package:fluffychat/pangea/login/pages/language_selection_page.dart';
import 'package:fluffychat/pangea/login/pages/login_or_signup_view.dart';
import 'package:fluffychat/pangea/login/pages/new_trip_page.dart';
import 'package:fluffychat/pangea/login/pages/plan_trip_page.dart';
import 'package:fluffychat/pangea/login/pages/private_trip_page.dart';
import 'package:fluffychat/pangea/login/pages/public_trip_page.dart';
import 'package:fluffychat/pangea/login/pages/new_course_page.dart';
import 'package:fluffychat/pangea/login/pages/public_courses_page.dart';
import 'package:fluffychat/pangea/login/pages/signup.dart';
import 'package:fluffychat/pangea/space_analytics/space_analytics.dart';
import 'package:fluffychat/pangea/spaces/constants/space_constants.dart';
@ -207,7 +207,7 @@ abstract class AppRoutes {
pageBuilder: (context, state) => defaultPageBuilder(
context,
state,
const PlanTripPage(route: 'registration'),
const AddCoursePage(route: 'registration'),
),
routes: [
GoRoute(
@ -216,7 +216,7 @@ abstract class AppRoutes {
return defaultPageBuilder(
context,
state,
const PrivateTripPage(),
const CourseCodePage(),
);
},
),
@ -226,7 +226,7 @@ abstract class AppRoutes {
return defaultPageBuilder(
context,
state,
const PublicTripPage(
const PublicCoursesPage(
route: 'registration',
showFilters: false,
),
@ -255,7 +255,7 @@ abstract class AppRoutes {
return defaultPageBuilder(
context,
state,
const NewTripPage(
const NewCoursePage(
route: 'registration',
showFilters: false,
),
@ -428,7 +428,7 @@ abstract class AppRoutes {
pageBuilder: (context, state) => defaultPageBuilder(
context,
state,
const PlanTripPage(route: 'rooms'),
const AddCoursePage(route: 'rooms'),
),
routes: [
GoRoute(
@ -437,7 +437,7 @@ abstract class AppRoutes {
return defaultPageBuilder(
context,
state,
const PrivateTripPage(),
const CourseCodePage(),
);
},
),
@ -447,7 +447,7 @@ abstract class AppRoutes {
return defaultPageBuilder(
context,
state,
const PublicTripPage(
const PublicCoursesPage(
route: 'rooms',
),
);
@ -475,7 +475,7 @@ abstract class AppRoutes {
return defaultPageBuilder(
context,
state,
const NewTripPage(route: 'rooms'),
const NewCoursePage(route: 'rooms'),
);
},
routes: [
@ -862,7 +862,7 @@ abstract class AppRoutes {
pageBuilder: (context, state) => defaultPageBuilder(
context,
state,
NewTripPage(
NewCoursePage(
route: 'rooms',
spaceId: state.pathParameters['spaceid']!,
),

View file

@ -5173,7 +5173,6 @@
"saveToCompletedActivities": "Save to completed activities",
"generatingSummary": "Analyzing chat and generating results",
"instructionsLanguage": "Instructions language",
"findCourse": "Find a course",
"activityCompletedDesc": "Your completed activity was added to analytics where you can review and practice the language you used.",
"pingParticipantsNotification": "{user} is looking for users to join the activity session in {room}",
"@pingParticipantsNotification": {
@ -5263,18 +5262,9 @@
"languages": "Languages",
"chooseLanguage": "Choose a language.",
"letsGo": "Let's go",
"planTrip": "Plan your trip",
"howAreYouTraveling": "How are you traveling?",
"unlockPrivateTrip": "Unlock a private trip",
"joinPublicTrip": "Join a public trip",
"startOwnTrip": "Start my own",
"tripPlanDesc": "Trips are courses. Each has 8-10 sequenced topics with a range of task-based language learning activities.",
"unlockPrivateTripTitle": "Unlock private trip",
"browsePublicTrips": "Browse public trips",
"startOwnTripTitle": "Start my own trip",
"courseCode": "Whats the secret password?",
"courseCodeHint": "Trip code or link",
"unlockMyTrip": "Unlock my trip",
"startOwn": "Start my own",
"joinCourseDesc": "Each course has 8-10 sequenced topics with a range of task-based language learning activities.",
"courseCodeHint": "Course code",
"anyLevel": "Any Level",
"signupOption": "How do you want to sign up?",
"withApple": "With Apple",
@ -5320,5 +5310,8 @@
"@shareCourse": {
"type": "String",
"placeholders": {}
}
},
"addCourse": "Add a course",
"joinCourseWithCode": "Join course with code",
"joinPublicCourse": "Join public course"
}

View file

@ -8,9 +8,9 @@ import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/pangea/common/widgets/pangea_logo_svg.dart';
class PlanTripPage extends StatelessWidget {
class AddCoursePage extends StatelessWidget {
final String route;
const PlanTripPage({
const AddCoursePage({
required this.route,
super.key,
});
@ -28,7 +28,7 @@ class PlanTripPage extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.map_outlined),
Text(L10n.of(context).planTrip),
Text(L10n.of(context).addCourse),
],
),
automaticallyImplyLeading: route == 'registration',
@ -51,12 +51,6 @@ class PlanTripPage extends StatelessWidget {
Column(
spacing: 16.0,
children: [
Text(
L10n.of(context).howAreYouTraveling,
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
ElevatedButton(
onPressed: () => context.go(
'/$route/course/private',
@ -78,7 +72,7 @@ class PlanTripPage extends StatelessWidget {
BlendMode.srcIn,
),
),
Text(L10n.of(context).unlockPrivateTrip),
Text(L10n.of(context).joinCourseWithCode),
],
),
),
@ -99,7 +93,7 @@ class PlanTripPage extends StatelessWidget {
size: 24.0,
color: theme.colorScheme.onPrimaryContainer,
),
Text(L10n.of(context).joinPublicTrip),
Text(L10n.of(context).joinPublicCourse),
],
),
),
@ -124,7 +118,7 @@ class PlanTripPage extends StatelessWidget {
BlendMode.srcIn,
),
),
Text(L10n.of(context).startOwnTrip),
Text(L10n.of(context).startOwn),
],
),
),
@ -132,7 +126,7 @@ class PlanTripPage extends StatelessWidget {
contentPadding: const EdgeInsets.all(0.0),
leading: const Icon(Icons.school),
title: Text(
L10n.of(context).tripPlanDesc,
L10n.of(context).joinCourseDesc,
style: theme.textTheme.labelLarge,
),
),

View file

@ -1,21 +1,24 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/pangea/common/widgets/pangea_logo_svg.dart';
import 'package:fluffychat/pangea/login/pages/add_course_page.dart';
import 'package:fluffychat/widgets/matrix.dart';
class PrivateTripPage extends StatefulWidget {
const PrivateTripPage({
class CourseCodePage extends StatefulWidget {
const CourseCodePage({
super.key,
});
@override
State<PrivateTripPage> createState() => PrivateTripPageState();
State<CourseCodePage> createState() => CourseCodePageState();
}
class PrivateTripPageState extends State<PrivateTripPage> {
class CourseCodePageState extends State<CourseCodePage> {
final TextEditingController _codeController = TextEditingController();
@override
@ -57,8 +60,16 @@ class PrivateTripPageState extends State<PrivateTripPage> {
spacing: 10.0,
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.map_outlined),
Text(L10n.of(context).unlockPrivateTripTitle),
SvgPicture.network(
"${AppConfig.assetsBaseURL}/${AddCoursePage.mapUnlockFileName}",
width: 24.0,
height: 24.0,
colorFilter: ColorFilter.mode(
theme.colorScheme.onSurface,
BlendMode.srcIn,
),
),
Text(L10n.of(context).joinCourseWithCode),
],
),
),
@ -81,7 +92,7 @@ class PrivateTripPageState extends State<PrivateTripPage> {
spacing: 16.0,
children: [
Text(
L10n.of(context).courseCode,
L10n.of(context).enterCodeToJoin,
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
@ -102,7 +113,7 @@ class PrivateTripPageState extends State<PrivateTripPage> {
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(L10n.of(context).unlockMyTrip),
Text(L10n.of(context).submit),
],
),
),

View file

@ -1,22 +1,25 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/pangea/bot/widgets/bot_face_svg.dart';
import 'package:fluffychat/pangea/common/widgets/url_image_widget.dart';
import 'package:fluffychat/pangea/course_creation/course_info_chip_widget.dart';
import 'package:fluffychat/pangea/course_creation/course_language_filter.dart';
import 'package:fluffychat/pangea/course_creation/course_search_provider.dart';
import 'package:fluffychat/pangea/login/pages/add_course_page.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/matrix.dart';
class NewTripPage extends StatefulWidget {
class NewCoursePage extends StatefulWidget {
final String route;
final String? spaceId;
final bool showFilters;
const NewTripPage({
const NewCoursePage({
super.key,
required this.route,
this.spaceId,
@ -24,10 +27,11 @@ class NewTripPage extends StatefulWidget {
});
@override
State<NewTripPage> createState() => NewTripPageState();
State<NewCoursePage> createState() => NewCoursePageState();
}
class NewTripPageState extends State<NewTripPage> with CourseSearchProvider {
class NewCoursePageState extends State<NewCoursePage>
with CourseSearchProvider {
@override
void initState() {
super.initState();
@ -49,11 +53,19 @@ class NewTripPageState extends State<NewTripPage> with CourseSearchProvider {
spacing: 10.0,
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.map_outlined),
SvgPicture.network(
"${AppConfig.assetsBaseURL}/${AddCoursePage.mapStartFileName}",
width: 24.0,
height: 24.0,
colorFilter: ColorFilter.mode(
theme.colorScheme.onSurface,
BlendMode.srcIn,
),
),
Text(
spaceId != null
? L10n.of(context).addCoursePlan
: L10n.of(context).startOwnTripTitle,
: L10n.of(context).startOwn,
),
],
),

View file

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/l10n/l10n.dart';
@ -17,20 +18,20 @@ import 'package:fluffychat/pangea/spaces/utils/public_course_extension.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/matrix.dart';
class PublicTripPage extends StatefulWidget {
class PublicCoursesPage extends StatefulWidget {
final String route;
final bool showFilters;
const PublicTripPage({
const PublicCoursesPage({
super.key,
required this.route,
this.showFilters = true,
});
@override
State<PublicTripPage> createState() => PublicTripPageState();
State<PublicCoursesPage> createState() => PublicCoursesPageState();
}
class PublicTripPageState extends State<PublicTripPage> {
class PublicCoursesPageState extends State<PublicCoursesPage> {
bool loading = true;
Object? error;
@ -153,8 +154,10 @@ class PublicTripPageState extends State<PublicTripPage> {
spacing: 10.0,
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.map_outlined),
Text(L10n.of(context).browsePublicTrips),
const Icon(
Symbols.map_search,
),
Text(L10n.of(context).joinPublicCourse),
],
),
),
@ -217,7 +220,7 @@ class PublicTripPageState extends State<PublicTripPage> {
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(L10n.of(context).startOwnTrip),
Text(L10n.of(context).startOwn),
],
),
),
@ -291,11 +294,36 @@ class PublicTripPageState extends State<PublicTripPage> {
),
),
Flexible(
child: Text(
displayname,
style: theme.textTheme.bodyLarge,
maxLines: 2,
overflow: TextOverflow.ellipsis,
child: Column(
spacing: 0.0,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
displayname,
style: theme.textTheme.bodyLarge,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
Row(
spacing: 4.0,
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
Icons.group,
size: 16.0,
),
Text(
L10n.of(context)
.countParticipants(
roomChunk.numJoinedMembers,
),
style:
theme.textTheme.bodyMedium,
),
],
),
],
),
),
],

View file

@ -178,7 +178,7 @@ class SpacesNavigationRail extends StatelessWidget {
child: const Icon(Icons.add),
),
),
toolTip: L10n.of(context).findCourse,
toolTip: L10n.of(context).addCourse,
// Pangea#
);
}