Hi everyone,
I’m building a test website with EditorX and I’m having trouble with one of the pages. The live page can be found here . Everything works perfectly EXCEPT if I refresh the page. I really don’t understand what’s going on…
ABOUT THE PAGE:
All of the filter elements and all of the repeater elements on the page are populated programmatically.
THE ISSUE:
-
The dropdown filters only work IF I access the page from the main menu for the first time or if I navigate to another page and come back. They do not work if I refresh the page.
-
Additional note: This problem has been sitting there for about a week now. I think it’s important to mention that for almost a week that the problem only occurred during the day and magically disappeared after 5pm. I am quite new to coding, so I can’t be sure that the problem isn’t with my code but this is certainly strange. For the past few days though the problem is consistent throughout the day so I don’t know.
WHAT I’VE DONE:
- Refreshed my browser a million times, on my laptop and phone (Android). Tried on someone else’s phone. Same issue. Cleared my cache and browser data several times.
MY CODE:
I’m pasting almost everything here except for a few small functions (for formatting numbers and dates) since I’m really not sure what could be the problem…
import wixData from "wix-data";
import wixLocation from "wix-location";
$w.onReady(() => {
//Populate dropdowns and initiate components
initComps();
//Initiate repeater
initRepeater();
//Show results based on search
buildFiltersAndPopulateRepeater();
});
//FUNCTION #1 TO DEFINE REPEATER ELEMENTS
function initRepeater() {
// REPEATER DATA FROM LEFT TO RIGHT
repeater.onItemReady(($item, itemData, index) => {
//DEPARTURE & ARRIVAL
//Format "Departure" & "Arrival" in DD MMM YYYY, e.g. 2 Apr 2023.
const departureDate = itemData.departure;
const formattedDeparture = formatDate.format(departureDate);
$item("#departureDate").text = String(formattedDeparture);
const arrivalDate = itemData.arrival;
const formattedArrival = formatDate.format(arrivalDate);
$item("#arrivalDate").text = String(formattedArrival);
//Count duration
const duration = calcDuration(departureDate, arrivalDate);
$item("#duration").text = String(`${duration} nights`);
//YACHT & DESTINATIONS
//Declare yacht name
$item("#yachtName").text = `${itemData.yacht.title}`;
//Add yacht link
const yachtURL = `/luxury-liveaboard/${itemData.yacht.url}`;
$item("#yachtName").onClick(function (event) {
wixLocation.to(yachtURL);
});
//Declare destinations
let dests = itemData.destinations;
let destsArr = [];
// Loop through no. of destinations
for (let x = 0; x < dests.length; x++) {
destsArr.push(dests[x].title);
}
$item("#destNames").text = destsArr.join(" - ");
//ITINERARY & ROUTEte
$item("#itineraryName").text = itemData.itinerary.title; //name
$item("#embarkDisembark").text = String(itemData.itinerary.embarkationPort + " to " + itemData.itinerary.disembarkationPort);
//PRICING & AVAILABILITY
//Pricing & Discount Elements
const startingPrice = itemData.cabinType1Price;
const discAmt = itemData.discAmt;
const discPercent = itemData.discPercentage;
const charterOnly = itemData.charterOnly;
const charterPrice = itemData.yacht.charterPrice;
const charterPriceTotal = charterPrice * duration;
const startPrice = $item("#startingPrice");
const ribbonBox = $item("#ribbonBox");
const ribbonText = $item("#ribbonText");
const beforePrice = $item("#beforePrice");
let discPrice;
let ribbonMsg;
const formattedPrice = String(USDollar.format(startingPrice));
const formattedCharterPrice = String(USDollar.format(charterPriceTotal));
//Remarks Elements
const remarks = $item("#tripRemarks");
const remarksVal = itemData.remarks;
//AVAILABILITY & CAPACITY
const yachtCap = itemData.yacht.capacity;
//Constructor Function for Cabin types
function CabinType(avail, male, female) {
this.avail = avail;
this.male = male;
this.female = female;
this.calcAvail = function (avail, male, female) {
let total = avail + male + female;
return total;
};
this.totalAvail = this.calcAvail(avail, male, female);
}
//Construct new cabins
const cabinType1 = new CabinType(itemData.cabinType1Availability, itemData.cabinType1ShareMale, itemData.cabinType1ShareFemale);
const cabinType2 = new CabinType(itemData.cabinType2Availability, itemData.cabinType2ShareMale, itemData.cabinType2ShareFemale);
//REPEATER FUNCTION #1: CHECK AVAILABILITY
const checkAvail = () => {
const totalYachtAvail = cabinType1.totalAvail + cabinType2.totalAvail;
if (!remarksVal) {
if (totalYachtAvail === yachtCap) {
remarks.text = `Available for charter`;
} else if (totalYachtAvail < 0.5 * yachtCap && totalYachtAvail > 0) {
remarks.text = `${totalYachtAvail} spots left`;
} else if (totalYachtAvail === 0) {
soldOut();
} else {
remarks.hide();
}
} else {
if (remarksVal === "EMPTY") {
remarks.hide();
} else {
remarks.text = remarksVal;
}
}
return totalYachtAvail;
};
//REPEATER FUNCTION #2: CALCULATE DISCOUNT
const calcDisc = (discType, basePrice, beforeVal) => {
if (discType === discAmt) {
discPrice = basePrice - discAmt;
startPrice.text = String(USDollar.format(discPrice));
ribbonMsg = `-${USDollar.format(discAmt)} off`;
} else {
discPrice = basePrice - (discPercent / 100) * basePrice;
startPrice.text = String(USDollar.format(discPrice));
ribbonMsg = `-${discPercent}% off`;
}
ribbonText.text = ribbonMsg.toUpperCase();
ribbonBox.show();
beforePrice.html = `<p>From ${beforeVal.strike()}</p>`;
};
//REPEATER FUNCTION #3: CLEAR IF SOLD OUT
const soldOut = () => {
startPrice.html = `<h3 style="color: #DA0000">SOLD OUT</h2>`;
ribbonBox.hide();
beforePrice.hide();
remarks.hide();
bookBtn.label = "Join Waitlist";
};
let curTotal = checkAvail();
//IF TRIP IS NOT SOLD OUT
if (curTotal > 0) {
//If it's not a "charter only" trip
if (!charterOnly) {
//CONDITIONS FOR DISCOUNTS
//If there's a discount amount
if (discAmt) {
calcDisc(discAmt, startingPrice, formattedPrice);
//If there's a discount%
} else if (discPercent) {
calcDisc(discPercent, startingPrice, formattedPrice);
} else {
//If there's no discount
ribbonBox.hide();
startPrice.text = String(formattedPrice);
}
// If it's a charter only trip
} else {
if (discAmt) {
calcDisc(discAmt, charterPriceTotal, formattedCharterPrice);
} else if (discPercent) {
calcDisc(discPercent, charterPriceTotal, formattedCharterPrice);
} else {
//If no discount
startPrice.text = String(formattedCharterPrice);
//Charter only without a discount;
beforePrice.text = `Charter from`;
ribbonBox.hide();
}
if (!remarksVal) {
remarks.text = `Charter only`;
} else {
if (remarksVal === "EMPTY") {
remarks.hide();
} else {
remarks.text = remarksVal;
}
}
}
//IF TRIP IS SOLD OUT
} else {
soldOut();
}
//BUTTON ELEMENTS
const bookBtn = $item("#bookBtn");
const itinBtn = $item("#itinBtn");
const btnLink = `/booking/${itemData.tripCode}`;
const itinLink = `/itinerary/${itemData.itinerary.url}`;
bookBtn.link = btnLink;
bookBtn.target = "_blank";
itinBtn.link = itinLink;
itinBtn.target = "_blank";
});
}
//FUNCTION #2 TO BUILD FILTERS AND POPULATE REPEATERS BASED ON FILTERS
async function buildFiltersAndPopulateRepeater() {
let query = wixData.query("ScheduleRates");
query = query.ascending("departure").include("yacht", "destinations", "itinerary");
if (yachtFilter.value) {
query = query.eq("yacht", yachtFilter.value);
}
if (destFilter.value) {
query = query.hasSome("destinations", destFilter.value);
}
if (yearFilter.value && yearFilter.value != "0") {
let firstDate = new Date(Number(yearFilter.value), 0);
let lastDate = new Date(Number(yearFilter.value) + 1, 0);
query = query.ge("departure", firstDate).lt("departure", lastDate);
}
repeater.data = await query.find().then((res) => {
let hasNext = res.hasNext;
let hasPrev = res.hasPrev;
if (res.items.length > 0) {
return res.items;
} else {
repeater.data = [];
}
});
}
//FUNCTION #3 TO INITIATE COMPONENTS
async function initComps() {
populateDropdown(destDataset, destFilter, "destinations");
populateDropdown(yachtsDataset, yachtFilter, "yacht");
populateYears();
//Allow filtering on change
const filterBy = (filter) => {
filter.onChange(() => {
buildFiltersAndPopulateRepeater();
});
};
filterBy(yachtFilter);
filterBy(destFilter);
filterBy(yearFilter);
//Define reset function
const resetFilter = () => {
yachtFilter.value = null;
destFilter.value = null;
yearFilter.value = null;
buildFiltersAndPopulateRepeater();
}
resetBtn.onClick(() => {
resetFilter();
})
}
//FUNCTION #4 TO POPULATE DROPDOWNS
function populateDropdown(dataset, dropdown, type) {
dataset.onReady(() => {
dataset
.getItems(0, Infinity)
.then((res) => {
let items = res.items;
let arr = [{ label: "-", value: null }];
for (let i = 0; i < items.length; i++) {
arr.push({ label: items[i].title, value: items[i]._id });
}
dropdown.options = arr;
if (type.slice(-1) === "s") {
let str = type.slice(0, -1)
dropdown.placeholder = `Select a ${str}`;
} else {
dropdown.placeholder = `Select a ${type}`;
}
})
});
}
//FUNCTION #5 TO POPULATE YEARS DROPDOWN
function populateYears() {
yearsDataset.onReady(() => {
yearsDataset.getItems(0, Infinity).then((res) => {
let trips = res.items;
let years = [];
let yearsArr = [{ label: "-", value: "0" }];
for (let i = 0; i < trips.length; i++) {
let year = trips[i].departure.getFullYear();
if (!years.includes(year)) {
years.push(year);
yearsArr.push({ label: String(year), value: String(year) });
yearsArr.sort((a, b) => a.value.localeCompare(b.value));
}
}
yearsArr[0].value = null;
yearFilter.options = yearsArr;
yearFilter.placeholder = `Select a year`;
})
})
}
Thank you!