mymuseum-visitapp/lib/Helpers/assistantSuggestions.dart

120 lines
4.4 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:mymuseum_visitapp/Helpers/translationHelper.dart';
import 'package:mymuseum_visitapp/Models/visitContext.dart';
/// Questions proposées au visiteur quand il ouvre l'assistant.
///
/// Dérivées du contenu réel de la configuration : les sections sont déjà en
/// mémoire (`VisitAppContext.currentSections`, alimenté au chargement de la
/// configuration) et leurs titres déjà traduits par le CMS. Un lieu sans agenda
/// ne propose donc pas de question sur l'agenda.
///
/// Miroir de `visitapp-web/src/lib/assistantSuggestions.ts` — garder les deux
/// listes de phrases alignées.
class AssistantSuggestions {
static const int _max = 3;
static const Map<String, Map<String, String>> _phrases = {
'aboutSection': {
'FR': 'Parlez-moi de « {name} »',
'NL': 'Vertel me over "{name}"',
'EN': 'Tell me about "{name}"',
'DE': 'Erzählen Sie mir von „{name}"',
'ES': 'Háblame de «{name}»',
'IT': 'Parlami di "{name}"',
},
'whatsOn': {
'FR': "Qu'est-ce qu'il y a cette semaine ?",
'NL': 'Wat is er deze week te doen?',
'EN': "What's on this week?",
'DE': 'Was gibt es diese Woche?',
'ES': '¿Qué hay esta semana?',
'IT': 'Cosa cè questa settimana?',
},
'withKids': {
'FR': 'Que faire avec des enfants ?',
'NL': 'Wat kunnen we doen met kinderen?',
'EN': 'What can we do with children?',
'DE': 'Was können wir mit Kindern machen?',
'ES': '¿Qué hacer con niños?',
'IT': 'Cosa fare con i bambini?',
},
'highlights': {
'FR': "Qu'est-ce qu'il ne faut pas manquer ?",
'NL': 'Wat mag ik niet missen?',
'EN': "What shouldn't I miss?",
'DE': 'Was sollte ich nicht verpassen?',
'ES': '¿Qué no me puedo perder?',
'IT': 'Cosa non devo perdere?',
},
'inOneHour': {
'FR': "Que voir si je n'ai qu'une heure ?",
'NL': 'Wat zie ik als ik maar één uur heb?',
'EN': 'What should I see in one hour?',
'DE': 'Was sollte ich in einer Stunde sehen?',
'ES': '¿Qué ver si solo tengo una hora?',
'IT': 'Cosa vedere se ho solo unora?',
},
'openingHours': {
'FR': 'Quels sont les horaires ?',
'NL': 'Wat zijn de openingstijden?',
'EN': 'What are the opening hours?',
'DE': 'Wie sind die Öffnungszeiten?',
'ES': '¿Cuál es el horario?',
'IT': 'Quali sono gli orari?',
},
};
static String _phrase(String key, String lang, [String? name]) {
final table = _phrases[key]!;
final template = table[lang] ?? table['FR']!;
return name == null ? template : template.replaceAll('{name}', name);
}
static String _titleOf(Map<String, dynamic> section, String lang) {
final titles = section['title'];
if (titles is! List || titles.isEmpty) return '';
final match = titles.firstWhere(
(t) => t is Map && t['language'] == lang && (t['value'] as String?)?.isNotEmpty == true,
orElse: () => titles.first,
);
if (match is! Map) return '';
return TranslationHelper.stripHtml((match['value'] as String?) ?? '');
}
static List<String> build(VisitAppContext context, {String? currentSectionId}) {
final lang = (context.language ?? 'FR').toUpperCase();
final sections = (context.currentSections ?? [])
.whereType<Map<String, dynamic>>()
.where((s) => s['isActive'] != false && s['isSubSection'] != true)
.toList();
bool has(String type) => sections.any((s) => s['type'] == type);
final suggestions = <String>[];
// La section ouverte passe en premier : c'est ce que le visiteur a sous les yeux.
if (currentSectionId != null) {
final current = sections.firstWhere(
(s) => s['id'] == currentSectionId,
orElse: () => <String, dynamic>{},
);
if (current.isNotEmpty) {
final name = _titleOf(current, lang);
if (name.isNotEmpty) suggestions.add(_phrase('aboutSection', lang, name));
}
}
if (has('Agenda')) suggestions.add(_phrase('whatsOn', lang));
if (has('Parcours') || has('Game')) suggestions.add(_phrase('withKids', lang));
// Génériques — trois, pour qu'un lieu minimal ait quand même le compte complet.
suggestions.add(_phrase('highlights', lang));
suggestions.add(_phrase('inOneHour', lang));
suggestions.add(_phrase('openingHours', lang));
return suggestions.toSet().take(_max).toList();
}
}