diff --git a/blocks/agent-communities/agent-communities.css b/blocks/agent-communities/agent-communities.css new file mode 100644 index 00000000..96612826 --- /dev/null +++ b/blocks/agent-communities/agent-communities.css @@ -0,0 +1,224 @@ +.agent-communities.block { + 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: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; + filter: brightness(0.8); + 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); +} + +.agent-communities.block .hero-item-heading { + text-transform: uppercase; + font-size: var(--body-font-size-s); + letter-spacing: 3.2px; +} + +.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..c98b11ca --- /dev/null +++ b/blocks/agent-communities/agent-communities.js @@ -0,0 +1,105 @@ +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 url = '/commonwealth-real-estate-ma312/east-greenwich/barry-alofsin/cid-473521'; + 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\/\w+$/; + const match = item.url.match(regex); + const link = match ? match[0] : ''; + + return { + name: item.name.toUpperCase(), + exploreName: `explore ${item.name}`, + link, + banner: item.banner_16x9, + }; + })); + } + + 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); + }); + + block.appendChild(cardsList); + } catch (error) { + // eslint-disable-next-line no-console + console.error('Error fetching data', error); + } + }, 3000); +} diff --git a/scripts/util.js b/scripts/util.js index c6728a17..1fbf4668 100644 --- a/scripts/util.js +++ b/scripts/util.js @@ -1,5 +1,5 @@ import { fetchPlaceholders, loadCSS } from './aem.js'; -import { div, domEl } from './dom-helpers.js'; +import { div, img, domEl } from './dom-helpers.js'; /** * Creates the standard Spinner Div. @@ -210,6 +210,13 @@ 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, @@ -218,6 +225,7 @@ const Util = { getCookieValue, getDesign, loadTemplateCSS, + getLoader, }; export default Util;