<!-- Google Tag Manager (noscript) --> <noscript><iframe src="/staging-disabled/analytics" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- eDesk widget 99x04c9ab --><script>(window._xsq||function(x,s){window._xsq=[];var c,b,a=document.createElement("iframe");a.src="javascript:false";a.title="";a.role="presentation";(a.frameElement||a).style.cssText="display: none";document.body.appendChild(a);try{b=a.contentWindow.document}catch(f){c=document.domain,a.src="javascript:var d=document.open();d.domain='"+c+"';void(0);",b=a.contentWindow.document}b.open()._l=function(){var a=this.createElement("script");c&&(this.domain=c);a.id="js-iframe-async";a.src="https://"+x+s;this.body.appendChild(a)};b.write('<body onload="document._l();">');b.close();return _xsq})("widgets.xsellco.com","/js/widgets.js").push(["load","99x04c9ab",document.scripts[document.scripts.length-1]]);</script><!-- End eDesk widget 99x04c9ab -->
<div class="jumbotron no-padding"> <div class="slider-bg"><img src="https://staging.diynation.co.uk/media/wysiwyg/homepage/mp-slider-bg.svg" alt="Slider Background" /></div> <div class="container navpro-expanded"></div> </div> <div class="jumbotron benefits"> <div class="container navpro-expanded"> <div class="benefits-top"> <div> <div class="icon"><i class="fa fa-truck" style="font-size: xx-large"></i></div> <div class="content"><p style="font-weight: bold; margin-bottom: 0">FREE SHIPPING OVER £29.99</p><p style="font-weight: 100; font-size: small; margin-bottom: 0">For order weights upto 10kg.</p></div> </div> <div> <div class="icon"><i class="fa fa-list-ol" style="font-size: xx-large"></i></div> <div class="content"><p style="font-weight: bold; margin-bottom: 0">WIDE RANGE</p><p style="font-weight: 100; font-size: small; margin-bottom: 0">Extensive array of products for every need.</p></div> </div> <div> <div class="icon"><i class="fa fa-clock-o" style="font-size: xx-large"></i></div> <div class="content"><p style="font-weight: bold; margin-bottom: 0">CUSTOMER SUPPORT 24x7</p><p style="font-weight: 100; font-size: small; margin-bottom: 0">Guaranteed resolution within 24 hours.</p></div> </div> <div> <div class="icon"><i class="fa fa-money" style="font-size: xx-large"></i></div> <div class="content"><p style="font-weight: bold; margin-bottom: 0">LOWEST PRICE POSSIBLE</p><p style="font-weight: 100; font-size: small; margin-bottom: 0">Special discounted prices on bulk orders.</p></div> </div> </div> </div> </div> <div class="jumbotron jumbotron-pastel jumbotron-overlap"> <div class="container"> <div class="element products-slider"> </div> <div class="element products-slider"> </div> <div class="block popular-categories"> <div class="block-title"> <strong role="heading" aria-level="2">Popular categories</strong> <p class="subtitle"> <a class="action view" href="https://staging.diynation.co.uk/departments/" title="View All"> <span>View All</span> </a> </p> </div> <div class="block-content" data-mage-init='{"Swissup_Swiper/js/swiper-wrapper": {"target": ".easycatalogimg", "loop": false, "slidesPerView": 5, "spaceBetween": 5, "breakpoints": {"1023": {"slidesPerView": 4}, "767": {"slidesPerView": 2}, "640": {"slidesPerView": 1}}}}'> </div> </div> <div class="block banners"> <div class="container a-center"> <!---->
</div> </div> <!--<div class="block apps a-center"> <div class="container"> <div class="apps-bg"> <img src="https://staging.diynation.co.uk/media/wysiwyg/homepage/apps/apps-bg.jpg" alt="Apps Background" /> </div> <div class="content"> <h2>Get the Mobile App</h2> <div class="info"> <p>Buy and sell anytime, anywhere</p> <p>and always make the best deals</p> </div> <a class="store-link" href="https://play.google.com/" title="Get on Google Play"><img src="https://staging.diynation.co.uk/media/wysiwyg/homepage/apps/google.svg" alt="Get on Google Play" /></a><a class="store-link" href="https://www.apple.com/app-store/" title="Download on the App Store"><img src="https://staging.diynation.co.uk/media/wysiwyg/homepage/apps/ios.svg" alt="Download on the App Store" /></a> </div> </div> </div>--> </div> </div> <!--<div class="jumbotron hero"> <div class="container"> <div class="element icon-text-top"> <div class="content"> <div class="item"> <div class="icon mp-icon mp-icon-big mp-cards"></div> <div class="info"> <h3 class="title">Pay with credit card or PayPal</h3> <div class="text"> <p>With our advanced payment module you can select the payment menthod that fits! And always secure!</p> <a href="https://staging.diynation.co.uk/payments/" title="More about payments">More about payments</a> </div> </div> </div> <div class="item"> <div class="icon mp-icon mp-icon-big mp-shipping"></div> <div class="info"> <h3 class="title">Free shipping starting at $50</h3> <div class="text"> <p>Benefit from our free shipping worldwide policy to get your products wherever you need them.</p> <a href="https://staging.diynation.co.uk/shipping/" title="More about shipping">More about shipping</a> </div> </div> </div> <div class="item"> <div class="icon mp-icon mp-icon-big mp-secure"></div> <div class="info"> <h3 class="title">Security, from start to finish</h3> <div class="text"> <p>We take security very seriously. This is why we don’t store your data and encrypt all transactions.</p> <a href="https://staging.diynation.co.uk/security/" title="More about security">More about security</a> </div> </div> </div> </div> </div> </div> </div>--> <div class="jumbotron hero"> <div class="container"> <div class="block row widget block-carousel"> <div class="block-title"> <strong>Browse brands</strong> </div> <div class="block-content"> <!--
There are no options matching the selection.
-->
</div> </div> </div> </div> <div class="jumbotron"> <div class="container"> <div class="block categories-bottom"> <div class="block-content"> </div> </div> </div> </div>
<style> @media screen and (min-width: 1280px) { .cms-index-index .jumbotron .navpro-expanded>div { margin-left: 0% !important; } } .cms-index-index .benefits-top .content { max-width: max-content !important; } @media (min-width: 768px) { .homepage-slider-mobile-view { display: none !important; } } @media (max-width: 767px) { .homepage-slider-desktop-view { display: none !important; } } </style>
<style> .parent-category-wrapper > .category-name.parent-category.parent-category-bottom { background: grey; text-align: left; } </style>
<style> @import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600&display=swap'); .powered-by strong { color: #2d7a3a; } .widget.open { display: flex; } @keyframes slideUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'DM Sans', sans-serif; } /* keep your full CSS below */ </style> <body> <div id="diynation-chat-widget"> <!-- Chat Bubble --> <button type="button" class="chat-bubble" id="chatBubble" onclick="toggleWidget()"> <span class="unread-badge" id="unreadBadge" style="display:none;">1</span> <svg class="chat-icon" viewBox="0 0 24 24"> <path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z"/> </svg> <svg class="close-icon" viewBox="0 0 24 24"> <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/> </svg> </button> <div class="widget" id="widget"> <div class="widget-header"> <div class="header-top"> <div> <div class="header-title">DIY Nation Support</div> <div class="header-subtitle"></div> </div> <button type="button" class="header-close" onclick="toggleWidget()">✕</button> </div> </div> <!-- Auth --> <div class="screen active" id="screenAuth"> <div class="auth-form"> <p class="welcome-text"> Hi there! Enter your details below to start a conversation with our support team. </p> <div class="form-group"> <label>Full Name *</label> <input type="text" id="customerName" placeholder="Enter your full name"> </div> <div class="form-group"> <label>Email Address *</label> <input type="email" id="customerEmail" placeholder="Enter your email"> </div> <div class="form-group"> <label>Your Message *</label> <input type="text" id="firstMessage" placeholder="How can we help you?"> </div> <div id="authError"></div> <button type="button" class="start-btn" onclick="startChat()"> Start Chat → </button> <p class="form-note"> We typically reply within a few minutes </p> </div> </div> <!-- Chat --> <div class="screen" id="screenChat"> <div class="chat-messages" id="chatMessages"></div> <div class="chat-input-area"> <textarea id="chatInput" class="chat-input" rows="1" placeholder="Type your message..." onkeydown="handleKey(event)" oninput="autoResize(this)"> </textarea> <button type="button" class="chat-send" onclick="sendMessage()"> <svg viewBox="0 0 24 24"> <path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/> </svg> </button> </div> <div class="powered-by"> Powered by <strong>VitaPoint</strong> </div> </div> <!-- Success --> <div class="screen" id="screenSuccess"> <div class="success-screen"> <div class="success-icon">✅</div> <div class="success-title"> Message Sent! </div> <div class="success-text"> Thanks! We've received your message and will get back to you shortly. </div> </div> <div class="powered-by"> Powered by <strong>VitaPoint</strong> </div> </div> </div> </div> </body> <script> // ================================ // CONFIG // ================================ const SERVER_URL = 'https://staging.diynation.co.uk/pub/proxy.php'; let widgetOpen = false; let sessionId = null; let customerData = {}; // ================================ const bubble = document.querySelector('.chat-bubble'); const widget = document.querySelector('.widget'); bubble.addEventListener('click', () => { bubble.classList.toggle('open'); widget.classList.toggle('open'); }); // ================================ // ================================ // TOGGLE WIDGET // ================================ function toggleWidget() { widgetOpen = !widgetOpen; const widget = document.getElementById('widget'); const bubble = document.getElementById('chatBubble'); if (widgetOpen) { widget.classList.add('open'); bubble.classList.add('open'); document.getElementById('unreadBadge').style.display = 'none'; } else { widget.classList.remove('open'); bubble.classList.remove('open'); } } // ================================ // SWITCH SCREEN // ================================ function showScreen(name) { document.querySelectorAll('.screen').forEach(s => s.classList.remove('active')); document.getElementById('screen' + name).classList.add('active'); } // ================================ // ENCRYPTION SETUP // ================================ const SECRET_KEY = 'DiyNation-Secret-Key-2024!!'; function encryptMessage(message) { try { const encrypted = CryptoJS.AES.encrypt(message, SECRET_KEY).toString(); return encrypted; } catch(e) { console.error('Encryption error:', e); return message; // Return original if encryption fails } } async function startChat() { // ✅ STEP 1: Get values FIRST const name = document.getElementById('customerName').value.trim(); const email = document.getElementById('customerEmail').value.trim(); const message = document.getElementById('firstMessage').value.trim(); const errEl = document.getElementById('authError'); // console.log(name); // console.log(email); // console.log(message); // console.log(errEl); // ✅ STEP 2: Validate if (!name || !email || !message) { errEl.textContent = 'Please fill in all fields.'; errEl.style.display = 'block'; return; } if (!email.includes('@')) { errEl.textContent = 'Please enter a valid email.'; errEl.style.display = 'block'; return; } errEl.style.display = 'none'; customerData = { name, email }; localStorage.setItem('diynation_customer_name', name); localStorage.setItem('diynation_customer_email', email); // ✅ STEP 3: Send to server try { const res = await fetch(SERVER_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, email, message, channel: 'diynation', source: 'diynation_website', url: window.location.href }) }); const text = await res.text(); // console.log("RAW RESPONSE:", text); if (!text) throw new Error("Empty response from server"); const data = JSON.parse(text); if (data.success) { sessionId = data.conv_id; lastMessageId = data.last_id ?? 0; // ✅ track last message ID } else { throw new Error(data.error || "API failed"); } } catch (e) { console.error('Send failed:', e); } // ✅ STEP 4: Show chat UI AFTER server call showScreen('Chat'); initChat(name, message); startPolling(); // ✅ only starts AFTER sessionId is set } // ================================ // INIT CHAT — Show first messages // ================================ function initChat(name, firstMsg) { const msgs = document.getElementById('chatMessages'); msgs.innerHTML = ''; // Customer first message appendCustomerMsg(firstMsg); // Bot auto reply after delay showTyping(); setTimeout(() => { hideTyping(); appendBotMsg(`Hey ${name}, while we wait for an agent to join the chat, how can we help you today?`); }, 1500); setTimeout(() => { appendSystem('chat'); }, 3000); } async function sendMessage() { const input = document.getElementById('chatInput'); const text = input.value.trim(); if (!text) return; input.value = ''; input.style.height = '38px'; appendCustomerMsg(text); // Send to server try { await fetch(SERVER_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: customerData.name, email: customerData.email, message: text, conv_id: sessionId, channel: 'diynation', source: 'diynation_website', url: window.location.href }) }); } catch(e) { console.error('Send failed:'); } } // ================================ // APPEND MESSAGES // ================================ function appendBotMsg(text) { const msgs = document.getElementById('chatMessages'); const now = new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}); const div = document.createElement('div'); div.innerHTML = ` <div class="msg-bot"> <div class="bot-avatar"></div> <div> <div class="bot-bubble">${text}</div> <div class="msg-time">${now}</div> </div> </div> `; msgs.appendChild(div); msgs.scrollTop = 9999; } function appendCustomerMsg(text) { const msgs = document.getElementById('chatMessages'); const now = new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}); const div = document.createElement('div'); div.innerHTML = ` <div class="msg-customer"> <div> <div class="customer-bubble">${text}</div> <div class="msg-time">${now}</div> </div> </div> `; msgs.appendChild(div); msgs.scrollTop = 9999; } // ------------------------------------------------------------- // ================================ // POLLING — check for agent replies // ================================ let lastMessageId = 0; let pollInterval = null; function startPolling() { // Poll every 4 seconds pollInterval = setInterval(pollMessages, 4000); } function stopPolling() { if (pollInterval) clearInterval(pollInterval); } async function pollMessages() { if (!sessionId) return; try { const res = await fetch('https://staging.diynation.co.uk/pub/proxy_get.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ conv_id: sessionId, after_id: lastMessageId }) }); const data = await res.json(); if (data.success && data.messages.length > 0) { data.messages.forEach(msg => { // Only show agent messages (customer msgs already shown instantly) if (msg.sender === 'agent') { appendAgentMsg(msg.message_body, msg.sent_at); } // Track highest ID so we only fetch new ones next time if (msg.id > lastMessageId) { lastMessageId = msg.id; } }); } } catch(e) { console.error('Poll failed:', e); } } function appendAgentMsg(text, sentAt) { const msgs = document.getElementById('chatMessages'); const time = sentAt ? new Date(sentAt).toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}) : new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}); const div = document.createElement('div'); div.innerHTML = ` <div class="msg-bot"> <div class="bot-avatar"></div> <div> <div class="bot-bubble">${text}</div> <div class="msg-time">${time}</div> </div> </div> `; msgs.appendChild(div); msgs.scrollTop = 9999; // Show unread badge if widget is closed if (!widgetOpen) { document.getElementById('unreadBadge').style.display = 'flex'; } } // ------------------------------------------------------------- function appendSystem(text) { const msgs = document.getElementById('chatMessages'); const div = document.createElement('div'); div.innerHTML = `<div class="msg-system"> ${text}</div>`; msgs.appendChild(div); msgs.scrollTop = 9999; } let typingEl = null; function showTyping() { const msgs = document.getElementById('chatMessages'); typingEl = document.createElement('div'); typingEl.innerHTML = ` <div class="typing-indicator"> <div class="bot-avatar"></div> <div class="typing-dots"> <div class="typing-dot"></div> <div class="typing-dot"></div> <div class="typing-dot"></div> </div> </div> `; msgs.appendChild(typingEl); msgs.scrollTop = 9999; } function hideTyping() { if (typingEl) { typingEl.remove(); typingEl = null; } } // ================================ // HELPERS // ================================ function handleKey(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); } } function autoResize(el) { el.style.height = '38px'; el.style.height = Math.min(el.scrollHeight, 100) + 'px'; } // Show unread badge after 5 seconds if widget not opened setTimeout(() => { if (!widgetOpen) { document.getElementById('unreadBadge').style.display = 'flex'; } }, 5000); </script>
<style> /* ================== OVERLAY WRAPPER ================== */ #delivery-overlay { position: fixed; right: 24px; bottom: 24px; width: 100%; max-width: 36rem; z-index: 99; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; font-family: inherit; } /* ================== CARD ================== */ #delivery-overlay .card { position: relative; display: flex; gap: 16px; padding: 16px 40px 16px 16px; border-radius: 16px; background: rgba(255,255,255,0.9); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border: 1px solid #e5e7eb; box-shadow: 0 20px 40px rgba(0,0,0,.15); overflow: hidden; } /* decorative blur */ #delivery-overlay .blur-bg { position: absolute; top: -40px; right: -40px; width: 96px; height: 96px; background: rgba(59,130,246,0.12); border-radius: 50%; filter: blur(32px); pointer-events: none; } /* ================== ICON ================== */ #delivery-overlay .icon-wrap { flex-shrink: 0; background: #dbeafe; color: #2563eb; padding: 10px; border-radius: 999px; } /* ================== TEXT ================== */ #delivery-overlay .content { display: flex; flex-direction: column; gap: 6px; } #delivery-overlay h3 { margin: 0; font-size: 1.4rem; font-weight: 700; color: #111827; display: flex; align-items: center; gap: 8px; } #delivery-overlay p { margin: 0; font-size: 1.4rem; color: #4b5563; line-height: 1.4; } #delivery-overlay .bold { font-weight: 700; color: #111827; } /* badge */ #delivery-overlay .badge { font-size: 10px; font-weight: 700; background: #2563eb; color: #fff; padding: 2px 6px 0; border-radius: 999px; text-transform: uppercase; letter-spacing: .08em; } /* timer row */ #delivery-overlay .timer { display: flex; align-items: center; gap: 6px; margin-top: 4px; font-size: 1rem; color: #6b7280; } /* ================== CLOSE BUTTON ================== */ #delivery-overlay .close-btn { position: absolute; top: 8px; right: 8px; width: 28px; height: 28px; border-radius: 999px; border: none; background: transparent; cursor: pointer; color: #9ca3af; display: flex; align-items: center; justify-content: center; } #delivery-overlay .close-btn:hover { background: #f3f4f6; color: #4b5563; } /* ================== ANIMATIONS ================== */ @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } #delivery-overlay.show { opacity: 1; pointer-events: auto; } #delivery-overlay.slide-in { animation: slideIn .5s cubic-bezier(.16,1,.3,1) forwards; } #delivery-overlay.fade-out { animation: fadeOut .3s ease forwards; } /* ================== MOBILE ================== */ @media (max-width: 480px) { #delivery-overlay { right: 12px; left: 12px; max-width: none; } } </style> <!-- ================== HTML ================== --> <div id="delivery-overlay"> <div class="card"> <div class="blur-bg"></div> <div class="icon-wrap"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2"/> <path d="M15 18H9"/> <path d="M19 18h2a1 1 0 0 0 1-1v-5l-4-4h-3v10a1 1 0 0 0 1 1Z"/> <circle cx="7" cy="18" r="2"/> <circle cx="17" cy="18" r="2"/> </svg> </div> <div class="content"> <h3> Fast Delivery <span class="badge">Next Day</span> </h3> <p> All orders placed before <span class="bold">5:30 PM</span> are delivered Next Day. </p> <div class="timer"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"/> <polyline points="12 6 12 12 16 14"/> </svg> <span id="delivery-timer">Time remaining: --h --m --s</span> </div> </div> <button class="close-btn" id="close-overlay" aria-label="Close"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"/> <path d="m6 6 12 12"/> </svg> </button> </div> </div> <script> document.addEventListener("DOMContentLoaded", function () { const overlay = document.getElementById('delivery-overlay'); const closeBtn = document.getElementById('close-overlay'); const timerEl = document.getElementById('delivery-timer'); if (!overlay || !closeBtn || !timerEl) return; // -------- show overlay -------- setTimeout(() => { overlay.classList.add('show', 'slide-in'); }, 1500); closeBtn.addEventListener('click', () => { overlay.classList.remove('slide-in'); overlay.classList.add('fade-out'); setTimeout(() => overlay.style.display = 'none', 300); }); // -------- UK TIME COUNTDOWN -------- function getUKNow() { const parts = new Intl.DateTimeFormat('en-GB', { timeZone: 'Europe/London', year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: false }).formatToParts(new Date()); const g = t => parts.find(p => p.type === t).value; return new Date(g('year'), g('month') - 1, g('day'), g('hour'), g('minute'), g('second')); } function updateTimer() { const now = getUKNow(); const cutoff = new Date(now); cutoff.setHours(17, 30, 0, 0); // 5:30 PM UK if (now >= cutoff) cutoff.setDate(cutoff.getDate() + 1); const diff = cutoff - now; if (diff <= 0) return; const s = Math.floor(diff / 1000); const h = Math.floor(s / 3600); const m = Math.floor((s % 3600) / 60); const sec = s % 60; timerEl.textContent = `Time remaining: ${String(h).padStart(2,'0')}h ` + `${String(m).padStart(2,'0')}m ` + `${String(sec).padStart(2,'0')}s`; } updateTimer(); setInterval(updateTimer, 1000); }); </script>