/** * Book Card Component * Reusable card displaying book thumbnail, title, description, author, and price * Horizontal layout with image on left and content on right */ class BookCard extends HTMLElement { static get observedAttributes() { return [ "title", "author", "description", "price", "image", "href", "theme", ]; } constructor() { super(); this.attachShadow({ mode: "open" }); } connectedCallback() { this.render(); this.setupEventListeners(); } setupEventListeners() { const addToCartButton = this.shadowRoot?.querySelector("add-to-cart-button"); if (addToCartButton) { addToCartButton.addEventListener("add-to-cart", (e) => { e.stopPropagation(); // Re-dispatch with book details this.dispatchEvent( new CustomEvent("add-to-cart", { bubbles: true, composed: true, detail: { title: this.title, author: this.author, price: this.price, }, }) ); }); } } attributeChangedCallback() { if (this.shadowRoot) { this.render(); this.setupEventListeners(); } } get title() { return this.getAttribute("title") || "Book Title"; } get author() { return this.getAttribute("author") || "Author Name"; } get description() { return this.getAttribute("description") || ""; } get price() { return this.getAttribute("price") || "$0.00"; } get image() { return this.getAttribute("image") || ""; } get href() { return this.getAttribute("href") || "book.html"; } get theme() { return this.getAttribute("theme") || "light"; // 'light' or 'dark' } render() { const backgroundColor = this.theme === "dark" ? "var(--color-card-dark-bg, #ebeef4)" : "var(--color-background, #ffffff)"; // Generate placeholder image if none provided const imageHtml = this.image ? `${this.title}` : `
`; this.shadowRoot.innerHTML = `
${imageHtml}
${this.title} ${ this.description ? `

${this.description}

` : "" } ${this.author}

${this.price}

`; } } customElements.define("book-card", BookCard);