diff --git a/README.md b/README.md new file mode 100644 index 0000000..ec0346a --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Custom patch for Colors FastCentrik theme + +This patch patches homepage and header for now. + +## Compilation and usage + +Use `fastcentrik-template-compiler` to compile this project into single JS patch file, and inject this in the `Vlastní JavaScript` section in your Colors template configuration. + +## TODO + +- Slider changable time in UI diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 1fa08e6..0000000 --- a/TODO.md +++ /dev/null @@ -1,6 +0,0 @@ -- Account and login in header - - -- Slider changable time in UI - -- Fix do košíku button diff --git a/global/templates/globals/style.css b/global/templates/globals/style.css index 412d835..eab3fe3 100644 --- a/global/templates/globals/style.css +++ b/global/templates/globals/style.css @@ -5,3 +5,44 @@ body { html { font-size: unset !important; } + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +:root { + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + + /* Layout Variables */ + --font-sans: "Geist", "Geist Fallback", ui-sans-serif, system-ui, sans-serif; + --max-w-7xl: 80rem; /* 1280px */ + --h-16: 4rem; /* 64px */ + --h-20: 5rem; /* 80px */ + --w-10: 2.5rem; /* 40px */ + --h-10: 2.5rem; /* 40px */ +} + +body { + background-color: var(--background); + color: var(--foreground); +} diff --git a/global/templates/header/config.yaml b/global/templates/header/config.yaml index a5194a2..4ad3fb7 100644 --- a/global/templates/header/config.yaml +++ b/global/templates/header/config.yaml @@ -1,3 +1,5 @@ -original_template: - default_styles: - disable: true +template_replacer: + replace_type: "hide" + +scraper: + rerender_key: "HEADER_RERENDER" diff --git a/global/templates/header/post_script.js b/global/templates/header/post_script.js new file mode 100644 index 0000000..d3d5666 --- /dev/null +++ b/global/templates/header/post_script.js @@ -0,0 +1,55 @@ +document.addEventListener("DOMContentLoaded", () => { + // 1. Search Bar Toggle & Close on Outside Click + const searchBtn = document.getElementById("search-toggle"); + const searchBar = document.getElementById("search-bar"); + + if (searchBtn && searchBar) { + searchBtn.addEventListener("click", (e) => { + e.stopPropagation(); + searchBar.classList.toggle("hidden"); + if (!searchBar.classList.contains("hidden")) { + searchBar.querySelector("input").focus(); + } + }); + + // Close search if clicking outside of it + document.addEventListener("click", (e) => { + if (!searchBar.classList.contains("hidden") && !searchBar.contains(e.target) && !searchBtn.contains(e.target)) { + searchBar.classList.add("hidden"); + } + }); + + // Prevent clicks inside search bar from closing it + searchBar.addEventListener("click", (e) => { + e.stopPropagation(); + }); + } + + // 2. Mobile Menu Toggle + const mobileBtn = document.getElementById("mobile-menu-toggle"); + const mobileMenu = document.getElementById("mobile-menu"); + const iconOpen = document.getElementById("menu-icon-open"); + const iconClose = document.getElementById("menu-icon-close"); + + if (mobileBtn && mobileMenu) { + mobileBtn.addEventListener("click", () => { + mobileMenu.classList.toggle("hidden"); + iconOpen.classList.toggle("hidden"); + iconClose.classList.toggle("hidden"); + }); + } + + // 3. Mobile Sub-Menu Toggles + const submenuToggles = document.querySelectorAll(".js-submenu-toggle"); + submenuToggles.forEach((toggle) => { + toggle.addEventListener("click", (e) => { + // Toggle rotation class on button + toggle.classList.toggle("active"); + // Find the sibling submenu div and toggle hidden class + const submenu = toggle.parentElement.nextElementSibling; + if (submenu && submenu.classList.contains("mobile-sub-menu")) { + submenu.classList.toggle("hidden"); + } + }); + }); +}); diff --git a/global/templates/header/scrape.js b/global/templates/header/scrape.js index 408f16b..0962d07 100644 --- a/global/templates/header/scrape.js +++ b/global/templates/header/scrape.js @@ -1,11 +1,22 @@ -(() => { +( () => { const header = document.querySelector("#header"); - // Extract Logo + const basketInfo = document.querySelector("#basketinfo"); + const basketContent = document.querySelector(".vc-basketinfoextended-content"); + const itemCountBasket = parseInt(document.querySelector(".vc-basketinfoextended-numberofitems")?.textContent) || 0; + + if (basketInfo && basketContent && basketContent.children.length === 0 && itemCountBasket > 0) { + const headerLink = basketInfo.querySelector('.vc-basketinfoextended-header'); + if (headerLink) { + headerLink.dispatchEvent(new MouseEvent('mouseover', { bubbles: true })); + headerLink.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true })); + } + } + const logoEl = header.querySelector(".vc-headerlogo img"); const logo = { - src: logoEl ? logoEl.src : '', - alt: logoEl ? logoEl.alt : '', + src: logoEl ? logoEl.getAttribute("src") : '', + alt: logoEl ? logoEl.getAttribute("alt") : '', }; const customContentBlock = header.querySelector(".custom-content-block.custom-content-header-1 > .content"); @@ -13,22 +24,17 @@ function extractMenuTree(ulElement) { if (!ulElement) return []; - const listItems = Array.from(ulElement.children).filter(el => el.tagName === 'LI'); - return listItems.map(li => { const link = li.querySelector(":scope > a"); - const itemData = { text: link ? link.textContent.trim() : '', - href: link ? link.href : '' + href: link ? link.getAttribute("href") : '' }; - const subMenu = li.querySelector(":scope > ul[role='menu']"); if (subMenu) { itemData.sublinks = extractMenuTree(subMenu); } - return itemData; }); } @@ -37,26 +43,63 @@ const menuData = extractMenuTree(rootMenu); const menuTop = header.querySelector("#menutop ul[role='menu']"); - const menuTopLinks = menuTop.querySelectorAll("li > a"); - const menuTopData = Array.from(menuTopLinks).map(link => ({ + const menuTopData = menuTop ? Array.from(menuTop.querySelectorAll("li > a")).map(link => ({ text: link.textContent.trim(), - href: link.href + href: link.getAttribute("href") + })) : []; + + const searchForm = header.querySelector("#frm-searchbox"); + const searchAction = searchForm ? searchForm.getAttribute("action") : "/hledani"; + + const userMenuNodes = header.querySelectorAll("#menuuser .content ul li a"); + const userMenu = Array.from(userMenuNodes).map(a => ({ + text: a.textContent.trim(), + href: a.getAttribute("href") })); - const itemCountBasket = parseInt(header.querySelector("#basketinfo .vc-basketinfoextended-numberofitems").textContent) || 0; + const basketPrice = header.querySelector("#basketinfo .vc-basketinfoextended-price")?.textContent.trim() || ''; + const basketLink = header.querySelector("#basketinfo .vc-basketinfoextended-header")?.getAttribute("href") || '/kosik'; - const basket = { - itemCount: itemCountBasket, - link: header.querySelector("#basketinfo .vc-basketinfoextended-header").href || '/kosik' - } + // Extract the newly populated items + const basketItemsNodes = header.querySelectorAll(".vc-basketinfoextended-item"); + const basketItems = Array.from(basketItemsNodes).map(item => { + const img = item.querySelector("img"); + const link = item.querySelector(".vc-basketinfoextended-item-namewrapper p a"); + const qty = item.querySelector(".quantity"); + const price = item.querySelector(".vc-basketinfoextended-item-price"); + const remove = item.querySelector(".removeBasketItemLink"); - return { + return { + imgSrc: img ? (img.getAttribute("data-src") || img.getAttribute("src")) : "", + imgAlt: img ? img.getAttribute("alt") : "", + name: link ? link.textContent.trim() : "", + href: link ? link.getAttribute("href") : "", + qty: qty ? qty.textContent.trim() : "", + price: price ? price.textContent.trim() : "", + removeLink: remove ? remove.getAttribute("href") : "" + }; + }); + + const freeDeliveryNode = header.querySelector(".ndBasketFreeDelivery_basketpopup p"); + const freeDeliveryText = freeDeliveryNode ? freeDeliveryNode.textContent.trim() : ""; + + const finalData = { logo, customContentHeader, + searchAction, + userMenu, menu: { top: menuTopData, main: menuData }, - basket, + basket: { + itemCount: itemCountBasket, + price: basketPrice, + link: basketLink, + items: basketItems, + freeDelivery: freeDeliveryText + } }; + + return finalData; })(); diff --git a/global/templates/header/style.css b/global/templates/header/style.css index e69de29..ade2e92 100644 --- a/global/templates/header/style.css +++ b/global/templates/header/style.css @@ -0,0 +1,523 @@ +.site-header { + font-family: var(--font-sans); + position: sticky; + top: 0; + z-index: 50; + background-color: var(--card); + border-bottom: 1px solid var(--border); + color: var(--foreground); +} + +.site-header a, +.site-header button { + text-decoration: none; + color: inherit; + font-family: inherit; +} + +.container { + max-width: var(--max-w-7xl); + margin: 0 auto; + padding: 0 1rem; +} +@media (min-width: 640px) { + .container { + padding: 0 1.5rem; + } +} +@media (min-width: 1024px) { + .container { + padding: 0 2rem; + } +} + +/* Utilities */ +.text-xs { font-size: 0.75rem; line-height: 1rem; } +.text-sm { font-size: 0.875rem; line-height: 1.25rem; } +.text-base { font-size: 1rem; line-height: 1.5rem; } +.text-lg { font-size: 1.125rem; line-height: 1.75rem; } +.text-xl { font-size: 1.25rem; line-height: 1.75rem; } +.font-medium { font-weight: 500; } +.font-bold { font-weight: 700; } +.uppercase { text-transform: uppercase; } +.tracking-wide { letter-spacing: 0.025em; } +.tracking-tight { letter-spacing: -0.025em; } +.hidden { display: none !important; } + +/* ------------------ Top Bar ------------------ */ +.top-bar { + background-color: var(--primary); + color: var(--primary-foreground); + padding: 0.5rem 0; +} +.top-bar-inner { + display: flex; + align-items: center; + justify-content: space-between; +} +.top-bar-left, +.top-bar-right { + display: flex; + align-items: center; + gap: 1.5rem; +} +.top-bar-left a, +.top-bar-right a { + transition: opacity 0.2s; +} +.top-bar-left a:hover, +.top-bar-right a:hover { + opacity: 0.8; +} +.top-bar-left { display: none; } +@media (min-width: 640px) { + .top-bar-left { display: flex; } +} + +/* ------------------ Main Header ------------------ */ +.main-header { + display: flex; + align-items: center; + justify-content: space-between; + height: var(--h-16); +} +@media (min-width: 1024px) { + .main-header { height: var(--h-20); } +} + +/* Logo */ +.logo { + display: flex; + align-items: center; + gap: 0.5rem; +} +.logo-img { + height: var(--h-10); + width: auto; +} +.logo-icon { + width: var(--w-10); + height: var(--h-10); + border-radius: 9999px; + background: linear-gradient(to bottom right, var(--accent), color-mix(in srgb, var(--accent) 70%, transparent)); + display: flex; + align-items: center; + justify-content: center; + color: var(--accent-foreground); +} +.logo-text { color: var(--foreground); } + +/* ------------------ Desktop Nav ------------------ */ +.desktop-nav { + display: none; + align-items: center; + gap: 2rem; + height: 100%; +} +@media (min-width: 1024px) { + .desktop-nav { display: flex; } +} + +.nav-item { + position: relative; + height: 100%; + display: flex; + align-items: center; +} +.nav-link { + display: flex; + align-items: center; + gap: 0.25rem; + padding: 0.5rem 0; + color: var(--foreground); + transition: color 0.2s; +} +.nav-link:hover { color: var(--accent-foreground); } +.nav-icon { width: 1rem; height: 1rem; transition: transform 0.2s; } +.nav-item:hover > .nav-link .nav-icon { transform: rotate(180deg); } + +/* Dropdowns */ +.dropdown { + display: none; + position: absolute; + top: 100%; + left: 0; + padding-top: 0.5rem; + z-index: 50; +} +.nav-item:hover .dropdown { display: block; } + +.dropdown-inner { + background-color: var(--card); + border: 1px solid var(--border); + border-radius: 0.5rem; + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1); + min-width: 200px; + padding: 0.5rem 0; +} +.dropdown-item { position: relative; } +.dropdown-link { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.625rem 1rem; + color: var(--foreground); + transition: all 0.2s; +} +.dropdown-link:hover, +.dropdown-item:hover > .dropdown-link { + background-color: var(--secondary); + color: var(--accent-foreground); +} + +/* Sub-Dropdowns */ +.sub-dropdown { + display: none; + position: absolute; + top: 0; + left: 100%; + padding-left: 0.5rem; + z-index: 50; +} +.dropdown-item:hover .sub-dropdown { display: block; } + +/* ------------------ Actions ------------------ */ +.actions { + display: flex; + align-items: center; + gap: 1rem; +} +.action-btn { + padding: 0.5rem; + border-radius: 9999px; + border: none; + background: transparent; + color: var(--foreground); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background-color 0.2s; +} +.action-btn:hover { background-color: var(--secondary); } +.action-btn svg { width: 1.25rem; height: 1.25rem; } + +.desktop-user { display: none; } +@media (min-width: 640px) { + .desktop-user { display: flex; } +} +.mobile-menu-btn { display: flex; } +@media (min-width: 1024px) { + .mobile-menu-btn { display: none; } +} + +.cart-wrapper { position: relative; } +.cart-badge { + position: absolute; + top: -0.25rem; + right: -0.25rem; + width: 1.25rem; + height: 1.25rem; + background-color: var(--accent); + color: var(--accent-foreground); + border-radius: 9999px; + display: flex; + align-items: center; + justify-content: center; +} + +/* ------------- ACTION DROPDOWNS ------------- */ +.action-dropdown-wrapper { + position: relative; + height: auto; +} + +.action-dropdown { + position: absolute !important; + top: 100% !important; + right: 0 !important; + left: auto !important; + padding-top: 0.5rem; +} + +.action-dropdown::before { + content: ''; + position: absolute; + top: 0; left: 0; right: 0; + height: 0.5rem; +} + +.user-dropdown .dropdown-inner { + min-width: 180px; +} + +/* ------------- BASKET REDESIGN ------------- */ +.cart-dropdown .dropdown-inner { + width: 22rem; + max-width: calc(100vw - 2rem); + padding: 0; + cursor: default; + overflow: hidden; +} + +.basket-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 1.25rem; + border-bottom: 1px solid var(--border); + background-color: color-mix(in srgb, var(--secondary) 50%, transparent); +} + +.basket-title { + font-weight: 700; + font-size: 1rem; + color: var(--foreground); +} + +.basket-count-text { + font-size: 0.8125rem; + color: var(--muted-foreground); + font-weight: 500; +} + +.basket-items-scroll { + max-height: 55vh; + overflow-y: auto; + padding: 0.5rem 0; +} + +.basket-item { + display: flex; + align-items: center; + gap: 1rem; + padding: 0.75rem 1.25rem; + transition: background-color 0.2s; +} +.basket-item:hover { + background-color: var(--secondary); +} + +.basket-item-img-wrap { + width: 3.5rem; + height: 3.5rem; + flex-shrink: 0; + border-radius: 0.5rem; + border: 1px solid var(--border); + overflow: hidden; + background-color: var(--card); +} +.basket-item-img-wrap img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.basket-item-details { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.basket-item-name { + font-size: 0.875rem; + font-weight: 600; + color: var(--foreground); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-decoration: none; +} +.basket-item-name:hover { color: var(--accent); } + +.basket-item-price-row { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.875rem; +} +.basket-item-qty { color: var(--muted-foreground); } +.basket-item-price { font-weight: 700; color: var(--foreground); } + +.basket-item-remove { + color: var(--muted-foreground); + padding: 0.5rem; + margin: -0.5rem; + border-radius: 0.375rem; + transition: all 0.2s; + display: flex; + align-items: center; + justify-content: center; +} +.basket-item-remove svg { width: 1.25rem; height: 1.25rem; } +.basket-item-remove:hover { + color: #ef4444; + background-color: color-mix(in srgb, #ef4444 10%, transparent); +} + +.basket-empty { + padding: 3rem 1.5rem; + text-align: center; + color: var(--muted-foreground); + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; +} +.basket-empty-icon { + width: 3rem; + height: 3rem; + opacity: 0.5; +} + +.basket-footer { + padding: 1.25rem; + border-top: 1px solid var(--border); + background-color: color-mix(in srgb, var(--secondary) 50%, transparent); + display: flex; + flex-direction: column; + gap: 1rem; +} + +.basket-freedelivery { + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + font-size: 0.8125rem; + font-weight: 600; + color: #10b981; + background-color: color-mix(in srgb, #10b981 10%, transparent); + padding: 0.5rem; + border-radius: 0.5rem; + text-align: center; +} +.basket-freedelivery svg { width: 1rem; height: 1rem; } + +.basket-total { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 1rem; + font-weight: 500; + color: var(--foreground); +} +.basket-total-price { + font-size: 1.25rem; + font-weight: 700; + color: var(--accent); +} + +.basket-checkout-btn { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + background-color: var(--primary); + color: var(--primary-foreground); + padding: 0.75rem; + border-radius: 0.5rem; + font-size: 0.9375rem; + font-weight: 600; + text-decoration: none; + transition: background-color 0.2s; +} +.basket-checkout-btn:hover { + background-color: color-mix(in srgb, var(--primary) 90%, transparent); +} + +/* ------------------ Search Bar ------------------ */ +.search-container { + padding-bottom: 1rem; + animation: slideDown 0.2s ease-out; +} +.search-input-wrapper { + position: relative; + display: flex; + width: 100%; +} +.search-input { + width: 100%; + padding: 0.75rem 3rem 0.75rem 1rem; + background-color: var(--secondary); + border: 1px solid transparent; + border-radius: 0.5rem; + color: var(--foreground); + outline: none; + transition: all 0.2s; +} +.search-input::placeholder { color: var(--muted-foreground); } +.search-input:focus { box-shadow: 0 0 0 2px var(--ring); } +.search-submit-btn { + position: absolute; + right: 0.5rem; + top: 50%; + transform: translateY(-50%); + background: transparent; + border: none; + cursor: pointer; + padding: 0.25rem; + color: var(--muted-foreground); + border-radius: 0.25rem; +} +.search-submit-btn:hover { color: var(--foreground); } +.search-submit-btn svg { width: 1.25rem; height: 1.25rem; } + +/* ------------------ Mobile Menu ------------------ */ +.mobile-menu { + border-top: 1px solid var(--border); + animation: slideDown 0.2s ease-out; +} +@media (min-width: 1024px) { + .mobile-menu { display: none !important; } +} +.mobile-nav-inner { + padding: 1rem 0; + display: flex; + flex-direction: column; + gap: 0.25rem; +} +.mobile-item-wrap { position: relative; } +.mobile-item-header { + display: flex; + align-items: center; + justify-content: space-between; +} +.mobile-link { + flex: 1; + padding: 0.5rem 0; + color: var(--foreground); + transition: color 0.2s; +} +.mobile-link:hover { color: var(--accent-foreground); } +.mobile-toggle { + padding: 0.5rem; + border: none; + background: transparent; + border-radius: 9999px; + color: var(--foreground); +} +.mobile-toggle:hover { background-color: var(--secondary); } +.mobile-toggle svg { width: 1rem; height: 1rem; transition: transform 0.2s; } +.mobile-toggle.active svg { transform: rotate(180deg); } +.mobile-sub-menu { + border-left: 2px solid var(--border); + margin-left: 0.5rem; + padding-left: 1rem; +} +.mobile-contact { + padding-top: 1rem; + margin-top: 0.5rem; + border-top: 1px solid var(--border); + color: var(--muted-foreground); + font-size: 0.875rem; +} +@media (min-width: 640px) { + .mobile-contact { display: none; } +} + +a { + color: unset !important; +} diff --git a/global/templates/header/template.html b/global/templates/header/template.html index 353f3ac..c8cd3f5 100644 --- a/global/templates/header/template.html +++ b/global/templates/header/template.html @@ -1,5 +1,4 @@ diff --git a/homepage/style.css b/homepage/style.css index ddf9493..3301f7e 100644 --- a/homepage/style.css +++ b/homepage/style.css @@ -1,6 +1,10 @@ -#AjaxMainSection { +#AjaxMainSection, +.section_middle > .container > .inner { display: flex; flex-direction: column; - gap: 1.5rem; + gap: 4.5rem; +} + +#AjaxMainSection { padding-top: 1.5rem; } diff --git a/homepage/templates/footer_before/replace_selector b/homepage/templates/footer_before/replace_selector new file mode 100644 index 0000000..0863776 --- /dev/null +++ b/homepage/templates/footer_before/replace_selector @@ -0,0 +1 @@ +.section_footer_before diff --git a/homepage/templates/footer_before/scrape.js b/homepage/templates/footer_before/scrape.js new file mode 100644 index 0000000..4992fd6 --- /dev/null +++ b/homepage/templates/footer_before/scrape.js @@ -0,0 +1,34 @@ +(() => { + const parseMethodsBlock = (wrapperSelector, boxSelector) => { + const container = document.querySelector(wrapperSelector); + if (!container) return null; + + const titleEl = container.querySelector(`${boxSelector} h2 span`); + const title = titleEl ? titleEl.textContent.trim() : null; + + const descEl = container.querySelector(`${boxSelector} .box-in p`); + const description = descEl ? descEl.textContent.trim() : null; + + const imageElements = container.querySelectorAll(`${boxSelector} .box-in .ico span img`); + const methods = Array.from(imageElements).map((img) => { + return { + name: img.getAttribute('alt') || null, + imageSrc: img.getAttribute('data-src') || img.getAttribute('src') || null + }; + }); + + return { + title, + description, + methods + }; + }; + + const paymentMethods = parseMethodsBlock('.section_footer_before .vc-content_paymentmethods', '.box-payment'); + const deliveryMethods = parseMethodsBlock('.section_footer_before .vc-content_deliverymethods', '.box-delivery'); + + return { + paymentMethods, + deliveryMethods + }; +})(); diff --git a/homepage/templates/footer_before/style.css b/homepage/templates/footer_before/style.css new file mode 100644 index 0000000..63b1c12 --- /dev/null +++ b/homepage/templates/footer_before/style.css @@ -0,0 +1,109 @@ +:root { + --card: oklch(1 0 0); + --secondary: oklch(0.97 0 0); + --foreground: oklch(0.145 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --border: oklch(0.922 0 0); + --font-sans: "Geist", "Geist Fallback", ui-sans-serif, system-ui, sans-serif; +} + +.methods-section { + font-family: var(--font-sans); + padding: 3rem 0; /* py-12 */ + background-color: var(--card); + border-top: 1px solid var(--border); +} +@media (min-width: 1024px) { + .methods-section { + padding: 4rem 0; /* lg:py-16 */ + } +} + +.container { + max-width: 80rem; /* max-w-7xl */ + margin: 0 auto; + padding: 0 1rem; /* px-4 */ +} +@media (min-width: 640px) { + .container { + padding: 0 1.5rem; /* sm:px-6 */ + } +} +@media (min-width: 1024px) { + .container { + padding: 0 2rem; /* lg:px-8 */ + } +} + +.methods-grid { + display: grid; + grid-template-columns: 1fr; + gap: 3rem; /* gap-12 */ +} +@media (min-width: 768px) { + .methods-grid { + grid-template-columns: repeat(2, 1fr); /* md:grid-cols-2 */ + } +} + +/* Header & Description */ +.section-header { + display: flex; + align-items: center; + gap: 0.5rem; /* gap-2 */ + font-size: 1.125rem; /* text-lg */ + font-weight: 600; /* font-semibold */ + color: var(--foreground); + margin: 0 0 0.5rem 0; +} + +.section-header svg { + width: 1.25rem; /* w-5 */ + height: 1.25rem; /* h-5 */ + color: var(--accent); +} + +.section-desc { + font-size: 0.875rem; + color: var(--muted-foreground); + margin: 0 0 1.5rem 0; + line-height: 1.5; +} + +/* Items Wrapper */ +.items-list { + display: flex; + flex-wrap: wrap; + gap: 1rem; /* gap-4 */ +} + +.item-card { + display: flex; + align-items: center; + gap: 0.75rem; /* gap-3 */ + padding: 0.75rem 1rem; /* px-4 py-3 */ + background-color: var(--secondary); + border-radius: 0.5rem; /* rounded-lg */ + border: 1px solid transparent; + transition: + background-color 0.2s, + border-color 0.2s; +} +.item-card:hover { + background-color: color-mix(in srgb, var(--secondary) 80%, transparent); + border-color: var(--border); +} + +.item-img { + height: 1.5rem; /* h-6 roughly */ + width: auto; + object-fit: contain; +} + +.item-name { + font-size: 0.875rem; /* text-sm */ + font-weight: 500; /* font-medium */ + color: var(--foreground); + margin: 0; +} diff --git a/homepage/templates/footer_before/template.html b/homepage/templates/footer_before/template.html new file mode 100644 index 0000000..90cd91f --- /dev/null +++ b/homepage/templates/footer_before/template.html @@ -0,0 +1,97 @@ +
+
+
+ + {{#if paymentMethods}} +
+

+ + + + + {{#if paymentMethods.title}}{{paymentMethods.title}}{{else}}Platební + metody{{/if}} +

+ + {{#if paymentMethods.description}} +

{{paymentMethods.description}}

+ {{/if}} + +
+ {{#each paymentMethods.methods}} +
+ {{#if this.imageSrc}} + {{this.name}} + {{/if}} + {{this.name}} +
+ {{/each}} +
+
+ {{/if}} + + + {{#if deliveryMethods}} +
+

+ + + + + + + + {{#if + deliveryMethods.title}}{{deliveryMethods.title}}{{else}}Doručovací + metody{{/if}} +

+ + {{#if deliveryMethods.description}} +

{{deliveryMethods.description}}

+ {{/if}} + +
+ {{#each deliveryMethods.methods}} +
+ {{#if this.imageSrc}} + {{this.name}} + {{/if}} + {{this.name}} +
+ {{/each}} +
+
+ {{/if}} +
+
+
diff --git a/homepage/templates/section_middle_novinky/config.yaml b/homepage/templates/section_middle_novinky/config.yaml new file mode 100644 index 0000000..6f7113c --- /dev/null +++ b/homepage/templates/section_middle_novinky/config.yaml @@ -0,0 +1,2 @@ +template_replacer: + replace_type: "hide" diff --git a/homepage/templates/section_middle_novinky/post_script.js b/homepage/templates/section_middle_novinky/post_script.js new file mode 100644 index 0000000..52ae021 --- /dev/null +++ b/homepage/templates/section_middle_novinky/post_script.js @@ -0,0 +1,22 @@ +document.querySelectorAll(".new-products-section .product-buy-form").forEach(form => { + const originalFormId = form.dataset.originalId; + + const submitButton = form.querySelector("button"); + + submitButton.addEventListener("click", (e) => { + e.preventDefault(); + + const form = document.getElementById(originalFormId).querySelector("form"); + if (form) { + form.dispatchEvent(new Event('submit', { + bubbles: true, + cancelable: true + })); + + // TODO: This is awful i know but idk a better way to do this for now + setTimeout(() => { + window.Rerender.rerenderComponent("HEADER_RERENDER"); + }, 2000) + } + }); +}); diff --git a/homepage/templates/section_middle_novinky/replace_selector b/homepage/templates/section_middle_novinky/replace_selector index 5d059f7..253c490 100644 --- a/homepage/templates/section_middle_novinky/replace_selector +++ b/homepage/templates/section_middle_novinky/replace_selector @@ -1 +1 @@ -main#main #AjaxMainSection section.section_middle .vc-commodity_attribute +main#main #AjaxMainSection section.section_middle > .container > .inner > .vc-commodity_attribute diff --git a/homepage/templates/section_middle_novinky/scrape.js b/homepage/templates/section_middle_novinky/scrape.js index cd80c0a..b16309e 100644 --- a/homepage/templates/section_middle_novinky/scrape.js +++ b/homepage/templates/section_middle_novinky/scrape.js @@ -9,11 +9,11 @@ // Select all products, ignoring carousel initialization wrappers to ensure we get everything const items = container.querySelectorAll("article.commodityBox"); - + const itemsData = Array.from(items).map((item) => { const productNode = item.querySelector("a.inner"); const link = productNode ? productNode.getAttribute("href") : null; - + // Extract flags and their computed styles const flagsElements = productNode.querySelectorAll(".flags > .flags-inner > .flag"); const flags = Array.from(flagsElements).map((flag) => { @@ -40,6 +40,8 @@ // Extract buy form HTML const buyFormEl = productNode.querySelector(".buyForm"); const buyFormContent = buyFormEl ? buyFormEl.innerHTML.trim() : null; + const id = "button-action-id-" + crypto.randomUUID(); + buyFormEl.setAttribute("id", id); // Extract pricing details const priceEl = productNode.querySelector(".pricing > .pricing-inner"); @@ -50,7 +52,7 @@ if (priceEl) { const priceDiscountEl = priceEl.querySelector(".discount .number"); priceDiscount = priceDiscountEl ? parseInt(priceDiscountEl.textContent.trim(), 10) : null; - + const priceBeforeDiscountEl = priceEl.querySelector(".price.beforeDiscount"); priceBeforeDiscount = priceBeforeDiscountEl ? priceBeforeDiscountEl.textContent.trim().replace(/\s+/g, ' ') : null; @@ -73,7 +75,8 @@ priceBeforeDiscount, priceDiscount, availability, - buyFormContent + buyFormContent, + buyFormId: id }; }); diff --git a/homepage/templates/section_middle_novinky/style.css b/homepage/templates/section_middle_novinky/style.css index fce4373..204cdc7 100644 --- a/homepage/templates/section_middle_novinky/style.css +++ b/homepage/templates/section_middle_novinky/style.css @@ -182,9 +182,6 @@ line-height: 1.3; transition: color 0.2s; } -.product-card:hover .product-title { - color: var(--accent); /* group-hover:text-accent */ -} .product-pricing { display: flex; diff --git a/homepage/templates/section_middle_novinky/template.html b/homepage/templates/section_middle_novinky/template.html index c6c9961..bebe74e 100644 --- a/homepage/templates/section_middle_novinky/template.html +++ b/homepage/templates/section_middle_novinky/template.html @@ -61,8 +61,7 @@ {{#if (eq this.availability "Skladem")}}✓ {{/if}}{{this.availability}} -
- +
{{{this.buyFormContent}}}
diff --git a/homepage/templates/section_middle_tabs/config.yaml b/homepage/templates/section_middle_tabs/config.yaml new file mode 100644 index 0000000..6f7113c --- /dev/null +++ b/homepage/templates/section_middle_tabs/config.yaml @@ -0,0 +1,2 @@ +template_replacer: + replace_type: "hide" diff --git a/homepage/templates/section_middle_tabs/post_script.js b/homepage/templates/section_middle_tabs/post_script.js index 47a83cd..7f4639c 100644 --- a/homepage/templates/section_middle_tabs/post_script.js +++ b/homepage/templates/section_middle_tabs/post_script.js @@ -1,18 +1,14 @@ - document.addEventListener('DOMContentLoaded', () => { const tabBtns = document.querySelectorAll('.js-tab-btn'); const tabPanes = document.querySelectorAll('.js-tab-pane'); tabBtns.forEach(btn => { btn.addEventListener('click', () => { - // Remove active class from all buttons and panes tabBtns.forEach(b => b.classList.remove('active')); tabPanes.forEach(p => p.classList.remove('active')); - // Add active class to clicked button btn.classList.add('active'); - // Show corresponding pane const targetId = btn.getAttribute('data-target'); const targetPane = document.getElementById(targetId); if (targetPane) { @@ -20,4 +16,27 @@ document.addEventListener('DOMContentLoaded', () => { } }); }); + + document.querySelectorAll(".featured-section .product-buy-form").forEach(form => { + const originalFormId = form.dataset.originalId; + + const submitButton = form.querySelector("button"); + + submitButton.addEventListener("click", (e) => { + e.preventDefault(); + + const form = document.getElementById(originalFormId).querySelector("form"); + if (form) { + form.dispatchEvent(new Event('submit', { + bubbles: true, + cancelable: true + })); + + // TODO: This is awful i know but idk a better way to do this for now + setTimeout(() => { + window.Rerender.rerenderComponent("HEADER_RERENDER"); + }, 2000) + } + }); + }); }); diff --git a/homepage/templates/section_middle_tabs/scrape.js b/homepage/templates/section_middle_tabs/scrape.js index 7511b4f..d7dd48a 100644 --- a/homepage/templates/section_middle_tabs/scrape.js +++ b/homepage/templates/section_middle_tabs/scrape.js @@ -15,14 +15,14 @@ for (let i = 0; i < tabTexts.length; i++) { const idName = `Index_${i + 1}`; - + const items = body.querySelectorAll(`#${idName} article.commodityBox`); - + const itemsData = Array.from(items).map((item) => { const productNode = item.querySelector("a.inner"); const link = productNode.getAttribute("href"); - + const flagsElements = productNode.querySelectorAll(".flags > .flags-inner > .flag"); const flags = Array.from(flagsElements).map((flag) => { const styles = window.getComputedStyle(flag); @@ -45,9 +45,11 @@ const buyFormEl = productNode.querySelector(".buyForm"); const buyFormContent = buyFormEl ? buyFormEl.innerHTML.trim() : null; + const id = "button-action-id-" + crypto.randomUUID(); + buyFormEl.setAttribute("id", id); const priceEl = productNode.querySelector(".pricing > .pricing-inner"); - + let priceDiscount = null; let priceBeforeDiscount = null; let priceHighlight = null; @@ -55,7 +57,7 @@ if (priceEl) { const priceDiscountEl = priceEl.querySelector(".discount .number"); priceDiscount = priceDiscountEl ? parseInt(priceDiscountEl.textContent.trim(), 10) : null; - + const priceBeforeDiscountEl = priceEl.querySelector(".price.beforeDiscount"); priceBeforeDiscount = priceBeforeDiscountEl ? priceBeforeDiscountEl.textContent.trim().replace(/\s+/g, ' ') : null; @@ -77,7 +79,8 @@ priceBeforeDiscount, priceDiscount, availability, - buyFormContent + buyFormContent, + buyFormId: id }; }); diff --git a/homepage/templates/section_middle_tabs/style.css b/homepage/templates/section_middle_tabs/style.css index 7b0ab5e..d0902a5 100644 --- a/homepage/templates/section_middle_tabs/style.css +++ b/homepage/templates/section_middle_tabs/style.css @@ -203,9 +203,6 @@ line-height: 1.3; transition: color 0.2s; } -.product-card:hover .product-title { - color: var(--accent); -} .product-pricing { display: flex; diff --git a/homepage/templates/section_middle_tabs/template.html b/homepage/templates/section_middle_tabs/template.html index c7c7bba..508f422 100644 --- a/homepage/templates/section_middle_tabs/template.html +++ b/homepage/templates/section_middle_tabs/template.html @@ -77,7 +77,7 @@ {{/if}}{{this.availability}} -
{{{this.buyFormContent}}}
+
{{{this.buyFormContent}}}