diff --git a/public/assets/images/placeholder.svg b/public/assets/images/placeholder.svg new file mode 100644 index 0000000..471b386 --- /dev/null +++ b/public/assets/images/placeholder.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/app/features/website/catalog/containers/catalog-container.component.ts b/src/app/features/website/catalog/containers/catalog-container.component.ts index 3c42d1f..bd1d6d6 100644 --- a/src/app/features/website/catalog/containers/catalog-container.component.ts +++ b/src/app/features/website/catalog/containers/catalog-container.component.ts @@ -110,7 +110,10 @@ export class CatalogContainerComponent { readonly isDrawerLayout = computed(() => this.viewportWidth() <= 1024); readonly isMobile = computed(() => this.viewportWidth() <= 767); readonly hasRawProducts = computed(() => this.rawProducts().length > 0); - readonly isEmptyCategoryState = computed(() => this.viewMode() === 'products' && !this.loadingProducts() && this.rawProducts().length === 0 && this.subcategoryChips().length === 0); + // A blank search query with zero raw results is a "nothing found" search result, not an + // empty category — showing category-navigation copy ("browse categories" / "go to parent + // category") here is misleading when the emptiness is caused by the user's search term. + readonly isEmptyCategoryState = computed(() => this.viewMode() === 'products' && !this.loadingProducts() && this.rawProducts().length === 0 && this.subcategoryChips().length === 0 && !this.state().search.trim()); readonly isFilteredEmptyState = computed(() => this.viewMode() === 'products' && !this.loadingProducts() && this.rawProducts().length > 0 && this.products().length === 0); readonly showDesktopFilters = computed(() => this.viewMode() === 'products' && !this.isEmptyCategoryState() && !this.isDrawerLayout() && !this.offlineState()); readonly showMobileToolbar = computed(() => this.viewMode() === 'products' && !this.isEmptyCategoryState() && this.isMobile() && !this.offlineState()); diff --git a/src/app/features/website/user-experience/compare/components/compare-table.component.ts b/src/app/features/website/user-experience/compare/components/compare-table.component.ts index afd5e44..29b45ea 100644 --- a/src/app/features/website/user-experience/compare/components/compare-table.component.ts +++ b/src/app/features/website/user-experience/compare/components/compare-table.component.ts @@ -10,6 +10,13 @@ interface CompareRow { identical: boolean; } +const STOCK_LABEL_KEYS: Record = { + high: 'catalog.stockHigh', + medium: 'catalog.stockMedium', + low: 'catalog.stockLow', + out: 'catalog.stockOut' +}; + @Component({ selector: 'app-compare-table', standalone: true, @@ -34,7 +41,7 @@ export class CompareTableComponent { const baseRows: CompareRow[] = [ this.toRow('price', this.i18n.t('ux.comparePrice'), products.map(product => `${product.price.toFixed(2)} ${product.currency}`)), this.toRow('rating', this.i18n.t('ux.compareRating'), products.map(product => `${(product.rating ?? 0).toFixed(1)}`)), - this.toRow('stock', this.i18n.t('ux.compareStock'), products.map(product => product.remainings ?? this.i18n.t('ux.compareUnknown'))), + this.toRow('stock', this.i18n.t('ux.compareStock'), products.map(product => this.stockLabel(product.remainings))), this.toRow('discount', this.i18n.t('ux.compareDiscount'), products.map(product => `${product.discount ?? 0}%`)), this.toRow('color', this.i18n.t('ux.compareColor'), products.map(product => product.colour ?? '—')), this.toRow('size', this.i18n.t('ux.compareSize'), products.map(product => product.size ?? '—')) @@ -58,6 +65,14 @@ export class CompareTableComponent { return this.highlightDifferences && !row.identical; } + private stockLabel(remainings: string | undefined): string { + if (!remainings) { + return this.i18n.t('ux.compareUnknown'); + } + const key = STOCK_LABEL_KEYS[remainings.toLowerCase()]; + return key ? this.i18n.t(key) : remainings; + } + private toRow(key: string, label: string, values: string[]): CompareRow { const normalized = values.map(value => value.trim().toLowerCase()); const identical = normalized.every(value => value === normalized[0]); diff --git a/src/app/pages/cart/cart.component.html b/src/app/pages/cart/cart.component.html index 44e1c43..9061471 100644 --- a/src/app/pages/cart/cart.component.html +++ b/src/app/pages/cart/cart.component.html @@ -40,7 +40,9 @@ -

{{ itemDesc(item) || '' }}...

+ @if (itemDesc(item)) { +

{{ itemDesc(item) }}...

+ } @if (item.colour || (item.size && item.size.toLowerCase() !== 'default')) {
diff --git a/src/assets/mock/bootstrap/bootstrap.json b/src/assets/mock/bootstrap/bootstrap.json index 1d3a493..31e9ef3 100644 --- a/src/assets/mock/bootstrap/bootstrap.json +++ b/src/assets/mock/bootstrap/bootstrap.json @@ -201,7 +201,7 @@ { "id": "footer-about", "labelKey": "nav.about", - "route": "/about", + "route": "/about-us", "order": 1 }, {