public/themes/karen/product-single.html.twig line 1

Open in your IDE?
  1. {% extends getThemeDir('base.html.twig') %}
  2. {% block seo %}
  3.     {{ render_seo('product', product, app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) }}
  4. {% endblock %}
  5. {% block body %}
  6.     <main class="container">
  7.         <nav class="flex mt-8" aria-label="Breadcrumb">
  8.             <ol class="inline-flex items-center space-x-1 md:space-x-2 rtl:space-x-reverse">
  9.                 <li class="inline-flex items-center">
  10.                     <a href="{{ path('app_shop_site_index') }}"
  11.                        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">
  12.                         <svg class="size-4 mb-0.5">
  13.                             <use href="#home"/>
  14.                         </svg>
  15.                         صفحه اصلی
  16.                     </a>
  17.                 </li>
  18.                 <li class="inline-flex items-center">
  19.                     <svg class="rtl:rotate-180 w-3 h-3 text-gray-400 mx-1" aria-hidden="true"
  20.                          xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 6 10">
  21.                         <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
  22.                               d="m1 9 4-4-4-4"/>
  23.                     </svg>
  24.                     <a href="{{ path('app_shop_site_products') }}"
  25.                        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">
  26.                         فروشگاه
  27.                     </a>
  28.                 </li>
  29.                 <li aria-current="page">
  30.                     <div class="flex items-center">
  31.                         <svg class="rtl:rotate-180 w-3 h-3 text-gray-400 mx-1" aria-hidden="true"
  32.                              xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 6 10">
  33.                             <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
  34.                                   d="m1 9 4-4-4-4"/>
  35.                         </svg>
  36.                         <span class="ms-1 text-sm  text-gray-500 md:ms-2 dark:text-gray-400">
  37.                         {{ product.name }}
  38.                     </span>
  39.                     </div>
  40.                 </li>
  41.             </ol>
  42.         </nav>
  43.         {{ form_start(addToCart , {'attr' : {'id' :"product-variant"}}) }}
  44.         <section
  45.                 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">
  46.             <div class="w-full lg:w-3/4">
  47.                 <div class="flex flex-col md:flex-row justify-start gap-x-8 xl:gap-x-2 items-start">
  48.                     <div class="w-2/4 hidden md:flex flex-col justify-center items-center gap-y-4">
  49.                         {% if product.productImages[0] is defined and product.productImages[0] is not null %}
  50.                             <span class="open-sliderModal">
  51.                             <img src="{{ product.productImages[0].imageUrl }}" class="cursor-pointer object-cover"
  52.                                  alt="">
  53.                         </span>
  54.                         {% endif %}
  55.                         <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">
  56.                             {% for key,image in product.productImages %}
  57.                                 {% if key < 3 %}
  58.                                     <div class="p-1 open-sliderModal">
  59.                                         <img src="{{ image.imageUrl }}" class="object-cover  rounded-lg">
  60.                                     </div>
  61.                                 {% endif %}
  62.                             {% endfor %}
  63.                             {% if product.productImages[4] is defined and product.productImages[4] is not null %}
  64.                                 <div class="overflow-hidden relative open-sliderModal">
  65.                                     <svg class="absolute size-8 text-gray-100 top-4 left-4 z-10">
  66.                                         <use href="#ellipsis"></use>
  67.                                     </svg>
  68.                                     <img src="{{ product.productImages[4].imageUrl }}"
  69.                                          class="object-cover rounded-lg blur-sm">
  70.                                 </div>
  71.                             {% endif %}
  72.                         </div>
  73.                     </div>
  74.                     <div class="slider-modal">
  75.                         <div class="flex w-full h-fit items-center justify-between">
  76.                             <h1 class="font-DanaMedium text-lg">
  77.                                 تصاویر {{ product.name }}
  78.                             </h1>
  79.                             <svg class="size-6 cursor-pointer close-sliderModal">
  80.                                 <use href="#x-mark"></use>
  81.                             </svg>
  82.                         </div>
  83.                         <div class="swiper ProductDetailsSlider mt-14 px-10 w-96 relative">
  84.                             <div class="swiper-wrapper w-[50%] child:w-full child:rounded-lg child:overflow-hidden">
  85.                                 {% for key,image in product.productImages %}
  86.                                     {% if key < 3 %}
  87.                                         <div class="swiper-slide">
  88.                                             <img src="{{ image.imageUrl }}" alt="{{ product.name }}">
  89.                                         </div>
  90.                                     {% endif %}
  91.                                 {% endfor %}
  92.                             </div>
  93.                         </div>
  94.                         <button class="slider-navigate_btn absolute right-40 top-[17rem] border dark:border-gray-700 border-gray-200 button-prev-ProductDetailsSlider z-20">
  95.                             <svg class="size-6 -rotate-90">
  96.                                 <use href="#chevron"/>
  97.                             </svg>
  98.                         </button>
  99.                         <button
  100.                                 class="slider-navigate_btn absolute left-40 top-[17rem] border dark:border-gray-700 border-gray-200 button-next-ProductDetailsSlider z-10">
  101.                             <svg class="size-6 rotate-90">
  102.                                 <use href="#chevron"/>
  103.                             </svg>
  104.                         </button>
  105.                     </div>
  106.                     <div class="w-full md:w-3/4 flex flex-col gap-y-7">
  107.                         <div class="flex items-center justify-between">
  108.                             {% if product.productCategories[0] is defined %}
  109.                                 <a href="{{ path('app_shop_site_product_category' , {'urlSlug' : product.productCategories[0].urlSlug}) }}"
  110.                                    class="font-DanaMedium text-sky-400">{{ product.productCategories[0].name }}</a>
  111.                             {% endif %}
  112.                         </div>
  113.                         <div class="flex md:hidden">
  114.                             <div class="swiper MobileProductSlider w-full">
  115.                                 <div class="swiper-wrapper w-full child:w-full child:overflow-hidden child:rounded-lg">
  116.                                     {% for key,image in product.productImages %}
  117.                                         <div class="swiper-slide">
  118.                                             <img src="{{ image.imageUrl }}" alt="{{ product.name }}">
  119.                                         </div>
  120.                                     {% endfor %}
  121.                                 </div>
  122.                                 <div class="swiper-pagination MobileProductSlider-pagination"></div>
  123.                             </div>
  124.                         </div>
  125.                         <div class="flex flex-col gap-y-3">
  126.                             <p class="text-lg font-DanaDemiBold dark:text-gray-300">
  127.                                 {{ product.name }}
  128.                             </p>
  129.                             <div class="flex items-center gap-x-2">
  130.                                 <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">
  131.                                 {{ product.productReviews|length }} دیدگاه
  132.                               </span>
  133.                             </div>
  134.                         </div>
  135.                         <div class="flex flex-col gap-y-4">
  136.                             {% set skip = ['quantity', '_token', 'product_price_id'] %}
  137.                             {% for key, field in addToCart.children %}
  138.                                 {% if key not in skip %}
  139.                                         {{ form_row(field, {
  140.                                             row_attr:   { class: 'mb-4 variant-selector' },
  141.                                             label_attr: { class: 'block text-sm text-gray-700 dark:text-gray-200 mb-1' },
  142.                                             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' },
  143.                                             help_attr:  { class: 'text-xs text-gray-500 mt-1' }
  144.                                         }) }}
  145.                                 {% else %}
  146.                                     {{ form_row(field, {
  147.                                         row_attr:   { class: 'mb-4' },
  148.                                         label_attr: { class: 'block text-sm text-gray-700 dark:text-gray-200 mb-1' },
  149.                                         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
  150.                             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' },
  151.                                         help_attr:  { class: 'text-xs text-gray-500 mt-1' }
  152.                                     }) }}
  153.                                 {% endif %}
  154.                             {% endfor %}
  155.                             {#                            {{ form_rest(addToCart) }} #}
  156.                         </div>
  157.                     </div>
  158.                 </div>
  159.                 <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">
  160.                     <span>
  161.                         <svg class="w-4 h-4 lg:w-6 lg:h-6">
  162.                             <use href="#arrow-path-rounded-square"></use>
  163.                         </svg>
  164.                         <p>ضمانت بازگشت کالا</p>
  165.                     </span>
  166.                     <span>
  167.                         <svg class="w-4 h-4 lg:w-6 lg:h-6">
  168.                             <use href="#check-badge"></use>
  169.                         </svg>
  170.                         <p>
  171.                             تضمین اصالت کالا
  172.                         </p>
  173.                     </span>
  174.                     <span>
  175.                         <svg class="w-4 h-4 lg:w-6 lg:h-6">
  176.                             <use href="#calender-day"></use>
  177.                         </svg>
  178.                         <p>پشتیبانی کل هفته</p>
  179.                     </span>
  180.                     <span>
  181.                         <svg class="w-4 h-4 lg:w-6 lg:h-6">
  182.                             <use href="#truke"></use>
  183.                         </svg>
  184.                         <p>ارسال به سراسر ایران </p>
  185.                     </span>
  186.                 </div>
  187.             </div>
  188.             <div class="w-full lg:w-1/4 lg:sticky top-5 flex flex-col gap-y-6">
  189.                 <div class="flex items-center gap-x-1">
  190.                     <p class="text-2xl font-DanaDemiBold"
  191.                        id="product-price">
  192.                         {{ product.displayPrice|number_format }}
  193.                         تومان
  194.                     </p>
  195.                 </div>
  196.                 {% if product.isSelling %}
  197.                     {% if getSellingType(product) == 'advanced' %}
  198.                         <button type="submit" id="buy-btnl"
  199.                                 disabled
  200.                                 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">
  201.                             افزودن به سبد
  202.                         </button>
  203.                         {% else %}
  204.                             <button type="submit" id="buy-btnl"
  205.                                     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">
  206.                                 افزودن به سبد
  207.                             </button>
  208.                     {% endif %}
  209.                 {% else %}
  210.                     <button disabled
  211.                             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">
  212.                         افزودن به سبد
  213.                     </button>
  214.                 {% endif %}
  215.             </div>
  216.         </section>
  217.         {{ form_end(addToCart, { render_rest: false }) }}
  218.         {% set products1 = getProducts() %}
  219.         {% include getThemeDir('modules/product-bar.html.twig') with {'title' : 'محصولات مرتبط' ,
  220.             subtitle: "جدیدترین و بروزترین محصولات",
  221.             products:products1,
  222.             container:0
  223.         } %}
  224.         <section class="relative mt-10 flex flex-col items-start gap-4 rounded-lg bg-white dark:bg-gray-800 shadow p-4">
  225.             <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">
  226.                 <button class="tab-btn text-blue-500" data-target="tab1">معرفی محصول</button>
  227.                 <button class="tab-btn text-gray-500 dark:text-gray-300" data-target="tab3">دیدگاه‌ها</button>
  228.             </div>
  229.             <div class="tab-content tab1 block">
  230.                 <h2 class="font-DanaDemiBold border-b-2 border-blue-500 w-fit p-1 text-lg mb-3">معرفی</h2>
  231.                 {#                <p class="mt-4 leading-8"> #}
  232.                 <div class="justify-content" style="text-align: justify">
  233.                     {{ product.description|raw }}
  234.                 </div>
  235.                 {#                </p> #}
  236.             </div>
  237.             <div class="tab-content tab3 hidden w-full">
  238.                 <div class="flex items-center gap-x-2 mb-6">
  239.                     <h2 class="font-DanaMedium text-2xl ">
  240.                         دیدگاه ها
  241.                     </h2>
  242.                     <p class="text-sm text-blue-500">
  243.                         ({{ product.productReviews|length }} دیدگاه)
  244.                     </p>
  245.                 </div>
  246.                 <div class="w-full flex flex-col md:flex-row items-start gap-10">
  247.                     <div class="lg:w-1/4 flex flex-col w-full ">
  248.                         <p class="font-DanaMedium text-lg mb-2">ثبت دیدگاه</p>
  249.                         {% if app.user %}
  250.                             {{ form_start(reviewForm , {'attr' : {'class' : 'pt-0'}}) }}
  251.                             {{ form_widget(reviewForm.content, {'attr': {'class': 'h-24 tailwind-input', 'rows': 5}}) }}
  252.                             {{ form_errors(reviewForm.content) }}
  253.                             {{ form_row(reviewForm.recommend, {
  254.                                 row_attr:   { class: 'mb-4 variant-selector' },
  255.                                 label_attr: { class: 'block text-sm text-gray-700 dark:text-gray-200 mb-1' },
  256.                                 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' },
  257.                                 help_attr:  { class: 'text-xs text-gray-500 mt-1' }
  258.                             }) }}
  259.                             {{ form_errors(reviewForm.recommend) }}
  260.                             {{ form_row(reviewForm.rating, {
  261.                                 row_attr:   { class: 'mb-4 variant-selector' },
  262.                                 label_attr: { class: 'block text-sm text-gray-700 dark:text-gray-200 mb-1' },
  263.                                 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' },
  264.                                 help_attr:  { class: 'text-xs text-gray-500 mt-1' }
  265.                             }) }}
  266.                             <button type="submit"
  267.                                     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">
  268.                                 ثبت نظر
  269.                             </button>
  270.                             {{ form_end(reviewForm) }}
  271.                         {% else %}
  272.                             <p>برای ثبت نظر، لازم است ابتدا وارد حساب کاربری خود
  273.                                 شوید.
  274.                             </p>
  275.                             <a href="{{ path('customer_panel_login') }}">ورود / ثبت نام</a>
  276.                         {% endif %}
  277.                     </div>
  278.                     <ul class="lg:w-3/4 flex flex-col gap-y-2 child:w-full ">
  279.                         {% for comment in comments %}
  280.                             <li class="child:flex py-4 border-b border-gray-200 dark:border-b-gray-200/20 child:border-white/20">
  281.                                 <div class="flex-col">
  282.                                     {% if comment.recommend %}
  283.                                         <h2 class="flex items-center gap-x-1 text-green-500 mb-4">
  284.                                             <svg class="w-4 h-4">
  285.                                                 <use href="#hand-up"></use>
  286.                                             </svg>
  287.                                             پیشنهاد میشود
  288.                                         </h2>
  289.                                     {% else %}
  290.                                         <h2 class="flex items-center gap-x-1 text-danger mb-4">
  291.                                             <svg class="w-4 h-4">
  292.                                                 <use href="#hand-down"></use>
  293.                                             </svg>
  294.                                             پیشنهاد نمیشود
  295.                                         </h2>
  296.                                     {% endif %}
  297.                                     <p class="text-gray-500 dark:text-gray-200 mb-2 line-clamp-2">
  298.                                         {{ comment.content }}
  299.                                     </p>
  300.                                 </div>
  301.                                 <div class="mt-2 lg:mt-0 flex-col lg:flex-row gap-y-2 lg:items-center justify-between">
  302.                                     <div class="flex items-center gap-x-4 text-gray-400 text-sm">
  303.                                         <p>{{ comment.createdAt|persianDate }}</p>
  304.                                         <p> {{ comment.author }}</p>
  305.                                     </div>
  306.                                 </div>
  307.                             </li>
  308.                             {% else %}
  309.                             اولین نفر برای ثبت نظر باشید
  310.                         {% endfor %}
  311.                     </ul>
  312.                 </div>
  313.             </div>
  314.         </section>
  315.     </main>
  316. {% endblock %}
  317. {% block javascripts %}
  318.     <script>
  319.         function setupDynamicCollection(containerId, addButtonId) {
  320.             const container = document.querySelector(`#${containerId} [data-prototype]`);
  321.             const addButton = document.getElementById(addButtonId);
  322.             let index = container.children.length;
  323.             addButton.addEventListener('click', () => {
  324.                 const prototype = container.dataset.prototype;
  325.                 const newForm = prototype.replace(/__name__/g, index);
  326.                 const wrapper = document.createElement('div');
  327.                 wrapper.classList.add('input-group', 'mb-2');
  328.                 wrapper.innerHTML = newForm + '<button type="button" class="btn btn-danger remove-item">–</button>';
  329.                 container.appendChild(wrapper);
  330.                 index++;
  331.             });
  332.             container.addEventListener('click', (e) => {
  333.                 if (e.target.classList.contains('remove-item')) {
  334.                     e.target.closest('.input-group').remove();
  335.                 }
  336.             });
  337.         }
  338.         document.addEventListener('DOMContentLoaded', () => {
  339.             setupDynamicCollection('pros-container', 'add-pro');
  340.             setupDynamicCollection('cons-container', 'add-con');
  341.         });
  342.     </script>
  343.     {% set jss = [
  344.         'base-assets/themes/karen/scripts/productDetails.js',
  345.     ] %}
  346.     {% for url in jss %}
  347.         <script src="{{ url('app_cdn_path' , {'path' : url})|replaceUrl('http://', 'https://') }}"></script>
  348.     {% endfor %}
  349. {#    <script>#}
  350. {#        $(function () {#}
  351. {#            const $root = $('#product-variant');#}
  352. {#            const $price = $('#product-price');#}
  353. {#            const $buyBtn = $('#buy-btnl');#}
  354. {#            const $priceId = $('#add_to_cart_product_price_id');#}
  355. {#            let pendingReq = null;#}
  356. {#            let debounceTimer = null;#}
  357. {#            function collectVariants() {#}
  358. {#                const data = {};#}
  359. {#                // رادیوهای انتخاب‌شده (فقط داخل گروه‌های variant)#}
  360. {#                $root.find('.variant-selector input[type="radio"]:checked').each(function () {#}
  361. {#                    data[this.name] = this.value;#}
  362. {#                });#}
  363. {#                // سلکت‌ها (اگر خالی نباشند)#}
  364. {#                $root.find('.variant-selector select').each(function () {#}
  365. {#                    const v = $(this).val();#}
  366. {#                    if (v !== '' && v != null) data[this.name] = v;#}
  367. {#                });#}
  368. {#                return data;#}
  369. {#            }#}
  370. {#            function updatePrice() {#}
  371. {#                const params = collectVariants();#}
  372. {#                // لغو درخواست قبلی اگر هنوز بازه#}
  373. {#                if (pendingReq && pendingReq.readyState !== 4) {#}
  374. {#                    pendingReq.abort();#}
  375. {#                }#}
  376. {#                pendingReq = $.ajax({#}
  377. {#                    url: '{{ path("app_shop_site_product_price", {"urlSlug": product.urlSlug}) }}',#}
  378. {#                    type: 'GET',#}
  379. {#                    dataType: 'json',#}
  380. {#                    cache: false,#}
  381. {#                    data: params,#}
  382. {#                    beforeSend: function () {#}
  383. {#                        $buyBtn.prop('disabled', true);#}
  384. {#                    },#}
  385. {#                    success: function (res) {#}
  386. {#                        if (res && res.res) {#}
  387. {#                            $price.text(res.text || '');#}
  388. {#                            $priceId.val(res.productPriceId || '');#}
  389. {#                            $buyBtn.prop('disabled', false);#}
  390. {#                        } else {#}
  391. {#                            $price.text(res && res.text ? res.text : '');#}
  392. {#                            $priceId.val('');#}
  393. {#                            $buyBtn.prop('disabled', true);#}
  394. {#                        }#}
  395. {#                    },#}
  396. {#                    error: function (xhr, status) {#}
  397. {#                        if (status === 'abort') return; // درخواست قبلی بود#}
  398. {#                        $buyBtn.prop('disabled', true);#}
  399. {#                    }#}
  400. {#                });#}
  401. {#            }#}
  402. {#            // هندل تغییر روی رادیو و سلکت‌ها (delegation)#}
  403. {#            $(document).on('change', '#product-variant .variant-selector input[type="radio"], #product-variant .variant-selector select', function () {#}
  404. {#                clearTimeout(debounceTimer);#}
  405. {#                debounceTimer = setTimeout(updatePrice, 150);#}
  406. {#            });#}
  407. {#            // اجرا روی بارگذاری اولیه (اگر چیزی از قبل انتخاب شده)#}
  408. {#            updatePrice();#}
  409. {#        });#}
  410. {#    </script>#}
  411.         <script>
  412.         $(document).ready(function () {
  413.             $('.variant-selector').change(function () {
  414.                 var selectedVariants = {};
  415.                 $('#product-variant .variant-selector input[type="radio"], #product-variant .variant-selector select').each(function () {
  416.                     selectedVariants[$(this).attr('name')] = $(this).val();
  417.                 });
  418.                 $.ajax({
  419.                     url: '{{ path('app_shop_site_product_price' , {'urlSlug' : product.urlSlug}) }}',  // Your endpoint to handle the price update
  420.                     type: 'GET',
  421.                     data: selectedVariants,  // Send the selected variants as parameters
  422.                     success: function (response) {
  423.                         // add Product price id to form hidden
  424.                         if (response.res) {
  425.                             $('#buy-btnl').removeAttr('disabled');
  426.                             $('#product-price').text(response.text);
  427.                             $('#add_to_cart_product_price_id').val(response.productPriceId);
  428.                         } else {
  429.                             $('#buy-btnl').attr('disabled', 'disabled');
  430.                             $('#product-price').text(response.text);
  431.                         }
  432.                     },
  433.                     error: function () {
  434.                         // alert('این');
  435.                     }
  436.                 });
  437.             });
  438.         });
  439.     </script>
  440.     <script>
  441.         document.addEventListener('DOMContentLoaded', function () {
  442.             document.querySelectorAll('.variant-selector').forEach(function (radio) {
  443.                 radio.addEventListener('change', function () {
  444.                     const targetSelector = this.dataset.selectTarget;
  445.                     const newValue = this.dataset.selectValue;
  446.                     if (targetSelector && newValue) {
  447.                         const select = document.querySelector(targetSelector);
  448.                         if (select) {
  449.                             select.value = newValue;
  450.                             select.dispatchEvent(new Event('change')); // ← برای ری‌اکت شدن با JSهای دیگه
  451.                         }
  452.                     }
  453.                 });
  454.             });
  455.         });
  456.     </script>
  457. {% endblock %}