{% extends 'base_home.html.twig' %}
{% block title %}Accueil | MaketOu - Votre marketplace haïtienne
{% endblock %}
{% block stylesheets %}
<style>
/* Styles personnalisés pour la page d'accueil */
.hero-banner {
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
color: white;
padding: 100px 0;
position: relative;
overflow: hidden;
}
.hero-banner::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="1" fill="rgba(255, 255, 255, 0.1)"/><circle cx="75" cy="75" r="1" fill="rgba(255, 255, 255, 0.1)"/><circle cx="50" cy="10" r="0.5" fill="rgba(255, 255, 255, 0.1)"/><circle cx="10" cy="90" r="0.5" fill="rgba(255, 255, 255, 0.1)"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
opacity: 0.3;
}
.hero-content {
position: relative;
z-index: 2;
}
.stats-card {
background: white;
border-radius: 15px;
padding: 30px;
text-align: center;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease;
}
.stats-card:hover {
transform: translateY(-5px);
}
.stats-number {
font-size: 3rem;
font-weight: bold;
color: #ffa200;
display: block;
}
.stats-label {
color: #666;
font-size: 1.1rem;
margin-top: 10px;
}
.category-card {
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
height: 100%;
}
.category-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.15);
}
.category-image {
height: 200px;
background-size: cover;
background-position: center;
position: relative;
}
.category-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg, rgba(255,162,0,0.8), rgba(232,145,10,0.8));
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.category-card:hover .category-overlay {
opacity: 1;
}
.product-card {
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
height: 100%;
}
.product-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.15);
}
.product-image {
height: 250px;
background-size: cover;
background-position: center;
position: relative;
}
.product-badge {
position: absolute;
top: 15px;
right: 15px;
background: #ffa200;
color: white;
padding: 5px 10px;
border-radius: 20px;
font-size: 0.8rem;
font-weight: bold;
}
.product-info {
padding: 20px;
}
.product-title {
font-size: 1.2rem;
font-weight: 600;
margin-bottom: 10px;
color: #333;
}
.product-price {
font-size: 1.5rem;
font-weight: bold;
color: #ffa200;
margin-bottom: 10px;
}
.product-shop {
font-size: 0.9rem;
color: #666;
margin-bottom: 15px;
}
.btn-primary-custom {
background: #ffa200;
border: none;
color: white;
padding: 12px 30px;
border-radius: 25px;
font-weight: 500;
transition: all 0.3s ease;
}
.btn-primary-custom:hover {
background: #e8910a;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(255, 162, 0, 0.3);
}
.section-title {
text-align: center;
margin-bottom: 50px;
}
.section-title h2 {
font-size: 2.5rem;
font-weight: bold;
color: #333;
margin-bottom: 15px;
}
.section-title p {
font-size: 1.2rem;
color: #666;
max-width: 600px;
margin: 0 auto;
}
.feature-card {
text-align: center;
padding: 30px 20px;
background: white;
border-radius: 15px;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
height: 100%;
}
.feature-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.15);
}
.feature-icon {
width: 80px;
height: 80px;
background: linear-gradient(135deg, #ffa200, #e8910a);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 20px;
font-size: 2rem;
color: white;
}
.newsletter-section {
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
color: white;
padding: 80px 0;
}
.newsletter-form {
max-width: 500px;
margin: 0 auto;
}
.newsletter-form .form-control {
border: none;
border-radius: 25px;
padding: 15px 25px;
font-size: 1.1rem;
}
.newsletter-form .btn {
border-radius: 25px;
padding: 15px 30px;
font-weight: 500;
}
/* Styles pour les catégories personnalisées */
.category-card-custom {
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
height: 100%;
display: flex;
flex-direction: column;
}
.category-card-custom:hover {
transform: translateY(-5px);
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.15);
}
.category-image-wrapper {
position: relative;
overflow: hidden;
}
.category-image {
height: 200px;
background-size: cover;
background-position: center;
position: relative;
transition: transform 0.5s ease;
}
.category-card-custom:hover .category-image {
transform: scale(1.1);
}
.category-overlay-custom {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.category-card-custom:hover .category-overlay-custom {
opacity: 1;
}
.category-icon-wrapper {
text-align: center;
color: white;
transform: translateY(20px);
transition: transform 0.3s ease;
}
.category-card-custom:hover .category-icon-wrapper {
transform: translateY(0);
}
.category-content {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.category-content .btn {
margin-top: auto;
}
/* Responsive Styles */
@media(max-width: 991.98px) {
.hero-banner {
padding: 60px 0;
}
.stats-number {
font-size: 2.5rem;
}
.section-title h2 {
font-size: 2rem;
}
.stats-card {
margin-bottom: 1.5rem;
}
}
@media(max-width: 767.98px) {
.hero-banner {
padding: 40px 0;
}
.hero-content h1 {
font-size: 1.75rem;
}
.stats-number {
font-size: 2rem;
}
.stats-label {
font-size: 0.9rem;
}
.section-title h2 {
font-size: 1.75rem;
}
.section-title p {
font-size: 1rem;
}
.category-card,
.product-card {
margin-bottom: 1.5rem;
}
.category-image {
height: 150px;
}
.product-image {
height: 200px;
}
.feature-card {
margin-bottom: 1.5rem;
}
.newsletter-section {
padding: 40px 0;
}
}
@media(max-width: 575.98px) {
.hero-banner {
padding: 30px 0;
}
.hero-content h1 {
font-size: 1.5rem;
}
.stats-card {
padding: 1.5rem;
}
.stats-number {
font-size: 1.75rem;
}
.section-title h2 {
font-size: 1.5rem;
}
.category-image {
height: 120px;
}
.product-image {
height: 180px;
}
.product-info {
padding: 1rem;
}
.product-title {
font-size: 1rem;
}
.product-price {
font-size: 1.25rem;
}
}
/* Styles modernes pour le carousel de bannière */
.banner-area-modern {
position: relative;
width: 100%;
min-height: 500px;
background: url('{{ asset('ui/img/banner/banner-bg.jpg') }}') center center no-repeat;
background-size: cover;
overflow: hidden;
padding: 60px 0;
}
.banner-area-modern::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.1);
z-index: 1;
}
.banner-carousel-wrapper {
position: relative;
width: 100%;
height: 100%;
z-index: 2;
}
.banner-slide-item {
min-height: 500px;
display: flex;
align-items: center;
padding: 40px 0;
}
.banner-content-modern {
position: relative;
z-index: 2;
padding: 30px;
background: rgba(255, 255, 255, 0.98);
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
backdrop-filter: blur(10px);
animation: fadeInUp 0.8s ease;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.banner-badge {
display: inline-block;
background: linear-gradient(135deg, #ffa200 0%, #ff6b00 100%);
color: white;
padding: 8px 20px;
border-radius: 50px;
font-size: 0.85rem;
font-weight: 600;
margin-bottom: 20px;
box-shadow: 0 4px 15px rgba(255, 162, 0, 0.4);
}
.banner-badge i {
margin-right: 5px;
}
.banner-title-modern {
font-size: 2.0rem;
font-weight: 600;
color: #2c3e50;
margin-bottom: 20px;
line-height: 1.2;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.banner-description-modern {
font-size: 1.1rem;
color: #555;
line-height: 1.8;
margin-bottom: 25px;
}
.banner-price-modern {
display: flex;
align-items: center;
gap: 15px;
margin-bottom: 30px;
padding: 15px 20px;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border-radius: 12px;
border-left: 4px solid #ffa200;
}
.banner-price-modern .price-label {
font-size: 0.9rem;
color: #666;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1px;
}
.banner-price-modern .price-value {
font-size: 1.2rem;
font-weight: 600;
color: #ffa200;
}
.banner-actions-modern {
display: flex;
gap: 15px;
flex-wrap: wrap;
}
.btn-banner-primary {
display: inline-flex;
align-items: center;
gap: 10px;
padding: 15px 35px;
background: linear-gradient(135deg, #ffa200 0%, #ff6b00 100%);
color: white;
text-decoration: none;
border-radius: 50px;
font-weight: 600;
font-size: 1rem;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(255, 162, 0, 0.4);
}
.btn-banner-primary:hover {
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(255, 162, 0, 0.6);
color: white;
}
.btn-banner-primary .btn-icon {
transition: transform 0.3s ease;
}
.btn-banner-primary:hover .btn-icon {
transform: translateX(5px);
}
.btn-banner-secondary {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 15px 25px;
background: white;
color: #667eea;
text-decoration: none;
border-radius: 50px;
font-weight: 600;
font-size: 0.95rem;
border: 2px solid #667eea;
transition: all 0.3s ease;
}
.btn-banner-secondary:hover {
background: #667eea;
color: white;
transform: translateY(-3px);
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.banner-image-modern {
position: relative;
height: 450px;
display: flex;
align-items: center;
justify-content: center;
}
.banner-image-wrapper {
position: relative;
width: 100%;
height: 100%;
border-radius: 20px;
overflow: hidden;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
background: white;
padding: 20px;
}
.banner-img {
width: 100%;
height: 100%;
object-fit: contain;
border-radius: 15px;
transition: transform 0.5s ease;
}
.banner-slide-item:hover .banner-img {
transform: scale(1.05);
}
.banner-image-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
border-radius: 15px;
pointer-events: none;
}
/* Styles pour Owl Carousel */
.banner-area-modern .owl-nav {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
pointer-events: none;
z-index: 10;
left: 0;
right: 0;
box-sizing: border-box;
}
.banner-area-modern .owl-nav button {
width: 60px;
height: 60px;
min-width: 60px;
min-height: 60px;
background: #ffa200 !important;
border-radius: 50% !important;
display: flex !important;
align-items: center;
justify-content: center;
color: white !important;
font-size: 24px !important;
box-shadow: 0 4px 15px rgba(255, 162, 0, 0.4);
transition: all 0.3s ease;
pointer-events: all;
border: none !important;
position: relative;
flex-shrink: 0;
margin: 0;
padding: 0;
line-height: 1;
}
.banner-area-modern .owl-nav button.owl-prev {
margin-right: auto;
}
.banner-area-modern .owl-nav button.owl-next {
margin-left: auto;
}
.banner-area-modern .owl-nav button:hover {
background: #ff6b00 !important;
color: white !important;
transform: scale(1.1);
box-shadow: 0 6px 20px rgba(255, 162, 0, 0.6);
}
.banner-area-modern .owl-nav button.disabled {
opacity: 0.5;
cursor: not-allowed;
}
.banner-area-modern .owl-nav button.disabled:hover {
transform: scale(1);
}
.banner-area-modern .owl-dots {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 10px;
z-index: 10;
}
.banner-area-modern .owl-dots button {
width: 12px;
height: 12px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.6) !important;
border: 2px solid white !important;
transition: all 0.3s ease;
margin: 0 5px;
}
.banner-area-modern .owl-dots button.active {
background: #ffa200 !important;
border-color: #ffa200 !important;
width: 30px;
border-radius: 6px;
}
/* Responsive */
@media(max-width: 992px) {
.banner-area-modern {
min-height: 450px;
padding: 40px 0;
background-size: cover;
background-position: center;
}
.banner-slide-item {
min-height: 450px;
padding: 30px 0;
}
.banner-title-modern {
font-size: 1.5rem;
}
.banner-description-modern {
font-size: 1rem;
}
.banner-image-modern {
height: 350px;
margin-top: 30px;
}
.banner-content-modern {
padding: 25px;
}
}
@media(max-width: 768px) {
.banner-area-modern {
min-height: 400px;
padding: 30px 0;
background-size: cover;
background-position: center;
}
.banner-slide-item {
min-height: 400px;
padding: 20px 0;
}
.banner-title-modern {
font-size: 1.25rem;
}
.banner-description-modern {
font-size: 0.95rem;
}
.banner-image-modern {
height: 280px;
margin-top: 20px;
}
.banner-content-modern {
padding: 20px;
}
.banner-price-modern .price-value {
font-size: 1.25rem;
}
.banner-actions-modern {
flex-direction: column;
}
.btn-banner-primary,
.btn-banner-secondary {
width: 100%;
justify-content: center;
}
.banner-area-modern .owl-nav button {
width: 50px;
height: 50px;
min-width: 50px;
min-height: 50px;
font-size: 20px !important;
background: #ffa200 !important;
}
.banner-area-modern .owl-nav button:hover {
background: #ff6b00 !important;
}
}
@media(max-width: 576px) {
.banner-area-modern {
min-height: 350px;
padding: 0;
background-size: cover;
background-position: center;
}
.banner-slide-item {
min-height: 350px;
}
.banner-title-modern {
font-size: 1.25rem;
}
.banner-image-modern {
height: 220px;
}
.banner-content-modern {
padding: 15px;
}
}
/* Styles pour les catégories de boutiques cliquables */
.shop-category-clickable {
cursor: pointer;
transition: all 0.3s ease;
height: 100%;
}
.shop-category-clickable:hover {
transform: translateY(-10px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
.shop-category-clickable:hover .category-image {
transform: scale(1.1);
}
.shop-category-clickable:hover .btn-primary-custom {
background: #e8910a;
transform: translateX(5px);
}
/* Styles pour les cartes de catégories personnalisées */
.category-card-custom {
border-radius: 15px;
overflow: hidden;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
background: white;
height: 100%;
}
.category-card-custom:hover {
transform: translateY(-10px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
.category-image-wrapper {
position: relative;
height: 200px;
overflow: hidden;
}
.category-image {
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
transition: transform 0.3s ease;
}
.category-card-custom:hover .category-image {
transform: scale(1.1);
}
.category-overlay-custom {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
color: white;
}
.category-card-custom:hover .category-overlay-custom {
opacity: 1;
}
.category-icon-wrapper {
text-align: center;
}
.category-icon-wrapper i {
color: #ffa200;
display: block;
}
.category-icon-wrapper h4 {
color: white;
margin-top: 10px;
}
/* Styles pour la galerie de produits en vedette */
.featured-products-carousel-section {
position: relative;
overflow: hidden;
}
.featured-gallery-wrapper {
position: relative;
max-width: 1400px;
margin: 0 auto;
padding: 0 15px;
}
.featured-gallery-container {
position: relative;
overflow: visible;
border-radius: 12px;
}
.featured-gallery-grid {
display: flex;
gap: 30px;
padding: 15px 0;
overflow-x: auto;
overflow-y: hidden;
scroll-behavior: smooth;
scroll-behavior: smooth;
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE/Edge */
-webkit-overflow-scrolling: touch; /* iOS smooth scroll */
will-change: scroll-position;
}
.featured-gallery-grid::-webkit-scrollbar {
display: none; /* Chrome/Safari */
}
/* Mode OwlCarousel */
.featured-gallery-grid.owl-carousel {
display: block;
overflow: hidden;
padding: 25px 0;
}
.featured-gallery-grid.owl-carousel .owl-stage-outer {
overflow: visible;
}
.featured-gallery-grid.owl-carousel .featured-gallery-item {
opacity: 1;
transform: none;
width: auto;
max-width: none;
margin: 0 15px;
}
.featured-gallery-grid.owl-carousel .owl-stage {
display: flex;
}
.featured-gallery-item {
flex: 0 0 auto; /* Largeur automatique basée sur le contenu */
width: 100%;
max-width: 100%;
opacity: 0;
transform: translateY(20px) scale(0.95);
animation: galleryItemFadeIn 0.5s cubic-bezier(0.4, 0, 0.2, 1) forwards;
animation-delay: calc(var(--item-index, 0) * 0.05s);
}
/* Produits plus larges et esthétiques - 3 par ligne sur grands écrans */
@media(min-width: 1200px) {
.featured-gallery-item {
flex: 0 0 calc(33.333333% - 20px);
max-width: calc(33.333333% - 20px);
}
}
@media(min-width: 992px) and (max-width: 1199px) {
.featured-gallery-item {
flex: 0 0 calc(33.333333% - 20px);
max-width: calc(33.333333% - 20px);
}
}
@media(min-width: 768px) and (max-width: 991px) {
.featured-gallery-item {
flex: 0 0 calc(50% - 15px);
max-width: calc(50% - 15px);
}
}
@media(max-width: 767px) {
.featured-gallery-item {
flex: 0 0 100%;
max-width: 100%;
}
}
/* Design amélioré pour single-product - plus large et esthétique */
.featured-gallery-item .single-product {
margin-bottom: 0;
min-height: 520px;
display: flex;
flex-direction: column;
padding: 25px;
background: #fff;
border-radius: 16px;
box-shadow: 0 8px 25px rgba(15, 34, 58, 0.1);
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
border: 1px solid rgba(0, 0, 0, 0.05);
position: relative;
overflow: hidden;
}
.featured-gallery-item .single-product::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, #ffa200 0%, #ff6b00 100%);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.4s ease;
}
.featured-gallery-item .single-product:hover {
transform: translateY(-8px);
box-shadow: 0 20px 50px rgba(15, 34, 58, 0.15);
border-color: rgba(255, 162, 0, 0.3);
}
.featured-gallery-item .single-product:hover::before {
transform: scaleX(1);
}
/* S'assurer que les images s'affichent correctement - styles identiques à listing.html.twig */
.featured-gallery-item .single-product img {
margin-bottom: 20px;
width: 100%;
}
/* Styles améliorés pour product-image-container - plus large et esthétique */
.featured-gallery-item .product-image-container {
position: relative;
overflow: hidden;
border-radius: 14px;
height: 320px;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #f7f7fb 0%, #e8ecf1 100%);
margin-bottom: 22px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
}
.featured-gallery-item .product-image-container:hover {
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
}
.featured-gallery-item .product-image-container:hover .main-product-img {
transform: scale(1.08);
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.featured-gallery-item .product-image-container a {
display: block;
width: 100%;
height: 100%;
}
.featured-gallery-item .main-product-img {
transition: transform 0.3s ease;
width: 100% !important;
height: 100% !important;
object-fit: cover;
object-position: center;
display: block;
will-change: transform, opacity;
}
.featured-gallery-item .main-product-img.image-fade {
animation: imageFade 0.5s ease;
}
@keyframes imageFade {
from {
opacity: 0;
transform: scale(1.02);
}
to {
opacity: 1;
transform: scale(1);
}
}
.featured-gallery-item .product-details {
display: flex;
flex-direction: column;
height: 100%;
padding: 0 5px;
}
.featured-gallery-item .product-details h6 {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 12px;
line-height: 1.4;
color: #2c3e50;
min-height: 48px;
}
.featured-gallery-item .product-details h6 a {
color: #2c3e50;
text-decoration: none;
transition: color 0.3s ease;
}
.featured-gallery-item .product-details h6 a:hover {
color: #ffa200;
}
.featured-gallery-item .prd-bottom {
margin-top: auto;
}
/* Styles pour img-nav-btn - identiques à listing.html.twig */
.featured-gallery-item .img-nav-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(0, 0, 0, 0.6);
color: white;
border: none;
width: 35px;
height: 35px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
z-index: 10;
}
.featured-gallery-item .img-nav-btn:hover {
background: #095ad3;
transform: translateY(-50%) scale(1.1);
}
.featured-gallery-item .img-nav-left {
left: 10px;
}
.featured-gallery-item .img-nav-right {
right: 10px;
}
.featured-gallery-item .img-indicators {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 5px;
z-index: 10;
}
.featured-gallery-item .indicator {
width: 8px;
height: 8px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.5);
cursor: pointer;
margin-bottom: 10px;
transition: all 0.3s ease;
border: 1px solid rgba(255, 255, 255, 0.3);
}
.featured-gallery-item .indicator.active {
background: #ffa200;
border-color: #ffa200;
transform: scale(1.2);
}
.featured-gallery-item .indicator:hover {
background: rgba(255, 255, 255, 0.8);
}
/* Styles pour shop-info - identiques à listing.html.twig */
.featured-gallery-item .shop-info {
margin: 10px 0 15px 0;
padding: 8px 0;
border-bottom: 1px solid #f0f0f0;
}
.featured-gallery-item .shop-info small {
font-size: 0.9rem;
}
.featured-gallery-item .shop-link {
color: #007bff;
text-decoration: none;
font-weight: 500;
}
.featured-gallery-item .shop-link:hover {
color: #ffa200;
text-decoration: underline;
}
/* Styles améliorés pour le prix */
.featured-gallery-item .price {
margin-bottom: 18px;
}
.featured-gallery-item .price h6 {
font-size: 1.4rem;
font-weight: 700;
color: #ffa200;
margin-bottom: 5px;
}
.featured-gallery-item .price h6.l-through {
font-size: 1rem;
color: #95a5a6;
text-decoration: line-through;
font-weight: 500;
}
/* Les autres styles (prd-bottom, social-info) sont déjà définis dans main.css */
@keyframes galleryItemFadeIn {
from {
opacity: 0;
transform: translateY(20px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.featured-gallery-card {
display: flex;
flex-direction: column;
height: 100%;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
border: 1px solid #f0f0f0;
}
.featured-gallery-card:hover {
transform: translateY(-5px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
border-color: #ffa200;
}
.featured-gallery-image-wrapper {
position: relative;
width: 100%;
padding-top: 100%; /* Ratio 1:1 pour une galerie carrée */
overflow: hidden;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.featured-gallery-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.featured-gallery-card:hover .featured-gallery-image {
transform: scale(1.08);
}
.featured-gallery-badge {
position: absolute;
top: 8px;
left: 8px;
background: linear-gradient(135deg, #ffa200 0%, #ff6b00 100%);
color: white;
padding: 4px 10px;
border-radius: 15px;
font-size: 12px;
font-weight: 600;
z-index: 2;
box-shadow: 0 2px 8px rgba(255, 162, 0, 0.4);
}
.featured-gallery-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.featured-gallery-card:hover .featured-gallery-overlay {
opacity: 1;
}
.featured-gallery-view-btn {
background: white;
color: #333;
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
text-decoration: none;
font-size: 18px;
transform: scale(0.8);
transition: transform 0.3s ease;
}
.featured-gallery-card:hover .featured-gallery-view-btn {
transform: scale(1);
}
.featured-gallery-info {
padding: 12px;
flex: 1;
display: flex;
flex-direction: column;
}
.featured-gallery-title {
font-size: 14px;
font-weight: 600;
margin-bottom: 6px;
color: #333;
line-height: 1.3;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
min-height: 36px;
}
.featured-gallery-title a {
color: #333;
text-decoration: none;
transition: color 0.3s ease;
}
.featured-gallery-title a:hover {
color: #ffa200;
}
.featured-gallery-price {
font-size: 16px;
font-weight: 700;
color: #ffa200;
margin-bottom: 6px;
}
.featured-gallery-rating {
display: flex;
align-items: center;
gap: 3px;
font-size: 11px;
}
.featured-gallery-rating .fa-star.active {
color: #ffa200;
}
.featured-gallery-rating .fa-star-o {
color: #ddd;
}
.featured-gallery-controls {
display: flex;
justify-content: center;
gap: 20px;
margin-top: 25px;
padding: 0 20px;
}
.featured-gallery-nav-btn {
width: 42px;
height: 42px;
border-radius: 50%;
border: 1.5px solid #ffa200;
background: white;
color: #ffa200;
font-size: 16px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 3px 10px rgba(255, 162, 0, 0.18);
position: relative;
overflow: hidden;
}
.featured-gallery-nav-btn.btn-ripple::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
border-radius: 50%;
background: rgba(255, 162, 0, 0.2);
animation: rippleEffect 0.35s ease;
}
@keyframes rippleEffect {
from {
transform: scale(0.6);
opacity: 0.7;
}
to {
transform: scale(1.4);
opacity: 0;
}
}
.featured-gallery-nav-btn:hover:not(:disabled) {
background: #ffa200;
color: white;
transform: scale(1.1);
box-shadow: 0 5px 18px rgba(255, 162, 0, 0.4);
}
.featured-gallery-nav-btn:active:not(:disabled) {
transform: scale(0.95);
}
.featured-gallery-nav-btn:disabled {
opacity: 0.3;
cursor: not-allowed;
}
.featured-gallery-load-more {
margin-top: 30px;
}
/* Style pour le bouton "Voir tous les produits" */
.btn-view-all-products {
display: inline-flex;
align-items: center;
gap: 12px;
padding: 16px 40px;
background: linear-gradient(135deg, #ffa200 0%, #ff6b00 100%);
color: white;
text-decoration: none;
border-radius: 50px;
font-weight: 600;
font-size: 16px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 15px rgba(255, 162, 0, 0.3);
position: relative;
overflow: hidden;
}
.btn-view-all-products::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transition: left 0.5s ease;
}
.btn-view-all-products:hover::before {
left: 100%;
}
.btn-view-all-products:hover {
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(255, 162, 0, 0.5);
color: white;
}
.btn-view-all-products:active {
transform: translateY(-1px);
}
.btn-view-all-products i {
font-size: 18px;
transition: transform 0.3s ease;
}
.btn-view-all-products:hover i {
transform: translateX(5px);
}
.btn-view-all-products span {
position: relative;
z-index: 1;
}
/* Responsive */
@media(max-width: 767px) {
.btn-view-all-products {
padding: 14px 30px;
font-size: 14px;
}
}
/* Responsive */
@media(max-width: 767px) {
.featured-gallery-grid {
gap: 10px;
}
.featured-gallery-info {
padding: 10px;
}
.featured-gallery-title {
font-size: 13px;
min-height: 32px;
}
.featured-gallery-price {
font-size: 14px;
}
}
/* Styles pour les grilles de produits Nouveautés */
.latest-products-grid {
margin-top: 30px;
}
.product-card-modern {
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
height: 100%;
display: flex;
flex-direction: column;
border: 1px solid #f0f0f0;
}
.product-card-modern:hover {
transform: translateY(-8px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
border-color: #ffa200;
}
.product-image-wrapper {
position: relative;
width: 100%;
padding-top: 75%; /* Ratio 4:3 */
overflow: hidden;
background: #f8f9fa;
}
.product-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
transition: transform 0.5s ease;
}
.product-card-modern:hover .product-image {
transform: scale(1.1);
}
.product-badge-modern {
position: absolute;
top: 10px;
right: 10px;
background: linear-gradient(135deg, #ffa200 0%, #ff6b00 100%);
color: white;
padding: 6px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
z-index: 2;
box-shadow: 0 2px 8px rgba(255, 162, 0, 0.3);
}
.product-badge-modern.new-badge {
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
}
.product-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 1;
}
.product-card-modern:hover .product-overlay {
opacity: 1;
}
.btn-view-product {
background: white;
color: #333;
padding: 12px 24px;
border-radius: 25px;
text-decoration: none;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.btn-view-product:hover {
background: #ffa200;
color: white;
transform: scale(1.05);
}
.product-info-modern {
padding: 16px;
flex-grow: 1;
display: flex;
flex-direction: column;
}
.product-title-modern {
margin: 0 0 8px;
font-size: 16px;
font-weight: 600;
line-height: 1.4;
}
.product-title-modern a {
color: #333;
text-decoration: none;
transition: color 0.3s ease;
}
.product-title-modern a:hover {
color: #ffa200;
}
.product-price-modern {
font-size: 20px;
font-weight: 700;
color: #ffa200;
margin-bottom: 8px;
}
.product-shop-modern {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: #666;
margin-bottom: 8px;
}
.product-shop-modern i {
color: #ffa200;
}
.shop-link {
color: #666;
text-decoration: none;
transition: color 0.3s ease;
}
.shop-link:hover {
color: #ffa200;
}
.product-rating-modern {
display: flex;
align-items: center;
gap: 4px;
margin-top: auto;
}
.product-rating-modern .fa-star.active {
color: #ffc107;
}
.product-rating-modern .fa-star-o {
color: #ddd;
}
.rating-count {
font-size: 12px;
color: #666;
margin-left: 4px;
}
.product-views-modern {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: #666;
margin-top: auto;
}
.product-views-modern i {
color: #999;
}
/* Style des cartes produits */
.product-card {
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
height: 100%;
display: flex;
flex-direction: column;
}
.product-card:hover {
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.2);
transform: translateY(-5px);
}
.product-image {
width: 100%;
height: 250px;
background-size: cover;
background-position: center;
position: relative;
overflow: hidden;
}
.product-image::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transition: left 0.6s ease;
}
.product-card:hover .product-image::before {
left: 100%;
}
.product-badge {
position: absolute;
top: 15px;
right: 15px;
background: linear-gradient(135deg, #ffa200 0%, #ff6b00 100%);
color: white;
padding: 8px 15px;
border-radius: 20px;
font-size: 0.85rem;
font-weight: 600;
box-shadow: 0 4px 10px rgba(255, 162, 0, 0.4);
z-index: 1;
}
.product-info {
padding: 20px;
flex-grow: 1;
display: flex;
flex-direction: column;
}
.product-title {
font-size: 1.1rem;
font-weight: 600;
color: #2c3e50;
margin-bottom: 10px;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.product-price {
font-size: 1.5rem;
font-weight: 800;
color: #ffa200;
margin-bottom: 15px;
}
.product-shop {
font-size: 0.9rem;
color: #666;
margin-bottom: 15px;
}
.product-shop a {
color: #667eea;
text-decoration: none;
transition: color 0.3s ease;
}
.product-shop a:hover {
color: #ffa200;
}
/* Newsletter Modern Styles */
.newsletter-section-modern {
background: linear-gradient(135deg, #ffa200 0%, #095ad3 100%);
position: relative;
overflow: hidden;
}
.newsletter-section-modern::before {
content: '';
position: absolute;
top: -50%;
right: -50%;
width: 100%;
height: 200%;
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
animation: pulse 3s ease-in-out infinite;
}
@keyframes pulse {
0,
100% {
transform: scale(1);
opacity: 0.5;
}
50% {
transform: scale(1.1);
opacity: 0.8;
}
}
.newsletter-card {
background: white;
border-radius: 20px;
padding: 40px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
position: relative;
z-index: 1;
}
.newsletter-title {
font-size: 2.5rem;
font-weight: bold;
color: #333;
}
.newsletter-description {
color: #666;
font-size: 1.1rem;
line-height: 1.8;
}
.newsletter-form-modern {
position: relative;
}
.newsletter-input-wrapper {
display: flex;
gap: 10px;
margin-bottom: 15px;
}
.newsletter-input {
flex: 1;
padding: 18px 25px;
border: 2px solid #e0e0e0;
border-radius: 50px;
font-size: 1rem;
transition: all 0.3s ease; background: #fff;
color: #333;
}
.newsletter-input::placeholder {
color: #777;
}
.newsletter-input:focus {
outline: none;
border-color: #ffa200;
box-shadow: 0 0 0 3px rgba(255, 162, 0, 0.1);
}
.newsletter-button {
padding: 18px 35px;
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
color: white;
border: none;
border-radius: 50px;
font-weight: 600;
font-size: 1rem;
cursor: pointer;
transition: all 0.3s ease;
white-space: nowrap;
}
.newsletter-button:hover {
transform: translateY(-2px);
box-shadow: 0 5px 20px rgba(255, 162, 0, 0.4);
}
.newsletter-privacy {
color: #999;
}
/* CTA Modern Styles */
.cta-section-modern {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.cta-card {
background: white;
border-radius: 25px;
padding: 50px;
box-shadow: 0 15px 50px rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden;
}
.cta-card::before {
content: '';
position: absolute;
top: -50px;
right: -50px;
width: 200px;
height: 200px;
background: linear-gradient(135deg, rgba(255,162,0,0.1) 0%, rgba(255,162,0,0.05) 100%);
border-radius: 50%;
}
.cta-badge {
display: inline-block;
padding: 8px 20px;
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
color: white;
border-radius: 50px;
font-size: 0.9rem;
font-weight: 600;
margin-bottom: 20px;
}
.cta-title {
font-size: 3rem;
font-weight: bold;
color: #333;
margin-bottom: 20px;
}
.cta-description {
font-size: 1.2rem;
color: #666;
line-height: 1.8;
}
.cta-features {
display: flex;
flex-direction: column;
gap: 15px;
}
.cta-feature-item {
display: flex;
align-items: center;
gap: 10px;
font-size: 1rem;
color: #555;
}
.cta-feature-item i {
color: #ffa200;
font-size: 1.3rem;
}
.cta-buttons {
display: flex;
gap: 15px;
flex-wrap: wrap;
}
.cta-button-primary {
padding: 15px 35px;
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
color: white;
border: none;
border-radius: 50px;
font-weight: 600;
font-size: 1.1rem;
transition: all 0.3s ease;
}
.cta-button-primary:hover {
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(255, 162, 0, 0.4);
color: white;
}
.cta-button-secondary {
padding: 15px 35px;
background: white;
color: #ffa200;
border: 2px solid #ffa200;
border-radius: 50px;
font-weight: 600;
font-size: 1.1rem;
transition: all 0.3s ease;
}
.cta-button-secondary:hover {
background: #ffa200;
color: white;
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(255, 162, 0, 0.3);
}
.cta-image-wrapper {
position: relative;
}
.cta-decoration {
position: absolute;
top: -20px;
right: -20px;
width: 150px;
height: 150px;
background: linear-gradient(135deg, rgba(255,162,0,0.2) 0%, rgba(255,162,0,0.05) 100%);
border-radius: 50%;
z-index: 0;
}
.cta-image {
position: relative;
z-index: 1;
max-width: 100%;
height: auto;
border-radius: 15px;
}
</style>
{% endblock %}
{% block body %}
<!-- Hero Section -->
<!-- start banner Area avec produits en vedette -->
{% if bannerProducts is defined and bannerProducts|length > 0 %}
<section class="banner-area-modern"> <div class="banner-carousel-wrapper">
<div class="active-banner-slider owl-carousel" style="margin-top: 100px;">
{% for product in bannerProducts %}
<!-- single-slide -->
<div class="banner-slide-item">
<div class="container">
<div class="row align-items-center">
<div class="col-lg-4 col-md-6 col-12">
<div class="banner-content-modern">
<div class="banner-badge">
<i class="lnr lnr-star"></i>
Produit en vedette
</div>
<h1 class="banner-title-modern">{{ product.name }}</h1>
<p class="banner-description-modern">
{{ product.description ? (product.description|striptags|slice(0, 120) ~ '...') : 'Découvrez ce produit exclusif sur MaketOu' }}
</p>
<div class="banner-price-modern">
<span class="price-label">Prix</span>
<span class="price-value">{{ product.price|number_format(2, '.', ' ') }}
HTG</span>
</div>
<div class="banner-actions-modern">
<a class="btn-banner-primary" href="{{ path('ui_product_show', {'slug': product.slug}) }}">
<span class="btn-text">Voir le produit</span>
<span class="btn-icon">
<i class="lnr lnr-arrow-right"></i>
</span>
</a>
{% if product.shop %}
<a class="btn-banner-secondary" href="{{ path('ui_shop_show', {'slug': product.shop.slug}) }}">
<i class="lnr lnr-store"></i>
<span>{{ product.shop.name }}</span>
</a>
{% endif %}
</div>
</div>
</div>
<div class="col-lg-8 col-md-6 col-12">
<div class="banner-image-modern">
<div class="banner-image-wrapper">
{% if product.images is defined and product.images|length > 0 %}
<img class="banner-img" src="{{ product.images[0] is defined and product.images[0] ? asset(product.images[0]) : asset('ui/img/product/p' ~ loop.index ~ '.jpg') }}" alt="{{ product.name }}">
{% else %}
<img class="banner-img" src="{{ asset('ui/img/product/p' ~ loop.index ~ '.jpg') }}" alt="{{ product.name }}">
{% endif %}
<div class="banner-image-overlay"></div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</section>
{% else %}
<!-- Banner par défaut si pas de produits en vedette -->
<section class="banner-area-modern">
<div class="banner-carousel-wrapper">
<div class="container">
<div class="row align-items-center justify-content-center">
<div class="col-lg-8 text-center">
<div class="banner-content-modern" style="margin-top: 140px;">
<h1 class="banner-title-modern">Bienvenue sur MaketOu</h1>
<p class="banner-description-modern">Votre marketplace haïtienne</p>
</div>
</div>
</div>
</div>
</div>
</section>
{% endif %}
<!-- End banner Area -->
<!-- Catégories de produits -->
{% if categories|length > 0 %}
<section class="py-5">
<div class="container">
<div class="section-title">
<h2>Nos catégories</h2>
<p>Explorez nos différentes catégories de produits</p>
</div>
<div class="row" id="productCategoriesContainer">
{% for category in categories|slice(0, 8) %}
<div class="col-lg-3 col-md-4 col-sm-6 mb-4">
<div class="category-card-custom">
<div class="category-image-wrapper">
<div class="category-image" style="background-image: url('{% if category.bannerImage %}{{ asset('uploads/categories/banner/' ~ category.bannerImage) }}{% else %}{{ asset('ui/img/category/cat-' ~ loop.index ~ '.jpg') }}{% endif %}')">
<div class="category-overlay-custom">
<div class="category-icon-wrapper">
<i class="lnr lnr-tag" style="font-size: 3rem;"></i>
<h4 class="mt-3">{{ category.name }}</h4>
</div>
</div>
</div>
</div>
<div class="category-content p-3">
<h5 class="mb-2">{{ category.name }}</h5>
{% if category.description %}
<p class="text-muted mb-3 small">{{ category.description|striptags|slice(0, 60) }}
{% if category.description|striptags|length > 60 %}...
{% endif %}
</p>
{% endif %}
<a href="{{ path('ui_listing', {'category': category.slug}) }}" class="btn btn-primary-custom btn-sm w-100">
Voir les produits
</a>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</section>
{% endif %}
<!-- Catégories de boutiques -->
{% if shopCategories|length > 0 %}
<section class="py-5 bg-light">
<div class="container">
<div class="section-title">
<h2>Nos catégories de boutiques</h2>
<p>Explorez les différentes catégories de boutiques disponibles sur MaketOu</p>
</div>
<div class="row" id="shopCategoriesContainer">
{% for shopCategory in shopCategories|slice(0, 6) %}
<div class="col-lg-4 col-md-6 mb-4">
<a href="{{ path('ui_shops_list') }}?category={{ shopCategory.slug }}" class="text-decoration-none" style="display: block;">
<div class="category-card-custom shop-category-clickable">
<div class="category-image-wrapper">
<div class="category-image" style="background-image: url('{% if shopCategory.bannerImage %}{{ asset(shopCategory.bannerImage) }}{% else %}{{ asset('ui/img/category/shop-' ~ loop.index ~ '.jpg') }}{% endif %}')">
<div class="category-overlay-custom">
<div class="category-icon-wrapper">
<i class="lnr lnr-store" style="font-size: 3rem;"></i>
<h4 class="mt-3">{{ shopCategory.name }}</h4>
{% if shopCategory.description %}
<p class="mt-2 px-3">{{ shopCategory.description|striptags|slice(0, 100) }}
{% if shopCategory.description|striptags|length > 100 %}...
{% endif %}
</p>
{% endif %}
</div>
</div>
</div>
</div>
<div class="category-content p-3">
<h5 class="mb-2">{{ shopCategory.name }}</h5>
{% if shopCategory.description %}
<p class="text-muted mb-3 small">{{ shopCategory.description|striptags|slice(0, 80) }}
{% if shopCategory.description|striptags|length > 80 %}...
{% endif %}
</p>
{% endif %}
<span class="btn btn-primary-custom btn-sm w-100">
Voir les boutiques
<i class="lnr lnr-arrow-right ms-2"></i>
</span>
</div>
</div>
</a>
</div>
{% endfor %}
</div>
{% if shopCategories|length > 6 %}
<div class="text-center mt-4">
<button class="btn btn-outline-primary btn-lg" onclick="showAllShopCategories()">
<i class="lnr lnr-store me-2"></i>
Voir toutes les catégories de boutiques ({{ shopCategories|length }})
</button>
</div>
{% endif %}
</div>
</section>
{% endif %}
<!-- Produits en vedette -->
{% if featuredProducts|length > 0 %}
<section class="py-5">
<div class="container">
<div class="section-title text-center mb-5">
<h2>Produits en vedette</h2>
<p>Découvrez nos produits les plus populaires et les mieux notés</p>
</div>
<div class="featured-gallery-wrapper">
<div class="featured-gallery-container">
<div class="featured-gallery-grid" id="featuredGalleryGrid">
{% for product in featuredProducts %}
<div class="featured-gallery-item">
<div class="single-product">
<div class="product-image-container" onmouseenter="showImageNav({{ product.id }})" onmouseleave="hideImageNav({{ product.id }})">
<a href="{{ path('ui_product_show', { slug: product.slug }) }}">
{% if product.images is defined and product.images|length > 0 %}
<img
class="img-fluid main-product-img"
id="main-img-{{ product.id }}"
src="{{ asset(product.images[0]) }}"
alt="{{ product.name }}"
onerror="this.onerror=null;this.src='{{ asset('ui/img/product/p1.jpg') }}';"
>
{% else %}
<img class="img-fluid main-product-img" id="main-img-{{ product.id }}" src="{{ asset('ui/img/product/p1.jpg') }}" alt="{{ product.name }}">
{% endif %}
</a>
<!-- Boutons de navigation (visibles au survol) -->
{% if product.images is defined and product.images|length > 1 %}
<button class="img-nav-btn img-nav-left" id="img-left-{{ product.id }}" onclick="prevImage({{ product.id }})" style="display: none;">
<span class="lnr lnr-chevron-left"></span>
</button>
<button class="img-nav-btn img-nav-right" id="img-right-{{ product.id }}" onclick="nextImage({{ product.id }})" style="display: none;">
<span class="lnr lnr-chevron-right"></span>
</button>
<!-- Indicateurs de position -->
<div class="img-indicators" id="img-indicators-{{ product.id }}" style="display: none;">
{% for img in product.images %}
<span class="indicator" id="indicator-{{ product.id }}-{{ loop.index0 }}" onclick="showImage({{ product.id }}, {{ loop.index0 }})"></span>
{% endfor %}
</div>
{% endif %}
</div>
<div class="product-details">
<a href="{{ path('ui_product_show', { slug: product.slug }) }}">
<h6>{{ product.name }}</h6>
</a>
<!-- Affichage de la boutique -->
<div class="shop-info">
<small class="text-muted">
<i class="lnr lnr-store"></i>
Vendu par :
{% if product.shop is defined and product.shop %}
<a href="{{ path('ui_shop_show', {'slug': product.shop.slug}) }}" class="shop-link">
{{ product.shop.name }}
</a>
{% else %}
<span class="text-muted">Boutique inconnue</span>
{% endif %}
</small>
</div>
<div class="price">
<h6>{{ product.price|number_format(2, '.', ' ') }}
HTG</h6>
{% if product.compareAtPrice %}
<h6 class="l-through">{{ product.compareAtPrice|number_format(2, '.', ' ') }}
HTG</h6>
{% endif %}
</div>
<div class="prd-bottom">
<a href="javascript:void(0)" class="social-info add-to-cart" data-product-id="{{ product.id }}" data-qty="1">
<span class="ti-bag"></span>
<p class="hover-text">+ panier</p>
</a>
<a href="#" class="social-info wishlist-btn" data-product-id="{{ product.id }}" {% if app.user %} onclick="toggleWishlist({{ product.id }}, this); return false;" {% else %} onclick="alert('Vous devez être connecté pour ajouter aux favoris'); return false;" {% endif %}>
<span class="lnr lnr-heart"></span>
<p class="hover-text">Favoris</p>
</a>
<a href="#" class="social-info comparison-btn" data-product-id="{{ product.id }}" {% if app.user %} onclick="toggleComparison({{ product.id }}, this); return false;" {% else %} onclick="alert('Vous devez être connecté pour comparer des produits'); return false;" {% endif %}>
<span class="lnr lnr-sync"></span>
<p class="hover-text">Comparer</p>
</a>
<a href="{{ path('ui_product_show', { slug: product.slug }) }}" class="social-info">
<span class="lnr lnr-move"></span>
<p class="hover-text">Voir plus</p>
</a>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<!-- Contrôles de navigation -->
<div class="featured-gallery-controls">
<button class="featured-gallery-nav-btn featured-gallery-prev" id="featuredGalleryPrev" aria-label="Précédent">
<i class="lnr lnr-chevron-left"></i>
</button>
<button class="featured-gallery-nav-btn featured-gallery-next" id="featuredGalleryNext" aria-label="Suivant">
<i class="lnr lnr-chevron-right"></i>
</button>
</div>
<!-- Bouton charger plus -->
<div class="featured-gallery-load-more text-center mt-4" id="featuredGalleryLoadMore" style="display: none;">
<button class="btn btn-outline-primary" id="loadMoreFeaturedBtn">
<i class="lnr lnr-plus-circle me-2"></i>
Charger plus de produits
</button>
</div>
</div>
<div class="text-center mt-5">
<a href="{{ path('ui_listing') }}" class="btn-view-all-products">
<span>Voir tous les produits</span>
<i class="lnr lnr-arrow-right"></i>
</a>
</div>
</div>
</section>
{% endif %}
<!-- Nouveautés -->
{% if latestProducts|length > 0 %}
<section class="py-5 bg-light">
<div class="container">
<div class="section-title text-center mb-5">
<h2>Nouveautés</h2>
<p>Les derniers produits ajoutés sur MaketOu</p>
</div>
<div class="featured-gallery-wrapper">
<div class="featured-gallery-container">
<div class="featured-gallery-grid" id="latestGalleryGrid">
{% for product in latestProducts %}
<div class="featured-gallery-item">
<div class="single-product">
<div class="product-image-container" onmouseenter="showImageNav({{ product.id }})" onmouseleave="hideImageNav({{ product.id }})">
<a href="{{ path('ui_product_show', { slug: product.slug }) }}">
{% if product.images is defined and product.images|length > 0 %}
<img class="img-fluid main-product-img" id="main-img-{{ product.id }}" src="{{ asset(product.images[0]) }}" alt="{{ product.name }}">
{% else %}
<img class="img-fluid main-product-img" id="main-img-{{ product.id }}" src="{{ asset('ui/img/product/p1.jpg') }}" alt="{{ product.name }}">
{% endif %}
</a>
<!-- Boutons de navigation (visibles au survol) -->
{% if product.images is defined and product.images|length > 1 %}
<button class="img-nav-btn img-nav-left" id="img-left-{{ product.id }}" onclick="prevImage({{ product.id }})" style="display: none;">
<span class="lnr lnr-chevron-left"></span>
</button>
<button class="img-nav-btn img-nav-right" id="img-right-{{ product.id }}" onclick="nextImage({{ product.id }})" style="display: none;">
<span class="lnr lnr-chevron-right"></span>
</button>
<!-- Indicateurs de position -->
<div class="img-indicators" id="img-indicators-{{ product.id }}" style="display: none;">
{% for img in product.images %}
<span class="indicator" id="indicator-{{ product.id }}-{{ loop.index0 }}" onclick="showImage({{ product.id }}, {{ loop.index0 }})"></span>
{% endfor %}
</div>
{% endif %}
</div>
<div class="product-details">
<a href="{{ path('ui_product_show', { slug: product.slug }) }}">
<h6>{{ product.name }}</h6>
</a>
<!-- Affichage de la boutique -->
<div class="shop-info">
<small class="text-muted">
<i class="lnr lnr-store"></i>
Vendu par :
{% if product.shop is defined and product.shop %}
<a href="{{ path('ui_shop_show', {'slug': product.shop.slug}) }}" class="shop-link">
{{ product.shop.name }}
</a>
{% else %}
<span class="text-muted">Boutique inconnue</span>
{% endif %}
</small>
</div>
<div class="price">
<h6>{{ product.price|number_format(2, '.', ' ') }}
HTG</h6>
{% if product.compareAtPrice %}
<h6 class="l-through">{{ product.compareAtPrice|number_format(2, '.', ' ') }}
HTG</h6>
{% endif %}
</div>
<div class="prd-bottom">
<a href="javascript:void(0)" class="social-info add-to-cart" data-product-id="{{ product.id }}" data-qty="1">
<span class="ti-bag"></span>
<p class="hover-text">+ panier</p>
</a>
<a href="#" class="social-info wishlist-btn" data-product-id="{{ product.id }}" {% if app.user %} onclick="toggleWishlist({{ product.id }}, this); return false;" {% else %} onclick="alert('Vous devez être connecté pour ajouter aux favoris'); return false;" {% endif %}>
<span class="lnr lnr-heart"></span>
<p class="hover-text">Favoris</p>
</a>
<a href="#" class="social-info comparison-btn" data-product-id="{{ product.id }}" {% if app.user %} onclick="toggleComparison({{ product.id }}, this); return false;" {% else %} onclick="alert('Vous devez être connecté pour comparer des produits'); return false;" {% endif %}>
<span class="lnr lnr-sync"></span>
<p class="hover-text">Comparer</p>
</a>
<a href="{{ path('ui_product_show', { slug: product.slug }) }}" class="social-info">
<span class="lnr lnr-move"></span>
<p class="hover-text">Voir plus</p>
</a>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<!-- Contrôles de navigation -->
<div class="featured-gallery-controls">
<button class="featured-gallery-nav-btn featured-gallery-prev" id="latestGalleryPrev" aria-label="Précédent">
<i class="lnr lnr-chevron-left"></i>
</button>
<button class="featured-gallery-nav-btn featured-gallery-next" id="latestGalleryNext" aria-label="Suivant">
<i class="lnr lnr-chevron-right"></i>
</button>
</div>
<!-- Bouton charger plus -->
<div class="featured-gallery-load-more text-center mt-4" id="latestGalleryLoadMore" style="display: none;">
<button class="btn btn-outline-primary" id="loadMoreLatestBtn">
<i class="lnr lnr-plus-circle me-2"></i>
Charger plus de produits
</button>
</div>
</div>
<div class="text-center mt-5">
<a href="{{ path('ui_listing') }}" class="btn-view-all-products">
<span>Voir tous les produits</span>
<i class="lnr lnr-arrow-right"></i>
</a>
</div>
</div>
</section>
{% endif %}
{% if recommendedProducts|length > 0 %}
<section class="py-5">
<div class="container">
<div class="section-title text-center mb-5">
<h2>Recommandés pour vous</h2>
<p>Suggestions basées sur votre activité récente et les tendances de MaketOu</p>
</div>
<div class="row g-4">
{% for product in recommendedProducts %}
<div class="col-12 col-sm-6 col-lg-3">
<div class="product-card h-100">
{% set productImage = product.images[0] ?? 'ui/img/product/p1.jpg' %}
<div class="product-image" style="background-image:url('{{ asset(productImage) }}');">
{% if product.isFeatured %}
<span class="product-badge bg-success">Populaire</span>
{% endif %}
</div>
<div class="p-3">
<h6 class="mb-2">
<a href="{{ path('ui_product_show', { slug: product.slug }) }}">{{ product.name }}</a>
</h6>
<p class="mb-2 text-muted small">
<i class="lnr lnr-store"></i>
{% if product.shop %}
<a href="{{ path('ui_shop_show', {'slug': product.shop.slug}) }}">{{ product.shop.name }}</a>
{% else %}
Boutique non spécifiée
{% endif %}
</p>
<div class="d-flex align-items-center justify-content-between">
<span class="fw-bold text-primary">{{ product.price|number_format(2, '.', ' ') }} HTG</span>
<a href="javascript:void(0)" class="btn btn-sm btn-outline-primary add-to-cart" data-product-id="{{ product.id }}" data-qty="1">
<i class="ti ti-bag"></i>
</a>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</section>
{% endif %}
{% if recentlyViewedProducts|length > 0 %}
<section class="py-5 bg-light">
<div class="container">
<div class="section-title text-center mb-5">
<h2>Récemment consultés</h2>
<p>Retrouvez les articles que vous avez explorés dernièrement</p>
</div>
<div class="featured-gallery-wrapper">
<div class="featured-gallery-container">
<div class="featured-gallery-grid">
{% for product in recentlyViewedProducts %}
<div class="featured-gallery-item">
<div class="single-product">
<div class="product-image-container">
<a href="{{ path('ui_product_show', { slug: product.slug }) }}">
{% if product.images is defined and product.images|length > 0 %}
<img class="img-fluid main-product-img" src="{{ asset(product.images[0]) }}" alt="{{ product.name }}">
{% else %}
<img class="img-fluid main-product-img" src="{{ asset('ui/img/product/p1.jpg') }}" alt="{{ product.name }}">
{% endif %}
</a>
</div>
<div class="product-details">
<a href="{{ path('ui_product_show', { slug: product.slug }) }}">
<h6>{{ product.name }}</h6>
</a>
<div class="price">
<h6>{{ product.price|number_format(2, '.', ' ') }} HTG</h6>
</div>
<div class="prd-bottom">
<a href="javascript:void(0)" class="social-info add-to-cart" data-product-id="{{ product.id }}" data-qty="1">
<span class="ti-bag"></span>
<p class="hover-text">+ panier</p>
</a>
<a href="{{ path('ui_product_show', { slug: product.slug }) }}" class="social-info">
<span class="lnr lnr-move"></span>
<p class="hover-text">Voir</p>
</a>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</section>
{% endif %}
<!-- Fonctionnalités -->
<section class="py-5">
<div class="container">
<div class="section-title">
<h2>Pourquoi choisir MaketOu ?</h2>
<p>Découvrez les avantages de notre plateforme</p>
</div>
<div class="row">
<div class="col-lg-3 col-md-6 mb-4">
<div class="feature-card">
<div class="feature-icon">
<i class="lnr lnr-rocket"></i>
</div>
<h5>Livraison rapide</h5>
<p>Recevez vos commandes rapidement avec notre réseau de livraison optimisé</p>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-4">
<div class="feature-card">
<div class="feature-icon">
<i class="lnr lnr-lock"></i>
</div>
<h5>Paiement sécurisé</h5>
<p>Vos transactions sont protégées avec les dernières technologies de sécurité</p>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-4">
<div class="feature-card">
<div class="feature-icon">
<i class="lnr lnr-phone"></i>
</div>
<h5>Support 24/7</h5>
<p>Notre équipe est disponible pour vous aider à tout moment</p>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-4">
<div class="feature-card">
<div class="feature-icon">
<i class="lnr lnr-undo"></i>
</div>
<h5>Retour facile</h5>
<p>Politique de retour flexible pour votre tranquillité d'esprit</p>
</div>
</div>
</div>
</div>
</section>
<!-- Newsletter -->
<section class="newsletter-section-modern py-5">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-10">
<div class="newsletter-card">
<div class="row align-items-center">
<div class="col-lg-6 text-center text-lg-start mb-4 mb-lg-0">
<div class="newsletter-icon mb-3">
<i class="lnr lnr-envelope" style="font-size: 4rem; color: #ffa200;"></i>
</div>
<h2 class="newsletter-title mb-3">Restez informé des dernières nouveautés</h2>
<p class="newsletter-description mb-0">
Inscrivez-vous à notre newsletter pour recevoir les offres exclusives,
les nouveaux produits et les meilleures promotions directement dans votre boîte mail.
</p>
</div>
<div class="col-lg-6">
<form class="newsletter-form-modern" id="newsletterFormHome">
<div class="newsletter-input-wrapper">
<input type="email" class="newsletter-input" placeholder="Votre adresse email" required name="email">
<button class="newsletter-button" type="submit">
<i class="lnr lnr-arrow-right me-2"></i>
S'abonner
</button>
</div>
<p class="newsletter-privacy mt-3 text-center">
<small>
<i class="lnr lnr-lock me-1"></i>
Vos données sont sécurisées. Pas de spam, désinscription facile.
</small>
</p>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Call to Action -->
<section class="cta-section-modern py-5">
<div class="container">
<div class="cta-card">
<div class="row align-items-center">
<div class="col-lg-6 mb-4 mb-lg-0">
<div class="cta-content">
<span class="cta-badge">
<i class="lnr lnr-rocket me-2"></i>
Commencez dès aujourd'hui
</span>
<h2 class="cta-title mb-3">Prêt à commencer ?</h2>
<p class="cta-description mb-4">
Que vous soyez
<strong>acheteur</strong>
ou
<strong>vendeur</strong>, MaketOu vous offre la plateforme idéale
pour vos besoins commerciaux en Haïti. Rejoignez des milliers d'utilisateurs satisfaits !
</p>
<div class="cta-features mb-4">
<div class="cta-feature-item">
<i class="lnr lnr-checkmark-circle"></i>
<span>Plateforme 100% sécurisée</span>
</div>
<div class="cta-feature-item">
<i class="lnr lnr-checkmark-circle"></i>
<span>Support client 24/7</span>
</div>
<div class="cta-feature-item">
<i class="lnr lnr-checkmark-circle"></i>
<span>Paiements multiples</span>
</div>
</div>
<div class="cta-buttons">
<button type="button" class="btn cta-button-primary" onclick="openReadyModal()">
<i class="lnr lnr-rocket me-2"></i>
Prêt à commencer ?
</button>
<a href="{{ path('ui_listing') }}" class="btn cta-button-secondary">
<i class="lnr lnr-magnifier me-2"></i>
Voir les produits
</a>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="cta-image-wrapper">
<div class="cta-decoration"></div>
<img src="{{ asset('Start.png') }}" alt="MaketOu" class="cta-image">
</div>
</div>
</div>
</div>
</div>
</section>
{% endblock %}
{% block javascripts %}
<script src="{{ asset('ui/js/product-unified.js') }}"></script>
<script>
window.openReadyModal = function () {
const modalEl = document.getElementById('readyModal');
if (!modalEl) {
console.error('readyModal introuvable');
return;
}
if (typeof bootstrap === 'undefined' || !bootstrap.Modal) {
console.error('Bootstrap Modal non chargé');
return;
}
const modalInstance = bootstrap.Modal.getOrCreateInstance(modalEl);
modalInstance.show();
};
</script>
<script>
// Variables globales pour la navigation des images (si pas déjà définies)
if (typeof productImages === 'undefined') {
window.productImages = {};
window.currentImageIndex = {};
}
// Initialisation des données d'images pour les produits "Produits en vedette"
{% if featuredProducts is defined %}
{% for product in featuredProducts %}
{% if product.images is defined and product.images|length > 0 %}
productImages[{{ product.id }}] = [{% for img in product.images %}'{{ asset(img) }}'{% if not loop.last %},{% endif %}{% endfor %}];
currentImageIndex[{{ product.id }}] = 0;{% endif %}{% endfor %}{% endif %}
// Initialisation des données d'images pour les produits "Nouveautés"
{% if latestProducts is defined %}
{% for product in latestProducts %}
{% if product.images is defined and product.images|length > 0 %}
productImages[{{ product.id }}] = [{% for img in product.images %}'{{ asset(img) }}'{% if not loop.last %},{% endif %}{% endfor %}];
currentImageIndex[{{ product.id }}] = 0;{% endif %}{% endfor %}{% endif %}
console.log('SCRIPT LOADED - Featured Gallery');
(function () {
'use strict';
const SECTION_CONFIGS = [
{ grid: '#featuredGalleryGrid', prev: '#featuredGalleryPrev', next: '#featuredGalleryNext' },
{ grid: '#latestGalleryGrid', prev: '#latestGalleryPrev', next: '#latestGalleryNext' }
];
function triggerRipple(button) {
button.classList.remove('btn-ripple');
void button.offsetWidth;
button.classList.add('btn-ripple');
setTimeout(() => button.classList.remove('btn-ripple'), 350);
}
function initSectionCarousel(config) {
const $grid = $(config.grid);
if (!$grid.length) {
console.warn('Grid not found:', config.grid);
return;
}
if (typeof $.fn.owlCarousel !== 'function') {
console.warn('OwlCarousel n\'est pas chargé pour', config.grid);
return;
}
// Si déjà initialisé, récupérer l'instance existante
let owlInstance;
if ($grid.hasClass('owl-loaded')) {
owlInstance = $grid.data('owl.carousel');
console.log('OwlCarousel already initialized for', config.grid, owlInstance);
} else {
if (!$grid.hasClass('owl-carousel')) {
$grid.addClass('owl-carousel');
}
owlInstance = $grid.owlCarousel({
loop: true,
margin: 30,
autoplay: true,
autoplayTimeout: 4800,
autoplayHoverPause: true,
smartSpeed: 650,
nav: false,
dots: false,
responsive: {
0: { items: 1, margin: 15 },
576: { items: 1.2, margin: 18 },
768: { items: 2, margin: 20 },
992: { items: 3, margin: 25 },
1400: { items: 4, margin: 30 }
}
});
console.log('OwlCarousel initialized for', config.grid, owlInstance);
}
const $prev = $(config.prev);
const $next = $(config.next);
if ($prev.length) {
$prev.off('click.carouselNav').on('click.carouselNav', function (e) {
e.preventDefault();
e.stopPropagation();
console.log('Prev clicked for', config.grid, 'Instance:', owlInstance);
if (owlInstance) {
try {
$grid.trigger('prev.owl.carousel');
triggerRipple(this);
} catch (err) {
console.error('Error triggering prev:', err);
}
} else {
console.error('OwlCarousel instance not available');
}
});
} else {
console.warn('Prev button not found:', config.prev);
}
if ($next.length) {
$next.off('click.carouselNav').on('click.carouselNav', function (e) {
e.preventDefault();
e.stopPropagation();
console.log('Next clicked for', config.grid, 'Instance:', owlInstance);
if (owlInstance) {
try {
$grid.trigger('next.owl.carousel');
triggerRipple(this);
} catch (err) {
console.error('Error triggering next:', err);
}
} else {
console.error('OwlCarousel instance not available');
}
});
} else {
console.warn('Next button not found:', config.next);
}
}
function ensureOwl(attempt = 0) {
if (window.jQuery && typeof $.fn !== 'undefined' && typeof $.fn.owlCarousel === 'function') {
SECTION_CONFIGS.forEach(initSectionCarousel);
} else if (attempt < 15) {
setTimeout(() => ensureOwl(attempt + 1), 200);
} else {
console.warn('OwlCarousel non disponible après plusieurs tentatives');
}
}
document.addEventListener('DOMContentLoaded', function () {
ensureOwl();
});
})();
document.addEventListener('DOMContentLoaded', function () { // Animation des cartes au scroll
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver(function (entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
// Observer toutes les cartes
document.querySelectorAll('.stats-card, .category-card, .product-card, .feature-card').forEach(card => {
card.style.opacity = '0';
card.style.transform = 'translateY(30px)';
card.style.transition = 'all 0.6s ease';
observer.observe(card);
});
// Compteur animé pour les statistiques
function animateCounter(element, target, duration = 2000) {
let start = 0;
const increment = target / (duration / 16);
function updateCounter() {
start += increment;
if (start < target) {
element.textContent = Math.floor(start).toLocaleString();
requestAnimationFrame(updateCounter);
} else {
element.textContent = target.toLocaleString();
}
}
updateCounter();
}
// Animer les compteurs quand ils sont visibles
const statsObserver = new IntersectionObserver(function (entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
const numberElement = entry.target.querySelector('.stats-number');
const target = parseInt(numberElement.textContent.replace(/,/g, ''));
animateCounter(numberElement, target);
statsObserver.unobserve(entry.target);
}
});
});
document.querySelectorAll('.stats-card').forEach(card => {
statsObserver.observe(card);
});
// Gestion de la newsletter
const newsletterForm = document.querySelector('.newsletter-form');
if (newsletterForm) {
newsletterForm.addEventListener('submit', function (e) {
e.preventDefault();
const email = this.querySelector('input[type="email"]').value;
const button = this.querySelector('button');
const originalText = button.innerHTML;
// Désactiver le bouton
button.disabled = true;
button.innerHTML = '<i class="lnr lnr-spinner me-2"></i>Inscription...';
// Envoyer la requête
fetch('{{ path("ui_newsletter_subscribe") }}', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest'
},
body: 'email=' + encodeURIComponent(email)
}).then(response => response.json()).then(data => {
if (data.success) {
button.innerHTML = '<i class="lnr lnr-check me-2"></i>Inscription réussie !';
button.classList.remove('btn-warning');
button.classList.add('btn-success');
this.reset();
} else {
button.innerHTML = '<i class="lnr lnr-warning me-2"></i>Erreur';
button.classList.remove('btn-warning');
button.classList.add('btn-danger');
}
setTimeout(() => {
button.innerHTML = originalText;
button.classList.remove('btn-success', 'btn-danger');
button.classList.add('btn-warning');
button.disabled = false;
}, 3000);
}).catch(error => {
console.error('Erreur:', error);
button.innerHTML = '<i class="lnr lnr-warning me-2"></i>Erreur';
button.classList.remove('btn-warning');
button.classList.add('btn-danger');
setTimeout(() => {
button.innerHTML = originalText;
button.classList.remove('btn-danger');
button.classList.add('btn-warning');
button.disabled = false;
}, 3000);
});
});
}
});
// Effet parallaxe léger pour le hero
window.addEventListener('scroll', function () {
const scrolled = window.pageYOffset;
const hero = document.querySelector('.hero-banner');
if (hero) {
hero.style.transform = `translateY(${
scrolled * 0.5
}px)`;
}
});
});
// Fonction pour afficher toutes les catégories
function showAllCategories () {
const container = document.getElementById('productCategoriesContainer');
const btn = document.getElementById('showAllCategoriesBtn');{% if allCategories|length > 8 %}{% for category in allCategories %}{% if loop.index > 8 %}const categoryHtml {{ loop.index }} = `
<div class="col-lg-3 col-md-4 col-sm-6 mb-4">
<div class="category-card-custom">
<div class="category-image-wrapper">
<div class="category-image" style="background-image: url('{% if category.bannerImage %}{{ asset('uploads/categories/banner/' ~ category.bannerImage) }}{% else %}{{ asset('ui/img/category/cat-' ~ loop.index ~ '.jpg') }}{% endif %}')">
<div class="category-overlay-custom">
<div class="category-icon-wrapper">
<i class="lnr lnr-tag" style="font-size: 3rem;"></i>
<h4 class="mt-3">{{ category.name }}</h4>
</div>
</div>
</div>
</div>
<div class="category-content p-3">
<h5 class="mb-2">{{ category.name }}</h5>
{% if category.description %}
<p class="text-muted mb-3 small">{{ category.description|striptags|slice(0, 60) }}{% if category.description|striptags|length > 60 %}...{% endif %}</p>
{% endif %}
<a href="{{ path('ui_listing', {'category': category.slug}) }}" class="btn btn-primary-custom btn-sm w-100">
Voir les produits
</a>
</div>
</div>
</div>
`;
container.insertAdjacentHTML('beforeend', categoryHtml {{ loop.index }});{% endif %}{% endfor %}{% endif %}if (btn)
btn.style.display = 'none';
}
// Fonction pour afficher toutes les catégories de boutiques
function showAllShopCategories () {
const container = document.getElementById('shopCategoriesContainer');
const btn = document.querySelector('[onclick="showAllShopCategories()"]') ?. parentElement;{% if allShopCategories|length > 6 %}{% for shopCategory in allShopCategories %}{% if loop.index > 6 %}const shopCategoryHtml {{ loop.index }} = `
<div class="col-lg-4 col-md-6 mb-4">
<a href="{{ path('ui_shops_list') }}?category={{ shopCategory.slug }}" class="text-decoration-none" style="display: block;">
<div class="category-card-custom shop-category-clickable">
<div class="category-image-wrapper">
<div class="category-image" style="background-image: url('{% if shopCategory.bannerImage %}{{ asset(shopCategory.bannerImage) }}{% else %}{{ asset('ui/img/category/shop-' ~ loop.index ~ '.jpg') }}{% endif %}')">
<div class="category-overlay-custom">
<div class="category-icon-wrapper">
<i class="lnr lnr-store" style="font-size: 3rem;"></i>
<h4 class="mt-3">{{ shopCategory.name }}</h4>
{% if shopCategory.description %}
<p class="mt-2 px-3">{{ shopCategory.description|striptags|slice(0, 100) }}{% if shopCategory.description|striptags|length > 100 %}...{% endif %}</p>
{% endif %}
</div>
</div>
</div>
</div>
<div class="category-content p-3">
<h5 class="mb-2">{{ shopCategory.name }}</h5>
{% if shopCategory.description %}
<p class="text-muted mb-3 small">{{ shopCategory.description|striptags|slice(0, 80) }}{% if shopCategory.description|striptags|length > 80 %}...{% endif %}</p>
{% endif %}
<span class="btn btn-primary-custom btn-sm w-100">
Voir les boutiques <i class="lnr lnr-arrow-right ms-2"></i>
</span>
</div>
</div>
</a>
</div>
`;
container.insertAdjacentHTML('beforeend', shopCategoryHtml {{ loop.index }});{% endif %}{% endfor %}{% endif %}if (btn)
btn.style.display = 'none';
}
// Initialiser les carousels
<script src="{{ asset('ui/js/product-unified.js') }}"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Init featured products images
{% if featuredProducts is defined %}
{% for product in featuredProducts %}
{% if product.images is defined and product.images|length > 0 %}
if (typeof initProductImages === 'function') {
initProductImages({{ product.id }}, {{ product.images|json_encode|raw }});
}
{% endif %}
{% endfor %}
{% endif %}
// Init latest products images
{% if latestProducts is defined %}
{% for product in latestProducts %}
{% if product.images is defined and product.images|length > 0 %}
if (typeof initProductImages === 'function') {
initProductImages({{ product.id }}, {{ product.images|json_encode|raw }});
}
{% endif %}
{% endfor %}
{% endif %}
});
</script>
<script>
$(document).ready(function () { // Carousel bannière principale
if ($('.active-banner-slider').length) {
$('.active-banner-slider').owlCarousel({
items: 1,
loop: true,
autoplay: true,
autoplayTimeout: 6000,
autoplayHoverPause: true,
nav: true,
dots: true,
navText: [
'<i class="lnr lnr-chevron-left"></i>', '<i class="lnr lnr-chevron-right"></i>'
],
smartSpeed: 1000,
animateOut: 'fadeOut',
animateIn: 'fadeIn',
responsive: {
0: {
items: 1,
nav: true,
dots: true
},
768: {
items: 1,
nav: true,
dots: true
},
992: {
items: 1,
nav: true,
dots: true
}
}
});
}
// Animation d'apparition pour les cartes produits
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const productObserver = new IntersectionObserver(function (entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
document.querySelectorAll('.product-card-modern').forEach((card, index) => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = `opacity 0.6s ease ${
index * 0.1
}s, transform 0.6s ease ${
index * 0.1
}s`;
productObserver.observe(card);
});
});
</script>
<!-- Modal "Prêt à commencer ?" -->
<div class="modal fade" id="readyModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="lnr lnr-rocket me-2"></i>Prêt à commencer ?
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
{% if app.user %}
{% if app.user.kycStatus == 'verified' %}
<div class="text-center">
<i class="lnr lnr-checkmark-circle" style="font-size: 4rem; color: #28a745;"></i>
<h4 class="mt-3">Votre compte est vérifié !</h4>
<p class="text-muted">Vous pouvez commencer à utiliser MaketOu en toute sérénité.</p>
<div class="mt-4">
<a href="{{ path('seller_index') }}" class="btn btn-primary me-2">
<i class="lnr lnr-store me-1"></i>Ouvrir ma boutique
</a>
<a href="{{ path('ui_listing') }}" class="btn btn-outline-primary">
<i class="lnr lnr-magnifier me-1"></i>Voir les produits
</a>
</div>
</div>
{% else %}
<div class="text-center">
<i class="lnr lnr-shield" style="font-size: 4rem; color: #ffa200;"></i>
<h4 class="mt-3">Vérification requise</h4>
<p class="text-muted">Pour utiliser toutes les fonctionnalités de MaketOu, vous devez compléter votre vérification KYC.</p>
<div class="mt-4">
<a href="{{ path('ui_account_kyc') }}" class="btn btn-primary btn-lg">
<i class="lnr lnr-checkmark-circle me-1"></i> <span class="d-none d-md-inline">Commencer la vérification</span>
</a>
</div>
</div>
{% endif %}
{% else %}
<div class="text-center">
<i class="lnr lnr-user" style="font-size: 4rem; color: #007bff;"></i>
<h4 class="mt-3">Connectez-vous pour commencer</h4>
<p class="text-muted">Créez un compte ou connectez-vous pour accéder à toutes les fonctionnalités de MaketOu.</p>
<div class="mt-4">
<a href="{{ path('ui_app_login') }}" class="btn btn-primary btn-lg me-2">
<i class="lnr lnr-enter me-1"></i> Se connecter
</a>
<a href="{{ path('ui_app_register') }}" class="btn btn-outline-primary btn-lg">
<i class="lnr lnr-user-plus me-1"></i> S'inscrire
</a>
</div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock %}