{% extends 'base.html.twig' %} {% block title %}{% if editMode|default(false) %}Édition : {% endif %}{{ metaTitle ?? title }}{% endblock %} {% block meta %} {% if featuredImagePath is defined and featuredImagePath %} {% endif %} {% endblock %} {% block stylesheets %} {{ parent() }} {{ encore_entry_link_tags('project-detail') }} {% endblock %} {% block javascripts %} {{ parent() }} {{ encore_entry_script_tags('project-detail') }} {% endblock %} {% block body %}
{# Hero restyle (node 409-624): title + subtitle + tag pills overlaid directly on the hero image, rather than the title rendering above it in its own .page-hero band. Tags here are the same Page<->Tag entity relation as Actualité's `show_tags`/TagPicker.ts (mutualized system, `tag_scope: 'project'`), just rendered inline in this custom hero markup instead of via _page_hero.html.twig (which this template doesn't use for its title/subtitle either). #} {% if (content.featuredImage is defined and content.featuredImage) or content.featuredImageDark|default(false) or editMode|default(false) %}
{% if editMode|default(false) and not (content.featuredImage|default(false) or content.featuredImageDark|default(false)) %} + Ajouter l'image principale {% endif %} {% include 'components/_themed_img.html.twig' with {light: featuredImagePath|default(''), dark: featuredImageDarkPath|default(''), alt: title, class: 'project-detail__hero-img'} only %}
{% include 'components/_page_hero.html.twig' with { title: title, subtitle: content.subtitle|default(null), edit_mode: editMode|default(false), title_class: 'page-hero__title--lato' } %} {% if (tags is defined and tags is not empty) or editMode|default(false) %}
{% if editMode|default(false) %} {# Page<->Tag relation, same TagPicker.ts as Actualité's #tag-picker (see components/_page_hero.html.twig) - mounted inline here since this hero doesn't include that partial. `tag_scope="project"` restricts the pickable/creatable catalog. #}
{% elseif tags is defined and tags is not empty %} {% for tag in tags %} {% include 'components/_tag.html.twig' with { label: tag.name, disabled: true, class: 'project-detail__hero-tag' } %} {% endfor %} {% endif %}
{% endif %}
{% endif %} {# "Le projet" info block (decision (a)): top-level content fields, always exactly one instance directly under the hero - not a `blocks[]` entry, so included here unconditionally rather than inside .project-detail__blocks. #} {% include 'components/_project-detail-info.html.twig' with { content: content, editMode: editMode|default(false) } %} {# Content blocks - rendered in stored order, dispatched by block.type. BlockListEditor.ts manages add/remove/reorder in edit mode: the wrapper below is always present in edit mode (even with zero blocks) so a new project can receive its first block via "Ajouter un bloc". Reuses the Actualité block partials for text/text-image-* (shared components, no duplication) plus a ProjectDetail-only gallery block. #} {% if (content.blocks is defined and content.blocks is not empty) or editMode|default(false) %}
{% for block in content.blocks|default([]) %} {% if block.type == 'text' %} {% include 'components/_actualite-block-text.html.twig' with { block: block } %} {% elseif block.type == 'text-image-left' or block.type == 'text-image-right' %} {% include 'components/_actualite-block-text-image.html.twig' with { block: block, imagePosition: block.type == 'text-image-left' ? 'left' : 'right', mobileImagePosition: block.fields.mobileImagePosition|default('before') } %} {% elseif block.type == 'gallery' %} {% include 'components/_project-detail-block-gallery.html.twig' with { block: block } %} {% elseif block.type == 'paragraphs-image' %} {% include 'components/_project-detail-block-paragraphs-image.html.twig' with { block: block } %} {% elseif block.type == 'before-after' %} {% include 'components/_project-detail-block-before-after.html.twig' with { block: block } %} {% endif %} {% endfor %}
{% endif %} {% if editMode|default(false) %} {# BlockListEditor.ts "Add block" control - offers the 4 block types, clones the matching hidden