diff --git a/best-cigars-guide/blocks/footer/footer.js b/best-cigars-guide/blocks/footer/footer.js index 93d9828..1a32f83 100644 --- a/best-cigars-guide/blocks/footer/footer.js +++ b/best-cigars-guide/blocks/footer/footer.js @@ -1,6 +1,6 @@ import { getMetadata } from '../../scripts/aem.js'; import { loadFragment } from '../fragment/fragment.js'; -import { isInternal } from '../../scripts/scripts.js'; +import { isInternal, isCategory } from '../../scripts/scripts.js'; import { addLdJsonScript } from '../../scripts/linking-data.js'; function buildLdJson(container) { @@ -19,7 +19,7 @@ function buildLdJson(container) { }; // Change type for category pages - if (document.querySelector('.article-list-container')) { + if (isCategory()) { ldJson['@type'] = 'CollectionPage'; } diff --git a/best-cigars-guide/blocks/item/item.css b/best-cigars-guide/blocks/item/item.css new file mode 100644 index 0000000..636fe07 --- /dev/null +++ b/best-cigars-guide/blocks/item/item.css @@ -0,0 +1,73 @@ +.item-wrapper { + border-bottom: 1px dashed #ccc; + margin-bottom: 40px; + padding-bottom: 45px; + font-size: 0.75em; + font-weight: 300; +} + +.item-wrapper h3 { + margin-bottom: 25px; + text-align: center; + font-size: var(--heading-font-size-s); +} + +.item-wrapper a { + display: block; + text-align: center; +} + +.item-wrapper img { + max-height: 75px; + width: auto; + margin-bottom: 25px; + text-align: center; +} + +.item-wrapper .item-stats { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + margin: 30px auto; + width: 90%; +} + +.item-wrapper .item-stat { + padding-right: 10px; +} + +.item-wrapper .item-stat .label { + font-weight: bold; +} + +.item-wrapper .item-buy-now a { + font-weight: 600; + text-decoration: none; + display: inline-block; + box-sizing: border-box; + width: auto; + padding: 10px 25px 9px; + background: #177abb; + border-bottom: 1px solid #035890; + color: #fff; + border-radius: 4px; + transition: background-color .15s; +} + +.item-wrapper .item-buy-now a:hover { + background: #0d67a2; +} + +.item-wrapper .item-subinfo { + display: flex; + justify-content: space-between; + align-items: center; + width: 280px; + margin: 0 auto; +} + +.item-wrapper .item-star-rating img { + width: 25px; + height: 25px; + margin: 0; +} diff --git a/best-cigars-guide/blocks/item/item.js b/best-cigars-guide/blocks/item/item.js new file mode 100644 index 0000000..55cab3b --- /dev/null +++ b/best-cigars-guide/blocks/item/item.js @@ -0,0 +1,110 @@ +/** + * parse block row data into a js object + * @param block + * @returns {{}} + */ +function parseData(block) { + const rows = block.children; + const data = {}; + + // eslint-disable-next-line no-plusplus + for (let i = 0; i < rows.length; i++) { + const fieldName = rows[i].firstElementChild.textContent; + + if (fieldName === 'Image') { + data[fieldName] = rows[i].lastElementChild.innerHTML; + } else if (fieldName === 'Rating') { + data[fieldName] = Number(rows[i].lastElementChild.textContent); + } else { + data[fieldName] = rows[i].lastElementChild.textContent; + } + } + + return data; +} + +/** + * render rating stats html + * @param data + */ +function renderRatingStars(data) { + let output = ''; + + // eslint-disable-next-line no-plusplus + for (let i = 0; i < 5; i++) { + if (i + 0.5 === data.Rating) { + output += ''; + } else if (i < data.Rating) { + output += ''; + } else { + output += ''; + } + } + + return output; +} + +/** + * render individual item stats + * @param data + * @returns {string} + */ +function renderStats(data) { + // list of possible stat fields from block data + const stats = [ + 'Country', + 'Strength', + 'Wrapper', + 'Color', + ]; + + let output = ''; + // eslint-disable-next-line no-plusplus + for (let i = 0; i < stats.length; i++) { + if (stats[i] in data) { + output += ` +
+

${stats[i]}

+

${data[stats[i]]}

+
+ `; + } + } + + return output; +} + +function render(data) { + const ratingLabel = data.Rating ? `Rated ${data.Rating} out of 5 stars.` : 'No ratings yet.'; + + return ` +

${data.Name}

+ + ${data.Image} + +
+

${data.Description}

+
+ ${renderStats(data)} +
+
+
+ ${renderRatingStars(data)} +
+
+ Buy Now +
+
+
+ `; +} + +/** + * loads and decorates the item + * @param {Element} block The item element + */ +export default async function decorate(block) { + const data = parseData(block); + block.innerHTML = render(data); + return block; +} diff --git a/best-cigars-guide/blocks/nav/nav.css b/best-cigars-guide/blocks/nav/nav.css index faa101b..eb176ed 100644 --- a/best-cigars-guide/blocks/nav/nav.css +++ b/best-cigars-guide/blocks/nav/nav.css @@ -3,8 +3,9 @@ display: flex; justify-content: space-between; align-items: center; - margin-bottom: 20px; - padding: 10px 0; + padding: 50px 1rem 15px; + max-width: var(--content-width); + margin: 0 auto 20px; } /* Breadcrumb styling */ @@ -68,6 +69,7 @@ .nav-row { flex-direction: column; /* Stack items vertically on small screens */ align-items: center; + padding: 10px 16px; } .breadcrumb, diff --git a/best-cigars-guide/blocks/nav/nav.js b/best-cigars-guide/blocks/nav/nav.js index 73b9731..16bc128 100644 --- a/best-cigars-guide/blocks/nav/nav.js +++ b/best-cigars-guide/blocks/nav/nav.js @@ -122,8 +122,8 @@ export default function decorate(block) { block.remove(); // Create nav - const startingTag = document.querySelector('body > main > div'); - const navDiv = document.createElement('div'); + const startingTag = document.querySelector('body > header'); + const navDiv = document.createElement('nav'); navDiv.className = 'nav-row'; // Create Breadcrumbs @@ -142,5 +142,5 @@ export default function decorate(block) { awaitCategoriesDropdown(); // Append nav to the dom - startingTag.prepend(navDiv); + startingTag.after(navDiv); } diff --git a/best-cigars-guide/blocks/sidebar/sidebar.css b/best-cigars-guide/blocks/sidebar/sidebar.css new file mode 100644 index 0000000..623c93a --- /dev/null +++ b/best-cigars-guide/blocks/sidebar/sidebar.css @@ -0,0 +1,49 @@ +.article-wrapper { + display: flex; + max-width: var(--content-width); + margin: auto; + justify-content: space-between; + padding: 0 1rem; +} + +.article-wrapper .section { + padding: 0; + width: 64%; +} + +.article-wrapper aside { + width: 30%; + max-width: 315px; +} + +aside h3 { + font-size: 0.9em; + margin: 0 0 1.2em; + font-weight: 700; +} + +aside ul { + list-style: none; + padding: 0; +} + +aside li { + margin: 0 0 12px; + font-weight: 300; + font-size: 0.7em; +} + +@media (max-width: 600px) { + .article-wrapper { + display: block; + } + + .article-wrapper .section { + width: 100%; + } + + .article-wrapper aside { + width: 100%; + max-width: 100%; + } +} diff --git a/best-cigars-guide/blocks/sidebar/sidebar.js b/best-cigars-guide/blocks/sidebar/sidebar.js new file mode 100644 index 0000000..2752481 --- /dev/null +++ b/best-cigars-guide/blocks/sidebar/sidebar.js @@ -0,0 +1,64 @@ +import { fetchCategoryList } from '../../scripts/scripts.js'; + +function getRelatedArticles() { + const wrap = document.createElement('div'); + wrap.className = 'sidebar-related-articles'; + + const heading = document.createElement('h3'); + heading.textContent = 'Related Articles'; + wrap.append(heading); + + const list = document.createElement('ul'); + + // todo: related article magic 🪄 + list.innerHTML = '
  • Dummy list item
  • Dummy list item 2
  • '; + + wrap.append(list); + + return wrap; +} + +async function getCategories() { + const wrap = document.createElement('div'); + wrap.className = 'sidebar-categories'; + + const heading = document.createElement('h3'); + heading.textContent = 'CATEGORY'; + wrap.append(heading); + + const currentCategoryPath = window.location.pathname.split('/').slice(0, 3).join('/'); + const categoriesList = await fetchCategoryList(); + // get the current category name + categoriesList.forEach((category) => { + const categoryPath = category.path.split('/') + .slice(0, 3) + .join('/'); + + if (categoryPath === currentCategoryPath) { + heading.innerText = category.path + .split('/') + .pop() + .replace(/-/g, ' ') + .replace(/\b\w/g, (char) => char.toUpperCase()); + } + }); + + const list = document.createElement('ul'); + + // todo: fetch sub-categories from index + list.innerHTML = '
  • Dummy list item
  • Dummy list item 2
  • '; + + wrap.append(list); + + return wrap; +} + +export default async function decorate(block) { + const categories = await getCategories(); + block.append(categories); + + const relatedArticles = getRelatedArticles(); + block.append(relatedArticles); + + return block; +} diff --git a/best-cigars-guide/icons/star-empty.png b/best-cigars-guide/icons/star-empty.png new file mode 100644 index 0000000..a28fbb4 Binary files /dev/null and b/best-cigars-guide/icons/star-empty.png differ diff --git a/best-cigars-guide/icons/star-half.png b/best-cigars-guide/icons/star-half.png new file mode 100644 index 0000000..2b78ab9 Binary files /dev/null and b/best-cigars-guide/icons/star-half.png differ diff --git a/best-cigars-guide/icons/star.png b/best-cigars-guide/icons/star.png new file mode 100644 index 0000000..098181d Binary files /dev/null and b/best-cigars-guide/icons/star.png differ diff --git a/best-cigars-guide/scripts/scripts.js b/best-cigars-guide/scripts/scripts.js index 3a0ffc2..330918e 100644 --- a/best-cigars-guide/scripts/scripts.js +++ b/best-cigars-guide/scripts/scripts.js @@ -1,6 +1,20 @@ /* eslint-disable max-len */ // eslint-disable-next-line object-curly-newline -import { sampleRUM, buildBlock, loadHeader, loadFooter, decorateButtons, decorateIcons, decorateSections, decorateBlocks, decorateTemplateAndTheme, waitForLCP, loadBlocks, loadCSS } from './aem.js'; +import { + sampleRUM, + buildBlock, + loadHeader, + loadFooter, + decorateButtons, + decorateIcons, + decorateSections, + decorateBlocks, + decorateTemplateAndTheme, + waitForLCP, + loadBlocks, + loadCSS, + decorateBlock, +} from './aem.js'; const LCP_BLOCKS = []; // add your LCP blocks to the list const CATEGORY_INDEX_PATH = '/best-cigars-guide/index/category-index.json'; @@ -47,6 +61,34 @@ function buildHeroBlock(main) { } } +/** + * check if this is a category listing page + */ +export function isCategory() { + return !!document.querySelector('.article-list-container, main.error'); +} + +/** + * builds sidebar block appends to main + * @param {Element} main The container element + */ +function buildSidebarBlock(main) { + const sidebarBlock = document.querySelector('main aside'); + + if (!isCategory() && !sidebarBlock && main.tagName === 'MAIN') { + const container = document.querySelector('main'); + const sidebar = document.createElement('aside'); + sidebar.className = 'sidebar-wrapper'; + + const block = buildBlock('sidebar', ''); + sidebar.append(block); + decorateBlock(block); + + container.classList.add('article-wrapper'); + container.append(sidebar); + } +} + /** * load fonts.css and set a session storage flag */ @@ -84,6 +126,7 @@ export function decorateMain(main) { buildAutoBlocks(main); decorateSections(main); decorateBlocks(main); + buildSidebarBlock(main); } /** diff --git a/best-cigars-guide/styles/styles.css b/best-cigars-guide/styles/styles.css index ba20c72..0c6bd05 100644 --- a/best-cigars-guide/styles/styles.css +++ b/best-cigars-guide/styles/styles.css @@ -12,8 +12,8 @@ :root { /* colors */ - --link-color: #035fe6; - --link-hover-color: #136ff6; + --link-color: #177abb; + --link-hover-color: #177abb; --header-color: #2c2c2c; --paragraph-color: #4a4a4a; --background-color: white; @@ -242,12 +242,12 @@ main img { /* sections */ main .section { - padding: 16px; + padding: 0 16px 16px; } @media (min-width: 600px) { main .section { - padding: 32px; + padding: 0 32px 32px; } } @@ -263,3 +263,13 @@ main .section.light, main .section.highlight { background-color: var(--light-color); } + +.default-content-wrapper { + font-size: 0.75em; + font-weight: 300; +} + +.default-content-wrapper h1 { + font-weight: 700; + margin: 0 0 1.2em; +}