UNPKG

@salla.sa/twilight-components

Version:
171 lines (170 loc) 7.72 kB
/*! * Crafted with ❤ by Salla */ import { h } from "@stencil/core"; import ShoppingBag from "../../assets/svg/shopping-bag.svg"; import Helper from "../../Helpers/Helper"; import { MasonryLayout } from "../../Helpers/masonry-layout"; export class SallaReviewsPage { constructor() { this.reviews = []; this.isLoading = false; this.pagination = null; this.sort = "latest"; } getUrlParams() { const params = new URLSearchParams(window.location.search); return { sort: params.get('sort') || null, page: Number.parseInt(params.get('page')) || 1 }; } updateUrlParams(params) { const url = new URL(window.location.href); for (const [key, value] of Object.entries(params)) { if (value) { url.searchParams.set(key, value.toString()); } else { url.searchParams.delete(key); } } ; window.history.replaceState({}, '', url.toString()); } fetchReviews(sort, page) { const urlParams = this.getUrlParams(); return salla.api.request('reviews', { params: { type: 'products', format: 'lite', per_page: 8, page: page || urlParams.page || 1, sort: sort || urlParams.sort || null } }); } async initializeMasonry() { const grid = this.el.querySelector('.s-reviews-page-grid'); if (!grid) return; try { new MasonryLayout(grid); salla.logger.info('Masonry initialized successfully'); } catch (error) { salla.logger.error('Masonry initialization failed:', error); } } animateReviewCards() { const items = this.wrapper.querySelectorAll('salla-review-card:not(.animated)'); Helper.animateItems(items); } initiateInfiniteScroll() { if (!this.wrapper) { salla.logger.error('Wrapper is undefined. Cannot initiate infinite scroll.'); return; } this.infiniteScroll = salla.infiniteScroll.initiate(this.wrapper, this.wrapper, { path: () => this.pagination?.links?.next || null, history: false, scrollThreshold: false, }, true); this.infiniteScroll?.on('request', () => { this.isLoading = true; }); this.infiniteScroll?.on('load', response => { this.pagination = response.pagination; this.reviews = [...this.reviews, ...response.data]; this.isLoading = false; // Update URL with the current page this.updateUrlParams({ page: response.pagination.current_page }); }); this.infiniteScroll?.on('error', (e) => { salla.logger.error('Error loading more reviews:', e); this.isLoading = false; }); } componentDidRender() { setTimeout(() => { requestAnimationFrame(this.animateReviewCards.bind(this)); }, 176); } async componentWillLoad() { try { await salla.onReady(); // Initialize language variables this.langTitlesReviews = salla.lang.get("common.titles.reviews"); this.langSorting = salla.lang.get('pages.categories.sorting'); this.placeholderText = salla.lang.choice("pages.rating.reviews", 0); this.langLoadMore = salla.lang.get('common.elements.load_more'); this.langSortByTopRating = salla.lang.get('pages.testimonials.sort_by_rating_desc'); this.langSortByMostRecent = salla.lang.get('pages.testimonials.sort_by_date_desc'); this.langSortByLeastRated = salla.lang.get('pages.testimonials.sort_by_rating_asc'); this.langSortByLeastRecent = salla.lang.get('pages.testimonials.sort_by_date_asc'); const urlParams = this.getUrlParams(); const response = await this.fetchReviews(urlParams.sort); this.sort = urlParams.sort; this.reviews = response.data; this.pagination = response.pagination; this.langRatingReviews = salla.lang.choice("pages.rating.reviews", this.pagination?.total); } catch (error) { salla.logger.error('Error loading reviews:', error); } } async handleSorting(e) { const value = e.target.value; this.sort = value; this.updateUrlParams({ sort: value, page: 1 }); // Reset to page 1 when changing sort const response = await this.fetchReviews(value, 1); this.reviews = response.data; this.pagination = response.pagination; } async componentDidLoad() { await this.initializeMasonry(); this.initiateInfiniteScroll(); this.sort = this.getUrlParams().sort || "latest"; this.updateUrlParams({ sort: this.sort, page: 1 }); } disconnectedCallback() { if (this.infiniteScroll) { this.infiniteScroll.destroy(); } } renderSortingOptions() { const options = [ { value: 'latest', label: this.langSortByMostRecent }, { value: 'oldest', label: this.langSortByLeastRecent }, { value: 'top_rating', label: this.langSortByTopRating }, { value: 'bottom_rating', label: this.langSortByLeastRated }, ]; return options.map(option => (h("option", { key: option.value, value: option.value, selected: option.value === this.sort }, option.label))); } render() { return (h("host", { key: '9e93c876f4cf9d49748bc219cd81c871ddfcb9ba' }, h("div", { key: '322e9487de2da90e78ef96eaf126c5ab9839255f', class: "s-reviews-page-header-wrapper" }, h("h2", { key: '7f2cc0885d83123bd1a2c0e7d795a7e61987b4a7', class: "s-reviews-page-title" }, this.langTitlesReviews, h("span", { key: 'e61048238b21b6645f4799ae1dcd5f9e6d660088', class: "s-reviews-page-count" }, "(", this.langRatingReviews, ")")), h("div", { key: 'ce8a0de87512c023f623604c0b486ea4f37ac8ab', class: "s-reviews-page-filter-wrapper" }, h("label", { key: '35bcbffd914e811ebf73253d93e7b972f3b56cbc', class: "s-reviews-page-filter-label", htmlFor: "testimonials-filter" }, this.langSorting), h("select", { key: 'e57ea01b2aba04e82c63e51edf952e5c6ee460e6', onChange: (e) => this.handleSorting(e), disabled: !this.reviews.length, class: "s-reviews-page-filter" }, this.renderSortingOptions()))), this.reviews.length ? h("main", { class: "s-reviews-page-grid", ref: el => { this.wrapper = el; } }, this.reviews.map(review => (h("salla-review-card", { key: review.id, review: review })))) : h("div", { class: "s-products-list-placeholder" }, h("span", { innerHTML: ShoppingBag }), h("p", null, this.placeholderText)), this.pagination?.links?.next && this.reviews.length ? (h("div", { class: "s-reviews-page-load-more-container" }, h("salla-button", { class: "s-reviews-page-load-more-btn", loading: this.isLoading, onClick: () => this.infiniteScroll?.loadNextPage(), onKeyUp: () => this.infiniteScroll?.loadNextPage() }, this.langLoadMore))) : null)); } static get is() { return "salla-reviews-page"; } static get originalStyleUrls() { return { "$": ["salla-reviews-page.css"] }; } static get styleUrls() { return { "$": ["salla-reviews-page.css"] }; } static get states() { return { "reviews": {}, "isLoading": {}, "pagination": {}, "sort": {} }; } static get elementRef() { return "el"; } }