From 2a73d7e8c612dc91a338ee89220b40e9709b014b Mon Sep 17 00:00:00 2001 From: Rob Rusher Date: Fri, 7 Jun 2024 18:27:04 -0600 Subject: [PATCH] added dynamic form information --- blocks/contact-form/contact-form.css | 12 ++++++ blocks/contact-form/contact-form.js | 43 ++++++++++++++++--- .../contact-form/forms/contact-property.html | 10 +++-- blocks/shared/property/cards.js | 2 +- blocks/side-modal/side-modal.css | 11 +++++ blocks/side-modal/side-modal.js | 3 +- scripts/apis/creg/creg.js | 16 +++++++ scripts/apis/creg/workers/envelope.js | 19 ++++++++ scripts/util.js | 17 ++++---- 9 files changed, 112 insertions(+), 21 deletions(-) create mode 100644 scripts/apis/creg/workers/envelope.js diff --git a/blocks/contact-form/contact-form.css b/blocks/contact-form/contact-form.css index 7bbae3e7..b13f27c3 100644 --- a/blocks/contact-form/contact-form.css +++ b/blocks/contact-form/contact-form.css @@ -11,6 +11,18 @@ margin-left: 40px; margin-bottom: 3em; } +.contact-form.block .contact-details { + display: flex; + flex-direction: row; + gap: 1em; + margin-bottom: 2em; +} + +.contact-form.block .profile { + display: flex; + flex-direction: column; + gap: 1em; +} .contact-form.block .company-name { font-size: var(--heading-font-size-m); diff --git a/blocks/contact-form/contact-form.js b/blocks/contact-form/contact-form.js index 33c855aa..527b3765 100644 --- a/blocks/contact-form/contact-form.js +++ b/blocks/contact-form/contact-form.js @@ -1,5 +1,7 @@ -import { loadScript } from '../../scripts/aem.js'; +import { createOptimizedPicture, loadScript } from '../../scripts/aem.js'; +// import { getEnvelope } from '../../scripts/apis/creg/creg.js'; import { removeSideModal, i18nLookup, getCookieValue } from '../../scripts/util.js'; +import { a, div } from '../../scripts/dom-helpers.js'; const LOGIN_ERROR = 'There was a problem processing your request.'; const i18n = await i18nLookup(); @@ -9,9 +11,17 @@ const phoneRegex = /^[+]?[ (]?\d{3}[)]?[-.\s]?\d{3}[-.\s]?\d{4}$/; // Load reCaptcha script used on all forms. loadScript('/blocks/contact-form/forms/callback.js'); -function findListing() { - const temp = window.propertyListings?.properties || []; - return temp?.find((property) => property.ListingId === window.selectedListingId) || null; +function getImageURL(jsonString) { + try { + const data = JSON.parse(jsonString); + if (Array.isArray(data) && data.length > 0) { + const imageUrl = data[0].url; + return imageUrl; + } + } catch (error) { + return '/media/images/no-profile-image.png'; + } + return null; // Add a return statement at the end of the function } /** @@ -320,9 +330,28 @@ const addForm = async (block) => { const taEl = block.querySelector('textarea'); if (taEl?.placeholder) taEl.placeholder = i18n(taEl.placeholder); - if (window.selectedListingId) { - const prop = findListing(); - taEl.value = `Hi, I would like more information about ${prop.StreetName}, ${prop.City}, ${prop.StateOrProvince} ${prop.PostalCode}.`; + if (window.selectedListing) { + // const prop = await findListing(); + const prop = window.selectedListing; + // if the listing agent is supposed to be displayed vs the office + if (prop.propertyDetails.listAgentCd) { + const info = block.querySelector('.contact-info'); + const pic = getImageURL(prop.listAgent.reAgentDetail.image); + const profile = div({ class: 'profile' }, createOptimizedPicture(pic, prop.listAgent.recipientName, 'lazy', [{ width: '82' }])); + info.insertAdjacentElement('beforebegin', profile); + const name = block.querySelector('.company-name'); + const link = a({ href: '#' }, prop.listAgent.recipientName); // TODO: add link to agent profile + name.replaceChildren(link); + const email = block.querySelector('.company-email a'); + email.textContent = prop.listAgent.reAgentDetail.email; + email.href = `mailto:${prop.listAgent.reAgentDetail.email}`; + const phone = block.querySelector('.company-phone a'); + phone.textContent = prop.listAgent.reAgentDetail.officeTelephone; + phone.href = `tel:${prop.listAgent.reAgentDetail.officeTelephone}`; + } + + taEl.value = `Hi, I would like more information about ${prop.propertyDetails.unparsedAddress}`; + if (window.location.pathname.length === 1) { block.querySelector('.disclaimer').remove(); } diff --git a/blocks/contact-form/forms/contact-property.html b/blocks/contact-form/forms/contact-property.html index 02fbfe94..452c2be9 100644 --- a/blocks/contact-form/forms/contact-property.html +++ b/blocks/contact-form/forms/contact-property.html @@ -1,8 +1,12 @@
Contact Us
-
Berkshire Hathaway HomeServices
Commonwealth Real Estate
- - +
+
+
Berkshire Hathaway HomeServices
Commonwealth Real Estate
+ + +
+
diff --git a/blocks/shared/property/cards.js b/blocks/shared/property/cards.js index e545776d..1b4076c9 100644 --- a/blocks/shared/property/cards.js +++ b/blocks/shared/property/cards.js @@ -80,7 +80,7 @@ export function createCard(listing) { div({ class: 'property-info-wrapper' }, div({ class: 'property-info' }, div({ class: 'sold-date' }, `Closed: ${listing.ClosedDate}`), - div({ id: `listing-${listing.ListingId}-address`, class: 'address' }, + div({ id: `listing-${listing.PropId}-address`, class: 'address' }, listing.StreetName, domEl('br'), `${listing.City}, `, diff --git a/blocks/side-modal/side-modal.css b/blocks/side-modal/side-modal.css index 312f63d3..9fb8c48b 100644 --- a/blocks/side-modal/side-modal.css +++ b/blocks/side-modal/side-modal.css @@ -29,4 +29,15 @@ aside.side-modal > div { aside.side-modal > div { padding: 53px 45px 15px; } + + body > div > div.side-modal-overlay { + background-color: #212529; + width: 100%; + height: 100%; + position: fixed; + opacity: .5; + z-index: 1040; + top: 0; + left: 0; + } } diff --git a/blocks/side-modal/side-modal.js b/blocks/side-modal/side-modal.js index ed30d06a..1835ba28 100644 --- a/blocks/side-modal/side-modal.js +++ b/blocks/side-modal/side-modal.js @@ -2,11 +2,12 @@ import { decorateSections, decorateBlocks, loadBlocks, decorateButtons, decorateIcons, loadCSS, } from '../../scripts/aem.js'; +import { getEnvelope } from '../../scripts/apis/creg/creg.js'; export async function showSideModal(a) { const { href } = a; const listing = a.parentNode.parentNode.previousElementSibling.querySelector('div.address').id.split('-')[1]; - window.selectedListingId = listing; + window.selectedListing = await getEnvelope(listing); const module$ = import(`${window.hlx.codeBasePath}/scripts/util.js`); await loadCSS(`${window.hlx.codeBasePath}/blocks/side-modal/side-modal.css`); const content = await fetch(`${href}.plain.html`); diff --git a/scripts/apis/creg/creg.js b/scripts/apis/creg/creg.js index e7c2d9bd..4e42cceb 100644 --- a/scripts/apis/creg/creg.js +++ b/scripts/apis/creg/creg.js @@ -78,3 +78,19 @@ export async function getEconomicDetails(lat, long) { }); }); } + +/** + * Retrieves the envelope for a given listing ID. + * + * @param {string} listingId - The ID of the listing. + * @returns {Promise} A promise that resolves to the envelope data. + */ +export async function getEnvelope(listingId) { + return new Promise((resolve) => { + const worker = new Worker(`${window.hlx.codeBasePath}/scripts/apis/creg/workers/envelope.js`, { type: 'module' }); + worker.onmessage = (e) => resolve(e.data); + worker.postMessage({ + listingId, + }); + }); +} diff --git a/scripts/apis/creg/workers/envelope.js b/scripts/apis/creg/workers/envelope.js new file mode 100644 index 00000000..768ed801 --- /dev/null +++ b/scripts/apis/creg/workers/envelope.js @@ -0,0 +1,19 @@ +/** + * Handle the Worker event. Fetches details for each provided listing id. + * + * @param {Object} event the worker event. + * @param {string} event.data.api the URL to fetch. + * @param {string[]} event.data.ids list of listing ids + */ +onmessage = async (event) => { + const { listingId } = event.data; + + try { + const response = await fetch(`/bin/bhhs/CregPropertySearchServlet?SearchType=Envelope&ListingId=${listingId}`); + const data = response.ok ? await response.json() : undefined; + + postMessage(data); + } catch (error) { + postMessage({}); + } +}; diff --git a/scripts/util.js b/scripts/util.js index 6a78bdd8..2f665867 100644 --- a/scripts/util.js +++ b/scripts/util.js @@ -1,4 +1,5 @@ import { fetchPlaceholders } from './aem.js'; +import { div, domEl } from './dom-helpers.js'; /** * Creates the standard Spinner Div. @@ -54,6 +55,7 @@ let focusElement; export function removeSideModal() { if (!sideModal) return; + sideModal.parentNode.nextSibling.remove(); sideModal.parentNode.remove(); sideModal = null; document.body.classList.remove('disable-scroll'); @@ -62,15 +64,12 @@ export function removeSideModal() { export async function showSideModal(content, decorateContent) { if (!sideModal) { - const fragment = document.createRange().createContextualFragment(` -
- -
- `); - sideModal = fragment.querySelector('.side-modal'); - document.body.append(...fragment.children); + const temp = div( + domEl('aside', { class: 'side-modal' }, div()), + div({ class: 'side-modal-overlay' }), + ); + sideModal = temp.querySelector('.side-modal'); + document.body.append(temp); } const container = sideModal.querySelector('div'); container.replaceChildren(...content);