{# # PAGE: SLIDIA — ÉCRAN DE CONFIGURATION (une page par méthode de création) # Remplace le wizard en trois étapes (`create.html.twig`) : tout tient sur un seul écran — # le titre, le choix du masque, le dépôt du document OU la saisie du brief selon la méthode, # le bandeau de structure détectée avec son interrupteur, et le profil de génération. # # ATTEIGNABLE PAR SON URL DIRECTE : cet écran ne dépend pas de la page de choix # (`/slidia/new`), vers laquelle pointe le retour de la barre de navigation, en bas. # # DONNÉES REQUISES (SlidiaController::configure) : method ('pdf'|'prompt'), templates, # lastUsedTemplateId. # # La soumission est un VRAI formulaire nommé, posté directement vers `app_slidia_create_submit` # — pas le formulaire caché soumis par JS du wizard. Conséquence directe et voulue : la case # du mode fidèle est un champ de formulaire ordinaire, dont aucune ligne de JavaScript n'écrit # la valeur (voir le commentaire posé sur elle plus bas). #} {% extends 'base.html.twig' %} {% block title %}Nouvelle présentation — Slidia{% endblock %} {% block meta_description %}Configurez votre présentation Slidia : titre, masque, contenu source et profil de génération.{% endblock %} {% block og_title %}Nouvelle présentation — Slidia{% endblock %} {% block og_description %}Générez une présentation PowerPoint professionnelle en quelques minutes avec Slidia, propulsé par l'IA.{% endblock %} {% block twitter_title %}Nouvelle présentation — Slidia{% endblock %} {% block twitter_description %}Générez une présentation PowerPoint professionnelle en quelques minutes avec Slidia, propulsé par l'IA.{% endblock %} {% block body %} {% set sdColor = tool_color_details['slidia'] %} {# Infobulle d'abonnement du bouton de génération — même molécule que la bibliothèque. #} {% set currentPlanSlug = app.user.company ? 'b2b' : (app.user.plan ? app.user.plan.slug : 'freemium') %} {% set generateTooltipHtml %}{% include '_molecules/upgrade-tooltip/upgrade-tooltip.html.twig' with { minTokens: slidiaMinTokens, currentPlanSlug: currentPlanSlug, upgradeUrl: path('app_upgrade') } only %}{% endset %} {% set sdRgb = sdColor.primary|hex_to_rgb %} {% set isPdf = method == 'pdf' %} {% set meta = { pdf: { title: 'Configurez votre présentation', subtitle: 'Derniers réglages avant que Slidia ne reprenne votre document.', icon: 'settings' }, prompt: { title: 'Configurez votre présentation', subtitle: "Derniers réglages avant que l'IA ne compose vos slides.", icon: 'settings' } }[method] %} {# Styles des CONTRÔLES de formulaire seulement (focus teinté, zone de dépôt, pastilles de choix) — le reste est en Tailwind. Motif repris de templates/scormia/configure.html.twig. #} {# Recoloration en ambre : les composants partagés sont écrits sur les variables de thème, jamais sur une couleur en dur — on les surcharge donc sur CE conteneur racine. #}
{# L'en-tête vit AU-DESSUS de la carte et la navigation EN DESSOUS, comme sur les écrans équivalents de Moodia et de Scormia : la carte ne porte que les réglages. #}
{% include '_atoms/icon/icon.html.twig' with { name: meta.icon, size: 'lg', colorPrimary: 'current', colorSecondary: 'current' } only %}

{{ meta.title }}

{{ meta.subtitle }}

{# `slidia_create` : l'identifiant de jeton attendu par `createSubmit()`. En changer ferait échouer la soumission sur un « accès refusé » opaque. #}
{# ── Titre ──────────────────────────────────────────────── #} {# ── Masque ─────────────────────────────────────────────── #} {# Le masque préretenu est résolu ICI, pas en JavaScript : le résumé doit être juste au premier pixel affiché, sans attendre qu'un contrôleur fouille une grille qui n'existe qu'une fois la modale ouverte. #} {% set masqueRetenu = templates|filter(t => t.id == lastUsedTemplateId)|first|default(null) %}
Masque {% if templates is empty %}

Aucun masque disponible

Importez un modèle .pptx depuis votre bibliothèque pour pouvoir générer une présentation.

{% else %} {% endif %}
{# ── Diapositives ─────────────────────────────────────────── Une CONSIGNE, pas une estimation : `SlidiaAiService` la transmet telle quelle au modèle. Le compteur remplace le curseur — à soixante crans, viser une valeur au glissement demandait de la précision pour un réglage qui se dit en un chiffre. Masqué tant que le suivi à la lettre est actif : le nombre vaut alors le nombre de sections, et le champ, désactivé, n'est même plus posté. #}
Diapositives {# Un seul contrôle pleine largeur : deux commandes et le nombre, écrit en toutes lettres. Les quatre ordres de grandeur qui l'accompagnaient proposaient des valeurs que la ligne d'aide justifie mieux qu'eux — et ils poussaient à choisir un chiffre rond plutôt que le bon. Le nombre est un CHAMP, pas un affichage : passer de 6 à 40 demandait trente-quatre clics. `min`/`max` viennent de `SlidiaConfig`, jamais d'un littéral, et le contrôleur les relit pour borner ce qui est saisi. #}

{# ── Densité d'images ─────────────────────────────────────── Trois positions, en langage métier. « Aucune » retire la forme `demonstration` du plan côté serveur : l'absence d'image est garantie par le schéma, pas par une consigne. #}
Images
{#- Chaque position porte sa VIGNETTE : une mini-diapositive qui montre ce que le mode produit — que du texte, texte + image, image dominante. `currentColor` : le pictogramme suit la couleur du segment, actif ou non. -#} {% for densite in [ { value: constant('App\\Config\\SlidiaConfig::IMAGE_DENSITY_NONE'), title: 'Aucune', hint: 'Un support tout en texte : aucun emplacement d\'image.', checked: false, icone: '' }, { value: constant('App\\Config\\SlidiaConfig::IMAGE_DENSITY_BALANCED'), title: 'Équilibré', hint: 'L\'IA place une image là où elle montre quelque chose.', checked: true, icone: '' }, { value: constant('App\\Config\\SlidiaConfig::IMAGE_DENSITY_RICH'), title: 'Illustré', hint: 'Un support visuel : une image dès que le propos s\'y prête.', checked: false, icone: '' } ] %} {% endfor %}

{# ── Densité de texte ─────────────────────────────────────── Trois positions, mêmes principes que la densité d'images : le choix pilote la CIBLE DE REMPLISSAGE des zones (`maxChars`) côté rédaction. #}
Texte
{% for densite in [ { value: constant('App\\Config\\SlidiaConfig::TEXT_DENSITY_LIGHT'), title: 'Synthétique', hint: 'L\'essentiel en peu de mots : une idée par diapositive.', checked: false, icone: '' }, { value: constant('App\\Config\\SlidiaConfig::TEXT_DENSITY_BALANCED'), title: 'Équilibré', hint: 'Des paragraphes courts qui respirent — le réglage conseillé.', checked: true, icone: '' }, { value: constant('App\\Config\\SlidiaConfig::TEXT_DENSITY_RICH'), title: 'Détaillé', hint: 'Chaque constat développé : conséquence, exemple, chiffre.', checked: false, icone: '' } ] %} {% endfor %}

{# ── Suivre le texte à la lettre ──────────────────────────── Rendu par le SERVEUR, et seulement quand l'analyse de l'étape 2 a trouvé une structure : la case n'existe pas dans le DOM d'une présentation qui n'a rien à respecter, donc rien ne peut être posté à l'insu de l'utilisateur. #} {% if source.hasStructure|default(false) %} {% endif %}

{# Ce qui bloque encore la génération, écrit par le contrôleur à côté du bouton : un bouton grisé sans explication oblige à relire tout l'écran. #} {# Navigation SOUS la carte, nue sur le fond de page. Le retour ramène à l'étape de la source — c'est d'elle qu'on vient, et c'est là qu'on va pour changer de contenu. #} {#- `embed` et non `include` : le bloc `next` est surchargé pour envelopper le bouton dans l'infobulle d'abonnement. C'est LUI qui dépense les tokens — le parcours laissait jusqu'ici l'utilisateur remplir tout le formulaire avant de le refuser à l'étape suivante, sans jamais lui dire ce qui manquait. Même patron que Pixia, Monalisia et Castia : la barrière est sur le bouton qui déclenche la dépense. -#} {% embed '_molecules/step-nav/step-nav.html.twig' with { class: 'pt-6', back: { href: path('app_slidia_source', { method: method }) }, next: { label: 'Générer la présentation', type: 'submit', disabled: true, gradientFrom: sdColor.primary, gradientTo: sdColor.secondary, attr: { 'data-slidia--configure-target': 'submitBtn' } }, canCreate: canCreate, tooltipHtml: generateTooltipHtml } only %} {% block next %} {{ parent() }} {% endblock %} {% endembed %}
{# ── La bibliothèque de masques, en entier ──────────────────────────────── Le MÊME partiel que /slidia, en mode « picker » : import d'un .pptx, filtres, aperçu des mises en page. L'ancienne modale de cet écran ne montrait qu'une grille de vignettes — on y choisissait un masque sans pouvoir regarder ce qu'il contient. Elle est POSÉE HORS DU FORMULAIRE : elle porte ses propres boutons (import, renommage, suppression), et un `
{% endblock %}