diff --git a/lib/Helpers/translations.dart b/lib/Helpers/translations.dart index c4a5952..48a978a 100644 --- a/lib/Helpers/translations.dart +++ b/lib/Helpers/translations.dart @@ -16,7 +16,8 @@ List translations = [ "quiz.seeResponses": "Voir les réponses", "quiz.restart": "Recommencer", "map.search": "Rechercher", - "back": "Retour" + "back": "Retour", + "event.live": "En cours" }), Translation(language: "EN", data: { "weather.hourly": "Hourly", @@ -33,7 +34,8 @@ List translations = [ "quiz.seeResponses": "See the answers", "quiz.restart": "Restart", "map.search": "Search", - "back": "Back" + "back": "Back", + "event.live": "Now on" }), Translation(language: "DE", data: { "weather.hourly": "Nächste Stunden", @@ -50,7 +52,8 @@ List translations = [ "quiz.seeResponses": "Sehen Sie sich die Antworten an", "quiz.restart": "Neu starten", "map.search": "Suchen", - "back": "Zurück" + "back": "Zurück", + "event.live": "Läuft" }), Translation(language: "NL", data: { "weather.hourly": "Volgende uren", @@ -67,7 +70,8 @@ List translations = [ "quiz.seeResponses": "Zie de antwoorden", "quiz.restart": "Herstarten", "map.search": "Zoeken", - "back": "Rug" + "back": "Rug", + "event.live": "Nu bezig" }), Translation(language: "IT", data: { "weather.hourly": "Le prossime ore", @@ -84,7 +88,8 @@ List translations = [ "quiz.seeResponses": "Vedi le risposte", "quiz.restart": "Ricomincia", "map.search": "Cerca", - "back": "Indietro" + "back": "Indietro", + "event.live": "In corso" }), Translation(language: "ES", data: { "weather.hourly": "Próximas horas", @@ -101,7 +106,8 @@ List translations = [ "quiz.seeResponses": "Ver las respuestas", "quiz.restart": "Reanudar", "map.search": "Buscar", - "back": "Atrás" + "back": "Atrás", + "event.live": "En curso" }), Translation(language: "PL", data: { "weather.hourly": "Następne godziny", @@ -118,7 +124,8 @@ List translations = [ "quiz.seeResponses": "Zobacz odpowiedzi", "quiz.restart": "Uruchom ponownie", "map.search": "Szukaj", - "back": "Z powrotem" + "back": "Z powrotem", + "event.live": "Trwa" }), Translation(language: "CN", data: { "weather.hourly": "接下来的几个小时", @@ -135,7 +142,8 @@ List translations = [ "quiz.seeResponses": "查看答案", "quiz.restart": "重新开始", "map.search": "搜索", - "back": "后退" + "back": "后退", + "event.live": "进行中" }), Translation(language: "UK", data: { "weather.hourly": "Наступні години", @@ -152,7 +160,8 @@ List translations = [ "quiz.seeResponses": "Подивіться відповіді", "quiz.restart": "Перезапустіть", "map.search": "Шукати", - "back": "Назад" + "back": "Назад", + "event.live": "Зараз" }), Translation(language: "AR", data: { "weather.hourly": "الساعات القادمة", @@ -169,6 +178,7 @@ List translations = [ "quiz.seeResponses": "انظر الإجابات", "quiz.restart": "إعادة تشغيل", "map.search": "بحث", - "back": "خلف" + "back": "خلف", + "event.live": "جارٍ الآن" }), ]; \ No newline at end of file diff --git a/lib/Screens/Article/article_view.dart b/lib/Screens/Article/article_view.dart index 38fa35f..c5c433f 100644 --- a/lib/Screens/Article/article_view.dart +++ b/lib/Screens/Article/article_view.dart @@ -1,47 +1,227 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; -//import 'dart:html'; -import 'dart:ui' as ui; - -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:manager_api_new/api.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:tablet_app/Components/loading_common.dart'; +import 'package:provider/provider.dart'; +import 'package:tablet_app/Components/cached_custom_resource.dart'; +import 'package:tablet_app/Helpers/ImageCustomProvider.dart'; +import 'package:tablet_app/Helpers/translationHelper.dart'; +import 'package:tablet_app/Models/tabletContext.dart'; +import 'package:tablet_app/app_context.dart'; +import 'package:tablet_app/constants.dart'; +/// Largeur de lecture. Une borne fait 1280 px de large : étirer le texte sur +/// toute la dalle le rend illisible, l'œil perd la ligne au retour. +const double kArticleMeasure = 720.0; + +const double kMediaRailFlex = 38.0; +const double kArticleTextFlex = 62.0; class ArticleView extends StatefulWidget { - final SectionDTO? section; - ArticleView({this.section}); + final ArticleDTO section; + + const ArticleView({Key? key, required this.section}) : super(key: key); @override - _ArticleView createState() => _ArticleView(); + State createState() => _ArticleViewState(); } -class _ArticleView extends State { - ArticleDTO articleDTO = ArticleDTO(); +class _ArticleViewState extends State { + String _audioId = ""; + ResourceDTO? _audioResource; @override void initState() { - /*print(widget.section!.data); - agendaDTO = AgendaDTO.fromJson(jsonDecode(widget.section!.data!))!; - print(agendaDTO);*/ - super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) => _resolveAudio()); } - @override - void dispose() { - //_webView = null; - super.dispose(); + /// L'audio est porté par langue : `audioIds` est une List. + /// Pas d'entrée pour la langue choisie = pas de lecteur, sans repli sur une + /// autre langue — servir l'audio français à un néerlandophone est pire que + /// le silence. + Future _resolveAudio() async { + final tabletAppContext = + Provider.of(context, listen: false).getContext() as TabletAppContext; + final audioId = TranslationHelper.get(widget.section.audioIds, tabletAppContext); + if (audioId.isEmpty) return; + + final embedded = widget.section.contents + ?.where((content) => content.resourceId == audioId && content.resource != null) + .firstOrNull; + + if (embedded != null) { + if (mounted) { + setState(() { + _audioId = audioId; + _audioResource = embedded.resource; + }); + } + return; + } + + try { + final resource = await tabletAppContext.clientAPI!.resourceApi!.resourceGetDetail(audioId); + if (resource != null && mounted) { + setState(() { + _audioId = audioId; + _audioResource = resource; + }); + } + } catch (e) { + print("ERROR _resolveAudio ArticleView"); + print(e); + } } + List _medias() { + final contents = widget.section.contents + ?.where((content) => content.resource != null && content.resourceId != _audioId) + .toList() ?? + []; + contents.sort((a, b) => (a.order ?? 0).compareTo(b.order ?? 0)); + return contents; + } @override Widget build(BuildContext context) { - return new Center( - child: Text("TODO Article"), + final appContext = Provider.of(context); + final tabletAppContext = appContext.getContext() as TabletAppContext; + final medias = _medias(); + + if (medias.isEmpty) { + return _buildTextOnly(appContext, tabletAppContext); + } + + final rail = Expanded( + flex: kMediaRailFlex.toInt(), + child: _buildMediaRail(appContext, tabletAppContext, medias), + ); + final text = Expanded( + flex: kArticleTextFlex.toInt(), + child: _buildTextColumn(tabletAppContext, showAudio: false), + ); + + // isContentTop veut dire « le texte avant le média ». En portrait c'était + // au-dessus ; en paysage il n'y a plus de dessus, le drapeau devient le côté. + final contentFirst = widget.section.isContentTop ?? false; + + return Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: contentFirst ? [text, rail] : [rail, text], ); } -} //_webView \ No newline at end of file + + Widget _buildTextOnly(AppContext appContext, TabletAppContext tabletAppContext) { + return Center( + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: kArticleMeasure), + child: _buildTextColumn(tabletAppContext, showAudio: true), + ), + ); + } + + Widget _buildMediaRail( + AppContext appContext, + TabletAppContext tabletAppContext, + List medias, + ) { + final main = medias.first; + final thumbs = medias.skip(1).toList(); + + return Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: CachedCustomResource( + resourceDTO: main.resource!, + isAuto: false, + webView: false, + fit: BoxFit.cover, + ), + ), + ), + if (thumbs.isNotEmpty) ...[ + const SizedBox(height: 12.0), + SizedBox( + height: 90.0, + child: Row( + children: thumbs + .map((content) => Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 8.0), + child: ClipRRect( + borderRadius: BorderRadius.circular(6.0), + child: Image( + image: ImageCustomProvider.getImageProvider( + appContext, + content.resourceId, + content.resource!.url ?? "", + ), + fit: BoxFit.cover, + ), + ), + ), + )) + .toList(), + ), + ), + ], + if (_audioResource != null) ...[ + const SizedBox(height: 12.0), + _buildAudio(), + ], + ], + ), + ); + } + + Widget _buildTextColumn(TabletAppContext tabletAppContext, {required bool showAudio}) { + final title = TranslationHelper.get(widget.section.title, tabletAppContext); + final content = TranslationHelper.get(widget.section.content, tabletAppContext); + + return SingleChildScrollView( + padding: const EdgeInsets.fromLTRB(24.0, 24.0, 24.0, 32.0), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: kArticleMeasure), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (title.isNotEmpty) + Text( + title, + style: const TextStyle( + fontSize: kSectionTitleDetailSize, + fontWeight: FontWeight.bold, + color: kMainGrey, + ), + ), + if (showAudio && _audioResource != null) ...[ + const SizedBox(height: 16.0), + _buildAudio(), + ], + const SizedBox(height: 16.0), + HtmlWidget( + content, + textStyle: const TextStyle( + fontSize: kSectionDescriptionDetailSize, + color: kSecondGrey, + ), + ), + ], + ), + ), + ); + } + + Widget _buildAudio() { + return CachedCustomResource( + resourceDTO: _audioResource!, + isAuto: widget.section.isReadAudioAuto ?? false, + webView: false, + ); + } +} diff --git a/lib/Screens/Event/event_view.dart b/lib/Screens/Event/event_view.dart new file mode 100644 index 0000000..e544cbf --- /dev/null +++ b/lib/Screens/Event/event_view.dart @@ -0,0 +1,465 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_map/flutter_map.dart'; +import 'package:latlong2/latlong.dart' as ll; +import 'package:manager_api_new/api.dart'; +import 'package:provider/provider.dart'; +import 'package:tablet_app/Helpers/ImageCustomProvider.dart'; +import 'package:tablet_app/Helpers/translationHelper.dart'; +import 'package:tablet_app/Models/tabletContext.dart'; +import 'package:tablet_app/app_context.dart'; +import 'package:tablet_app/constants.dart'; + +/// Bande héros : 26 % de la hauteur. Sur mobile elle en prend 52 % et le +/// parallaxe récompense le défilement ; debout devant une borne, personne ne +/// défile pour découvrir qu'il y a un programme dessous. +const double kEventHeroRatio = 0.26; + +const int kEventProgrammeFlex = 44; +const int kEventMapFlex = 56; + +/// Couleur du bloc en cours et de ses annotations. Sémantique, distincte de +/// l'accent : c'est ce qui permet de relier une ligne du programme à un point +/// de la carte sans légende. +const Color kEventLiveColor = Color(0xFFC4622D); + +/// Les coordonnées portées par `geometry.coordinates` sont en **[lng, lat]** +/// (GeoJSON). Celles de `GuidedStep` sont en [lat, lng] — les deux ordres +/// coexistent en production et une confusion ne lève aucune erreur, elle +/// déplace les points. Ne pas réutiliser un helper venu d'un autre contexte. +class _Annotation { + final GeometryType? geometryType; + final Object? coordinates; + final String? polyColor; + + _Annotation(this.geometryType, this.coordinates, this.polyColor); + + static _Annotation fromDto(MapAnnotationDTO a) => + _Annotation(a.geometryType, a.geometry?.coordinates, a.polyColor); + + static _Annotation fromBlock(MapAnnotation a) => + _Annotation(a.geometryType, a.geometry?.coordinates, a.polyColor); +} + +class EventView extends StatefulWidget { + final SectionEventDTO section; + + const EventView({Key? key, required this.section}) : super(key: key); + + @override + State createState() => _EventViewState(); +} + +class _EventViewState extends State { + ProgrammeBlock? _selectedBlock; + + ProgrammeBlock? get _activeBlock { + final now = DateTime.now(); + return widget.section.programme + ?.where((block) => + block.startTime != null && + block.endTime != null && + !now.isBefore(block.startTime!) && + !now.isAfter(block.endTime!)) + .firstOrNull; + } + + Color _primaryColor(TabletAppContext tabletAppContext) { + try { + return Color(int.parse( + tabletAppContext.configuration!.primaryColor!.split('(0x')[1].split(')')[0], + radix: 16)); + } catch (_) { + return kTestSecondColor; + } + } + + String _formatTime(DateTime? date) { + if (date == null) return ""; + return "${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}"; + } + + String _formatDate(DateTime date) => + "${date.day.toString().padLeft(2, '0')}/${date.month.toString().padLeft(2, '0')}/${date.year}"; + + /// Les dates sont numériques, donc lisibles dans toutes les langues sans + /// traduction. C'est ce qui porte l'information « avant / pendant / après » + /// quand l'événement n'a pas lieu aujourd'hui. + String _formatDateRange() { + final start = widget.section.startDate; + final end = widget.section.endDate; + if (start == null && end == null) return ""; + if (start == null) return _formatDate(end!); + if (end == null) return _formatDate(start); + return "${_formatDate(start)} → ${_formatDate(end)}"; + } + + @override + Widget build(BuildContext context) { + final appContext = Provider.of(context); + final tabletAppContext = appContext.getContext() as TabletAppContext; + final primaryColor = _primaryColor(tabletAppContext); + final size = MediaQuery.of(context).size; + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SizedBox( + height: size.height * kEventHeroRatio, + child: _buildHero(appContext, tabletAppContext, primaryColor), + ), + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + flex: kEventProgrammeFlex, + child: _buildProgramme(tabletAppContext, primaryColor), + ), + Expanded( + flex: kEventMapFlex, + child: _buildMapColumn(tabletAppContext, primaryColor), + ), + ], + ), + ), + ], + ); + } + + Widget _buildHero( + AppContext appContext, + TabletAppContext tabletAppContext, + Color primaryColor, + ) { + final title = TranslationHelper.get(widget.section.title, tabletAppContext); + final dateRange = _formatDateRange(); + + return Stack( + fit: StackFit.expand, + children: [ + if (widget.section.imageSource != null) + Image( + image: ImageCustomProvider.getImageProvider( + appContext, + widget.section.imageId, + widget.section.imageSource!, + ), + fit: BoxFit.cover, + ) + else + DecoratedBox( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + primaryColor, + Color.lerp(primaryColor, Colors.white, 0.45) ?? primaryColor, + ], + ), + ), + ), + const DecoratedBox( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Colors.transparent, Colors.black54], + stops: [0.4, 1.0], + ), + ), + ), + Positioned( + left: 24.0, + right: 24.0, + bottom: 18.0, + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Text( + title, + style: const TextStyle( + color: Colors.white, + fontSize: kTitleSize, + fontWeight: FontWeight.bold, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + if (dateRange.isNotEmpty) + Container( + margin: const EdgeInsets.only(left: 16.0), + padding: const EdgeInsets.symmetric(horizontal: 14.0, vertical: 6.0), + decoration: BoxDecoration( + color: Colors.white.withValues(alpha: 0.92), + borderRadius: BorderRadius.circular(20.0), + ), + child: Text( + dateRange, + style: TextStyle( + color: primaryColor, + fontSize: 16.0, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ), + ], + ); + } + + Widget _buildProgramme(TabletAppContext tabletAppContext, Color primaryColor) { + final blocks = widget.section.programme ?? []; + if (blocks.isEmpty) return const SizedBox.shrink(); + + final active = _activeBlock; + + return ListView.builder( + padding: const EdgeInsets.all(16.0), + itemCount: blocks.length, + itemBuilder: (context, index) { + final block = blocks[index]; + return _buildBlock( + tabletAppContext, + primaryColor, + block, + isActive: block == active, + isSelected: block == _selectedBlock, + ); + }, + ); + } + + Widget _buildBlock( + TabletAppContext tabletAppContext, + Color primaryColor, + ProgrammeBlock block, { + required bool isActive, + required bool isSelected, + }) { + final title = TranslationHelper.get(block.title, tabletAppContext); + final start = _formatTime(block.startTime); + final end = _formatTime(block.endTime); + final liveLabel = TranslationHelper.getFromLocale("event.live", tabletAppContext); + + return InkWell( + onTap: () => setState(() => _selectedBlock = isSelected ? null : block), + child: Container( + margin: const EdgeInsets.only(bottom: 10.0), + padding: const EdgeInsets.symmetric(horizontal: 14.0, vertical: 14.0), + decoration: BoxDecoration( + color: isActive ? kEventLiveColor.withValues(alpha: 0.12) : Colors.white, + borderRadius: BorderRadius.circular(8.0), + border: Border.all( + color: isActive + ? kEventLiveColor + : (isSelected ? primaryColor : kBackgroundGrey.withValues(alpha: 0.5)), + width: isSelected && !isActive ? 2.0 : 1.0, + ), + ), + child: Row( + children: [ + SizedBox( + width: 62.0, + child: Text( + start, + style: TextStyle( + fontSize: 16.0, + fontWeight: isActive ? FontWeight.bold : FontWeight.normal, + color: isActive ? kEventLiveColor : kSecondGrey, + ), + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + fontSize: 18.0, + fontWeight: isActive ? FontWeight.bold : FontWeight.w500, + color: kMainGrey, + ), + ), + if (start.isNotEmpty && end.isNotEmpty) + Text( + "$start – $end", + style: const TextStyle(fontSize: 14.0, color: kSecondGrey), + ), + ], + ), + ), + if (isActive && liveLabel.isNotEmpty) + Container( + padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 4.0), + decoration: BoxDecoration( + color: kEventLiveColor, + borderRadius: BorderRadius.circular(12.0), + ), + child: Text( + liveLabel, + style: const TextStyle( + color: Colors.white, + fontSize: 12.0, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ), + ); + } + + Widget _buildMapColumn(TabletAppContext tabletAppContext, Color primaryColor) { + final detail = _selectedBlock; + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded(child: _buildMap(primaryColor)), + if (detail != null) _buildBlockDetail(tabletAppContext, primaryColor, detail), + ], + ); + } + + Widget _buildMap(Color primaryColor) { + final latitude = double.tryParse(widget.section.latitude ?? ""); + final longitude = double.tryParse(widget.section.longitude ?? ""); + final center = latitude != null && longitude != null + ? ll.LatLng(latitude, longitude) + : const ll.LatLng(50.465503, 4.865105); + + final global = (widget.section.globalMapAnnotations ?? []).map(_Annotation.fromDto).toList(); + final blockAnnotations = + (_selectedBlock ?? _activeBlock)?.mapAnnotations?.map(_Annotation.fromBlock).toList() ?? []; + + return FlutterMap( + options: MapOptions(initialCenter: center, initialZoom: 14.0), + children: [ + TileLayer( + urlTemplate: "https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}", + userAgentPackageName: "be.unov.tabletapp", + ), + PolylineLayer(polylines: _polylines(global, primaryColor)), + MarkerLayer(markers: _markers(global, primaryColor)), + PolylineLayer(polylines: _polylines(blockAnnotations, kEventLiveColor)), + MarkerLayer(markers: _markers(blockAnnotations, kEventLiveColor)), + ], + ); + } + + List _markers(List<_Annotation> annotations, Color color) { + final markers = []; + for (final annotation in annotations) { + if (annotation.geometryType?.value != 0) continue; + final coordinates = annotation.coordinates; + if (coordinates is! List || coordinates.length < 2) continue; + markers.add(Marker( + point: ll.LatLng( + (coordinates[1] as num).toDouble(), + (coordinates[0] as num).toDouble(), + ), + width: 34.0, + height: 34.0, + child: Icon(Icons.place, color: color, size: 34.0), + )); + } + return markers; + } + + List _polylines(List<_Annotation> annotations, Color fallback) { + final polylines = []; + for (final annotation in annotations) { + if (annotation.geometryType?.value != 1) continue; + final coordinates = annotation.coordinates; + if (coordinates is! List) continue; + + final points = []; + for (final point in coordinates) { + if (point is List && point.length >= 2) { + points.add(ll.LatLng( + (point[1] as num).toDouble(), + (point[0] as num).toDouble(), + )); + } + } + if (points.length < 2) continue; + + polylines.add(Polyline( + points: points, + color: _polyColor(annotation.polyColor, fallback), + strokeWidth: 4.0, + )); + } + return polylines; + } + + Color _polyColor(String? hex, Color fallback) { + if (hex == null) return fallback; + final value = int.tryParse("FF${hex.replaceAll('#', '')}", radix: 16); + return value != null ? Color(value) : fallback; + } + + /// Sur mobile ce détail s'ouvre en `showModalBottomSheet` : une réponse à + /// l'étroitesse. Sur une borne il y a la place à côté, donc il s'affiche sous + /// la carte sans masquer ce qu'on regardait. + Widget _buildBlockDetail( + TabletAppContext tabletAppContext, + Color primaryColor, + ProgrammeBlock block, + ) { + final title = TranslationHelper.get(block.title, tabletAppContext); + final description = TranslationHelper.get(block.description, tabletAppContext); + + return Container( + constraints: const BoxConstraints(maxHeight: 220.0), + padding: const EdgeInsets.all(18.0), + decoration: BoxDecoration( + color: kBackgroundLight, + border: Border(top: BorderSide(color: kBackgroundGrey.withValues(alpha: 0.5))), + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + title, + style: const TextStyle( + fontSize: 20.0, + fontWeight: FontWeight.bold, + color: kMainGrey, + ), + ), + ), + IconButton( + icon: const Icon(Icons.close, color: kSecondGrey), + onPressed: () => setState(() => _selectedBlock = null), + ), + ], + ), + Text( + "${_formatTime(block.startTime)} – ${_formatTime(block.endTime)}", + style: TextStyle(fontSize: 15.0, color: primaryColor, fontWeight: FontWeight.w600), + ), + if (description.isNotEmpty) ...[ + const SizedBox(height: 10.0), + Text( + description, + style: const TextStyle(fontSize: 16.0, color: kSecondGrey), + ), + ], + ], + ), + ), + ); + } +} diff --git a/lib/Screens/MainView/main_view.dart b/lib/Screens/MainView/main_view.dart index c4f4060..3303aee 100644 --- a/lib/Screens/MainView/main_view.dart +++ b/lib/Screens/MainView/main_view.dart @@ -23,6 +23,7 @@ import 'package:tablet_app/Helpers/MQTTHelper.dart'; import 'package:tablet_app/Helpers/translationHelper.dart'; import 'package:tablet_app/Screens/Agenda/agenda_view.dart'; import 'package:tablet_app/Screens/Article/article_view.dart'; +import 'package:tablet_app/Screens/Event/event_view.dart'; import 'package:tablet_app/Screens/Configuration/config_view.dart'; import 'package:tablet_app/Screens/MainView/section_page_detail.dart'; import 'package:tablet_app/Screens/Weather/weather_view.dart'; @@ -650,9 +651,12 @@ Widget getContent(TabletAppContext tabletAppContext, SectionDTO sectionSelected, case SectionType.Agenda : AgendaDTO agendaDTO = AgendaDTO.fromJson(rawSectionData)!; return AgendaView(section: agendaDTO); - /*case SectionType.article : // TODO - elementToShow = ArticleView(section: sectionSelected); - break;*/ + case SectionType.Article : + ArticleDTO articleDTO = ArticleDTO.fromJson(rawSectionData)!; + return ArticleView(section: articleDTO); + case SectionType.Event : + SectionEventDTO eventDTO = SectionEventDTO.fromJson(rawSectionData)!; + return EventView(section: eventDTO); case SectionType.Weather : WeatherDTO weatherDTO = WeatherDTO.fromJson(rawSectionData)!; return WeatherView(section: weatherDTO);