Studio lot 8bis : présenter les personnages au visiteur
Écran d'entrée au chargement de la configuration. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011VxSQeGQYUvPmSEoGdnidA
This commit is contained in:
parent
172530e00a
commit
8979ab2e63
118
lib/Components/casting_intro_dialog.dart
Normal file
118
lib/Components/casting_intro_dialog.dart
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:manager_api_new/api.dart';
|
||||||
|
|
||||||
|
/// Écran d'entrée « les personnes que vous allez rencontrer » (plan Studio décision 25).
|
||||||
|
///
|
||||||
|
/// Le serveur n'envoie le casting qu'avec l'interrupteur armé et au moins deux portraits. Montré une
|
||||||
|
/// fois par configuration et par lancement de l'app : revenir à la liste ne le rouvre pas. Comme la
|
||||||
|
/// mention IA, les libellés sont portés ici — l'app n'a pas de traductions pour ses propres textes.
|
||||||
|
class CastingIntroDialog extends StatelessWidget {
|
||||||
|
const CastingIntroDialog({Key? key, required this.casting, required this.language}) : super(key: key);
|
||||||
|
|
||||||
|
final List<CastingVisitorMemberDTO> casting;
|
||||||
|
final String? language;
|
||||||
|
|
||||||
|
static final Set<String> _shown = {};
|
||||||
|
|
||||||
|
static const _titles = {
|
||||||
|
'FR': 'Les personnes que vous allez rencontrer',
|
||||||
|
'NL': 'De personen die u zult ontmoeten',
|
||||||
|
'EN': 'The people you will meet',
|
||||||
|
'DE': 'Die Menschen, denen Sie begegnen werden',
|
||||||
|
'ES': 'Las personas que va a conocer',
|
||||||
|
'IT': 'Le persone che incontrerete',
|
||||||
|
'PL': 'Osoby, które spotkasz',
|
||||||
|
'CN': '您将遇到的人物',
|
||||||
|
'AR': 'الشخصيات التي ستلتقيها',
|
||||||
|
'UK': 'Люди, яких ви зустрінете',
|
||||||
|
'LB': "D'Leit, déi Dir kenne léiert",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const _starts = {
|
||||||
|
'FR': 'Commencer la visite',
|
||||||
|
'NL': 'Het bezoek beginnen',
|
||||||
|
'EN': 'Start the visit',
|
||||||
|
'DE': 'Besuch beginnen',
|
||||||
|
'ES': 'Empezar la visita',
|
||||||
|
'IT': 'Inizia la visita',
|
||||||
|
'PL': 'Rozpocznij zwiedzanie',
|
||||||
|
'CN': '开始参观',
|
||||||
|
'AR': 'ابدأ الزيارة',
|
||||||
|
'UK': 'Почати відвідування',
|
||||||
|
'LB': 'Besuch ufänken',
|
||||||
|
};
|
||||||
|
|
||||||
|
static void showIfNeeded(BuildContext context, ConfigurationDTO configuration, String? language) {
|
||||||
|
final casting = configuration.casting;
|
||||||
|
if (casting == null || casting.length < 2 || configuration.id == null) return;
|
||||||
|
if (!_shown.add(configuration.id!)) return;
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => CastingIntroDialog(casting: casting, language: language),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _label(Map<String, String> labels) => labels[(language ?? 'FR').toUpperCase()] ?? labels['FR']!;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Dialog(
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(22)),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(20, 24, 20, 20),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
_label(_titles),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w700, color: Color(0xFF1E2A33)),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Wrap(
|
||||||
|
alignment: WrapAlignment.center,
|
||||||
|
spacing: 16,
|
||||||
|
runSpacing: 16,
|
||||||
|
children: casting
|
||||||
|
.map((member) => SizedBox(
|
||||||
|
width: 110,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
ClipOval(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 88,
|
||||||
|
height: 88,
|
||||||
|
child: Image.network(
|
||||||
|
member.portraitUrl ?? '',
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
errorBuilder: (_, __, ___) => Container(color: const Color(0xFFE8E3DA)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text(member.name ?? '',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600)),
|
||||||
|
if ((member.role ?? '').isNotEmpty)
|
||||||
|
Text(member.role!,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(fontSize: 12, color: Color(0xFF6B7B86))),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
child: FilledButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text(_label(_starts)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:tablet_app/Components/casting_intro_dialog.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
@ -328,6 +329,11 @@ class _MainViewWidget extends State<MainViewWidget> {
|
|||||||
|
|
||||||
await getCurrentConfiguration(appContext);
|
await getCurrentConfiguration(appContext);
|
||||||
|
|
||||||
|
final loadedConfiguration = tabletAppContext.configuration;
|
||||||
|
if (mounted && loadedConfiguration != null) {
|
||||||
|
CastingIntroDialog.showIfNeeded(context, loadedConfiguration, tabletAppContext.language);
|
||||||
|
}
|
||||||
|
|
||||||
// Load applicationInstanceDTO to check if assistant/statistics are enabled
|
// Load applicationInstanceDTO to check if assistant/statistics are enabled
|
||||||
try {
|
try {
|
||||||
if (tabletAppContext.instanceId != null) {
|
if (tabletAppContext.instanceId != null) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user