Files
print-calculator/frontend/src/app/features/shop/shop-page.component.html
Joe Küng d27558a3ee
Some checks failed
Build and Deploy / test-backend (push) Successful in 39s
Build and Deploy / test-frontend (push) Successful in 1m3s
Build and Deploy / build-and-push (push) Successful in 32s
Build and Deploy / deploy (push) Successful in 19s
PR Checks / security-sast (pull_request) Successful in 30s
PR Checks / prettier-autofix (pull_request) Failing after 11s
PR Checks / test-backend (pull_request) Successful in 28s
PR Checks / test-frontend (pull_request) Successful in 1m3s
fix(front-end): fix no index product 3 hope the last one
2026-03-24 12:59:09 +01:00

236 lines
7.7 KiB
HTML

<section class="shop-page">
<div class="container ui-simple-hero shop-hero">
<h1 class="ui-simple-hero__title">{{ "NAV.SHOP" | translate }}</h1>
<p class="ui-simple-hero__subtitle">{{ heroSubtitle() }}</p>
</div>
<div class="container shop-layout">
<aside class="shop-sidebar">
<app-card class="category-card">
<div class="panel-head">
<div>
<p class="panel-kicker">
{{ "SHOP.CATEGORY_PANEL_KICKER" | translate }}
</p>
<h2 class="panel-title">
{{ "SHOP.CATEGORY_PANEL_TITLE" | translate }}
</h2>
</div>
</div>
<button
type="button"
class="category-link"
[class.active]="!currentCategorySlug()"
(click)="navigateToCategory()"
>
<span class="category-name">{{
"SHOP.ALL_CATEGORIES" | translate
}}</span>
</button>
<div class="category-list">
@for (node of categoryNodes(); track trackByCategory($index, node)) {
<button
type="button"
class="category-link"
[class.active]="node.current"
[style.--depth]="node.depth"
(click)="navigateToCategory(node.slug)"
>
<span class="category-name">{{ node.name }}</span>
<small class="category-count">{{ node.productCount }}</small>
</button>
}
</div>
</app-card>
<app-card class="cart-card">
<div class="panel-head">
<div>
<p class="panel-kicker">{{ "SHOP.CART_TITLE" | translate }}</p>
<h2 class="panel-title">
{{ "SHOP.CART_SUMMARY_TITLE" | translate }}
</h2>
</div>
@if (cartHasItems()) {
<button
type="button"
class="text-action"
[disabled]="cartMutating()"
(click)="clearCart()"
>
{{ "SHOP.CLEAR_CART" | translate }}
</button>
}
</div>
@if (cartLoading() && !cart()) {
<p class="panel-empty">{{ "SHOP.CART_LOADING" | translate }}</p>
} @else if (!cartHasItems()) {
<p class="panel-empty">{{ "SHOP.CART_EMPTY" | translate }}</p>
} @else {
<div class="cart-lines">
@for (item of cartItems(); track trackByCartItem($index, item)) {
<article class="cart-line">
<div class="cart-line-copy">
<strong>{{ cartItemName(item) }}</strong>
@if (cartItemVariant(item); as variant) {
<span class="cart-line-meta">{{
variant | translate
}}</span>
}
@if (cartItemColor(item); as color) {
<span class="cart-line-color">
<span
class="color-dot"
[style.background-color]="cartItemColorHex(item)"
></span>
<span>{{ color | translate }}</span>
</span>
}
</div>
<div class="cart-line-controls">
<div class="qty-control">
<button
type="button"
[disabled]="
cartMutating() && busyLineItemId() === item.id
"
(click)="decreaseQuantity(item)"
>
-
</button>
<span>{{ item.quantity }}</span>
<button
type="button"
[disabled]="
cartMutating() && busyLineItemId() === item.id
"
(click)="increaseQuantity(item)"
>
+
</button>
</div>
<strong class="line-total">{{
item.unitPriceChf * item.quantity | currency: "CHF"
}}</strong>
</div>
<button
type="button"
class="line-remove"
[disabled]="cartMutating() && busyLineItemId() === item.id"
(click)="removeItem(item)"
>
{{ "SHOP.REMOVE" | translate }}
</button>
</article>
}
</div>
<div class="cart-totals">
<div class="cart-total-row">
<span>{{ "SHOP.CART_SUBTOTAL" | translate }}</span>
<strong>{{
cart()?.itemsTotalChf || 0 | currency: "CHF"
}}</strong>
</div>
<div class="cart-total-row">
<span>{{ "SHOP.CART_SHIPPING" | translate }}</span>
<strong>{{
cart()?.shippingCostChf || 0 | currency: "CHF"
}}</strong>
</div>
<div class="cart-total-row cart-total-row-final">
<span>{{ "SHOP.CART_TOTAL" | translate }}</span>
<strong>{{
cart()?.grandTotalChf || 0 | currency: "CHF"
}}</strong>
</div>
</div>
<app-button
variant="primary"
[fullWidth]="true"
[disabled]="cartMutating()"
(click)="goToCheckout()"
>
{{ "SHOP.GO_TO_CHECKOUT" | translate }}
</app-button>
}
</app-card>
</aside>
<section class="catalog-content">
@if (error()) {
<div class="catalog-state catalog-state-error">
{{ error() | translate }}
</div>
} @else {
<section class="catalog-panel">
<div class="section-head catalog-head">
<div>
<p class="ui-eyebrow ui-eyebrow--compact">
{{ catalogEyebrow() }}
</p>
<h2 class="section-title">{{ catalogTitle() }}</h2>
</div>
<span class="catalog-counter">
{{ products().length }}
{{ "SHOP.ITEMS_FOUND" | translate }}
</span>
</div>
@if (loading() || softFallbackActive()) {
<div class="product-grid skeleton-grid">
@for (ghost of [1, 2, 3, 4]; track ghost) {
<div class="skeleton-card"></div>
}
</div>
} @else if (products().length === 0) {
<div class="catalog-state">
{{ "SHOP.EMPTY_CATEGORY" | translate }}
</div>
} @else {
<div class="product-grid">
@for (
product of products();
track trackByProduct($index, product)
) {
<app-product-card
[product]="product"
[cartQuantity]="productCartQuantity(product.id)"
></app-product-card>
}
</div>
}
</section>
}
</section>
</div>
<section class="container shop-custom-cta">
<app-card class="shop-custom-cta-card">
<div class="shop-custom-cta-inner">
<div class="shop-custom-cta-copy">
<p class="panel-kicker">
{{ "SHOP.CUSTOM_PART_FOOTER_TITLE" | translate }}
</p>
<h2 class="shop-custom-cta-title">
{{ "SHOP.CUSTOM_PART_FOOTER_TEXT" | translate }}
</h2>
</div>
<app-button
variant="primary"
[routerLink]="languageService.localizedPath('/contact')"
>
{{ "NAV.CONTACT" | translate }}
</app-button>
</div>
</app-card>
</section>
</section>