{% extends 'base.html.twig' %} {% block title %}{{ is_edit ? 'Modifier' : 'Nouvel' }} outil - Admin{% endblock %} {% block body %}
{# Header #}
{% include '_molecules/page-header/page-header.html.twig' with { title: is_edit ? 'Modifier « ' ~ tool.name ~ ' »' : 'Nouvel outil', icon: is_edit ? 'edit' : 'plus', backHref: path('admin_tool_list'), backLabel: 'Retour aux outils' } only %}
{# Formulaire #} {{ form_start(form, {'attr': {'class': 'space-y-6'}}) }} {# ============================================================ CARD 1 : Informations générales ============================================================ #}
{% include '_atoms/icon/icon.html.twig' with { name: 'settings', size: 'md', color: 'primary' } only %}

Informations générales

Identité et description de l'outil

{# Nom et Code #}
{{ form_label(form.name, null, {'label_attr': {'class': 'block text-sm font-medium text-gray-700 mb-2'}}) }} {{ form_widget(form.name, {'attr': {'class': 'w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-base bg-gray-50 focus:bg-white'}}) }} {{ form_errors(form.name) }}
{{ form_label(form.code, null, {'label_attr': {'class': 'block text-sm font-medium text-gray-700 mb-2'}}) }} {{ form_widget(form.code, {'attr': {'class': 'w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-base bg-gray-50 focus:bg-white font-mono text-sm'}}) }} {% if form.code.vars.help %}

{{ form.code.vars.help }}

{% endif %} {{ form_errors(form.code) }}
{# Description #}
{{ form_label(form.description, null, {'label_attr': {'class': 'block text-sm font-medium text-gray-700 mb-2'}}) }} {{ form_widget(form.description, {'attr': {'class': 'w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-base bg-gray-50 focus:bg-white resize-none', 'rows': 3}}) }} {{ form_errors(form.description) }}
{# Icône et Token Tailwind #}
{{ form_label(form.icon, null, {'label_attr': {'class': 'block text-sm font-medium text-gray-700 mb-2'}}) }} {{ form_widget(form.icon, {'attr': {'class': 'w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-base bg-gray-50 focus:bg-white'}}) }} {% if form.icon.vars.help %}

{{ form.icon.vars.help }}

{% endif %} {{ form_errors(form.icon) }}
{{ form_label(form.color, null, {'label_attr': {'class': 'block text-sm font-medium text-gray-700 mb-2'}}) }} {{ form_widget(form.color, {'attr': {'class': 'w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-base bg-gray-50 focus:bg-white appearance-none'}}) }} {% if form.color.vars.help %}

{{ form.color.vars.help }}

{% endif %} {{ form_errors(form.color) }}
{# ── Palette de couleurs (4 sélecteurs visuels) ── #}

Palette de couleurs

{# Aperçu live #}
{{ tool.name|default('Nom de l\'outil') }} Aperçu de la palette
{# 4 sélecteurs #}
{% for fieldName, fieldLabel in { 'colorBackground': 'Fond', 'colorPrimary': 'Primaire', 'colorSecondary': 'Secondaire', 'colorBorder': 'Bordure' } %} {% set field = attribute(form, fieldName) %} {% set hexVal = field.vars.value ?? '' %}
{{ form_widget(field, {'attr': {'class': 'w-full px-3 py-2 border-2 border-gray-200 rounded-lg focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-base bg-gray-50 focus:bg-white font-mono text-xs uppercase', 'oninput': " const picker = this.previousElementSibling?.previousElementSibling || this.closest('div').querySelector('input[type=color]'); if (picker && this.value.match(/^#[0-9a-fA-F]{6}$/)) picker.value = this.value; updateColorPreview(); "}}) }}
{{ form_errors(field) }}
{% endfor %}

Format hex (#RRGGBB). Le sélecteur met à jour l'aperçu en temps réel.

{# ============================================================ CARD 2 : Routage ============================================================ #}
{% include '_atoms/icon/icon.html.twig' with { name: 'arrow-right', size: 'md', color: 'primary' } only %}

Routage

Routes Symfony pour la navigation et la protection

{{ form_label(form.routeName, null, {'label_attr': {'class': 'block text-sm font-medium text-gray-700 mb-2'}}) }} {{ form_widget(form.routeName, {'attr': {'class': 'w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-base bg-gray-50 focus:bg-white font-mono text-sm'}}) }} {% if form.routeName.vars.help %}

{{ form.routeName.vars.help }}

{% endif %} {{ form_errors(form.routeName) }}
{{ form_label(form.routePrefix, null, {'label_attr': {'class': 'block text-sm font-medium text-gray-700 mb-2'}}) }} {{ form_widget(form.routePrefix, {'attr': {'class': 'w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-base bg-gray-50 focus:bg-white font-mono text-sm'}}) }} {% if form.routePrefix.vars.help %}

{{ form.routePrefix.vars.help }}

{% endif %} {{ form_errors(form.routePrefix) }}
{# ============================================================ CARD 3 : Tokens et affichage ============================================================ #}
{% include '_atoms/icon/icon.html.twig' with { name: 'token', size: 'md', color: 'primary' } only %}

Tokens et affichage

Consommation et ordre dans l'interface

{{ form_label(form.minTokens, null, {'label_attr': {'class': 'block text-sm font-medium text-gray-700 mb-2'}}) }} {{ form_widget(form.minTokens, {'attr': {'class': 'w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-base bg-gray-50 focus:bg-white tabular-nums'}}) }} {% if form.minTokens.vars.help %}

{{ form.minTokens.vars.help }}

{% endif %} {{ form_errors(form.minTokens) }}
{{ form_label(form.sortOrder, null, {'label_attr': {'class': 'block text-sm font-medium text-gray-700 mb-2'}}) }} {{ form_widget(form.sortOrder, {'attr': {'class': 'w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-base bg-gray-50 focus:bg-white tabular-nums'}}) }} {% if form.sortOrder.vars.help %}

{{ form.sortOrder.vars.help }}

{% endif %} {{ form_errors(form.sortOrder) }}
{# Toggles #}
{# isTokenable #} {# isVisibleInSidebar #} {# isVisibleInDashboard #}
{# ============================================================ CARD 4 : Visibilité et dashboard ============================================================ #}
{% include '_atoms/icon/icon.html.twig' with { name: 'eye', size: 'md', color: 'primary' } only %}

Visibilité et dashboard

Règle de visibilité et description pour le dashboard

{# Règle de visibilité #}
{{ form_label(form.visibilityRule, null, {'label_attr': {'class': 'block text-sm font-medium text-gray-700 mb-2'}}) }} {{ form_widget(form.visibilityRule, {'attr': {'class': 'w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-base bg-gray-50 focus:bg-white appearance-none'}}) }} {% if form.visibilityRule.vars.help %}

{{ form.visibilityRule.vars.help }}

{% endif %} {{ form_errors(form.visibilityRule) }}
{# Description dashboard #}
{{ form_label(form.dashboardDescription, null, {'label_attr': {'class': 'block text-sm font-medium text-gray-700 mb-2'}}) }} {{ form_widget(form.dashboardDescription, {'attr': {'class': 'w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-base bg-gray-50 focus:bg-white resize-none', 'rows': 3}}) }} {% if form.dashboardDescription.vars.help %}

{{ form.dashboardDescription.vars.help }}

{% endif %} {{ form_errors(form.dashboardDescription) }}
{# Actions #}
{% include '_atoms/button/button.html.twig' with { label: 'Annuler', variant: 'ghost', size: 'lg', icon: 'arrow-left', href: path('admin_tool_list') } only %} {% include '_atoms/button/button.html.twig' with { label: is_edit ? 'Enregistrer' : 'Créer l\'outil', variant: 'primary', size: 'lg', icon: 'check', type: 'submit' } only %}
{{ form_end(form) }}
{% endblock %}