import type { CMSFilters } from '$types/CMSFilters'; import type { MSCCRawTour, MSCCTour } from '$types/Tours'; import { fetchItems } from '$utils/fetch'; import { handleDates } from '$utils/handleDates'; // * Handle the tours functionality export async function handleCapitolTours(API_URL: string) { // Get the element with ID of 'mscc-events' const toursElement = document.getElementById('mscc-tours'); // If the element doesn't exist, return early if (!toursElement) return false; handleDates(); // ************************************************/ // * Function to initialize CMS filtering & loading. // ************************************************/ window.fsAttributes = window.fsAttributes || []; window.fsAttributes.push([ 'cmsfilter', async (filtersInstances: CMSFilters[]) => { // Get the filters instance const [filtersInstance] = filtersInstances; if (!filtersInstance) return; // Get the list instance const { listInstance } = filtersInstance; // Save a copy of the template const [firstItem] = listInstance.items; const itemTemplateElement = firstItem.element; // Remove existing items listInstance.clearItems(); // Fetch external data const tours = (await fetchItems(API_URL)) as MSCCRawTour[]; // If there are no tours, return early if (!tours) return; // Create the new items const newItemsPromises = tours.map((singleTour: MSCCRawTour) => { const processedTour = processTour(singleTour); return createTourCard(processedTour, itemTemplateElement); }); const newItems = await Promise.all(newItemsPromises); console.log('newItems', newItems); // Populate the list listInstance.addItems(newItems); // Populate the tour type & location dropdowns const tourTypes = getTourTypes(tours); // Get the dropdown template elements const dropdownTemplateElementType = document.querySelector( 'select[fs-cmsfilter-field="type"]' ) as NonNullable; const dropdownTemplateWrapperElementType = dropdownTemplateElementType.parentElement as NonNullable; // Create the dropdown const dropdownType = createDropdown( tourTypes, dropdownTemplateElementType! ); // Insert the dropdown dropdownTemplateWrapperElementType.insertBefore( dropdownType, dropdownTemplateWrapperElementType.children[1] ); filtersInstance.storeFiltersData(); }, ]); } function createTourCard(singleTour: MSCCTour, templateElement: HTMLDivElement) { // Clone the template element const newItem = templateElement.cloneNode(true) as HTMLDivElement; // return newItem; // Query inner elements const title = newItem.querySelector( '[mscc-field="title"]' ) as NonNullable; const type = newItem.querySelector( '[mscc-field="type"]' ) as NonNullable; const location = newItem.querySelector( '[mscc-field="location"]' ) as NonNullable; const startDate = newItem.querySelector( '[mscc-field="startDate"]' ) as NonNullable; // This is a different naming convention for query selector usage const dateRange = newItem.querySelector( '[mscc-field="dates"]' ) as NonNullable; const endDate = newItem.querySelector( '[mscc-field="endDate"]' ) as NonNullable; const totalDate = newItem.querySelector( '[mscc-field="totalDate"]' ) as NonNullable; const startYear = newItem.querySelector( '[mscc-field="startYear"]' ) as NonNullable; const startMonth = newItem.querySelector( '[mscc-field="startMonth"]' ) as NonNullable; const startDay = newItem.querySelector( '[mscc-field="startDay"]' ) as NonNullable; ///////////////////////////// // Populate inner elements // ///////////////////////////// title && (title.textContent = singleTour.title ?? 'UNKNOWN'); type && (type.textContent = singleTour.type ?? 'UNKNOWN'); location && (location.textContent = singleTour.location); if (!singleTour.location || singleTour.location === '') { location.style.display = 'none'; } startDate && (startDate.textContent = singleTour.startDate); endDate && (endDate.textContent = singleTour.endDate); dateRange && (dateRange.textContent = singleTour.dateRange); totalDate && (totalDate.textContent = singleTour.totalDate); startYear && (startYear.textContent = singleTour.startYear); startMonth && (startMonth.textContent = singleTour.startMonth); startDay && (startDay.textContent = singleTour.startDay); return newItem; } // * Process the tour data function processTour(singleTour: NonNullable) { const processedTour = {} as MSCCTour; const dateFormat = { timeZone: 'America/Detroit', month: 'long', day: 'numeric', year: 'numeric', hour: 'numeric', minute: 'numeric', } as Intl.DateTimeFormatOptions; // Tour group name, type, and location processedTour.title = singleTour[ '_hso_tourgroup_value@OData.Community.Display.V1.FormattedValue' ]; processedTour.type = singleTour['_hso_tourtype_value@OData.Community.Display.V1.FormattedValue']; processedTour.location = singleTour['hso_TourGroup']?.address1_city; // Tour start and end date processedTour.startDate = new Date( singleTour.hso_starttime ).toLocaleDateString('en-US', dateFormat); processedTour.dateRange = new Date(singleTour.hso_starttime).toLocaleString( 'en-US', { month: 'long', day: 'numeric', year: 'numeric', } ); // Remove the comma from the dateRange processedTour.dateRange = processedTour.dateRange.replace(/,/g, ''); const endDate = new Date(singleTour.hso_endtime); processedTour.endDate = endDate.toLocaleString('en-US', dateFormat); if ( new Date(endDate).setHours(0, 0, 0, 0).toString() === new Date(singleTour.hso_starttime).setHours(0, 0, 0, 0).toString() ) { processedTour.totalDate = `${processedTour.startDate} — ${endDate.toLocaleTimeString('en-US', { hour: 'numeric', minute: 'numeric' })}`; } else { processedTour.totalDate = `${processedTour.startDate} — ${processedTour.endDate}`; } processedTour.startYear = new Date(singleTour.hso_starttime) .getFullYear() .toString(); processedTour.startMonth = new Date(singleTour.hso_starttime).toLocaleString( 'en-US', { month: 'short', } ); processedTour.startDay = new Date(singleTour.hso_starttime) .getDate() .toString(); return processedTour; } // * Get the unique tour types function getTourTypes(tours: MSCCRawTour[]) { const processedTours = tours.map((tour) => processTour(tour)); const tourTypes = processedTours.map((tour) => tour.type); return Array.from(new Set(tourTypes)); } const createDropdown = ( tourTypes: string[], templateElement: HTMLSelectElement ) => { // Clone the template element const newDropdown = templateElement.cloneNode( true ) as NonNullable; // Clear the dropdown newDropdown.innerHTML = ''; // Check query string for tour type const urlParams = new URLSearchParams(window.location.search); const queryType = urlParams.get('type'); // Populate the dropdown const dropdownItems = tourTypes.map((type) => { const option = document.createElement('option'); option.value = type; option.textContent = type; if (queryType === type) { option.selected = true; } return option; }); // Add a default option const defaultOption = document.createElement('option'); defaultOption.value = ''; defaultOption.textContent = 'Select a tour type...'; newDropdown.prepend(defaultOption); // Add the dropdown items newDropdown.append(...dropdownItems); // Remove the template element templateElement.remove(); return newDropdown; };