{% extends "Accueil/layoutAccueil.html.twig" %}
{% block title %}Commande Groupée — 5sur5 Séjour{% endblock %}
{% block stylesheets %}
{{ parent() }}
<style>
:root {
--bg-page: #F9FBFC;
--text-primary: #1a2b3c;
--text-secondary: #6B7280;
--border-light: #e2e8f0;
}
.group-order-page {
background: var(--bg-page);
min-height: calc(100vh - 80px);
padding: 60px 24px 80px;
}
.group-order-container {
max-width: 800px;
margin: 0 auto;
}
.group-order-header {
text-align: center;
margin-bottom: 40px;
}
.group-order-icon {
width: 80px;
height: 80px;
border-radius: 20px;
background: linear-gradient(135deg, rgba(245, 96, 64, 0.1) 0%, rgba(65, 162, 170, 0.1) 100%);
display: inline-flex;
align-items: center;
justify-content: center;
margin-bottom: 20px;
}
.group-order-icon i {
font-size: 36px;
background: linear-gradient(135deg, #F56040 0%, #41A2AA 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.group-order-title {
font-size: 32px;
font-weight: 700;
color: var(--text-primary);
margin-bottom: 12px;
}
.group-order-subtitle {
font-size: 16px;
color: var(--text-secondary);
max-width: 500px;
margin: 0 auto;
}
.group-order-badges {
display: flex;
justify-content: center;
gap: 16px;
margin-top: 20px;
flex-wrap: wrap;
}
.group-order-badge {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
background: white;
border: 1px solid var(--border-light);
border-radius: 30px;
font-size: 13px;
color: var(--text-secondary);
}
.group-order-badge i {
color: #F56040;
}
.group-order-card {
background: white;
border-radius: 20px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
overflow: hidden;
}
.group-order-progress {
padding: 24px 32px;
background: linear-gradient(135deg, rgba(65, 162, 170, 0.04) 0%, rgba(245, 96, 64, 0.04) 100%);
border-bottom: 1px solid var(--border-light);
}
.progress-tracker {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.step-dot {
width: 36px;
height: 36px;
border-radius: 50%;
background: white;
border: 2px solid #e5e5e5;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: 600;
color: #9b9b9b;
transition: all 0.3s ease;
}
.step-dot.active {
background: #41A2AA;
border-color: #41A2AA;
color: white;
}
.step-dot.completed {
background: #10B981;
border-color: #10B981;
color: white;
}
.step-line {
width: 60px;
height: 2px;
background: #e5e5e5;
transition: background 0.3s ease;
}
.step-line.completed {
background: #10B981;
}
.step-labels {
display: flex;
justify-content: center;
gap: 40px;
margin-top: 12px;
}
.step-label {
font-size: 12px;
font-weight: 500;
color: #9b9b9b;
transition: color 0.3s ease;
}
.step-label.active {
color: #41A2AA;
}
.group-order-body {
padding: 32px;
}
.form-step {
display: none;
}
.form-step.active {
display: block;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.section-title {
font-size: 18px;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 24px;
text-align: center;
}
/* Product Cards */
.products-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.product-card {
border: 2px solid #e5e7eb;
border-radius: 14px;
padding: 0;
cursor: pointer;
transition: all 0.3s ease;
overflow: hidden;
background: white;
}
.product-card:hover {
border-color: #41A2AA;
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}
.product-card.selected {
border-color: #1a1a1a;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
}
.product-image {
height: 120px;
background: linear-gradient(135deg, rgba(65, 162, 170, 0.08) 0%, rgba(245, 96, 64, 0.08) 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
}
.product-image img {
max-height: 100%;
max-width: 100%;
object-fit: contain;
}
.product-info {
padding: 16px;
text-align: center;
}
.product-title {
font-size: 14px;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 4px;
}
.product-desc {
font-size: 12px;
color: var(--text-secondary);
margin-bottom: 8px;
}
.product-requirement {
font-size: 11px;
color: #F56040;
}
/* Form inputs */
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
margin-bottom: 16px;
}
.form-row.full {
grid-template-columns: 1fr;
}
.form-group {
display: flex;
flex-direction: column;
gap: 6px;
}
.form-label {
font-size: 13px;
font-weight: 500;
color: var(--text-secondary);
}
.form-input {
padding: 12px 16px;
border: 1px solid #e5e7eb;
border-radius: 10px;
font-size: 14px;
color: var(--text-primary);
transition: all 0.2s ease;
}
.form-input:focus {
outline: none;
border-color: #41A2AA;
box-shadow: 0 0 0 3px rgba(65, 162, 170, 0.1);
}
.form-input.is-invalid {
border-color: #F56040;
}
/* Radio options */
.radio-group {
display: flex;
gap: 12px;
}
.radio-option {
flex: 1;
position: relative;
}
.radio-option input {
position: absolute;
opacity: 0;
}
.radio-option label {
display: block;
padding: 14px 20px;
border: 1px solid #e5e7eb;
border-radius: 10px;
text-align: center;
font-size: 14px;
font-weight: 500;
color: var(--text-primary);
cursor: pointer;
transition: all 0.2s ease;
}
.radio-option input:checked + label {
background: rgba(65, 162, 170, 0.08);
border-color: #41A2AA;
color: #41A2AA;
}
/* Discount display */
.discount-box {
background: linear-gradient(135deg, rgba(245, 96, 64, 0.08) 0%, rgba(245, 96, 64, 0.04) 100%);
border-radius: 12px;
padding: 20px;
text-align: center;
margin-top: 20px;
}
.discount-value {
font-size: 36px;
font-weight: 700;
color: #F56040;
}
.discount-label {
font-size: 14px;
color: var(--text-secondary);
}
/* Footer */
.group-order-footer {
padding: 20px 32px;
border-top: 1px solid var(--border-light);
display: flex;
justify-content: space-between;
align-items: center;
background: #fafbfc;
}
.footer-info {
display: flex;
align-items: center;
gap: 8px;
font-size: 13px;
color: var(--text-secondary);
}
.footer-info i {
color: #10B981;
}
.footer-actions {
display: flex;
gap: 12px;
}
.btn-back {
padding: 12px 24px;
border: 1px solid #e5e7eb;
border-radius: 10px;
background: white;
color: var(--text-secondary);
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
}
.btn-back:hover {
background: #f5f5f5;
}
.btn-next {
padding: 12px 32px;
border: none;
border-radius: 10px;
background: linear-gradient(135deg, #F56040 0%, #ff7659 100%);
color: white;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
box-shadow: 0 4px 12px rgba(245, 96, 64, 0.25);
}
.btn-next:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(245, 96, 64, 0.35);
}
.btn-submit {
padding: 12px 32px;
border: none;
border-radius: 10px;
background: linear-gradient(135deg, #41A2AA 0%, #359BA3 100%);
color: white;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
box-shadow: 0 4px 12px rgba(65, 162, 170, 0.25);
}
.btn-submit:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(65, 162, 170, 0.35);
}
/* Info section */
.info-section {
background: linear-gradient(135deg, rgba(65, 162, 170, 0.05) 0%, rgba(245, 96, 64, 0.05) 100%);
border-radius: 16px;
padding: 32px;
margin-top: 40px;
text-align: center;
}
.info-section h3 {
font-size: 20px;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 16px;
}
.info-section p {
font-size: 15px;
color: var(--text-secondary);
line-height: 1.6;
margin-bottom: 24px;
}
.info-benefits {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
margin-top: 24px;
}
.info-benefit {
text-align: center;
}
.info-benefit-icon {
width: 48px;
height: 48px;
border-radius: 12px;
background: white;
display: inline-flex;
align-items: center;
justify-content: center;
margin-bottom: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.info-benefit-icon i {
font-size: 22px;
color: #41A2AA;
}
.info-benefit h4 {
font-size: 14px;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 4px;
}
.info-benefit p {
font-size: 13px;
color: var(--text-secondary);
margin: 0;
}
/* Responsive */
@media (max-width: 768px) {
.group-order-page {
padding: 40px 16px 60px;
}
.group-order-title {
font-size: 26px;
}
.products-grid {
grid-template-columns: 1fr;
}
.form-row {
grid-template-columns: 1fr;
}
.radio-group {
flex-direction: column;
}
.group-order-footer {
flex-direction: column;
gap: 16px;
}
.footer-actions {
width: 100%;
}
.footer-actions button {
flex: 1;
}
.step-labels {
gap: 20px;
}
.step-line {
width: 30px;
}
.info-benefits {
grid-template-columns: 1fr;
}
}
</style>
{% endblock %}
{% block Content %}
<div class="group-order-page">
<div class="group-order-container">
{# Header #}
<div class="group-order-header">
<div class="group-order-icon">
<i class="bi bi-people-fill"></i>
</div>
<h1 class="group-order-title">Commande Groupée</h1>
<p class="group-order-subtitle">Proposez aux familles de commander ensemble et bénéficiez de réductions exclusives !</p>
<div class="group-order-badges">
<span class="group-order-badge"><i class="bi bi-percent"></i> Jusqu'à -20%</span>
<span class="group-order-badge"><i class="bi bi-truck"></i> Livraison gratuite</span>
<span class="group-order-badge"><i class="bi bi-shield-check"></i> Paiement sécurisé</span>
</div>
</div>
{# Form Card #}
<div class="group-order-card">
{# Progress #}
<div class="group-order-progress">
<div class="progress-tracker">
<div class="step-dot active" data-step="1">1</div>
<div class="step-line" id="line1"></div>
<div class="step-dot" data-step="2">2</div>
<div class="step-line" id="line2"></div>
<div class="step-dot" data-step="3">3</div>
</div>
<div class="step-labels">
<span class="step-label active" data-step="1">Produit</span>
<span class="step-label" data-step="2">Informations</span>
<span class="step-label" data-step="3">Validation</span>
</div>
</div>
{# Form Body #}
<form id="groupOrderForm" method="POST" action="{{ path('app_contact') }}">
<input type="hidden" name="subject" value="Demande de commande groupée">
<div class="group-order-body">
{# Step 1: Product #}
<div class="form-step active" id="step1">
<h3 class="section-title">Quel produit vous intéresse ?</h3>
<div class="products-grid">
<div class="product-card selected" onclick="selectProduct('livre', this)">
<input type="hidden" name="product_type" value="Livre Séjour">
<div class="product-image">
<img src="https://res.cloudinary.com/apss-factory/image/upload/v1585907734/newprod/LivreSouvenir5sur5-4_vyykcv.jpg" alt="Livre Séjour">
</div>
<div class="product-info">
<h4 class="product-title">Livre Séjour</h4>
<p class="product-desc">Format A4 • Couverture rigide</p>
<span class="product-requirement">📷 Min. 32 photos</span>
</div>
</div>
<div class="product-card" onclick="selectProduct('album', this)">
<div class="product-image">
<img src="https://res.cloudinary.com/apss-factory/image/upload/v1585907462/newprod/Album5sur5-5_zqlq4g.jpg" alt="Album Photo">
</div>
<div class="product-info">
<h4 class="product-title">Album Photo</h4>
<p class="product-desc">Format classique • Reliure souple</p>
<span class="product-requirement">📷 Min. 20 photos</span>
</div>
</div>
<div class="product-card" onclick="selectProduct('pochette', this)">
<div class="product-image">
<img src="https://5sur5sejour.com/images/produit/PochettePhoto5sur5-2.jpg" alt="Pochette Tirages">
</div>
<div class="product-info">
<h4 class="product-title">Pochette Tirages</h4>
<p class="product-desc">Photos 10×15 • Papier brillant</p>
<span class="product-requirement" style="color: #41A2AA;">✓ Toujours disponible</span>
</div>
</div>
</div>
</div>
{# Step 2: Contact Info #}
<div class="form-step" id="step2">
<h3 class="section-title">Vos coordonnées</h3>
<div class="form-row">
<div class="form-group">
<label class="form-label">Nom *</label>
<input type="text" name="name" id="contact_name" class="form-input" placeholder="Votre nom" required>
</div>
<div class="form-group">
<label class="form-label">Prénom *</label>
<input type="text" name="firstname" id="contact_firstname" class="form-input" placeholder="Votre prénom" required>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Email *</label>
<input type="email" name="email" id="contact_email" class="form-input" placeholder="votre@email.com" required>
</div>
<div class="form-group">
<label class="form-label">Téléphone *</label>
<input type="tel" name="phone" id="contact_phone" class="form-input" placeholder="06 00 00 00 00" required>
</div>
</div>
<div class="form-row full">
<div class="form-group">
<label class="form-label">Nom de l'établissement *</label>
<input type="text" name="organization" id="contact_organization" class="form-input" placeholder="École, collège, association..." required>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Nombre de familles estimé</label>
<input type="number" name="families_count" id="familyCount" class="form-input" value="10" min="1" max="500" style="text-align: center;">
</div>
<div class="form-group">
<label class="form-label">Réduction estimée</label>
<div class="discount-box" style="margin-top: 0; padding: 12px;">
<div class="discount-value" id="discountValue" style="font-size: 24px;">-10%</div>
</div>
</div>
</div>
</div>
{# Step 3: Validation #}
<div class="form-step" id="step3">
<h3 class="section-title">Message complémentaire</h3>
<div class="form-row full">
<div class="form-group">
<label class="form-label">Votre message (optionnel)</label>
<textarea name="message" class="form-input" rows="4" placeholder="Précisez vos besoins, dates du séjour, questions..."></textarea>
</div>
</div>
<div class="form-row full">
<div class="form-group">
<label style="display: flex; align-items: flex-start; gap: 10px; cursor: pointer;">
<input type="checkbox" name="consent" required style="margin-top: 4px;">
<span style="font-size: 13px; color: var(--text-secondary);">
J'accepte que mes données soient utilisées pour me recontacter concernant ma demande de commande groupée.
</span>
</label>
</div>
</div>
</div>
</div>
{# Footer #}
<div class="group-order-footer">
<div class="footer-info">
<i class="bi bi-shield-check"></i>
<span>Réponse sous 24h • Sans engagement</span>
</div>
<div class="footer-actions">
<button type="button" class="btn-back" id="btnBack" style="display: none;" onclick="prevStep()">
<i class="bi bi-arrow-left me-2"></i> Retour
</button>
<button type="button" class="btn-next" id="btnNext" onclick="nextStep()">
Suivant <i class="bi bi-arrow-right ms-2"></i>
</button>
<button type="submit" class="btn-submit" id="btnSubmit" style="display: none;">
<i class="bi bi-send me-2"></i> Envoyer ma demande
</button>
</div>
</div>
</form>
</div>
{# Info Section #}
<div class="info-section">
<h3>Comment ça fonctionne ?</h3>
<p>La commande groupée permet aux familles de bénéficier de tarifs réduits en commandant ensemble.</p>
<div class="info-benefits">
<div class="info-benefit">
<div class="info-benefit-icon">
<i class="bi bi-people"></i>
</div>
<h4>Regroupez les familles</h4>
<p>Plus il y a de participants, plus la réduction est importante</p>
</div>
<div class="info-benefit">
<div class="info-benefit-icon">
<i class="bi bi-percent"></i>
</div>
<h4>Jusqu'à -20%</h4>
<p>Des réductions exclusives pour les commandes groupées</p>
</div>
<div class="info-benefit">
<div class="info-benefit-icon">
<i class="bi bi-truck"></i>
</div>
<h4>Livraison unique</h4>
<p>Livraison gratuite à l'adresse de votre choix</p>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block javascript %}
{{ parent() }}
<script>
let currentStep = 1;
const totalSteps = 3;
function selectProduct(value, element) {
document.querySelectorAll('.product-card').forEach(card => card.classList.remove('selected'));
element.classList.add('selected');
// Update hidden input
const productNames = {
'livre': 'Livre Séjour',
'album': 'Album Photo',
'pochette': 'Pochette Tirages'
};
document.querySelector('input[name="product_type"]').value = productNames[value];
}
function showStep(step) {
// Hide all steps
document.querySelectorAll('.form-step').forEach(s => s.classList.remove('active'));
// Show current step
document.getElementById('step' + step).classList.add('active');
// Update progress dots
document.querySelectorAll('.step-dot').forEach((dot, index) => {
const stepNum = index + 1;
dot.classList.remove('active', 'completed');
if (stepNum === step) {
dot.classList.add('active');
} else if (stepNum < step) {
dot.classList.add('completed');
}
});
// Update progress lines
for (let i = 1; i < totalSteps; i++) {
const line = document.getElementById('line' + i);
if (line) {
line.classList.toggle('completed', i < step);
}
}
// Update labels
document.querySelectorAll('.step-label').forEach((label, index) => {
label.classList.toggle('active', (index + 1) === step);
});
// Update buttons
document.getElementById('btnBack').style.display = step > 1 ? 'inline-flex' : 'none';
document.getElementById('btnNext').style.display = step < totalSteps ? 'inline-flex' : 'none';
document.getElementById('btnSubmit').style.display = step === totalSteps ? 'inline-flex' : 'none';
currentStep = step;
}
function nextStep() {
// Validate step 2 (contact info)
if (currentStep === 2) {
const fields = ['contact_name', 'contact_firstname', 'contact_email', 'contact_phone', 'contact_organization'];
let isValid = true;
fields.forEach(id => {
const el = document.getElementById(id);
if (!el.value.trim()) {
el.classList.add('is-invalid');
isValid = false;
} else {
el.classList.remove('is-invalid');
}
});
if (!isValid) {
return;
}
}
if (currentStep < totalSteps) {
showStep(currentStep + 1);
}
}
function prevStep() {
if (currentStep > 1) {
showStep(currentStep - 1);
}
}
// Discount calculation
document.getElementById('familyCount').addEventListener('input', function() {
const count = parseInt(this.value) || 0;
let discount = 0;
if (count >= 30) discount = 20;
else if (count >= 20) discount = 15;
else if (count >= 10) discount = 10;
else if (count >= 5) discount = 5;
document.getElementById('discountValue').textContent = `-${discount}%`;
});
// Form validation on submit
document.getElementById('groupOrderForm').addEventListener('submit', function(e) {
const consent = document.querySelector('input[name="consent"]');
if (!consent.checked) {
e.preventDefault();
alert('Veuillez accepter les conditions pour envoyer votre demande.');
}
});
</script>
{% endblock %}