document.addEventListener("DOMContentLoaded", function () { const modalConfig = [ { key: "add", modalId: "basalamAddProductsModal", openBtnId: "basalamOpenAddProductsModal", formId: "basalamAddProductsForm", action: "create_products_to_basalam", }, { key: "update", modalId: "BasalamUpdateProductsModal", openBtnId: "BasalamOpenUpdateProductsModal", formId: "BasalamUpdateProductsForm", action: "update_products_in_basalam", }, { key: "connect", modalId: "BasalamConnectProductsModal", openBtnId: "BasalamOpenConnectProductsModal", formId: "BasalamConnectProductsForm", action: "connect_products_with_basalam", }, ]; const updateModal = document.getElementById("BasalamUpdateProductsModal"); let updateStatusPoller = null; let updateStatusInFlight = false; const showUpdatePanel = (panelId) => { ["update-status-loading", "update-status-error", "update-type-selection", "quick-update-in-progress", "active-jobs-info"].forEach((id) => { const panel = document.getElementById(id); if (panel) panel.hidden = id !== panelId; }); }; const refreshUpdateStatus = () => { if (!updateModal || !document.getElementById("update-type-selection") || updateStatusInFlight) return; updateStatusInFlight = true; const formData = new FormData(); formData.append("action", "get_update_queue_status"); formData.append("_wpnonce", updateModal.dataset.statusNonce || ""); return fetch(ajaxurl, { method: "POST", body: formData, cache: "no-store" }) .then((response) => response.json()) .then((response) => { if (!response.success || !response.data) throw new Error("Update status unavailable"); const status = response.data; if (!status.active) { showUpdatePanel("update-type-selection"); } else if (status.type === "quick") { const badge = document.getElementById("quick-update-status"); if (badge) badge.textContent = status.status === "processing" ? "در حال پردازش" : "در انتظار"; showUpdatePanel("quick-update-in-progress"); } else { const count = Number(status.count) || 0; const countRow = document.getElementById("update-queue-count-row"); const countBadge = document.getElementById("update-queue-count"); if (countRow) countRow.hidden = count === 0; if (countBadge) countBadge.textContent = `${count} محصول`; showUpdatePanel("active-jobs-info"); } }) .catch((error) => { console.error("Error fetching product update status:", error); showUpdatePanel("update-status-error"); }) .finally(() => { updateStatusInFlight = false; }); }; const closeModal = () => { if (updateStatusPoller) { clearInterval(updateStatusPoller); updateStatusPoller = null; } document.querySelectorAll(".basalam-modal").forEach((modal) => { modal.style.display = "none"; }); document.body.style.overflow = "auto"; }; modalConfig.forEach(({ modalId, openBtnId, formId, action }) => { const modal = document.getElementById(modalId); const openBtn = document.getElementById(openBtnId); const form = document.getElementById(formId); if (openBtn && modal) { openBtn.addEventListener("click", () => { modal.style.display = "block"; document.body.style.overflow = "hidden"; if (modalId === "BasalamUpdateProductsModal") { if (document.getElementById("update-type-selection")) { showUpdatePanel("update-status-loading"); refreshUpdateStatus(); if (updateStatusPoller) clearInterval(updateStatusPoller); updateStatusPoller = setInterval(refreshUpdateStatus, 5000); } } }); } if (form) { form.addEventListener("submit", function (e) { e.preventDefault(); if (action === "create_products_to_basalam") { const confirmModal = document.getElementById("BasalamConfirmModal"); confirmModal.style.display = "block"; document.body.style.overflow = "hidden"; const confirmButton = document.getElementById("confirmSubmitBtn"); const newConfirmBtn = confirmButton.cloneNode(true); confirmButton.parentNode.replaceChild(newConfirmBtn, confirmButton); newConfirmBtn.addEventListener("click", function () { confirmModal.style.display = "none"; submitToServer(form, action); }); } else { submitToServer(form, action); } }); } }); document.getElementById("update-status-retry")?.addEventListener("click", () => { showUpdatePanel("update-status-loading"); refreshUpdateStatus(); }); setTimeout(() => { const quickUpdateBtn = document.getElementById("quick-update-btn"); const fullUpdateBtn = document.getElementById("full-update-btn"); if (quickUpdateBtn) { quickUpdateBtn.addEventListener("click", (e) => { e.preventDefault(); const formData = new FormData(); formData.append("update_type", "quick"); formData.append("action", "update_products_in_basalam"); formData.append( "_wpnonce", document.querySelector( '#BasalamUpdateProductsModal input[name="_wpnonce"]' )?.value || "" ); submitUpdateRequest(formData, "quick"); }); } if (fullUpdateBtn) { fullUpdateBtn.addEventListener("click", (e) => { e.preventDefault(); const formData = new FormData(); formData.append("update_type", "full"); formData.append("action", "update_products_in_basalam"); formData.append( "_wpnonce", document.querySelector( '#BasalamUpdateProductsModal input[name="_wpnonce"]' )?.value || "" ); submitUpdateRequest(formData, "full"); }); } }, 100); function submitUpdateRequest(formData, updateType) { const quickBtn = document.getElementById("quick-update-btn"); const fullBtn = document.getElementById("full-update-btn"); if (quickBtn) quickBtn.disabled = true; if (fullBtn) fullBtn.disabled = true; const clickedBtn = updateType === "quick" ? quickBtn : fullBtn; if (clickedBtn) { const originalText = clickedBtn.innerHTML; clickedBtn.innerHTML = 'در حال ارسال...'; fetch(ajaxurl, { method: "POST", body: formData, }) .then((response) => response.json()) .then((data) => { closeModal(); if (data.success) { window.BasalamToast.success(data.data?.message || "عملیات با موفقیت آغاز شد."); } else { window.BasalamToast.error(data.data?.message || "خطایی رخ داده است."); } location.reload(); }) .catch((error) => { console.error("Error:", error); window.BasalamToast.error("خطایی در ارسال رخ داده است."); if (quickBtn) quickBtn.disabled = false; if (fullBtn) fullBtn.disabled = false; if (clickedBtn) clickedBtn.innerHTML = originalText; }); } } function submitToServer(form, action, updateType = null) { const formData = new FormData(form); formData.append("action", action); const submitButton = form.querySelector('button[type="submit"]'); submitButton.disabled = true; submitButton.innerHTML = ' در حال ارسال...'; fetch(ajaxurl, { method: "POST", body: formData, }) .then((response) => response.json()) .then((data) => { closeModal(); if (data.success) { window.BasalamToast.success(data.data?.message || "عملیات با موفقیت آغاز شد."); } else { window.BasalamToast.error(data.data?.message || "خطایی رخ داده است."); } location.reload(); }) .catch((error) => { console.error("Error:", error); window.BasalamToast.error("خطایی در ارسال رخ داده است."); }) .finally(() => { submitButton.disabled = false; submitButton.innerHTML = ' انجام شد'; }); } document.querySelectorAll(".basalam-modal-close").forEach((btn) => { btn.addEventListener("click", closeModal); }); window.addEventListener("click", (event) => { if (event.target.classList.contains("basalam-modal")) { closeModal(); } }); document.addEventListener("keydown", (event) => { if (event.key === "Escape") { closeModal(); } }); const select = document.getElementById("basalam-sync-type"); if (select) { const customFields = document.getElementById("Basalam-custom-fields"); const settingsForm = select.closest("form"); const validationMessage = "در حالت سفارشی باید حداقل یک فیلد را برای بروزرسانی انتخاب کنید."; const toggleFields = (val) => { if (customFields) { customFields.style.display = val === "custom" ? "block" : "none"; } }; const hasSelectedCustomField = () => customFields && Array.from( customFields.querySelectorAll('input[type="checkbox"]') ).some((checkbox) => checkbox.checked); toggleFields(select.value); select.addEventListener("change", (e) => toggleFields(e.target.value)); if (settingsForm) { settingsForm.addEventListener("submit", (event) => { if (select.value !== "custom" || hasSelectedCustomField()) return; event.preventDefault(); event.stopImmediatePropagation(); if (window.BasalamToast) { window.BasalamToast.error(validationMessage); } if (customFields) { customFields.scrollIntoView({ behavior: "smooth", block: "center" }); customFields.querySelector('input[type="checkbox"]')?.focus(); } }, true); } } // Tab functionality for settings modal const initTabs = () => { const tabBtns = document.querySelectorAll(".basalam-tab-btn"); const tabContents = document.querySelectorAll(".basalam-tab-content"); tabBtns.forEach((btn) => { btn.addEventListener("click", () => { const tabId = btn.getAttribute("data-tab"); // Remove active class from all buttons and contents tabBtns.forEach((b) => b.classList.remove("active")); tabContents.forEach((c) => c.classList.remove("active")); // Add active class to clicked button and corresponding content btn.classList.add("active"); const content = document.getElementById(tabId); if (content) { content.classList.add("active"); } }); }); }; initTabs(); const initPointerOnboarding = () => { const pointerTour = window.basalamPointerTour; if ( !pointerTour || !Array.isArray(pointerTour.steps) || pointerTour.steps.length === 0 ) { return; } if ( typeof window.jQuery === "undefined" || typeof window.jQuery.fn.pointer !== "function" ) { return; } const steps = pointerTour.steps.filter( (step) => step && typeof step.selector === "string" && document.querySelector(step.selector) ); if (steps.length === 0) { return; } let completionRequested = false; const markTourCompleted = () => { if (completionRequested) { return; } completionRequested = true; if (!pointerTour.completeAction || !pointerTour.nonce) { return; } const formData = new FormData(); formData.append("action", pointerTour.completeAction); formData.append("nonce", pointerTour.nonce); fetch(ajaxurl, { method: "POST", body: formData, }).catch(() => {}); }; const openStep = (index) => { if (index >= steps.length) { markTourCompleted(); return; } const step = steps[index]; const $target = window.jQuery(step.selector).first(); if (!$target.length) { openStep(index + 1); return; } const targetElement = $target.get(0); if (targetElement && typeof targetElement.scrollIntoView === "function") { targetElement.scrollIntoView({ behavior: "smooth", block: "center" }); } let shouldAdvance = false; let shouldStop = false; $target .pointer({ pointerClass: "sync-basalam-pointer", content: step.content || "", position: step.position || { edge: "right", align: "middle" }, buttons: function (event, t) { const isLastStep = index === steps.length - 1; const skipLabel = step.skipLabel || "بستن"; const nextLabel = isLastStep ? step.doneLabel || "اتمام" : step.nextLabel || "بعدی"; const $skipButton = window.jQuery( '' ).text(skipLabel); const $nextButton = window.jQuery( '' ).text(nextLabel); $skipButton.on("click", function () { shouldStop = true; t.element.pointer("close"); }); $nextButton.on("click", function () { shouldAdvance = true; t.element.pointer("close"); }); return window.jQuery('
') .append($skipButton) .append($nextButton); }, close: function () { if (shouldStop) { markTourCompleted(); return; } if (shouldAdvance) { openStep(index + 1); return; } markTourCompleted(); }, }) .pointer("open"); }; openStep(0); }; initPointerOnboarding(); const initAnnouncementsPanel = () => { const announcementsConfig = window.basalamAnnouncements; if ( !announcementsConfig || !Array.isArray(announcementsConfig.items) || announcementsConfig.items.length === 0 ) { return; } const root = document.getElementById("sync-basalam-announcement-root"); const trigger = document.getElementById("sync-basalam-announcement-trigger"); const panel = document.getElementById("sync-basalam-announcement-panel"); const overlay = document.getElementById("sync-basalam-announcement-overlay"); const closeBtn = document.getElementById("sync-basalam-announcement-close"); const counter = document.getElementById("sync-basalam-announcement-counter"); const list = document.getElementById("sync-basalam-announcement-list"); const pageIndicator = document.getElementById("sync-basalam-announcement-page"); const prevBtn = document.getElementById("sync-basalam-announcement-prev"); const nextBtn = document.getElementById("sync-basalam-announcement-next"); if ( !root || !trigger || !panel || !overlay || !closeBtn || !counter || !list || !pageIndicator || !prevBtn || !nextBtn ) { return; } const normalizeItems = (rawItems) => rawItems .map((item) => { const files = Array.isArray(item?.files) ? item.files : []; const imageFile = files.find((f) => f?.url && /\.(png|jpe?g|gif|webp|svg)/i.test(f.url)); return { id: String(item?.id || ""), description: String(item?.description || ""), link: String(item?.link || "#"), linkText: String(item?.linkText || "ادامه"), image: imageFile ? String(imageFile.url) : (item?.image ? String(item.image) : ""), }; }) .filter((item) => item.id && item.description); let items = normalizeItems(announcementsConfig.items); if (items.length === 0) { root.remove(); return; } let currentPage = 1; let totalPages = Math.max(parseInt(announcementsConfig.totalPage, 10) || 1, 1); let isFetching = false; let seenIds = new Set( Array.isArray(announcementsConfig.seenIds) ? announcementsConfig.seenIds.map((id) => String(id)) : [] ); let seenRequested = false; const getUnreadCount = () => items.reduce((total, item) => total + (seenIds.has(item.id) ? 0 : 1), 0); const updateCounter = () => { const unreadCount = getUnreadCount(); counter.textContent = String(unreadCount); counter.classList.toggle( "sync-basalam-announcement-counter-hidden", unreadCount === 0 ); }; const renderItems = (pageItems) => { list.innerHTML = ""; pageItems.forEach((item) => { const card = document.createElement("article"); card.className = "sync-basalam-announcement-card" + (item.image ? "" : " sync-basalam-announcement-card-no-image") + (seenIds.has(item.id) ? " is-seen" : " is-unread"); if (item.image) { const imageWrapper = document.createElement("div"); imageWrapper.className = "sync-basalam-announcement-image-wrap"; const image = document.createElement("img"); image.className = "sync-basalam-announcement-image"; image.src = item.image; image.alt = "خبر ووسلام"; image.loading = "lazy"; imageWrapper.appendChild(image); card.appendChild(imageWrapper); } const content = document.createElement("div"); content.className = "sync-basalam-announcement-content"; const description = document.createElement("p"); description.className = "sync-basalam-announcement-text"; description.textContent = item.description; const link = document.createElement("a"); link.className = "sync-basalam-announcement-link"; link.href = item.link; link.textContent = item.linkText || "ادامه"; link.target = "_blank"; link.rel = "noopener noreferrer"; content.appendChild(description); if (item.link && item.link !== "#") { content.appendChild(link); } card.appendChild(content); list.appendChild(card); }); }; const updatePagination = () => { pageIndicator.textContent = `${currentPage} / ${totalPages}`; prevBtn.disabled = currentPage <= 1 || isFetching; nextBtn.disabled = currentPage >= totalPages || isFetching; }; const renderPage = () => { renderItems(items); updatePagination(); }; const fetchPage = (page) => { if (isFetching) { return; } isFetching = true; prevBtn.disabled = true; nextBtn.disabled = true; list.innerHTML = '