// shows n rows of activity suggestions vertically, where n is the number of rows // as the user tries to scroll horizontally to the right, the client will fetch more activity suggestions import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; import 'package:shimmer/shimmer.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; import 'package:fluffychat/pangea/activity_planner/media_enum.dart'; import 'package:fluffychat/pangea/activity_suggestions/activity_plan_search_repo.dart'; import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_card.dart'; import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog.dart'; import 'package:fluffychat/pangea/activity_suggestions/activity_suggestions_constants.dart'; import 'package:fluffychat/pangea/common/widgets/customized_svg.dart'; import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; import 'package:fluffychat/widgets/matrix.dart'; class ActivitySuggestionsArea extends StatefulWidget { final Axis? scrollDirection; final bool showTitle; final Room? room; const ActivitySuggestionsArea({ super.key, this.scrollDirection, this.showTitle = false, this.room, }); @override ActivitySuggestionsAreaState createState() => ActivitySuggestionsAreaState(); } class ActivitySuggestionsAreaState extends State { @override void initState() { super.initState(); _setActivityItems(); } @override void dispose() { _scrollController.dispose(); super.dispose(); } bool _loading = true; bool get _isColumnMode => FluffyThemes.isColumnMode(context); final List _activityItems = []; final ScrollController _scrollController = ScrollController(); double get cardHeight => _isColumnMode ? 325.0 : 250.0; double get cardWidth => _isColumnMode ? 225.0 : 150.0; Future _setActivityItems() async { try { final ActivityPlanRequest request = ActivityPlanRequest( topic: "", mode: "", objective: "", media: MediaEnum.nan, cefrLevel: LanguageLevelTypeEnum.a1, languageOfInstructions: LanguageKeys.defaultLanguage, targetLanguage: MatrixState.pangeaController.languageController.userL2?.langCode ?? LanguageKeys.defaultLanguage, numberOfParticipants: 3, count: 5, ); final resp = await ActivitySearchRepo.get(request); _activityItems.addAll(resp.activityPlans); } finally { if (mounted) setState(() => _loading = false); } } @override Widget build(BuildContext context) { final theme = Theme.of(context); final isColumnMode = FluffyThemes.isColumnMode(context); final List cards = _loading ? List.generate(5, (i) { return Shimmer.fromColors( baseColor: theme.colorScheme.primary.withAlpha(20), highlightColor: theme.colorScheme.primary.withAlpha(50), child: Container( height: cardHeight, width: cardWidth, decoration: BoxDecoration( color: theme.colorScheme.surfaceContainer, borderRadius: BorderRadius.circular(24.0), ), ), ); }) : _activityItems .map((activity) { return ActivitySuggestionCard( activity: activity, onPressed: () { showDialog( context: context, builder: (context) { return ActivitySuggestionDialog( activity: activity, buttonText: L10n.of(context).inviteAndLaunch, room: widget.room, ); }, ); }, width: cardWidth, height: cardHeight, onChange: () { if (mounted) setState(() {}); }, ); }) .cast() .toList(); final scrollDirection = widget.scrollDirection ?? (_isColumnMode ? Axis.horizontal : Axis.vertical); return Column( spacing: 8.0, children: [ if (widget.showTitle) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Flexible( child: Text( L10n.of(context).startChat, style: isColumnMode ? theme.textTheme.titleLarge ?.copyWith(fontWeight: FontWeight.bold) : theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), overflow: TextOverflow.ellipsis, ), ), Row( spacing: 8.0, children: [ InkWell( customBorder: const CircleBorder(), onTap: () => context.go('/homepage/newgroup'), child: Container( decoration: BoxDecoration( color: theme.colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(36.0), ), padding: const EdgeInsets.symmetric( vertical: 6.0, horizontal: 10.0, ), child: Row( spacing: 8.0, mainAxisSize: MainAxisSize.min, children: [ CustomizedSvg( svgUrl: "${AppConfig.assetsBaseURL}/${ActivitySuggestionsConstants.plusIconPath}", colorReplacements: { "#CDBEF9": colorToHex( Theme.of(context).colorScheme.secondary, ), }, height: 16.0, width: 16.0, ), Text( isColumnMode ? L10n.of(context).createOwnChat : L10n.of(context).chat, style: theme.textTheme.titleSmall?.copyWith( fontWeight: FontWeight.bold, ), ), ], ), ), ), InkWell( customBorder: const CircleBorder(), onTap: () => context.go('/homepage/planner'), child: Container( decoration: BoxDecoration( color: theme.colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(36.0), ), padding: const EdgeInsets.symmetric( vertical: 6.0, horizontal: 10.0, ), child: Row( spacing: 8.0, mainAxisSize: MainAxisSize.min, children: [ CustomizedSvg( svgUrl: "${AppConfig.assetsBaseURL}/${ActivitySuggestionsConstants.crayonIconPath}", colorReplacements: { "#CDBEF9": colorToHex( Theme.of(context).colorScheme.secondary, ), }, height: 16.0, width: 16.0, ), Text( isColumnMode ? L10n.of(context).makeYourOwnActivity : L10n.of(context).createActivity, style: theme.textTheme.titleSmall?.copyWith( fontWeight: FontWeight.bold, ), ), ], ), ), ), ], ), ], ), Container( decoration: const BoxDecoration(), child: scrollDirection == Axis.horizontal ? Scrollbar( thumbVisibility: true, controller: _scrollController, child: Padding( padding: const EdgeInsets.only(bottom: 16.0), child: SingleChildScrollView( controller: _scrollController, scrollDirection: Axis.horizontal, child: Row( spacing: 8.0, children: cards, ), ), ), ) : SizedBox( width: MediaQuery.of(context).size.width, child: Wrap( alignment: WrapAlignment.spaceEvenly, runSpacing: 16.0, spacing: 4.0, children: cards, ), ), ), ], ); } }