<?php
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Extension\CoreExtension;
use Twig\Extension\SandboxExtension;
use Twig\Markup;
use Twig\Sandbox\SecurityError;
use Twig\Sandbox\SecurityNotAllowedTagError;
use Twig\Sandbox\SecurityNotAllowedFilterError;
use Twig\Sandbox\SecurityNotAllowedFunctionError;
use Twig\Source;
use Twig\Template;
use Twig\TemplateWrapper;
/* shop/reviews/index.html.twig */
class __TwigTemplate_b3685988d74272770f151e22763354d4 extends Template
{
private Source $source;
/**
* @var array<string, Template>
*/
private array $macros = [];
public function __construct(Environment $env)
{
parent::__construct($env);
$this->source = $this->getSourceContext();
$this->blocks = [
'title' => [$this, 'block_title'],
'stylesheets' => [$this, 'block_stylesheets'],
'body' => [$this, 'block_body'],
'javascripts' => [$this, 'block_javascripts'],
];
}
protected function doGetParent(array $context): bool|string|Template|TemplateWrapper
{
// line 1
return "base_home.html.twig";
}
protected function doDisplay(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "shop/reviews/index.html.twig"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "shop/reviews/index.html.twig"));
$this->parent = $this->load("base_home.html.twig", 1);
yield from $this->parent->unwrap()->yield($context, array_merge($this->blocks, $blocks));
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
}
// line 3
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_title(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "title"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "title"));
yield "Avis - ";
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "name", [], "any", false, false, false, 3), "html", null, true);
yield " | MaketOu";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 5
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_stylesheets(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "stylesheets"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "stylesheets"));
// line 6
yield " ";
yield from $this->yieldParentBlock("stylesheets", $context, $blocks);
yield "
<style>
/* Styles spécifiques aux reviews - tous scoped pour éviter les conflits avec le template de base */
.shop-reviews-page .review-card {
border: 1px solid #e0e0e0;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
background: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.shop-reviews-page .review-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.shop-reviews-page .review-user {
display: flex;
align-items: center;
}
.shop-reviews-page .review-user-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background: linear-gradient(45deg, #667eea, #764ba2);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
margin-right: 12px;
}
.shop-reviews-page .review-user-info h6 {
margin: 0;
font-weight: 600;
color: #333;
}
.shop-reviews-page .review-user-info small {
color: #666;
}
.shop-reviews-page .review-rating {
display: flex;
align-items: center;
gap: 5px;
}
.shop-reviews-page .stars {
color: #ffc107;
font-size: 18px;
}
.shop-reviews-page .review-date {
color: #666;
font-size: 14px;
}
.shop-reviews-page .review-content {
margin-bottom: 15px;
line-height: 1.6;
color: #333;
}
.shop-reviews-page .review-type {
display: inline-block;
background: #f8f9fa;
color: #495057;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
margin-bottom: 10px;
}
.shop-reviews-page .review-actions {
display: flex;
gap: 10px;
align-items: center;
}
.shop-reviews-page .helpful-btn {
background: none;
border: 1px solid #dee2e6;
padding: 5px 10px;
border-radius: 4px;
font-size: 12px;
color: #6c757d;
cursor: pointer;
transition: all 0.3s ease;
}
.shop-reviews-page .helpful-btn:hover {
background: #f8f9fa;
border-color: #adb5bd;
}
.shop-reviews-page .helpful-btn.active {
background: #28a745;
color: white;
border-color: #28a745;
}
.shop-reviews-page .stats-card {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.shop-reviews-page .stats-header {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.shop-reviews-page .overall-rating {
font-size: 48px;
font-weight: bold;
color: #333;
margin-right: 20px;
}
.shop-reviews-page .rating-breakdown {
flex: 1;
}
.shop-reviews-page .rating-bar {
display: flex;
align-items: center;
margin-bottom: 8px;
}
.shop-reviews-page .rating-label {
width: 60px;
font-size: 14px;
color: #666;
}
.shop-reviews-page .rating-progress {
flex: 1;
height: 8px;
background: #e9ecef;
border-radius: 4px;
margin: 0 10px;
overflow: hidden;
}
.shop-reviews-page .rating-fill {
height: 100%;
background: linear-gradient(45deg, #ffc107, #ff8c00);
transition: width 0.3s ease;
}
.shop-reviews-page .rating-count {
width: 40px;
text-align: right;
font-size: 14px;
color: #666;
}
.shop-reviews-page .filters-card {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.shop-reviews-page .filter-group {
margin-bottom: 15px;
}
.shop-reviews-page .filter-group label {
font-weight: 600;
margin-bottom: 5px;
display: block;
}
.shop-reviews-page .rating-filter {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.shop-reviews-page .rating-btn {
padding: 8px 12px;
border: 1px solid #dee2e6;
background: white;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
font-size: 14px;
}
.shop-reviews-page .rating-btn:hover {
background: #f8f9fa;
}
.shop-reviews-page .rating-btn.active {
background: #007bff;
color: white;
border-color: #007bff;
}
.shop-reviews-page .verified-badge {
background: #28a745;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
margin-left: 5px;
}
.shop-reviews-page .pagination-wrapper {
display: flex;
justify-content: center;
margin-top: 30px;
}
.shop-reviews-page .btn-review {
background: linear-gradient(45deg, #667eea, #764ba2);
border: none;
color: white;
padding: 12px 24px;
border-radius: 6px;
font-weight: 600;
text-decoration: none;
display: inline-block;
transition: all 0.3s ease;
}
.shop-reviews-page .btn-review:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
color: white;
}
.shop-reviews-page .empty-reviews {
text-align: center;
padding: 60px 20px;
color: #666;
}
.shop-reviews-page .empty-reviews i {
font-size: 64px;
color: #ddd;
margin-bottom: 20px;
}
@media (max-width: 768px) {
.shop-reviews-page .review-header {
flex-direction: column;
align-items: flex-start;
}
.shop-reviews-page .stats-header {
flex-direction: column;
text-align: center;
}
.shop-reviews-page .overall-rating {
margin-right: 0;
margin-bottom: 15px;
}
.shop-reviews-page .rating-filter {
justify-content: center;
}
}
</style>
";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 285
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_body(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "body"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "body"));
// line 286
yield " <div class=\"shop-reviews-page\">
<!-- Breadcrumb -->
<section class=\"banner-area organic-breadcrumb\">
<div class=\"container\">
<div class=\"breadcrumb-banner d-flex flex-wrap align-items-center justify-content-end\">
<div class=\"col-first\">
<h1>Avis - ";
// line 292
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "name", [], "any", false, false, false, 292), "html", null, true);
yield "</h1>
<nav class=\"d-flex align-items-center\">
<a href=\"";
// line 294
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_home");
yield "\">Accueil<span class=\"lnr lnr-arrow-right\"></span></a>
<a href=\"";
// line 295
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_shop_show", ["slug" => CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "slug", [], "any", false, false, false, 295)]), "html", null, true);
yield "\">";
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "name", [], "any", false, false, false, 295), "html", null, true);
yield "<span class=\"lnr lnr-arrow-right\"></span></a>
<a href=\"javascript:void(0)\">Avis</a>
</nav>
</div>
</div>
</div>
</section>
<section class=\"blog_area\">
<div class=\"container my-5\">
<div class=\"row\">
<!-- Statistiques des avis -->
<div class=\"col-12\">
<div class=\"stats-card\">
<div class=\"stats-header\">
<div class=\"overall-rating\">
";
// line 311
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Twig\Extension\CoreExtension']->formatNumber(CoreExtension::getAttribute($this->env, $this->source, ($context["stats"] ?? null), "averageRating", [], "any", false, false, false, 311), 1), "html", null, true);
yield "
<div class=\"stars\">";
// line 312
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['App\Twig\RatingExtension']->formatRatingStars(CoreExtension::getAttribute($this->env, $this->source, ($context["stats"] ?? null), "averageRating", [], "any", false, false, false, 312)), "html", null, true);
yield "</div>
</div>
<div class=\"rating-breakdown\">
";
// line 315
$context["ratingMap"] = [5 => "fiveStars", 4 => "fourStars", 3 => "threeStars", 2 => "twoStars", 1 => "oneStar"];
// line 322
yield " ";
$context['_parent'] = $context;
$context['_seq'] = CoreExtension::ensureTraversable(range(5, 1));
foreach ($context['_seq'] as $context["_key"] => $context["rating"]) {
// line 323
yield " ";
$context["ratingKey"] = (($_v0 = ($context["ratingMap"] ?? null)) && is_array($_v0) || $_v0 instanceof ArrayAccess ? ($_v0[$context["rating"]] ?? null) : null);
// line 324
yield " ";
$context["ratingCount"] = ((CoreExtension::getAttribute($this->env, $this->source, ($context["stats"] ?? null), ($context["ratingKey"] ?? null), [], "any", true, true, false, 324)) ? (Twig\Extension\CoreExtension::default(CoreExtension::getAttribute($this->env, $this->source, ($context["stats"] ?? null), ($context["ratingKey"] ?? null), [], "any", false, false, false, 324), 0)) : (0));
// line 325
yield " ";
$context["percentage"] = (((CoreExtension::getAttribute($this->env, $this->source, ($context["stats"] ?? null), "totalReviews", [], "any", false, false, false, 325) > 0)) ? (((($context["ratingCount"] ?? null) / CoreExtension::getAttribute($this->env, $this->source, ($context["stats"] ?? null), "totalReviews", [], "any", false, false, false, 325)) * 100)) : (0));
// line 326
yield " <div class=\"rating-bar\">
<span class=\"rating-label\">";
// line 327
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["rating"], "html", null, true);
yield " étoiles</span>
<div class=\"rating-progress\">
<div class=\"rating-fill\" style=\"width: ";
// line 329
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(($context["percentage"] ?? null), "html", null, true);
yield "%\"></div>
</div>
<span class=\"rating-count\">";
// line 331
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(($context["ratingCount"] ?? null), "html", null, true);
yield "</span>
</div>
";
}
$_parent = $context['_parent'];
unset($context['_seq'], $context['_key'], $context['rating'], $context['_parent']);
$context = array_intersect_key($context, $_parent) + $_parent;
// line 334
yield " </div>
</div>
<div class=\"row text-center\">
<div class=\"col-md-3\">
<h4>";
// line 338
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, ($context["stats"] ?? null), "totalReviews", [], "any", false, false, false, 338), "html", null, true);
yield "</h4>
<p class=\"text-muted mb-0\">Avis total</p>
</div>
<div class=\"col-md-3\">
<h4>";
// line 342
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, ($context["stats"] ?? null), "positivePercentage", [], "any", false, false, false, 342), "html", null, true);
yield "%</h4>
<p class=\"text-muted mb-0\">Positifs</p>
</div>
<div class=\"col-md-3\">
<h4>";
// line 346
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, ($context["stats"] ?? null), "verifiedReviews", [], "any", false, false, false, 346), "html", null, true);
yield "</h4>
<p class=\"text-muted mb-0\">Vérifiés</p>
</div>
<div class=\"col-md-3\">
<h4>";
// line 350
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(((CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "followersCount", [], "any", true, true, false, 350)) ? (Twig\Extension\CoreExtension::default(CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "followersCount", [], "any", false, false, false, 350), 0)) : (0)), "html", null, true);
yield "</h4>
<p class=\"text-muted mb-0\">Followers</p>
</div>
</div>
</div>
</div>
<!-- Filtres -->
<div class=\"col-md-3\">
<div class=\"filters-card\">
<h5 class=\"mb-3\">Filtrer les avis</h5>
<div class=\"filter-group\">
<label>Note</label>
<div class=\"rating-filter\">
<button class=\"rating-btn ";
// line 365
yield (((CoreExtension::getAttribute($this->env, $this->source, ($context["filters"] ?? null), "rating", [], "any", false, false, false, 365) == "")) ? ("active") : (""));
yield "\" data-rating=\"\">
Toutes
</button>
";
// line 368
$context['_parent'] = $context;
$context['_seq'] = CoreExtension::ensureTraversable(range(5, 1));
foreach ($context['_seq'] as $context["_key"] => $context["rating"]) {
// line 369
yield " <button class=\"rating-btn ";
yield (((CoreExtension::getAttribute($this->env, $this->source, ($context["filters"] ?? null), "rating", [], "any", false, false, false, 369) == $context["rating"])) ? ("active") : (""));
yield "\" data-rating=\"";
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["rating"], "html", null, true);
yield "\">
";
// line 370
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["rating"], "html", null, true);
yield "★
</button>
";
}
$_parent = $context['_parent'];
unset($context['_seq'], $context['_key'], $context['rating'], $context['_parent']);
$context = array_intersect_key($context, $_parent) + $_parent;
// line 373
yield " </div>
</div>
<div class=\"filter-group\">
<label>
<input type=\"checkbox\" ";
// line 378
yield (((($tmp = CoreExtension::getAttribute($this->env, $this->source, ($context["filters"] ?? null), "verified", [], "any", false, false, false, 378)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) ? ("checked") : (""));
yield " id=\"verified-filter\">
Avis vérifiés uniquement
</label>
</div>
<div class=\"filter-group\">
<label>Rechercher</label>
<input type=\"text\" class=\"form-control\" id=\"search-filter\" placeholder=\"Rechercher dans les avis...\" value=\"";
// line 385
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, ($context["filters"] ?? null), "search", [], "any", false, false, false, 385), "html", null, true);
yield "\">
</div>
<button class=\"btn btn-primary w-100\" onclick=\"applyFilters()\">
Appliquer les filtres
</button>
</div>
";
// line 393
if ((($tmp = ($context["canReview"] ?? null)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 394
yield " <div class=\"text-center mt-3\">
<a href=\"";
// line 395
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("shop_reviews_new", ["slug" => CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "slug", [], "any", false, false, false, 395)]), "html", null, true);
yield "\" class=\"btn-review\">
<i class=\"lnr lnr-star\"></i> Laisser un avis
</a>
</div>
";
}
// line 400
yield " </div>
<!-- Liste des avis -->
<div class=\"col-md-9\">
";
// line 404
if ((Twig\Extension\CoreExtension::length($this->env->getCharset(), ($context["reviews"] ?? null)) > 0)) {
// line 405
yield " <div id=\"reviews-container\">
";
// line 406
$context['_parent'] = $context;
$context['_seq'] = CoreExtension::ensureTraversable(($context["reviews"] ?? null));
foreach ($context['_seq'] as $context["_key"] => $context["review"]) {
// line 407
yield " <div class=\"review-card\">
<div class=\"review-header\">
<div class=\"review-user\">
<div class=\"review-user-avatar\">
";
// line 411
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(Twig\Extension\CoreExtension::default(Twig\Extension\CoreExtension::upper($this->env->getCharset(), Twig\Extension\CoreExtension::first($this->env->getCharset(), CoreExtension::getAttribute($this->env, $this->source, CoreExtension::getAttribute($this->env, $this->source, $context["review"], "user", [], "any", false, false, false, 411), "firstName", [], "any", false, false, false, 411))), Twig\Extension\CoreExtension::upper($this->env->getCharset(), Twig\Extension\CoreExtension::first($this->env->getCharset(), CoreExtension::getAttribute($this->env, $this->source, CoreExtension::getAttribute($this->env, $this->source, $context["review"], "user", [], "any", false, false, false, 411), "email", [], "any", false, false, false, 411)))), "html", null, true);
yield "
</div>
<div class=\"review-user-info\">
<h6>";
// line 414
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(((CoreExtension::getAttribute($this->env, $this->source, CoreExtension::getAttribute($this->env, $this->source, $context["review"], "user", [], "any", false, true, false, 414), "firstName", [], "any", true, true, false, 414)) ? (Twig\Extension\CoreExtension::default(CoreExtension::getAttribute($this->env, $this->source, CoreExtension::getAttribute($this->env, $this->source, $context["review"], "user", [], "any", false, false, false, 414), "firstName", [], "any", false, false, false, 414), "Utilisateur")) : ("Utilisateur")), "html", null, true);
yield "</h6>
<small>";
// line 415
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, $context["review"], "getTimeAgo", [], "method", false, false, false, 415), "html", null, true);
yield "</small>
</div>
</div>
<div class=\"review-rating\">
<div class=\"stars\">";
// line 419
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, $context["review"], "getRatingStars", [], "method", false, false, false, 419), "html", null, true);
yield "</div>
";
// line 420
if ((($tmp = CoreExtension::getAttribute($this->env, $this->source, $context["review"], "isVerified", [], "any", false, false, false, 420)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 421
yield " <span class=\"verified-badge\">✓ Vérifié</span>
";
}
// line 423
yield " </div>
</div>
";
// line 426
if ((($tmp = CoreExtension::getAttribute($this->env, $this->source, $context["review"], "reviewType", [], "any", false, false, false, 426)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 427
yield " <div class=\"review-type\">";
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, $context["review"], "getReviewTypeLabel", [], "method", false, false, false, 427), "html", null, true);
yield "</div>
";
}
// line 429
yield "
<div class=\"review-content\">
";
// line 431
yield Twig\Extension\CoreExtension::nl2br($this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, $context["review"], "comment", [], "any", false, false, false, 431), "html", null, true));
yield "
</div>
<div class=\"review-actions\">
<button class=\"helpful-btn\" onclick=\"markAsHelpful(";
// line 435
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, $context["review"], "id", [], "any", false, false, false, 435), "html", null, true);
yield ")\">
<i class=\"lnr lnr-thumbs-up\"></i> Utile (";
// line 436
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, $context["review"], "helpfulCount", [], "any", false, false, false, 436), "html", null, true);
yield ")
</button>
<button class=\"helpful-btn\" onclick=\"markAsNotHelpful(";
// line 438
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, $context["review"], "id", [], "any", false, false, false, 438), "html", null, true);
yield ")\">
<i class=\"lnr lnr-thumbs-down\"></i> Pas utile (";
// line 439
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env, $this->source, $context["review"], "notHelpfulCount", [], "any", false, false, false, 439), "html", null, true);
yield ")
</button>
";
// line 442
if ((CoreExtension::getAttribute($this->env, $this->source, $context["review"], "user", [], "any", false, false, false, 442) == CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "user", [], "any", false, false, false, 442))) {
// line 443
yield " <div class=\"ms-auto\">
<a href=\"";
// line 444
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("shop_reviews_edit", ["slug" => CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "slug", [], "any", false, false, false, 444), "id" => CoreExtension::getAttribute($this->env, $this->source, $context["review"], "id", [], "any", false, false, false, 444)]), "html", null, true);
yield "\" class=\"btn btn-sm btn-outline-primary\">
<i class=\"lnr lnr-pencil\"></i> Modifier
</a>
<form method=\"post\" action=\"";
// line 447
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("shop_reviews_delete", ["slug" => CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "slug", [], "any", false, false, false, 447), "id" => CoreExtension::getAttribute($this->env, $this->source, $context["review"], "id", [], "any", false, false, false, 447)]), "html", null, true);
yield "\" class=\"d-inline\" onsubmit=\"return confirm('Supprimer cet avis ?')\">
<input type=\"hidden\" name=\"_token\" value=\"";
// line 448
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getRuntime('Symfony\Component\Form\FormRenderer')->renderCsrfToken(("delete" . CoreExtension::getAttribute($this->env, $this->source, $context["review"], "id", [], "any", false, false, false, 448))), "html", null, true);
yield "\">
<button type=\"submit\" class=\"btn btn-sm btn-outline-danger\">
<i class=\"lnr lnr-trash\"></i> Supprimer
</button>
</form>
</div>
";
}
// line 455
yield " </div>
</div>
";
}
$_parent = $context['_parent'];
unset($context['_seq'], $context['_key'], $context['review'], $context['_parent']);
$context = array_intersect_key($context, $_parent) + $_parent;
// line 458
yield " </div>
<!-- Pagination -->
";
// line 461
if ((CoreExtension::getAttribute($this->env, $this->source, ($context["pagination"] ?? null), "pages", [], "any", false, false, false, 461) > 1)) {
// line 462
yield " <div class=\"pagination-wrapper\">
<nav>
<ul class=\"pagination\">
";
// line 465
if ((CoreExtension::getAttribute($this->env, $this->source, ($context["pagination"] ?? null), "page", [], "any", false, false, false, 465) > 1)) {
// line 466
yield " <li class=\"page-item\">
<a class=\"page-link\" href=\"";
// line 467
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("shop_reviews_index", ["slug" => CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "slug", [], "any", false, false, false, 467), "page" => (CoreExtension::getAttribute($this->env, $this->source, ($context["pagination"] ?? null), "page", [], "any", false, false, false, 467) - 1)]), "html", null, true);
yield "\">Précédent</a>
</li>
";
}
// line 470
yield "
";
// line 471
$context['_parent'] = $context;
$context['_seq'] = CoreExtension::ensureTraversable(range(1, CoreExtension::getAttribute($this->env, $this->source, ($context["pagination"] ?? null), "pages", [], "any", false, false, false, 471)));
foreach ($context['_seq'] as $context["_key"] => $context["page"]) {
// line 472
yield " ";
if (($context["page"] == CoreExtension::getAttribute($this->env, $this->source, ($context["pagination"] ?? null), "page", [], "any", false, false, false, 472))) {
// line 473
yield " <li class=\"page-item active\">
<span class=\"page-link\">";
// line 474
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["page"], "html", null, true);
yield "</span>
</li>
";
} else {
// line 477
yield " <li class=\"page-item\">
<a class=\"page-link\" href=\"";
// line 478
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("shop_reviews_index", ["slug" => CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "slug", [], "any", false, false, false, 478), "page" => $context["page"]]), "html", null, true);
yield "\">";
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["page"], "html", null, true);
yield "</a>
</li>
";
}
// line 481
yield " ";
}
$_parent = $context['_parent'];
unset($context['_seq'], $context['_key'], $context['page'], $context['_parent']);
$context = array_intersect_key($context, $_parent) + $_parent;
// line 482
yield "
";
// line 483
if ((CoreExtension::getAttribute($this->env, $this->source, ($context["pagination"] ?? null), "page", [], "any", false, false, false, 483) < CoreExtension::getAttribute($this->env, $this->source, ($context["pagination"] ?? null), "pages", [], "any", false, false, false, 483))) {
// line 484
yield " <li class=\"page-item\">
<a class=\"page-link\" href=\"";
// line 485
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("shop_reviews_index", ["slug" => CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "slug", [], "any", false, false, false, 485), "page" => (CoreExtension::getAttribute($this->env, $this->source, ($context["pagination"] ?? null), "page", [], "any", false, false, false, 485) + 1)]), "html", null, true);
yield "\">Suivant</a>
</li>
";
}
// line 488
yield " </ul>
</nav>
</div>
";
}
// line 492
yield " ";
} else {
// line 493
yield " <div class=\"empty-reviews\">
<i class=\"lnr lnr-star\"></i>
<h3>Aucun avis pour le moment</h3>
<p>Soyez le premier à laisser un avis sur cette boutique !</p>
";
// line 497
if ((($tmp = ($context["canReview"] ?? null)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 498
yield " <a href=\"";
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("shop_reviews_new", ["slug" => CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "slug", [], "any", false, false, false, 498)]), "html", null, true);
yield "\" class=\"btn-review\">
<i class=\"lnr lnr-star\"></i> Laisser un avis
</a>
";
}
// line 502
yield " </div>
";
}
// line 504
yield " </div>
</div>
</div>
</section>
</div>
";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 511
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_javascripts(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascripts"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascripts"));
// line 512
yield " ";
yield from $this->yieldParentBlock("javascripts", $context, $blocks);
yield "
<script>
// Scoper toutes les fonctions dans le contexte de la page reviews pour éviter les conflits
(function() {
'use strict';
function applyFilters() {
const ratingBtn = document.querySelector('.shop-reviews-page .rating-btn.active');
if (!ratingBtn) return;
const rating = ratingBtn.dataset.rating;
const verified = document.getElementById('verified-filter')?.checked || false;
const search = document.getElementById('search-filter')?.value || '';
const params = new URLSearchParams();
if (rating) params.append('rating', rating);
if (verified) params.append('verified', '1');
if (search) params.append('search', search);
window.location.href = '";
// line 531
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("shop_reviews_index", ["slug" => CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "slug", [], "any", false, false, false, 531)]), "html", null, true);
yield "?' + params.toString();
}
function markAsHelpful(reviewId) {
fetch('";
// line 535
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("shop_reviews_helpful", ["slug" => CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "slug", [], "any", false, false, false, 535), "id" => "REVIEW_ID"]), "html", null, true);
yield "'.replace('REVIEW_ID', reviewId), {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert(data.message || 'Une erreur est survenue');
}
})
.catch(error => {
console.error('Erreur:', error);
alert('Une erreur est survenue lors du vote');
});
}
function markAsNotHelpful(reviewId) {
fetch('";
// line 556
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("shop_reviews_not_helpful", ["slug" => CoreExtension::getAttribute($this->env, $this->source, ($context["shop"] ?? null), "slug", [], "any", false, false, false, 556), "id" => "REVIEW_ID"]), "html", null, true);
yield "'.replace('REVIEW_ID', reviewId), {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert(data.message || 'Une erreur est survenue');
}
})
.catch(error => {
console.error('Erreur:', error);
alert('Une erreur est survenue lors du vote');
});
}
// Exposer les fonctions globalement pour les boutons onclick
window.applyFilters = applyFilters;
window.markAsHelpful = markAsHelpful;
window.markAsNotHelpful = markAsNotHelpful;
// Gestion des boutons de filtre par note - scoped à la page reviews
document.addEventListener('DOMContentLoaded', function() {
const reviewPage = document.querySelector('.shop-reviews-page');
if (!reviewPage) return;
reviewPage.querySelectorAll('.rating-btn').forEach(btn => {
btn.addEventListener('click', function() {
reviewPage.querySelectorAll('.rating-btn').forEach(b => b.classList.remove('active'));
this.classList.add('active');
});
});
});
})();
</script>
";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
/**
* @codeCoverageIgnore
*/
public function getTemplateName(): string
{
return "shop/reviews/index.html.twig";
}
/**
* @codeCoverageIgnore
*/
public function isTraitable(): bool
{
return false;
}
/**
* @codeCoverageIgnore
*/
public function getDebugInfo(): array
{
return array ( 914 => 556, 890 => 535, 883 => 531, 860 => 512, 847 => 511, 831 => 504, 827 => 502, 819 => 498, 817 => 497, 811 => 493, 808 => 492, 802 => 488, 796 => 485, 793 => 484, 791 => 483, 788 => 482, 782 => 481, 774 => 478, 771 => 477, 765 => 474, 762 => 473, 759 => 472, 755 => 471, 752 => 470, 746 => 467, 743 => 466, 741 => 465, 736 => 462, 734 => 461, 729 => 458, 721 => 455, 711 => 448, 707 => 447, 701 => 444, 698 => 443, 696 => 442, 690 => 439, 686 => 438, 681 => 436, 677 => 435, 670 => 431, 666 => 429, 660 => 427, 658 => 426, 653 => 423, 649 => 421, 647 => 420, 643 => 419, 636 => 415, 632 => 414, 626 => 411, 620 => 407, 616 => 406, 613 => 405, 611 => 404, 605 => 400, 597 => 395, 594 => 394, 592 => 393, 581 => 385, 571 => 378, 564 => 373, 555 => 370, 548 => 369, 544 => 368, 538 => 365, 520 => 350, 513 => 346, 506 => 342, 499 => 338, 493 => 334, 484 => 331, 479 => 329, 474 => 327, 471 => 326, 468 => 325, 465 => 324, 462 => 323, 457 => 322, 455 => 315, 449 => 312, 445 => 311, 424 => 295, 420 => 294, 415 => 292, 407 => 286, 394 => 285, 104 => 6, 91 => 5, 66 => 3, 43 => 1,);
}
public function getSourceContext(): Source
{
return new Source("{% extends 'base_home.html.twig' %}
{% block title %}Avis - {{ shop.name }} | MaketOu{% endblock %}
{% block stylesheets %}
{{ parent() }}
<style>
/* Styles spécifiques aux reviews - tous scoped pour éviter les conflits avec le template de base */
.shop-reviews-page .review-card {
border: 1px solid #e0e0e0;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
background: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.shop-reviews-page .review-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.shop-reviews-page .review-user {
display: flex;
align-items: center;
}
.shop-reviews-page .review-user-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background: linear-gradient(45deg, #667eea, #764ba2);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
margin-right: 12px;
}
.shop-reviews-page .review-user-info h6 {
margin: 0;
font-weight: 600;
color: #333;
}
.shop-reviews-page .review-user-info small {
color: #666;
}
.shop-reviews-page .review-rating {
display: flex;
align-items: center;
gap: 5px;
}
.shop-reviews-page .stars {
color: #ffc107;
font-size: 18px;
}
.shop-reviews-page .review-date {
color: #666;
font-size: 14px;
}
.shop-reviews-page .review-content {
margin-bottom: 15px;
line-height: 1.6;
color: #333;
}
.shop-reviews-page .review-type {
display: inline-block;
background: #f8f9fa;
color: #495057;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
margin-bottom: 10px;
}
.shop-reviews-page .review-actions {
display: flex;
gap: 10px;
align-items: center;
}
.shop-reviews-page .helpful-btn {
background: none;
border: 1px solid #dee2e6;
padding: 5px 10px;
border-radius: 4px;
font-size: 12px;
color: #6c757d;
cursor: pointer;
transition: all 0.3s ease;
}
.shop-reviews-page .helpful-btn:hover {
background: #f8f9fa;
border-color: #adb5bd;
}
.shop-reviews-page .helpful-btn.active {
background: #28a745;
color: white;
border-color: #28a745;
}
.shop-reviews-page .stats-card {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.shop-reviews-page .stats-header {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.shop-reviews-page .overall-rating {
font-size: 48px;
font-weight: bold;
color: #333;
margin-right: 20px;
}
.shop-reviews-page .rating-breakdown {
flex: 1;
}
.shop-reviews-page .rating-bar {
display: flex;
align-items: center;
margin-bottom: 8px;
}
.shop-reviews-page .rating-label {
width: 60px;
font-size: 14px;
color: #666;
}
.shop-reviews-page .rating-progress {
flex: 1;
height: 8px;
background: #e9ecef;
border-radius: 4px;
margin: 0 10px;
overflow: hidden;
}
.shop-reviews-page .rating-fill {
height: 100%;
background: linear-gradient(45deg, #ffc107, #ff8c00);
transition: width 0.3s ease;
}
.shop-reviews-page .rating-count {
width: 40px;
text-align: right;
font-size: 14px;
color: #666;
}
.shop-reviews-page .filters-card {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.shop-reviews-page .filter-group {
margin-bottom: 15px;
}
.shop-reviews-page .filter-group label {
font-weight: 600;
margin-bottom: 5px;
display: block;
}
.shop-reviews-page .rating-filter {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.shop-reviews-page .rating-btn {
padding: 8px 12px;
border: 1px solid #dee2e6;
background: white;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
font-size: 14px;
}
.shop-reviews-page .rating-btn:hover {
background: #f8f9fa;
}
.shop-reviews-page .rating-btn.active {
background: #007bff;
color: white;
border-color: #007bff;
}
.shop-reviews-page .verified-badge {
background: #28a745;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
margin-left: 5px;
}
.shop-reviews-page .pagination-wrapper {
display: flex;
justify-content: center;
margin-top: 30px;
}
.shop-reviews-page .btn-review {
background: linear-gradient(45deg, #667eea, #764ba2);
border: none;
color: white;
padding: 12px 24px;
border-radius: 6px;
font-weight: 600;
text-decoration: none;
display: inline-block;
transition: all 0.3s ease;
}
.shop-reviews-page .btn-review:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
color: white;
}
.shop-reviews-page .empty-reviews {
text-align: center;
padding: 60px 20px;
color: #666;
}
.shop-reviews-page .empty-reviews i {
font-size: 64px;
color: #ddd;
margin-bottom: 20px;
}
@media (max-width: 768px) {
.shop-reviews-page .review-header {
flex-direction: column;
align-items: flex-start;
}
.shop-reviews-page .stats-header {
flex-direction: column;
text-align: center;
}
.shop-reviews-page .overall-rating {
margin-right: 0;
margin-bottom: 15px;
}
.shop-reviews-page .rating-filter {
justify-content: center;
}
}
</style>
{% endblock %}
{% block body %}
<div class=\"shop-reviews-page\">
<!-- Breadcrumb -->
<section class=\"banner-area organic-breadcrumb\">
<div class=\"container\">
<div class=\"breadcrumb-banner d-flex flex-wrap align-items-center justify-content-end\">
<div class=\"col-first\">
<h1>Avis - {{ shop.name }}</h1>
<nav class=\"d-flex align-items-center\">
<a href=\"{{ path('ui_home') }}\">Accueil<span class=\"lnr lnr-arrow-right\"></span></a>
<a href=\"{{ path('ui_shop_show', {'slug': shop.slug}) }}\">{{ shop.name }}<span class=\"lnr lnr-arrow-right\"></span></a>
<a href=\"javascript:void(0)\">Avis</a>
</nav>
</div>
</div>
</div>
</section>
<section class=\"blog_area\">
<div class=\"container my-5\">
<div class=\"row\">
<!-- Statistiques des avis -->
<div class=\"col-12\">
<div class=\"stats-card\">
<div class=\"stats-header\">
<div class=\"overall-rating\">
{{ stats.averageRating|number_format(1) }}
<div class=\"stars\">{{ stats.averageRating|rating_stars }}</div>
</div>
<div class=\"rating-breakdown\">
{% set ratingMap = {
5: 'fiveStars',
4: 'fourStars',
3: 'threeStars',
2: 'twoStars',
1: 'oneStar'
} %}
{% for rating in 5..1 %}
{% set ratingKey = ratingMap[rating] %}
{% set ratingCount = attribute(stats, ratingKey)|default(0) %}
{% set percentage = stats.totalReviews > 0 ? (ratingCount / stats.totalReviews * 100) : 0 %}
<div class=\"rating-bar\">
<span class=\"rating-label\">{{ rating }} étoiles</span>
<div class=\"rating-progress\">
<div class=\"rating-fill\" style=\"width: {{ percentage }}%\"></div>
</div>
<span class=\"rating-count\">{{ ratingCount }}</span>
</div>
{% endfor %}
</div>
</div>
<div class=\"row text-center\">
<div class=\"col-md-3\">
<h4>{{ stats.totalReviews }}</h4>
<p class=\"text-muted mb-0\">Avis total</p>
</div>
<div class=\"col-md-3\">
<h4>{{ stats.positivePercentage }}%</h4>
<p class=\"text-muted mb-0\">Positifs</p>
</div>
<div class=\"col-md-3\">
<h4>{{ stats.verifiedReviews }}</h4>
<p class=\"text-muted mb-0\">Vérifiés</p>
</div>
<div class=\"col-md-3\">
<h4>{{ shop.followersCount|default(0) }}</h4>
<p class=\"text-muted mb-0\">Followers</p>
</div>
</div>
</div>
</div>
<!-- Filtres -->
<div class=\"col-md-3\">
<div class=\"filters-card\">
<h5 class=\"mb-3\">Filtrer les avis</h5>
<div class=\"filter-group\">
<label>Note</label>
<div class=\"rating-filter\">
<button class=\"rating-btn {{ filters.rating == '' ? 'active' : '' }}\" data-rating=\"\">
Toutes
</button>
{% for rating in 5..1 %}
<button class=\"rating-btn {{ filters.rating == rating ? 'active' : '' }}\" data-rating=\"{{ rating }}\">
{{ rating }}★
</button>
{% endfor %}
</div>
</div>
<div class=\"filter-group\">
<label>
<input type=\"checkbox\" {{ filters.verified ? 'checked' : '' }} id=\"verified-filter\">
Avis vérifiés uniquement
</label>
</div>
<div class=\"filter-group\">
<label>Rechercher</label>
<input type=\"text\" class=\"form-control\" id=\"search-filter\" placeholder=\"Rechercher dans les avis...\" value=\"{{ filters.search }}\">
</div>
<button class=\"btn btn-primary w-100\" onclick=\"applyFilters()\">
Appliquer les filtres
</button>
</div>
{% if canReview %}
<div class=\"text-center mt-3\">
<a href=\"{{ path('shop_reviews_new', {'slug': shop.slug}) }}\" class=\"btn-review\">
<i class=\"lnr lnr-star\"></i> Laisser un avis
</a>
</div>
{% endif %}
</div>
<!-- Liste des avis -->
<div class=\"col-md-9\">
{% if reviews|length > 0 %}
<div id=\"reviews-container\">
{% for review in reviews %}
<div class=\"review-card\">
<div class=\"review-header\">
<div class=\"review-user\">
<div class=\"review-user-avatar\">
{{ review.user.firstName|first|upper|default(review.user.email|first|upper) }}
</div>
<div class=\"review-user-info\">
<h6>{{ review.user.firstName|default('Utilisateur') }}</h6>
<small>{{ review.getTimeAgo() }}</small>
</div>
</div>
<div class=\"review-rating\">
<div class=\"stars\">{{ review.getRatingStars() }}</div>
{% if review.isVerified %}
<span class=\"verified-badge\">✓ Vérifié</span>
{% endif %}
</div>
</div>
{% if review.reviewType %}
<div class=\"review-type\">{{ review.getReviewTypeLabel() }}</div>
{% endif %}
<div class=\"review-content\">
{{ review.comment|nl2br }}
</div>
<div class=\"review-actions\">
<button class=\"helpful-btn\" onclick=\"markAsHelpful({{ review.id }})\">
<i class=\"lnr lnr-thumbs-up\"></i> Utile ({{ review.helpfulCount }})
</button>
<button class=\"helpful-btn\" onclick=\"markAsNotHelpful({{ review.id }})\">
<i class=\"lnr lnr-thumbs-down\"></i> Pas utile ({{ review.notHelpfulCount }})
</button>
{% if review.user == app.user %}
<div class=\"ms-auto\">
<a href=\"{{ path('shop_reviews_edit', {'slug': shop.slug, 'id': review.id}) }}\" class=\"btn btn-sm btn-outline-primary\">
<i class=\"lnr lnr-pencil\"></i> Modifier
</a>
<form method=\"post\" action=\"{{ path('shop_reviews_delete', {'slug': shop.slug, 'id': review.id}) }}\" class=\"d-inline\" onsubmit=\"return confirm('Supprimer cet avis ?')\">
<input type=\"hidden\" name=\"_token\" value=\"{{ csrf_token('delete' ~ review.id) }}\">
<button type=\"submit\" class=\"btn btn-sm btn-outline-danger\">
<i class=\"lnr lnr-trash\"></i> Supprimer
</button>
</form>
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
<!-- Pagination -->
{% if pagination.pages > 1 %}
<div class=\"pagination-wrapper\">
<nav>
<ul class=\"pagination\">
{% if pagination.page > 1 %}
<li class=\"page-item\">
<a class=\"page-link\" href=\"{{ path('shop_reviews_index', {'slug': shop.slug, 'page': pagination.page - 1}) }}\">Précédent</a>
</li>
{% endif %}
{% for page in 1..pagination.pages %}
{% if page == pagination.page %}
<li class=\"page-item active\">
<span class=\"page-link\">{{ page }}</span>
</li>
{% else %}
<li class=\"page-item\">
<a class=\"page-link\" href=\"{{ path('shop_reviews_index', {'slug': shop.slug, 'page': page}) }}\">{{ page }}</a>
</li>
{% endif %}
{% endfor %}
{% if pagination.page < pagination.pages %}
<li class=\"page-item\">
<a class=\"page-link\" href=\"{{ path('shop_reviews_index', {'slug': shop.slug, 'page': pagination.page + 1}) }}\">Suivant</a>
</li>
{% endif %}
</ul>
</nav>
</div>
{% endif %}
{% else %}
<div class=\"empty-reviews\">
<i class=\"lnr lnr-star\"></i>
<h3>Aucun avis pour le moment</h3>
<p>Soyez le premier à laisser un avis sur cette boutique !</p>
{% if canReview %}
<a href=\"{{ path('shop_reviews_new', {'slug': shop.slug}) }}\" class=\"btn-review\">
<i class=\"lnr lnr-star\"></i> Laisser un avis
</a>
{% endif %}
</div>
{% endif %}
</div>
</div>
</div>
</section>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script>
// Scoper toutes les fonctions dans le contexte de la page reviews pour éviter les conflits
(function() {
'use strict';
function applyFilters() {
const ratingBtn = document.querySelector('.shop-reviews-page .rating-btn.active');
if (!ratingBtn) return;
const rating = ratingBtn.dataset.rating;
const verified = document.getElementById('verified-filter')?.checked || false;
const search = document.getElementById('search-filter')?.value || '';
const params = new URLSearchParams();
if (rating) params.append('rating', rating);
if (verified) params.append('verified', '1');
if (search) params.append('search', search);
window.location.href = '{{ path(\"shop_reviews_index\", {\"slug\": shop.slug}) }}?' + params.toString();
}
function markAsHelpful(reviewId) {
fetch('{{ path(\"shop_reviews_helpful\", {\"slug\": shop.slug, \"id\": \"REVIEW_ID\"}) }}'.replace('REVIEW_ID', reviewId), {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert(data.message || 'Une erreur est survenue');
}
})
.catch(error => {
console.error('Erreur:', error);
alert('Une erreur est survenue lors du vote');
});
}
function markAsNotHelpful(reviewId) {
fetch('{{ path(\"shop_reviews_not_helpful\", {\"slug\": shop.slug, \"id\": \"REVIEW_ID\"}) }}'.replace('REVIEW_ID', reviewId), {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert(data.message || 'Une erreur est survenue');
}
})
.catch(error => {
console.error('Erreur:', error);
alert('Une erreur est survenue lors du vote');
});
}
// Exposer les fonctions globalement pour les boutons onclick
window.applyFilters = applyFilters;
window.markAsHelpful = markAsHelpful;
window.markAsNotHelpful = markAsNotHelpful;
// Gestion des boutons de filtre par note - scoped à la page reviews
document.addEventListener('DOMContentLoaded', function() {
const reviewPage = document.querySelector('.shop-reviews-page');
if (!reviewPage) return;
reviewPage.querySelectorAll('.rating-btn').forEach(btn => {
btn.addEventListener('click', function() {
reviewPage.querySelectorAll('.rating-btn').forEach(b => b.classList.remove('active'));
this.classList.add('active');
});
});
});
})();
</script>
{% endblock %}
", "shop/reviews/index.html.twig", "/home/u540977899/domains/maketou-ht.com/public_html/templates/shop/reviews/index.html.twig");
}
}