import 'package:flutter/material.dart'; import 'package:manager_app/Components/multi_string_input_container.dart'; import 'package:manager_app/Components/resource_input_container.dart'; import 'package:manager_app/Screens/Configurations/Section/SubSection/Slider/new_update_image_slider.dart'; import 'package:manager_app/constants.dart'; import 'package:manager_app/l10n/app_localizations.dart'; import 'package:manager_api_new/api.dart'; /// Les champs d'un `ContentDTO`, tels qu'ils étaient dans /// `showNewOrUpdateContentSlider` — mais posés dans le panneau d'édition en /// place du gabarit B au lieu d'une modale. class ContentFields extends StatefulWidget { const ContentFields({ Key? key, required this.content, required this.onChanged, this.showTitle = true, this.showDescription = true, this.resourceTypes = kSliderContentResourceTypes, }) : super(key: key); final ContentDTO content; final VoidCallback onChanged; final bool showTitle; final bool showDescription; final List resourceTypes; @override State createState() => _ContentFieldsState(); } class _ContentFieldsState extends State { @override Widget build(BuildContext context) { final l = AppLocalizations.of(context)!; final content = widget.content; return LayoutBuilder( builder: (context, constraints) { final isWide = constraints.maxWidth > 520; final resource = ResourceInputContainer( label: l.resourceColonLabel, initialValue: content.resourceId, inResourceTypes: widget.resourceTypes, onChanged: (ResourceDTO resource) { setState(() { if (resource.id == null) { content.resourceId = null; content.resource = null; } else { content.resourceId = resource.id; content.resource = resource; } }); widget.onChanged(); }, ); final texts = Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if (widget.showTitle) MultiStringInputContainer( label: l.displayTitleLabel, modalLabel: l.titleModalLabel, isHTML: true, initialValue: content.title ?? [], onGetResult: (value) { setState(() => content.title = value); widget.onChanged(); }, maxLines: 1, isTitle: true, showPreview: true, ), if (widget.showTitle && widget.showDescription) const SizedBox(height: kSpace5), if (widget.showDescription) MultiStringInputContainer( label: l.displayedDescriptionLabel, modalLabel: l.descriptionModalLabel, isHTML: true, initialValue: content.description ?? [], isMandatory: false, onGetResult: (value) { setState(() => content.description = value); widget.onChanged(); }, maxLines: 1, isTitle: false, showPreview: true, ), ], ); if (!widget.showTitle && !widget.showDescription) return resource; if (isWide) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ resource, const SizedBox(width: kSpace5), Expanded(child: texts), ], ); } return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ resource, const SizedBox(height: kSpace5), texts, ], ); }, ); } } /// Le libellé d'un contenu dans la liste : son titre FR, ou son rang. String contentLabel(AppLocalizations l, ContentDTO content, int index) { final titles = content.title ?? []; final title = titles.isEmpty ? "" : (titles .firstWhere((t) => t.language == 'FR', orElse: () => titles.first) .value ?? ""); final plain = title.replaceAll(RegExp(r'<[^>]*>'), ' ').trim(); return plain.isEmpty ? l.untitledContent(index + 1) : plain; } /// Un contenu vide, avec une traduction par langue de la configuration — /// c'est ce que faisait `showNewOrUpdateContentSlider` à l'ouverture. ContentDTO emptyContent(List languages) { final content = ContentDTO(); content.title = []; content.description = []; for (final language in languages) { content.title!.add(TranslationDTO(language: language, value: "")); content.description!.add(TranslationDTO(language: language, value: "")); } return content; }