class MarketGrid extends Shadow { listings; constructor(listings) { super() this.listings = listings } boldUntilFirstSpace(text) { if(!text) return const index = text.indexOf(' '); if (index === -1) { // No spaces — bold the whole thing return `${text}`; } return `${text.slice(0, index)}${text.slice(index)}`; } render() { VStack(() => { h3("Results") .marginTop(0.1, em) .marginBottom(1, em) .marginLeft(0.4, em) .color("var(--accent)") .opacity(0.7) if (this.listings.length > 0) { ZStack(() => { // BuyModal() let params = new URLSearchParams(window.location.search); const hyperiaMade = params.get("hyperia-made") === "true"; const americaMade = params.get("america-made") === "true"; const newItem = params.get("new") === "true"; const usedItem = params.get("used") === "true"; let filtered = this.listings; if (hyperiaMade) { filtered = filtered.filter(item => item.madeIn === "Hyperia"); } if (americaMade) { filtered = filtered.filter(item => item.madeIn === "America"); } if (newItem) { filtered = filtered.filter(item => item.type === "new"); } if (usedItem) { filtered = filtered.filter(item => item.type === "used"); } for (let i = 0; i < filtered.length; i++) { const rating = filtered[i].stars const percent = (rating / 5) VStack(() => { img(filtered[i].image) .marginBottom(0.5, em) p(filtered[i].company) .marginBottom(0.5, em) p(filtered[i].title) .fontSize(1.2, em) .fontWeight("bold") .marginBottom(0.5, em) HStack(() => { p(filtered[i].stars) .marginRight(0.2, em) ZStack(() => { div("★★★★★") // Empty stars (background) .color("#ccc") div("★★★★★") // Filled stars (foreground, clipped by width) .color("#ffa500") .position("absolute") .top(0) .left(0) .whiteSpace("nowrap") .overflow("hidden") .width(percent * 5, em) }) .display("inline-block") .position("relative") .fontSize(1.2, em) .lineHeight(1) p(filtered[i].reviews) .marginLeft(0.2, em) }) .marginBottom(0.5, em) p(filtered[i].price) .fontSize(1.75, em) .marginBottom(0.5, em) button("Coming Soon!") .onClick((finished) => { if(finished) { } }) .onHover(function (hovering) { if(hovering) { this.style.backgroundColor = "var(--green)" } else { this.style.backgroundColor = "" } }) }) .padding(1, em) .border("1px solid var(--accent2)") .borderRadius(5, "px") } }) .display("grid") .gridTemplateColumns("repeat(auto-fill, minmax(250px, 1fr))") .gap(1, em) } else { p("No Listings!") } }) .onQueryChanged(() => { console.log("query did change yup") this.rerender() }) .height(100, vh) .paddingLeft(2, em) .paddingRight(2, em) .gap(0, em) .width(100, "%") } } register(MarketGrid)