{% extends getThemeDir('base.html.twig') %}
{% block seo %}
{{ render_seo('product', product, app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) }}
{% endblock %}
{% block body %}
<main class="container">
<nav class="flex mt-8" aria-label="Breadcrumb">
<ol class="inline-flex items-center space-x-1 md:space-x-2 rtl:space-x-reverse">
<li class="inline-flex items-center">
<a href="{{ path('app_shop_site_index') }}"
class="inline-flex items-center text-sm gap-x-1 text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
<svg class="size-4 mb-0.5">
<use href="#home"/>
</svg>
صفحه اصلی
</a>
</li>
<li class="inline-flex items-center">
<svg class="rtl:rotate-180 w-3 h-3 text-gray-400 mx-1" aria-hidden="true"
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 6 10">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="m1 9 4-4-4-4"/>
</svg>
<a href="{{ path('app_shop_site_products') }}"
class="inline-flex items-center text-sm gap-x-1 text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
فروشگاه
</a>
</li>
<li aria-current="page">
<div class="flex items-center">
<svg class="rtl:rotate-180 w-3 h-3 text-gray-400 mx-1" aria-hidden="true"
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 6 10">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="m1 9 4-4-4-4"/>
</svg>
<span class="ms-1 text-sm text-gray-500 md:ms-2 dark:text-gray-400">
{{ product.name }}
</span>
</div>
</li>
</ol>
</nav>
{{ form_start(addToCart , {'attr' : {'id' :"product-variant"}}) }}
<section
class="mt-5 flex flex-col lg:flex-row items-start gap-4 child:rounded-lg child:bg-white child:dark:bg-gray-800 child:shadow child:p-4">
<div class="w-full lg:w-3/4">
<div class="flex flex-col md:flex-row justify-start gap-x-8 xl:gap-x-2 items-start">
<div class="w-2/4 hidden md:flex flex-col justify-center items-center gap-y-4">
{% if product.productImages[0] is defined and product.productImages[0] is not null %}
<span class="open-sliderModal">
<img src="{{ product.productImages[0].imageUrl }}" class="cursor-pointer object-cover"
alt="">
</span>
{% endif %}
<div class="grid grid-cols-12 child:col-span-3 child:app-border gap-x-4 child:size-16 child:rounded-lg child:cursor-pointer">
{% for key,image in product.productImages %}
{% if key < 3 %}
<div class="p-1 open-sliderModal">
<img src="{{ image.imageUrl }}" class="object-cover rounded-lg">
</div>
{% endif %}
{% endfor %}
{% if product.productImages[4] is defined and product.productImages[4] is not null %}
<div class="overflow-hidden relative open-sliderModal">
<svg class="absolute size-8 text-gray-100 top-4 left-4 z-10">
<use href="#ellipsis"></use>
</svg>
<img src="{{ product.productImages[4].imageUrl }}"
class="object-cover rounded-lg blur-sm">
</div>
{% endif %}
</div>
</div>
<div class="slider-modal">
<div class="flex w-full h-fit items-center justify-between">
<h1 class="font-DanaMedium text-lg">
تصاویر {{ product.name }}
</h1>
<svg class="size-6 cursor-pointer close-sliderModal">
<use href="#x-mark"></use>
</svg>
</div>
<div class="swiper ProductDetailsSlider mt-14 px-10 w-96 relative">
<div class="swiper-wrapper w-[50%] child:w-full child:rounded-lg child:overflow-hidden">
{% for key,image in product.productImages %}
{% if key < 3 %}
<div class="swiper-slide">
<img src="{{ image.imageUrl }}" alt="{{ product.name }}">
</div>
{% endif %}
{% endfor %}
</div>
</div>
<button class="slider-navigate_btn absolute right-40 top-[17rem] border dark:border-gray-700 border-gray-200 button-prev-ProductDetailsSlider z-20">
<svg class="size-6 -rotate-90">
<use href="#chevron"/>
</svg>
</button>
<button
class="slider-navigate_btn absolute left-40 top-[17rem] border dark:border-gray-700 border-gray-200 button-next-ProductDetailsSlider z-10">
<svg class="size-6 rotate-90">
<use href="#chevron"/>
</svg>
</button>
</div>
<div class="w-full md:w-3/4 flex flex-col gap-y-7">
<div class="flex items-center justify-between">
{% if product.productCategories[0] is defined %}
<a href="{{ path('app_shop_site_product_category' , {'urlSlug' : product.productCategories[0].urlSlug}) }}"
class="font-DanaMedium text-sky-400">{{ product.productCategories[0].name }}</a>
{% endif %}
</div>
<div class="flex md:hidden">
<div class="swiper MobileProductSlider w-full">
<div class="swiper-wrapper w-full child:w-full child:overflow-hidden child:rounded-lg">
{% for key,image in product.productImages %}
<div class="swiper-slide">
<img src="{{ image.imageUrl }}" alt="{{ product.name }}">
</div>
{% endfor %}
</div>
<div class="swiper-pagination MobileProductSlider-pagination"></div>
</div>
</div>
<div class="flex flex-col gap-y-3">
<p class="text-lg font-DanaDemiBold dark:text-gray-300">
{{ product.name }}
</p>
<div class="flex items-center gap-x-2">
<span class="h-6 bg-slate-100 text-gray-400 dark:bg-slate-700 dark:text-gray-400 flex items-center justify-center rounded-full px-2 text-xs font-DanaMedium pt-1">
{{ product.productReviews|length }} دیدگاه
</span>
</div>
</div>
<div class="flex flex-col gap-y-4">
{% set skip = ['quantity', '_token', 'product_price_id'] %}
{% for key, field in addToCart.children %}
{% if key not in skip %}
{{ form_row(field, {
row_attr: { class: 'mb-4 variant-selector' },
label_attr: { class: 'block text-sm text-gray-700 dark:text-gray-200 mb-1' },
attr: { class: 'block w-full rounded-md border border-gray-300 bg-white dark:bg-gray-900 dark:text-gray-100 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-300 focus:border-blue-500' },
help_attr: { class: 'text-xs text-gray-500 mt-1' }
}) }}
{% else %}
{{ form_row(field, {
row_attr: { class: 'mb-4' },
label_attr: { class: 'block text-sm text-gray-700 dark:text-gray-200 mb-1' },
attr: { class: 'block w-full py-1.5 px-3 text-base outline dark:outline-none outline-1 -outline-offset-1 placeholder:text-gray-400 transition-all col-span-6
text-gray-800 dark:text-gray-100 dark:bg-gray-900 bg-slate-100 border border-transparent hover:border-slate-200 appearance-none rounded-md outline-none focus:bg-white focus:border-indigo-400 focus:ring-2 focus:ring-indigo-100 dark:focus:ring-blue-400 h-11' },
help_attr: { class: 'text-xs text-gray-500 mt-1' }
}) }}
{% endif %}
{% endfor %}
{# {{ form_rest(addToCart) }} #}
</div>
</div>
</div>
<div class="mt-10 lg:mr-2 grid grid-cols-12 child:col-span-6 xl:child:col-span-3 gap-x-1 gap-y-2 lg:gap-4 child:border child:text-gray-400 child:dark:border-white/20 child:border-gray-200 child:rounded-lg child:h-12 child:p-2 child:flex child:items-center child:gap-x-1 lg:child:gap-x-2 child:text-sm lg:text-base">
<span>
<svg class="w-4 h-4 lg:w-6 lg:h-6">
<use href="#arrow-path-rounded-square"></use>
</svg>
<p>ضمانت بازگشت کالا</p>
</span>
<span>
<svg class="w-4 h-4 lg:w-6 lg:h-6">
<use href="#check-badge"></use>
</svg>
<p>
تضمین اصالت کالا
</p>
</span>
<span>
<svg class="w-4 h-4 lg:w-6 lg:h-6">
<use href="#calender-day"></use>
</svg>
<p>پشتیبانی کل هفته</p>
</span>
<span>
<svg class="w-4 h-4 lg:w-6 lg:h-6">
<use href="#truke"></use>
</svg>
<p>ارسال به سراسر ایران </p>
</span>
</div>
</div>
<div class="w-full lg:w-1/4 lg:sticky top-5 flex flex-col gap-y-6">
<div class="flex items-center gap-x-1">
<p class="text-2xl font-DanaDemiBold"
id="product-price">
{{ product.displayPrice|number_format }}
تومان
</p>
</div>
{% if product.isSelling %}
{% if getSellingType(product) == 'advanced' %}
<button type="submit" id="buy-btnl"
disabled
class="w-full btn-add-to-cart-txt flex items-center gap-x-1 justify-center bg-blue-500 text-white hover:bg-blue-600 transition-all rounded-lg shadow py-2">
افزودن به سبد
</button>
{% else %}
<button type="submit" id="buy-btnl"
class="w-full btn-add-to-cart-txt flex items-center gap-x-1 justify-center bg-blue-500 text-white hover:bg-blue-600 transition-all rounded-lg shadow py-2">
افزودن به سبد
</button>
{% endif %}
{% else %}
<button disabled
class="w-full btn-add-to-cart-txt flex items-center gap-x-1 justify-center bg-blue-500 text-white hover:bg-blue-600 transition-all rounded-lg shadow py-2">
افزودن به سبد
</button>
{% endif %}
</div>
</section>
{{ form_end(addToCart, { render_rest: false }) }}
{% set products1 = getProducts() %}
{% include getThemeDir('modules/product-bar.html.twig') with {'title' : 'محصولات مرتبط' ,
subtitle: "جدیدترین و بروزترین محصولات",
products:products1,
container:0
} %}
<section class="relative mt-10 flex flex-col items-start gap-4 rounded-lg bg-white dark:bg-gray-800 shadow p-4">
<div class="w-full py-3 flex items-center gap-x-6 child:font-DanaMedium tab-buttons z-10 border-b border-gray-600/20 dark:border-b-gray-200/20">
<button class="tab-btn text-blue-500" data-target="tab1">معرفی محصول</button>
<button class="tab-btn text-gray-500 dark:text-gray-300" data-target="tab3">دیدگاهها</button>
</div>
<div class="tab-content tab1 block">
<h2 class="font-DanaDemiBold border-b-2 border-blue-500 w-fit p-1 text-lg mb-3">معرفی</h2>
{# <p class="mt-4 leading-8"> #}
<div class="justify-content" style="text-align: justify">
{{ product.description|raw }}
</div>
{# </p> #}
</div>
<div class="tab-content tab3 hidden w-full">
<div class="flex items-center gap-x-2 mb-6">
<h2 class="font-DanaMedium text-2xl ">
دیدگاه ها
</h2>
<p class="text-sm text-blue-500">
({{ product.productReviews|length }} دیدگاه)
</p>
</div>
<div class="w-full flex flex-col md:flex-row items-start gap-10">
<div class="lg:w-1/4 flex flex-col w-full ">
<p class="font-DanaMedium text-lg mb-2">ثبت دیدگاه</p>
{% if app.user %}
{{ form_start(reviewForm , {'attr' : {'class' : 'pt-0'}}) }}
{{ form_widget(reviewForm.content, {'attr': {'class': 'h-24 tailwind-input', 'rows': 5}}) }}
{{ form_errors(reviewForm.content) }}
{{ form_row(reviewForm.recommend, {
row_attr: { class: 'mb-4 variant-selector' },
label_attr: { class: 'block text-sm text-gray-700 dark:text-gray-200 mb-1' },
attr: { class: 'block w-full rounded-md border border-gray-300 bg-white dark:bg-gray-900 dark:text-gray-100 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-300 focus:border-blue-500' },
help_attr: { class: 'text-xs text-gray-500 mt-1' }
}) }}
{{ form_errors(reviewForm.recommend) }}
{{ form_row(reviewForm.rating, {
row_attr: { class: 'mb-4 variant-selector' },
label_attr: { class: 'block text-sm text-gray-700 dark:text-gray-200 mb-1' },
attr: { class: 'block w-full rounded-md border border-gray-300 bg-white dark:bg-gray-900 dark:text-gray-100 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-300 focus:border-blue-500' },
help_attr: { class: 'text-xs text-gray-500 mt-1' }
}) }}
<button type="submit"
class="w-100 group shadow-xl text-sm md:text-base flex gap-x-1.5 items-center px-2 h-10 md:px-3 text-white bg-blue-600 rounded-xl">
ثبت نظر
</button>
{{ form_end(reviewForm) }}
{% else %}
<p>برای ثبت نظر، لازم است ابتدا وارد حساب کاربری خود
شوید.
</p>
<a href="{{ path('customer_panel_login') }}">ورود / ثبت نام</a>
{% endif %}
</div>
<ul class="lg:w-3/4 flex flex-col gap-y-2 child:w-full ">
{% for comment in comments %}
<li class="child:flex py-4 border-b border-gray-200 dark:border-b-gray-200/20 child:border-white/20">
<div class="flex-col">
{% if comment.recommend %}
<h2 class="flex items-center gap-x-1 text-green-500 mb-4">
<svg class="w-4 h-4">
<use href="#hand-up"></use>
</svg>
پیشنهاد میشود
</h2>
{% else %}
<h2 class="flex items-center gap-x-1 text-danger mb-4">
<svg class="w-4 h-4">
<use href="#hand-down"></use>
</svg>
پیشنهاد نمیشود
</h2>
{% endif %}
<p class="text-gray-500 dark:text-gray-200 mb-2 line-clamp-2">
{{ comment.content }}
</p>
</div>
<div class="mt-2 lg:mt-0 flex-col lg:flex-row gap-y-2 lg:items-center justify-between">
<div class="flex items-center gap-x-4 text-gray-400 text-sm">
<p>{{ comment.createdAt|persianDate }}</p>
<p> {{ comment.author }}</p>
</div>
</div>
</li>
{% else %}
اولین نفر برای ثبت نظر باشید
{% endfor %}
</ul>
</div>
</div>
</section>
</main>
{% endblock %}
{% block javascripts %}
<script>
function setupDynamicCollection(containerId, addButtonId) {
const container = document.querySelector(`#${containerId} [data-prototype]`);
const addButton = document.getElementById(addButtonId);
let index = container.children.length;
addButton.addEventListener('click', () => {
const prototype = container.dataset.prototype;
const newForm = prototype.replace(/__name__/g, index);
const wrapper = document.createElement('div');
wrapper.classList.add('input-group', 'mb-2');
wrapper.innerHTML = newForm + '<button type="button" class="btn btn-danger remove-item">–</button>';
container.appendChild(wrapper);
index++;
});
container.addEventListener('click', (e) => {
if (e.target.classList.contains('remove-item')) {
e.target.closest('.input-group').remove();
}
});
}
document.addEventListener('DOMContentLoaded', () => {
setupDynamicCollection('pros-container', 'add-pro');
setupDynamicCollection('cons-container', 'add-con');
});
</script>
{% set jss = [
'base-assets/themes/karen/scripts/productDetails.js',
] %}
{% for url in jss %}
<script src="{{ url('app_cdn_path' , {'path' : url})|replaceUrl('http://', 'https://') }}"></script>
{% endfor %}
{# <script>#}
{# $(function () {#}
{# const $root = $('#product-variant');#}
{# const $price = $('#product-price');#}
{# const $buyBtn = $('#buy-btnl');#}
{# const $priceId = $('#add_to_cart_product_price_id');#}
{# let pendingReq = null;#}
{# let debounceTimer = null;#}
{# function collectVariants() {#}
{# const data = {};#}
{# // رادیوهای انتخابشده (فقط داخل گروههای variant)#}
{# $root.find('.variant-selector input[type="radio"]:checked').each(function () {#}
{# data[this.name] = this.value;#}
{# });#}
{# // سلکتها (اگر خالی نباشند)#}
{# $root.find('.variant-selector select').each(function () {#}
{# const v = $(this).val();#}
{# if (v !== '' && v != null) data[this.name] = v;#}
{# });#}
{# return data;#}
{# }#}
{# function updatePrice() {#}
{# const params = collectVariants();#}
{# // لغو درخواست قبلی اگر هنوز بازه#}
{# if (pendingReq && pendingReq.readyState !== 4) {#}
{# pendingReq.abort();#}
{# }#}
{# pendingReq = $.ajax({#}
{# url: '{{ path("app_shop_site_product_price", {"urlSlug": product.urlSlug}) }}',#}
{# type: 'GET',#}
{# dataType: 'json',#}
{# cache: false,#}
{# data: params,#}
{# beforeSend: function () {#}
{# $buyBtn.prop('disabled', true);#}
{# },#}
{# success: function (res) {#}
{# if (res && res.res) {#}
{# $price.text(res.text || '');#}
{# $priceId.val(res.productPriceId || '');#}
{# $buyBtn.prop('disabled', false);#}
{# } else {#}
{# $price.text(res && res.text ? res.text : '');#}
{# $priceId.val('');#}
{# $buyBtn.prop('disabled', true);#}
{# }#}
{# },#}
{# error: function (xhr, status) {#}
{# if (status === 'abort') return; // درخواست قبلی بود#}
{# $buyBtn.prop('disabled', true);#}
{# }#}
{# });#}
{# }#}
{# // هندل تغییر روی رادیو و سلکتها (delegation)#}
{# $(document).on('change', '#product-variant .variant-selector input[type="radio"], #product-variant .variant-selector select', function () {#}
{# clearTimeout(debounceTimer);#}
{# debounceTimer = setTimeout(updatePrice, 150);#}
{# });#}
{# // اجرا روی بارگذاری اولیه (اگر چیزی از قبل انتخاب شده)#}
{# updatePrice();#}
{# });#}
{# </script>#}
<script>
$(document).ready(function () {
$('.variant-selector').change(function () {
var selectedVariants = {};
$('#product-variant .variant-selector input[type="radio"], #product-variant .variant-selector select').each(function () {
selectedVariants[$(this).attr('name')] = $(this).val();
});
$.ajax({
url: '{{ path('app_shop_site_product_price' , {'urlSlug' : product.urlSlug}) }}', // Your endpoint to handle the price update
type: 'GET',
data: selectedVariants, // Send the selected variants as parameters
success: function (response) {
// add Product price id to form hidden
if (response.res) {
$('#buy-btnl').removeAttr('disabled');
$('#product-price').text(response.text);
$('#add_to_cart_product_price_id').val(response.productPriceId);
} else {
$('#buy-btnl').attr('disabled', 'disabled');
$('#product-price').text(response.text);
}
},
error: function () {
// alert('این');
}
});
});
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function () {
document.querySelectorAll('.variant-selector').forEach(function (radio) {
radio.addEventListener('change', function () {
const targetSelector = this.dataset.selectTarget;
const newValue = this.dataset.selectValue;
if (targetSelector && newValue) {
const select = document.querySelector(targetSelector);
if (select) {
select.value = newValue;
select.dispatchEvent(new Event('change')); // ← برای ریاکت شدن با JSهای دیگه
}
}
});
});
});
</script>
{% endblock %}