// This script will run after the HTML document has been fully loaded and parsed. document.addEventListener("DOMContentLoaded", () => { // =================================================================== // Element Selectors // =================================================================== const siteHeader = document.querySelector(".site-header"); const menuToggleBtn = document.getElementById("universalMenuToggleBtnMobile"); const fullscreenMenu = document.getElementById("fullscreenMenuRestored"); const closeMenuBtn = document.getElementById("closeFullscreenMenuBtn"); const headerCartBadge = document.getElementById("headerCartBadge"); const mobileCartBadge = document.getElementById("mobileCartBadge"); const whatsAppFabGroup = document.getElementById("whatsAppFabGroup"); const showChatBubble = document.getElementById("showChatBubble"); const closeWhatsAppFab = document.getElementById("closeWhatsAppFab"); const accessoriesBtn = document.getElementById("accessoriesBtn"); const accessoriesOverlay = document.getElementById("accessoriesOverlay"); const closeAccessoriesOverlayBtn = document.getElementById("closeAccessoriesOverlayBtn"); const cancelAccessoriesBtn = document.getElementById("cancelAccessoriesBtn"); const addAccessoriesToBuildBtn = document.getElementById("addAccessoriesToBuildBtn"); const pickCharacterBtn = document.getElementById("pickCharacterBtn"); const pickCharacterOverlay = document.getElementById("pickCharacterOverlay"); const closePickCharacterOverlayBtn = document.getElementById("closePickCharacterOverlayBtn"); const submitCharacterBtn = document.getElementById("submitCharacterBtn"); const reviewSubmitBtn = document.getElementById("reviewSubmitBtn"); const reviewSubmissionOverlay = document.getElementById("reviewSubmissionOverlay"); const closeReviewSubmissionOverlayBtn = document.getElementById("closeReviewSubmissionOverlayBtn"); const reviewForm = document.getElementById("reviewForm"); const cancelReviewBtn = document.getElementById("cancelReviewBtn"); const toggleReviewsBtn = document.getElementById("toggleReviewsBtn"); const selectCaseButton = document.getElementById("selectCaseButton"); const caseSelectionOverlay = document.getElementById("caseSelectionOverlay"); const closeCaseSelectionOverlayBtn = document.getElementById("closeCaseSelectionOverlayBtn"); const overlayCaseGrid = document.getElementById("overlayCaseGrid"); const imageLightbox = document.getElementById("imageLightbox"); const lightboxContent = document.getElementById("lightboxContent"); const lightboxClose = document.getElementById("lightboxClose"); const addOnsListDisplay = document.getElementById("addOnsList"); const upgradesListDisplay = document.getElementById("upgradesList"); const casePreviewModal = document.getElementById("casePreviewModal"); const casePreviewImage = document.getElementById("casePreviewImage"); const cancelCasePreviewBtn = document.getElementById("cancelCasePreviewBtn"); const selectCasePreviewBtn = document.getElementById("selectCasePreviewBtn"); const readMoreBtn = document.getElementById("readMoreBtn"); const mobileDescriptionMore = document.getElementById("mobileDescriptionMore"); // =================================================================== // State and Configuration // =================================================================== let cartItems = []; let selectedAddOns = {}; let selectedCaseIdForPreview = null; const caseUpgradeBasePrice = 15; // JAVASCRIPT UPDATE: All case image paths updated to new directory structure const allCases = [ { id: "mastercase_620h", name: "MasterCase 620H", price: 15, imageUrl: "/img/cases/MasterCase_620H.webp", specialOffer: false }, { id: "mastercase_240h", name: "MasterCase 240H", price: 0, imageUrl: "/img/cases/MasterCase_240H.webp", specialOffer: false }, { id: "aerocool_cs107", name: "Aerocool CS-107 v2 FRGB", price: 15, imageUrl: "/img/cases/Aerocool_CS-107_v2_FRGB.webp", specialOffer: false }, { id: "powertrain_flying", name: "Power Train Flying", price: 15, imageUrl: "/img/cases/Power_Train_Flying.webp", specialOffer: false }, { id: "mastercase_500h", name: "MasterCase 500H", price: 30, imageUrl: "/img/cases/MasterCase_500H.webp", specialOffer: true }, { id: "powertrain_illusionary", name: "Power Train Illusionary Realm", price: 34, imageUrl: "/img/cases/Power_Train_Illusionary_Realm.webp", specialOffer: false }, { id: "aerocool_p500c", name: "Aerocool P500C", price: 35, imageUrl: "/img/cases/Aerocool_P500C.webp", specialOffer: true }, { id: "gamdias_atlas_e1", name: "GAMDIAS ATLAS E1", price: 39, imageUrl: "/img/cases/GAMDIAS_ATLAS_E1.webp", specialOffer: false }, { id: "foifkin_x01", name: "FOIFKIN X01", price: 40, imageUrl: "/img/cases/FOIFKIN_X01.webp", specialOffer: false }, { id: "jonsbo_c6", name: "Jonsbo C6 Mesh", price: 40, imageUrl: "/img/cases/Jonsbo_C6_Mesh.webp", specialOffer: false }, { id: "ionz_kzz", name: "IONZ KZ-Z (Dual-Chamber)", price: 42, imageUrl: "/img/cases/IONZ_KZ-Z_Dual-Chamber.webp", specialOffer: false }, { id: "ionz_apex", name: "IONZ APEX (Black Rainbow)", price: 46, imageUrl: "/img/cases/IONZ_APEX_Black_Rainbow.webp", specialOffer: false }, { id: "ionz_kzze", name: "IONZ KZ-ZE-B (White)", price: 47, imageUrl: "/img/cases/IONZ_KZ-ZE-B_White.webp", specialOffer: false }, { id: "corsair_3000d", name: "CORSAIR 3000D Airflow", price: 47, imageUrl: "/img/cases/CORSAIR_3000D_Airflow.webp", specialOffer: false }, { id: "antec_cx800", name: "Antec CX800 Wood ARGB", price: 48, imageUrl: "/img/cases/Antec_CX800_Wood_ARGB.webp", specialOffer: false }, { id: "antec_cx600m", name: "Antec CX600M Wood", price: 49, imageUrl: "/img/cases/Antec_CX600M_Wood.webp", specialOffer: false }, { id: "powertrain_n5", name: "Power Train N5", price: 52, imageUrl: "/img/cases/Power_Train_N5.webp", specialOffer: false }, { id: "antec_c8", name: "Antec C8 Curve Wood", price: 70, imageUrl: "/img/cases/Antec_C8_Curve_Wood.webp", specialOffer: false }, { id: "ssupd_xhuttle", name: "SSUPD XHUTTLE", price: 80, imageUrl: "/img/cases/SSUPD_XHUTTLE.webp", specialOffer: false }, { id: "valkyrie_vk03", name: "Valkyrie VK03", price: 120, imageUrl: "/img/cases/Valkyrie_VK03.webp", specialOffer: true } ]; const caseOptions = allCases.map(c => ({ ...c, upgradePrice: Math.max(0, c.price - caseUpgradeBasePrice) })); const basePrice = 1295.49; // JAVASCRIPT UPDATE: Default case image path updated let currentBuild = { cpu: { id: "cpu-base", name: "Ryzen 9 9700X", price: 0 }, gpu: { id: "gpu-base-7900xt", name: "Radeon RX 7900 XT", price: 0 }, ram: { id: "ram-base-32gb", name: "32 GB DDR5", price: 0 }, storage: { id: "storage-base-1tb", name: "1 TB NVMe SSD", price: 0 }, case: { id: "mastercase_620h", name: "MasterCase 620H", price: 0, upgradePrice: 0, imageUrl: "/img/products/thor-hero-desktop.webp" }, os: { name: "Windows 11 Pro" }, warranty: { name: "2 Years" } }; const componentUpgrades = { cpu: [ { id: "cpu-base", name: "Ryzen 9 9700X", price: 0, displayPrice: "Included" }, { id: "cpu-upgrade-9800x", name: "Ryzen 9 9800X3D", price: 150, displayPrice: "+£150.00" } ], gpu: [ { id: "gpu-base-7900xt", name: "Radeon RX 7900 XT", price: 0, displayPrice: "Included" }, { id: "gpu-sidegrade-4070s", name: "RTX 4070 Super", price: -20, displayPrice: "-£20.00" }, { id: "gpu-upgrade-4080", name: "RTX 4080", price: 100, displayPrice: "+£100.00" } ], ram: [ { id: "ram-base-32gb", name: "32 GB DDR5", price: 0, displayPrice: "Included" }, { id: "ram-upgrade-64gb", name: "64 GB DDR5", price: 90, displayPrice: "+£90.00" } ], storage: [ { id: "storage-base-1tb", name: "1 TB NVMe SSD", price: 0, displayPrice: "Included" }, { id: "storage-upgrade-2tb", name: "2 TB SSD", price: 60, displayPrice: "+£60.00" }, { id: "storage-upgrade-4tb", name: "4 TB SSD", price: 120, displayPrice: "+£120.00" } ] }; // =================================================================== // Cart Functions // =================================================================== function loadCartFromStorage() { const storedCart = localStorage.getItem("masterRaceCartItems"); if (storedCart) { try { cartItems = JSON.parse(storedCart); if (!Array.isArray(cartItems)) { cartItems = []; } } catch (error) { console.error("Error parsing cart items from localStorage", error); cartItems = []; } } updateCartBadge(); } function updateCartBadge() { // Try to get cached count first for performance let totalItems = parseInt(localStorage.getItem("masterRaceCartCount")) || 0; // Verify cache is still accurate (fallback safety check) const actualTotal = cartItems.reduce((sum, item) => sum + (item.quantity || 1), 0); if (totalItems !== actualTotal) { totalItems = actualTotal; localStorage.setItem("masterRaceCartCount", totalItems.toString()); } [headerCartBadge, mobileCartBadge].forEach(badge => { if (badge) { badge.textContent = totalItems; badge.style.display = totalItems > 0 ? "inline-block" : "none"; } }); } function updateCartCount() { const totalItems = cartItems.reduce((sum, item) => sum + (item.quantity || 1), 0); localStorage.setItem("masterRaceCartCount", totalItems.toString()); return totalItems; } // =================================================================== // UI Interaction Functions // =================================================================== function toggleOverlay(overlay, triggerElement, focusOnOpen) { if (!overlay) return; const isOpen = overlay.classList.toggle("open"); document.body.classList.toggle("no-scroll", isOpen); document.documentElement.classList.toggle("no-scroll", isOpen); if (isOpen) { overlay.scrollTop = 0; // Reset scroll position on open if (focusOnOpen) focusOnOpen.focus(); } else { if (triggerElement) triggerElement.focus(); } } function showInfoMessage(message) { const overlay = document.getElementById("infoMessageOverlay"); const textElement = document.getElementById("infoMessageText"); const closeBtn = document.getElementById("infoMessageCloseBtn"); if (overlay && textElement && closeBtn) { textElement.textContent = message; overlay.style.display = "flex"; closeBtn.onclick = () => { overlay.style.display = "none"; }; } else { // Fallback for environments where the elements might not exist alert(message); } } function setupGlobalEventListeners() { // Fullscreen Menu Toggle if (menuToggleBtn) { menuToggleBtn.addEventListener("click", (e) => { e.preventDefault(); menuToggleBtn.classList.toggle("active"); toggleOverlay(fullscreenMenu, menuToggleBtn, closeMenuBtn); }); } if (closeMenuBtn) { closeMenuBtn.addEventListener("click", () => { menuToggleBtn.classList.remove("active"); toggleOverlay(fullscreenMenu, menuToggleBtn, menuToggleBtn); }); } if (fullscreenMenu) { fullscreenMenu.addEventListener("click", (e) => { if (e.target === fullscreenMenu) { menuToggleBtn.classList.remove("active"); toggleOverlay(fullscreenMenu, menuToggleBtn, menuToggleBtn); } }); } document.addEventListener("keydown", (e) => { if (e.key === "Escape" && fullscreenMenu?.classList.contains("open")) { menuToggleBtn.classList.remove("active"); toggleOverlay(fullscreenMenu, menuToggleBtn, menuToggleBtn); } }); // WhatsApp FAB Toggle if (whatsAppFabGroup && showChatBubble && closeWhatsAppFab) { closeWhatsAppFab.addEventListener("click", () => { whatsAppFabGroup.classList.add("hidden"); showChatBubble.classList.remove("hidden"); }); showChatBubble.addEventListener("click", () => { whatsAppFabGroup.classList.remove("hidden"); showChatBubble.classList.add("hidden"); }); } } function setupHeaderScrollBehavior() { let lastScrollTop = 0; window.addEventListener("scroll", () => { if (window.innerWidth <= 767) { // Only on mobile let scrollTop = window.pageYOffset || document.documentElement.scrollTop; if (scrollTop > lastScrollTop && scrollTop > siteHeader.offsetHeight) { siteHeader.classList.add("header-hidden"); } else { siteHeader.classList.remove("header-hidden"); } lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; } else { siteHeader.classList.remove("header-hidden"); } }, false); } // =================================================================== // Product Page Specific Functions // =================================================================== function initializeProductPage() { setupProductPageEventListeners(); updateAllDisplays(); initializeConfigurator(); } function setupProductPageEventListeners() { if(readMoreBtn) { readMoreBtn.addEventListener("click", () => { mobileDescriptionMore.classList.toggle("show"); readMoreBtn.textContent = mobileDescriptionMore.classList.contains("show") ? "Read Less" : "Read More"; }); } document.body.addEventListener("click", (e) => { const thumbnail = e.target.closest(".product-image-thumbnails img"); if (thumbnail) { const baseName = thumbnail.dataset.largeImgBase; const desktopHero = document.getElementById('mainProductImageDesktop'); const mobileHero = document.getElementById('mainProductImageMobile'); if(baseName && desktopHero && mobileHero){ let mobileSrc = `/img/mobile-products/${baseName}-mobile.webp`; let desktopSrc = `/img/products/${baseName}-desktop.webp`; // Handle the main hero image which has a different naming convention if (baseName === 'thor-hero') { mobileSrc = '/img/mobile-products/herothor.webp'; desktopSrc = '/img/products/thor-hero-desktop.webp'; } desktopHero.src = desktopSrc; mobileHero.src = mobileSrc; } document.querySelectorAll(".product-image-thumbnails img").forEach(img => img.classList.remove("active-thumbnail")); thumbnail.classList.add("active-thumbnail"); } if (e.target.classList.contains("product-hero-image")) { if(lightboxContent) { lightboxContent.src = e.target.src; } toggleOverlay(imageLightbox, e.target, lightboxClose); } else if (e.target.id === "lightboxClose") { toggleOverlay(imageLightbox, null, lightboxClose); } else if (e.target.id === "addToCartBtn") { handleAddToCart(); } else if (e.target.id === "buyNowBtn") { handleAddToCart(); setTimeout(() => { window.location.href = "checkout.html"; }, 100); } else if (e.target.id === "accessoriesBtn") { toggleOverlay(accessoriesOverlay, accessoriesBtn, closeAccessoriesOverlayBtn); } else if (e.target.id === "closeAccessoriesOverlayBtn" || e.target.id === "cancelAccessoriesBtn") { toggleOverlay(accessoriesOverlay, accessoriesBtn, closeAccessoriesOverlayBtn); } else if (e.target.id === "addAccessoriesToBuildBtn") { handleAddAccessories(); } else if (e.target.id === "pickCharacterBtn") { toggleOverlay(pickCharacterOverlay, pickCharacterBtn, closePickCharacterOverlayBtn); } else if (e.target.id === "closePickCharacterOverlayBtn") { toggleOverlay(pickCharacterOverlay, pickCharacterBtn, closePickCharacterOverlayBtn); } else if (e.target.id === "submitCharacterBtn") { handleSubmitCharacter(); } else if (e.target.id === "submitReviewBtn") { toggleOverlay(reviewSubmissionOverlay, reviewSubmitBtn, closeReviewSubmissionOverlayBtn); } else if (e.target.id === "closeReviewSubmissionOverlayBtn" || e.target.id === "cancelReviewBtn") { toggleOverlay(reviewSubmissionOverlay, reviewSubmitBtn, closeReviewSubmissionOverlayBtn); } else if (e.target.id === "selectCaseButton") { populateCaseSelectionOverlay(); toggleOverlay(caseSelectionOverlay, selectCaseButton, closeCaseSelectionOverlayBtn); } else if (e.target.id === "closeCaseSelectionOverlayBtn" || e.target.id === "cancelCaseSelectionBtn") { toggleOverlay(caseSelectionOverlay, selectCaseButton, closeCaseSelectionOverlayBtn); } else if (e.target.closest(".review-scroll-trigger")) { document.getElementById("reviewsSection").scrollIntoView({ behavior: "smooth" }); } else if(e.target.id === 'toggleReviewsBtn') { const hiddenReviews = document.querySelectorAll('.review-item.hidden-review'); const isShowingAll = toggleReviewsBtn.textContent === 'Show Less Reviews'; hiddenReviews.forEach(review => review.classList.toggle('show')); toggleReviewsBtn.textContent = isShowingAll ? 'Show More Reviews' : 'Show Less Reviews'; } }); if (reviewForm) { reviewForm.addEventListener("submit", (e) => { e.preventDefault(); showInfoMessage("Thank you for your review!"); toggleOverlay(reviewSubmissionOverlay, reviewSubmitBtn, closeReviewSubmissionOverlayBtn); reviewForm.reset(); }); } if (cancelCasePreviewBtn) { cancelCasePreviewBtn.addEventListener("click", () => { casePreviewModal.style.display = "none"; }); } if (selectCasePreviewBtn) { selectCasePreviewBtn.addEventListener("click", handleSelectCase); } } function updateAddOnsDisplay() { if (!addOnsListDisplay) return; let html = ""; let addOnKeys = Object.keys(selectedAddOns); if (addOnKeys.length > 0) { addOnKeys.forEach(key => { const addOn = selectedAddOns[key]; html += `
${addOn.name} +£${addOn.price.toFixed(2)}
`; }); } else { html = '

No add-ons selected.

'; } addOnsListDisplay.innerHTML = html; updateAllDisplays(); } function handleAddAccessories() { document.querySelectorAll('#accessoriesOverlay input[type="checkbox"]').forEach(checkbox => { const id = checkbox.id; if (checkbox.checked) { selectedAddOns[id] = { name: checkbox.dataset.accName, price: parseFloat(checkbox.dataset.accPrice) }; } else { delete selectedAddOns[id]; } }); updateAddOnsDisplay(); toggleOverlay(accessoriesOverlay, accessoriesBtn, closeAccessoriesOverlayBtn); } function handleSubmitCharacter() { const nameField = document.getElementById("characterNameInput"); const detailsField = document.getElementById("characterDetailsTextarea"); if (!nameField && !detailsField) { toggleOverlay(pickCharacterOverlay, pickCharacterBtn, closePickCharacterOverlayBtn); return; } const name = nameField ? nameField.value : ''; const details = detailsField ? detailsField.value : ''; selectedAddOns['character_service'] = { name: "Custom Design", price: 100.00, details: `Name: ${name || 'N/A'}, Details: ${details || 'N/A'}` }; updateAddOnsDisplay(); toggleOverlay(pickCharacterOverlay, pickCharacterBtn, closePickCharacterOverlayBtn); } function updateAllDisplays() { let upgradeCost = 0; let hasUpgrades = false; if(upgradesListDisplay) upgradesListDisplay.innerHTML = ""; let upgradeItemsHTML = []; ["cpu", "gpu", "ram", "storage", "case"].forEach(component => { const selection = currentBuild[component]; const summaryDetailsEl = document.getElementById(`summary-${component}-details`); const summaryPriceEl = document.getElementById(`summary-${component}-price`); const displayEl = document.getElementById(`display-${component}-name`); const expandableItem = document.querySelector(`.summary-item-expandable[data-component="${component}"]`); if (selection && selection.name) { const price = component === 'case' ? (selection.upgradePrice || 0) : (selection.price || 0); if (typeof price === 'number') { upgradeCost += price; if (price !== 0) { hasUpgrades = true; if(upgradesListDisplay) { upgradeItemsHTML.push(`
${selection.name} ${price > 0 ? '+' : ''}£${price.toFixed(2)}
`); } } } if (summaryDetailsEl) summaryDetailsEl.textContent = selection.name; if (displayEl) displayEl.textContent = selection.name; if (summaryPriceEl && expandableItem && expandableItem.dataset.upgradable === 'true') { if (price === 0 && componentUpgrades[component]?.length > 1) { summaryPriceEl.textContent = "Customise"; summaryPriceEl.classList.add("customise-text"); } else if (price > 0) { summaryPriceEl.textContent = `+£${price.toFixed(2)}`; summaryPriceEl.classList.remove("customise-text"); } else if (price < 0) { summaryPriceEl.textContent = `-£${Math.abs(price).toFixed(2)}`; summaryPriceEl.classList.remove("customise-text"); } else { summaryPriceEl.textContent = "Included"; summaryPriceEl.classList.remove("customise-text"); } } } }); if (upgradesListDisplay) { upgradesListDisplay.innerHTML = hasUpgrades ? upgradeItemsHTML.join('') : '

No upgrades selected.

'; } let addOnCost = Object.values(selectedAddOns).reduce((sum, item) => sum + item.price, 0); const totalPrice = basePrice + upgradeCost + addOnCost; const formattedPrice = `£${totalPrice.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`; ["mainProductPriceDesktop", "mainProductPriceMobile", "totalPriceRight"].forEach(id => { const el = document.getElementById(id); if (el) el.textContent = formattedPrice; }); } function populateUpgradeOptions(listElement, component) { if (!listElement || !componentUpgrades[component]) return; let html = ""; componentUpgrades[component].forEach(option => { const isSelected = currentBuild[component].id === option.id; html += `
  • ${option.name} ${option.displayPrice}
  • `; }); listElement.innerHTML = html; } function initializeConfigurator() { const configuratorPanel = document.getElementById("productConfiguratorPanel"); if (!configuratorPanel) return; // Populate initial options document.querySelectorAll(".upgrade-options-container").forEach(container => { const component = container.dataset.component; const list = container.querySelector(".upgrade-options-list"); if (list && componentUpgrades[component]) { populateUpgradeOptions(list, component); } }); // Add event listeners for expand/collapse and selection configuratorPanel.addEventListener("click", (e) => { const expandableItem = e.target.closest('.summary-item-expandable[data-upgradable="true"]'); const upgradeButton = e.target.closest(".btn-upgrade-option:not(:disabled)"); const backButton = e.target.closest(".upgrade-options-container h3"); if (expandableItem && !upgradeButton) { const component = expandableItem.dataset.component; const optionsContainer = configuratorPanel.querySelector(`.upgrade-options-container[data-component="${component}"]`); if (!optionsContainer) return; const wasActive = expandableItem.classList.contains("active"); // Close any other open sections configuratorPanel.querySelectorAll(".summary-item-expandable.active").forEach(item => { if (item !== expandableItem) { item.classList.remove("active"); item.style.display = ""; // Reset display for mobile const otherOptions = configuratorPanel.querySelector(`.upgrade-options-container[data-component="${item.dataset.component}"]`); if (otherOptions) otherOptions.classList.add("hidden-section"); } }); // Toggle the current section optionsContainer.classList.toggle("hidden-section", wasActive); expandableItem.classList.toggle("active", !wasActive); if (window.innerWidth <= 991 && !wasActive) { expandableItem.style.display = "none"; // Hide summary item on mobile when options are open } } if (upgradeButton) { const component = upgradeButton.dataset.component; const optionId = upgradeButton.dataset.id; const selectedOption = componentUpgrades[component]?.find(opt => opt.id === optionId); if (selectedOption) { currentBuild[component] = selectedOption; updateAllDisplays(); } const listElement = upgradeButton.closest(".upgrade-options-list"); if (listElement) { populateUpgradeOptions(listElement, component); } } if (backButton || n) { const optionsContainer = e.target.closest(".upgrade-options-container"); if (optionsContainer) { const component = optionsContainer.dataset.component; const summaryItem = configuratorPanel.querySelector(`.summary-item-expandable[data-component="${component}"]`); optionsContainer.classList.add("hidden-section"); if (summaryItem) { summaryItem.classList.remove("active"); summaryItem.style.display = ""; // Reset display } } } }); } function sortCases(cases) { return cases.sort((a, b) => { if (a.id === 'mastercase_620h') return -1; if (b.id === 'mastercase_620h') return 1; return a.upgradePrice - b.upgradePrice; }); } function populateCaseSelectionOverlay() { if (!overlayCaseGrid) return; overlayCaseGrid.innerHTML = ""; const sortedCases = sortCases([...caseOptions]); sortedCases.forEach(caseOpt => { const item = document.createElement("div"); item.className = "case-option-item"; item.dataset.caseId = caseOpt.id; if (currentBuild.case.id === caseOpt.id) { item.classList.add("selected-case-option"); } if (caseOpt.name.includes("MasterCase")) { item.classList.add("master-case-glow"); } let priceText = caseOpt.upgradePrice === 0 ? "Included" : `+£${caseOpt.upgradePrice.toFixed(2)}`; item.innerHTML = ` ${caseOpt.specialOffer ? 'Offer' : ''} ${caseOpt.name} `; item.addEventListener("click", () => { selectedCaseIdForPreview = caseOpt.id; casePreviewImage.src = caseOpt.imageUrl; casePreviewModal.style.display = "flex"; }); overlayCaseGrid.appendChild(item); }); } function handleSelectCase() { if (selectedCaseIdForPreview) { const selectedCase = caseOptions.find(c => c.id === selectedCaseIdForPreview); if (selectedCase) { currentBuild.case = { id: selectedCase.id, name: selectedCase.name, price: selectedCase.price, upgradePrice: selectedCase.upgradePrice, imageUrl: selectedCase.imageUrl }; const desktopHero = document.getElementById('mainProductImageDesktop'); const mobileHero = document.getElementById('mainProductImageMobile'); if(desktopHero) desktopHero.src = selectedCase.imageUrl; if(mobileHero) mobileHero.src = selectedCase.imageUrl; updateAllDisplays(); } } casePreviewModal.style.display = "none"; toggleOverlay(caseSelectionOverlay, selectCaseButton, closeCaseSelectionOverlayBtn); selectedCaseIdForPreview = null; } function handleAddToCart() { let upgradeCost = 0; Object.values(currentBuild).forEach(component => { if (component && typeof component.price === 'number') { const price = component.upgradePrice !== undefined ? component.upgradePrice : component.price; upgradeCost += price; } }); let addOnCost = Object.values(selectedAddOns).reduce((sum, item) => sum + item.price, 0); const finalPrice = basePrice + upgradeCost + addOnCost; const finalAddOns = Object.values(selectedAddOns); cartItems.push({ id: `thor-${Date.now()}`, name: "Thor Protector of Asgard (Customised)", price: finalPrice, quantity: 1, mainImage: currentBuild.case.imageUrl, baseConfig: currentBuild, addOns: finalAddOns }); localStorage.setItem("masterRaceCartItems", JSON.stringify(cartItems)); updateCartCount(); // Update cached count updateCartBadge(); showInfoMessage("Thor build added to your cart!"); } // =================================================================== // Initialization // =================================================================== loadCartFromStorage(); setupGlobalEventListeners(); setupHeaderScrollBehavior(); initializeProductPage(); });