Tell us what’s happening:
Hi all
test 39 - 42 fail, which are the filter button tests
I can see the filters working in the preview.
i tried the solutions mentioned in other similar questions, like
I’ve tried getting the buttons with a querySelectorAll and getting them separately.
I’ve used incognito mode, and reseting the task and repasting my code
but nothing seams to solve it
any help or pointers will be gratefully received
Your code so far
<!-- file: index.html -->
/* file: styles.css */
/* file: index.ts */
interface Item {
type: "book" | "electronics" | "clothing";
id: string;
price: number;
}
interface Book extends Item {
type: "book";
title: string;
author: string;
}
interface Electronics extends Item {
type: "electronics";
item: string;
model: string;
warranty?: number;
}
interface Clothing extends Item {
type: "clothing";
item: string;
brand: string;
size?: "S" | "M" | "L";
}
type Product = Book | Electronics | Clothing;
class Collection <T> {
items : T[]
constructor (items: T[]) {
this.items = items
}
getAll(): T[] {
return this.items
}
filter(callback: Function) {
return this.items.filter((item: T) => callback(item))
}
}
function isBook(item: Item): item is Book {
return item.type === "book"
}
function isElectronics(item: Item): item is Electronics {
return item.type === "electronics"
}
function isClothing(item: Item): item is Clothing {
return item.type === "clothing"
}
function renderProduct (product: Product): string {
const sterlingFormatter = new Intl.NumberFormat('en-GB', {
style: 'currency',
currency: 'GBP',
})
let HTMLStringArr = [`
<div id="${product.id}" class="item">
`]
if (isBook(product)) {
HTMLStringArr.push(`
<p>Book: ${product.title} by ${product.author}</p>
`)
}
else if (isElectronics(product)) {
HTMLStringArr.push(`
<p>Electronics: ${product.item} - ${product.model}${product.warranty ? ` - Warranty: ${product.warranty} year(s)` : ""}</p>
`)
}
else if (isClothing(product)) {
HTMLStringArr.push(`
<p>Clothing: ${product.item} by ${product.brand}${product.size ? ` - Size ${product.size}` : ""}</p>
`)
}
else {
throw new Error(`Unknown product type: ${JSON.stringify(product)}`)
}
HTMLStringArr.push(`<p class="price">${sterlingFormatter.format(product.price)}</p></div>
`)
return HTMLStringArr.join("")
}
const books: Book[] = [
{ id: "b1", type: "book", price: 12.99, title: "The Hobbit", author: "J.R.R. Tolkien" },
{ id: "b2", type: "book", price: 9.5, title: "1984", author: "George Orwell" },
{ id: "b3", type: "book", price: 15, title: "Dune", author: "Frank Herbert" },
{ id: "b4", type: "book", price: 8.75, title: "Fahrenheit 451", author: "Ray Bradbury" },
];
const electronics: Electronics[] = [
{ id: "e1", type: "electronics", price: 799, item: "Laptop", model: "X1-Carbon", warranty: 24 },
{ id: "e2", type: "electronics", price: 149, item: "Headphones", model: "QuietComfort", warranty: 1 },
{ id: "e3", type: "electronics", price: 999, item: "Smartphone", model: "Pixel 9", warranty: 6 },
{ id: "e4", type: "electronics", price: 249, item: "Tablet", model: "MiniPad 3" },
];
const clothing: Clothing[] = [
{ id: "c1", type: "clothing", price: 45, item: "T-Shirt", brand: "Uniqlo", size: "M" },
{ id: "c2", type: "clothing", price: 89, item: "Jeans", brand: "Levi's", size: "L" },
{ id: "c3", type: "clothing", price: 120, item: "Jacket", brand: "The North Face" },
{ id: "c4", type: "clothing", price: 25, item: "Socks", brand: "Nike", size: "S" },
];
const allItems: Product[] = [...books, ...electronics, ...clothing];
const products = new Collection<Product>(allItems)
const outputElement: HTMLElement = document.getElementById("output")!
// const buttonElements: NodeListOf<HTMLButtonElement> = document.querySelectorAll("button")
function isButtonElement(button: unknown): button is HTMLButtonElement {
return button instanceof HTMLButtonElement
}
// buttonElements.forEach(button => {
// button.addEventListener("click", (e) => {
// if (isButtonElement(e.currentTarget)){
// let id: string = e.currentTarget.id
// if (id === "books") id = "book"
// showProducts(id)
// }
// })
// })
const allButton = document.querySelector("#all") as HTMLButtonElement
const booksButton = document.querySelector("#books") as HTMLButtonElement
const electronicsButton = document.querySelector("#electronics") as HTMLButtonElement
const clothingButton = document.querySelector("#clothing") as HTMLButtonElement
allButton.addEventListener("click", (e) => {
if (isButtonElement(e.currentTarget)){
showProducts("all")
}
})
booksButton.addEventListener("click", (e) => {
if (isButtonElement(e.currentTarget)){
showProducts("book")
}
})
electronicsButton.addEventListener("click", (e) => {
if (isButtonElement(e.currentTarget)){
showProducts("electronics")
}
})
clothingButton.addEventListener("click", (e) => {
if (isButtonElement(e.currentTarget)){
showProducts("clothing")
}
})
function showProducts(filterBy: string = "all"): void {
let productsToRender: Product[]
if (filterBy === "all" || filterBy === undefined) {
productsToRender = products.getAll()
}
else {
productsToRender = products.getAll().filter((product: Product) => product.type === filterBy)
}
outputElement.innerHTML = productsToRender.map(product => renderProduct(product)).join("")
}
document.addEventListener("DOMContentLoaded", (event) => {
showProducts()
});
Your browser information:
User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36
Challenge Information:
Build a Product Showcase - Build a Product Showcase