{# # ============================================================================ # PAGE: PIXIA — Générateur d'images IA # ============================================================================ # # Interface unifiée : galerie masonry + drawer de création. # Structure : header sticky · galerie · drawer droit. # # DONNÉES REQUISES (depuis PixiaController::index) # | tokenStats | array | {remaining, energyConsumptionWh} | # | images | array | Collection de PixiaImage | # | totalItems | int | Nombre total d'images | # | hasMore | bool | Pagination infinie | # | styles | array | {value: label} | # ============================================================================ #} {% extends 'base.html.twig' %} {% set pxColor = tool_color_details['pixia'] ?? { primary: '#6366F1', secondary: '#4F46E5', bg: '#EEF2FF', border: '#C7D2FE' } %} {% set currentPlanSlug = app.user.company ? 'b2b' : (app.user.plan ? app.user.plan.slug : 'freemium') %} {% set createTooltipHtml %}{% include '_molecules/upgrade-tooltip/upgrade-tooltip.html.twig' with { minTokens: pixiaMinTokens, currentPlanSlug: currentPlanSlug, upgradeUrl: path('app_upgrade') } only %}{% endset %} {% block title %}Pixia — Générateur d'images IA{% endblock %} {% block main_class %}p-0 overflow-hidden bg-[#F5F5F5]{% endblock %} {% block body %}
{# ══════════════════════════════════════════ EN-TÊTE DE PAGE ══════════════════════════════════════════ #}
{# Branding #}
{% include '_atoms/icon/icon.html.twig' with { name: 'bubul-pixia', size: 'lg', colorPrimary: pxColor.primary, colorSecondary: pxColor.secondary } only %}

Pixia

{{ totalItems }} image{{ totalItems != 1 ? 's' : '' }}
{# Stats + action #}
{#- Plus d'infobulle « Passer en Pro » ici : ce bouton n'ouvre que le panneau, il ne génère rien. La barrière de tokens vit sur le bouton « Générer », au pied du panneau — c'est là qu'elle s'applique vraiment, et là qu'elle se comprend. -#} {# `data-tour-step` sur ce bouton : le tutoriel a besoin de lui pour OUVRIR le tiroir avant de désigner ce qu'il contient — sans quoi ses étapes visent des éléments hors de l'écran. Voir docs/tours.md. L'ancre est posée que la création soit autorisée ou non : elle identifie ce bouton, elle n'accorde rien. Réservée au seul cas autorisé, elle disparaissait pour un compte à court de tokens — et le tutoriel commentait alors un tiroir qu'il n'avait aucun moyen d'ouvrir. #} {% include '_atoms/button/button.html.twig' with { label: 'Créer', size: 'md', icon: 'plus', gradientFrom: pxColor.primary, gradientTo: pxColor.secondary, attr: { 'data-action': 'click->pixia--generator#openDrawer', 'data-tour-step': 'pixia-ouvrir' } } only %}
{# ══════════════════════════════════════════ GALERIE ══════════════════════════════════════════ #}
{# État vide #}
{% include '_atoms/icon/icon.html.twig' with { name: 'bubul-pixia', size: 'xl', colorPrimary: pxColor.primary, colorSecondary: pxColor.secondary } only %}

Votre galerie est vide

Décrivez une image et laissez Pixia la créer pour vous en quelques secondes.

{#- Plus d'infobulle « Passer en Pro » ici : ce bouton n'ouvre que le panneau, il ne génère rien. La barrière de tokens vit sur le bouton « Générer », au pied du panneau — c'est là qu'elle s'applique vraiment, et là qu'elle se comprend. -#} {% include '_atoms/button/button.html.twig' with { label: 'Générer ma première image', size: 'lg', icon: 'magic-stick', gradientFrom: pxColor.primary, gradientTo: pxColor.secondary, attr: { 'data-action': 'click->pixia--generator#openDrawer', 'data-tour-step': 'pixia-ouvrir' } } only %}
{# Grille masonry #}
{% for image in images %} {% include 'pixia/_image_card.html.twig' with { image: image } only %} {% endfor %}
{# Sentinel scroll infini #} {% if hasMore %}
Chargement…
{% endif %}
{# ══════════════════════════════════════════ BACKDROP DRAWER ══════════════════════════════════════════ #} {# ══════════════════════════════════════════ DRAWER — FORMULAIRE DE CRÉATION ══════════════════════════════════════════ #}
{# Header drawer #}
{% include '_atoms/icon/icon.html.twig' with { name: 'bubul-pixia', size: 'md', colorPrimary: pxColor.primary, colorSecondary: pxColor.secondary } only %}

Nouvelle image

{# Corps scrollable #}
{# ── Étape 1 : Mode ── #}
1 Mode de création

{# ── Étape 2 : Contenu ── #}
2 Contenu
{# Champ Titre (commun aux deux modes) #}
{# Panel Texte #}
Décrivez votre image {% include '_atoms/button/button.html.twig' with { label: 'Améliorer', variant: 'ghost', size: 'sm', icon: 'magic-stick', type: 'button', radius: 'full', class: 'px-soft-btn', attr: { 'data-action': 'click->pixia--generator#improvePrompt', 'data-pixia--generator-target': 'improveBtn' } } only %}
0 / {{ constant('App\\Config\\AppLimits::PIXIA_PROMPT_MAX_LENGTH')|number_format(0, ',', ' ') }}
{# Panel PDF #}
{# Zone de dépôt #}
{# Aperçu du fichier sélectionné (masqué par défaut) #}

{# ── Étape 3 : Style ── #}
3 Style
{% set styleImageFiles = { 'vivid': 'vivid.png', 'natural': 'naturel.png', 'cinematic': 'cinematique.png', 'anime': 'anime.png', 'sketch': 'esquisse.png', } %}
{% for value, label in styles %} {% endfor %}

{# ── Étape 4 : Qualité ── #}
4 Qualité
{% set isPaid = app.user.hasPaidAccess %}
{% for key, preset in qualityPresets %} {% set locked = (preset.paidOnly ?? false) and not isPaid %} {% endfor %}

{# ── Étape 5 : Format ── #}
5 Format
{# État de chargement (remplace le formulaire) #}
{# Footer drawer — bouton générer #}
{#- LA BARRIÈRE DE TOKENS EST ICI, et nulle part ailleurs : c'est ce bouton qui déclenche la dépense. Elle était posée sur « Créer », qui n'ouvre que le panneau — l'utilisateur se voyait refuser l'entrée sans avoir vu ce qu'il y avait dedans, et le tutoriel de l'outil devenait inatteignable avec elle. -#} {% include '_atoms/button/button.html.twig' with { label: 'Générer l\'image', size: 'lg', icon: 'magic-stick', type: 'button', width: 'full', gradientFrom: pxColor.primary, gradientTo: pxColor.secondary, disabled: not canCreate, attr: { 'data-pixia--generator-target': 'submitBtn', 'data-action': 'click->pixia--generator#generate' } } only %}

Pixia peut faire des erreurs. Vérifiez les contenus sensibles.

{# /drawer #} {# ══════════════════════════════════════════ MODAL — RENOMMER L'IMAGE ══════════════════════════════════════════ #} {% embed '_organisms/rename-modal/rename-modal.html.twig' with { title: 'Renommer l\'image', subtitle: 'Donnez un titre plus parlant à votre image.', placeholder: 'Ex: Paysage montagneux au coucher de soleil…', confirmLabel: 'Renommer', color: pxColor, modalAttr: {'data-pixia--generator-target': 'renameModal', 'style': 'z-index: 110;'}, inputAttr: { 'data-pixia--generator-target': 'renameInput', 'data-action': 'keydown->pixia--generator#handleRenameKey' }, cancelAttr: {'data-action': 'click->pixia--generator#closeRenameModal'}, confirmAttr: {'data-action': 'click->pixia--generator#confirmRename'} } %} {% block hiddenInputs %} {% endblock %} {% endembed %} {# ══════════════════════════════════════════ MODAL — SUPPRIMER L'IMAGE ══════════════════════════════════════════ #} {% embed '_organisms/delete-modal/delete-modal.html.twig' with { title: 'Supprimer cette image ?', modalAttr: {'data-pixia--generator-target': 'deleteModal', 'data-action': 'keydown.esc@window->pixia--generator#closeDeleteModal', 'style': 'z-index: 110;'}, cancelAttr: {'data-action': 'click->pixia--generator#closeDeleteModal'}, confirmAttr: {'data-action': 'click->pixia--generator#confirmDelete'} } only %} {% block description %}

L'image sera supprimée définitivement.

{% endblock %} {% endembed %} {# ══════════════════════════════════════════ LIGHTBOX ══════════════════════════════════════════ #} {% embed '_organisms/ai-lightbox/ai-lightbox.html.twig' with { controller: 'pixia--generator', primaryRgb: pxColor.primary|hex_to_rgb } %} {% block meta %} {# Partie fixe : badges, titre, date, stats #}

{# Description : flex-1 pour remplir l'espace jusqu'aux boutons #}
Description

{% endblock %} {% block actions %} {% include '_atoms/button/button.html.twig' with { label: 'Renommer', icon: 'edit', size: 'sm', width: 'full', gradientFrom: pxColor.primary, gradientTo: pxColor.secondary, attr: { 'data-action': 'click->pixia--generator#openRenameModal', 'data-pixia--generator-target': 'lightboxRenameBtn' } } only %} {% include '_atoms/button/button.html.twig' with { label: 'Télécharger', icon: 'download', size: 'sm', width: 'full', href: '#', gradientFrom: pxColor.primary, gradientTo: pxColor.secondary, attr: { 'data-pixia--generator-target': 'lightboxDownload', 'download': '' } } only %} {% include '_atoms/button/button.html.twig' with { label: 'Supprimer', icon: 'trash', variant: 'error', size: 'sm', width: 'full', attr: { 'data-action': 'click->pixia--generator#openDeleteModal' } } only %} {% endblock %} {% endembed %}
{% endblock %}