feat(shop): Ajoute une note sur les ventes soutenant l'association et compresse le HTML.

This commit is contained in:
Serreau Jovann
2025-11-21 19:37:02 +01:00
parent 973e795b88
commit 0e4077b875
8 changed files with 106 additions and 8 deletions

View File

@@ -0,0 +1,25 @@
<?php
namespace App\EventSubscriber;
use App\Service\Compressor\HtmlCompressor;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
#[AsEventListener(event: ResponseEvent::class, method: 'onResponse', priority: 10)]
class RequestSubscriber
{
public function __construct(private HtmlCompressor $htmlCompressor)
{
}
public function onResponse(ResponseEvent $event): void
{
if($_ENV['APP_ENV'] == "prod") {
$response = $event->getResponse();
$response->setContent($this->htmlCompressor->compress($response->getContent()));
$event->setResponse($response);
$event->stopPropagation();
}
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace App\Service\Compressor;
/**
* Classe HtmlCompressor
* Permet de minifier le contenu HTML en supprimant les commentaires et les espaces
* inutiles entre les balises.
*/
class HtmlCompressor
{
/**
* Minifie une chaîne de caractères contenant du HTML.
* * Cette méthode effectue les étapes suivantes :
* 1. Suppression des commentaires HTML (sauf les commentaires conditionnels IE).
* 2. Suppression des sauts de ligne, retours chariot et tabulations.
* 3. Suppression des espaces multiples.
* 4. Suppression des espaces autour des balises (entre > et <).
*
* @param string $html Le contenu HTML à minifier.
* @return string Le contenu HTML minifié.
*/
public function compress(string $html): string
{
// 1. Supprime les commentaires HTML, tout en préservant les commentaires conditionnels (<!--[if ...)
$html = preg_replace('/<!--(?!\[if|<!\[endif).*?-->/s', '', $html);
// 2. Supprime tous les sauts de ligne, retours chariot et tabulations
$html = str_replace(array("\r\n", "\r", "\n", "\t"), '', $html);
// 3. Remplace les multiples espaces par un seul espace
$html = preg_replace('/\s+/', ' ', $html);
// 4. Supprime les espaces qui se trouvent juste après '>' ou juste avant '<'
// Cela compresse l'espace entre les balises.
$html = preg_replace('/>\s</', '><', $html);
return trim($html);
}
}

View File

@@ -37,7 +37,7 @@
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('favicon/apple-touch-icon.png') }}"/>
<meta name="apple-mobile-web-app-title" content="E-Cosplay"/>
<link rel="manifest" href="{{ asset('site.webmanifest') }}"/>
<link rel="stylesheet" href="{{ asset('assets/css/all.min.css') }}" crossorigin="anonymous"
<link rel="stylesheet" href="{{ asset('assets/icons/css/fontawesome.min.css') }}" crossorigin="anonymous"
referrerpolicy="no-referrer"/>
<meta name="google-site-verification" content="D6YvgLKg4oj2Ksk_cYhO3fijbmxZWib7wqqHTJyfftQ"/>
<meta name="env" content="{{ app.environment }}">
@@ -134,7 +134,7 @@
{# LOGO / NOM DU SITE #}
<div class="flex-shrink-0 flex items-center">
<a href="{{ path('app_home') }}" class="flex items-center space-x-2 text-xl font-bold text-gray-900">
<img class="h-8 w-auto" src="{{ asset('assets/images/logo.jpg') | imagine_filter('webp') }}"
<img class="h-8 w-auto" width="57px" height="32px" src="{{ asset('assets/images/logo.jpg') | imagine_filter('webp') }}"
alt="E-Cosplay Logo">
{# Le texte du nom du site peut rester en noir pour la lisibilité #}
<span class="text-gray-900">E-Cosplay</span>

View File

@@ -125,10 +125,10 @@
{# BOUCLE SUR LES PARTENAIRES #}
{# NOTE: La variable `partners` doit être passée par le contrôleur (e.g., [ { image: '/asset/partenair/house-of-geek.jpg', name: 'House Of Geek', facebook_link: 'lien' }, ... ] ) #}
{% for partner in partners|default([
{ 'image': '/assets/partenair/house-of-geek.jpg', 'name': 'House Of Geek', 'facebook_link': 'https://www.facebook.com/houseofgeek02' },
{ 'image': '/assets/partenair/cosplay-familly.jpg', 'name': 'Cosplays family arts', 'facebook_link': 'https://www.facebook.com/profile.php?id=61568494078902' },
{ 'image': '/assets/partenair/couronnes-d-or.jpg', 'name': 'Le Comité des Couronnes Dor', 'facebook_link': 'https://www.facebook.com/p/Le-Comit%C3%A9-des-Couronnes-Dor-61576548182126/' },
{ 'image': '/assets/partenair/siteconseil.png', 'name': 'SARL SITECONSEIL', 'facebook_link': 'https://www.facebook.com/siteconseil','website':'https://www.siteconseil.fr' }
{ 'w':64,'h':64, 'image': '/assets/partenair/house-of-geek.jpg', 'name': 'House Of Geek', 'facebook_link': 'https://www.facebook.com/houseofgeek02' },
{ 'w':64,'h':64, 'image': '/assets/partenair/cosplay-familly.jpg', 'name': 'Cosplays family arts', 'facebook_link': 'https://www.facebook.com/profile.php?id=61568494078902' },
{ 'w':64,'h':64, 'image': '/assets/partenair/couronnes-d-or.jpg', 'name': 'Le Comité des Couronnes Dor', 'facebook_link': 'https://www.facebook.com/p/Le-Comit%C3%A9-des-Couronnes-Dor-61576548182126/' },
{ 'w':64,'h':64, 'image': '/assets/partenair/siteconseil.png', 'name': 'SARL SITECONSEIL', 'facebook_link': 'https://www.facebook.com/siteconseil','website':'https://www.siteconseil.fr' }
]) %}
{# Conteneur du partenaire #}
<a href=" {% if partner.website is defined and partner.website %}{{ partner.website }}{% else %}{{ partner.facebook_link ?? '#' }}{% endif %}" target="_blank" class="col-span-1 flex flex-col items-center justify-center py-6 px-4 bg-white rounded-xl shadow-md border border-gray-100 hover:shadow-lg hover:border-indigo-200 transition duration-300 group">
@@ -137,6 +137,8 @@
<img class="max-h-16 w-auto object-contain mb-3"
src="{{ partner.image | imagine_filter('webp') }}"
alt="{{ partner.name }}"
width="{{ partner.w }}"
height="{{ partner.h }}"
onerror="this.style.display='none'; this.nextElementSibling.style.display='block';"
>

View File

@@ -168,7 +168,7 @@
{{ product.price | number_format(2, ',', ' ') }} € TTC
</span>
<a href="{{ path('app_product_show', {'slug': (product.name|lower|replace({' ': '-'}))~"-"~product.id}) }}" class="text-indigo-600 hover:text-indigo-800 text-sm font-semibold inline-flex items-center group">
En savoir plus
{{ 'shop_more'|trans }}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-right ml-1 group-hover:translate-x-0.5 transition-transform"><path d="m9 18l6-6-6-6"/></svg>
</a>
</div>
@@ -177,7 +177,18 @@
{% endfor %}
</div>
<div class="mt-12 mb-8 p-6 bg-indigo-50 border-l-4 border-indigo-500 rounded-lg shadow-inner">
<h3 class="text-xl font-bold text-indigo-800 mb-3 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-heart-handshake mr-2"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5"/><path d="M12 20v-6h3a1 1 0 0 1 1 1v4h1a2 2 0 0 1 2 2v0a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v0a2 2 0 0 1 2-2h1.5l1.5-4h2.8l-3.5 6H22"/></svg>
{{ 'shop.sales_note_title'|trans }}
</h3>
<p class="text-gray-700 leading-relaxed">
{{ 'shop.sales_note_main'|trans|raw }}
</p>
<p class="mt-3 text-sm italic text-gray-600">
{{ 'shop.sales_note_details'|trans }}
</p>
</div>
</main>
</div>
{% endblock %}

View File

@@ -610,3 +610,9 @@ product_short_desc_title: "快速概览"
product_long_desc_title: "详细描述"
product_estimated_delivery: "预计交货时间2-5个工作日。"
product_shipping_methods: "通过 Mondial Relay / Colissimo 交付,起价 6€ TTC"
shop.sales_note_title: "我们的销售收入将用于支持协会"
shop.sales_note_main: >
本店大部分商品的全部销售收入100%利润)将用于支持本协会。这些资金将用于网站开发、活动组织以及举办比赛。
shop.sales_note_details: >
请注意,针对特定的 Cosplay 写真印品销售收益分配如下5% 用于支付协会的银行手续费95% 直接返还给制作该印品的会员。
shop_more: '了解更多'

View File

@@ -678,3 +678,9 @@ product_short_desc_title: "Quick Overview"
product_long_desc_title: "Detailed Description"
product_estimated_delivery: "Estimated delivery: 2-5 working days."
product_shipping_methods: "Shipping via Mondial Relay / Colissimo starting from €6 incl. tax"
shop.sales_note_title: "Our Sales for the Association"
shop.sales_note_main: >
The entirety of sales (100% of the profit) from the majority of the shop's items is intended to support the association. These funds are used for website development, event organization, and setting up contests.
shop.sales_note_details: >
Please note that for specific cosplay print sales, the distribution is as follows: 5% of the amount covers the association's banking fees, and 95% is directly remitted to the member who created the print.
shop_more: 'Learn more'

View File

@@ -612,3 +612,9 @@ product_short_desc_title: "Aperçu rapide"
product_long_desc_title: "Description détaillée"
product_estimated_delivery: "Livraison estimée : 2-5 jours ouvrés."
product_shipping_methods: "Livraison par Mondial Relay / Colissimo à partir de 6€ TTC"
shop.sales_note_title: "Nos Ventes pour l'Association"
shop.sales_note_main: >
La totalité des ventes (100% du bénéfice) de la majorité des articles de la boutique est destinée à soutenir l'association. Ces fonds servent au développement du site internet, à l'organisation d'événements, ainsi qu'à la mise en place de jeux concours.
shop.sales_note_details: >
Notez que pour les ventes de prints cosplay spécifiques, la répartition est la suivante : 5% du montant couvre les frais bancaires de l'association, et 95% est reversé directement à l'adhérent créateur du print.
shop_more: 'En savoir plus'