diff --git a/blocks/agent-transactions/agent-transactions.css b/blocks/agent-transactions/agent-transactions.css new file mode 100644 index 00000000..061fc67c --- /dev/null +++ b/blocks/agent-transactions/agent-transactions.css @@ -0,0 +1,157 @@ +.agent-transactions.block table { + width: 100%; + font-size: var(--body-font-size-s); + line-height: var(--line-height-m); + margin-bottom: 0.25rem; +} + +.agent-transactions.block h1 { + font-size: var(--heading-font-size-l); + line-height: var(--line-height-s); + color: var(--primary-color); + margin: 0 1.875rem 1.5rem 0; + font-weight: 600; +} + +.agent-transactions.block .hide { + display: none; +} + +.agent-transactions.block .show { + display: table-row; +} + +.agent-transactions.block thead { + background: var(--platinum); + font-size: var(--body-font-size-xs); + line-height: var(--line-height-m); + font-weight: var(--font-weight-bold); + text-transform: capitalize; +} + +.agent-transactions.block tbody td { + padding-bottom: 0.5rem; + padding-top: 0.25rem; + font-size: var(--body-font-size-xs); +} + +.agent-transactions.block a { + line-height: var(--line-height-m); + letter-spacing: var(--letter-spacing-m); + text-transform: uppercase; + padding-left: 1rem; + cursor: pointer; +} + +.agent-transactions.block a.show-more::after { + content: "View More"; + display: inline-block; + background-image: url("../../icons/arrow-down.svg"); + background-repeat: no-repeat; + background-position: right; + padding-right: 1rem; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); +} + +.agent-transactions.block a.show-less::after { + content: "View Less"; + display: inline-block; + background-image: url("../../icons/arrow-up.svg"); + background-repeat: no-repeat; + background-position: right; + padding-right: 1rem; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); +} + +.agent-transactions.block thead th { + padding-top: 0.125rem; + padding-bottom: 0.125rem; +} + +.agent-transactions.block thead th:first-of-type { + padding-left: 1rem; +} + +.agent-transactions.block tbody td:first-of-type { + padding-left: 1rem; +} + +.agent-transactions.block .default { + display: table-cell; +} + +.agent-transactions.block .medium, +.agent-transactions.block .large, +.agent-transactions.block .xl { + display: none; +} + +.agent-transactions.block .sold-price { + width: 40%; +} + +@media (min-width: 600px) { + .agent-transactions.block .medium { + display: table-cell; + } + + .agent-transactions.block .address { + width: 48.7%; + } + + .agent-transactions.block .city { + width: 24.5%; + } + + .agent-transactions.block .state { + width: 7.4%; + } + + .agent-transactions.block .sold-price { + width: 40%; + } +} + +@media (min-width: 992px) { + .agent-transactions.block h1 { + font-size: 1.875rem; + } + + .agent-transactions.block thead { + font-size: var(--body-font-size-s); + } + + .agent-transactions.block tbody td { + font-size: var(--body-font-size-s); + padding-top: 0.5rem; + } + + .agent-transactions.block .large { + display: table-cell; + } + + .agent-transactions.block .address { + width: auto; + } + + .agent-transactions.block .city { + width: 15%; + } + + .agent-transactions.block .sold-price { + width: 13%; + } +} + +@media (min-width: 1200px) { + .agent-transactions.block .xl { + display: table-cell; + } + + .agent-transactions.block .beds, + .agent-transactions.block .baths { + width: 5%; + } +} diff --git a/blocks/agent-transactions/agent-transactions.js b/blocks/agent-transactions/agent-transactions.js new file mode 100644 index 00000000..e2e354a8 --- /dev/null +++ b/blocks/agent-transactions/agent-transactions.js @@ -0,0 +1,105 @@ +import { + table, tbody, th, thead, tr, td, h1, a, +} from '../../scripts/dom-helpers.js'; +import { getMetadata } from '../../scripts/aem.js'; + +const getClosedTransactions = async () => { + const agentId = getMetadata('agent-id'); + const formattedData = []; + + try { + const response = await fetch(`/bin/bhhs/agentPropertyListingsServlet.${agentId}.json`); + const data = await response.json(); + + if (data && data?.closedTransactions?.properties?.length) { + data.closedTransactions.properties.forEach((property) => { + formattedData.push({ + address: property.StreetName, + city: property.City, + state: property.StateOrProvince, + 'sold-price': property.closePrice, + beds: property.BedroomsTotal, + baths: property.BathroomsTotal, + 'approx-sq-ft': property.LivingArea, + type: property.PropertyType, + 'closed-date': property.ClosedDate, + }); + }); + } + } catch (error) { + // eslint-disable-next-line no-console + console.error('Error fetching closed transactions', error); + } + + return formattedData; +}; + +export default async function decorate(block) { + const transactionsData = await getClosedTransactions(); + if (transactionsData.length === 0) { + return; + } + + const thList = ['address', 'city', 'state', 'sold price', 'beds', 'baths', 'approx sq. ft.', 'type', 'closed date']; + const thDefault = { class: 'default', list: [0, 3] }; + const thMedium = { class: 'medium', list: [1, 2] }; + const thLarge = { class: 'large', list: [4, 5, 8] }; + const thXL = { class: 'xl', list: [6, 7] }; + + const theadTr = tr(); + const getClass = (index) => { + if (thDefault.list.includes(index)) { + return `${thDefault.class}`; + } + if (thMedium.list.includes(index)) { + return `${thMedium.class}`; + } + if (thLarge.list.includes(index)) { + return `${thLarge.class}`; + } + return `${thXL.class}`; + }; + + thList.forEach((x, index) => { + theadTr.appendChild(th({ class: `${x.split(' ').join('-').replace(/\./g, '')} ${getClass(index)}` }, x)); + }); + + const trBody = tbody(); + const intialTransactionsCount = 6; // show 6 transactions initially + + transactionsData.forEach((data, topIndex) => { + const trElement = tr({ class: `${topIndex < intialTransactionsCount ? 'show' : 'hide'}` }); + + thList.forEach((x, index) => { + const key = x.split(' ').join('-').replace(/\./g, ''); + trElement.appendChild(td({ class: `${x.split(' ').join('-').replace(/\./g, '')} ${getClass(index)}` }, (data[key]) || '')); + }); + + trBody.appendChild(trElement); + }); + + const tableElement = table({}, thead({}, theadTr), trBody); + const heading1 = h1({}, 'Closed Transactions'); + const anchor = a({ class: 'show-more' }); + anchor.addEventListener('click', () => { + if (anchor.classList.contains('show-more')) { + anchor.classList.remove('show-more'); + anchor.classList.add('show-less'); + const tBodyTr = block.querySelectorAll('tbody tr.hide'); + tBodyTr.forEach((trElement) => { + trElement.classList.remove('hide'); + }); + } else { + anchor.classList.remove('show-less'); + anchor.classList.add('show-more'); + const tBodyTr = block.querySelectorAll('tbody tr'); + tBodyTr.forEach((trElement, index) => { + if (index >= intialTransactionsCount) { + trElement.classList.add('hide'); + } + }); + } + }); + + block.replaceChildren(heading1, tableElement, anchor); +} diff --git a/icons/arrow-down.svg b/icons/arrow-down.svg new file mode 100644 index 00000000..4d8c6193 --- /dev/null +++ b/icons/arrow-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/icons/arrow-up.svg b/icons/arrow-up.svg new file mode 100644 index 00000000..8edce9af --- /dev/null +++ b/icons/arrow-up.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/scripts/dom-helpers.js b/scripts/dom-helpers.js index 1fce908c..7059545f 100644 --- a/scripts/dom-helpers.js +++ b/scripts/dom-helpers.js @@ -97,3 +97,9 @@ export function article(...items) { return domEl('article', ...items); } export function strong(...items) { return domEl('strong', ...items); } export function select(...items) { return domEl('select', ...items); } export function option(...items) { return domEl('option', ...items); } +export function table(...items) { return domEl('table', ...items); } +export function tbody(...items) { return domEl('tbody', ...items); } +export function th(...items) { return domEl('th', ...items); } +export function thead(...items) { return domEl('thead', ...items); } +export function tr(...items) { return domEl('tr', ...items); } +export function td(...items) { return domEl('td', ...items); }