Files
ludikevent_crm/templates/dashboard/devis/add.twig
Serreau Jovann 4c14932fee ```
 feat(Devis.php): Ajoute adresses de facturation et de livraison au devis.

🔒️ fix(IntranetLocked.php): Autorise l'accès à la route st_control en mode debug.

 feat(CustomerAddress.php): Gère les adresses de facturation et livraison.

 feat: Ajoute la console superadmin pour le contrôle système.

 feat(DevisController.php): Supprime la génération PDF temporaire.

 feat(st_control.js): Ajoute la logique de contrôle système via JS.

 feat: Crée les templates CGV, Cookies, Hébergement et RGPD.

🎨 style(app.scss): Ajoute un style de fond pour la console.

 feat: Ajoute le template pour les informations d'hébergement.

 feat: Crée un template de mail d'alerte pour les accès root.

 feat: Crée le template RGPD (données personnelles).

🐛 fix(ErrorListener.php): Gère les erreurs 404 en prod (JSON/HTML).

 feat: Ajoute les mentions légales.

 feat(DevisPdfService.php): Améliore la génération PDF du devis.

 feat(admin.js): Charge dynamiquement les produits dans le select.

 feat(add.twig): Ajoute un sélecteur de produit et d'autres champs.

 chore(config): Ajoute INTRANET_LOCK à l'env.
```
2026-01-19 13:52:41 +01:00

167 lines
10 KiB
Twig

{% extends 'dashboard/base.twig' %}
{% block title %}Création Devis{% endblock %}
{% block title_header %}Nouveau <span class="text-blue-500">Devis</span>{% endblock %}
{% block actions %}
<a href="{{ path('app_crm_devis') }}" class="flex items-center px-4 py-2 text-[10px] font-black text-slate-400 hover:text-white uppercase tracking-widest transition-all group">
<svg class="w-4 h-4 mr-2 transform group-hover:-translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
</svg>
Annuler
</a>
{% endblock %}
{% block body %}
<div class="w-full animate-in fade-in zoom-in-95 duration-500">
{{ form_start(form,{attr:{'data-turbo':'false'}}) }}
<div class="backdrop-blur-xl bg-[#1e293b]/40 border border-white/5 rounded-[3rem] p-10 shadow-2xl relative overflow-hidden w-full">
{# Décoration de fond #}
<div class="absolute top-0 right-0 -mr-16 -mt-16 w-96 h-96 bg-blue-600/5 rounded-full blur-3xl pointer-events-none"></div>
{# Header #}
<div class="relative mb-12">
<div class="flex items-center space-x-6">
<div class="flex items-center justify-center w-12 h-12 rounded-2xl bg-blue-600 shadow-lg shadow-blue-600/30 text-white">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
</svg>
</div>
<div>
<h3 class="text-2xl font-black text-white tracking-tight">Création d'un devis</h3>
<p class="text-[9px] text-slate-500 uppercase tracking-[0.3em] font-bold mt-1">Configuration des informations d'entête</p>
</div>
</div>
</div>
<div class="relative space-y-10">
{# GRILLE À 3 COLONNES #}
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
{# COLONNE 1 : NUMÉRO #}
<div class="space-y-3">
{{ form_label(form.num) }}
<div class="relative">
{{ form_widget(form.num) }}
</div>
</div>
{# COLONNE 2 : DATE #}
<div class="space-y-3">
{{ form_label(form.createA) }}
<div class="relative">
{{ form_widget(form.createA) }}
</div>
</div>
{# COLONNE 3 : CLIENT #}
<div class="space-y-3" is="devis-manager">
{{ form_label(form.customer) }}
{{ form_widget(form.customer) }}
</div>
<div>
<label for="billAddress">Adresse de facturation</label>
<select id="billAddress" name="devis[ship_address]">
</select>
</div>
<div>
<label for="shipAddress">Adresse de livraison</label>
<select id="shipAddress" name="devis[ship_address]">
</select>
</div>
</div>
<div class="form-repeater" data-component="repeater" is="repeat-line">
<ol class="form-repeater__rows" data-ref="rows" tabindex="0">
<li class="form-repeater__row" style="border-bottom: 1px solid white">
<fieldset class="form-group form-group--horizontal">
<div class="flex space-x-4">
<div class="flex-1">
<div class="form-field">
<div class="mb-1">
<label for="product" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Produit</label>
<select data-load="product" type="text" name="lines[0][title]" id="lines[0][title]" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
</select>
</div>
<div class="mb-1">
<label for="product" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Nombre de jour</label>
<input type="number" step="1" name="lines[0][price]" id="lines[0][price]" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required />
</div>
<div class="mb-1">
<label for="product" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Prix Ht</label>
<input type="number" step="0.1" name="lines[0][price]" id="lines[0][price]" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required />
</div>
<div class="mb-1">
<label for="product" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Date de début</label>
<input type="date" name="lines[0][price]" id="lines[0][price]" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required />
</div>
<div class="mb-1">
<label for="product" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Date de fin</label>
<input type="date" name="lines[0][price]" id="lines[0][price]" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required />
</div>
<button
class="w-full form-repeater__remove-button bg-red-600 hover:bg-red-700 text-white px-3 py-1 rounded"
data-ref="removeButton"
type="button"
>
Supprimer la ligne
</button>
</div>
</div>
</div>
</fieldset>
</li>
</ol>
<button
class="mt-2 form-repeater__add-button w-full bg-purple-600 hover:bg-purple-700 text-white px-3 py-1 rounded"
data-ref="addButton"
type="button"
>
+ Ajouter une ligne
</button>
</div>
{# BOUTON LARGEUR TOTALE #}
<div class="pt-4">
<button type="submit" class="w-full py-6 bg-blue-600 hover:bg-blue-500 text-white text-[11px] font-black uppercase tracking-[0.5em] rounded-2xl shadow-2xl shadow-blue-600/40 transition-all hover:scale-[1.005] active:scale-95 flex items-center justify-center group">
<span>Valider et créer le devis</span>
<svg class="w-5 h-5 ml-4 transform group-hover:translate-x-2 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 5l7 7m0 0l-7 7m7-7H3"/>
</svg>
</button>
</div>
</div>
</div>
{{ form_end(form) }}
</div>
<style>
label {
@apply block text-[10px] font-black text-slate-500 uppercase tracking-[0.2em] mb-3 ml-2 !important;
}
input, select {
@apply w-full bg-slate-900/60 border border-white/5 rounded-2xl px-6 py-5 text-sm text-white outline-none focus:border-blue-500/50 focus:bg-slate-900/80 transition-all duration-500 !important;
}
input[readonly] {
@apply border-white/5 bg-white/5 cursor-not-allowed text-slate-500 !important;
}
select {
@apply appearance-none cursor-pointer;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%233b82f6'%3E%3Cpath stroke-linecap='round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"%3E%3C/path%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 1.5rem center;
background-size: 1rem;
}
</style>
{% endblock %}