From 45c31afc2b68eba0a7ecf2961c546d1ea91b0561 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 15 Jan 2026 10:36:31 -0500 Subject: [PATCH] display grammar copy --- .../analytics_practice_page.dart | 9 +++- .../analytics_practice_session_repo.dart | 1 + .../analytics_practice_view.dart | 16 ++++++- .../choice_cards/grammar_choice_card.dart | 48 +++++++++++++++++++ .../morph_category_activity_generator.dart | 6 +-- .../practice_activities/practice_target.dart | 9 +++- 6 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 lib/pangea/analytics_practice/choice_cards/grammar_choice_card.dart diff --git a/lib/pangea/analytics_practice/analytics_practice_page.dart b/lib/pangea/analytics_practice/analytics_practice_page.dart index 250a267d9..d85725f48 100644 --- a/lib/pangea/analytics_practice/analytics_practice_page.dart +++ b/lib/pangea/analytics_practice/analytics_practice_page.dart @@ -163,6 +163,9 @@ class AnalyticsPracticeState extends State } String getChoiceText(PracticeTarget target, String choiceId) { + if (widget.type == ConstructTypeEnum.morph) { + return choiceId; + } if (_choiceTexts.containsKey(target) && _choiceTexts[target]!.containsKey(choiceId)) { return _choiceTexts[target]![choiceId]!; @@ -171,8 +174,10 @@ class AnalyticsPracticeState extends State return cId?.lemma ?? choiceId; } - String? getChoiceEmoji(PracticeTarget target, String choiceId) => - _choiceEmojis[target]?[choiceId]; + String? getChoiceEmoji(PracticeTarget target, String choiceId) { + if (widget.type == ConstructTypeEnum.morph) return null; + return _choiceEmojis[target]?[choiceId]; + } String choiceTargetId(String choiceId) => '${widget.type.name}-choice-card-${choiceId.replaceAll(' ', '_')}'; diff --git a/lib/pangea/analytics_practice/analytics_practice_session_repo.dart b/lib/pangea/analytics_practice/analytics_practice_session_repo.dart index ecc97ef2a..27c4d5700 100644 --- a/lib/pangea/analytics_practice/analytics_practice_session_repo.dart +++ b/lib/pangea/analytics_practice/analytics_practice_session_repo.dart @@ -132,6 +132,7 @@ class AnalyticsPracticeSessionRepo { break; } + if (use.lemma.isEmpty) continue; final form = use.form; if (seenForms.contains(form) || form == null) { continue; diff --git a/lib/pangea/analytics_practice/analytics_practice_view.dart b/lib/pangea/analytics_practice/analytics_practice_view.dart index bb6cf5716..3e9379d26 100644 --- a/lib/pangea/analytics_practice/analytics_practice_view.dart +++ b/lib/pangea/analytics_practice/analytics_practice_view.dart @@ -6,6 +6,7 @@ import 'package:fluffychat/pangea/analytics_practice/analytics_practice_page.dar import 'package:fluffychat/pangea/analytics_practice/analytics_practice_session_model.dart'; import 'package:fluffychat/pangea/analytics_practice/choice_cards/audio_choice_card.dart'; import 'package:fluffychat/pangea/analytics_practice/choice_cards/game_choice_card.dart'; +import 'package:fluffychat/pangea/analytics_practice/choice_cards/grammar_choice_card.dart'; import 'package:fluffychat/pangea/analytics_practice/choice_cards/meaning_choice_card.dart'; import 'package:fluffychat/pangea/analytics_practice/completed_activity_session_view.dart'; import 'package:fluffychat/pangea/analytics_practice/practice_timer_widget.dart'; @@ -122,7 +123,7 @@ class _AnalyticsActivityView extends StatelessWidget { valueListenable: controller.activityTarget, builder: (context, target, __) => target != null ? Text( - target.promptText(), + target.promptText(context), textAlign: TextAlign.center, style: Theme.of(context).textTheme.titleLarge?.copyWith( @@ -335,6 +336,19 @@ class _ChoiceCard extends StatelessWidget { height: cardHeight, ); + case ActivityTypeEnum.grammarCategory: + return GrammarChoiceCard( + key: ValueKey( + '${constructId.string}_${activityType.name}_grammar_$choiceId', + ), + choiceId: choiceId, + targetId: targetId, + feature: (activity as MorphPracticeActivityModel).morphFeature, + tag: choiceText, + onPressed: onPressed, + isCorrect: isCorrect, + ); + default: return GameChoiceCard( key: ValueKey( diff --git a/lib/pangea/analytics_practice/choice_cards/grammar_choice_card.dart b/lib/pangea/analytics_practice/choice_cards/grammar_choice_card.dart new file mode 100644 index 000000000..c1299b611 --- /dev/null +++ b/lib/pangea/analytics_practice/choice_cards/grammar_choice_card.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; + +import 'package:fluffychat/pangea/analytics_practice/choice_cards/game_choice_card.dart'; +import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; +import 'package:fluffychat/pangea/morphs/morph_features_enum.dart'; + +/// Choice card for meaning activity with emoji, and alt text on flip +class GrammarChoiceCard extends StatelessWidget { + final String choiceId; + final String targetId; + + final MorphFeaturesEnum feature; + final String tag; + + final VoidCallback onPressed; + final bool isCorrect; + final double height; + + const GrammarChoiceCard({ + required this.choiceId, + required this.targetId, + required this.feature, + required this.tag, + required this.onPressed, + required this.isCorrect, + this.height = 72.0, + super.key, + }); + + @override + Widget build(BuildContext context) { + final copy = getGrammarCopy( + category: feature.name, + lemma: tag, + context: context, + ) ?? + tag; + + return GameChoiceCard( + shouldFlip: false, + targetId: targetId, + onPressed: onPressed, + isCorrect: isCorrect, + height: height, + child: Text(copy), + ); + } +} diff --git a/lib/pangea/analytics_practice/morph_category_activity_generator.dart b/lib/pangea/analytics_practice/morph_category_activity_generator.dart index d9020b7b5..adae7a3ea 100644 --- a/lib/pangea/analytics_practice/morph_category_activity_generator.dart +++ b/lib/pangea/analytics_practice/morph_category_activity_generator.dart @@ -45,9 +45,9 @@ class MorphCategoryActivityGenerator { ) .toList(); - possibleDistractors.shuffle(); - final choices = possibleDistractors.take(3).toSet(); + final choices = possibleDistractors.take(3).toList(); choices.add(morphTag); + choices.shuffle(); return MessageActivityResponse( activity: MorphCategoryPracticeActivityModel( @@ -55,7 +55,7 @@ class MorphCategoryActivityGenerator { langCode: req.userL2, morphFeature: feature, multipleChoiceContent: MultipleChoiceActivity( - choices: choices, + choices: choices.toSet(), answers: {morphTag}, ), ), diff --git a/lib/pangea/practice_activities/practice_target.dart b/lib/pangea/practice_activities/practice_target.dart index a780112e0..465535591 100644 --- a/lib/pangea/practice_activities/practice_target.dart +++ b/lib/pangea/practice_activities/practice_target.dart @@ -1,9 +1,11 @@ import 'dart:developer'; import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; +import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/constructs/construct_identifier.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; @@ -165,10 +167,13 @@ class PracticeTarget { return false; } - String promptText() { + String promptText(BuildContext context) { switch (activityType) { case ActivityTypeEnum.grammarCategory: - return "${tokens.first.vocabConstructID.lemma}: ${morphFeature!.name}"; + return L10n.of(context).whatIsTheMorphTag( + morphFeature!.getDisplayCopy(context), + tokens.first.text.content, + ); default: return tokens.first.vocabConstructID.lemma; }