Товар-конфигуратор

0
Гарантия 2 года
Печать
На почту
Сохранить
Процессор
Процессор Intel Celeron G5905
OEM CM8070104292115
Артикул: 1200000
1шт.
4 450 ₽
Выбрать
Видеокарта
Процессор Intel Celeron G5905
OEM CM8070104292115
Артикул: 1200000
1шт.
4 450 ₽
Выбрать
Накопитель SSD
Процессор Intel Celeron G5905
OEM CM8070104292115
Артикул: 1200000
1шт.
4 450 ₽
Выбрать
Оперативная память
Процессор Intel Celeron G5905
OEM CM8070104292115
Артикул: 1200000
1шт.
4 450 ₽
Выбрать
Материнская плата
Процессор Intel Celeron G5905
OEM CM8070104292115
Артикул: 1200000
1шт.
4 450 ₽
Выбрать
Жёсткий диск
Процессор Intel Celeron G5905
OEM CM8070104292115
Артикул: 1200000
1шт.
4 450 ₽
Выбрать
Корпуса
Процессор Intel Celeron G5905
OEM CM8070104292115
Артикул: 1200000
1шт.
4 450 ₽
Выбрать
Блоки питания
Процессор Intel Celeron G5905
OEM CM8070104292115
Артикул: 1200000
1шт.
4 450 ₽
Выбрать
Услуга сборки и тестирования *
Процессор Intel Celeron G5905
OEM CM8070104292115
Артикул: 1200000
1шт.
4 450 ₽
'; const w = window.open('', '_blank', 'width=900,height=700,scrollbars=yes'); if (w) { w.document.write(html); w.document.close(); } else { sysmess.add('Разрешите всплывающие окна для печати', 'err'); } } document.querySelectorAll('.tools-options-block .tool-btn[data-action="print"]').forEach(function(btn) { btn.addEventListener('click', function() { openPrintWindow(); }); }); (function() { var emailModal = document.getElementById('configurator-email-modal'); var emailForm = document.getElementById('configurator-email-form'); var emailInput = document.getElementById('configurator-email-to'); var submitBtn = document.getElementById('configurator-email-submit'); if (!emailModal || !emailForm) return; function openEmailModal() { if (!isConfiguratorFilled()) { sysmess.add('Добавьте комплектующие', 'err'); return; } emailModal.setAttribute('aria-hidden', 'false'); emailForm.reset(); emailForm.querySelector('.field-error').textContent = ''; if (emailInput) emailInput.focus(); } function closeEmailModal() { emailModal.setAttribute('aria-hidden', 'true'); } document.querySelectorAll('.tools-options-block .tool-btn[data-action="email"]').forEach(function(btn) { btn.addEventListener('click', openEmailModal); }); emailModal.querySelectorAll('.configurator-email-close, .configurator-email-overlay').forEach(function(el) { el.addEventListener('click', closeEmailModal); }); emailForm.addEventListener('submit', function(e) { e.preventDefault(); var email = (emailInput && emailInput.value) ? emailInput.value.trim() : ''; var comment = (document.getElementById('configurator-email-comment') && document.getElementById('configurator-email-comment').value) ? document.getElementById('configurator-email-comment').value.trim() : ''; var errEl = emailForm.querySelector('.field-error'); if (!email) { if (errEl) errEl.textContent = 'Укажите email'; return; } var re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!re.test(email)) { if (errEl) errEl.textContent = 'Некорректный email'; return; } if (errEl) errEl.textContent = ''; submitBtn.disabled = true; submitBtn.textContent = 'Отправка...'; var nonce = 'b9e944b601'; fetch(ajax_obj.ajax_url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ action: 'configurator_send_email', email: email, comment: comment, configurator_data: JSON.stringify(window.configuratorState), _wpnonce: nonce }) }) .then(function(res) { return res.json(); }) .then(function(data) { submitBtn.disabled = false; submitBtn.textContent = 'Отправить'; if (data.success) { closeEmailModal(); sysmess.add('Конфигурация отправлена на ' + email, 'sys'); } else { if (emailForm.querySelector('.field-error')) emailForm.querySelector('.field-error').textContent = (data.data && data.data.message) ? data.data.message : 'Ошибка отправки'; } }) .catch(function() { submitBtn.disabled = false; submitBtn.textContent = 'Отправить'; if (emailForm.querySelector('.field-error')) emailForm.querySelector('.field-error').textContent = 'Ошибка сети'; }); }); })(); (function() { var saveModal = document.getElementById('configurator-save-modal'); var saveLinkInput = document.getElementById('configurator-save-link-input'); var saveCopyBtn = document.getElementById('configurator-save-copy-btn'); var saveBackBtn = document.getElementById('configurator-save-back-btn'); var saveCloseBtn = saveModal && saveModal.querySelector('.configurator-save-close'); var saveOverlay = saveModal && saveModal.querySelector('.configurator-save-overlay'); function getSaveLink() { var state = JSON.stringify(window.configuratorState); var base64 = btoa(unescape(encodeURIComponent(state))).replace(/\+/g, '-').replace(/\//g, '_'); return window.location.origin + window.location.pathname + '?config=' + base64; } function copySaveLink() { if (!saveLinkInput || !saveLinkInput.value) return; if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(saveLinkInput.value).then(function() { sysmess.add('Ссылка на конфигуратор скопирована в буфер обмена', 'sys'); }).catch(function() { sysmess.add('Ссылка: ' + saveLinkInput.value, 'info'); }); } else { sysmess.add('Ссылка: ' + saveLinkInput.value, 'info'); } } function openSaveModal() { if (!isConfiguratorFilled()) { sysmess.add('Добавьте комплектующие', 'err'); return; } var url = getSaveLink(); if (saveLinkInput) saveLinkInput.value = url; if (saveModal) saveModal.setAttribute('aria-hidden', 'false'); copySaveLink(); } function closeSaveModal() { if (saveModal) saveModal.setAttribute('aria-hidden', 'true'); } var saveBtn = document.querySelector('.tools-options-block .tool-btn[data-action="save"]'); if (saveBtn) saveBtn.addEventListener('click', openSaveModal); if (saveCopyBtn) saveCopyBtn.addEventListener('click', copySaveLink); if (saveBackBtn) saveBackBtn.addEventListener('click', closeSaveModal); if (saveCloseBtn) saveCloseBtn.addEventListener('click', closeSaveModal); if (saveOverlay) saveOverlay.addEventListener('click', closeSaveModal); })(); window.configuratorBlockMeta = { "proc": { max_count: 1 }, "videocard": { max_count: 1 }, "ssd": { max_count: 1 }, "ram": { max_count: 4 }, "board": { max_count: 1 }, "hdd": { max_count: 1 }, "box": { max_count: 1 }, "power": { max_count: 1 }, "service": { max_count: 1 }, }; var CONFIGURATOR_STORAGE_KEY = 'configurator_state_374578'; function getSlotEntries(slot) { var v = window.configuratorState[slot]; if (!v) return []; return Array.isArray(v) ? v : (v && v.id ? [v] : []); } function syncConfiguratorData() { var input = document.querySelector('input[name="configurator_data"]'); if (input) input.value = JSON.stringify(window.configuratorState); try { localStorage.setItem(CONFIGURATOR_STORAGE_KEY, JSON.stringify(window.configuratorState)); } catch (e) {} } window.configuratorState = { main: 374578, "proc": [],"videocard": [],"ssd": [],"ram": [],"board": [],"hdd": [],"box": [],"power": [],"service": [], }; (function() { var params = new URLSearchParams(window.location.search); var configParam = params.get('config'); var stored = null; if (configParam) { try { stored = JSON.parse(decodeURIComponent(escape(atob(configParam.replace(/-/g, '+').replace(/_/g, '/'))))); } catch (e) {} } if (!stored || !stored.main) { try { var raw = localStorage.getItem(CONFIGURATOR_STORAGE_KEY); if (raw) stored = JSON.parse(raw); } catch (e) {} } if (stored && stored.main) { window.configuratorState.main = stored.main; for (var s in window.configuratorState) { if (s === 'main') continue; if (stored[s] != null) { window.configuratorState[s] = Array.isArray(stored[s]) ? stored[s] : (stored[s] && stored[s].id ? [stored[s]] : []); } } syncConfiguratorData(); window.configuratorRestoredFromStorage = true; } })(); function escapeHtml(s) { if (s == null) return ''; var str = String(s); return str.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } function fetchProductPreview(productId) { if (window.productPriceCache && window.productPriceCache[productId] && window.productNameCache && window.productNameCache[productId]) { return Promise.resolve({ name: window.productNameCache[productId], price: window.productPriceCache[productId], price_html: (window.productPriceCache[productId]).toLocaleString('ru-RU') + ' ₽', image: '', sku: '—' }); } return fetch('/wp-admin/admin-ajax.php?action=get_product_preview&product_id=' + productId) .then(function(res) { return res.json(); }) .then(function(data) { if (!data.success) throw new Error('Нет данных'); window.productPriceCache[productId] = data.data.price; window.productNameCache[productId] = data.data.name || ''; return { name: data.data.name, price: data.data.price, price_html: data.data.price_html || (data.data.price + ' ₽'), image: data.data.image || '', sku: data.data.sku || '—' }; }); } function renderSlot(slot) { var slotContainer = document.querySelector('.configurator-slot[data-slot="' + slot + '"]'); if (!slotContainer) return Promise.resolve(); var preview = slotContainer.querySelector('.slot-preview'); var itemCost = slotContainer.querySelector('.item-cost .item-price'); var entries = getSlotEntries(slot); if (entries.length === 0) { if (preview) preview.innerHTML = ''; if (itemCost) itemCost.innerHTML = ''; slotContainer.classList.remove('active'); slotContainer.dataset.count = 0; updateTotalPrice(); return Promise.resolve(); } var promises = entries.map(function(entry, idx) { return fetchProductPreview(entry.id).then(function(r) { return { r: r, entry: entry, idx: idx }; }); }); var maxCount = window.configuratorBlockMeta[slot] && window.configuratorBlockMeta[slot].max_count ? window.configuratorBlockMeta[slot].max_count : 1; var totalInSlot = entries.reduce(function(sum, e) { return sum + (e.count || 1); }, 0); return Promise.all(promises).then(function(results) { var html = ''; var slotTotal = 0; results.forEach(function(o) { var r = o.r, entry = o.entry, idx = o.idx; var count = entry.count || 1; var lineTotal = r.price * count; slotTotal += lineTotal; var qtyBlock = ''; if (maxCount > 1) { var canPlus = totalInSlot < maxCount; qtyBlock = '
' + count + '
'; } else { qtyBlock = '
1
'; } var imgSrc = (r.image && r.image.trim()) ? r.image : 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"%3E%3Crect fill="%23f0f0f0" width="48" height="48"/%3E%3C/svg%3E'; html += '
' + escapeHtml(r.name) + '
Артикул: ' + escapeHtml(r.sku) + '
' + qtyBlock + '
'; }); if (preview) preview.innerHTML = html; if (itemCost) itemCost.innerHTML = slotTotal.toLocaleString('ru-RU') + ' ₽'; slotContainer.classList.add('active'); slotContainer.dataset.count = entries.length; updateTotalPrice(); }).catch(function(err) { console.error(err); sysmess.add('Не удалось загрузить товар', 'err'); }); } document.addEventListener('click', function(e) { var removeBtn = e.target.closest('.slot-preview-item-remove'); if (removeBtn) { e.preventDefault(); var slot = removeBtn.getAttribute('data-slot'); var idx = parseInt(removeBtn.getAttribute('data-index'), 10); if (slot == null || isNaN(idx)) return; var entries = getSlotEntries(slot); if (idx < 0 || idx >= entries.length) return; entries.splice(idx, 1); window.configuratorState[slot] = entries; syncConfiguratorData(); renderSlot(slot); sysmess.add('Позиция удалена', 'info'); return; } var minusBtn = e.target.closest('.slot-qty-minus'); if (minusBtn) { e.preventDefault(); var slot = minusBtn.getAttribute('data-slot'); var idx = parseInt(minusBtn.getAttribute('data-index'), 10); if (slot == null || isNaN(idx)) return; var entries = getSlotEntries(slot); if (idx < 0 || idx >= entries.length) return; var entry = entries[idx]; var c = (entry.count || 1) - 1; if (c < 1) { entries.splice(idx, 1); sysmess.add('Позиция удалена', 'info'); } else { entry.count = c; } window.configuratorState[slot] = entries; syncConfiguratorData(); renderSlot(slot); return; } var plusBtn = e.target.closest('.slot-qty-plus'); if (plusBtn && !plusBtn.disabled) { e.preventDefault(); var slot = plusBtn.getAttribute('data-slot'); var idx = parseInt(plusBtn.getAttribute('data-index'), 10); if (slot == null || isNaN(idx)) return; var entries = getSlotEntries(slot); if (idx < 0 || idx >= entries.length) return; var maxCount = window.configuratorBlockMeta[slot] && window.configuratorBlockMeta[slot].max_count ? window.configuratorBlockMeta[slot].max_count : 1; var totalInSlot = entries.reduce(function(sum, e) { return sum + (e.count || 1); }, 0); if (totalInSlot >= maxCount) return; var entry = entries[idx]; entry.count = (entry.count || 1) + 1; window.configuratorState[slot] = entries; syncConfiguratorData(); renderSlot(slot); } }); window.addEventListener('message', function(event) { if (event.data.action === 'catalog_iframe_loaded') { var slot = event.data.slot; var entries = slot ? getSlotEntries(slot) : []; var selectedForSlot = entries.map(function(e) { return { id: e.id, count: e.count || 1 }; }); var maxCount = (slot && window.configuratorBlockMeta[slot]) ? (window.configuratorBlockMeta[slot].max_count || 1) : 1; if (event.source) { event.source.postMessage({ action: 'configurator_selected_for_slot', selectedForSlot: selectedForSlot, maxCount: maxCount }, '*'); } return; } if (event.data.action === 'configurator_set_quantity' && event.source) { var slot = event.data.slot; var productId = event.data.productId; var delta = event.data.delta; if (!slot || productId == null || delta == null) return; var entries = getSlotEntries(slot); var idx = entries.findIndex(function(e) { return e.id == productId; }); if (idx < 0) return; var maxCount = window.configuratorBlockMeta[slot] && window.configuratorBlockMeta[slot].max_count ? window.configuratorBlockMeta[slot].max_count : 1; var totalInSlot = entries.reduce(function(sum, e) { return sum + (e.count || 1); }, 0); if (delta > 0 && totalInSlot >= maxCount) return; var entry = entries[idx]; var c = (entry.count || 1) + delta; if (c < 1) { entries.splice(idx, 1); } else { entry.count = c; } window.configuratorState[slot] = entries; syncConfiguratorData(); renderSlot(slot).then(function() { var selectedForSlot = getSlotEntries(slot).map(function(e) { return { id: e.id, count: e.count || 1 }; }); event.source.postMessage({ action: 'configurator_selected_for_slot', selectedForSlot: selectedForSlot, maxCount: maxCount }, '*'); }); return; } if (event.data.action !== 'configurator_item_selected') return; var slot = event.data.slot; var productId = event.data.productId; if (!(slot in window.configuratorState) || slot === 'main') { sysmess.add('Недопустимый слот: ' + slot, 'err'); return; } var slotContainer = document.querySelector('.configurator-slot[data-slot="' + slot + '"]'); if (!slotContainer) { sysmess.add('Контейнер слота не найден', 'err'); return; } var maxCount = window.configuratorBlockMeta[slot] && window.configuratorBlockMeta[slot].max_count ? window.configuratorBlockMeta[slot].max_count : 1; var entries = getSlotEntries(slot); var existing = entries.find(function(e) { return e.id == productId; }); if (existing && slot === 'ram') { existing.count = Math.min((existing.count || 1) + 1, maxCount); } else if (existing) { sysmess.add('Товар уже добавлен в этот слот', 'info'); return; } else if (entries.length >= maxCount) { sysmess.add('Достигнут лимит позиций для этого слота', 'err'); return; } else { entries.push({ id: productId, count: 1 }); } window.configuratorState[slot] = entries; syncConfiguratorData(); var label = slotContainer.dataset.label || slot; sysmess.add('Добавлено: ' + label, 'sys'); renderSlot(slot); }); if (window.configuratorRestoredFromStorage) { window.configuratorRestoredFromStorage = false; for (var s in window.configuratorState) { if (s === 'main') continue; if (getSlotEntries(s).length > 0) renderSlot(s); } } var ajax_obj = { ajax_url: 'https://hardcomp.ru/wp-admin/admin-ajax.php' }; var isSubmitting = false; let isSubmitted = false; // флаг успешной отправки function isConfiguratorFilled() { for (var slot in window.configuratorState) { if (slot === 'main') continue; if (getSlotEntries(slot).length > 0) return true; } return false; } function send_cart() { // Проверка: заполнена ли сборка? if (!isConfiguratorFilled()) { sysmess.add('Выберите хотя бы один комплектующий', 'err'); return; } if (isSubmitting || isSubmitted) { return; } isSubmitting = true; const btn = this; const originalText = btn.textContent; btn.textContent = 'Отправка...'; btn.disabled = true; // ... отправка fetch ... const bundleProductId = 374578; // ID текущего товара const configuratorData = JSON.stringify(window.configuratorState); var configuratorNonce = 'ed7281174c'; fetch(ajax_obj.ajax_url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ action: 'add_configurator_bundle', bundle_product_id: bundleProductId, configurator_data: configuratorData, _wpnonce: configuratorNonce }) }) .then(res => res.json()) .then(response => { if (response.success) { isSubmitted = true; // ← флаг успеха btn.textContent = 'Заказ отправлен'; sysmess.add('Сборка добавлена в корзину!', 'sys'); // Обновить фрагменты корзины (мини-корзина, иконка) if (window.jQuery) { jQuery(document.body).trigger('wc_fragment_refresh'); } } else { // Возврат кнопки при ошибке btn.textContent = originalText; btn.disabled = false; sysmess.add('Ошибка: ' + (response.data?.message || 'неизвестно'), 'err'); console.log(JSON.stringify(response, null, 2)); } }) .catch(err => { btn.textContent = originalText; btn.disabled = false; sysmess.add('Ошибка сети', 'err'); }) .finally(() => { isSubmitting = false; }); } const configuratorForm = document.getElementById('configurator-form'); if (configuratorForm) { configuratorForm.addEventListener('submit', function(e) { e.preventDefault(); const input = this.querySelector('input[name="configurator_data"]'); if (input) input.value = JSON.stringify(window.configuratorState); const btn = e.submitter || this.querySelector('#submit-configurator'); if (btn && typeof send_cart === 'function') send_cart.call(btn); }); }