diff --git a/blocks/agent-about/agent-about.css b/blocks/agent-about/agent-about.css deleted file mode 100644 index 29fbbb77..00000000 --- a/blocks/agent-about/agent-about.css +++ /dev/null @@ -1,99 +0,0 @@ -.agent-about.block { - display: flex; - flex-direction: column; - margin-top: 3rem; - line-height: var(--line-height-m); - font-size: var(--body-font-size-xs); - letter-spacing: normal; -} - -.agent-about.block .hide { - display: none; -} - -.agent-about.block a.view-more::after, -.agent-about.block a.view-less::after { - display: inline-block; - margin-top: 1rem; - text-decoration: underline; - font-size: var(--body-font-size-xs); - color: var(--black); -} - -.agent-about.block a.view-more::after { - content: "View More"; -} - -.agent-about.block a.view-less::after { - content: "View Less"; -} - -.agent-about.block>div.cols-1, -.agent-about.block>div.cols-2, -.agent-about.block>div.cols-3 { - padding-bottom: 2rem; -} - -.agent-about.block>div>div:first-of-type { - font-size: var(--body-font-size-s); - font-weight: var(--font-weight-bold); - margin-bottom: 0.5rem; - text-transform: capitalize; -} - -.agent-about.block ul { - list-style: unset; - margin: 0 0 0 1.25rem; -} - -@media (min-width: 600px) { - .agent-about.block { - flex-direction: row; - } - - .agent-about.block>div.cols-1 { - flex: 0 0 41.6667%; - max-width: 41.6667%; - padding-right: 1rem; - } - - .agent-about.block>div.cols-2 { - flex: 0 0 33.33%; - max-width: 33.33%; - padding-left: 1rem; - padding-right: 1rem; - } - - .agent-about.block>div.cols-3 { - flex: 0 0 25%; - max-width: 25%; - padding-left: 1rem; - padding-right: 1rem; - } -} - -@media (min-width: 900px) { - .agent-about.block>div.cols-1 { - flex: 0 0 50%; - max-width: 50%; - } - - .agent-about.block>div.cols-2, - .agent-about.block>div.cols-3 { - flex: 0 0 25%; - max-width: 25%; - } - - .agent-about.block { - font-size: var(--body-font-size-s); - } - - .agent-about.block>div>div:first-of-type { - font-size: var(--body-font-size-m); - } - - .agent-about.block a.view-more::after, - .agent-about.block a.view-less::after { - font-size: var(--body-font-size-s); - } -} diff --git a/blocks/agent-about/agent-about.js b/blocks/agent-about/agent-about.js deleted file mode 100644 index fabeecae..00000000 --- a/blocks/agent-about/agent-about.js +++ /dev/null @@ -1,78 +0,0 @@ -import { getMetadata } from '../../scripts/aem.js'; -import { - a, div, ul, li, -} from '../../scripts/dom-helpers.js'; - -const viewMoreOnClick = (name, anchor, block) => { - anchor.addEventListener('click', () => { - if (anchor.classList.contains('view-more')) { - anchor.classList.remove('view-more'); - anchor.classList.add('view-less'); - block.querySelector(`.${name}`).classList.remove('hide'); - block.querySelector(`.${name}-truncate`).classList.add('hide'); - } else { - anchor.classList.remove('view-less'); - anchor.classList.add('view-more'); - block.querySelector(`.${name}`).classList.add('hide'); - block.querySelector(`.${name}-truncate`).classList.remove('hide'); - } - }); -}; - -const getCol = (list, colText) => { - const colsUl = ul(); - list.split(',').forEach((x) => { - colsUl.append(li(x.trim())); - }); - return div(div(colText), div(colsUl)); -}; - -export default function decorate(block) { - const aboutText = getMetadata('about'); - const accreditations = getMetadata('professional-accreditations'); - const languages = getMetadata('languages'); - - block.replaceChildren(div(div('About'), div(aboutText)), - getCol(accreditations, 'Professional Accreditations'), - getCol(languages, 'Languages')); - - const children = [...block.children]; - if (children?.length) { - children.forEach((child, index) => { - child.classList.add(`cols-${index + 1}`); - if (index === 0) { - const name = 'about-text'; - const threshold = 245; - child.children[1].classList.add(name); - if (child.children[1].textContent > threshold) { - child.children[1].classList.add('hide'); - child.append(div({ class: `${name}-truncate` }, - `${child.children[1].textContent.substring(0, threshold)}...`)); - const anchor = a({ class: 'view-more', href: '#' }); - child.append(anchor); - viewMoreOnClick(name, anchor, block); - } - } else { - const threshold = 3; - const name = child.children[0].textContent.toLowerCase().replace(/\s/g, '-'); - const liItems = child.children[1].querySelectorAll('li'); - child.children[1].classList.add(name); - - if (liItems.length > threshold) { - child.children[1].classList.add('hide'); - const tempUl = ul(); - Array.from(child.children[1].querySelectorAll('li')) - .slice(0, threshold).forEach((liItem) => { - const tempLi = li(liItem.textContent); - tempUl.append(tempLi); - }); - - child.append(div({ class: `${name}-truncate` }, tempUl)); - const anchor = a({ class: 'view-more', href: '#' }); - child.append(anchor); - viewMoreOnClick(name, anchor, block); - } - } - }); - } -} diff --git a/blocks/agent-address/agent-address.css b/blocks/agent-address/agent-address.css deleted file mode 100644 index bc074896..00000000 --- a/blocks/agent-address/agent-address.css +++ /dev/null @@ -1,35 +0,0 @@ -.agent-address.block { - padding: 2rem; - background-color: var(--tertiary-color); -} - -.agent-address.block .address { - margin-bottom: 2rem; -} - -.agent-address.block .address>p { - margin-bottom: 0; - font-size: var(--body-font-size-xs); -} - -.agent-address.block a { - border: 1px solid var(--primary-color); - color: var(--primary-color); - font-weight: var(--font-weight-bold); - letter-spacing: var(--letter-spacing-m); - text-transform: uppercase; - padding: 0.5rem 1rem; - text-decoration: none; - font-size: var(--body-font-size-s); -} - -.agent-address.block a:hover { - color: var(--primary-light); - background-color: var(--primary-color); -} - -@media (min-width: 600px) { - .agent-address.block { - display: none; - } -} diff --git a/blocks/agent-address/agent-address.js b/blocks/agent-address/agent-address.js deleted file mode 100644 index 187419f0..00000000 --- a/blocks/agent-address/agent-address.js +++ /dev/null @@ -1,22 +0,0 @@ -import { getMetadata } from '../../scripts/aem.js'; -import { - a, div, p, -} from '../../scripts/dom-helpers.js'; - -export default function decorate(block) { - const streetAddress = getMetadata('streetaddress'); - const addressLocality = getMetadata('addresslocality'); - const addressRegion = getMetadata('addressregion'); - const postalCode = getMetadata('postalcode'); - - const textDiv = div({ class: 'address' }, - p('Berkshire Hathaway HomeServices'), - p('Commonwealth Real Estate'), - p(streetAddress), - p(`${addressLocality}, ${addressRegion} ${postalCode}`), - ); - const text = `${streetAddress}, ${addressLocality}, ${addressRegion} ${postalCode}`; - - const anchor = a({ href: `https://maps.google.com/maps?q=${text}`, target: '_blank' }, 'Directions'); - block.replaceChildren(textDiv, anchor); -} diff --git a/blocks/agent-communities/agent-communities.css b/blocks/agent-communities/agent-communities.css new file mode 100644 index 00000000..d48ad79a --- /dev/null +++ b/blocks/agent-communities/agent-communities.css @@ -0,0 +1,242 @@ +@import url('./design-1.css'); + +.agent-communities.block { + min-height: 1000px; +} + +.agent-communities.block .cards-list { + display: flex; + flex-wrap: wrap; + + --anim-speed: 0.2s; + --zoom: 10px; + --columns: 1; +} + +.agent-communities.block .cards-list .cards-item { + height: 11.5rem; + flex-basis: calc(100% / var(--columns) - 20px); + margin: 10px; + cursor: pointer; + transition: flex-basis var(--anim-speed) ease-in-out; +} + +.agent-communities.block .cards-list .cards-item:first-of-type { + order: 1; + border: 1px solid var(--primary-color); +} + +.agent-communities.block .cards-list .cards-item-body h4 { + padding-top: 5rem; + color: var(--white); + text-align: center; + font-weight: var(--font-weight-bold); + height: 100%; + text-transform: uppercase; + font-size: var(--heading-font-size-s); + filter: drop-shadow(0 0 2px var(--black)); + background: linear-gradient(transparent, transparent, rgba(0 0 0 / 50%)); +} + +.agent-communities.block .cards-list .cards-item-body h4:hover { + background: unset; +} + +.agent-communities.block .cards-list .cards-item-body h4::before { + font-size: var(--heading-font-size-m); + font-weight: var(--font-weight-bold); + content: 'Explore '; +} + +.agent-communities.block .cards-list .cards-item:first-of-type h4 { + color: var(--primary-color); + background: unset; + filter: unset; +} + +.agent-communities.block .hero-item { + margin: 10px 10px 2rem; + display: flex; + flex-direction: column; +} + +.agent-communities.block .hero-item img { + width: 100%; + height: fit-content; + object-fit: cover; + margin-bottom: 10px; + background-position: center 70%; + background-size: cover; + background-repeat: no-repeat; +} + +.agent-communities.block .hero-item-explore { + text-transform: uppercase; + color: var(--primary-color); + border: solid 1px var(--primary-color); + margin: auto; + padding: .5rem .75rem; + text-decoration: none; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); +} + +.agent-communities.block .hero-item-explore:hover { + color: var(--primary-light); + background-color: var(--primary-color); +} + +.agent-communities.block .hero-item-heading { + text-transform: uppercase; + font-size: var(--body-font-size-s); + letter-spacing: 3.2px; + font-weight: var(--font-weight-bold); +} + +.agent-communities.block .hero-item-bio { + font-size: var(--body-font-size-s); + line-height: var(--line-height-m); + margin-top: 0.5rem; +} + +.agent-communities.block .cards-list .cards-item-body { + width: 100%; + height: 100%; + background-size: cover; +} + +.agent-communities.block .cards-list .cards-item-body:hover { + width: calc(100% + var(--zoom)); + height: calc(100% + var(--zoom)); + margin: calc(0px - var(--zoom)/2); + transition: margin var(--anim-speed) ease-in-out, width var(--anim-speed) ease-in-out, height var(--anim-speed) ease-in-out; +} + +.agent-communities.block .agent-communities-loader { + position: absolute; + display: flex; + justify-content: center; + align-items: center; + top: 0; + left: 50%; + height: 100%; + width: 100%; + max-width: 400px; + transform: translateX(-50%); + margin: 0 auto; + opacity: 0; + visibility: hidden; + transition: all 2s linear; + z-index: 2 +} + +.agent-communities.block.loading .agent-communities-loader { + opacity: 1; + visibility: visible; + transition: all 2s linear; +} + +.agent-communities.block .agent-communities-loader .animation { + position: relative; + width: 100%; +} + +@keyframes pulse { + from { + border: 0 solid white; + } + + to { + border: 75px solid white + } +} + +.agent-communities.block .agent-communities-loader .pulse { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: 50%; + overflow: hidden; + animation: linear 2s infinite alternate pulse; + z-index: 2; +} + +.agent-communities.block .agent-communities-loader picture { + position: relative; + display: block; + width: 100%; + padding-bottom: 100%; + border-radius: 50%; + overflow: hidden; +} + +.agent-communities.block .agent-communities-loader picture img { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-position: center; + object-fit: cover; +} + +@media (min-width: 600px) { + .agent-communities.block .cards-list { + --columns: 2; + } + + .agent-communities.block .hero-item img { + height: 18.5rem; + } + + .agent-communities.block .hero-item-explore { + padding: .85rem 1.15rem; + font-size: var(--body-font-size-s); + margin-left: 0; + margin-bottom: 0; + } + + .agent-communities.block .cards-list .cards-item-body h4 { + font-size: var(--heading-font-size-m); + } + + .agent-communities.block .hero-item-heading { + color: var(--black); + padding: 1rem 2rem 0 0; + background: var(--white); + width: fit-content; + min-width: 18.75rem; + } + + .agent-communities.block .hero-item-heading, + .agent-communities.block .hero-item-bio, + .agent-communities.block .hero-item-explore { + position: relative; + top: -3.125rem; + } + + .agent-communities.block .hero-item { + margin-bottom: 0; + } +} + +@media (min-width: 1200px) { + .agent-communities.block .cards-list { + --columns: 4; + } + + .agent-communities.block .hero-item-bio { + font-size: var(--body-font-size-m); + line-height: var(--line-height-m); + } + + .agent-communities.block .hero-item img { + height: 31.25rem; + } + + .agent-communities.block .hero-item-heading { + font-size: var(--body-font-size-m); + } +} diff --git a/blocks/agent-communities/agent-communities.js b/blocks/agent-communities/agent-communities.js new file mode 100644 index 00000000..328da9f4 --- /dev/null +++ b/blocks/agent-communities/agent-communities.js @@ -0,0 +1,109 @@ +import { + a, div, + img, + span, + p, +} from '../../scripts/dom-helpers.js'; +import { getLoader } from '../../scripts/util.js'; + +export default async function decorate(block) { + block.classList.add('cards', 'loading'); + block.appendChild(getLoader('agent-communities')); + + window.setTimeout(async () => { + const url = `/commonwealth-real-estate-ma312${window.location.pathname}`; + const bhhsCode = 'bhhs-ma312'; + + const finalUrl = new URL('https://api.liveby.com/v1/pages'); + finalUrl.search = new URLSearchParams({ + id: bhhsCode, + ref: url, + }); + + try { + const response1 = await fetch(finalUrl, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + const data1 = await response1.json(); + + const response2 = await fetch('https://api.liveby.com/v1/neighborhood-brokerage-lookup/pages', { + method: 'POST', + body: JSON.stringify({ + brokerage: bhhsCode, + child_pages: data1.child_pages, + }), + }); + + const data2 = await response2.json(); + const modifiedData = []; + + if (data1) { + const heroItemDiv = div({ class: 'hero-item' }, + img({ src: data1.banner_16x9 }), + span({ class: 'hero-item-heading' }, data1.name), + p({ class: 'hero-item-bio' }, data1.bio), + a({ class: 'hero-item-explore', href: `/communities/${data1.name.split(' ').join('-').toLowerCase()}` }, `Explore ${data1.name}`), + ); + + block.replaceChildren(heroItemDiv); + } + + if (data2.length) { + modifiedData.push(...data2.map((item) => { + const regex = /\/communities/; + const match = item.url.match(regex); + const link = match ? match[0] : ''; + + if (link) { + return { + name: item.name.toUpperCase(), + exploreName: `${item.name}`, + link, + banner: item.banner_16x9, + }; + } + return null; + }).filter((item) => item !== undefined && item !== null)); + } + + const cardsList = div({ class: 'cards-list' }); + modifiedData.forEach((item) => { + const card = div({ class: 'cards-item' }); + cardsList.appendChild(card); + + const cardBody = div({ class: 'cards-item-body' }); + card.appendChild(cardBody); + + cardBody.onclick = () => { + document.location.href = item.link; + }; + + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + if (item.banner) { + cardBody.style.backgroundImage = `url(${item.banner})`; + } + observer.unobserve(cardBody); + } + }); + }); + observer.observe(cardBody); + + const paragraphElement = document.createElement(('h4')); + paragraphElement.textContent = item.exploreName; + cardBody.appendChild(paragraphElement); + }); + + if (cardsList.hasChildNodes()) { + block.appendChild(cardsList); + } + } catch (error) { + // eslint-disable-next-line no-console + console.error('Error fetching data', error); + } + }, 3000); +} diff --git a/blocks/agent-communities/design-1.css b/blocks/agent-communities/design-1.css new file mode 100644 index 00000000..308df5f0 --- /dev/null +++ b/blocks/agent-communities/design-1.css @@ -0,0 +1,34 @@ +.design-1 .agent-communities.block .cards-list .cards-item-body h4 { + font-family: var(--font-family-secondary); + font-size: 2rem; + text-transform: none; + padding-top: 3rem; +} + +.design-1 .agent-communities.block .cards-list .cards-item-body h4::before { + font-size: 1rem; + line-height: var(--line-height-m); + letter-spacing: var(--letter-spacing-l); + display: block; + text-align: center; + margin-bottom: 0.5rem; +} + +/* +Theme: Black & White +*/ +.design-1.black-white .agent-communities.block .hero-item-explore { + color: var(--black); + border: solid 1px var(--black); +} + +.design-1.black-white .agent-communities.block .hero-item-explore:hover { + color: var(--white); + background-color: var(--black); +} + +.design-1.black-white .agent-communities.block .cards-list .cards-item:first-of-type h4 { + color: var(--black); + padding-left: 0.5rem; + padding-right: 0.5rem; +} diff --git a/blocks/agent-profile/agent-profile.css b/blocks/agent-profile/agent-profile.css index fa575e7f..a4885da1 100644 --- a/blocks/agent-profile/agent-profile.css +++ b/blocks/agent-profile/agent-profile.css @@ -1,20 +1,12 @@ +@import url('./design-1.css'); + .agent-profile.block { - display: flex; padding: 0 1rem; + gap: 3rem; } -main .section.agent-profile-container .agent-profile-wrapper { - word-break: break-word; -} - -.agent-profile.block .profile-image img { - width: 9.375rem; - height: 11.875rem; -} - -.agent-profile.block .profile-content .contact-me { - margin-top: 1.5rem; - display: none; +.agent-profile.block .profile-details { + display: flex; } .agent-profile.block .profile-content { @@ -22,31 +14,71 @@ main .section.agent-profile-container .agent-profile-wrapper { font-size: var(--body-font-size-s); } -.agent-profile.block .profile-content .name { +.agent-profile.block .profile-content > div { + margin-bottom: 0.5rem; +} + +.agent-profile.block .profile-content h1 { font-size: var(--body-font-size-xl); line-height: var(--line-height-m); - margin-bottom: 0.5rem; + font-weight: var(--font-weight-bold); } .agent-profile.block .profile-content .designation, .agent-profile.block .profile-content .license-number { font-size: var(--body-font-size-xs); text-transform: uppercase; - margin-bottom: 0.25rem; +} + +main .section.agent-profile-container .agent-profile-wrapper { + word-break: break-word; +} + +.agent-profile.block .profile-image img { + width: 9.375rem; + aspect-ratio: 1 / 1.5; + object-fit: cover; +} + +.agent-profile.block .profile-content .contact-me { + display: none; +} + +.agent-profile.block .lang-prof-accred ul { + margin-top: 1rem; } .agent-profile.block .profile-content .social ul { display: flex; - margin-top: 1rem; - opacity: .5; +} + +.agent-profile.block .lang-prof-accred li { + list-style: outside; + margin-left: 1rem; +} + +.agent-profile.block .profile-content .phone li { + margin-bottom: 0.5rem; } .agent-profile.block .profile-content .social li { margin-right: 0.5rem; } +.agent-profile.block .address a { + border: 1px solid var(--primary-color); + color: var(--primary-color); + font-weight: var(--font-weight-bold); + letter-spacing: var(--letter-spacing-m); + text-transform: uppercase; + padding: 0.5rem 1rem; + text-decoration: none; + font-size: var(--body-font-size-xs); +} + .agent-profile.block .profile-content .email a, .agent-profile.block .profile-content .website a { + line-height: var(--line-height-xs); font-size: var(--body-font-size-xs); color: var(--black); text-transform: lowercase; @@ -63,27 +95,106 @@ main .section.agent-profile-container .agent-profile-wrapper { text-decoration: none; } -.agent-profile.block .profile-content .contact-me a:hover { +.agent-profile.block .address a:hover { color: var(--primary-light); background-color: var(--primary-color); } -.agent-profile.block .profile-content .website, -.agent-profile.block .profile-content .email { - margin-bottom: 0.25rem; +.agent-profile.block .profile-content .contact-me a:hover { + color: var(--primary-light); + background-color: var(--primary-color); } .agent-profile.block .profile-content .phone { font-size: var(--body-font-size-xs); } -.agent-profile.block .profile-content .phone li { - margin-bottom: 0.25rem; +.agent-profile.block .address { + padding: 2rem; + background-color: var(--tertiary-color); + margin-top: 1.5rem; +} + +.agent-profile.block .address>p { + margin-bottom: 0; + font-size: var(--body-font-size-xs); +} + +.agent-profile.block .address>p:last-of-type { + margin-bottom: 2rem; +} + +.agent-profile.block .about-non-truncate.hide, +.agent-profile.block .languages-non-truncate.hide, +.agent-profile.block .professional-accreditations-non-truncate.hide, +.agent-profile.block .about-truncate.hide, +.agent-profile.block .languages-truncate.hide, +.agent-profile.block .professional-accreditations-truncate.hide { + display: none; +} + +.agent-profile.block .about { + margin: 1rem 0 2rem; + font-size: var(--body-font-size-s); + line-height: var(--line-height-xs); +} + +.agent-profile.block .lang-prof-accred .languages, +.agent-profile.block .lang-prof-accred .professional-accreditations { + margin-bottom: 2rem; + font-size: var(--body-font-size-s); + line-height: var(--line-height-xs); +} + + +.agent-profile.block .about::before { + content: 'About'; + font-weight: var(--font-weight-bold); +} + +.agent-profile.block .lang-prof-accred .languages::before { + content: 'Languages'; + font-weight: var(--font-weight-bold); +} + +.agent-profile.block .lang-prof-accred .professional-accreditations::before { + content: 'Professional Accreditations'; + font-weight: var(--font-weight-bold); +} + +.agent-profile.block .about>div { + margin-top: 0.75rem; +} + +.agent-profile.block a.view-more::after, +.agent-profile.block a.view-less::after { + display: inline-block; + margin-top: 0.5rem; + text-decoration: underline; + font-size: var(--body-font-size-s); + color: var(--black); +} + +.agent-profile.block a.view-more::after { + content: "View More"; +} + +.agent-profile.block a.view-less::after { + content: "View Less"; } @media (min-width: 600px) { + .agent-profile.block .about { + margin-top: 0; + } + .agent-profile.block .profile-content .contact-me { display: block; + margin: 1.5rem 0; + } + + .agent-profile.block .address { + display: none; } } @@ -92,41 +203,26 @@ main .section.agent-profile-container .agent-profile-wrapper { position: relative; } - main .section.agent-profile-container .agent-profile-wrapper { + .agent-profile.block .profile-details { position: absolute; display: flex; left: auto; width: 34rem; right: 0; - bottom: 4.625rem; + top: -29rem; padding: 1.875rem 1.875rem 0; z-index: 1; background-color: var(--white); } .agent-profile.block { - position: relative; + display: flex; line-height: var(--line-height-s); } .agent-profile.block .profile-image img { width: 13.125rem; - height: 15.625rem; - } - - .agent-profile.block .profile-content .phone { - font-size: var(--body-font-size-s); - margin-top: 2px; - line-height: var(--line-height-m); - } - - .agent-profile.block .profile-content .email a, - .agent-profile.block .profile-content .website a { - font-size: var(--body-font-size-xs); - } - - .agent-profile.block .profile-content { - padding-left: 1.875rem; + height: 22rem; } .agent-profile.block .profile-content .designation, @@ -137,4 +233,14 @@ main .section.agent-profile-container .agent-profile-wrapper { .agent-profile.block .profile-content .phone li { margin-bottom: unset; } + + .agent-profile.block .lang-prof-accred { + gap: 3rem; + display: flex; + flex-basis: 40%; + } + + .agent-profile.block .about { + flex-basis: 60%; + } } diff --git a/blocks/agent-profile/agent-profile.js b/blocks/agent-profile/agent-profile.js index 191b685f..d01ee2b4 100644 --- a/blocks/agent-profile/agent-profile.js +++ b/blocks/agent-profile/agent-profile.js @@ -1,6 +1,6 @@ import { decorateIcons, getMetadata } from '../../scripts/aem.js'; import { - a, div, h1, ul, li, img, span, + a, div, h1, ul, li, img, span, p, } from '../../scripts/dom-helpers.js'; const getPhoneDiv = () => { @@ -79,7 +79,26 @@ const getSocialDiv = () => { return null; }; -export default async function decorate(block) { +const decorateAddress = (block) => { + const streetAddress = getMetadata('street-address'); + const city = getMetadata('city'); + const state = getMetadata('state'); + const zip = getMetadata('zip'); + const text = `${streetAddress}, ${city}, ${state} ${zip}`; + + const addressDiv = div({ class: 'address' }, + p('Berkshire Hathaway HomeServices'), + p('Commonwealth Real Estate'), + p(streetAddress), + p(`${city}, ${state} ${zip}`), + a({ href: `https://maps.google.com/maps?q=${text}`, target: '_blank' }, 'Directions'), + ); + + block.append(addressDiv); +}; + +const decorateProfileDetails = (block) => { + const profileDetails = div({ class: 'profile-details' }); const profileImage = getImageDiv(); const profileContent = div({ class: 'profile-content' }, div({ class: 'name' }, h1(getMetadata('name'))), @@ -114,6 +133,73 @@ export default async function decorate(block) { if (socialDiv) { profileContent.append(socialDiv); } + decorateIcons(profileContent); - block.replaceChildren(profileImage, profileContent); + profileDetails.append(profileImage, profileContent); + block.replaceChildren(profileDetails); +}; + +const viewMoreOnClick = (name, anchor, block) => { + anchor.addEventListener('click', (event) => { + event.preventDefault(); + if (anchor.classList.contains('view-more')) { + anchor.classList.remove('view-more'); + anchor.classList.add('view-less'); + block.querySelector(`.${name}-non-truncate`).classList.remove('hide'); + block.querySelector(`.${name}-truncate`).classList.add('hide'); + } else { + anchor.classList.remove('view-less'); + anchor.classList.add('view-more'); + block.querySelector(`.${name}-non-truncate`).classList.add('hide'); + block.querySelector(`.${name}-truncate`).classList.remove('hide'); + } + }); +}; + +const decorateAbout = (block) => { + const text = 'about'; + const aboutText = getMetadata(text); + const aboutDiv = div({ class: text }); + const threshold = 245; + aboutDiv.append(div({ class: `${text}-truncate` }, aboutText.substring(0, threshold))); + aboutDiv.append(div({ class: `${text}-non-truncate hide` }, aboutText)); + aboutDiv.append(a({ href: '#', class: 'view-more' })); + viewMoreOnClick(text, aboutDiv.querySelector('a'), block); + block.append(aboutDiv); +}; + +const createLangoOrProfAccred = (key, langProfAccredDiv) => { + const threshold = 3; + const truncateDiv = ul({ class: `${key}-truncate` }); + const nontruncateDiv = ul({ class: `${key}-non-truncate hide` }); + + getMetadata(key).split(',').filter((x) => x).forEach((x, index) => { + if (index < threshold) { + truncateDiv.append(li(x.trim())); + } + nontruncateDiv.append(li(x.trim())); + }); + + const anchor = a({ href: '#', class: 'view-more' }); + langProfAccredDiv.append(div({ class: key }, + truncateDiv, + nontruncateDiv, + anchor, + )); + + viewMoreOnClick(key, anchor, langProfAccredDiv); +}; + +const decorateLangProfAccred = (block) => { + const langProfAccredDiv = div({ class: 'lang-prof-accred' }); + createLangoOrProfAccred('languages', langProfAccredDiv); + createLangoOrProfAccred('professional-accreditations', langProfAccredDiv); + block.append(langProfAccredDiv); +}; + +export default async function decorate(block) { + decorateProfileDetails(block); + decorateAbout(block); + decorateLangProfAccred(block); + decorateAddress(block); } diff --git a/blocks/agent-profile/design-1.css b/blocks/agent-profile/design-1.css new file mode 100644 index 00000000..98069465 --- /dev/null +++ b/blocks/agent-profile/design-1.css @@ -0,0 +1,190 @@ +.design-1 .agent-profile.block { + display: flex; + flex-direction: column; + gap: 2rem; +} + +.design-1 .agent-profile.block .profile-details { + position: relative; + top: unset; + flex-direction: column; + display: flex; + margin-top: 2rem; +} + +.design-1 .agent-profile.block .profile-content { + font-size: var(--body-font-size-l); + font-weight: var(--font-weight-bold); + padding-left: 0; +} + +.design-1 .agent-profile.block .profile-content div { + margin-bottom: 0.5rem; +} + +.design-1 .agent-profile.block .profile-content .name h1 { + font-family: var(--font-family-secondary); + font-size: var(--body-font-size-xxxl); + margin-bottom: 2rem; + margin-top: 1rem; +} + +.design-1.traditional .agent-profile.block .profile-content .name h1 { + color: var(--primary-color); +} + +.design-1 .agent-profile.block .about { + margin-bottom: 0; + letter-spacing: var(--letter-spacing-xs); +} + +.design-1 .agent-profile.block .lang-prof-accred { + letter-spacing: var(--letter-spacing-xs); +} + +.design-1 .agent-profile.block .profile-image img { + width: 100%; + aspect-ratio: 1/1; + max-width: calc((100% - 60px * 2)); + margin: 0 auto; + object-fit: cover; + height: fit-content; +} + +.design-1.traditional .agent-profile.block .profile-image img { + box-shadow: var(--primary-color) 3rem -3rem; +} + +.design-1 .agent-profile.block .profile-content .contact-me { + display: none; + font-size: var(--body-font-size-s); +} + +.design-1 .agent-profile.block .profile-image { + display: flex; +} + +.design-1.traditional .agent-profile.block .address { + background-color: var(--primary-color); +} + +.design-1.traditional .agent-profile.block .address p { + color: var(--white); +} + +.design-1.black-white .agent-profile.block .address a { + color: var(--white); + border: 1px solid var(--white); +} + +.design-1.traditional .agent-profile.block .address a { + color: var(--white); + border: 1px solid var(--white); +} + +.design-1.black-white .agent-profile.block .address a:hover { + background-color: var(--white); + color: var(--black); +} + +.design-1.traditional .agent-profile.block .address a:hover { + color: var(--primary-color); + background-color: var(--primary-light); +} + +.design-1.black-white .agent-profile.block .profile-image img { + box-shadow: var(--black) 4.375rem -4.375rem; +} + +.design-1.black-white .agent-profile.block .profile-content .name { + color: var(--black); +} + +.design-1.black-white .agent-profile.block .profile-content .name h1 { + color: var(--black); +} + +.design-1.black-white .agent-profile.block .profile-content .contact-me a { + color: var(--black); + border: 1px solid var(--black); +} + +.design-1.black-white .agent-profile.block .profile-content .contact-me a:hover { + background-color: var(--black); + color: var(--white); +} + +.design-1.black-white .agent-profile.block .address { + background-color: var(--black); +} + +.design-1.black-white .agent-profile.block .address p { + color: var(--white); +} + +@media (min-width: 900px) { + .design-1 .agent-profile.block { + position: relative; + } + + .design-1 .agent-profile.block .profile-details { + flex-direction: row-reverse; + } + + .design-1 .agent-profile.block .profile-content .name h1 { + font-size: 2.75rem; + margin-top: 0; + } + + .design-1 .agent-profile.block .profile-image { + flex-basis: 60%; + } + + .design-1 .agent-profile.block .profile-content { + flex-basis: 40%; + margin-top: 0; + } + + .design-1 .agent-profile.block .profile-image img { + margin-top: 70px; + position: absolute; + width: 50%; + margin-left: calc(0.025 * 100vw); + } + + .design-1.traditional .agent-profile.block .profile-image img { + box-shadow: var(--primary-color) 4.375rem -4.375rem; + } + + .design-1 .agent-profile.block .profile-content .contact-me { + margin-top: 2rem; + margin-bottom: 1rem; + display: block; + } + + .design-1 .agent-profile.block .about { + flex-basis: 0; + width: 40%; + } + + .design-1 .agent-profile.block .lang-prof-accred { + display: flex; + gap: 2rem; + } + + .design-1 .agent-profile.block .profile-content div { + font-size: var(--body-font-size-s); + } + + .design-1 .agent-profile.block .profile-content .email a, + .design-1 .agent-profile.block .profile-content .website a { + font-size: var(--body-font-size-s); + } +} + +@media (min-width: 1200px) { + .design-1 .agent-profile.block .profile-details { + padding: 0; + width: unset; + } +} diff --git a/blocks/agent-property/agent-property.css b/blocks/agent-property/agent-property.css new file mode 100644 index 00000000..fbbef556 --- /dev/null +++ b/blocks/agent-property/agent-property.css @@ -0,0 +1,100 @@ +@import url('../shared/property/cards.css'); + +.agent-property.block { + overflow: hidden; + width: 100%; +} + +.agent-property.block a { + text-decoration: none; +} + +.agent-property.block .gmap-canvas { + width: 100%; + height: 0; + transition: height 0.5s ease; + display: none; +} + +.agent-property.block .view-toggle { + margin-bottom: 20px; +} + +.agent-property.block .gmap-canvas.active { + display:block; + height: 500px; +} + +.agent-property.block .view-toggle .card-view { + display: none; + margin-left: 70%; + font-family: Manrope, sans-serif; + font-size: 16px; + font-style: normal; + font-weight: 700; + letter-spacing: 1.6px; + text-transform: uppercase; + border: 1px solid #2a2223; + line-height: 35px; + background: #fff; +} + +.agent-property.block .view-toggle .map-view { + margin-left: 70%; + font-family: Manrope, sans-serif; + font-size: 16px; + font-style: normal; + font-weight: 700; + letter-spacing: 1.6px; + text-transform: uppercase; + border: 1px solid #2a2223; + line-height: 35px; + background: #fff; +} + +.agent-property.block .header { + display: flex; + flex-direction: column; +} + +.agent-property.block .header > div { + margin-bottom: 24px; +} + +.agent-property.block .header > div > span { + color: var(--primary-color); + font-size: var(--heading-font-size-l); + font-weight: var(--font-weight-semibold); + letter-spacing: initial; + line-height: var(--line-height-m); + text-transform: capitalize; +} + +.agent-property.block .header > div > p { + margin: 0; +} + +.agent-property.block .property-list-cards .listing-tile .extra-info { + display:none; +} + +.liveby-community .agent-property.block { + max-width: 1150px; + margin: auto; +} + +@media (min-width: 600px) { + .agent-property.block .header { + flex-direction: row; + justify-content: space-between; + } + + .agent-property.block .header .button-container { + justify-content: flex-end; + } + + .agent-property.block .view-toggle .map-view , .agent-property.block .view-toggle .card-view { + margin-left: 90.5%; + width: 115px; + } +} \ No newline at end of file diff --git a/blocks/agent-property/agent-property.js b/blocks/agent-property/agent-property.js new file mode 100644 index 00000000..acef071c --- /dev/null +++ b/blocks/agent-property/agent-property.js @@ -0,0 +1,81 @@ +/* global google */ + +import { render as renderCards } from '../shared/property/cards.js'; +import { button, div } from '../../scripts/dom-helpers.js'; +import loadMaps from '../../scripts/google-maps/index.js'; +import { loadScript, getMetadata } from '../../scripts/aem.js'; + +const cardView = button({ class: 'card-view' }, 'Grid View'); +const mapView = button({ class: 'map-view' }, 'Map View'); +const viewToggle = div({ class: 'view-toggle' }); +const map = div({ class: 'gmap-canvas' }); +const agentId = getMetadata('id'); +let centerlat; +let centerlong; +let data; + +function initMap(block, properties) { + const ele = block.querySelector('.gmap-canvas'); + const gmap = new google.maps.Map(ele, { + zoom: 9, // Set an appropriate zoom level + center: { lat: centerlat, lng: centerlong }, // Set a default center + mapTypeId: google.maps.MapTypeId?.ROADMAP, + clickableIcons: false, + gestureHandling: 'cooperative', + visualRefresh: true, + disableDefaultUI: true, + }); + + const createMarker = (property, amap) => new google.maps.Marker({ + position: { lat: parseFloat(property.Latitude), lng: parseFloat(property.Longitude) }, + map: amap, + title: property.StreetName, + }); + + properties.forEach((property) => { + createMarker(property, gmap); + }); +} + +export default async function decorate(block) { + const list = document.createElement('div'); + list.classList.add('property-list-cards', 'rows-1'); + viewToggle.append(cardView, mapView); + block.append(viewToggle, list, map); + + try { + const response = await fetch(`/bin/bhhs/agentPropertyListingsServlet.${agentId}.json`); + data = await response.json(); + if (data) { + const [firstProperty] = data.listings.properties; + const { Latitude: latitude, Longitude: longitude } = firstProperty; + centerlat = parseFloat(latitude); + centerlong = parseFloat(longitude); + renderCards(list, data.listings.properties); + } + } catch (error) { + // eslint-disable-next-line no-console + console.error('Error fetching agent properties', error); + } + + document.querySelector('.card-view').addEventListener('click', () => { + document.querySelector('.property-list-cards').style.display = 'grid'; + document.querySelector('.card-view').style.display = 'none'; + document.querySelector('.map-view').style.display = 'block'; + document.querySelector('.gmap-canvas').classList.remove('active'); + }); + + document.querySelector('.map-view').addEventListener('click', async () => { + document.querySelector('.gmap-canvas').classList.add('active'); + document.querySelector('.map-view').style.display = 'none'; + document.querySelector('.card-view').style.display = 'block'; + document.querySelector('.property-list-cards').style.display = 'none'; + loadMaps(); + await google.maps.importLibrary('core'); + await google.maps.importLibrary('maps'); + await google.maps.importLibrary('marker'); + await loadScript('https://unpkg.com/@googlemaps/markerclusterer/dist/index.min.js', { type: 'application/javascript' }); + await loadScript('https://unpkg.com/jsts/dist/jsts.min.js', { type: 'application/javascript' }); + initMap(block, data.listings.properties); + }); +} diff --git a/blocks/agent-search/agent-search.css b/blocks/agent-search/agent-search.css index 877db498..80edb34b 100644 --- a/blocks/agent-search/agent-search.css +++ b/blocks/agent-search/agent-search.css @@ -9,6 +9,11 @@ main .section.agent-search-container { position: relative; } +.agent-search.block .loading-spinner { + position: fixed; + top: var(--nav-height); +} + .agent-search.block .search-bar-wrapper { position: relative; width: 100%; diff --git a/blocks/agent-search/agent-search.js b/blocks/agent-search/agent-search.js index cf3165ce..9b13c665 100644 --- a/blocks/agent-search/agent-search.js +++ b/blocks/agent-search/agent-search.js @@ -46,6 +46,7 @@ const search = async () => { }; const updateSearch = async (callback) => { + document.querySelector('body').classList.add('no-scroll'); const block = document.querySelector('.agent-search.block'); const spinner = getSpinner(); block.append(spinner); @@ -78,6 +79,7 @@ const updateSearch = async (callback) => { block.querySelector(RESULTS_SELECTOR).replaceWith(buildResults(agents.value)); spinner.remove(); + document.querySelector('body').classList.remove('no-scroll'); wrapper.scrollIntoView({ behavior: 'smooth' }); }; diff --git a/blocks/agent-search/builders/results.js b/blocks/agent-search/builders/results.js index d952b6ec..c9ac7bcb 100644 --- a/blocks/agent-search/builders/results.js +++ b/blocks/agent-search/builders/results.js @@ -69,7 +69,7 @@ export const buildResults = (list) => { results.append(ul); ul.classList.add('agent-list'); - list.forEach((agent) => ul.append(buildCard(agent))); + list?.forEach((agent) => ul.append(buildCard(agent))); return results; }; diff --git a/blocks/agent-testimonials/agent-testimonials.js b/blocks/agent-testimonials/agent-testimonials.js index 54419661..761f4f1d 100644 --- a/blocks/agent-testimonials/agent-testimonials.js +++ b/blocks/agent-testimonials/agent-testimonials.js @@ -44,7 +44,7 @@ export default function decorate(block) { }); }; - const externalID = getMetadata('externalid'); + const externalID = getMetadata('id'); fetch(`https://testimonialtree.com/Widgets/jsonFeed.aspx?widgetid=45133&externalID=${externalID}`) .then((response) => response.json()) .then((data) => { diff --git a/blocks/agent-transactions/agent-transactions.css b/blocks/agent-transactions/agent-transactions.css index 061fc67c..3519d79c 100644 --- a/blocks/agent-transactions/agent-transactions.css +++ b/blocks/agent-transactions/agent-transactions.css @@ -1,3 +1,5 @@ +@import url('./design-1.css'); + .agent-transactions.block table { width: 100%; font-size: var(--body-font-size-s); @@ -114,7 +116,7 @@ } } -@media (min-width: 992px) { +@media (min-width: 900px) { .agent-transactions.block h1 { font-size: 1.875rem; } diff --git a/blocks/agent-transactions/agent-transactions.js b/blocks/agent-transactions/agent-transactions.js index d7e13c00..ca365caf 100644 --- a/blocks/agent-transactions/agent-transactions.js +++ b/blocks/agent-transactions/agent-transactions.js @@ -4,14 +4,14 @@ import { import { getMetadata } from '../../scripts/aem.js'; const getClosedTransactions = async () => { - const agentId = getMetadata('agent-id'); + const agentId = getMetadata('id'); const formattedData = []; try { const response = await fetch(`/bin/bhhs/agentPropertyListingsServlet.${agentId}.json`); const data = await response.json(); - if (data && data?.closedTransactions?.properties?.length) { + if (data?.closedTransactions?.properties?.length) { data.closedTransactions.properties.forEach((property) => { formattedData.push({ address: property.StreetName, diff --git a/blocks/agent-transactions/design-1.css b/blocks/agent-transactions/design-1.css new file mode 100644 index 00000000..f37a148e --- /dev/null +++ b/blocks/agent-transactions/design-1.css @@ -0,0 +1,42 @@ +.design-1 .agent-transactions.block h1 { + font-family: var(--font-family-secondary); + font-size: 1.75rem; + font-weight: var(--font-weight-normal); + text-align: center; +} + +.design-1 .agent-transactions.block th { + color: var(--white); +} + +@media (min-width: 600px) { + .design-1 .agent-transactions.block h1 { + font-size: 2.25rem; + } +} + +@media (min-width: 1200px) { + .design-1 .agent-transactions.block h1 { + font-size: 2.75rem; + } +} + +/* +---------------------------------------- +* Theme Name: Traditional +*/ +.design-1.traditional .agent-transactions.block thead { + background: var(--primary-color); +} + +/* +---------------------------------------- +* Theme Name: Black & White +*/ +.design-1.black-white .agent-transactions.block h1 { + color: var(--black); +} + +.design-1.black-white .agent-transactions.block thead { + background: var(--black); +} diff --git a/blocks/floating-images/design-1.css b/blocks/floating-images/design-1.css new file mode 100644 index 00000000..d6a9762a --- /dev/null +++ b/blocks/floating-images/design-1.css @@ -0,0 +1,77 @@ +.design-1 .block.floating-images > div { + background-color: var(--white); +} + +.design-1 .block.floating-images .content h2 { + font-size: 2rem; +} + +@media (min-width: 900px) { + .design-1 .block.floating-images .image { + margin-top: 4.375rem; + margin-right: 4.375rem; + } +} + +@media (min-width: 1200px) { + .design-1 .block.floating-images .content h2 { + font-size: var(--heading-font-size-xxl); + } +} + +/** +Theme Name: Traditional +*/ +.design-1.traditional .block.floating-images .content h2 { + color: var(--primary-color); +} + +.design-1.traditional .block.floating-images .content p { + color: var(--primary-color); +} + +.design-1.traditional .block.floating-images .content a { + color: var(--primary-color); + border: 1px solid var(--primary-color); + margin-top: 1rem; +} + +.design-1.traditional .block.floating-images .content a:hover { + background-color: var(--primary-color); + color: var(--primary-light); +} + +@media (min-width: 900px) { + .design-1.traditional .with-border .block.floating-images .image { + box-shadow: var(--primary-color) 4.375rem -4.375rem; + } +} + +/* +Theme Name: Black & White +*/ +.design-1.black-white .block.floating-images .content h2 { + color: var(--black); +} + +.design-1.black-white .block.floating-images .content p { + color: var(--black); +} + +/* stylelint-disable-next-line no-descending-specificity */ +.design-1.black-white .block.floating-images .content a { + color: var(--black); + border: 1px solid var(--black); + margin-top: 1rem; +} + +.design-1.black-white .block.floating-images .content a:hover { + background-color: var(--black); + color: var(--white); +} + +@media (min-width: 900px) { + .design-1.black-white .with-border .block.floating-images .image { + box-shadow: var(--black) 4.375rem -4.375rem; + } +} diff --git a/blocks/floating-images/floating-images.css b/blocks/floating-images/floating-images.css index cbd42254..bc8ac470 100644 --- a/blocks/floating-images/floating-images.css +++ b/blocks/floating-images/floating-images.css @@ -1,5 +1,6 @@ /* styles for the floating images auto block */ @import url('luxury-collection-template.css'); +@import url('./design-1.css'); .block.floating-images { margin-bottom: 5em; @@ -60,6 +61,17 @@ line-height: var(--line-height-m); } +.block.floating-images .content a { + color: var(--primary-color); + border: 1px solid var(--primary-color); + margin-top: 1rem; +} + +.block.floating-images .content a:hover { + background-color: var(--primary-color); + color: var(--primary-light); +} + @media screen and (min-width: 900px) { .block.floating-images > div { flex-direction: row; diff --git a/blocks/floatingagent/floatingagent.css b/blocks/floatingagent/floatingagent.css index 688323d9..7cb39365 100644 --- a/blocks/floatingagent/floatingagent.css +++ b/blocks/floatingagent/floatingagent.css @@ -29,6 +29,7 @@ border: 0; padding: 10px; margin-left: 35%; + text-decoration: none; } @media (min-width: 600px) { diff --git a/blocks/floatingagent/floatingagent.js b/blocks/floatingagent/floatingagent.js index ef0d685c..9b0513e2 100644 --- a/blocks/floatingagent/floatingagent.js +++ b/blocks/floatingagent/floatingagent.js @@ -2,19 +2,20 @@ import { getMetadata, } from '../../scripts/aem.js'; import { - button, + a, div, h2, img, p, strong, } from '../../scripts/dom-helpers.js'; +import { decorateFormLinks } from '../../scripts/scripts.js'; export default function decorate(block) { const agentName = getMetadata('name'); - const agentDesc = getMetadata('desc'); - const pic = getMetadata('pic'); - const lic = getMetadata('lic'); + const agentDesc = getMetadata('description'); + const pic = getMetadata('photo'); + const lic = getMetadata('license-number'); const agentPicture = document.createElement('picture'); agentPicture.appendChild(img({ @@ -32,13 +33,14 @@ export default function decorate(block) { p(lic), ); - const contactButton = button({ class: 'contactagent' }, 'CONTACT AGENT'); + const contactButton = a({ class: 'contactagent', href: '/fragments/contact-property-form' }, 'CONTACT AGENT'); block.append( div({ class: 'floating-agent-col' }, agentPicture), agentInfo, contactButton, ); + decorateFormLinks(block); const displayedElement = document.querySelector('.floatingagent'); const heroElement = document.querySelector('.hero-wrapper'); diff --git a/blocks/fragment/fragment.css b/blocks/fragment/fragment.css index b3c58707..8ee60d37 100644 --- a/blocks/fragment/fragment.css +++ b/blocks/fragment/fragment.css @@ -1 +1,4 @@ /* stylelint-disable-next-line no-empty-source */ +main .section.two-columns > div.fragment-wrapper { + flex: unset; +} diff --git a/blocks/hero/hero.css b/blocks/hero/hero.css index d52e7d8f..05384f08 100644 --- a/blocks/hero/hero.css +++ b/blocks/hero/hero.css @@ -12,6 +12,7 @@ main .section.hero-container { margin-bottom: 57px; justify-content: center; align-items: center; + overflow-x: hidden; } main .section.full-width > .hero-wrapper { diff --git a/blocks/hero/search/home.css b/blocks/hero/search/home.css index 962430b2..8861e65f 100644 --- a/blocks/hero/search/home.css +++ b/blocks/hero/search/home.css @@ -274,3 +274,13 @@ max-height: 185px; } } + +@media screen and (min-width: 1200px) { + .hero.block.small-size > div .content h2 { + max-width: 505px; + } + + .hero.block.small-size .content .homes .filters .select-wrapper .selected::after { + position: relative; + } +} diff --git a/blocks/hero/search/search.css b/blocks/hero/search/search.css index 4d0fa6c9..627eb44a 100644 --- a/blocks/hero/search/search.css +++ b/blocks/hero/search/search.css @@ -85,7 +85,6 @@ display: block; } - .hero.block .content .search-bar .suggester-results > li > ul { padding: 0 15px; } @@ -148,3 +147,9 @@ padding: 10px; } } + +@media screen and (min-width: 1200px) { + .hero.block.small-size .content .search-bar { + max-width: 505px; + } +} diff --git a/blocks/property-listing/property-listing.js b/blocks/property-listing/property-listing.js index 524623ae..30e4e2cc 100644 --- a/blocks/property-listing/property-listing.js +++ b/blocks/property-listing/property-listing.js @@ -11,6 +11,10 @@ export default async function decorate(block) { // Find and process list type configurations. const config = readBlockConfig(block); const search = await Search.fromBlockConfig(config); + if (search.pageSize % 4 !== 0) { + search.pageSize -= (search.pageSize % 4); + } + search.franchiseeCode = getMetadata('office-id'); const searchUrl = `search?${search.asCregURLSearchParameters()}`; @@ -41,7 +45,7 @@ export default async function decorate(block) { } const { contactKey } = user; - const list = div({ class: `property-list-cards rows-${Math.floor(search.pageSize / 8)}` }); + const list = div({ class: `property-list-cards rows-${Math.floor(search.pageSize / 4)}` }); block.append(list); propertySearch(search).then((results) => { renderCards(list, results.properties); diff --git a/blocks/quote/design-1.css b/blocks/quote/design-1.css new file mode 100644 index 00000000..ed9b9e73 --- /dev/null +++ b/blocks/quote/design-1.css @@ -0,0 +1,7 @@ +.design-1.black-white .quote.block { + border-top: 1px solid var(--black); +} + +.design-1.black-white .quote.block p { + color: var(--black); +} \ No newline at end of file diff --git a/blocks/quote/quote.css b/blocks/quote/quote.css index 9832623c..460c8157 100644 --- a/blocks/quote/quote.css +++ b/blocks/quote/quote.css @@ -1,5 +1,7 @@ +@import url('./design-1.css'); + .quote.block { - border-top: 1px solid var(--body-color); + border-top: 1px solid var(--secondary-accent); } .quote.block .quote { @@ -30,3 +32,6 @@ text-transform: uppercase; } +.quote.block p { + color: var(--secondary-color); +} diff --git a/blocks/shared/property/cards.css b/blocks/shared/property/cards.css index 1020b277..b6bbc78b 100644 --- a/blocks/shared/property/cards.css +++ b/blocks/shared/property/cards.css @@ -350,7 +350,7 @@ @media (min-width: 1200px) { .property-list-cards { display: grid; - grid-template: repeat(2, 1fr) / repeat(4, 1fr); + grid-template-columns: repeat(4, 1fr); gap: 20px; padding-bottom: 20px; } diff --git a/blocks/shared/search/util.js b/blocks/shared/search/util.js index 832212ac..d8b587c9 100644 --- a/blocks/shared/search/util.js +++ b/blocks/shared/search/util.js @@ -50,11 +50,11 @@ export function buildFilterSelect(name, placeholder, options) { wrapper.classList.add('select-wrapper', name); wrapper.innerHTML = ` - + `; diff --git a/scripts/apis/agent/workers/search.js b/scripts/apis/agent/workers/search.js index f8009564..69a62c1a 100644 --- a/scripts/apis/agent/workers/search.js +++ b/scripts/apis/agent/workers/search.js @@ -5,12 +5,16 @@ * @param {string} event.data.url the URL to fetch. * */ -onmessage = (event) => { - fetch(event.data.url).then(async (resp) => { +onmessage = async (event) => { + try { + const resp = await fetch(event.data.url); if (resp.ok) { postMessage(await resp.json()); } else { postMessage({}); } - }); + } catch (e) { + console.log('Error fetching data', e); + postMessage({}); + } }; diff --git a/scripts/scripts.js b/scripts/scripts.js index f38e57d7..2147f5c0 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -349,6 +349,26 @@ export function loadLogin(main) { return loadBlock(loginBlock); } +function loadHeaderAndFooter(doc) { + const header = doc.querySelector('header'); + const footer = doc.querySelector('footer'); + + header.style.visibility = 'hidden'; + footer.style.visibility = 'hidden'; + + const headerLoaded = loadHeader(header); + const footerLoaded = loadFooter(footer); + + headerLoaded.then(() => { + header.style.visibility = null; + }); + footerLoaded.then(() => { + footer.style.visibility = null; + }); + + return Promise.all([headerLoaded, footerLoaded]); +} + /** * Loads everything that doesn't need to be delayed. * @param {Element} doc The container element @@ -360,13 +380,18 @@ async function loadLazy(doc) { const { hash } = window.location; const element = hash ? doc.getElementById(hash.substring(1)) : false; if (hash && element) element.scrollIntoView(); - loadHeader(doc.querySelector('header')); - loadFooter(doc.querySelector('footer')); - loadLogin(doc.querySelector('main')); + // no need to await any of these individually + // but want them all to complete before moving on to delayed phase + const lazyPromises = []; + + lazyPromises.push(loadHeaderAndFooter(doc)); + lazyPromises.push(loadLogin(doc.querySelector('main'))); + lazyPromises.push(loadCSS(`${window.hlx.codeBasePath}/styles/lazy-styles.css`)); + lazyPromises.push(loadFonts()); + lazyPromises.push(addFavIcon(`${window.hlx.codeBasePath}/styles/bhhs_seal_favicon.ico`)); + + await Promise.all(lazyPromises); - loadCSS(`${window.hlx.codeBasePath}/styles/lazy-styles.css`); - loadFonts(); - addFavIcon(`${window.hlx.codeBasePath}/styles/bhhs_seal_favicon.ico`); sampleRUM('lazy'); sampleRUM.observe(main.querySelectorAll('div[data-block-name]')); sampleRUM.observe(main.querySelectorAll('picture > img')); diff --git a/scripts/util.js b/scripts/util.js index db887d1c..1fbf4668 100644 --- a/scripts/util.js +++ b/scripts/util.js @@ -1,5 +1,5 @@ -import { fetchPlaceholders } from './aem.js'; -import { div, domEl } from './dom-helpers.js'; +import { fetchPlaceholders, loadCSS } from './aem.js'; +import { div, img, domEl } from './dom-helpers.js'; /** * Creates the standard Spinner Div. @@ -189,12 +189,43 @@ export function phoneFormat(num) { return phoneNum; } +export const getDesign = (designType, defaultDesign, design1, design2, design3, design4, design5) => { + switch (designType.toLowerCase()) { + case 'design-1': + return design1; + case 'design-2': + return design2; + case 'design-3': + return design3; + case 'design-4': + return design4; + case 'design-5': + return design5; + default: + return defaultDesign; + } +}; + +export const loadTemplateCSS = (blockName, designType) => { + loadCSS(`${window.hlx.codeBasePath}/blocks/${blockName}/${designType.toLowerCase()}.css`); +}; + +export const getLoader = (className) => div({ class: `${className}-loader` }, + div({ class: 'animation' }, + domEl('picture', img({ src: '/styles/images/loading.png' })), + div({ class: 'pulse' }), + ), +); + const Util = { getSpinner, showModal, i18nLookup, getEnvType, getCookieValue, + getDesign, + loadTemplateCSS, + getLoader, }; export default Util; diff --git a/styles/styles.css b/styles/styles.css index 82a72c53..6feff2e7 100644 --- a/styles/styles.css +++ b/styles/styles.css @@ -310,8 +310,8 @@ main .section.padding { main .section.two-columns { display: flex; - flex-wrap: wrap; justify-content: space-around; + flex-flow: column wrap; } main .section.two-columns > div { @@ -607,6 +607,12 @@ form button[type="submit"]:hover { } } +@media screen and (min-width: 900px) { + main .section.two-columns { + flex-direction: row; + } +} + @media screen and (min-width: 1200px) { :root { --nav-height: 140px;