PluginProbe
ووسلام – همگام سازی ووکامرس و باسلام / 1.10.18
ووسلام – همگام سازی ووکامرس و باسلام v1.10.18
1.10.18 1.10.17 1.10.15 1.10.14 1.10.13 1.10.12 1.10.10 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.2 1.9.1 1.9.0 1.8.8 1.8.5 1.8.6 1.8.7 1.8.4 All 51 releases
sync-basalam / assets / js / admin.js

admin.js in ووسلام – همگام سازی ووکامرس و باسلام 1.10.18, at assets/js/admin.js

1,152 lines 32.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 document.addEventListener("DOMContentLoaded", function () {
2 const modalConfig = [
3 {
4 key: "add",
5 modalId: "basalamAddProductsModal",
6 openBtnId: "basalamOpenAddProductsModal",
7 formId: "basalamAddProductsForm",
8 action: "create_products_to_basalam",
9 },
10 {
11 key: "update",
12 modalId: "BasalamUpdateProductsModal",
13 openBtnId: "BasalamOpenUpdateProductsModal",
14 formId: "BasalamUpdateProductsForm",
15 action: "update_products_in_basalam",
16 },
17 {
18 key: "connect",
19 modalId: "BasalamConnectProductsModal",
20 openBtnId: "BasalamOpenConnectProductsModal",
21 formId: "BasalamConnectProductsForm",
22 action: "connect_products_with_basalam",
23 },
24 ];
25
26 const closeModal = () => {
27 document.querySelectorAll(".basalam-modal").forEach((modal) => {
28 modal.style.display = "none";
29 });
30 document.body.style.overflow = "auto";
31 };
32
33 modalConfig.forEach(({ modalId, openBtnId, formId, action }) => {
34 const modal = document.getElementById(modalId);
35 const openBtn = document.getElementById(openBtnId);
36 const form = document.getElementById(formId);
37
38 if (openBtn && modal) {
39 openBtn.addEventListener("click", () => {
40 modal.style.display = "block";
41 document.body.style.overflow = "hidden";
42
43 if (modalId === "BasalamUpdateProductsModal") {
44 const selectionDiv = document.getElementById("update-type-selection");
45 const quickConfirm = document.getElementById("quick-update-confirm");
46 const fullConfirm = document.getElementById("full-update-confirm");
47
48 if (selectionDiv) selectionDiv.style.display = "block";
49 if (quickConfirm) quickConfirm.style.display = "none";
50 if (fullConfirm) fullConfirm.style.display = "none";
51 }
52 });
53 }
54
55 if (form) {
56 form.addEventListener("submit", function (e) {
57 e.preventDefault();
58
59 if (action === "create_products_to_basalam") {
60 const confirmModal = document.getElementById("BasalamConfirmModal");
61 confirmModal.style.display = "block";
62 document.body.style.overflow = "hidden";
63
64 const confirmButton = document.getElementById("confirmSubmitBtn");
65
66 const newConfirmBtn = confirmButton.cloneNode(true);
67 confirmButton.parentNode.replaceChild(newConfirmBtn, confirmButton);
68
69 newConfirmBtn.addEventListener("click", function () {
70 confirmModal.style.display = "none";
71
72 submitToServer(form, action);
73 });
74 } else {
75 submitToServer(form, action);
76 }
77 });
78 }
79 });
80
81 setTimeout(() => {
82 const quickUpdateBtn = document.getElementById("quick-update-btn");
83 const fullUpdateBtn = document.getElementById("full-update-btn");
84
85 if (quickUpdateBtn) {
86 quickUpdateBtn.addEventListener("click", (e) => {
87 e.preventDefault();
88
89 const formData = new FormData();
90 formData.append("update_type", "quick");
91 formData.append("action", "update_products_in_basalam");
92 formData.append(
93 "_wpnonce",
94 document.querySelector(
95 '#BasalamUpdateProductsModal input[name="_wpnonce"]'
96 )?.value || ""
97 );
98
99 submitUpdateRequest(formData, "quick");
100 });
101 }
102
103 if (fullUpdateBtn) {
104 fullUpdateBtn.addEventListener("click", (e) => {
105 e.preventDefault();
106
107 const formData = new FormData();
108 formData.append("update_type", "full");
109 formData.append("action", "update_products_in_basalam");
110 formData.append(
111 "_wpnonce",
112 document.querySelector(
113 '#BasalamUpdateProductsModal input[name="_wpnonce"]'
114 )?.value || ""
115 );
116
117 submitUpdateRequest(formData, "full");
118 });
119 }
120 }, 100);
121
122 function submitUpdateRequest(formData, updateType) {
123 const quickBtn = document.getElementById("quick-update-btn");
124 const fullBtn = document.getElementById("full-update-btn");
125
126 if (quickBtn) quickBtn.disabled = true;
127 if (fullBtn) fullBtn.disabled = true;
128
129 const clickedBtn = updateType === "quick" ? quickBtn : fullBtn;
130 if (clickedBtn) {
131 const originalText = clickedBtn.innerHTML;
132 clickedBtn.innerHTML =
133 '<span class="basalam-loading-text">در حال ارسال...</span>';
134
135 fetch(ajaxurl, {
136 method: "POST",
137 body: formData,
138 })
139 .then((response) => response.json())
140 .then((data) => {
141 closeModal();
142 if (data.success) {
143 window.BasalamToast.success(data.data?.message || "ع�
144 لیات با �
145 وفقیت آغاز شد.");
146 } else {
147 window.BasalamToast.error(data.data?.message || "خطایی رخ داده است.");
148 }
149 location.reload();
150 })
151 .catch((error) => {
152 console.error("Error:", error);
153 window.BasalamToast.error("خطایی در ارسال رخ داده است.");
154
155 if (quickBtn) quickBtn.disabled = false;
156 if (fullBtn) fullBtn.disabled = false;
157 if (clickedBtn) clickedBtn.innerHTML = originalText;
158 });
159 }
160 }
161
162 function submitToServer(form, action, updateType = null) {
163 const formData = new FormData(form);
164 formData.append("action", action);
165
166 const submitButton = form.querySelector('button[type="submit"]');
167 submitButton.disabled = true;
168 submitButton.innerHTML =
169 '<span class="dashicons dashicons-update"></span> در حال ارسال...';
170
171 fetch(ajaxurl, {
172 method: "POST",
173 body: formData,
174 })
175 .then((response) => response.json())
176 .then((data) => {
177 closeModal();
178 if (data.success) {
179 window.BasalamToast.success(data.data?.message || "ع�
180 لیات با �
181 وفقیت آغاز شد.");
182 } else {
183 window.BasalamToast.error(data.data?.message || "خطایی رخ داده است.");
184 }
185 location.reload();
186 })
187 .catch((error) => {
188 console.error("Error:", error);
189 window.BasalamToast.error("خطایی در ارسال رخ داده است.");
190 })
191 .finally(() => {
192 submitButton.disabled = false;
193 submitButton.innerHTML =
194 '<span class="dashicons dashicons-plus-alt"></span> انجا�
195 شد';
196 });
197 }
198
199 document.querySelectorAll(".basalam-modal-close").forEach((btn) => {
200 btn.addEventListener("click", closeModal);
201 });
202
203 window.addEventListener("click", (event) => {
204 if (event.target.classList.contains("basalam-modal")) {
205 closeModal();
206 }
207 });
208
209 document.addEventListener("keydown", (event) => {
210 if (event.key === "Escape") {
211 closeModal();
212 }
213 });
214
215 const select = document.getElementById("basalam-sync-type");
216 if (select) {
217 const customFields = document.getElementById("Basalam-custom-fields");
218 const settingsForm = select.closest("form");
219 const validationMessage =
220 "در حالت سفارشی باید حداقل یک فیلد را برای بروزرسانی انتخاب کنید.";
221
222 const toggleFields = (val) => {
223 if (customFields) {
224 customFields.style.display = val === "custom" ? "block" : "none";
225 }
226 };
227
228 const hasSelectedCustomField = () =>
229 customFields &&
230 Array.from(
231 customFields.querySelectorAll('input[type="checkbox"]')
232 ).some((checkbox) => checkbox.checked);
233
234 toggleFields(select.value);
235 select.addEventListener("change", (e) => toggleFields(e.target.value));
236
237 if (settingsForm) {
238 settingsForm.addEventListener("submit", (event) => {
239 if (select.value !== "custom" || hasSelectedCustomField()) return;
240
241 event.preventDefault();
242 event.stopImmediatePropagation();
243
244 if (window.BasalamToast) {
245 window.BasalamToast.error(validationMessage);
246 }
247
248 if (customFields) {
249 customFields.scrollIntoView({ behavior: "smooth", block: "center" });
250 customFields.querySelector('input[type="checkbox"]')?.focus();
251 }
252 }, true);
253 }
254 }
255
256 // Tab functionality for settings modal
257 const initTabs = () => {
258 const tabBtns = document.querySelectorAll(".basalam-tab-btn");
259 const tabContents = document.querySelectorAll(".basalam-tab-content");
260
261 tabBtns.forEach((btn) => {
262 btn.addEventListener("click", () => {
263 const tabId = btn.getAttribute("data-tab");
264
265 // Remove active class from all buttons and contents
266 tabBtns.forEach((b) => b.classList.remove("active"));
267 tabContents.forEach((c) => c.classList.remove("active"));
268
269 // Add active class to clicked button and corresponding content
270 btn.classList.add("active");
271 const content = document.getElementById(tabId);
272 if (content) {
273 content.classList.add("active");
274 }
275 });
276 });
277 };
278
279 initTabs();
280
281 const initPointerOnboarding = () => {
282 const pointerTour = window.basalamPointerTour;
283
284 if (
285 !pointerTour ||
286 !Array.isArray(pointerTour.steps) ||
287 pointerTour.steps.length === 0
288 ) {
289 return;
290 }
291
292 if (
293 typeof window.jQuery === "undefined" ||
294 typeof window.jQuery.fn.pointer !== "function"
295 ) {
296 return;
297 }
298
299 const steps = pointerTour.steps.filter(
300 (step) =>
301 step &&
302 typeof step.selector === "string" &&
303 document.querySelector(step.selector)
304 );
305
306 if (steps.length === 0) {
307 return;
308 }
309
310 let completionRequested = false;
311
312 const markTourCompleted = () => {
313 if (completionRequested) {
314 return;
315 }
316
317 completionRequested = true;
318
319 if (!pointerTour.completeAction || !pointerTour.nonce) {
320 return;
321 }
322
323 const formData = new FormData();
324 formData.append("action", pointerTour.completeAction);
325 formData.append("nonce", pointerTour.nonce);
326
327 fetch(ajaxurl, {
328 method: "POST",
329 body: formData,
330 }).catch(() => {});
331 };
332
333 const openStep = (index) => {
334 if (index >= steps.length) {
335 markTourCompleted();
336 return;
337 }
338
339 const step = steps[index];
340 const $target = window.jQuery(step.selector).first();
341
342 if (!$target.length) {
343 openStep(index + 1);
344 return;
345 }
346
347 const targetElement = $target.get(0);
348 if (targetElement && typeof targetElement.scrollIntoView === "function") {
349 targetElement.scrollIntoView({ behavior: "smooth", block: "center" });
350 }
351
352 let shouldAdvance = false;
353 let shouldStop = false;
354
355 $target
356 .pointer({
357 pointerClass: "sync-basalam-pointer",
358 content: step.content || "",
359 position: step.position || { edge: "right", align: "middle" },
360 buttons: function (event, t) {
361 const isLastStep = index === steps.length - 1;
362 const skipLabel = step.skipLabel || "بستن";
363 const nextLabel = isLastStep
364 ? step.doneLabel || "ات�
365 ا�
366 "
367 : step.nextLabel || "بعدی";
368
369 const $skipButton = window.jQuery(
370 '<button type="button" class="button button-secondary"></button>'
371 ).text(skipLabel);
372
373 const $nextButton = window.jQuery(
374 '<button type="button" class="button button-primary"></button>'
375 ).text(nextLabel);
376
377 $skipButton.on("click", function () {
378 shouldStop = true;
379 t.element.pointer("close");
380 });
381
382 $nextButton.on("click", function () {
383 shouldAdvance = true;
384 t.element.pointer("close");
385 });
386
387 return window.jQuery('<div class="wp-pointer-buttons" />')
388 .append($skipButton)
389 .append($nextButton);
390 },
391 close: function () {
392 if (shouldStop) {
393 markTourCompleted();
394 return;
395 }
396
397 if (shouldAdvance) {
398 openStep(index + 1);
399 return;
400 }
401
402 markTourCompleted();
403 },
404 })
405 .pointer("open");
406 };
407
408 openStep(0);
409 };
410
411 initPointerOnboarding();
412
413 const initAnnouncementsPanel = () => {
414 const announcementsConfig = window.basalamAnnouncements;
415
416 if (
417 !announcementsConfig ||
418 !Array.isArray(announcementsConfig.items) ||
419 announcementsConfig.items.length === 0
420 ) {
421 return;
422 }
423
424 const root = document.getElementById("sync-basalam-announcement-root");
425 const trigger = document.getElementById("sync-basalam-announcement-trigger");
426 const panel = document.getElementById("sync-basalam-announcement-panel");
427 const overlay = document.getElementById("sync-basalam-announcement-overlay");
428 const closeBtn = document.getElementById("sync-basalam-announcement-close");
429 const counter = document.getElementById("sync-basalam-announcement-counter");
430 const list = document.getElementById("sync-basalam-announcement-list");
431 const pageIndicator = document.getElementById("sync-basalam-announcement-page");
432 const prevBtn = document.getElementById("sync-basalam-announcement-prev");
433 const nextBtn = document.getElementById("sync-basalam-announcement-next");
434
435 if (
436 !root ||
437 !trigger ||
438 !panel ||
439 !overlay ||
440 !closeBtn ||
441 !counter ||
442 !list ||
443 !pageIndicator ||
444 !prevBtn ||
445 !nextBtn
446 ) {
447 return;
448 }
449
450 const normalizeItems = (rawItems) =>
451 rawItems
452 .map((item) => {
453 const files = Array.isArray(item?.files) ? item.files : [];
454 const imageFile = files.find((f) => f?.url && /\.(png|jpe?g|gif|webp|svg)/i.test(f.url));
455
456 return {
457 id: String(item?.id || ""),
458 description: String(item?.description || ""),
459 link: String(item?.link || "#"),
460 linkText: String(item?.linkText || "ادا�
461 ه"),
462 image: imageFile ? String(imageFile.url) : (item?.image ? String(item.image) : ""),
463 };
464 })
465 .filter((item) => item.id && item.description);
466
467 let items = normalizeItems(announcementsConfig.items);
468
469 if (items.length === 0) {
470 root.remove();
471 return;
472 }
473
474 let currentPage = 1;
475 let totalPages = Math.max(parseInt(announcementsConfig.totalPage, 10) || 1, 1);
476 let isFetching = false;
477
478 let seenIds = new Set(
479 Array.isArray(announcementsConfig.seenIds)
480 ? announcementsConfig.seenIds.map((id) => String(id))
481 : []
482 );
483 let seenRequested = false;
484
485 const getUnreadCount = () =>
486 items.reduce((total, item) => total + (seenIds.has(item.id) ? 0 : 1), 0);
487
488 const updateCounter = () => {
489 const unreadCount = getUnreadCount();
490 counter.textContent = String(unreadCount);
491 counter.classList.toggle(
492 "sync-basalam-announcement-counter-hidden",
493 unreadCount === 0
494 );
495 };
496
497 const renderItems = (pageItems) => {
498 list.innerHTML = "";
499
500 pageItems.forEach((item) => {
501 const card = document.createElement("article");
502 card.className =
503 "sync-basalam-announcement-card" +
504 (item.image ? "" : " sync-basalam-announcement-card-no-image") +
505 (seenIds.has(item.id) ? " is-seen" : " is-unread");
506
507 if (item.image) {
508 const imageWrapper = document.createElement("div");
509 imageWrapper.className = "sync-basalam-announcement-image-wrap";
510
511 const image = document.createElement("img");
512 image.className = "sync-basalam-announcement-image";
513 image.src = item.image;
514 image.alt = "خبر ووسلا�
515 ";
516 image.loading = "lazy";
517
518 imageWrapper.appendChild(image);
519 card.appendChild(imageWrapper);
520 }
521
522 const content = document.createElement("div");
523 content.className = "sync-basalam-announcement-content";
524
525 const description = document.createElement("p");
526 description.className = "sync-basalam-announcement-text";
527 description.textContent = item.description;
528
529 const link = document.createElement("a");
530 link.className = "sync-basalam-announcement-link";
531 link.href = item.link;
532 link.textContent = item.linkText || "ادا�
533 ه";
534 link.target = "_blank";
535 link.rel = "noopener noreferrer";
536
537 content.appendChild(description);
538 if (item.link && item.link !== "#") {
539 content.appendChild(link);
540 }
541 card.appendChild(content);
542 list.appendChild(card);
543 });
544 };
545
546 const updatePagination = () => {
547 pageIndicator.textContent = `${currentPage} / ${totalPages}`;
548 prevBtn.disabled = currentPage <= 1 || isFetching;
549 nextBtn.disabled = currentPage >= totalPages || isFetching;
550 };
551
552 const renderPage = () => {
553 renderItems(items);
554 updatePagination();
555 };
556
557 const fetchPage = (page) => {
558 if (isFetching) {
559 return;
560 }
561
562 isFetching = true;
563 prevBtn.disabled = true;
564 nextBtn.disabled = true;
565 list.innerHTML = '<div class="sync-basalam-announcement-loading">در حال بارگذاری...</div>';
566
567 const formData = new FormData();
568 formData.append("action", announcementsConfig.fetchPageAction || "");
569 formData.append("nonce", announcementsConfig.fetchPageNonce || "");
570 formData.append("page", String(page));
571
572 fetch(ajaxurl, {
573 method: "POST",
574 body: formData,
575 })
576 .then((response) => response.json())
577 .then((data) => {
578 if (!data?.success) {
579 return;
580 }
581
582 const newItems = normalizeItems(data.data.items || []);
583 items = newItems;
584 currentPage = parseInt(data.data.page, 10) || page;
585 totalPages = parseInt(data.data.totalPage, 10) || totalPages;
586
587 renderPage();
588 })
589 .catch(() => {
590 updatePagination();
591 })
592 .finally(() => {
593 isFetching = false;
594 updatePagination();
595 });
596 };
597
598 const markAllSeen = () => {
599 if (seenRequested || getUnreadCount() === 0) {
600 return;
601 }
602
603 seenRequested = true;
604
605 const formData = new FormData();
606 formData.append("action", announcementsConfig.markSeenAction || "");
607 formData.append("nonce", announcementsConfig.nonce || "");
608
609 fetch(ajaxurl, {
610 method: "POST",
611 body: formData,
612 })
613 .then((response) => response.json())
614 .then((data) => {
615 if (!data?.success) {
616 return;
617 }
618
619 seenIds = new Set(items.map((item) => item.id));
620 updateCounter();
621 renderPage();
622 })
623 .catch(() => {})
624 .finally(() => {
625 seenRequested = false;
626 });
627 };
628
629 const openPanel = () => {
630 root.classList.add("is-open");
631 panel.setAttribute("aria-hidden", "false");
632 document.body.classList.add("sync-basalam-announcement-open");
633 markAllSeen();
634 };
635
636 const closePanel = () => {
637 root.classList.remove("is-open");
638 panel.setAttribute("aria-hidden", "true");
639 document.body.classList.remove("sync-basalam-announcement-open");
640 };
641
642 trigger.addEventListener("click", openPanel);
643 closeBtn.addEventListener("click", closePanel);
644 overlay.addEventListener("click", closePanel);
645
646 document.addEventListener("mousedown", (event) => {
647 if (!root.classList.contains("is-open")) {
648 return;
649 }
650
651 const target = event.target;
652 if (!(target instanceof Node)) {
653 return;
654 }
655
656 if (panel.contains(target) || trigger.contains(target)) {
657 return;
658 }
659
660 closePanel();
661 });
662
663 prevBtn.addEventListener("click", () => {
664 if (currentPage <= 1 || isFetching) {
665 return;
666 }
667 fetchPage(currentPage - 1);
668 });
669
670 nextBtn.addEventListener("click", () => {
671 if (currentPage >= totalPages || isFetching) {
672 return;
673 }
674 fetchPage(currentPage + 1);
675 });
676
677 document.addEventListener("keydown", (event) => {
678 if (event.key === "Escape" && root.classList.contains("is-open")) {
679 closePanel();
680 }
681 });
682
683 updateCounter();
684 renderPage();
685 };
686
687 initAnnouncementsPanel();
688
689 const advancedSettingsForm = document.getElementById(
690 "basalam-advanced-settings-form"
691 );
692 const advancedSubmitSection = document.getElementById(
693 "basalam-advanced-submit-section"
694 );
695
696 const isTrackedAdvancedSettingField = (fieldName) =>
697 typeof fieldName === "string" &&
698 fieldName.startsWith("sync_basalam_settings[");
699
700 if (advancedSettingsForm && advancedSubmitSection) {
701 const serializeAdvancedSettings = () => {
702 const formData = new FormData(advancedSettingsForm);
703 const entries = [];
704
705 formData.forEach((value, key) => {
706 if (isTrackedAdvancedSettingField(key)) {
707 entries.push(`${key}=${String(value)}`);
708 }
709 });
710
711 return entries.join("&");
712 };
713
714 let initialSettingsSnapshot = "";
715
716 const toggleAdvancedSubmitVisibility = () => {
717 const currentSnapshot = serializeAdvancedSettings();
718 const hasChanges = currentSnapshot !== initialSettingsSnapshot;
719
720 advancedSubmitSection.classList.toggle(
721 "basalam-submit-section-hidden",
722 !hasChanges
723 );
724 };
725
726 const captureInitialSnapshot = () => {
727 initialSettingsSnapshot = serializeAdvancedSettings();
728 toggleAdvancedSubmitVisibility();
729 };
730
731 const handleSettingsFieldMutation = (event) => {
732 const fieldName = event.target?.name || "";
733
734 if (!isTrackedAdvancedSettingField(fieldName)) {
735 return;
736 }
737
738 window.requestAnimationFrame(toggleAdvancedSubmitVisibility);
739 };
740
741 advancedSettingsForm.addEventListener("input", handleSettingsFieldMutation);
742 advancedSettingsForm.addEventListener(
743 "change",
744 handleSettingsFieldMutation
745 );
746
747 captureInitialSnapshot();
748 window.requestAnimationFrame(captureInitialSnapshot);
749 }
750
751 const infoTriggers = document.querySelectorAll(".basalam-info-trigger");
752
753 const moveModalsToBody = () => {
754 const allModals = document.querySelectorAll(".basalam-info-modal");
755 allModals.forEach((modal) => {
756 if (modal.parentNode !== document.body) {
757 document.body.appendChild(modal);
758 }
759 });
760 };
761
762 moveModalsToBody();
763
764 const closeAllModals = () => {
765 const allModals = document.querySelectorAll(".basalam-info-modal");
766 allModals.forEach((modal) => {
767 modal.style.display = "none";
768 modal.classList.remove("show");
769 });
770 document.body.style.overflow = "auto";
771 };
772
773 const openModal = (modalId) => {
774 const modal = document.getElementById(modalId);
775 if (modal) {
776 if (modal.parentNode !== document.body) {
777 document.body.appendChild(modal);
778 }
779
780 modal.style.display = "block";
781 modal.classList.add("show");
782 document.body.style.overflow = "hidden";
783
784 modal.focus();
785 }
786 };
787
788 infoTriggers.forEach((trigger) => {
789 trigger.addEventListener("click", (e) => {
790 e.preventDefault();
791 e.stopPropagation();
792
793 const modalId = trigger.getAttribute("data-modal-id");
794 if (modalId) {
795 openModal(modalId);
796 }
797 });
798 });
799
800 document.addEventListener("click", (e) => {
801 if (e.target.classList.contains("basalam-info-modal-close")) {
802 e.preventDefault();
803 closeAllModals();
804 }
805
806 if (e.target.classList.contains("basalam-info-modal-overlay")) {
807 closeAllModals();
808 }
809
810 if (e.target.classList.contains("basalam-info-modal")) {
811 closeAllModals();
812 }
813 });
814
815 document.addEventListener("keydown", (e) => {
816 if (e.key === "Escape") {
817 closeAllModals();
818 }
819 });
820
821 document.addEventListener("click", (e) => {
822 if (e.target.closest(".basalam-info-modal-content")) {
823 e.stopPropagation();
824 }
825 });
826
827 const tasksAutoToggle = document.querySelector(".basalam-tasks-auto-toggle");
828 const tasksManualContainer = document.querySelector(
829 ".basalam-tasks-manual-container"
830 );
831 const tasksManualInput = document.querySelector(
832 ".basalam-tasks-manual-input"
833 );
834 const tasksAutoHidden = document.querySelector(".basalam-tasks-auto-hidden");
835
836 const toggleTasksManualInput = () => {
837 if (tasksAutoToggle && tasksManualInput) {
838 const isAuto = tasksAutoToggle.checked;
839
840 if (isAuto) {
841 tasksManualInput.disabled = true;
842 if (tasksAutoHidden) tasksAutoHidden.disabled = true;
843 } else {
844 tasksManualInput.disabled = false;
845 if (tasksAutoHidden) tasksAutoHidden.disabled = false;
846 }
847 }
848 };
849
850 if (tasksAutoToggle) {
851 tasksAutoToggle.addEventListener("change", toggleTasksManualInput);
852 }
853
854 // Attribute suffix toggle handler
855 const attributeSuffixToggle = document.querySelector(
856 ".basalam-attribute-suffix-toggle"
857 );
858 const attributeSuffixPriority = document.querySelector(
859 ".basalam-attribute-suffix-priority"
860 );
861 const attributeSuffixContainer = document.querySelector(
862 ".basalam-attribute-suffix-container"
863 );
864 const attributeSuffixHidden = document.querySelector(
865 ".basalam-attribute-suffix-hidden"
866 );
867
868 const toggleAttributeSuffixPriority = () => {
869 if (attributeSuffixToggle) {
870 const isEnabled = attributeSuffixToggle.checked;
871
872 if (attributeSuffixPriority) {
873 attributeSuffixPriority.disabled = !isEnabled;
874 }
875
876 if (attributeSuffixContainer) {
877 attributeSuffixContainer.style.display = isEnabled ? "block" : "none";
878 }
879
880 if (attributeSuffixHidden) {
881 attributeSuffixHidden.disabled = isEnabled;
882 }
883 }
884 };
885
886 if (attributeSuffixToggle) {
887 attributeSuffixToggle.addEventListener(
888 "change",
889 toggleAttributeSuffixPriority
890 );
891 // Initialize on page load
892 toggleAttributeSuffixPriority();
893 }
894
895 const initBulkEditFields = () => {
896 const SYNC_BASALAM_BULK_ACTION = "sync_basalam_bulk_edit";
897
898 const syncTypeVisibility = () => {
899 document
900 .querySelectorAll('select[name="sync_basalam_bulk_product_type_action"]')
901 .forEach((select) => {
902 const container = select
903 .closest(".sync-basalam-bulk-edit")
904 ?.querySelector(".sync-basalam-bulk-type-fields");
905
906 if (container) {
907 container.style.display = select.value === "yes" ? "flex" : "none";
908 }
909 });
910 };
911
912 const syncPriceChangeVisibility = () => {
913 document
914 .querySelectorAll('select[name="sync_basalam_bulk_price_change_action"]')
915 .forEach((select) => {
916 const field = select
917 .closest(".sync-basalam-bulk-edit")
918 ?.querySelector(".sync-basalam-bulk-price-change-value");
919
920 if (field) {
921 field.style.display = select.value === "set" ? "block" : "none";
922 }
923 });
924 };
925
926 const setBulkEditMode = (mode) => {
927 const bulkRow = document.getElementById("bulk-edit");
928 if (!bulkRow) {
929 return;
930 }
931
932 bulkRow.classList.remove("sync-basalam-bulk-mode", "sync-basalam-default-bulk-mode");
933 bulkRow.classList.add(mode === "basalam" ? "sync-basalam-bulk-mode" : "sync-basalam-default-bulk-mode");
934 };
935
936 const openBasalamBulkEditor = (sourceSelect) => {
937 if (!window.inlineEditPost || typeof window.inlineEditPost.setBulk !== "function") {
938 return;
939 }
940
941 setBulkEditMode("basalam");
942
943 sourceSelect.value = "edit";
944 window.inlineEditPost.setBulk();
945 sourceSelect.value = SYNC_BASALAM_BULK_ACTION;
946
947 window.requestAnimationFrame(() => {
948 setBulkEditMode("basalam");
949 syncTypeVisibility();
950 syncPriceChangeVisibility();
951 });
952 };
953
954 document.addEventListener("change", (event) => {
955 const target = event.target;
956 if (!(target instanceof HTMLSelectElement)) {
957 return;
958 }
959
960 if (target.name === "sync_basalam_bulk_product_type_action") {
961 syncTypeVisibility();
962 }
963
964 if (target.name === "sync_basalam_bulk_price_change_action") {
965 syncPriceChangeVisibility();
966 }
967 });
968
969 document.addEventListener("click", (event) => {
970 const button = event.target instanceof Element
971 ? event.target.closest("#doaction, #doaction2")
972 : null;
973
974 if (!button) {
975 return;
976 }
977
978 const selectorId = button.id === "doaction2" ? "bulk-action-selector-bottom" : "bulk-action-selector-top";
979 const actionSelect = document.getElementById(selectorId);
980
981 if (!(actionSelect instanceof HTMLSelectElement)) {
982 return;
983 }
984
985 if (actionSelect.value === SYNC_BASALAM_BULK_ACTION) {
986 event.preventDefault();
987 event.stopImmediatePropagation();
988 openBasalamBulkEditor(actionSelect);
989 return;
990 }
991
992 if (actionSelect.value === "edit") {
993 setBulkEditMode("default");
994 }
995 }, true);
996
997 document.addEventListener("click", (event) => {
998 const cancelButton = event.target instanceof Element
999 ? event.target.closest("#bulk-edit .cancel")
1000 : null;
1001
1002 if (!cancelButton) {
1003 return;
1004 }
1005
1006 setBulkEditMode("default");
1007 });
1008
1009 setBulkEditMode("default");
1010
1011 syncTypeVisibility();
1012 syncPriceChangeVisibility();
1013 };
1014
1015 initBulkEditFields();
1016
1017 var modal = document.getElementById("sync_basalam_support_modal");
1018 var btn = document.getElementById("sync_basalam_support_btn");
1019 var cancelBtn = document.getElementById("sync_basalam_cancel_btn");
1020
1021 if (btn) {
1022 btn.addEventListener("click", function () {
1023 if (modal) {
1024 modal.style.display = "flex";
1025 }
1026 });
1027 }
1028
1029 if (cancelBtn) {
1030 cancelBtn.addEventListener("click", function () {
1031 if (modal) {
1032 modal.style.display = "none";
1033 }
1034 });
1035 }
1036
1037 if (modal) {
1038 modal.addEventListener("click", function (e) {
1039 if (e.target === modal) {
1040 modal.style.display = "none";
1041 }
1042 });
1043 }
1044
1045 // Star rating functionality
1046 var currentRating = 5;
1047
1048 function updateStars(rating) {
1049 var stars = document.querySelectorAll('#basalam_rating_stars .basalam-star');
1050 stars.forEach(function(star) {
1051 var starRating = parseInt(star.getAttribute('data-rating'));
1052 if (starRating <= rating) {
1053 star.style.color = '#f5a623';
1054 } else {
1055 star.style.color = '#ddd';
1056 }
1057 });
1058 }
1059
1060 updateStars(5);
1061
1062 var starsContainer = document.getElementById('basalam_rating_stars');
1063 if (starsContainer) {
1064 starsContainer.addEventListener('mouseover', function(e) {
1065 if (e.target.classList.contains('basalam-star')) {
1066 var hoverRating = parseInt(e.target.getAttribute('data-rating'));
1067 updateStars(hoverRating);
1068 }
1069 });
1070
1071 starsContainer.addEventListener('mouseout', function() {
1072 updateStars(currentRating);
1073 });
1074
1075 starsContainer.addEventListener('click', function(e) {
1076 if (e.target.classList.contains('basalam-star')) {
1077 currentRating = parseInt(e.target.getAttribute('data-rating'));
1078 document.getElementById('sync_basalam_rating').value = currentRating;
1079 updateStars(currentRating);
1080 }
1081 });
1082 }
1083
1084 // Remind Later button
1085 var remindLaterBtn = document.getElementById('sync_basalam_remind_later_review_btn');
1086 if (remindLaterBtn) {
1087 remindLaterBtn.addEventListener('click', function() {
1088 var nonceEl = document.getElementById('sync_basalam_remind_later_review_nonce');
1089 jQuery.ajax({
1090 url: ajaxurl,
1091 type: 'POST',
1092 data: {
1093 action: 'sync_basalam_remind_later_review',
1094 _wpnonce: nonceEl ? nonceEl.value : ''
1095 },
1096 success: function() {
1097 document.getElementById('sync_basalam_like_alert').style.display = 'none';
1098 }
1099 });
1100 });
1101 }
1102
1103 // Never Remind button
1104 var neverRemindBtn = document.getElementById('sync_basalam_never_remind_review_btn');
1105 if (neverRemindBtn) {
1106 neverRemindBtn.addEventListener('click', function() {
1107 var nonceEl = document.getElementById('sync_basalam_never_remind_review_nonce');
1108 jQuery.ajax({
1109 url: ajaxurl,
1110 type: 'POST',
1111 data: {
1112 action: 'sync_basalam_never_remind_review',
1113 _wpnonce: nonceEl ? nonceEl.value : ''
1114 },
1115 success: function() {
1116 document.getElementById('sync_basalam_like_alert').style.display = 'none';
1117 }
1118 });
1119 });
1120 }
1121
1122 // Submit Review form
1123 var supportForm = document.getElementById('sync_basalam_support_form');
1124 if (supportForm) {
1125 supportForm.addEventListener('submit', function(e) {
1126 e.preventDefault();
1127 var nonceEl = document.getElementById('sync_basalam_submit_review_nonce');
1128 var ratingEl = document.getElementById('sync_basalam_rating');
1129 var commentEl = document.getElementById('sync_basalam_comment');
1130
1131 jQuery.ajax({
1132 url: ajaxurl,
1133 type: 'POST',
1134 data: {
1135 action: 'sync_basalam_submit_review',
1136 _wpnonce: nonceEl ? nonceEl.value : '',
1137 sync_basalam_rating: ratingEl ? ratingEl.value : '5',
1138 sync_basalam_comment: commentEl ? commentEl.value : ''
1139 },
1140 success: function(response) {
1141 if (response.success) {
1142 document.getElementById('sync_basalam_like_alert').style.display = 'none';
1143 if (modal) modal.style.display = 'none';
1144 } else {
1145 window.BasalamToast.error(response.data && response.data.message ? response.data.message : 'خطا در ارسال نظر');
1146 }
1147 }
1148 });
1149 });
1150 }
1151 });
1152