Files
e-cosplay/templates/shop/product_details.twig
Serreau Jovann adefe7a1df ```
 feat(shop): Ajoute la page de détails du produit avec schema.org.
```
2025-11-20 13:25:05 +01:00

202 lines
8.9 KiB
Twig

{% extends 'base.twig' %}
{# --- METADATA & SCHEMA --- #}
{% block title %}{{ product.name }}{% endblock %}
{% block meta_description %}{{ product.shortDescription }}{% endblock %}
{% block canonical_url %}<link rel="canonical" href="{{ app.request.pathInfo }}" />{% endblock %}
{% block breadcrumb_schema %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "{{ 'breadcrumb.home'|trans }}",
"item": "{{ app.request.schemeAndHttpHost }}"
},
{
"@type": "ListItem",
"position": 2,
"name": "{{ product.name }}",
"item": "{{ app.request.schemeAndHttpHost }}{{ app.request.pathInfo }}"
}
]
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org/",
"@type": "ImageObject",
"contentUrl": "{{ vich_uploader_asset(product,'image') | imagine_filter('webp') }}",
"license": "https://example.com/license",
"acquireLicensePage": "{{ app.request.schemeAndHttpHost}}{{ path('app_legal') }}",
"creditText": "E-Cosplay",
"creator": {
"@type": "Person",
"name": "E-Cosplay"
},
"copyrightNotice": "E-Cosplay"
}}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org/",
"@type": "Product",
"name": "{{ product.name }}",
"image": "{{ vich_uploader_asset(product,'image') | imagine_filter('webp') }}",
"description": "{{ product.shortDescription }}",
"sku": "EC-{{ product.id }}",
"brand": {
"@type": "Brand",
"name": "E-COSPLAY"
},
"shippingDetails": {
"@type": "OfferShippingDetails",
"shippingRate": {
"@type": "MonetaryAmount",
"value": 6.00,
"currency": "EUR"
},
"shippingDestination": {
"@type": "DefinedRegion",
"addressCountry": "FR"
},
"deliveryTime": {
"@type": "ShippingDeliveryTime",
"handlingTime": {
"@type": "QuantitativeValue",
"minValue": 0,
"maxValue": 1,
"unitCode": "DAY"
},
"transitTime": {
"@type": "QuantitativeValue",
"minValue": 1,
"maxValue": 5,
"unitCode": "DAY"
}
}
},
"offers": {
"@type": "Offer",
"url": "{{ app.request.schemeAndHttpHost }}{{ path('app_product_show', {'slug': (product.name|lower|replace({' ': '-'}))~"-"~product.id}) }}",
"priceCurrency": "EUR",
"price": "{{ product.price }}",
"itemCondition": "https://schema.org/{% if product.state == 'new' %}NewCondition{% else %}UsedCondition{% endif %}",
"availability": "https://schema.org/InStock",
"hasMerchantReturnPolicy": {
"@type": "MerchantReturnPolicy",
"applicableCountry": "FR",
"returnPolicyCategory": "https://schema.org/{% if product.custom %}MerchantReturnNotPermitted {% else %}MerchantReturnFiniteReturnWindow{% endif %}",
"merchantReturnDays": {% if product.custom %}0{%else%}14{% endif %},
"returnFees": "https://schema.org/{% if product.custom %}ReturnFeesCustomerResponsibility{%else%}ReturnFeesCustomerResponsibility{% endif %}",
"returnMethod": "https://schema.org/ReturnByMail"
}
}
}
</script>
{% endblock %}
{# --- BODY --- #}
{% block body %}
{# Ajout d'une balise style pour définir les couleurs personnalisées du bouton #}
<style>
.btn-custom-yellow {
background-color: #FABF04; /* Couleur de base: Jaune vif */
color: #1f2937; /* Texte gris foncé pour un meilleur contraste */
}
.btn-custom-yellow:hover {
background-color: #e6a800; /* Jaune légèrement plus foncé au survol */
}
.btn-custom-yellow:focus {
--tw-ring-color: #f7d976; /* Anneau de focus jaune clair */
}
</style>
<main class="container mx-auto px-4 py-8">
{# Conteneur simplifié et épuré #}
<div class="max-w-7xl mx-auto p-4 lg:p-6">
{# Titre H1 #}
<h1 class="text-3xl lg:text-4xl font-extrabold text-gray-900 mb-6 text-center lg:text-left">
{{ product.name }}
</h1>
<div class="lg:grid lg:grid-cols-2 lg:gap-12">
{# --- Product Image (Left Column on Desktop) --- #}
<div class="mb-8 lg:mb-0">
<img src="{{ vich_uploader_asset(product,'image') | imagine_filter('webp') }}"
alt="{{ product.name }}"
class="w-full h-auto rounded-lg transition transform hover:scale-[1.01] duration-300"
>
</div>
{# --- Product Details & Actions (Right Column on Desktop) --- #}
<div class="flex flex-col space-y-8">
{# --- Price (Simple TTC Display) --- #}
<div class="pt-2">
<p class="text-5xl font-extrabold text-red-600">
{{ product.price|number_format(2, ',', ' ') }} € TTC
</p>
</div>
{# --- Short Description --- #}
<div class="pt-1">
<p class="text-xl text-gray-700 leading-relaxed">
{{ product.shortDescription }}
</p>
</div>
{# --- Reference and Custom/Handmade Tags --- #}
<div class="space-y-4 pt-2">
{# Product Reference #}
<p class="text-base text-gray-600">
<strong>{{ 'product_ref'|trans }}:</strong> <span class="font-medium text-gray-800">{{ product.ref }}</span>
</p>
{# Custom / Fait Main Badges #}
<div class="flex flex-wrap gap-2">
{% if product.handmade %}
<span class="inline-flex items-center px-3 py-1 text-sm font-semibold bg-pink-100 text-pink-800 rounded-full shadow-md">
<i class="fas fa-hand-sparkles mr-2"></i> {{ 'product_handmade'|trans }}
</span>
{% endif %}
{% if product.custom %}
<span class="inline-flex items-center px-3 py-1 text-sm font-semibold bg-indigo-100 text-indigo-800 rounded-full shadow-md">
<i class="fas fa-crown mr-2"></i> {{ 'product_custom'|trans }}
</span>
{% endif %}
</div>
</div>
{# --- Action: Add to Cart Button (Updated with custom yellow class) --- #}
<div class="pt-4" style="display:none;">
<button type="button"
class="w-full lg:w-3/4 px-6 py-4 btn-custom-yellow font-bold text-lg rounded-xl shadow-lg transition duration-300 transform hover:scale-[1.01] focus:outline-none focus:ring-4 focus:ring-opacity-75">
<i class="fas fa-shopping-cart mr-2"></i> {{ 'product_add_to_cart'|trans }}
</button>
</div>
{# Messages de livraison/stock traduits #}
<div class="text-sm text-gray-500 pt-2 space-y-1">
<p>{{ 'product_estimated_delivery'|trans }}</p>
<p>{{ 'product_shipping_methods'|trans }}</p>
</div>
</div>
</div>
{# --- Long Description (Full Width Below) --- #}
<div class="mt-12 pt-8 border-t border-gray-300">
<h2 class="text-2xl font-bold text-gray-800 mb-4">{{'product_long_desc_title'|trans}}</h2>
<div class="prose max-w-none text-gray-700 leading-relaxed">
{{ product.longDescription|raw }}
</div>
</div>
</div>
</main>
{% endblock %}