Migration Angular v19 -> v20

This commit is contained in:
Lorenz Hilpert
2025-06-16 11:54:47 +02:00
parent 54664123fb
commit d8c2ca9bdc
272 changed files with 10560 additions and 9792 deletions

View File

@@ -2,6 +2,3 @@ last 1 Chrome version
last 1 Firefox version last 1 Firefox version
last 2 Edge major versions last 2 Edge major versions
last 2 iOS major versions last 2 iOS major versions
safari > 11
Firefox ESR
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.

View File

@@ -1,4 +1,4 @@
import { DOCUMENT } from '@angular/common';
import { import {
Component, Component,
effect, effect,
@@ -10,6 +10,7 @@ import {
Renderer2, Renderer2,
signal, signal,
untracked, untracked,
DOCUMENT
} from '@angular/core'; } from '@angular/core';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { SwUpdate } from '@angular/service-worker'; import { SwUpdate } from '@angular/service-worker';

View File

@@ -3,10 +3,12 @@
<p>Vorschläge:</p> <p>Vorschläge:</p>
<ul class="content"> <ul class="content">
<li *ngFor="let item of ref?.data"> @for (item of ref?.data; track item) {
<li>
<span>{{ item.street }} {{ item.streetNumber }}, {{ item.zipCode }} {{ item.city }}</span> <span>{{ item.street }} {{ item.streetNumber }}, {{ item.zipCode }} {{ item.city }}</span>
<button (click)="ref.close(item)">Übernehmen</button> <button (click)="ref.close(item)">Übernehmen</button>
</li> </li>
}
</ul> </ul>
<div class="center"> <div class="center">

View File

@@ -7,12 +7,18 @@
(click)="filter(input.value)" (click)="filter(input.value)"
[disabled]="branchesFetching$ | async" [disabled]="branchesFetching$ | async"
> >
<ui-icon class="spin" *ngIf="branchesFetching$ | async" icon="spinner" size="32px"></ui-icon> @if (branchesFetching$ | async) {
<ui-icon *ngIf="!(branchesFetching$ | async)" icon="search" size="24px"></ui-icon> <ui-icon class="spin" icon="spinner" size="32px"></ui-icon>
}
@if (!(branchesFetching$ | async)) {
<ui-icon icon="search" size="24px"></ui-icon>
}
</button> </button>
<button *ngIf="input.value" type="reset" uiSearchboxClearButton (click)="filter(''); cancelSearch(); input.value = ''"> @if (input.value) {
<button type="reset" uiSearchboxClearButton (click)="filter(''); cancelSearch(); input.value = ''">
<ui-icon icon="close" size="22px"></ui-icon> <ui-icon icon="close" size="22px"></ui-icon>
</button> </button>
}
</ui-searchbox> </ui-searchbox>
<p class="subtitle"> <p class="subtitle">
@@ -25,7 +31,7 @@
<hr /> <hr />
<div class="branches"> <div class="branches">
<ng-container *ngFor="let branch of filteredBranches$ | async"> @for (branch of filteredBranches$ | async; track branch) {
<div class="branch"> <div class="branch">
<div class="branch-info"> <div class="branch-info">
<span class="branch-name"> <span class="branch-name">
@@ -36,25 +42,23 @@
{{ branch.address.city }} {{ branch.address.city }}
</span> </span>
</div> </div>
<div class="branch-actions"> <div class="branch-actions">
@if ((branch.id | stockInfo: (inStock$ | async))?.availableQuantity > 0 && branch?.isShippingEnabled) {
<button <button
*ngIf="(branch.id | stockInfo: (inStock$ | async))?.availableQuantity > 0 && branch?.isShippingEnabled"
class="cta-reserve" class="cta-reserve"
(click)="reserve(branch)" (click)="reserve(branch)"
> >
Reservieren Reservieren
</button> </button>
}
<ui-spinner [show]="stockFetching$ | async"> <ui-spinner [show]="stockFetching$ | async">
<span class="branch-stock"> <span class="branch-stock">
<ui-icon icon="home" size="22px"></ui-icon> <ui-icon icon="home" size="22px"></ui-icon>
<span>{{ branch.id | inStock: (inStock$ | async) }}x</span> <span>{{ branch.id | inStock: (inStock$ | async) }}x</span>
</span> </span>
</ui-spinner> </ui-spinner>
</div> </div>
</div> </div>
<hr /> <hr />
</ng-container> }
</div> </div>

View File

@@ -3,9 +3,11 @@
</div> </div>
<div class="thumbnails-wrapper"> <div class="thumbnails-wrapper">
<button *ngFor="let image of images" (click)="activeImage = image" [class.selected]="activeImage.url === image.url"> @for (image of images; track image) {
<button (click)="activeImage = image" [class.selected]="activeImage.url === image.url">
<img class="thumbnail" [src]="image.thumbUrl" /> <img class="thumbnail" [src]="image.thumbUrl" />
</button> </button>
}
</div> </div>
<div class="controls"> <div class="controls">

View File

@@ -18,9 +18,11 @@
<ui-quantity-dropdown [quantity]="itemQuantity$ | async" (quantityChange)="onQuantityChange($event)"></ui-quantity-dropdown> <ui-quantity-dropdown [quantity]="itemQuantity$ | async" (quantityChange)="onQuantityChange($event)"></ui-quantity-dropdown>
</div> </div>
<div class="relative"> <div class="relative">
<div *ngIf="stockWarning$ | async" class="text-warning font-bold absolute right-0 top-0 whitespace-nowrap"> @if (stockWarning$ | async) {
<div class="text-warning font-bold absolute right-0 top-0 whitespace-nowrap">
Es befinden sich {{ availableQuantity$ | async }} Exemplare in der Filiale Es befinden sich {{ availableQuantity$ | async }} Exemplare in der Filiale
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -20,18 +20,21 @@
</div> </div>
</div> </div>
<div class="overflow-y-auto -mx-4 scroll-bar"> <div class="overflow-y-auto -mx-4 scroll-bar">
<div *ngIf="emptyShoppingCart$ | async" class="h-full grid items-center justify-center"> @if (emptyShoppingCart$ | async) {
<div class="h-full grid items-center justify-center">
<h3 class="text-xl font-bold text-center text-gray-500"> <h3 class="text-xl font-bold text-center text-gray-500">
Warenkorb ist leer, bitte suchen oder scannen Warenkorb ist leer, bitte suchen oder scannen
<br /> <br />
Sie Artikel um den Warenkob zu füllen. Sie Artikel um den Warenkob zu füllen.
</h3> </h3>
</div> </div>
}
@for (item of items$ | async; track trackItemById($index, item)) {
<shared-kulturpass-order-item <shared-kulturpass-order-item
class="border-b border-solid border-[#EFF1F5]" class="border-b border-solid border-[#EFF1F5]"
*ngFor="let item of items$ | async; trackBy: trackItemById"
[item]="item" [item]="item"
></shared-kulturpass-order-item> ></shared-kulturpass-order-item>
}
</div> </div>
<div class="flex flex-row justify-evenly items-stretch border-t border-solid border-[#EFF1F5] py-3 px-4 -mx-4"> <div class="flex flex-row justify-evenly items-stretch border-t border-solid border-[#EFF1F5] py-3 px-4 -mx-4">
<div class="grid grid-flow-row text-xl"> <div class="grid grid-flow-row text-xl">
@@ -49,7 +52,9 @@
</div> </div>
</div> </div>
<div class="grid items-end justify-between"> <div class="grid items-end justify-between">
<div *ngIf="negativeBalance$ | async" class="text-xl text-warning font-bold text-center">Der Betrag übersteigt ihr Guthaben</div> @if (negativeBalance$ | async) {
<div class="text-xl text-warning font-bold text-center">Der Betrag übersteigt ihr Guthaben</div>
}
<button <button
type="button" type="button"
class="bg-brand text-white px-6 py-3 font-bold rounded-full disabled:bg-disabled-branch disabled:text-active-branch" class="bg-brand text-white px-6 py-3 font-bold rounded-full disabled:bg-disabled-branch disabled:text-active-branch"

View File

@@ -2,8 +2,8 @@
{{ message }} {{ message }}
</p> </p>
<div class="message-modal-actions grid grid-flow-col gap-4 items-center justify-center"> <div class="message-modal-actions grid grid-flow-col gap-4 items-center justify-center">
@for (action of actions; track action) {
<button <button
*ngFor="let action of actions"
type="button" type="button"
class="btn rounded-full font-bold text-p1 border-[2px] border-solid border-brand px-6" class="btn rounded-full font-bold text-p1 border-[2px] border-solid border-brand px-6"
[class.bg-brand]="action.primary" [class.bg-brand]="action.primary"
@@ -17,4 +17,5 @@
> >
{{ action.label }} {{ action.label }}
</button> </button>
}
</div> </div>

View File

@@ -1,4 +1,4 @@
import { CommonModule } from '@angular/common';
import { Component, ChangeDetectionStrategy } from '@angular/core'; import { Component, ChangeDetectionStrategy } from '@angular/core';
import { UiModalRef } from '@ui/modal'; import { UiModalRef } from '@ui/modal';
import { MessageModalData } from './message-modal.data'; import { MessageModalData } from './message-modal.data';
@@ -10,7 +10,7 @@ import { MessageModalAction } from './message-modal.action';
styleUrls: ['message-modal.component.css'], styleUrls: ['message-modal.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'shared-message-modal' }, host: { class: 'shared-message-modal' },
imports: [CommonModule], imports: [],
}) })
export class MessageModalComponent { export class MessageModalComponent {
get message() { get message() {

View File

@@ -4,8 +4,10 @@
<div class="notification-text">{{ item.text }}</div> <div class="notification-text">{{ item.text }}</div>
</div> </div>
<div> <div>
<button *ngIf="editButton" class="notification-edit-cta text-brand font-bold text-lg px-4 py-3" (click)="itemSelected.emit(item)"> @if (editButton) {
<button class="notification-edit-cta text-brand font-bold text-lg px-4 py-3" (click)="itemSelected.emit(item)">
{{ editButtonLabel }} {{ editButtonLabel }}
</button> </button>
}
</div> </div>
</div> </div>

View File

@@ -1,5 +1,5 @@
<div class="notification-list scroll-bar"> <div class="notification-list scroll-bar">
<ng-container *ngFor="let notification of notifications"> @for (notification of notifications; track notification) {
<modal-notifications-list-item <modal-notifications-list-item
(click)="itemSelected(notification)" (click)="itemSelected(notification)"
[editButtonLabel]="'Packstück-Prüfung'" [editButtonLabel]="'Packstück-Prüfung'"
@@ -7,5 +7,5 @@
(itemSelected)="itemSelected($event)" (itemSelected)="itemSelected($event)"
></modal-notifications-list-item> ></modal-notifications-list-item>
<hr /> <hr />
</ng-container> }
</div> </div>

View File

@@ -1,8 +1,8 @@
<div class="notification-list scroll-bar"> <div class="notification-list scroll-bar">
<ng-container *ngFor="let notification of notifications"> @for (notification of notifications; track notification) {
<modal-notifications-list-item [item]="notification" (itemSelected)="itemSelected($event)"></modal-notifications-list-item> <modal-notifications-list-item [item]="notification" (itemSelected)="itemSelected($event)"></modal-notifications-list-item>
<hr /> <hr />
</ng-container> }
</div> </div>
<div class="actions"> <div class="actions">

View File

@@ -1,8 +1,8 @@
<div class="notification-list scroll-bar"> <div class="notification-list scroll-bar">
<ng-container *ngFor="let notification of notifications"> @for (notification of notifications; track notification) {
<modal-notifications-list-item [item]="notification" (itemSelected)="itemSelected($event)"></modal-notifications-list-item> <modal-notifications-list-item [item]="notification" (itemSelected)="itemSelected($event)"></modal-notifications-list-item>
<hr /> <hr />
</ng-container> }
</div> </div>
<div class="actions"> <div class="actions">

View File

@@ -1,8 +1,8 @@
<div class="notification-list scroll-bar"> <div class="notification-list scroll-bar">
<ng-container *ngFor="let notification of notifications"> @for (notification of notifications; track notification) {
<modal-notifications-list-item [item]="notification" (itemSelected)="itemSelected($event)"></modal-notifications-list-item> <modal-notifications-list-item [item]="notification" (itemSelected)="itemSelected($event)"></modal-notifications-list-item>
<hr /> <hr />
</ng-container> }
</div> </div>
<div class="actions"> <div class="actions">

View File

@@ -1,11 +1,11 @@
<div class="notification-list scroll-bar"> <div class="notification-list scroll-bar">
<ng-container *ngFor="let notification of notifications"> @for (notification of notifications; track notification) {
<div class="notification-headline"> <div class="notification-headline">
<h1>{{ notification.headline }}</h1> <h1>{{ notification.headline }}</h1>
</div> </div>
<div class="notification-text">{{ notification.text }}</div> <div class="notification-text">{{ notification.text }}</div>
<hr /> <hr />
</ng-container> }
</div> </div>
<div class="actions"> <div class="actions">

View File

@@ -1,6 +1,6 @@
<h1>Sie haben neue Nachrichten</h1> <h1>Sie haben neue Nachrichten</h1>
<ng-container *ngFor="let notification of notifications$ | async | keyvalue"> @for (notification of notifications$ | async | keyvalue; track notification) {
<button type="button" class="notification-card" (click)="selectArea(notification.key)"> <button type="button" class="notification-card" (click)="selectArea(notification.key)">
<div class="notification-icon"> <div class="notification-icon">
<div class="notification-counter">{{ notification.value?.length }}</div> <div class="notification-counter">{{ notification.value?.length }}</div>
@@ -9,30 +9,37 @@
<span>{{ notification.value?.[0]?.category }}</span> <span>{{ notification.value?.[0]?.category }}</span>
</button> </button>
<hr class="-mx-4" /> <hr class="-mx-4" />
<ng-container *ngIf="notification.key === selectedArea" [ngSwitch]="notification.value?.[0]?.category"> @if (notification.key === selectedArea) {
@switch (notification.value?.[0]?.category) {
@case ('ISA-Update') {
<modal-notifications-update-group <modal-notifications-update-group
*ngSwitchCase="'ISA-Update'"
[notifications]="notifications[selectedArea]" [notifications]="notifications[selectedArea]"
></modal-notifications-update-group> ></modal-notifications-update-group>
}
@case ('Reservierungsanfragen') {
<modal-notifications-reservation-group <modal-notifications-reservation-group
*ngSwitchCase="'Reservierungsanfragen'"
[notifications]="notifications[selectedArea]" [notifications]="notifications[selectedArea]"
(navigated)="close()" (navigated)="close()"
></modal-notifications-reservation-group> ></modal-notifications-reservation-group>
}
@case ('Remission') {
<modal-notifications-remission-group <modal-notifications-remission-group
*ngSwitchCase="'Remission'"
[notifications]="notifications[selectedArea]" [notifications]="notifications[selectedArea]"
(navigated)="close()" (navigated)="close()"
></modal-notifications-remission-group> ></modal-notifications-remission-group>
}
@case ('Tätigkeitskalender') {
<modal-notifications-task-calendar-group <modal-notifications-task-calendar-group
*ngSwitchCase="'Tätigkeitskalender'"
[notifications]="notifications[selectedArea]" [notifications]="notifications[selectedArea]"
(navigated)="close()" (navigated)="close()"
></modal-notifications-task-calendar-group> ></modal-notifications-task-calendar-group>
}
@case ('Wareneingang Lagerware') {
<modal-notifications-package-inspection-group <modal-notifications-package-inspection-group
*ngSwitchCase="'Wareneingang Lagerware'"
[notifications]="notifications[selectedArea]" [notifications]="notifications[selectedArea]"
(navigated)="close()" (navigated)="close()"
></modal-notifications-package-inspection-group> ></modal-notifications-package-inspection-group>
</ng-container> }
</ng-container> }
}
}

View File

@@ -2,13 +2,17 @@
<div class="header"> <div class="header">
<h1>Wählen Sie einen Drucker aus</h1> <h1>Wählen Sie einen Drucker aus</h1>
<span *ngIf="error" class="error-message">{{ errorMessage }}</span> @if (error) {
<span class="error-message">{{ errorMessage }}</span>
}
</div> </div>
<div class="body"> <div class="body">
<ui-spinner [show]="!loaded"> <ui-spinner [show]="!loaded">
<ui-select class="select" [(ngModel)]="selectedPrinterKey"> <ui-select class="select" [(ngModel)]="selectedPrinterKey">
<ui-select-option *ngFor="let printer of printers$ | async" [label]="printer.description" [value]="printer.key"></ui-select-option> @for (printer of printers$ | async; track printer) {
<ui-select-option [label]="printer.description" [value]="printer.key"></ui-select-option>
}
</ui-select> </ui-select>
</ui-spinner> </ui-spinner>
</div> </div>

View File

@@ -1,5 +1,9 @@
<div class="flex flex-col text-right" [class.hidden]="hideHeader$ | async"> <div class="flex flex-col text-right" [class.hidden]="hideHeader$ | async">
<button type="button" class="font-bold text-[#0556B4]" *ngIf="selectButton$ | async" (click)="selectAll()">Alle auswählen</button> @if (selectButton$ | async) {
<button type="button" class="font-bold text-[#0556B4]" *ngIf="unselectButton$ | async" (click)="unselectAll()">Alle abwählen</button> <button type="button" class="font-bold text-[#0556B4]" (click)="selectAll()">Alle auswählen</button>
}
@if (unselectButton$ | async) {
<button type="button" class="font-bold text-[#0556B4]" (click)="unselectAll()">Alle abwählen</button>
}
<span class="mt-2">{{ selectedItemsCount$ | async }} von {{ itemsCount$ | async }} Artikel</span> <span class="mt-2">{{ selectedItemsCount$ | async }} von {{ itemsCount$ | async }} Artikel</span>
</div> </div>

View File

@@ -15,39 +15,46 @@
</div> </div>
<div class="shared-purchase-options-list-item__manufacturer-and-ean"> <div class="shared-purchase-options-list-item__manufacturer-and-ean">
{{ product?.manufacturer }} {{ product?.manufacturer }}
<span *ngIf="product?.manufacturer && product?.ean">|</span> @if (product?.manufacturer && product?.ean) {
<span>|</span>
}
{{ product?.ean }} {{ product?.ean }}
</div> </div>
<div class="shared-purchase-options-list-item__volume-and-publication-date"> <div class="shared-purchase-options-list-item__volume-and-publication-date">
{{ product?.volume }} {{ product?.volume }}
<span *ngIf="product?.volume && product?.publicationDate">|</span> @if (product?.volume && product?.publicationDate) {
<span>|</span>
}
{{ product?.publicationDate | date: 'dd. MMMM yyyy' }} {{ product?.publicationDate | date: 'dd. MMMM yyyy' }}
</div> </div>
<div class="shared-purchase-options-list-item__availabilities mt-3 grid grid-flow-row gap-2 justify-start"> <div class="shared-purchase-options-list-item__availabilities mt-3 grid grid-flow-row gap-2 justify-start">
<div class="whitespace-nowrap self-center" *ngIf="(availabilities$ | async)?.length">Verfügbar als</div> @if ((availabilities$ | async)?.length) {
<div *ngFor="let availability of availabilities$ | async" class="grid grid-flow-col gap-4 justify-start"> <div class="whitespace-nowrap self-center">Verfügbar als</div>
}
@for (availability of availabilities$ | async; track availability) {
<div class="grid grid-flow-col gap-4 justify-start">
<div <div
[ngSwitch]="availability.purchaseOption"
class="shared-purchase-options-list-item__availability grid grid-flow-col gap-2 items-center" class="shared-purchase-options-list-item__availability grid grid-flow-col gap-2 items-center"
[attr.data-option]="availability.purchaseOption" [attr.data-option]="availability.purchaseOption"
> >
<ng-container *ngSwitchCase="'delivery'"> @switch (availability.purchaseOption) {
@case ('delivery') {
<shared-icon icon="isa-truck" [size]="22"></shared-icon> <shared-icon icon="isa-truck" [size]="22"></shared-icon>
{{ availability.data.estimatedDelivery?.start | date: 'EE dd.MM.' }} {{ availability.data.estimatedDelivery?.start | date: 'EE dd.MM.' }}
- -
{{ availability.data.estimatedDelivery?.stop | date: 'EE dd.MM.' }} {{ availability.data.estimatedDelivery?.stop | date: 'EE dd.MM.' }}
</ng-container> }
<ng-container *ngSwitchCase="'dig-delivery'"> @case ('dig-delivery') {
<shared-icon icon="isa-truck" [size]="22"></shared-icon> <shared-icon icon="isa-truck" [size]="22"></shared-icon>
{{ availability.data.estimatedDelivery?.start | date: 'EE dd.MM.' }} {{ availability.data.estimatedDelivery?.start | date: 'EE dd.MM.' }}
- -
{{ availability.data.estimatedDelivery?.stop | date: 'EE dd.MM.' }} {{ availability.data.estimatedDelivery?.stop | date: 'EE dd.MM.' }}
</ng-container> }
<ng-container *ngSwitchCase="'b2b-delivery'"> @case ('b2b-delivery') {
<shared-icon icon="isa-b2b-truck" [size]="24"></shared-icon> <shared-icon icon="isa-b2b-truck" [size]="24"></shared-icon>
{{ availability.data.estimatedShippingDate | date: 'dd. MMMM yyyy' }} {{ availability.data.estimatedShippingDate | date: 'dd. MMMM yyyy' }}
</ng-container> }
<ng-container *ngSwitchCase="'pickup'"> @case ('pickup') {
<shared-icon <shared-icon
class="cursor-pointer" class="cursor-pointer"
#uiOverlayTrigger="uiOverlayTrigger" #uiOverlayTrigger="uiOverlayTrigger"
@@ -68,39 +75,49 @@
> >
<b>{{ availability.data?.orderDeadline | orderDeadline }}</b> <b>{{ availability.data?.orderDeadline | orderDeadline }}</b>
</ui-tooltip> </ui-tooltip>
</ng-container> }
<ng-container *ngSwitchCase="'in-store'"> @case ('in-store') {
<shared-icon icon="isa-shopping-bag" [size]="18"></shared-icon> <shared-icon icon="isa-shopping-bag" [size]="18"></shared-icon>
{{ availability.data.inStock }}x {{ availability.data.inStock }}x
<ng-container *ngIf="isEVT; else noEVT">ab {{ isEVT | date: 'dd. MMMM yyyy' }}</ng-container> @if (isEVT) {
<ng-template #noEVT>ab sofort</ng-template> ab {{ isEVT | date: 'dd. MMMM yyyy' }}
</ng-container> } @else {
<ng-container *ngSwitchCase="'download'"> ab sofort
}
}
@case ('download') {
<shared-icon icon="isa-download" [size]="22"></shared-icon> <shared-icon icon="isa-download" [size]="22"></shared-icon>
Download Download
</ng-container> }
}
</div> </div>
</div> </div>
}
</div> </div>
</div> </div>
<div class="shared-purchase-options-list-item__price text-right ml-4 flex flex-col items-end"> <div class="shared-purchase-options-list-item__price text-right ml-4 flex flex-col items-end">
<div class="shared-purchase-options-list-item__price-value font-bold text-xl flex flex-row items-center"> <div class="shared-purchase-options-list-item__price-value font-bold text-xl flex flex-row items-center">
<div class="relative flex flex-row justify-end items-start"> <div class="relative flex flex-row justify-end items-start">
@if (canEditVat$ | async) {
<ui-select <ui-select
*ngIf="canEditVat$ | async"
class="w-[6.5rem] min-h-[3.4375rem] p-4 rounded-card border border-solid border-[#AEB7C1] mr-4" class="w-[6.5rem] min-h-[3.4375rem] p-4 rounded-card border border-solid border-[#AEB7C1] mr-4"
tabindex="-1" tabindex="-1"
[formControl]="manualVatFormControl" [formControl]="manualVatFormControl"
[defaultLabel]="'MwSt'" [defaultLabel]="'MwSt'"
> >
<ui-select-option *ngFor="let vat of vats$ | async" [label]="vat.name + '%'" [value]="vat.vatType"></ui-select-option> @for (vat of vats$ | async; track vat) {
<ui-select-option [label]="vat.name + '%'" [value]="vat.vatType"></ui-select-option>
}
</ui-select> </ui-select>
}
@if (canEditPrice$ | async) {
<shared-input-control <shared-input-control
[class.ml-6]="priceFormControl?.invalid && priceFormControl?.dirty" [class.ml-6]="priceFormControl?.invalid && priceFormControl?.dirty"
*ngIf="canEditPrice$ | async; else priceTmpl"
> >
<shared-input-control-indicator> <shared-input-control-indicator>
<shared-icon *ngIf="priceFormControl?.invalid && priceFormControl?.dirty" icon="mat-info"></shared-icon> @if (priceFormControl?.invalid && priceFormControl?.dirty) {
<shared-icon icon="mat-info"></shared-icon>
}
</shared-input-control-indicator> </shared-input-control-indicator>
<input <input
[uiOverlayTrigger]="giftCardTooltip" [uiOverlayTrigger]="giftCardTooltip"
@@ -121,6 +138,9 @@
<shared-input-control-error error="min">Preis ist ungültig</shared-input-control-error> <shared-input-control-error error="min">Preis ist ungültig</shared-input-control-error>
<shared-input-control-error error="max">Preis ist ungültig</shared-input-control-error> <shared-input-control-error error="max">Preis ist ungültig</shared-input-control-error>
</shared-input-control> </shared-input-control>
} @else {
{{ priceValue$ | async | currency: 'EUR' : 'code' }}
}
<ui-tooltip [warning]="true" xPosition="after" yPosition="below" [xOffset]="-55" [yOffset]="18" [closeable]="true" #giftCardTooltip> <ui-tooltip [warning]="true" xPosition="after" yPosition="below" [xOffset]="-55" [yOffset]="18" [closeable]="true" #giftCardTooltip>
Tragen Sie hier den Tragen Sie hier den
@@ -128,31 +148,35 @@
Gutscheinbetrag ein. Gutscheinbetrag ein.
</ui-tooltip> </ui-tooltip>
</div> </div>
<ng-template #priceTmpl>
{{ priceValue$ | async | currency: 'EUR' : 'code' }}
</ng-template>
</div> </div>
<ui-quantity-dropdown class="mt-2" [formControl]="quantityFormControl" [range]="maxSelectableQuantity$ | async"></ui-quantity-dropdown> <ui-quantity-dropdown class="mt-2" [formControl]="quantityFormControl" [range]="maxSelectableQuantity$ | async"></ui-quantity-dropdown>
<div class="pt-7"> <div class="pt-7">
@if ((canAddResult$ | async)?.canAdd) {
<input <input
*ngIf="(canAddResult$ | async)?.canAdd"
class="fancy-checkbox" class="fancy-checkbox"
[class.checked]="selectedFormControl?.value" [class.checked]="selectedFormControl?.value"
[formControl]="selectedFormControl" [formControl]="selectedFormControl"
type="checkbox" type="checkbox"
/> />
}
</div> </div>
<ng-container *ngIf="canAddResult$ | async; let canAddResult"> @if (canAddResult$ | async; as canAddResult) {
<span *ngIf="!canAddResult.canAdd" class="inline-block font-bold text-[#BE8100] mt-[14px] max-w-[19rem]"> @if (!canAddResult.canAdd) {
<span class="inline-block font-bold text-[#BE8100] mt-[14px] max-w-[19rem]">
{{ canAddResult.message }} {{ canAddResult.message }}
</span> </span>
</ng-container> }
}
<span *ngIf="showMaxAvailableQuantity$ | async" class="font-bold text-[#BE8100] mt-[14px]"> @if (showMaxAvailableQuantity$ | async) {
<span class="font-bold text-[#BE8100] mt-[14px]">
{{ (availability$ | async)?.inStock }} Exemplare sofort lieferbar {{ (availability$ | async)?.inStock }} Exemplare sofort lieferbar
</span> </span>
<span *ngIf="showNotAvailable$ | async" class="font-bold text-[#BE8100] mt-[14px]">Derzeit nicht bestellbar</span> }
@if (showNotAvailable$ | async) {
<span class="font-bold text-[#BE8100] mt-[14px]">Derzeit nicht bestellbar</span>
}
</div> </div>
</div> </div>
<div class="flex flex-row"> <div class="flex flex-row">

View File

@@ -1,28 +1,37 @@
<h3 class="text-center font-bold text-h3">Lieferung auswählen</h3> <h3 class="text-center font-bold text-h3">Lieferung auswählen</h3>
<p class="text-center font-2xl mt-4">Wie möchten Sie die Artikel erhalten?</p> <p class="text-center font-2xl mt-4">Wie möchten Sie die Artikel erhalten?</p>
<div class="rounded p-4 shadow-card mt-4 grid grid-flow-col gap-4 justify-center items-center relative"> <div class="rounded p-4 shadow-card mt-4 grid grid-flow-col gap-4 justify-center items-center relative">
<ng-container *ngIf="!(isDownloadOnly$ | async)"> @if (!(isDownloadOnly$ | async)) {
<ng-container *ngIf="!(isGiftCardOnly$ | async)"> @if (!(isGiftCardOnly$ | async)) {
<app-in-store-purchase-options-tile *ngIf="showOption('in-store')"></app-in-store-purchase-options-tile> @if (showOption('in-store')) {
<app-pickup-purchase-options-tile *ngIf="showOption('pickup')"></app-pickup-purchase-options-tile> <app-in-store-purchase-options-tile></app-in-store-purchase-options-tile>
</ng-container> }
<app-delivery-purchase-options-tile *ngIf="showOption('delivery')"></app-delivery-purchase-options-tile> @if (showOption('pickup')) {
</ng-container> <app-pickup-purchase-options-tile></app-pickup-purchase-options-tile>
}
}
@if (showOption('delivery')) {
<app-delivery-purchase-options-tile></app-delivery-purchase-options-tile>
}
}
<ng-container *ngIf="hasDownload$ | async"> @if (hasDownload$ | async) {
<app-download-purchase-options-tile *ngIf="showOption('download')"></app-download-purchase-options-tile> @if (showOption('download')) {
</ng-container> <app-download-purchase-options-tile></app-download-purchase-options-tile>
}
}
</div> </div>
<shared-purchase-options-list-header></shared-purchase-options-list-header> <shared-purchase-options-list-header></shared-purchase-options-list-header>
<div class="shared-purchase-options-modal__items -mx-4"> <div class="shared-purchase-options-modal__items -mx-4">
@for (item of items$ | async; track itemTrackBy($index, item)) {
<shared-purchase-options-list-item <shared-purchase-options-list-item
class="border-t border-gray-200 p-4 border-solid" class="border-t border-gray-200 p-4 border-solid"
*ngFor="let item of items$ | async; trackBy: itemTrackBy"
[item]="item" [item]="item"
></shared-purchase-options-list-item> ></shared-purchase-options-list-item>
}
</div> </div>
<div class="text-center -mx-4 border-t border-gray-200 p-4 border-solid"> <div class="text-center -mx-4 border-t border-gray-200 p-4 border-solid">
<ng-container *ngIf="type === 'add'"> @if (type === 'add') {
<button type="button" class="isa-cta-button" [disabled]="!(canContinue$ | async) || saving" (click)="save('continue-shopping')"> <button type="button" class="isa-cta-button" [disabled]="!(canContinue$ | async) || saving" (click)="save('continue-shopping')">
Weiter einkaufen Weiter einkaufen
</button> </button>
@@ -34,8 +43,8 @@
> >
Fortfahren Fortfahren
</button> </button>
</ng-container> }
<ng-container *ngIf="type === 'update'"> @if (type === 'update') {
<button <button
type="button" type="button"
class="ml-4 isa-cta-button isa-button-primary" class="ml-4 isa-cta-button isa-button-primary"
@@ -44,5 +53,5 @@
> >
Fortfahren Fortfahren
</button> </button>
</ng-container> }
</div> </div>

View File

@@ -1,4 +1,4 @@
import { CommonModule } from '@angular/common';
import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { PurchaseOptionsStore } from '../store'; import { PurchaseOptionsStore } from '../store';
import { BasePurchaseOptionDirective } from './base-purchase-option.directive'; import { BasePurchaseOptionDirective } from './base-purchase-option.directive';
@@ -9,7 +9,7 @@ import { IconComponent } from '@shared/components/icon';
templateUrl: 'download-purchase-options-tile.component.html', templateUrl: 'download-purchase-options-tile.component.html',
styleUrls: ['purchase-options-tile.component.css'], styleUrls: ['purchase-options-tile.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule, IconComponent], imports: [IconComponent],
}) })
export class DownloadPurchaseOptionTileComponent extends BasePurchaseOptionDirective { export class DownloadPurchaseOptionTileComponent extends BasePurchaseOptionDirective {
constructor( constructor(

View File

@@ -2,30 +2,31 @@
<hr /> <hr />
<ng-container *ngIf="orderItem$ | async; let orderItem"> @if (orderItem$ | async; as orderItem) {
<div class="header"> <div class="header">
@if (orderItem?.product?.ean | productImage; as productImage) {
<img <img
class="thumbnail" class="thumbnail"
loading="lazy" loading="lazy"
*ngIf="orderItem?.product?.ean | productImage; let productImage"
[src]="productImage" [src]="productImage"
[alt]="orderItem?.product?.name" [alt]="orderItem?.product?.name"
/> />
}
<div class="details"> <div class="details">
<div class="product-name">{{ orderItem.product?.name }}</div> <div class="product-name">{{ orderItem.product?.name }}</div>
<div *ngIf="orderItem.product?.format && orderItem.product.formatDetail" class="product-format"> @if (orderItem.product?.format && orderItem.product.formatDetail) {
<div class="product-format">
<img class="format-icon" [src]="'/assets/images/Icon_' + orderItem.product?.format + '.svg'" alt="format icon" /> <img class="format-icon" [src]="'/assets/images/Icon_' + orderItem.product?.format + '.svg'" alt="format icon" />
{{ orderItem.product.formatDetail }} {{ orderItem.product.formatDetail }}
</div> </div>
}
<div class="product-ean"> <div class="product-ean">
{{ orderItem.product?.ean }} {{ orderItem.product?.ean }}
</div> </div>
<div class="quantity">{{ orderItem.quantity }}x</div> <div class="quantity">{{ orderItem.quantity }}x</div>
</div> </div>
</div> </div>
@if (availabilities$ | async; as availabilities) {
<ng-container *ngIf="availabilities$ | async; let availabilities; else: showLoadingSpinner">
<div class="supplier-grid"> <div class="supplier-grid">
<span></span> <span></span>
<span class="number">Bestand</span> <span class="number">Bestand</span>
@@ -34,53 +35,56 @@
<span>vsl. Lieferdatum</span> <span>vsl. Lieferdatum</span>
<span class="number">Preis</span> <span class="number">Preis</span>
<span></span> <span></span>
@for (availability of availabilities; track availability; let i = $index) {
<ng-container *ngFor="let availability of availabilities; let i = index"> @if (availability) {
<ng-container *ngIf="availability">
<span class="first-cell">{{ availability.supplier | supplierName }}</span> <span class="first-cell">{{ availability.supplier | supplierName }}</span>
<span class="number">{{ availability.qty || 0 }}</span> <span class="number">{{ availability.qty || 0 }}</span>
<span>{{ availability.ssc }}</span> <span>{{ availability.ssc }}</span>
<span> <span>
<ui-checkbox *ngIf="availability.supplier !== 'F'" [(ngModel)]="availability.isPrebooked"></ui-checkbox> @if (availability.supplier !== 'F') {
<ui-checkbox [(ngModel)]="availability.isPrebooked"></ui-checkbox>
}
</span> </span>
<span>{{ availability.at | date: 'dd.MM.yy' }}</span> <span>{{ availability.at | date: 'dd.MM.yy' }}</span>
<span class="number">{{ availability.price?.value?.value | currency: 'EUR' : 'code' }}</span> <span class="number">{{ availability.price?.value?.value | currency: 'EUR' : 'code' }}</span>
<span> <span>
@if (availability.supplier !== 'F' || availability.qty > 0) {
<ui-select-bullet <ui-select-bullet
*ngIf="availability.supplier !== 'F' || availability.qty > 0"
[(ngModel)]="checkedSupplier" [(ngModel)]="checkedSupplier"
[value]="availability.supplier" [value]="availability.supplier"
(ngModelChange)="checked($event, availability)" (ngModelChange)="checked($event, availability)"
></ui-select-bullet> ></ui-select-bullet>
}
</span> </span>
</ng-container> }
</ng-container> }
</div> </div>
@if (storeAvailabilityError$ | async) {
<ng-container *ngIf="storeAvailabilityError$ | async">
<div class="availability-error">Lieferantenbestand nicht verfügbar</div> <div class="availability-error">Lieferantenbestand nicht verfügbar</div>
<hr /> <hr />
</ng-container> }
@if (takeAwayAvailabilityError$ | async) {
<ng-container *ngIf="takeAwayAvailabilityError$ | async">
<div class="availability-error">Filialbestand nicht verfügbar</div> <div class="availability-error">Filialbestand nicht verfügbar</div>
<hr /> <hr />
</ng-container> }
@if (showReasons$ | async) {
<div class="reason" *ngIf="showReasons$ | async"> <div class="reason">
<button class="reason-dropdown" [uiOverlayTrigger]="statusDropdown" #dropdown="uiOverlayTrigger"> <button class="reason-dropdown" [uiOverlayTrigger]="statusDropdown" #dropdown="uiOverlayTrigger">
{{ selectedReason || 'Warum wird nachbestellt?' }} {{ selectedReason || 'Warum wird nachbestellt?' }}
<ui-icon [rotate]="dropdown.opened ? '270deg' : '90deg'" icon="arrow_head"></ui-icon> <ui-icon [rotate]="dropdown.opened ? '270deg' : '90deg'" icon="arrow_head"></ui-icon>
</button> </button>
<ui-dropdown #statusDropdown yPosition="above" xPosition="after" [xOffset]="8"> <ui-dropdown #statusDropdown yPosition="above" xPosition="after" [xOffset]="8">
<button uiDropdownItem *ngFor="let reason of reorderReasons$ | async" (click)="selectedReason = reason.value; dropdown.close()"> @for (reason of reorderReasons$ | async; track reason) {
<button uiDropdownItem (click)="selectedReason = reason.value; dropdown.close()">
{{ reason.value }} {{ reason.value }}
</button> </button>
}
</ui-dropdown> </ui-dropdown>
@if (showReasonError$ | async) {
<span *ngIf="showReasonError$ | async" class="error">Bitte wählen Sie einen Grund für das nachbestellen</span> <span class="error">Bitte wählen Sie einen Grund für das nachbestellen</span>
}
</div> </div>
}
<div class="actions"> <div class="actions">
<button class="cta-not-available cta-action-secondary" [disabled]="ctaDisabled$ | async" (click)="notAvailable()"> <button class="cta-not-available cta-action-secondary" [disabled]="ctaDisabled$ | async" (click)="notAvailable()">
<ui-spinner [show]="ctaDisabled$ | async">Nicht lieferbar</ui-spinner> <ui-spinner [show]="ctaDisabled$ | async">Nicht lieferbar</ui-spinner>
@@ -89,9 +93,7 @@
<ui-spinner [show]="ctaDisabled$ | async">Bestellen</ui-spinner> <ui-spinner [show]="ctaDisabled$ | async">Bestellen</ui-spinner>
</button> </button>
</div> </div>
</ng-container> } @else {
<ng-template #showLoadingSpinner>
<ui-spinner class="load-spinner" [show]="true"></ui-spinner> <ui-spinner class="load-spinner" [show]="true"></ui-spinner>
</ng-template> }
</ng-container> }

View File

@@ -5,7 +5,7 @@
<div class="reviews"> <div class="reviews">
<hr /> <hr />
<ng-container *ngFor="let review of reviews"> @for (review of reviews; track review) {
<div class="review"> <div class="review">
<div class="row"> <div class="row">
<ui-stars [rating]="review.rating"></ui-stars> <ui-stars [rating]="review.rating"></ui-stars>
@@ -16,21 +16,29 @@
</div> </div>
<div class="row"> <div class="row">
<span> <span>
<span class="text" *ngIf="expandIds.indexOf(review.id) === -1">{{ review.text | substr: 150 }}</span> @if (expandIds.indexOf(review.id) === -1) {
<span class="text" *ngIf="expandIds.indexOf(review.id) > -1">{{ review.text }}</span> <span class="text">{{ review.text | substr: 150 }}</span>
}
@if (expandIds.indexOf(review.id) > -1) {
<span class="text">{{ review.text }}</span>
}
</span> </span>
</div> </div>
<div class="row right"> <div class="row right">
<button *ngIf="expandIds.indexOf(review.id) === -1" class="btn-expand" (click)="expand(review.id)"> @if (expandIds.indexOf(review.id) === -1) {
<button class="btn-expand" (click)="expand(review.id)">
Mehr Mehr
<ui-icon icon="arrow"></ui-icon> <ui-icon icon="arrow"></ui-icon>
</button> </button>
<button *ngIf="expandIds.indexOf(review.id) > -1" class="btn-collapse" (click)="expand(review.id)"> }
@if (expandIds.indexOf(review.id) > -1) {
<button class="btn-collapse" (click)="expand(review.id)">
<ui-icon icon="arrow" rotate="180deg"></ui-icon> <ui-icon icon="arrow" rotate="180deg"></ui-icon>
Weniger Weniger
</button> </button>
}
</div> </div>
</div> </div>
<hr /> <hr />
</ng-container> }
</div> </div>

View File

@@ -10,13 +10,14 @@
<div class="page-price-update-item__item-card p-5 bg-white"> <div class="page-price-update-item__item-card p-5 bg-white">
<div class="page-price-update-item__item-thumbnail text-center mr-4 w-[47px] h-[73px]"> <div class="page-price-update-item__item-thumbnail text-center mr-4 w-[47px] h-[73px]">
@if (item?.product?.ean | productImage; as productImage) {
<img <img
class="page-price-update-item__item-image w-[47px] max-h-[73px]" class="page-price-update-item__item-image w-[47px] max-h-[73px]"
loading="lazy" loading="lazy"
*ngIf="item?.product?.ean | productImage; let productImage"
[src]="productImage" [src]="productImage"
[alt]="item?.product?.name" [alt]="item?.product?.name"
/> />
}
</div> </div>
<div class="page-price-update-item__item-details"> <div class="page-price-update-item__item-details">
@@ -36,23 +37,28 @@
</div> </div>
<div class="page-price-update-item__item-format"> <div class="page-price-update-item__item-format">
<div *ngIf="item?.product?.format && item?.product?.formatDetail" class="font-bold flex flex-row"> @if (item?.product?.format && item?.product?.formatDetail) {
<div class="font-bold flex flex-row">
@if (item?.product?.format !== '--') {
<img <img
class="mr-3" class="mr-3"
*ngIf="item?.product?.format !== '--'"
loading="lazy" loading="lazy"
src="assets/images/Icon_{{ item?.product?.format }}.svg" src="assets/images/Icon_{{ item?.product?.format }}.svg"
[alt]="item?.product?.formatDetail" [alt]="item?.product?.formatDetail"
/> />
}
{{ environment.isTablet() ? (item?.product?.formatDetail | substr: 25) : item?.product?.formatDetail }} {{ environment.isTablet() ? (item?.product?.formatDetail | substr: 25) : item?.product?.formatDetail }}
</div> </div>
}
</div> </div>
<div class="page-price-update-item__item-misc"> <div class="page-price-update-item__item-misc">
{{ environment.isTablet() ? (item?.product?.manufacturer | substr: 18) : item?.product?.manufacturer }} | {{ item?.product?.ean }} {{ environment.isTablet() ? (item?.product?.manufacturer | substr: 18) : item?.product?.manufacturer }} | {{ item?.product?.ean }}
<br /> <br />
{{ item?.product?.volume }} {{ item?.product?.volume }}
<span *ngIf="item?.product?.volume && item?.product?.publicationDate">|</span> @if (item?.product?.volume && item?.product?.publicationDate) {
<span>|</span>
}
{{ publicationDate }} {{ publicationDate }}
</div> </div>
</div> </div>
@@ -69,18 +75,21 @@
</div> </div>
<div class="page-price-update-item__item-select-bullet"> <div class="page-price-update-item__item-select-bullet">
<input *ngIf="isSelectable" [ngModel]="selected" (ngModelChange)="setSelected()" class="isa-select-bullet" type="checkbox" /> @if (isSelectable) {
<input [ngModel]="selected" (ngModelChange)="setSelected()" class="isa-select-bullet" type="checkbox" />
}
</div> </div>
<div class="page-price-update-item__item-stock flex flex-row font-bold"> <div class="page-price-update-item__item-stock flex flex-row font-bold">
<ui-icon class="mt-px-2 mr-1" icon="home" size="1em"></ui-icon> <ui-icon class="mt-px-2 mr-1" icon="home" size="1em"></ui-icon>
@if (inStock$ | async; as stock) {
<span <span
*ngIf="inStock$ | async; let stock"
[class.skeleton]="stock?.inStock === undefined" [class.skeleton]="stock?.inStock === undefined"
class="min-w-[1rem] text-right inline-block" class="min-w-[1rem] text-right inline-block"
> >
{{ stock?.inStock }} {{ stock?.inStock }}
</span> </span>
}
x x
</div> </div>
</div> </div>

View File

@@ -8,16 +8,22 @@
Drucken Drucken
</button> </button>
<div class="flex flex-row items-center justify-end"> <div class="flex flex-row items-center justify-end">
<div *ngIf="getSelectableItems().length > 0" class="text-[#0556B4] font-bold text-p3 mr-5"> @if (getSelectableItems().length > 0) {
<ng-container *ngIf="selectedItemUids$ | async; let selectedItems"> <div class="text-[#0556B4] font-bold text-p3 mr-5">
<button class="page-price-update-list__cta-unselect-all" *ngIf="selectedItems?.length > 0" type="button" (click)="unselectAll()"> @if (selectedItemUids$ | async; as selectedItems) {
@if (selectedItems?.length > 0) {
<button class="page-price-update-list__cta-unselect-all" type="button" (click)="unselectAll()">
Alle entfernen ({{ selectedItems?.length }}) Alle entfernen ({{ selectedItems?.length }})
</button> </button>
<button class="page-price-update-list__cta-select-all" type="button" (click)="selectAll()" *ngIf="selectedItems?.length === 0"> }
@if (selectedItems?.length === 0) {
<button class="page-price-update-list__cta-select-all" type="button" (click)="selectAll()">
Alle auswählen ({{ getSelectableItems().length }}) Alle auswählen ({{ getSelectableItems().length }})
</button> </button>
</ng-container> }
}
</div> </div>
}
<div class="page-price-update-list__items-count inline-flex flex-row items-center pr-5 text-p3"> <div class="page-price-update-list__items-count inline-flex flex-row items-center pr-5 text-p3">
{{ items?.length ?? 0 }} {{ items?.length ?? 0 }}
Titel Titel
@@ -38,7 +44,9 @@
} }
} }
<page-price-update-item-loader *ngIf="fetching"></page-price-update-item-loader> @if (fetching) {
<page-price-update-item-loader></page-price-update-item-loader>
}
<div class="h-28"></div> <div class="h-28"></div>
</div> </div>
@@ -56,9 +64,9 @@
</cdk-virtual-scroll-viewport> --> </cdk-virtual-scroll-viewport> -->
<div class="page-price-update-list__action-wrapper"> <div class="page-price-update-list__action-wrapper">
@if (!fetching) {
<button <button
[@cta] [@cta]
*ngIf="!fetching"
[disabled]="(selectedItemUids$ | async).length === 0 || (loading$ | async)" [disabled]="(selectedItemUids$ | async).length === 0 || (loading$ | async)"
class="page-price-update-list__complete-items isa-button isa-cta-button isa-button-primary px-11" class="page-price-update-list__complete-items isa-button isa-cta-button isa-button-primary px-11"
type="button" type="button"
@@ -66,4 +74,5 @@
> >
<ui-spinner [show]="loading$ | async">Erledigt</ui-spinner> <ui-spinner [show]="loading$ | async">Erledigt</ui-spinner>
</button> </button>
}
</div> </div>

View File

@@ -11,11 +11,14 @@
</button> </button>
</div> </div>
@if (showList$ | async) {
<page-price-update-list <page-price-update-list
*ngIf="showList$ | async; else noResults"
[items]="store.items$ | async" [items]="store.items$ | async"
[fetching]="store.fetching$ | async" [fetching]="store.fetching$ | async"
></page-price-update-list> ></page-price-update-list>
} @else {
<div class="bg-white text-h3 text-center pt-10 font-bold rounded-b h-[calc(100vh_-_370px)]">Keine Preisänderungen vorhanden.</div>
}
<shell-filter-overlay #filterOverlay class="relative"> <shell-filter-overlay #filterOverlay class="relative">
<div class="relative"> <div class="relative">
@@ -26,8 +29,8 @@
<h3 class="text-3xl text-center font-bold mt-8">Filter</h3> <h3 class="text-3xl text-center font-bold mt-8">Filter</h3>
@if (filterOverlay.isOpen) {
<ui-filter <ui-filter
*ngIf="filterOverlay.isOpen"
#filter #filter
class="mx-4" class="mx-4"
[filter]="store.pendingFilter$ | async" [filter]="store.pendingFilter$ | async"
@@ -35,6 +38,7 @@
[loading]="store.fetching$ | async" [loading]="store.fetching$ | async"
[hint]="hint$ | async" [hint]="hint$ | async"
></ui-filter> ></ui-filter>
}
<div class="absolute bottom-8 left-0 right-0 grid grid-flow-col gap-4 justify-center"> <div class="absolute bottom-8 left-0 right-0 grid grid-flow-col gap-4 justify-center">
<button <button
@@ -55,6 +59,3 @@
</div> </div>
</shell-filter-overlay> </shell-filter-overlay>
<ng-template #noResults>
<div class="bg-white text-h3 text-center pt-10 font-bold rounded-b h-[calc(100vh_-_370px)]">Keine Preisänderungen vorhanden.</div>
</ng-template>

View File

@@ -1,14 +1,16 @@
<ng-container *ngFor="let line of lines"> @for (line of lines; track line) {
<ng-container [ngSwitch]="line | lineType"> @switch (line | lineType) {
<ng-container *ngSwitchCase="'reihe'"> @case ('reihe') {
<page-article-details-text-link *ngFor="let reihe of getReihen(line)" [route]="reihe | reiheRoute"> @for (reihe of getReihen(line); track reihe) {
<page-article-details-text-link [route]="reihe | reiheRoute">
{{ reihe }} {{ reihe }}
</page-article-details-text-link> </page-article-details-text-link>
}
<br /> <br />
</ng-container> }
<ng-container *ngSwitchDefault> @default {
{{ line }} {{ line }}
<br /> <br />
</ng-container> }
</ng-container> }
</ng-container> }

View File

@@ -1,7 +1,7 @@
import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
import { TextDTO } from '@generated/swagger/cat-search-api'; import { TextDTO } from '@generated/swagger/cat-search-api';
import { ArticleDetailsTextLinkComponent } from './article-details-text-link.component'; import { ArticleDetailsTextLinkComponent } from './article-details-text-link.component';
import { NgFor, NgSwitch, NgSwitchCase, NgSwitchDefault } from '@angular/common';
import { LineTypePipe } from './line-type.pipe'; import { LineTypePipe } from './line-type.pipe';
import { ReiheRoutePipe } from './reihe-route.pipe'; import { ReiheRoutePipe } from './reihe-route.pipe';
@@ -13,12 +13,8 @@ import { ReiheRoutePipe } from './reihe-route.pipe';
host: { class: 'page-article-details-text' }, host: { class: 'page-article-details-text' },
imports: [ imports: [
ArticleDetailsTextLinkComponent, ArticleDetailsTextLinkComponent,
NgFor,
NgSwitch,
NgSwitchCase,
NgSwitchDefault,
LineTypePipe, LineTypePipe,
ReiheRoutePipe, ReiheRoutePipe
], ],
}) })
export class ArticleDetailsTextComponent { export class ArticleDetailsTextComponent {

View File

@@ -1,19 +1,24 @@
<div class="page-article-details__wrapper"> <div class="page-article-details__wrapper">
<div #detailsContainer class="page-article-details__container px-5" *ngIf="store.item$ | async; let item"> @if (store.item$ | async; as item) {
<div #detailsContainer class="page-article-details__container px-5">
<div class="page-article-details__product-details mb-3"> <div class="page-article-details__product-details mb-3">
<div class="page-article-details__product-bookmark flex fixed justify-self-end"> <div class="page-article-details__product-bookmark flex fixed justify-self-end">
<div *ngIf="showArchivBadge$ | async" class="archiv-badge"> @if (showArchivBadge$ | async) {
<div class="archiv-badge">
<button [uiOverlayTrigger]="archivTooltip" class="p-0 m-0 outline-none border-none bg-transparent relative -top-[0.3125rem]"> <button [uiOverlayTrigger]="archivTooltip" class="p-0 m-0 outline-none border-none bg-transparent relative -top-[0.3125rem]">
<img src="/assets/images/bookmark_benachrichtigung_archiv.svg" alt="Archiv Badge" /> <img src="/assets/images/bookmark_benachrichtigung_archiv.svg" alt="Archiv Badge" />
<ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #archivTooltip [closeable]="true"> <ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #archivTooltip [closeable]="true">
<ng-container *ngIf="isAvailable$ | async; else notAvailable"> @if (isAvailable$ | async) {
Archivtitel. Wird nicht mehr gedruckt. Artikel ist bestellbar, weil lieferbar. Archivtitel. Wird nicht mehr gedruckt. Artikel ist bestellbar, weil lieferbar.
</ng-container> } @else {
<ng-template #notAvailable>Archivtitel. Wird nicht mehr gedruckt. Nicht bestellbar.</ng-template> Archivtitel. Wird nicht mehr gedruckt. Nicht bestellbar.
}
</ui-tooltip> </ui-tooltip>
</button> </button>
</div> </div>
<div *ngIf="showSubscriptionBadge$ | async"> }
@if (showSubscriptionBadge$ | async) {
<div>
<button <button
[uiOverlayTrigger]="subscribtionTooltip" [uiOverlayTrigger]="subscribtionTooltip"
class="p-0 m-0 outline-none border-none bg-transparent relative -top-[0.3125rem]" class="p-0 m-0 outline-none border-none bg-transparent relative -top-[0.3125rem]"
@@ -28,7 +33,9 @@
bestellt werden. bestellt werden.
</ui-tooltip> </ui-tooltip>
</div> </div>
<div *ngIf="showPromotionBadge$ | async" class="promotion-badge"> }
@if (showPromotionBadge$ | async) {
<div class="promotion-badge">
<button [uiOverlayTrigger]="promotionTooltip" class="p-0 m-0 outline-none border-none bg-transparent relative -top-[0.3125rem]"> <button [uiOverlayTrigger]="promotionTooltip" class="p-0 m-0 outline-none border-none bg-transparent relative -top-[0.3125rem]">
<shared-icon-badge icon="gift" alt="Prämienkatalog Badge"></shared-icon-badge> <shared-icon-badge icon="gift" alt="Prämienkatalog Badge"></shared-icon-badge>
<ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #promotionTooltip [closeable]="true"> <ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #promotionTooltip [closeable]="true">
@@ -36,8 +43,8 @@
</ui-tooltip> </ui-tooltip>
</button> </button>
</div> </div>
}
</div> </div>
<div class="page-article-details__product-image-recessions flex flex-col items-center"> <div class="page-article-details__product-image-recessions flex flex-col items-center">
<div class="page-article-details__product-image"> <div class="page-article-details__product-image">
<button class="border-none outline-none bg-transparent relative" (click)="showImages()"> <button class="border-none outline-none bg-transparent relative" (click)="showImages()">
@@ -47,198 +54,201 @@
[src]="item.imageId | productImage: 195 : 315 : true" [src]="item.imageId | productImage: 195 : 315 : true"
alt="product image" alt="product image"
/> />
@if (imageLoaded$ | async) {
<ui-icon <ui-icon
class="absolute text-[#A7B9CB] inline-block bottom-[0.875rem] right-[1.125rem]" class="absolute text-[#A7B9CB] inline-block bottom-[0.875rem] right-[1.125rem]"
*ngIf="imageLoaded$ | async"
icon="search_add" icon="search_add"
size="25px" size="25px"
></ui-icon> ></ui-icon>
}
</button> </button>
</div> </div>
@if (item.reviews?.length > 0) {
<button <button
(click)="showReviews()" (click)="showReviews()"
class="page-article-details__product-recessions flex flex-col mt-2 items-center bg-transparent border-none outline-none" class="page-article-details__product-recessions flex flex-col mt-2 items-center bg-transparent border-none outline-none"
*ngIf="item.reviews?.length > 0"
> >
<ui-stars [rating]="store.reviewRating$ | async"></ui-stars> <ui-stars [rating]="store.reviewRating$ | async"></ui-stars>
<div class="text-p2 text-[#0556B4] font-bold">{{ item.reviews.length }} Rezensionen</div> <div class="text-p2 text-[#0556B4] font-bold">{{ item.reviews.length }} Rezensionen</div>
</button> </button>
}
</div> </div>
<div class="page-article-details__product-contributors"> <div class="page-article-details__product-contributors">
@for (contributor of contributors$ | async; track contributor; let last = $last) {
<a <a
*ngFor="let contributor of contributors$ | async; let last = last"
class="text-[#0556B4] font-semibold no-underline text-p2" class="text-[#0556B4] font-semibold no-underline text-p2"
[routerLink]="resultsPath" [routerLink]="resultsPath"
[queryParams]="{ main_qs: contributor, main_author: 'author' }" [queryParams]="{ main_qs: contributor, main_author: 'author' }"
> >
{{ contributor }}{{ last ? '' : ';' }} {{ contributor }}{{ last ? '' : ';' }}
</a> </a>
}
</div> </div>
<div class="page-article-details__product-print justify-self-end" [class.mt-4]="isBadgeVisible$ | async"> <div class="page-article-details__product-print justify-self-end" [class.mt-4]="isBadgeVisible$ | async">
<button class="bg-transparent text-brand font-bold text-lg outline-none border-none p-0" (click)="print()">Drucken</button> <button class="bg-transparent text-brand font-bold text-lg outline-none border-none p-0" (click)="print()">Drucken</button>
</div> </div>
<div class="page-article-details__product-title text-h3 font-bold mb-6"> <div class="page-article-details__product-title text-h3 font-bold mb-6">
{{ item.product?.name }} {{ item.product?.name }}
</div> </div>
<div class="page-article-details__product-misc flex flex-col mb-4"> <div class="page-article-details__product-misc flex flex-col mb-4">
@if (item?.product?.format && item?.product?.formatDetail) {
<div <div
class="page-article-details__product-format flex items-center font-bold text-p3" class="page-article-details__product-format flex items-center font-bold text-p3"
*ngIf="item?.product?.format && item?.product?.formatDetail"
> >
@if (item?.product?.format !== '--') {
<img <img
*ngIf="item?.product?.format !== '--'"
class="flex mr-2 h-[1.125rem]" class="flex mr-2 h-[1.125rem]"
[src]="'/assets/images/Icon_' + item.product?.format + '.svg'" [src]="'/assets/images/Icon_' + item.product?.format + '.svg'"
[alt]="item.product?.formatDetail" [alt]="item.product?.formatDetail"
/> />
}
{{ item.product?.formatDetail }} {{ item.product?.formatDetail }}
</div> </div>
}
<div class="page-article-details__product-volume" *ngIf="item?.product?.volume">Band/Reihe {{ item?.product?.volume }}</div> @if (item?.product?.volume) {
<div class="page-article-details__product-volume">Band/Reihe {{ item?.product?.volume }}</div>
}
<div class="page-article-details__product-publication">{{ publicationDate$ | async }}</div> <div class="page-article-details__product-publication">{{ publicationDate$ | async }}</div>
</div> </div>
<div class="page-article-details__product-price-info flex flex-col mb-4 flex-nowrap self-end"> <div class="page-article-details__product-price-info flex flex-col mb-4 flex-nowrap self-end">
<div class="page-article-details__product-price font-bold text-xl self-end" *ngIf="price$ | async; let price"> @if (price$ | async; as price) {
<div class="page-article-details__product-price font-bold text-xl self-end">
{{ price?.value?.value | currency: price?.value?.currency : 'code' }} {{ price?.value?.value | currency: price?.value?.currency : 'code' }}
</div> </div>
<div *ngIf="price$ | async; let price" class="page-article-details__product-price-bound self-end"> }
@if (price$ | async; as price) {
<div class="page-article-details__product-price-bound self-end">
{{ price?.vat?.vatType | vat: (priceMaintained$ | async) }} {{ price?.vat?.vatType | vat: (priceMaintained$ | async) }}
</div> </div>
<div class="page-article-details__product-points self-end" *ngIf="store.promotionPoints$ | async; let promotionPoints"> }
@if (store.promotionPoints$ | async; as promotionPoints) {
<div class="page-article-details__product-points self-end">
{{ promotionPoints }} Lesepunkte {{ promotionPoints }} Lesepunkte
</div> </div>
}
</div> </div>
<div class="page-article-details__product-origin-infos flex flex-col mb-4"> <div class="page-article-details__product-origin-infos flex flex-col mb-4">
<div class="page-article-details__product-manufacturer" data-name="product-manufacturer">{{ item.product?.manufacturer }}</div> <div class="page-article-details__product-manufacturer" data-name="product-manufacturer">{{ item.product?.manufacturer }}</div>
@if (item?.product?.locale) {
<div class="page-article-details__product-language" *ngIf="item?.product?.locale" data-name="product-language"> <div class="page-article-details__product-language" data-name="product-language">
{{ item?.product?.locale }} {{ item?.product?.locale }}
</div> </div>
}
</div> </div>
<div class="page-article-details__product-stock flex justify-end items-center"> <div class="page-article-details__product-stock flex justify-end items-center">
<div class="h-5 w-16 bg-[#e6eff9] animate-[load_0.75s_linear_infinite]" *ngIf="store.fetchingTakeAwayAvailability$ | async"></div> @if (store.fetchingTakeAwayAvailability$ | async) {
<div class="h-5 w-16 bg-[#e6eff9] animate-[load_0.75s_linear_infinite]"></div>
}
@if (!(store.fetchingTakeAwayAvailability$ | async)) {
<button <button
class="flex flex-row py-4 pl-4" class="flex flex-row py-4 pl-4"
type="button" type="button"
[uiOverlayTrigger]="tooltip" [uiOverlayTrigger]="tooltip"
[overlayTriggerDisabled]="!(stockTooltipText$ | async)" [overlayTriggerDisabled]="!(stockTooltipText$ | async)"
(click)="showTooltip()" (click)="showTooltip()"
*ngIf="!(store.fetchingTakeAwayAvailability$ | async)"
> >
<ng-container *ngIf="store.takeAwayAvailability$ | async; let takeAwayAvailability"> @if (store.takeAwayAvailability$ | async; as takeAwayAvailability) {
<ui-icon class="mr-2 mb-1" icon="home" size="15px"></ui-icon> <ui-icon class="mr-2 mb-1" icon="home" size="15px"></ui-icon>
<span class="font-bold text-p3">{{ takeAwayAvailability.inStock || 0 }}x</span> <span class="font-bold text-p3">{{ takeAwayAvailability.inStock || 0 }}x</span>
</ng-container> }
</button> </button>
}
<ui-tooltip #tooltip yPosition="above" xPosition="after" [yOffset]="-12" [closeable]="true"> <ui-tooltip #tooltip yPosition="above" xPosition="after" [yOffset]="-12" [closeable]="true">
{{ stockTooltipText$ | async }} {{ stockTooltipText$ | async }}
</ui-tooltip> </ui-tooltip>
</div> </div>
<div class="page-article-details__product-ean-specs flex flex-col"> <div class="page-article-details__product-ean-specs flex flex-col">
<div class="page-article-details__product-ean" data-name="product-ean">{{ item.product?.ean }}</div> <div class="page-article-details__product-ean" data-name="product-ean">{{ item.product?.ean }}</div>
<div class="page-article-details__product-specs"> <div class="page-article-details__product-specs">
<ng-container *ngIf="item?.specs?.length > 0"> @if (item?.specs?.length > 0) {
{{ (item?.specs)[0]?.value }} {{ (item?.specs)[0]?.value }}
</ng-container> }
</div> </div>
</div> </div>
<div class="page-article-details__product-availabilities flex flex-row items-center justify-end mt-4"> <div class="page-article-details__product-availabilities flex flex-row items-center justify-end mt-4">
@if (store.fetchingTakeAwayAvailability$ | async) {
<div <div
class="h-5 w-6 bg-[#e6eff9] animate-[load_0.75s_linear_infinite]" class="h-5 w-6 bg-[#e6eff9] animate-[load_0.75s_linear_infinite]"
*ngIf="store.fetchingTakeAwayAvailability$ | async; else showAvailabilityTakeAwayIcon"
></div> ></div>
<ng-template #showAvailabilityTakeAwayIcon> } @else {
@if (store.isTakeAwayAvailabilityAvailable$ | async) {
<div <div
*ngIf="store.isTakeAwayAvailabilityAvailable$ | async"
class="w-[2.25rem] h-[2.25rem] bg-[#D8DFE5] rounded-[5px_5px_0px_5px] flex items-center justify-center" class="w-[2.25rem] h-[2.25rem] bg-[#D8DFE5] rounded-[5px_5px_0px_5px] flex items-center justify-center"
> >
<ui-icon class="mx-1" icon="shopping_bag" size="18px"></ui-icon> <ui-icon class="mx-1" icon="shopping_bag" size="18px"></ui-icon>
</div> </div>
</ng-template> }
}
@if (store.fetchingPickUpAvailability$ | async) {
<div <div
class="h-5 w-6 bg-[#e6eff9] animate-[load_0.75s_linear_infinite]" class="h-5 w-6 bg-[#e6eff9] animate-[load_0.75s_linear_infinite]"
*ngIf="store.fetchingPickUpAvailability$ | async; else showAvailabilityPickUpIcon"
></div> ></div>
<ng-template #showAvailabilityPickUpIcon> } @else {
@if (store.isPickUpAvailabilityAvailable$ | async) {
<div <div
#uiOverlayTrigger="uiOverlayTrigger" #uiOverlayTrigger="uiOverlayTrigger"
[uiOverlayTrigger]="orderDeadlineTooltip" [uiOverlayTrigger]="orderDeadlineTooltip"
*ngIf="store.isPickUpAvailabilityAvailable$ | async"
class="page-article-details__product-pick-up-availability w-[2.25rem] h-[2.25rem] cursor-pointer bg-[#D8DFE5] rounded-[5px_5px_0px_5px] flex items-center justify-center ml-3" class="page-article-details__product-pick-up-availability w-[2.25rem] h-[2.25rem] cursor-pointer bg-[#D8DFE5] rounded-[5px_5px_0px_5px] flex items-center justify-center ml-3"
[class.tooltip-active]="uiOverlayTrigger.opened" [class.tooltip-active]="uiOverlayTrigger.opened"
> >
<shared-icon icon="isa-box-out" [size]="24"></shared-icon> <shared-icon icon="isa-box-out" [size]="24"></shared-icon>
</div> </div>
}
<ui-tooltip [warning]="true" yPosition="above" xPosition="after" [yOffset]="-12" #orderDeadlineTooltip [closeable]="true"> <ui-tooltip [warning]="true" yPosition="above" xPosition="after" [yOffset]="-12" #orderDeadlineTooltip [closeable]="true">
<b>{{ (store.pickUpAvailability$ | async)?.orderDeadline | orderDeadline }}</b> <b>{{ (store.pickUpAvailability$ | async)?.orderDeadline | orderDeadline }}</b>
</ui-tooltip> </ui-tooltip>
</ng-template> }
@if (store.fetchingDeliveryAvailability$ | async) {
<div <div
class="h-5 w-6 bg-[#e6eff9] animate-[load_0.75s_linear_infinite]" class="h-5 w-6 bg-[#e6eff9] animate-[load_0.75s_linear_infinite]"
*ngIf="store.fetchingDeliveryAvailability$ | async; else showAvailabilityDeliveryIcon"
></div> ></div>
<ng-template #showAvailabilityDeliveryIcon> } @else {
@if (showDeliveryTruck$ | async) {
<div <div
*ngIf="showDeliveryTruck$ | async"
class="w-[2.25rem] h-[2.25rem] bg-[#D8DFE5] rounded-[5px_5px_0px_5px] flex items-center justify-center ml-3" class="w-[2.25rem] h-[2.25rem] bg-[#D8DFE5] rounded-[5px_5px_0px_5px] flex items-center justify-center ml-3"
> >
<ui-icon class="-mb-[0.3125rem] -mt-[0.3125rem] mx-1" icon="truck" size="30px"></ui-icon> <ui-icon class="-mb-[0.3125rem] -mt-[0.3125rem] mx-1" icon="truck" size="30px"></ui-icon>
</div> </div>
</ng-template> }
}
@if (store.fetchingDeliveryB2BAvailability$ | async) {
<div <div
class="h-5 w-6 bg-[#e6eff9] animate-[load_0.75s_linear_infinite]" class="h-5 w-6 bg-[#e6eff9] animate-[load_0.75s_linear_infinite]"
*ngIf="store.fetchingDeliveryB2BAvailability$ | async; else showAvailabilityDeliveryB2BIcon"
></div> ></div>
<ng-template #showAvailabilityDeliveryB2BIcon> } @else {
@if (showDeliveryB2BTruck$ | async) {
<div <div
*ngIf="showDeliveryB2BTruck$ | async"
class="w-[2.25rem] h-[2.25rem] bg-[#D8DFE5] rounded-[5px_5px_0px_5px] flex items-center justify-center ml-3" class="w-[2.25rem] h-[2.25rem] bg-[#D8DFE5] rounded-[5px_5px_0px_5px] flex items-center justify-center ml-3"
> >
<ui-icon class="-mb-[0.625rem] -mt-[0.625rem] mx-1" icon="truck_b2b" size="30px"></ui-icon> <ui-icon class="-mb-[0.625rem] -mt-[0.625rem] mx-1" icon="truck_b2b" size="30px"></ui-icon>
</div> </div>
</ng-template> }
}
<span *ngIf="store.isDownload$ | async" class="flex flex-row items-center"> @if (store.isDownload$ | async) {
<span class="flex flex-row items-center">
<div class="w-[2.25rem] h-[2.25rem] bg-[#D8DFE5] rounded-[5px_5px_0px_5px] flex items-center justify-center ml-3"> <div class="w-[2.25rem] h-[2.25rem] bg-[#D8DFE5] rounded-[5px_5px_0px_5px] flex items-center justify-center ml-3">
<ui-icon class="mx-1" icon="download" size="18px"></ui-icon> <ui-icon class="mx-1" icon="download" size="18px"></ui-icon>
</div> </div>
</span> </span>
}
</div> </div>
<div class="page-article-details__shelf-ssc"> <div class="page-article-details__shelf-ssc">
<div class="page-article-details__ssc flex justify-end my-2 font-bold text-lg"> <div class="page-article-details__ssc flex justify-end my-2 font-bold text-lg">
<div class="w-52 h-5 bg-[#e6eff9] animate-[load_0.75s_linear_infinite]" *ngIf="fetchingAvailabilities$ | async"></div> @if (fetchingAvailabilities$ | async) {
<ng-container *ngIf="!(fetchingAvailabilities$ | async)"> <div class="w-52 h-5 bg-[#e6eff9] animate-[load_0.75s_linear_infinite]"></div>
<div class="text-right" *ngIf="store.sscText$ | async; let sscText"> }
@if (!(fetchingAvailabilities$ | async)) {
@if (store.sscText$ | async; as sscText) {
<div class="text-right">
{{ sscText }} {{ sscText }}
</div> </div>
</ng-container> }
}
</div> </div>
@if (store.isDownload$ | async) {
<div class="page-article-details__shelfinfo text-right" *ngIf="store.isDownload$ | async"> <div class="page-article-details__shelfinfo text-right">
<ng-container @if (
*ngIf=" item?.stockInfos && item?.shelfInfos && (item?.stockInfos)[0]?.compartment && (item?.shelfInfos)[0]?.label) {
item?.stockInfos && item?.shelfInfos && (item?.stockInfos)[0]?.compartment && (item?.shelfInfos)[0]?.label;
else stockInfos
"
>
<span data-name="compartment"> <span data-name="compartment">
{{ (item?.stockInfos)[0]?.compartment }} {{ (item?.stockInfos)[0]?.compartment }}
</span> </span>
@@ -247,108 +257,110 @@
<span data-name="shelf-info-label"> <span data-name="shelf-info-label">
{{ (item?.shelfInfos)[0]?.label }} {{ (item?.shelfInfos)[0]?.label }}
</span> </span>
</ng-container> } @else {
<ng-template #stockInfos> @if (item?.stockInfos && (item?.stockInfos)[0]?.compartment) {
<ng-container *ngIf="item?.stockInfos && (item?.stockInfos)[0]?.compartment; else shelfInfos">
{{ (item?.stockInfos)[0]?.compartment }} {{ (item?.stockInfos)[0]?.compartment }}
</ng-container> } @else {
</ng-template> @if (item?.shelfInfos && (item?.shelfInfos)[0]?.label) {
<ng-template #shelfInfos>
<ng-container *ngIf="item?.shelfInfos && (item?.shelfInfos)[0]?.label">
<span data-name="shelf-info-label">{{ (item?.shelfInfos)[0]?.label }}</span> <span data-name="shelf-info-label">{{ (item?.shelfInfos)[0]?.label }}</span>
</ng-container> }
</ng-template> }
}
</div> </div>
<div class="page-article-details__shelfinfo text-right" *ngIf="!(store.isDownload$ | async)"> }
<ng-container @if (!(store.isDownload$ | async)) {
*ngIf=" <div class="page-article-details__shelfinfo text-right">
item?.stockInfos && item?.shelfInfos && (item?.stockInfos)[0]?.compartment && (item?.shelfInfos)[0]?.label; @if (
else stockInfos2 item?.stockInfos && item?.shelfInfos && (item?.stockInfos)[0]?.compartment && (item?.shelfInfos)[0]?.label) {
"
>
<span data-name="compartment">{{ (item?.stockInfos)[0]?.compartment }}</span> <span data-name="compartment">{{ (item?.stockInfos)[0]?.compartment }}</span>
/ /
<br /> <br />
<span data-name="shelf-info-label">{{ (item?.shelfInfos)[0]?.label }}</span> <span data-name="shelf-info-label">{{ (item?.shelfInfos)[0]?.label }}</span>
</ng-container> } @else {
<ng-template #stockInfos2> @if (item?.stockInfos && (item?.stockInfos)[0]?.compartment) {
<ng-container *ngIf="item?.stockInfos && (item?.stockInfos)[0]?.compartment; else shelfInfos2">
{{ (item?.stockInfos)[0]?.compartment }} {{ (item?.stockInfos)[0]?.compartment }}
</ng-container> } @else {
</ng-template> @if (item?.shelfInfos && (item?.shelfInfos)[0]?.label) {
<ng-template #shelfInfos2>
<ng-container *ngIf="item?.shelfInfos && (item?.shelfInfos)[0]?.label">
{{ (item?.shelfInfos)[0]?.label }} {{ (item?.shelfInfos)[0]?.label }}
</ng-container> }
</ng-template> }
}
</div>
}
</div> </div>
</div> </div>
</div> @if (item.family?.length > 0) {
<div class="page-article-details__product-formats-container mt-3" *ngIf="item.family?.length > 0"> <div class="page-article-details__product-formats-container mt-3">
<hr class="bg-[#E6EFF9] border-t-2" /> <hr class="bg-[#E6EFF9] border-t-2" />
<div class="pt-3"> <div class="pt-3">
<div class="page-article-details__product-formats"> <div class="page-article-details__product-formats">
<span class="mr-2">Auch verfügbar als</span> <span class="mr-2">Auch verfügbar als</span>
<ui-slider [scrollDistance]="250"> <ui-slider [scrollDistance]="250">
@for (format of item.family; track format) {
<a <a
class="mr-4 text-[#0556B4] font-bold no-underline px-2" class="mr-4 text-[#0556B4] font-bold no-underline px-2"
*ngFor="let format of item.family"
[routerLink]="getDetailsPath(format.product.ean)" [routerLink]="getDetailsPath(format.product.ean)"
queryParamsHandling="preserve" queryParamsHandling="preserve"
> >
<span class="flex items-center"> <span class="flex items-center">
@if (!!format.product?.format) {
<img <img
class="mr-2" class="mr-2"
*ngIf="!!format.product?.format"
[src]="'/assets/images/OF_Icon_' + format.product?.format + '.svg'" [src]="'/assets/images/OF_Icon_' + format.product?.format + '.svg'"
alt="format icon" alt="format icon"
/> />
}
{{ format.product?.formatDetail }} {{ format.product?.formatDetail }}
<span class="ml-1">{{ format.catalogAvailability?.price?.value?.value | currency: '€' }}</span> <span class="ml-1">{{ format.catalogAvailability?.price?.value?.value | currency: '€' }}</span>
</span> </span>
</a> </a>
}
</ui-slider> </ui-slider>
</div> </div>
</div> </div>
</div> </div>
}
<hr class="bg-[#E6EFF9] border-t-2 my-3" /> <hr class="bg-[#E6EFF9] border-t-2 my-3" />
<div #description class="page-article-details__product-description flex flex-col flex-grow mb-6" *ngIf="item.texts?.length > 0"> @if (item.texts?.length > 0) {
<div #description class="page-article-details__product-description flex flex-col flex-grow mb-6">
<page-article-details-text class="block box-border" [text]="item.texts[0]"></page-article-details-text> <page-article-details-text class="block box-border" [text]="item.texts[0]"></page-article-details-text>
<div class="box-border"> <div class="box-border">
@if (!showMore && item?.texts?.length > 1) {
<button <button
class="font-bold flex flex-row text-[#0556B4] items-center mt-2" class="font-bold flex flex-row text-[#0556B4] items-center mt-2"
*ngIf="!showMore && item?.texts?.length > 1"
(click)="showMore = !showMore" (click)="showMore = !showMore"
> >
Mehr Mehr
<ui-icon class="ml-2" size="15px" icon="arrow"></ui-icon> <ui-icon class="ml-2" size="15px" icon="arrow"></ui-icon>
</button> </button>
}
</div> </div>
@if (showMore) {
<div *ngIf="showMore" class="page-article-details__product-description-text flex flex-col whitespace-pre-line break-words box-border"> <div class="page-article-details__product-description-text flex flex-col whitespace-pre-line break-words box-border">
<span *ngFor="let text of item.texts | slice: 1"> @for (text of item.texts | slice: 1; track text) {
<span>
<h3 class="my-4 text-p2 font-bold">{{ text.label }}</h3> <h3 class="my-4 text-p2 font-bold">{{ text.label }}</h3>
{{ text.value }} {{ text.value }}
</span> </span>
}
<button class="font-bold flex flex-row text-[#0556B4] items-center mt-2" (click)="showMore = !showMore"> <button class="font-bold flex flex-row text-[#0556B4] items-center mt-2" (click)="showMore = !showMore">
<ui-icon class="transform ml-0 mr-2 rotate-180" size="15px" icon="arrow"></ui-icon> <ui-icon class="transform ml-0 mr-2 rotate-180" size="15px" icon="arrow"></ui-icon>
Weniger Weniger
</button> </button>
<button class="page-article-details__scroll-top-cta" (click)="scrollTop(description)"> <button class="page-article-details__scroll-top-cta" (click)="scrollTop(description)">
<ui-icon class="text-[#0556B4]" icon="arrow" size="20px"></ui-icon> <ui-icon class="text-[#0556B4]" icon="arrow" size="20px"></ui-icon>
</button> </button>
</div> </div>
}
<div class="h-28 box-border"></div> <div class="h-28 box-border"></div>
</div> </div>
}
</div> </div>
}
<div class="page-article-details__product-recommendations relative"> <div class="page-article-details__product-recommendations relative">
@if (store.item$ | async; as item) {
<button <button
*ngIf="store.item$ | async; let item"
class="shadow-[#dce2e9_0px_-2px_18px_0px] mb-5 border-none outline-none flex items-center px-5 h-14 min-h-[3.5rem] bg-white w-full" class="shadow-[#dce2e9_0px_-2px_18px_0px] mb-5 border-none outline-none flex items-center px-5 h-14 min-h-[3.5rem] bg-white w-full"
(click)="showRecommendations = true" (click)="showRecommendations = true"
matomoClickCategory="prodict-details" matomoClickCategory="prodict-details"
@@ -358,15 +370,16 @@
<span class="uppercase text-[#0556B4] font-bold text-p3">Empfehlungen</span> <span class="uppercase text-[#0556B4] font-bold text-p3">Empfehlungen</span>
<img class="absolute right-5 -top-[0.125rem] h-12" src="assets/images/recommendation_tag.png" alt="recommendation icon" /> <img class="absolute right-5 -top-[0.125rem] h-12" src="assets/images/recommendation_tag.png" alt="recommendation icon" />
</button> </button>
}
</div> </div>
</div> </div>
@if (store.item$ | async; as item) {
<div <div
class="page-article-details__actions absolute bottom-32 left-1/2 -translate-x-1/2 whitespace-nowrap" class="page-article-details__actions absolute bottom-32 left-1/2 -translate-x-1/2 whitespace-nowrap"
*ngIf="store.item$ | async; let item"
> >
@if (!(store.isDownload$ | async)) {
<button <button
*ngIf="!(store.isDownload$ | async)"
class="text-brand border-2 border-brand bg-white font-bold text-lg px-[1.375rem] py-4 rounded-full mr-[1.875rem]" class="text-brand border-2 border-brand bg-white font-bold text-lg px-[1.375rem] py-4 rounded-full mr-[1.875rem]"
(click)="showAvailabilities()" (click)="showAvailabilities()"
matomoClickCategory="prodict-details" matomoClickCategory="prodict-details"
@@ -375,6 +388,7 @@
> >
Bestände in anderen Filialen Bestände in anderen Filialen
</button> </button>
}
<button <button
class="text-white bg-brand border-brand font-bold text-lg px-[1.375rem] py-4 rounded-full border-none no-underline" class="text-white bg-brand border-brand font-bold text-lg px-[1.375rem] py-4 rounded-full border-none no-underline"
(click)="showPurchasingModal()" (click)="showPurchasingModal()"
@@ -386,10 +400,13 @@
In den Warenkorb In den Warenkorb
</button> </button>
</div> </div>
}
<div class="page-article-details__recommendations-overlay absolute top-0 inset-x-0" @slideYAnimation *ngIf="showRecommendations"> @if (showRecommendations) {
<div class="page-article-details__recommendations-overlay absolute top-0 inset-x-0" @slideYAnimation>
<page-article-recommendations (close)="showRecommendations = false"></page-article-recommendations> <page-article-recommendations (close)="showRecommendations = false"></page-article-recommendations>
</div> </div>
}
<!-- <!--
<ng-container *ngIf="!showRecommendations"> <ng-container *ngIf="!showRecommendations">

View File

@@ -1,4 +1,4 @@
<ng-container *ngIf="store.item$ | async; let item"> @if (store.item$ | async; as item) {
<button <button
class="h-[3.75rem] shadow-[0_-2px_24px_0_#dce2e9] flex flex-row justify-center items-center w-full text-xl bg-white text-[#0556B4] font-bold border-none outline-none rounded-t" class="h-[3.75rem] shadow-[0_-2px_24px_0_#dce2e9] flex flex-row justify-center items-center w-full text-xl bg-white text-[#0556B4] font-bold border-none outline-none rounded-t"
(click)="close.emit()" (click)="close.emit()"
@@ -7,20 +7,20 @@
</button> </button>
<h1>Empfehlungen für Sie</h1> <h1>Empfehlungen für Sie</h1>
<p>Neben dem Titel "{{ item.product?.name }}" gibt es noch andere Artikel, die Sie interessieren könnten.</p> <p>Neben dem Titel "{{ item.product?.name }}" gibt es noch andere Artikel, die Sie interessieren könnten.</p>
<div class="articles"> <div class="articles">
<span class="label mb-2"> <span class="label mb-2">
<ui-icon icon="recommendation" size="20px"></ui-icon> <ui-icon icon="recommendation" size="20px"></ui-icon>
Artikel Artikel
</span> </span>
@if (store.recommendations$ | async; as recommendations) {
<ng-container *ngIf="store.recommendations$ | async; let recommendations"> @if (recommendations.length === 0) {
<span *ngIf="recommendations.length === 0" class="empty-message">Keine Empfehlungen verfügbar</span> <span class="empty-message">Keine Empfehlungen verfügbar</span>
}
<ui-slider *ngIf="recommendations.length > 0" [scrollDistance]="210"> @if (recommendations.length > 0) {
<ui-slider [scrollDistance]="210">
@for (recommendation of store.recommendations$ | async; track recommendation) {
<a <a
class="article" class="article"
*ngFor="let recommendation of store.recommendations$ | async"
[routerLink]="getDetailsPath(recommendation.product.ean)" [routerLink]="getDetailsPath(recommendation.product.ean)"
[queryParams]="{ main_qs: recommendation.product.ean, filter_format: '' }" [queryParams]="{ main_qs: recommendation.product.ean, filter_format: '' }"
(click)="close.emit()" (click)="close.emit()"
@@ -31,7 +31,9 @@
<span class="price">{{ recommendation.catalogAvailability?.price?.value?.value | currency: ' ' }} EUR</span> <span class="price">{{ recommendation.catalogAvailability?.price?.value?.value | currency: ' ' }} EUR</span>
</div> </div>
</a> </a>
}
</ui-slider> </ui-slider>
</ng-container> }
}
</div> </div>
</ng-container> }

View File

@@ -1,10 +1,10 @@
<div class="hidden desktop-large:block" [class.show-filter]="showFilter"> <div class="hidden desktop-large:block" [class.show-filter]="showFilter">
<ng-container *ngIf="filter$ | async; let filter"> @if (filter$ | async; as filter) {
<div class="catalog-search-filter-content"> <div class="catalog-search-filter-content">
<div class="w-full flex flex-row justify-end items-center"> <div class="w-full flex flex-row justify-end items-center">
<button (click)="clearFilter(filter)" class="text-[#0556B4] p-4">Alle Filter entfernen</button> <button (click)="clearFilter(filter)" class="text-[#0556B4] p-4">Alle Filter entfernen</button>
@if (showFilterClose$ | async) {
<a <a
*ngIf="showFilterClose$ | async"
class="text-black p-4 outline-none border-none bg-transparent" class="text-black p-4 outline-none border-none bg-transparent"
[routerLink]="closeFilterRoute" [routerLink]="closeFilterRoute"
(click)="showFilter = false" (click)="showFilter = false"
@@ -12,8 +12,8 @@
> >
<shared-icon icon="close" [size]="25"></shared-icon> <shared-icon icon="close" [size]="25"></shared-icon>
</a> </a>
}
</div> </div>
<div class="catalog-search-filter-content-main -mt-14 desktop-small:-mt-8 desktop-large:-mt-12"> <div class="catalog-search-filter-content-main -mt-14 desktop-small:-mt-8 desktop-large:-mt-12">
<h1 class="text-h3 text-[1.625rem] font-bold text-center pt-6 pb-10">Filter</h1> <h1 class="text-h3 text-[1.625rem] font-bold text-center pt-6 pb-10">Filter</h1>
<shared-filter <shared-filter
@@ -24,16 +24,14 @@
[scanner]="true" [scanner]="true"
></shared-filter> ></shared-filter>
</div> </div>
<div class="cta-wrapper"> <div class="cta-wrapper">
<button class="cta-reset-filter" (click)="resetFilter(filter)" [disabled]="fetching$ | async">Filter zurücksetzen</button> <button class="cta-reset-filter" (click)="resetFilter(filter)" [disabled]="fetching$ | async">Filter zurücksetzen</button>
<button class="cta-apply-filter" (click)="applyFilter(filter)" [disabled]="(fetching$ | async) || !hasSelectedOptions(filter)"> <button class="cta-apply-filter" (click)="applyFilter(filter)" [disabled]="(fetching$ | async) || !hasSelectedOptions(filter)">
<ui-spinner [show]="fetching$ | async">Filter anwenden</ui-spinner> <ui-spinner [show]="fetching$ | async">Filter anwenden</ui-spinner>
</button> </button>
</div> </div>
</div> </div>
</ng-container> }
</div> </div>
<div class="desktop-large:hidden" [class.hidden]="showFilter"> <div class="desktop-large:hidden" [class.hidden]="showFilter">
<page-article-search-main (showFilter)="showFilter = true"></page-article-search-main> <page-article-search-main (showFilter)="showFilter = true"></page-article-search-main>

View File

@@ -1,12 +1,13 @@
<div class="bg-white rounded py-10 px-4 text-center shadow-[0_-2px_24px_0_#dce2e9] h-full"> <div class="bg-white rounded py-10 px-4 text-center shadow-[0_-2px_24px_0_#dce2e9] h-full">
<h1 class="text-h3 text-[1.625rem] font-bold mb-[0.375rem]">Artikelsuche</h1> <h1 class="text-h3 text-[1.625rem] font-bold mb-[0.375rem]">Artikelsuche</h1>
<p class="text-lg mb-10">Welchen Artikel suchen Sie?</p> <p class="text-lg mb-10">Welchen Artikel suchen Sie?</p>
<ng-container *ngIf="filter$ | async; let filter"> @if (filter$ | async; as filter) {
@if (!(isDesktop$ | async)) {
<shared-filter-filter-group-main <shared-filter-filter-group-main
class="mb-8 w-full" class="mb-8 w-full"
*ngIf="!(isDesktop$ | async)"
[inputGroup]="filter?.filter | group: 'main'" [inputGroup]="filter?.filter | group: 'main'"
></shared-filter-filter-group-main> ></shared-filter-filter-group-main>
}
<div class="flex flex-row px-12 justify-center desktop-large:px-0"> <div class="flex flex-row px-12 justify-center desktop-large:px-0">
<shared-filter-input-group-main <shared-filter-input-group-main
class="block w-full mr-3 desktop-large:mx-auto" class="block w-full mr-3 desktop-large:mx-auto"
@@ -17,9 +18,9 @@
[showDescription]="false" [showDescription]="false"
[scanner]="true" [scanner]="true"
></shared-filter-input-group-main> ></shared-filter-input-group-main>
@if (!(isDesktop$ | async)) {
<button <button
type="button" type="button"
*ngIf="!(isDesktop$ | async)"
(click)="showFilter.emit()" (click)="showFilter.emit()"
class="page-search-main__filter w-[6.75rem] h-14 rounded font-bold px-5 mb-4 text-lg bg-[#AEB7C1] flex flex-row flex-nowrap items-center justify-center" class="page-search-main__filter w-[6.75rem] h-14 rounded font-bold px-5 mb-4 text-lg bg-[#AEB7C1] flex flex-row flex-nowrap items-center justify-center"
[class.active]="hasFilter$ | async" [class.active]="hasFilter$ | async"
@@ -27,12 +28,13 @@
<shared-icon class="mr-2" icon="filter-variant"></shared-icon> <shared-icon class="mr-2" icon="filter-variant"></shared-icon>
Filter Filter
</button> </button>
}
</div> </div>
<div class="flex flex-col items-start ml-12 desktop-large:ml-8 py-6 bg-white overflow-hidden h-[calc(100%-13.5rem)]"> <div class="flex flex-col items-start ml-12 desktop-large:ml-8 py-6 bg-white overflow-hidden h-[calc(100%-13.5rem)]">
<h3 class="text-p3 font-bold mb-3">Deine letzten Suchanfragen</h3> <h3 class="text-p3 font-bold mb-3">Deine letzten Suchanfragen</h3>
<ul class="flex flex-col justify-start overflow-hidden overflow-y-scroll items-start m-0 p-0 bg-white w-full"> <ul class="flex flex-col justify-start overflow-hidden overflow-y-scroll items-start m-0 p-0 bg-white w-full">
<li class="list-none pb-3" *ngFor="let recentQuery of history$ | async"> @for (recentQuery of history$ | async; track recentQuery) {
<li class="list-none pb-3">
<button <button
class="flex flex-row items-center outline-none border-none bg-white text-black text-p2 m-0 p-0" class="flex flex-row items-center outline-none border-none bg-white text-black text-p2 m-0 p-0"
(click)="setQueryHistory(filter, recentQuery.friendlyName)" (click)="setQueryHistory(filter, recentQuery.friendlyName)"
@@ -48,7 +50,8 @@
<p class="m-0 p-0 whitespace-nowrap overflow-hidden overflow-ellipsis max-w-[25rem]">{{ recentQuery.friendlyName }}</p> <p class="m-0 p-0 whitespace-nowrap overflow-hidden overflow-ellipsis max-w-[25rem]">{{ recentQuery.friendlyName }}</p>
</button> </button>
</li> </li>
}
</ul> </ul>
</div> </div>
</ng-container> }
</div> </div>

View File

@@ -1,4 +1,6 @@
<p class="can-add-message" *ngIf="ref.data.canAddMessage">{{ ref.data.canAddMessage }}</p> @if (ref.data.canAddMessage) {
<p class="can-add-message">{{ ref.data.canAddMessage }}</p>
}
<div class="actions"> <div class="actions">
<button (click)="continue()" class="cta cta-action-secondary">Weiter Einkaufen</button> <button (click)="continue()" class="cta cta-action-secondary">Weiter Einkaufen</button>

View File

@@ -1,4 +1,4 @@
<ng-container *ngIf="!primaryOutletActive; else primaryOutlet"> @if (!primaryOutletActive) {
<div class="bg-ucla-blue rounded w-[4.375rem] h-[5.625rem] animate-[load_1s_linear_infinite]"></div> <div class="bg-ucla-blue rounded w-[4.375rem] h-[5.625rem] animate-[load_1s_linear_infinite]"></div>
<div class="flex flex-col flex-grow"> <div class="flex flex-col flex-grow">
<div class="h-4 bg-ucla-blue ml-4 mb-2 w-[7.8125rem] animate-[load_1s_linear_infinite]"></div> <div class="h-4 bg-ucla-blue ml-4 mb-2 w-[7.8125rem] animate-[load_1s_linear_infinite]"></div>
@@ -16,9 +16,7 @@
<div class="h-4 bg-ucla-blue ml-4 w-[7.8125rem] animate-[load_1s_linear_infinite]"></div> <div class="h-4 bg-ucla-blue ml-4 w-[7.8125rem] animate-[load_1s_linear_infinite]"></div>
</div> </div>
</div> </div>
</ng-container> } @else {
<ng-template #primaryOutlet>
<div class="bg-ucla-blue rounded w-[3rem] h-[4.125rem] animate-[load_1s_linear_infinite]"></div> <div class="bg-ucla-blue rounded w-[3rem] h-[4.125rem] animate-[load_1s_linear_infinite]"></div>
<div class="flex flex-col ml-4 w-[36.6%]"> <div class="flex flex-col ml-4 w-[36.6%]">
<div class="h-4 bg-ucla-blue mb-2 w-[8.8125rem] animate-[load_1s_linear_infinite]"></div> <div class="h-4 bg-ucla-blue mb-2 w-[8.8125rem] animate-[load_1s_linear_infinite]"></div>
@@ -35,4 +33,5 @@
<div class="h-4 bg-ucla-blue mb-2 w-[8.8125rem] animate-[load_1s_linear_infinite]"></div> <div class="h-4 bg-ucla-blue mb-2 w-[8.8125rem] animate-[load_1s_linear_infinite]"></div>
<div class="h-4 bg-ucla-blue w-[8.8125rem] animate-[load_1s_linear_infinite]"></div> <div class="h-4 bg-ucla-blue w-[8.8125rem] animate-[load_1s_linear_infinite]"></div>
</div> </div>
</ng-template> }

View File

@@ -4,13 +4,14 @@
[class.active]="isActive" [class.active]="isActive"
> >
<div class="page-search-result-item__item-thumbnail text-center mr-4 w-[3.125rem] h-[4.9375rem]"> <div class="page-search-result-item__item-thumbnail text-center mr-4 w-[3.125rem] h-[4.9375rem]">
@if (item?.imageId | thumbnailUrl; as thumbnailUrl) {
<img <img
class="page-search-result-item__item-image w-[3.125rem] max-h-[4.9375rem]" class="page-search-result-item__item-image w-[3.125rem] max-h-[4.9375rem]"
loading="lazy" loading="lazy"
*ngIf="item?.imageId | thumbnailUrl; let thumbnailUrl"
[src]="thumbnailUrl" [src]="thumbnailUrl"
[alt]="item?.product?.name" [alt]="item?.product?.name"
/> />
}
</div> </div>
<div <div
@@ -20,14 +21,15 @@
<div <div
class="page-search-result-item__item-contributors desktop-small:text-p3 font-bold text-[#0556B4] text-ellipsis overflow-hidden max-w-[24rem] whitespace-nowrap" class="page-search-result-item__item-contributors desktop-small:text-p3 font-bold text-[#0556B4] text-ellipsis overflow-hidden max-w-[24rem] whitespace-nowrap"
> >
@for (contributor of contributors; track contributor; let last = $last) {
<a <a
*ngFor="let contributor of contributors; let last = last"
[routerLink]="resultsPath" [routerLink]="resultsPath"
[queryParams]="{ main_qs: contributor, main_author: 'author' }" [queryParams]="{ main_qs: contributor, main_author: 'author' }"
(click)="$event?.stopPropagation()" (click)="$event?.stopPropagation()"
> >
{{ contributor }}{{ last ? '' : ';' }} {{ contributor }}{{ last ? '' : ';' }}
</a> </a>
}
</div> </div>
<div <div
@@ -42,16 +44,19 @@
</div> </div>
<div class="page-search-result-item__item-format desktop-small:text-p3"> <div class="page-search-result-item__item-format desktop-small:text-p3">
<div *ngIf="item?.product?.format && item?.product?.formatDetail" class="font-bold flex flex-row"> @if (item?.product?.format && item?.product?.formatDetail) {
<div class="font-bold flex flex-row">
@if (item?.product?.format !== '--') {
<img <img
class="mr-3" class="mr-3"
*ngIf="item?.product?.format !== '--'"
loading="lazy" loading="lazy"
src="assets/images/Icon_{{ item?.product?.format }}.svg" src="assets/images/Icon_{{ item?.product?.format }}.svg"
[alt]="item?.product?.formatDetail" [alt]="item?.product?.formatDetail"
/> />
}
{{ item?.product?.formatDetail | substr: 30 }} {{ item?.product?.formatDetail | substr: 30 }}
</div> </div>
}
</div> </div>
<div class="page-search-result-item__item-manufacturer desktop-small:text-p3"> <div class="page-search-result-item__item-manufacturer desktop-small:text-p3">
@@ -60,7 +65,9 @@
<div class="page-search-result-item__item-misc desktop-small:text-p3"> <div class="page-search-result-item__item-misc desktop-small:text-p3">
{{ item?.product?.volume }} {{ item?.product?.volume }}
<span *ngIf="item?.product?.volume && item?.product?.publicationDate">|</span> @if (item?.product?.volume && item?.product?.publicationDate) {
<span>|</span>
}
{{ publicationDate }} {{ publicationDate }}
</div> </div>
@@ -72,8 +79,8 @@
</div> </div>
<div class="page-search-result-item__item-select-bullet justify-self-end"> <div class="page-search-result-item__item-select-bullet justify-self-end">
@if (selectable) {
<input <input
*ngIf="selectable"
(click)="$event.stopPropagation()" (click)="$event.stopPropagation()"
[ngModel]="selected" [ngModel]="selected"
(ngModelChange)=" (ngModelChange)="
@@ -85,6 +92,7 @@
matomoTracker matomoTracker
#tracker="matomo" #tracker="matomo"
/> />
}
</div> </div>
<button <button
@@ -96,18 +104,19 @@
(click)="$event.stopPropagation(); $event.preventDefault(); showTooltip()" (click)="$event.stopPropagation(); $event.preventDefault(); showTooltip()"
> >
<ui-icon class="mr-[0.125rem] -mt-[0.275rem]" icon="home" size="1rem"></ui-icon> <ui-icon class="mr-[0.125rem] -mt-[0.275rem]" icon="home" size="1rem"></ui-icon>
<ng-container *ngIf="isOrderBranch$ | async"> @if (isOrderBranch$ | async) {
@if (inStock$ | async; as stock) {
<span <span
*ngIf="inStock$ | async; let stock"
[class.skeleton]="stock.inStock === undefined" [class.skeleton]="stock.inStock === undefined"
class="min-w-[0.75rem] text-right inline-block" class="min-w-[0.75rem] text-right inline-block"
> >
{{ stock?.inStock }} {{ stock?.inStock }}
</span> </span>
</ng-container> }
<ng-container *ngIf="!(isOrderBranch$ | async)"> }
@if (!(isOrderBranch$ | async)) {
<span class="min-w-[1rem] text-center inline-block">-</span> <span class="min-w-[1rem] text-center inline-block">-</span>
</ng-container> }
<span>x</span> <span>x</span>
</button> </button>
<ui-tooltip #tooltip yPosition="above" xPosition="after" [yOffset]="-12" [closeable]="true"> <ui-tooltip #tooltip yPosition="above" xPosition="after" [yOffset]="-12" [closeable]="true">
@@ -118,13 +127,13 @@
class="page-search-result-item__item-ssc desktop-small:text-p3 w-full text-right overflow-hidden text-ellipsis whitespace-nowrap" class="page-search-result-item__item-ssc desktop-small:text-p3 w-full text-right overflow-hidden text-ellipsis whitespace-nowrap"
[class.page-search-result-item__item-ssc-primary]="primaryOutletActive" [class.page-search-result-item__item-ssc-primary]="primaryOutletActive"
> >
<ng-container *ngIf="ssc$ | async; let ssc"> @if (ssc$ | async; as ssc) {
<div class="hidden" [class.page-search-result-item__item-ssc-tooltip]="primaryOutletActive"> <div class="hidden" [class.page-search-result-item__item-ssc-tooltip]="primaryOutletActive">
{{ ssc?.ssc }} - {{ ssc?.sscText }} {{ ssc?.ssc }} - {{ ssc?.sscText }}
</div> </div>
<strong>{{ ssc?.ssc }}</strong> <strong>{{ ssc?.ssc }}</strong>
- {{ ssc?.sscText }} - {{ ssc?.sscText }}
</ng-container> }
</div> </div>
</div> </div>
</div> </div>

View File

@@ -4,8 +4,8 @@
[class.flex-col]="!(primaryOutletActive$ | async)" [class.flex-col]="!(primaryOutletActive$ | async)"
> >
<div class="flex flex-row w-full desktop:w-min" [class.desktop-large:w-full]="!(primaryOutletActive$ | async)"> <div class="flex flex-row w-full desktop:w-min" [class.desktop-large:w-full]="!(primaryOutletActive$ | async)">
@if (filter$ | async; as filter) {
<shared-filter-input-group-main <shared-filter-input-group-main
*ngIf="filter$ | async; let filter"
class="block mr-3 w-full desktop:w-[23.5rem]" class="block mr-3 w-full desktop:w-[23.5rem]"
[class.desktop-large:w-full]="!(primaryOutletActive$ | async)" [class.desktop-large:w-full]="!(primaryOutletActive$ | async)"
[hint]="searchboxHint$ | async" [hint]="searchboxHint$ | async"
@@ -15,6 +15,7 @@
[showDescription]="false" [showDescription]="false"
[scanner]="true" [scanner]="true"
></shared-filter-input-group-main> ></shared-filter-input-group-main>
}
<a <a
class="page-search-results__filter w-[6.75rem] h-14 rounded font-bold px-5 mb-4 text-lg bg-[#AEB7C1] flex flex-row flex-nowrap items-center justify-center" class="page-search-results__filter w-[6.75rem] h-14 rounded font-bold px-5 mb-4 text-lg bg-[#AEB7C1] flex flex-row flex-nowrap items-center justify-center"
@@ -27,25 +28,27 @@
</a> </a>
</div> </div>
@if (hits$ | async; as hits) {
<div <div
*ngIf="hits$ | async; let hits"
class="page-search-results__items-count inline-flex flex-row items-center pr-5 text-p3" class="page-search-results__items-count inline-flex flex-row items-center pr-5 text-p3"
[class.mb-4]="primaryOutletActive$ | async" [class.mb-4]="primaryOutletActive$ | async"
> >
{{ hits ?? 0 }} {{ hits ?? 0 }}
Titel Titel
</div> </div>
}
</div> </div>
<div class="page-search-results__order-by mb-[0.125rem]" [class.page-search-results__order-by-primary]="primaryOutletActive$ | async"> <div class="page-search-results__order-by mb-[0.125rem]" [class.page-search-results__order-by-primary]="primaryOutletActive$ | async">
@if (filter$ | async; as filter) {
<shared-order-by-filter <shared-order-by-filter
*ngIf="filter$ | async; let filter"
[orderBy]="filter?.orderBy" [orderBy]="filter?.orderBy"
(selectedOrderByChange)="search({ filter, clear: true, orderBy: true }); updateBreadcrumbs()" (selectedOrderByChange)="search({ filter, clear: true, orderBy: true }); updateBreadcrumbs()"
></shared-order-by-filter> ></shared-order-by-filter>
}
</div> </div>
<ng-container *ngIf="primaryOutletActive$ | async; else sideOutlet"> @if (primaryOutletActive$ | async) {
<cdk-virtual-scroll-viewport class="product-list" [itemSize]="103 * (scale$ | async)" (scrolledIndexChange)="scrolledIndexChange($event)"> <cdk-virtual-scroll-viewport class="product-list" [itemSize]="103 * (scale$ | async)" (scrolledIndexChange)="scrolledIndexChange($event)">
<a <a
*cdkVirtualFor="let item of results$ | async; let i = index; trackBy: trackByItemId" *cdkVirtualFor="let item of results$ | async; let i = index; trackBy: trackByItemId"
@@ -65,12 +68,14 @@
[isActive]="rla.isActive" [isActive]="rla.isActive"
></search-result-item> ></search-result-item>
</a> </a>
<page-search-result-item-loading [primaryOutletActive]="true" *ngIf="fetching$ | async"></page-search-result-item-loading> @if (fetching$ | async) {
<page-search-result-item-loading [primaryOutletActive]="true"></page-search-result-item-loading>
}
</cdk-virtual-scroll-viewport> </cdk-virtual-scroll-viewport>
<div class="actions z-sticky h-0"> <div class="actions z-sticky h-0">
@if ((selectedItemIds$ | async)?.length > 0) {
<button <button
[disabled]="loading$ | async" [disabled]="loading$ | async"
*ngIf="(selectedItemIds$ | async)?.length > 0"
class="cta-cart cta-action-primary" class="cta-cart cta-action-primary"
(click)="addToCart()" (click)="addToCart()"
matomoClickCategory="Trefferliste" matomoClickCategory="Trefferliste"
@@ -79,10 +84,9 @@
> >
<ui-spinner [show]="loading$ | async">In den Warenkorb legen</ui-spinner> <ui-spinner [show]="loading$ | async">In den Warenkorb legen</ui-spinner>
</button> </button>
}
</div> </div>
</ng-container> } @else {
<ng-template #sideOutlet>
<cdk-virtual-scroll-viewport class="product-list" [itemSize]="191 * (scale$ | async)" (scrolledIndexChange)="scrolledIndexChange($event)"> <cdk-virtual-scroll-viewport class="product-list" [itemSize]="191 * (scale$ | async)" (scrolledIndexChange)="scrolledIndexChange($event)">
<a <a
*cdkVirtualFor="let item of results$ | async; let i = index; trackBy: trackByItemId" *cdkVirtualFor="let item of results$ | async; let i = index; trackBy: trackByItemId"
@@ -102,16 +106,20 @@
[isActive]="rla.isActive" [isActive]="rla.isActive"
></search-result-item> ></search-result-item>
</a> </a>
<page-search-result-item-loading [primaryOutletActive]="false" *ngIf="fetching$ | async"></page-search-result-item-loading> @if (fetching$ | async) {
<page-search-result-item-loading [primaryOutletActive]="false"></page-search-result-item-loading>
}
</cdk-virtual-scroll-viewport> </cdk-virtual-scroll-viewport>
<div class="actions z-sticky h-0"> <div class="actions z-sticky h-0">
@if ((selectedItemIds$ | async)?.length > 0) {
<button <button
[disabled]="loading$ | async" [disabled]="loading$ | async"
*ngIf="(selectedItemIds$ | async)?.length > 0"
class="cta-cart cta-action-primary" class="cta-cart cta-action-primary"
(click)="addToCart()" (click)="addToCart()"
> >
<ui-spinner [show]="loading$ | async">In den Warenkorb legen</ui-spinner> <ui-spinner [show]="loading$ | async">In den Warenkorb legen</ui-spinner>
</button> </button>
}
</div> </div>
</ng-template> }

View File

@@ -9,7 +9,8 @@
</p> </p>
</div> </div>
</div> </div>
<form *ngIf="control" [formGroup]="control" (submit)="submit()"> @if (control) {
<form [formGroup]="control" (submit)="submit()">
<ui-form-control class="searchbox-control" label="EAN/ISBN"> <ui-form-control class="searchbox-control" label="EAN/ISBN">
<ui-searchbox <ui-searchbox
formControlName="ean" formControlName="ean"
@@ -65,7 +66,9 @@
</ui-form-control> </ui-form-control>
<ui-form-control class="supplier-dropdown" label="Lieferant" requiredMark="*"> <ui-form-control class="supplier-dropdown" label="Lieferant" requiredMark="*">
<ui-select tabindex="-1" formControlName="supplier"> <ui-select tabindex="-1" formControlName="supplier">
<ui-select-option *ngFor="let supplier of suppliers$ | async" [label]="supplier.name" [value]="supplier.id"></ui-select-option> @for (supplier of suppliers$ | async; track supplier) {
<ui-select-option [label]="supplier.name" [value]="supplier.id"></ui-select-option>
}
</ui-select> </ui-select>
</ui-form-control> </ui-form-control>
<div class="control-row"> <div class="control-row">
@@ -74,7 +77,9 @@
</ui-form-control> </ui-form-control>
<ui-form-control class="mwst-dropdown" label="MwSt" requiredMark="*"> <ui-form-control class="mwst-dropdown" label="MwSt" requiredMark="*">
<ui-select tabindex="-1" formControlName="vat"> <ui-select tabindex="-1" formControlName="vat">
<ui-select-option *ngFor="let vat of vats$ | async" [label]="vat.name + '%'" [value]="vat.vatType"></ui-select-option> @for (vat of vats$ | async; track vat) {
<ui-select-option [label]="vat.name + '%'" [value]="vat.vatType"></ui-select-option>
}
</ui-select> </ui-select>
</ui-form-control> </ui-form-control>
</div> </div>
@@ -92,4 +97,5 @@
</button> </button>
</div> </div>
</form> </form>
}
</div> </div>

View File

@@ -1,10 +1,9 @@
<ng-container *ngIf="(groupedItems$ | async)?.length <= 0 && !(fetching$ | async); else shoppingCart"> @if ((groupedItems$ | async)?.length <= 0 && !(fetching$ | async)) {
<div class="card stretch"> <div class="card stretch">
<div class="empty-message"> <div class="empty-message">
<span class="cart-icon flex items-center justify-center"> <span class="cart-icon flex items-center justify-center">
<shared-icon icon="shopping-cart-bold" [size]="24"></shared-icon> <shared-icon icon="shopping-cart-bold" [size]="24"></shared-icon>
</span> </span>
<h1>Ihr Warenkorb ist leer.</h1> <h1>Ihr Warenkorb ist leer.</h1>
<p> <p>
Sie haben alle Artikel aus dem Sie haben alle Artikel aus dem
@@ -13,73 +12,65 @@
<br /> <br />
keinen Artikel hinzugefügt. keinen Artikel hinzugefügt.
</p> </p>
<div class="btn-wrapper"> <div class="btn-wrapper">
<a class="cta-primary" [routerLink]="productSearchBasePath">Artikel suchen</a> <a class="cta-primary" [routerLink]="productSearchBasePath">Artikel suchen</a>
<button class="cta-secondary" (click)="openDummyModal({})">Neuanlage</button> <button class="cta-secondary" (click)="openDummyModal({})">Neuanlage</button>
</div> </div>
</div> </div>
</div> </div>
</ng-container> } @else {
@if (shoppingCart$ | async; as shoppingCart) {
<div class="flex items-center justify-center card stretch" *ngIf="fetching$ | async">
<ui-spinner [show]="true"></ui-spinner>
</div>
<ng-template #shoppingCart>
<ng-container *ngIf="shoppingCart$ | async; let shoppingCart">
<div class="card stretch"> <div class="card stretch">
<div class="cta-print-wrapper"> <div class="cta-print-wrapper">
<button class="cta-print" (click)="openPrintModal()">Drucken</button> <button class="cta-print" (click)="openPrintModal()">Drucken</button>
</div> </div>
<h1 class="header">Warenkorb</h1> <h1 class="header">Warenkorb</h1>
@if (!(isDesktop$ | async)) {
<ng-container *ngIf="!(isDesktop$ | async)">
<page-checkout-review-details></page-checkout-review-details> <page-checkout-review-details></page-checkout-review-details>
</ng-container> }
@for (group of groupedItems$ | async; track trackByGroupedItems($index, group); let lastGroup = $last) {
<ng-container *ngFor="let group of groupedItems$ | async; let lastGroup = last; trackBy: trackByGroupedItems"> @if (group?.orderType !== undefined) {
<ng-container *ngIf="group?.orderType !== undefined">
<hr /> <hr />
<div class="row item-group-header bg-[#F5F7FA]"> <div class="row item-group-header bg-[#F5F7FA]">
@if (group.orderType !== 'Dummy') {
<shared-icon <shared-icon
*ngIf="group.orderType !== 'Dummy'"
class="icon-order-type" class="icon-order-type"
[size]="group.orderType === 'B2B-Versand' ? 36 : 24" [size]="group.orderType === 'B2B-Versand' ? 36 : 24"
[icon]="group.orderType" [icon]="group.orderType"
></shared-icon> ></shared-icon>
}
<div class="label" [class.dummy]="group.orderType === 'Dummy'"> <div class="label" [class.dummy]="group.orderType === 'Dummy'">
{{ group.orderType !== 'Dummy' ? group.orderType : 'Manuelle Anlage / Dummy Bestellung' }} {{ group.orderType !== 'Dummy' ? group.orderType : 'Manuelle Anlage / Dummy Bestellung' }}
@if (group.orderType === 'Dummy') {
<button <button
*ngIf="group.orderType === 'Dummy'"
class="text-brand border-none font-bold text-p1 outline-none pl-4" class="text-brand border-none font-bold text-p1 outline-none pl-4"
(click)="openDummyModal({ changeDataFromCart: true })" (click)="openDummyModal({ changeDataFromCart: true })"
> >
Hinzufügen Hinzufügen
</button> </button>
}
</div> </div>
<div class="grow"></div> <div class="grow"></div>
<div class="pl-4" *ngIf="group.orderType !== 'Download' && group.orderType !== 'Dummy'"> @if (group.orderType !== 'Download' && group.orderType !== 'Dummy') {
<div class="pl-4">
<button class="cta-edit" (click)="showPurchasingListModal(group.items)">Ändern</button> <button class="cta-edit" (click)="showPurchasingListModal(group.items)">Ändern</button>
</div> </div>
}
</div> </div>
<hr @if (
*ngIf="
group.orderType === 'Download' || group.orderType === 'Download' ||
group.orderType === 'Versand' || group.orderType === 'Versand' ||
group.orderType === 'B2B-Versand' || group.orderType === 'B2B-Versand' ||
group.orderType === 'DIG-Versand' group.orderType === 'DIG-Versand'
" ) {
<hr
/> />
</ng-container> }
<ng-container *ngFor="let item of group.items; let lastItem = last; let i = index; trackBy: trackByItemId"> }
<ng-container @for (item of group.items; track trackByItemId(i, item); let lastItem = $last; let i = $index) {
*ngIf="group?.orderType !== undefined && (item.features?.orderType === 'Abholung' || item.features?.orderType === 'Rücklage')" @if (group?.orderType !== undefined && (item.features?.orderType === 'Abholung' || item.features?.orderType === 'Rücklage')) {
> @if (item?.destination?.data?.targetBranch?.data; as targetBranch) {
<ng-container *ngIf="item?.destination?.data?.targetBranch?.data; let targetBranch"> @if (i === 0 || checkIfMultipleDestinationsForOrderTypeExist(targetBranch, group, i)) {
<ng-container *ngIf="i === 0 || checkIfMultipleDestinationsForOrderTypeExist(targetBranch, group, i)">
<div <div
class="flex flex-row items-center px-5 pt-0 pb-[0.875rem] -mt-2 bg-[#F5F7FA]" class="flex flex-row items-center px-5 pt-0 pb-[0.875rem] -mt-2 bg-[#F5F7FA]"
[class.multiple-destinations]="checkIfMultipleDestinationsForOrderTypeExist(targetBranch, group, i)" [class.multiple-destinations]="checkIfMultipleDestinationsForOrderTypeExist(targetBranch, group, i)"
@@ -87,10 +78,9 @@
<span class="branch-name">{{ targetBranch?.name }} | {{ targetBranch | branchAddress }}</span> <span class="branch-name">{{ targetBranch?.name }} | {{ targetBranch | branchAddress }}</span>
</div> </div>
<hr /> <hr />
</ng-container> }
</ng-container> }
</ng-container> }
<page-shopping-cart-item <page-shopping-cart-item
(changeItem)="changeItem($event)" (changeItem)="changeItem($event)"
(changeDummyItem)="changeDummyItem($event)" (changeDummyItem)="changeDummyItem($event)"
@@ -101,19 +91,22 @@
[loadingOnItemChangeById]="loadingOnItemChangeById$ | async" [loadingOnItemChangeById]="loadingOnItemChangeById$ | async"
[loadingOnQuantityChangeById]="loadingOnQuantityChangeById$ | async" [loadingOnQuantityChangeById]="loadingOnQuantityChangeById$ | async"
></page-shopping-cart-item> ></page-shopping-cart-item>
@if (!lastItem) {
<hr *ngIf="!lastItem" /> <hr />
</ng-container> }
</ng-container> }
}
<div class="h-[8.9375rem]"></div> <div class="h-[8.9375rem]"></div>
</div> </div>
<div class="card footer flex flex-col justify-center items-center"> <div class="card footer flex flex-col justify-center items-center">
<div class="flex flex-row items-start justify-between w-full mb-1"> <div class="flex flex-row items-start justify-between w-full mb-1">
<ng-container *ngIf="totalItemCount$ | async; let totalItemCount"> @if (totalItemCount$ | async; as totalItemCount) {
<div *ngIf="totalReadingPoints$ | async; let totalReadingPoints" class="total-item-reading-points w-full"> @if (totalReadingPoints$ | async; as totalReadingPoints) {
<div class="total-item-reading-points w-full">
{{ totalItemCount }} Artikel | {{ totalReadingPoints }} Lesepunkte {{ totalItemCount }} Artikel | {{ totalReadingPoints }} Lesepunkte
</div> </div>
</ng-container> }
}
<div class="flex flex-col w-full"> <div class="flex flex-col w-full">
<strong class="total-value"> <strong class="total-value">
Zwischensumme {{ shoppingCart?.total?.value | currency: shoppingCart?.total?.currency : 'code' }} Zwischensumme {{ shoppingCart?.total?.value | currency: shoppingCart?.total?.currency : 'code' }}
@@ -136,5 +129,12 @@
</ui-spinner> </ui-spinner>
</button> </button>
</div> </div>
</ng-container> }
</ng-template> }
@if (fetching$ | async) {
<div class="flex items-center justify-center card stretch">
<ui-spinner [show]="true"></ui-spinner>
</div>
}

View File

@@ -2,21 +2,23 @@
Überprüfen Sie die Details. Überprüfen Sie die Details.
</h1> </h1>
<ng-container *ngIf="buyer$ | async; let buyer"> @if (buyer$ | async; as buyer) {
<div *ngIf="!(showAddresses$ | async)" class="flex flex-row items-start justify-between p-5"> @if (!(showAddresses$ | async)) {
<div class="flex flex-row items-start justify-between p-5">
<div class="flex flex-row flex-wrap pr-4"> <div class="flex flex-row flex-wrap pr-4">
<ng-container *ngIf="getNameFromBuyer(buyer); let name"> @if (getNameFromBuyer(buyer); as name) {
<div class="mr-3">{{ name.label }}</div> <div class="mr-3">{{ name.label }}</div>
<div class="font-bold">{{ name.value }}</div> <div class="font-bold">{{ name.value }}</div>
</ng-container> }
</div> </div>
<button (click)="changeAddress()" class="text-p1 font-bold text-[#F70400]">Ändern</button> <button (click)="changeAddress()" class="text-p1 font-bold text-[#F70400]">Ändern</button>
</div> </div>
</ng-container> }
}
<ng-container *ngIf="showNotificationChannels$ | async"> @if (showNotificationChannels$ | async) {
<form class="pb-4" *ngIf="control" [formGroup]="control"> @if (control) {
<form class="pb-4" [formGroup]="control">
<shared-notification-channel-control <shared-notification-channel-control
[communicationDetails]="communicationDetails$ | async" [communicationDetails]="communicationDetails$ | async"
(channelActionEvent)="updateNotifications($event)" (channelActionEvent)="updateNotifications($event)"
@@ -25,33 +27,36 @@
formGroupName="notificationChannel" formGroupName="notificationChannel"
></shared-notification-channel-control> ></shared-notification-channel-control>
</form> </form>
</ng-container> }
}
<ng-container *ngIf="payer$ | async; let payer"> @if (payer$ | async; as payer) {
<div *ngIf="showAddresses$ | async" class="flex flex-row items-start justify-between p-5 pt-0"> @if (showAddresses$ | async) {
<div class="flex flex-row items-start justify-between p-5 pt-0">
<div class="flex flex-row flex-wrap pr-4" data-address-type="Rechnungsadresse" data-which="Rechnungsadresse"> <div class="flex flex-row flex-wrap pr-4" data-address-type="Rechnungsadresse" data-which="Rechnungsadresse">
<div class="mr-3" data-what="title">Rechnungsadresse</div> <div class="mr-3" data-what="title">Rechnungsadresse</div>
<div class="font-bold" data-what="address"> <div class="font-bold" data-what="address">
{{ payer | payerAddress }} {{ payer | payerAddress }}
</div> </div>
</div> </div>
<button (click)="changeAddress()" class="text-p1 font-bold text-[#F70400]">Ändern</button> <button (click)="changeAddress()" class="text-p1 font-bold text-[#F70400]">Ändern</button>
</div> </div>
</ng-container> }
}
<ng-container *ngIf="payer$ | async; let payer"> @if (payer$ | async; as payer) {
<div *ngIf="showAddresses$ | async" class="flex flex-row items-start justify-between px-5"> @if (showAddresses$ | async) {
<div class="flex flex-row items-start justify-between px-5">
<div class="flex flex-row flex-wrap pr-4" data-address-type="Lieferadresse" data-which="Lieferadresse"> <div class="flex flex-row flex-wrap pr-4" data-address-type="Lieferadresse" data-which="Lieferadresse">
<div class="mr-3" data-what="title">Lieferadresse</div> <div class="mr-3" data-what="title">Lieferadresse</div>
<div class="font-bold" data-what="address"> <div class="font-bold" data-what="address">
{{ shippingAddress$ | async | shippingAddress }} {{ shippingAddress$ | async | shippingAddress }}
</div> </div>
</div> </div>
<button (click)="changeAddress()" class="text-p1 font-bold text-[#F70400]">Ändern</button> <button (click)="changeAddress()" class="text-p1 font-bold text-[#F70400]">Ändern</button>
</div> </div>
</ng-container> }
}
<page-special-comment <page-special-comment
class="mb-6 mt-4" class="mb-6 mt-4"

View File

@@ -1,18 +1,21 @@
<div class="item-thumbnail"> <div class="item-thumbnail">
<a [routerLink]="productSearchDetailsPath" [queryParams]="{ main_qs: item?.product?.ean }"> <a [routerLink]="productSearchDetailsPath" [queryParams]="{ main_qs: item?.product?.ean }">
<img loading="lazy" *ngIf="item?.product?.ean | productImage; let thumbnailUrl" [src]="thumbnailUrl" [alt]="item?.product?.name" /> @if (item?.product?.ean | productImage; as thumbnailUrl) {
<img loading="lazy" [src]="thumbnailUrl" [alt]="item?.product?.name" />
}
</a> </a>
</div> </div>
<div class="item-contributors"> <div class="item-contributors">
@for (contributor of contributors$ | async; track contributor; let last = $last) {
<a <a
*ngFor="let contributor of contributors$ | async; let last = last"
[routerLink]="productSearchResultsPath" [routerLink]="productSearchResultsPath"
[queryParams]="{ main_qs: contributor, main_author: 'author' }" [queryParams]="{ main_qs: contributor, main_author: 'author' }"
(click)="$event?.stopPropagation()" (click)="$event?.stopPropagation()"
> >
{{ contributor }}{{ last ? '' : ';' }} {{ contributor }}{{ last ? '' : ';' }}
</a> </a>
}
</div> </div>
<div <div
@@ -25,82 +28,102 @@
<a [routerLink]="productSearchDetailsPath" [queryParams]="{ main_qs: item?.product?.ean }">{{ item?.product?.name }}</a> <a [routerLink]="productSearchDetailsPath" [queryParams]="{ main_qs: item?.product?.ean }">{{ item?.product?.name }}</a>
</div> </div>
<div class="item-format" *ngIf="item?.product?.format && item?.product?.formatDetail"> @if (item?.product?.format && item?.product?.formatDetail) {
<div class="item-format">
@if (item?.product?.format !== '--') {
<img <img
*ngIf="item?.product?.format !== '--'"
src="assets/images/Icon_{{ item?.product?.format }}.svg" src="assets/images/Icon_{{ item?.product?.format }}.svg"
[alt]="item?.product?.formatDetail" [alt]="item?.product?.formatDetail"
/> />
}
{{ item?.product?.formatDetail }} {{ item?.product?.formatDetail }}
</div> </div>
}
<div class="item-info text-p2"> <div class="item-info text-p2">
<div class="mb-1">{{ item?.product?.manufacturer | substr: 25 }} | {{ item?.product?.ean }}</div> <div class="mb-1">{{ item?.product?.manufacturer | substr: 25 }} | {{ item?.product?.ean }}</div>
<div class="mb-1"> <div class="mb-1">
{{ item?.product?.volume }} {{ item?.product?.volume }}
<span *ngIf="item?.product?.volume && item?.product?.publicationDate">|</span> @if (item?.product?.volume && item?.product?.publicationDate) {
<span>|</span>
}
{{ item?.product?.publicationDate | date }} {{ item?.product?.publicationDate | date }}
</div> </div>
<div *ngIf="notAvailable$ | async"> @if (notAvailable$ | async) {
<div>
<span class="text-brand item-date">Nicht verfügbar</span> <span class="text-brand item-date">Nicht verfügbar</span>
</div> </div>
}
<shared-skeleton-loader class="w-40" *ngIf="refreshingAvailabilit$ | async; else avaTmplt"></shared-skeleton-loader> @if (refreshingAvailabilit$ | async) {
<shared-skeleton-loader class="w-40"></shared-skeleton-loader>
<ng-template #avaTmplt> } @else {
<div class="item-date" [class.availability-changed]="estimatedShippingDateChanged$ | async" *ngIf="orderType === 'Abholung'"> @if (orderType === 'Abholung') {
<div class="item-date" [class.availability-changed]="estimatedShippingDateChanged$ | async">
Abholung ab {{ item?.availability?.estimatedShippingDate | date }} Abholung ab {{ item?.availability?.estimatedShippingDate | date }}
</div> </div>
}
@if (orderType === 'Versand' || orderType === 'B2B-Versand' || orderType === 'DIG-Versand') {
<div <div
class="item-date" class="item-date"
[class.availability-changed]="estimatedShippingDateChanged$ | async" [class.availability-changed]="estimatedShippingDateChanged$ | async"
*ngIf="orderType === 'Versand' || orderType === 'B2B-Versand' || orderType === 'DIG-Versand'"
> >
<ng-container *ngIf="item?.availability?.estimatedDelivery; else estimatedShippingDate"> @if (item?.availability?.estimatedDelivery) {
Zustellung zwischen {{ (item?.availability?.estimatedDelivery?.start | date: 'EEE, dd.MM.')?.replace('.', '') }} Zustellung zwischen {{ (item?.availability?.estimatedDelivery?.start | date: 'EEE, dd.MM.')?.replace('.', '') }}
und und
{{ (item?.availability?.estimatedDelivery?.stop | date: 'EEE, dd.MM.')?.replace('.', '') }} {{ (item?.availability?.estimatedDelivery?.stop | date: 'EEE, dd.MM.')?.replace('.', '') }}
</ng-container> } @else {
<ng-template #estimatedShippingDate>Versand {{ item?.availability?.estimatedShippingDate | date }}</ng-template> Versand {{ item?.availability?.estimatedShippingDate | date }}
}
</div> </div>
</ng-template> }
}
<div class="item-availability-message" *ngIf="olaError$ | async">Artikel nicht verfügbar</div>
@if (olaError$ | async) {
<div class="item-availability-message">Artikel nicht verfügbar</div>
}
</div> </div>
<div class="item-price-stock flex flex-col"> <div class="item-price-stock flex flex-col">
<div class="text-p2 font-bold">{{ item?.availability?.price?.value?.value | currency: 'EUR' : 'code' }}</div> <div class="text-p2 font-bold">{{ item?.availability?.price?.value?.value | currency: 'EUR' : 'code' }}</div>
<div class="text-p2 font-normal"> <div class="text-p2 font-normal">
@if (!(isDummy$ | async)) {
<ui-quantity-dropdown <ui-quantity-dropdown
*ngIf="!(isDummy$ | async); else quantityDummy"
[ngModel]="item?.quantity" [ngModel]="item?.quantity"
(ngModelChange)="onChangeQuantity($event)" (ngModelChange)="onChangeQuantity($event)"
[showSpinner]="(loadingOnQuantityChangeById$ | async) === item?.id" [showSpinner]="(loadingOnQuantityChangeById$ | async) === item?.id"
[disabled]="(loadingOnItemChangeById$ | async) === item?.id" [disabled]="(loadingOnItemChangeById$ | async) === item?.id"
[range]="quantityRange$ | async" [range]="quantityRange$ | async"
></ui-quantity-dropdown> ></ui-quantity-dropdown>
<ng-template #quantityDummy> } @else {
<div class="mt-2">{{ item?.quantity }}x</div> <div class="mt-2">{{ item?.quantity }}x</div>
</ng-template> }
</div> </div>
<div class="quantity-error" *ngIf="quantityError"> @if (quantityError) {
<div class="quantity-error">
{{ quantityError }} {{ quantityError }}
</div> </div>
}
</div> </div>
<div class="actions" *ngIf="orderType !== 'Download'"> @if (orderType !== 'Download') {
<div class="actions">
@if (!(hasOrderType$ | async)) {
<button <button
[disabled]="(loadingOnQuantityChangeById$ | async) === item?.id || (loadingOnItemChangeById$ | async) === item?.id" [disabled]="(loadingOnQuantityChangeById$ | async) === item?.id || (loadingOnItemChangeById$ | async) === item?.id"
(click)="onChangeItem()" (click)="onChangeItem()"
*ngIf="!(hasOrderType$ | async)"
> >
<ui-spinner [show]="(loadingOnItemChangeById$ | async) === item?.id">Lieferweg auswählen</ui-spinner> <ui-spinner [show]="(loadingOnItemChangeById$ | async) === item?.id">Lieferweg auswählen</ui-spinner>
</button> </button>
}
@if (canEdit$ | async) {
<button <button
[disabled]="(loadingOnQuantityChangeById$ | async) === item?.id || (loadingOnItemChangeById$ | async) === item?.id" [disabled]="(loadingOnQuantityChangeById$ | async) === item?.id || (loadingOnItemChangeById$ | async) === item?.id"
(click)="onChangeItem()" (click)="onChangeItem()"
*ngIf="canEdit$ | async"
> >
<ui-spinner [show]="(loadingOnItemChangeById$ | async) === item?.id">Lieferweg ändern</ui-spinner> <ui-spinner [show]="(loadingOnItemChangeById$ | async) === item?.id">Lieferweg ändern</ui-spinner>
</button> </button>
}
</div> </div>
}

View File

@@ -24,11 +24,15 @@
></textarea> ></textarea>
<div class="comment-actions py-4"> <div class="comment-actions py-4">
<button type="reset" class="clear pl-4" *ngIf="!disabled && !!value" (click)="clear(); triggerResize()"> @if (!disabled && !!value) {
<button type="reset" class="clear pl-4" (click)="clear(); triggerResize()">
<shared-icon icon="close" [size]="24"></shared-icon> <shared-icon icon="close" [size]="24"></shared-icon>
</button> </button>
}
</div> </div>
</div> </div>
<div *ngIf="!(hasPayer || hasBuyer)" class="text-p3">Zur Info: Sie haben dem Warenkorb noch keinen Kunden hinzugefügt.</div> @if (!(hasPayer || hasBuyer)) {
<div class="text-p3">Zur Info: Sie haben dem Warenkorb noch keinen Kunden hinzugefügt.</div>
}
</div> </div>

View File

@@ -7,66 +7,63 @@
<h1 class="text-center text-h2 my-1 font-bold">Bestellbestätigung</h1> <h1 class="text-center text-h2 my-1 font-bold">Bestellbestätigung</h1>
<p class="text-center text-p1 mb-10">Nachfolgend erhalten Sie die Übersicht Ihrer Bestellung.</p> <p class="text-center text-p1 mb-10">Nachfolgend erhalten Sie die Übersicht Ihrer Bestellung.</p>
<ng-container *ngFor="let displayOrder of displayOrders$ | async; let i = index; let orderLast = last"> @for (displayOrder of displayOrders$ | async; track displayOrder; let i = $index; let orderLast = $last) {
<ng-container *ngIf="i === 0"> @if (i === 0) {
<div class="flex flex-row items-center bg-white shadow-card min-h-[3.3125rem]"> <div class="flex flex-row items-center bg-white shadow-card min-h-[3.3125rem]">
<div class="text-h3 font-bold px-5 py-[0.875rem]"> <div class="text-h3 font-bold px-5 py-[0.875rem]">
{{ displayOrder?.buyer | buyerName }} {{ displayOrder?.buyer | buyerName }}
</div> </div>
</div> </div>
<hr /> <hr />
</ng-container> }
<div class="flex flex-row items-center bg-[#F5F7FA] min-h-[3.3125rem]"> <div class="flex flex-row items-center bg-[#F5F7FA] min-h-[3.3125rem]">
<div class="flex flex-row items-center justify-center px-5 py-[0.875rem]"> <div class="flex flex-row items-center justify-center px-5 py-[0.875rem]">
@if ((displayOrder?.items)[0]?.features?.orderType !== 'Dummy') {
<shared-icon <shared-icon
*ngIf="(displayOrder?.items)[0]?.features?.orderType !== 'Dummy'"
class="mr-2" class="mr-2"
[size]="(displayOrder?.items)[0]?.features?.orderType === 'B2B-Versand' ? 36 : 24" [size]="(displayOrder?.items)[0]?.features?.orderType === 'B2B-Versand' ? 36 : 24"
[icon]="(displayOrder?.items)[0]?.features?.orderType" [icon]="(displayOrder?.items)[0]?.features?.orderType"
></shared-icon> ></shared-icon>
}
<p class="text-p1 font-bold mr-3">{{ (displayOrder?.items)[0]?.features?.orderType }}</p> <p class="text-p1 font-bold mr-3">{{ (displayOrder?.items)[0]?.features?.orderType }}</p>
@if (
(displayOrder?.items)[0]?.features?.orderType === 'Abholung' || (displayOrder?.items)[0]?.features?.orderType === 'Rücklage') {
<div <div
*ngIf="
(displayOrder?.items)[0]?.features?.orderType === 'Abholung' || (displayOrder?.items)[0]?.features?.orderType === 'Rücklage';
else shippingAddress
"
> >
{{ displayOrder.targetBranch?.name }}, {{ displayOrder.targetBranch | branchAddress }} {{ displayOrder.targetBranch?.name }}, {{ displayOrder.targetBranch | branchAddress }}
</div> </div>
<ng-template #shippingAddress> } @else {
{{ displayOrder.shippingAddress | branchAddress }} {{ displayOrder.shippingAddress | branchAddress }}
</ng-template> }
<div *ngIf="(displayOrder?.items)[0]?.features?.orderType === 'Download'"> @if ((displayOrder?.items)[0]?.features?.orderType === 'Download') {
<div>
| {{ displayOrder.buyer?.communicationDetails?.email }} | {{ displayOrder.buyer?.communicationDetails?.email }}
</div> </div>
}
</div> </div>
</div> </div>
<hr /> <hr />
<div class="flex flex-row justify-between items-center"> <div class="flex flex-row justify-between items-center">
<div class="flex flex-col px-5 py-4 bg-white" [attr.data-order-type]="(displayOrder?.items)[0]?.features?.orderType"> <div class="flex flex-col px-5 py-4 bg-white" [attr.data-order-type]="(displayOrder?.items)[0]?.features?.orderType">
<div class="flex flex-row justify-between items-center mb-[0.375rem]"> <div class="flex flex-row justify-between items-center mb-[0.375rem]">
<div class="flex flex-row"> <div class="flex flex-row">
<span class="w-32">Vorgangs-ID</span> <span class="w-32">Vorgangs-ID</span>
<ng-container *ngIf="customer$ | async; let customer"> @if (customer$ | async; as customer) {
@if (customer$ | async; as customer) {
<a <a
data-which="Vorgangs-ID" data-which="Vorgangs-ID"
data-what="link" data-what="link"
*ngIf="customer$ | async; let customer"
class="font-bold text-[#0556B4] no-underline" class="font-bold text-[#0556B4] no-underline"
[routerLink]="['/kunde', processId, 'customer', 'search', customer?.id, 'orders', displayOrder.id]" [routerLink]="['/kunde', processId, 'customer', 'search', customer?.id, 'orders', displayOrder.id]"
[queryParams]="{ main_qs: customer?.customerNumber, filter_customertype: '' }" [queryParams]="{ main_qs: customer?.customerNumber, filter_customertype: '' }"
> >
{{ displayOrder.orderNumber }} {{ displayOrder.orderNumber }}
</a> </a>
</ng-container> }
}
<ui-spinner class="text-[#0556B4] h-4 w-4" [show]="!(customer$ | async)"></ui-spinner> <ui-spinner class="text-[#0556B4] h-4 w-4" [show]="!(customer$ | async)"></ui-spinner>
</div> </div>
</div> </div>
<div class="flex flex-row justify-between items-center"> <div class="flex flex-row justify-between items-center">
<div class="flex flex-row"> <div class="flex flex-row">
<span class="w-32">Bestelldatum</span> <span class="w-32">Bestelldatum</span>
@@ -74,7 +71,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="mr-4"> <div class="mr-4">
<button <button
(click)="expanded[i] = !expanded[i]" (click)="expanded[i] = !expanded[i]"
@@ -93,9 +89,8 @@
</button> </button>
</div> </div>
</div> </div>
@for (order of displayOrder.items; track order; let last = $last) {
<ng-container *ngFor="let order of displayOrder.items; let last = last"> @if (expanded[i]) {
<ng-container *ngIf="expanded[i]">
<div <div
class="page-checkout-summary__items-tablet px-5 pb-[1.875rem] bg-white" class="page-checkout-summary__items-tablet px-5 pb-[1.875rem] bg-white"
[class.page-checkout-summary__items]="isDesktop$ | async" [class.page-checkout-summary__items]="isDesktop$ | async"
@@ -106,7 +101,6 @@
<img class="w-[3.125rem] max-h-20 mr-2" [src]="order.product?.ean | productImage: 195 : 315 : true" /> <img class="w-[3.125rem] max-h-20 mr-2" [src]="order.product?.ean | productImage: 195 : 315 : true" />
</a> </a>
</div> </div>
<div class="page-checkout-summary__items-title whitespace-nowrap overflow-ellipsis overflow-hidden"> <div class="page-checkout-summary__items-title whitespace-nowrap overflow-ellipsis overflow-hidden">
<a <a
class="font-bold no-underline text-[#0556B4]" class="font-bold no-underline text-[#0556B4]"
@@ -116,90 +110,93 @@
{{ order?.product?.name }} {{ order?.product?.name }}
</a> </a>
</div> </div>
@if ((order?.subsetItems)[0]; as subsetItem) {
<div class="page-checkout-summary__items-ssc" *ngIf="(order?.subsetItems)[0]; let subsetItem"> <div class="page-checkout-summary__items-ssc">
<span class="mr-2">{{ subsetItem.supplierName }}</span> <span class="mr-2">{{ subsetItem.supplierName }}</span>
<span *ngIf="subsetItem?.ssc && subsetItem?.sscText" class="font-bold border-l border-black pl-2"> @if (subsetItem?.ssc && subsetItem?.sscText) {
<span class="font-bold border-l border-black pl-2">
{{ subsetItem.ssc }} - {{ subsetItem.sscText }} {{ subsetItem.ssc }} - {{ subsetItem.sscText }}
</span> </span>
}
</div> </div>
}
<div class="page-checkout-summary__items-quantity font-bold justify-self-end"> <div class="page-checkout-summary__items-quantity font-bold justify-self-end">
<span>{{ order.quantity }}x</span> <span>{{ order.quantity }}x</span>
</div> </div>
<div class="page-checkout-summary__items-price font-bold justify-self-end"> <div class="page-checkout-summary__items-price font-bold justify-self-end">
<span>{{ order.price?.value?.value | currency: ' ' }} {{ order.price?.value?.currency }}</span> <span>{{ order.price?.value?.value | currency: ' ' }} {{ order.price?.value?.currency }}</span>
</div> </div>
<div class="page-checkout-summary__items-delivery product-details"> <div class="page-checkout-summary__items-delivery product-details">
<div class="delivery-row" [ngSwitch]="order?.features?.orderType"> <div class="delivery-row">
<ng-container *ngSwitchCase="'Abholung'"> @switch (order?.features?.orderType) {
@case ('Abholung') {
<span class="order-type"> <span class="order-type">
Abholung ab {{ (order?.subsetItems)[0]?.estimatedShippingDate | date }} Abholung ab {{ (order?.subsetItems)[0]?.estimatedShippingDate | date }}
<ng-container [ngTemplateOutlet]="abholfrist" [ngTemplateOutletContext]="{ order: order }"></ng-container> <ng-container [ngTemplateOutlet]="abholfrist" [ngTemplateOutletContext]="{ order: order }"></ng-container>
</span> </span>
</ng-container> }
<ng-container *ngSwitchCase="'Rücklage'"> @case ('Rücklage') {
<span class="order-type"> <span class="order-type">
{{ order?.features?.orderType }} {{ order?.features?.orderType }}
<ng-container [ngTemplateOutlet]="abholfrist" [ngTemplateOutletContext]="{ order: order }"></ng-container> <ng-container [ngTemplateOutlet]="abholfrist" [ngTemplateOutletContext]="{ order: order }"></ng-container>
</span> </span>
</ng-container> }
<ng-container *ngSwitchCase="['Versand', 'B2B-Versand', 'DIG-Versand'].indexOf(order?.features?.orderType) > -1"> @case (['Versand', 'B2B-Versand', 'DIG-Versand'].indexOf(order?.features?.orderType) > -1) {
<ng-container *ngIf="(order?.subsetItems)[0]?.estimatedDelivery; else estimatedShippingDate"> @if ((order?.subsetItems)[0]?.estimatedDelivery) {
<span class="order-type"> <span class="order-type">
Zustellung zwischen Zustellung zwischen
{{ ((order?.subsetItems)[0]?.estimatedDelivery?.start | date: 'EEE, dd.MM.')?.replace('.', '') }} und {{ ((order?.subsetItems)[0]?.estimatedDelivery?.start | date: 'EEE, dd.MM.')?.replace('.', '') }} und
{{ ((order?.subsetItems)[0]?.estimatedDelivery?.stop | date: 'EEE, dd.MM.')?.replace('.', '') }} {{ ((order?.subsetItems)[0]?.estimatedDelivery?.stop | date: 'EEE, dd.MM.')?.replace('.', '') }}
</span> </span>
</ng-container> } @else {
<ng-template #estimatedShippingDate>
<span class="order-type">Versanddatum {{ (order?.subsetItems)[0]?.estimatedShippingDate | date }}</span> <span class="order-type">Versanddatum {{ (order?.subsetItems)[0]?.estimatedShippingDate | date }}</span>
</ng-template> }
</ng-container> }
<ng-container *ngSwitchDefault> @default {
<span class="order-type">{{ order?.features?.orderType }}</span> <span class="order-type">{{ order?.features?.orderType }}</span>
</ng-container> }
}
</div> </div>
</div> </div>
</div> </div>
</ng-container> }
@if (last) {
<hr *ngIf="last" /> <hr />
</ng-container> }
<ng-container *ngIf="orderLast"> }
@if (orderLast) {
<div class="flex flex-row justify-between items-center min-h-[3.3125rem] bg-white px-5 py-4 rounded-b"> <div class="flex flex-row justify-between items-center min-h-[3.3125rem] bg-white px-5 py-4 rounded-b">
<span *ngIf="totalReadingPoints$ | async; let totalReadingPoints" class="text-p2 font-bold"> @if (totalReadingPoints$ | async; as totalReadingPoints) {
<span class="text-p2 font-bold">
{{ totalItemCount$ | async }} Artikel | {{ totalReadingPoints }} Lesepunkte {{ totalItemCount$ | async }} Artikel | {{ totalReadingPoints }} Lesepunkte
</span> </span>
}
<div class="flex flex-row items-center justify-center"> <div class="flex flex-row items-center justify-center">
<div class="text-p1 font-bold flex flex-row items-center"> <div class="text-p1 font-bold flex flex-row items-center">
<div class="mr-1">Gesamtsumme {{ totalPrice$ | async | currency: ' ' }} {{ totalPriceCurrency$ | async }}</div> <div class="mr-1">Gesamtsumme {{ totalPrice$ | async | currency: ' ' }} {{ totalPriceCurrency$ | async }}</div>
</div> </div>
@if ((takeNowOrders$ | async)?.length === 1 && (isB2BCustomer$ | async)) {
<div <div
class="bg-brand text-white font-bold text-p1 outline-none border-none rounded-full px-6 py-3 ml-2" class="bg-brand text-white font-bold text-p1 outline-none border-none rounded-full px-6 py-3 ml-2"
*ngIf="(takeNowOrders$ | async)?.length === 1 && (isB2BCustomer$ | async)"
> >
<button class="cta-goods-out" (click)="navigateToShelfOut()">Zur Warenausgabe</button> <button class="cta-goods-out" (click)="navigateToShelfOut()">Zur Warenausgabe</button>
</div> </div>
}
</div> </div>
</div> </div>
</ng-container> }
</ng-container> }
</div> </div>
</div> </div>
<ng-template #abholfrist let-order="order"> <ng-template #abholfrist let-order="order">
<div *ngIf="!(updatingPreferredPickUpDate$ | async)[(order?.subsetItems)[0].id]" class="inline-flex"> @if (!(updatingPreferredPickUpDate$ | async)[(order?.subsetItems)[0].id]) {
<div class="inline-flex">
<button [uiOverlayTrigger]="deadlineDatepicker" #deadlineDatepickerTrigger="uiOverlayTrigger" class="flex flex-row items-center"> <button [uiOverlayTrigger]="deadlineDatepicker" #deadlineDatepickerTrigger="uiOverlayTrigger" class="flex flex-row items-center">
<span class="mx-[0.625rem] font-normal">bis</span> <span class="mx-[0.625rem] font-normal">bis</span>
<strong class="border-r border-[#AEB7C1] pr-4"> <strong class="border-r border-[#AEB7C1] pr-4">
{{ ((order?.subsetItems)[0]?.preferredPickUpDate | date: 'dd.MM.yy') || 'TT.MM.JJJJ' }} {{ ((order?.subsetItems)[0]?.preferredPickUpDate | date: 'dd.MM.yy') || 'TT.MM.JJJJ' }}
</strong> </strong>
<shared-icon class="text-[#596470] ml-4" [size]="24" icon="isa-calendar"></shared-icon> <shared-icon class="text-[#596470] ml-4" [size]="24" icon="isa-calendar"></shared-icon>
</button> </button>
<ui-datepicker <ui-datepicker
@@ -221,7 +218,10 @@
</div> </div>
</ui-datepicker> </ui-datepicker>
</div> </div>
<div class="fetching" *ngIf="!!(updatingPreferredPickUpDate$ | async)[(order?.subsetItems)[0].id]"></div> }
@if (!!(updatingPreferredPickUpDate$ | async)[(order?.subsetItems)[0].id]) {
<div class="fetching"></div>
}
</ng-template> </ng-template>
<div class="relative"> <div class="relative">
@@ -236,13 +236,14 @@
<ui-spinner class="min-h-4 min-w-4" [show]="isPrinting$ | async">Bestellbestätigung drucken</ui-spinner> <ui-spinner class="min-h-4 min-w-4" [show]="isPrinting$ | async">Bestellbestätigung drucken</ui-spinner>
</button> </button>
@if (hasAbholung$ | async) {
<button <button
*ngIf="hasAbholung$ | async"
type="button" type="button"
class="px-6 py-2 rounded-full border-2 border-solid border-brand text-brand bg-white font-bold text-lg whitespace-nowrap h-14" class="px-6 py-2 rounded-full border-2 border-solid border-brand text-brand bg-white font-bold text-lg whitespace-nowrap h-14"
(click)="sendOrderConfirmation()" (click)="sendOrderConfirmation()"
> >
Bestellbestätigung senden Bestellbestätigung senden
</button> </button>
}
</div> </div>
</div> </div>

View File

@@ -15,7 +15,11 @@ import { CrmCustomerService } from '@domain/crm';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { DomainOmsService } from '@domain/oms'; import { DomainOmsService } from '@domain/oms';
import { DomainCatalogService } from '@domain/catalog'; import { DomainCatalogService } from '@domain/catalog';
import { DisplayOrderDTO, DisplayOrderItemDTO, DisplayOrderItemSubsetDTO } from '@generated/swagger/oms-api'; import {
DisplayOrderDTO,
DisplayOrderItemDTO,
DisplayOrderItemSubsetDTO,
} from '@generated/swagger/oms-api';
import { BreadcrumbService } from '@core/breadcrumb'; import { BreadcrumbService } from '@core/breadcrumb';
import { ApplicationService } from '@core/application'; import { ApplicationService } from '@core/application';
import { DomainPrinterService } from '@domain/printer'; import { DomainPrinterService } from '@domain/printer';
@@ -49,45 +53,73 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
private _onDestroy$ = new Subject<void>(); private _onDestroy$ = new Subject<void>();
processId = Date.now(); processId = Date.now();
selectedDate = this.dateAdapter.today(); selectedDate = this.dateAdapter.today();
minDateDatepicker = this.dateAdapter.addCalendarDays(this.dateAdapter.today(), -1); minDateDatepicker = this.dateAdapter.addCalendarDays(
this.dateAdapter.today(),
-1,
);
updatingPreferredPickUpDate$ = new BehaviorSubject<Record<string, string>>({}); updatingPreferredPickUpDate$ = new BehaviorSubject<Record<string, string>>(
{},
);
displayOrders$ = combineLatest([this.domainCheckoutService.getOrders(), this._route.params]).pipe( displayOrders$ = combineLatest([
this.domainCheckoutService.getOrders(),
this._route.params,
]).pipe(
map(([orders, params]) => { map(([orders, params]) => {
let filteredOrders: DisplayOrderDTO[] = []; let filteredOrders: DisplayOrderDTO[] = [];
if (params?.orderIds) { if (params?.orderIds) {
const orderIds: string[] = params.orderIds.split(','); const orderIds: string[] = params.orderIds.split(',');
filteredOrders = orders.filter((order) => orderIds.find((id) => Number(id) === order.id)); filteredOrders = orders.filter((order) =>
orderIds.find((id) => Number(id) === order.id),
);
} else { } else {
return filteredOrders; return filteredOrders;
} }
// Ticket #4228 Für die korrekte Gruppierung der Items bei gleichem Bestellziel (Aufsplitten von Abholung und Rücklage) // Ticket #4228 Für die korrekte Gruppierung der Items bei gleichem Bestellziel (Aufsplitten von Abholung und Rücklage)
const ordersWithMultipleFeatures = filteredOrders.filter((order) => const ordersWithMultipleFeatures = filteredOrders.filter((order) =>
order.items.find((item) => item.features.orderType !== order.features.orderType), order.items.find(
(item) => item.features.orderType !== order.features.orderType,
),
); );
if (ordersWithMultipleFeatures) { if (ordersWithMultipleFeatures) {
for (let orderWithMultipleFeatures of ordersWithMultipleFeatures) { for (let orderWithMultipleFeatures of ordersWithMultipleFeatures) {
if (orderWithMultipleFeatures?.items?.length > 1) { if (orderWithMultipleFeatures?.items?.length > 1) {
const itemsWithOrderFeature = orderWithMultipleFeatures.items.filter( const itemsWithOrderFeature =
(item) => item.features.orderType === orderWithMultipleFeatures.features.orderType, orderWithMultipleFeatures.items.filter(
(item) =>
item.features.orderType ===
orderWithMultipleFeatures.features.orderType,
); );
const itemsWithDifferentOrderFeature = orderWithMultipleFeatures.items.filter( const itemsWithDifferentOrderFeature =
(item) => item.features.orderType !== orderWithMultipleFeatures.features.orderType, orderWithMultipleFeatures.items.filter(
(item) =>
item.features.orderType !==
orderWithMultipleFeatures.features.orderType,
); );
filteredOrders = [...filteredOrders.filter((order) => order.id !== orderWithMultipleFeatures.id)]; filteredOrders = [
...filteredOrders.filter(
(order) => order.id !== orderWithMultipleFeatures.id,
),
];
if (itemsWithOrderFeature?.length > 0) { if (itemsWithOrderFeature?.length > 0) {
filteredOrders = [...filteredOrders, { ...orderWithMultipleFeatures, items: itemsWithOrderFeature }]; filteredOrders = [
...filteredOrders,
{ ...orderWithMultipleFeatures, items: itemsWithOrderFeature },
];
} }
if (itemsWithDifferentOrderFeature?.length > 0) { if (itemsWithDifferentOrderFeature?.length > 0) {
filteredOrders = [ filteredOrders = [
...filteredOrders, ...filteredOrders,
{ ...orderWithMultipleFeatures, items: itemsWithDifferentOrderFeature }, {
...orderWithMultipleFeatures,
items: itemsWithDifferentOrderFeature,
},
]; ];
} }
} }
@@ -97,7 +129,9 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
return filteredOrders?.map((order) => { return filteredOrders?.map((order) => {
return { return {
...order, ...order,
items: [...order.items]?.sort((a, b) => a.product?.name.localeCompare(b.product?.name)), items: [...order.items]?.sort((a, b) =>
a.product?.name.localeCompare(b.product?.name),
),
}; };
}); });
}), }),
@@ -105,14 +139,23 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
); );
hasAbholung$ = this.displayOrders$.pipe( hasAbholung$ = this.displayOrders$.pipe(
map((displayOrders) => displayOrders.filter((order) => order.features?.orderType === 'Abholung')?.length > 0), map(
(displayOrders) =>
displayOrders.filter(
(order) => order.features?.orderType === 'Abholung',
)?.length > 0,
),
); );
totalItemCount$ = this.displayOrders$.pipe( totalItemCount$ = this.displayOrders$.pipe(
map((displayOrders) => map((displayOrders) =>
displayOrders.reduce( displayOrders.reduce(
(total, displayOrder) => (total, displayOrder) =>
total + displayOrder?.items?.reduce((subTotal, order) => subTotal + order?.quantity, 0), total +
displayOrder?.items?.reduce(
(subTotal, order) => subTotal + order?.quantity,
0,
),
0, 0,
), ),
), ),
@@ -121,7 +164,10 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
totalReadingPoints$ = this.displayOrders$.pipe( totalReadingPoints$ = this.displayOrders$.pipe(
switchMap((displayOrders) => { switchMap((displayOrders) => {
const items = displayOrders const items = displayOrders
.reduce<DisplayOrderItemDTO[]>((items, order) => [...items, ...order.items], []) .reduce<DisplayOrderItemDTO[]>(
(items, order) => [...items, ...order.items],
[],
)
.map((i) => { .map((i) => {
if (i?.product?.catalogProductNumber) { if (i?.product?.catalogProductNumber) {
return { return {
@@ -135,7 +181,14 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
if (items.length !== 0) { if (items.length !== 0) {
return this.domainCatalogService return this.domainCatalogService
.getPromotionPoints({ items }) .getPromotionPoints({ items })
.pipe(map((response) => Object.values(response.result).reduce((sum, points) => sum + points, 0))); .pipe(
map((response) =>
Object.values(response.result).reduce(
(sum, points) => sum + points,
0,
),
),
);
} else { } else {
return NEVER; return NEVER;
} }
@@ -147,7 +200,11 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
displayOrders.reduce( displayOrders.reduce(
(total, displayOrder) => (total, displayOrder) =>
total + total +
displayOrder?.items?.reduce((subTotal, order) => subTotal + order?.price?.value?.value * order.quantity, 0), displayOrder?.items?.reduce(
(subTotal, order) =>
subTotal + order?.price?.value?.value * order.quantity,
0,
),
0, 0,
), ),
), ),
@@ -162,22 +219,33 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
containsDeliveryOrder$ = this.displayOrders$.pipe( containsDeliveryOrder$ = this.displayOrders$.pipe(
map( map(
(displayOrders) => (displayOrders) =>
displayOrders.filter((o) => ['Versand', 'B2B-Versand', 'DIG-Versand'].indexOf(o.features?.orderType) > -1) displayOrders.filter(
?.length > 0, (o) =>
['Versand', 'B2B-Versand', 'DIG-Versand'].indexOf(
o.features?.orderType,
) > -1,
)?.length > 0,
), ),
); );
customer$ = this.displayOrders$.pipe( customer$ = this.displayOrders$.pipe(
switchMap((o) => this.customerService.getCustomers(o[0].buyerNumber, { take: 5 })), switchMap((o) =>
this.customerService.getCustomers(o[0].buyerNumber, { take: 5 }),
),
map((customers) => customers.result[0]), map((customers) => customers.result[0]),
shareReplay(), shareReplay(),
); );
isB2BCustomer$ = this.customer$.pipe(map((customer) => customer?.features?.find((f) => f.key === 'b2b') != null)); isB2BCustomer$ = this.customer$.pipe(
map((customer) => customer?.features?.find((f) => f.key === 'b2b') != null),
);
takeNowOrders$ = this.displayOrders$.pipe( takeNowOrders$ = this.displayOrders$.pipe(
map((displayOrders) => map((displayOrders) =>
displayOrders.filter((o) => o.items.find((oi) => oi.features?.orderType === 'Rücklage') != null), displayOrders.filter(
(o) =>
o.items.find((oi) => oi.features?.orderType === 'Rücklage') != null,
),
), ),
); );
@@ -210,7 +278,9 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
private _cdr: ChangeDetectorRef, private _cdr: ChangeDetectorRef,
) { ) {
this.breadcrumb this.breadcrumb
.getBreadcrumbsByKeyAndTags$(this.applicationService.activatedProcessId, ['checkout']) .getBreadcrumbsByKeyAndTags$(this.applicationService.activatedProcessId, [
'checkout',
])
.pipe(first()) .pipe(first())
.subscribe(async (crumbs) => { .subscribe(async (crumbs) => {
for await (const crumb of crumbs) { for await (const crumb of crumbs) {
@@ -264,7 +334,8 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
getProductSearchDetailsQueryParams(item: DisplayOrderItemDTO) { getProductSearchDetailsQueryParams(item: DisplayOrderItemDTO) {
return { return {
main_qs: item?.product?.ean, main_qs: item?.product?.ean,
filter_format: item?.features?.orderType === 'Download' ? 'eb;dl' : undefined, filter_format:
item?.features?.orderType === 'Download' ? 'eb;dl' : undefined,
}; };
} }
@@ -274,9 +345,14 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
try { try {
const items = item ? [item] : await this.getAllOrderItems(); const items = item ? [item] : await this.getAllOrderItems();
const subsetItems = items const subsetItems = items
.filter((item) => ['Rücklage', 'Abholung'].includes(item.features.orderType)) .filter((item) =>
['Rücklage', 'Abholung'].includes(item.features.orderType),
)
// .flatMap((item) => item.subsetItems); // .flatMap((item) => item.subsetItems);
.reduce<DisplayOrderItemSubsetDTO[]>((acc, item) => [...acc, ...item.subsetItems], []); .reduce<DisplayOrderItemSubsetDTO[]>(
(acc, item) => [...acc, ...item.subsetItems],
[],
);
subsetItems.forEach((item) => (data[`${item.id}`] = date?.toISOString())); subsetItems.forEach((item) => (data[`${item.id}`] = date?.toISOString()));
try { try {
@@ -310,7 +386,10 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
async getAllOrderItems() { async getAllOrderItems() {
const orders = await this.displayOrders$.pipe(first()).toPromise(); const orders = await this.displayOrders$.pipe(first()).toPromise();
return orders.reduce<DisplayOrderItemDTO[]>((agg, order) => [...agg, ...order.items], []); return orders.reduce<DisplayOrderItemDTO[]>(
(agg, order) => [...agg, ...order.items],
[],
);
} }
async updateDisplayOrderItem(item: DisplayOrderItemDTO) { async updateDisplayOrderItem(item: DisplayOrderItemDTO) {
@@ -322,9 +401,16 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
if (takeNowOrders.length != 1) return; if (takeNowOrders.length != 1) return;
try { try {
await this.router.navigate(this._shelfOutNavigationService.listRoute({ processId: Date.now() }).path, { await this.router.navigate(
queryParams: { main_qs: takeNowOrders[0].orderNumber, filter_supplier_id: '16' }, this._shelfOutNavigationService.listRoute({ processId: Date.now() })
}); .path,
{
queryParams: {
main_qs: takeNowOrders[0].orderNumber,
filter_supplier_id: '16',
},
},
);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
@@ -344,7 +430,8 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
.pipe( .pipe(
first(), first(),
map((printers) => { map((printers) => {
if (Array.isArray(printers)) return printers.find((printer) => printer.selected === true); if (Array.isArray(printers))
return printers.find((printer) => printer.selected === true);
}), }),
) )
.toPromise(); .toPromise();
@@ -362,10 +449,16 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
const result = await this.domainPrinterService const result = await this.domainPrinterService
.printOrder({ orderIds: orders.map((o) => o.id), printer }) .printOrder({ orderIds: orders.map((o) => o.id), printer })
.toPromise(); .toPromise();
this._toaster.open({ type: 'success', message: 'Bestellbestätigung wurde gedruckt' }); this._toaster.open({
type: 'success',
message: 'Bestellbestätigung wurde gedruckt',
});
return result; return result;
} catch (error) { } catch (error) {
this._toaster.open({ type: 'danger', message: 'Fehler beim Drucken der Bestellbestätigung' }); this._toaster.open({
type: 'danger',
message: 'Fehler beim Drucken der Bestellbestätigung',
});
} finally { } finally {
this.isPrinting$.next(false); this.isPrinting$.next(false);
} }
@@ -381,12 +474,21 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
} else { } else {
try { try {
const result = await this.domainPrinterService const result = await this.domainPrinterService
.printOrder({ orderIds: orders.map((o) => o.id), printer: selectedPrinter.key }) .printOrder({
orderIds: orders.map((o) => o.id),
printer: selectedPrinter.key,
})
.toPromise(); .toPromise();
this._toaster.open({ type: 'success', message: 'Bestellbestätigung wurde gedruckt' }); this._toaster.open({
type: 'success',
message: 'Bestellbestätigung wurde gedruckt',
});
return result; return result;
} catch (error) { } catch (error) {
this._toaster.open({ type: 'danger', message: 'Fehler beim Drucken der Bestellbestätigung' }); this._toaster.open({
type: 'danger',
message: 'Fehler beim Drucken der Bestellbestätigung',
});
} finally { } finally {
this.isPrinting$.next(false); this.isPrinting$.next(false);
} }

View File

@@ -1,35 +1,35 @@
<ng-container *ngIf="orderItem$ | async; let orderItem"> @if (orderItem$ | async; as orderItem) {
<div #features class="page-customer-order-details-item__features"> <div #features class="page-customer-order-details-item__features">
<ng-container *ngIf="orderItem?.features?.prebooked"> @if (orderItem?.features?.prebooked) {
<img [uiOverlayTrigger]="prebookedTooltip" src="/assets/images/tag_icon_preorder.svg" [alt]="orderItem?.features?.prebooked" /> <img [uiOverlayTrigger]="prebookedTooltip" src="/assets/images/tag_icon_preorder.svg" [alt]="orderItem?.features?.prebooked" />
<ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #prebookedTooltip [closeable]="true"> <ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #prebookedTooltip [closeable]="true">
Artikel wird für Sie vorgemerkt. Artikel wird für Sie vorgemerkt.
</ui-tooltip> </ui-tooltip>
</ng-container> }
<ng-container *ngIf="notificationsSent$ | async; let notificationsSent"> @if (notificationsSent$ | async; as notificationsSent) {
<ng-container *ngIf="notificationsSent?.NOTIFICATION_EMAIL"> @if (notificationsSent?.NOTIFICATION_EMAIL) {
<img [uiOverlayTrigger]="emailTooltip" src="/assets/images/email_bookmark.svg" /> <img [uiOverlayTrigger]="emailTooltip" src="/assets/images/email_bookmark.svg" />
<ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #emailTooltip [closeable]="true"> <ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #emailTooltip [closeable]="true">
Per E-Mail benachrichtigt Per E-Mail benachrichtigt
<br /> <br />
<ng-container *ngFor="let notification of notificationsSent?.NOTIFICATION_EMAIL"> @for (notification of notificationsSent?.NOTIFICATION_EMAIL; track notification) {
{{ notification | date: 'dd.MM.yyyy | HH:mm' }} Uhr {{ notification | date: 'dd.MM.yyyy | HH:mm' }} Uhr
<br /> <br />
</ng-container> }
</ui-tooltip> </ui-tooltip>
</ng-container> }
<ng-container *ngIf="notificationsSent?.NOTIFICATION_SMS"> @if (notificationsSent?.NOTIFICATION_SMS) {
<img [uiOverlayTrigger]="smsTooltip" src="/assets/images/sms_bookmark.svg" /> <img [uiOverlayTrigger]="smsTooltip" src="/assets/images/sms_bookmark.svg" />
<ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #smsTooltip [closeable]="true"> <ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #smsTooltip [closeable]="true">
Per SMS benachrichtigt Per SMS benachrichtigt
<br /> <br />
<ng-container *ngFor="let notification of notificationsSent?.NOTIFICATION_SMS"> @for (notification of notificationsSent?.NOTIFICATION_SMS; track notification) {
{{ notification | date: 'dd.MM.yyyy | HH:mm' }} Uhr {{ notification | date: 'dd.MM.yyyy | HH:mm' }} Uhr
<br /> <br />
</ng-container> }
</ui-tooltip> </ui-tooltip>
</ng-container> }
</ng-container> }
</div> </div>
<div class="page-customer-order-details-item__item-container"> <div class="page-customer-order-details-item__item-container">
<div class="page-customer-order-details-item__thumbnail"> <div class="page-customer-order-details-item__thumbnail">
@@ -48,163 +48,184 @@
</h3> </h3>
<div class="history-wrapper flex flex-col items-end justify-center"> <div class="history-wrapper flex flex-col items-end justify-center">
<button class="cta-history text-p1" (click)="historyClick.emit(orderItem)">Historie</button> <button class="cta-history text-p1" (click)="historyClick.emit(orderItem)">Historie</button>
@if (selectable$ | async) {
<input <input
*ngIf="selectable$ | async"
[ngModel]="selected$ | async" [ngModel]="selected$ | async"
(ngModelChange)="setSelected($event)" (ngModelChange)="setSelected($event)"
class="isa-select-bullet mt-4" class="isa-select-bullet mt-4"
type="checkbox" type="checkbox"
/> />
}
</div> </div>
</div> </div>
<div class="detail"> <div class="detail">
<div class="label">Menge</div> <div class="label">Menge</div>
<div class="value"> <div class="value">
<ng-container *ngIf="!(canChangeQuantity$ | async)">{{ orderItem?.quantity }}x</ng-container> @if (!(canChangeQuantity$ | async)) {
{{ orderItem?.quantity }}x
}
@if (canChangeQuantity$ | async) {
<ui-quantity-dropdown <ui-quantity-dropdown
*ngIf="canChangeQuantity$ | async"
[showTrash]="false" [showTrash]="false"
[range]="orderItem?.quantity" [range]="orderItem?.quantity"
[(ngModel)]="quantity" [(ngModel)]="quantity"
[showSpinner]="false" [showSpinner]="false"
></ui-quantity-dropdown> ></ui-quantity-dropdown>
}
<span class="overall-quantity">(von {{ orderItem?.overallQuantity }})</span> <span class="overall-quantity">(von {{ orderItem?.overallQuantity }})</span>
</div> </div>
</div> </div>
<div class="detail" *ngIf="!!orderItem.product?.formatDetail"> @if (!!orderItem.product?.formatDetail) {
<div class="detail">
<div class="label">Format</div> <div class="label">Format</div>
<div class="value"> <div class="value">
@if (orderItem?.product?.format && orderItem?.product?.format !== 'UNKNOWN') {
<img <img
*ngIf="orderItem?.product?.format && orderItem?.product?.format !== 'UNKNOWN'"
class="format-icon" class="format-icon"
[src]="'/assets/images/Icon_' + orderItem.product?.format + '.svg'" [src]="'/assets/images/Icon_' + orderItem.product?.format + '.svg'"
alt="format icon" alt="format icon"
/> />
}
<span>{{ orderItem.product?.formatDetail }}</span> <span>{{ orderItem.product?.formatDetail }}</span>
</div> </div>
</div> </div>
<div class="detail" *ngIf="!!orderItem.product?.ean"> }
@if (!!orderItem.product?.ean) {
<div class="detail">
<div class="label">ISBN/EAN</div> <div class="label">ISBN/EAN</div>
<div class="value">{{ orderItem.product?.ean }}</div> <div class="value">{{ orderItem.product?.ean }}</div>
</div> </div>
<div class="detail" *ngIf="orderItem.price !== undefined"> }
@if (orderItem.price !== undefined) {
<div class="detail">
<div class="label">Preis</div> <div class="label">Preis</div>
<div class="value">{{ orderItem.price | currency: 'EUR' }}</div> <div class="value">{{ orderItem.price | currency: 'EUR' }}</div>
</div> </div>
<div class="detail" *ngIf="!!orderItem.retailPrice?.vat?.inPercent"> }
@if (!!orderItem.retailPrice?.vat?.inPercent) {
<div class="detail">
<div class="label">MwSt</div> <div class="label">MwSt</div>
<div class="value">{{ orderItem.retailPrice?.vat?.inPercent }}%</div> <div class="value">{{ orderItem.retailPrice?.vat?.inPercent }}%</div>
</div> </div>
}
<hr class="border-[#EDEFF0] border-t-2 my-4" /> <hr class="border-[#EDEFF0] border-t-2 my-4" />
@if (orderItem.supplier) {
<div class="detail" *ngIf="orderItem.supplier"> <div class="detail">
<div class="label">Lieferant</div> <div class="label">Lieferant</div>
<div class="value">{{ orderItem.supplier }}</div> <div class="value">{{ orderItem.supplier }}</div>
</div> </div>
<div class="detail" *ngIf="!!orderItem.ssc || !!orderItem.sscText"> }
@if (!!orderItem.ssc || !!orderItem.sscText) {
<div class="detail">
<div class="label">Meldenummer</div> <div class="label">Meldenummer</div>
<div class="value">{{ orderItem.ssc }} - {{ orderItem.sscText }}</div> <div class="value">{{ orderItem.ssc }} - {{ orderItem.sscText }}</div>
</div> </div>
<div class="detail" *ngIf="!!orderItem.targetBranch"> }
@if (!!orderItem.targetBranch) {
<div class="detail">
<div class="label">Zielfiliale</div> <div class="label">Zielfiliale</div>
<div class="value">{{ orderItem.targetBranch }}</div> <div class="value">{{ orderItem.targetBranch }}</div>
</div> </div>
}
<div class="detail"> <div class="detail">
<div class="label"> <div class="label">
<ng-container @if (
*ngIf="
orderItemFeature(orderItem) === 'Versand' || orderItemFeature(orderItem) === 'Versand' ||
orderItemFeature(orderItem) === 'B2B-Versand' || orderItemFeature(orderItem) === 'B2B-Versand' ||
orderItemFeature(orderItem) === 'DIG-Versand' orderItemFeature(orderItem) === 'DIG-Versand'
" ) {
>
{{ orderItem?.estimatedDelivery ? 'Lieferung zwischen' : 'Lieferung ab' }} {{ orderItem?.estimatedDelivery ? 'Lieferung zwischen' : 'Lieferung ab' }}
</ng-container> }
<ng-container *ngIf="orderItemFeature(orderItem) === 'Abholung' || orderItemFeature(orderItem) === 'Rücklage'"> @if (orderItemFeature(orderItem) === 'Abholung' || orderItemFeature(orderItem) === 'Rücklage') {
Abholung ab Abholung ab
</ng-container> }
</div> </div>
@if (!!orderItem?.estimatedDelivery || !!orderItem?.estimatedShippingDate) {
<ng-container *ngIf="!!orderItem?.estimatedDelivery || !!orderItem?.estimatedShippingDate">
<div class="value bg-[#D8DFE5] rounded w-max px-2"> <div class="value bg-[#D8DFE5] rounded w-max px-2">
<ng-container *ngIf="!!orderItem?.estimatedDelivery; else estimatedShippingDate"> @if (!!orderItem?.estimatedDelivery) {
{{ orderItem?.estimatedDelivery?.start | date: 'dd.MM.yy' }} und {{ orderItem?.estimatedDelivery?.start | date: 'dd.MM.yy' }} und
{{ orderItem?.estimatedDelivery?.stop | date: 'dd.MM.yy' }} {{ orderItem?.estimatedDelivery?.stop | date: 'dd.MM.yy' }}
</ng-container> } @else {
</div> @if (!!orderItem?.estimatedShippingDate) {
</ng-container>
<ng-template #estimatedShippingDate>
<ng-container *ngIf="!!orderItem?.estimatedShippingDate">
{{ orderItem?.estimatedShippingDate | date: 'dd.MM.yy' }} {{ orderItem?.estimatedShippingDate | date: 'dd.MM.yy' }}
</ng-container> }
</ng-template> }
</div> </div>
<div class="page-customer-order-details-item__tracking-details" *ngIf="getOrderItemTrackingData(orderItem); let trackingData"> }
</div>
@if (getOrderItemTrackingData(orderItem); as trackingData) {
<div class="page-customer-order-details-item__tracking-details">
<div class="label">{{ trackingData.length > 1 ? 'Sendungsnummern' : 'Sendungsnummer' }}</div> <div class="label">{{ trackingData.length > 1 ? 'Sendungsnummern' : 'Sendungsnummer' }}</div>
<ng-container *ngFor="let tracking of trackingData"> @for (tracking of trackingData; track tracking) {
<ng-container *ngIf="tracking.trackingProvider === 'DHL' && !isNative; else noTrackingLink"> @if (tracking.trackingProvider === 'DHL' && !isNative) {
<a class="value text-[#0556B4]" [href]="getTrackingNumberLink(tracking.trackingNumber)" target="_blank"> <a class="value text-[#0556B4]" [href]="getTrackingNumberLink(tracking.trackingNumber)" target="_blank">
{{ tracking.trackingProvider }}: {{ tracking.trackingNumber }} {{ tracking.trackingProvider }}: {{ tracking.trackingNumber }}
</a> </a>
</ng-container> } @else {
<ng-template #noTrackingLink>
<p class="value">{{ tracking.trackingProvider }}: {{ tracking.trackingNumber }}</p> <p class="value">{{ tracking.trackingProvider }}: {{ tracking.trackingNumber }}</p>
</ng-template> }
</ng-container> }
</div> </div>
}
<hr class="border-[#EDEFF0] border-t-2 my-4" /> <hr class="border-[#EDEFF0] border-t-2 my-4" />
@if (!!orderItem?.compartmentCode) {
<div class="detail" *ngIf="!!orderItem?.compartmentCode"> <div class="detail">
<div class="label">Abholfachnr.</div> <div class="label">Abholfachnr.</div>
<div class="value">{{ orderItem?.compartmentCode }}</div> <div class="value">{{ orderItem?.compartmentCode }}</div>
</div> </div>
}
<div class="detail"> <div class="detail">
<div class="label">Vormerker</div> <div class="label">Vormerker</div>
<div class="value">{{ orderItem.isPrebooked ? 'Ja' : 'Nein' }}</div> <div class="value">{{ orderItem.isPrebooked ? 'Ja' : 'Nein' }}</div>
</div> </div>
<hr class="border-[#EDEFF0] border-t-2 my-4" /> <hr class="border-[#EDEFF0] border-t-2 my-4" />
@if (!!orderItem.paymentProcessing) {
<div class="detail" *ngIf="!!orderItem.paymentProcessing"> <div class="detail">
<div class="label">Zahlungsweg</div> <div class="label">Zahlungsweg</div>
<div class="value">{{ orderItem.paymentProcessing || '-' }}</div> <div class="value">{{ orderItem.paymentProcessing || '-' }}</div>
</div> </div>
<div class="detail" *ngIf="!!orderItem.paymentType"> }
@if (!!orderItem.paymentType) {
<div class="detail">
<div class="label">Zahlungsart</div> <div class="label">Zahlungsart</div>
<div class="value">{{ orderItem.paymentType | paymentType }}</div> <div class="value">{{ orderItem.paymentType | paymentType }}</div>
</div> </div>
}
<h4 class="receipt-header" *ngIf="receiptCount$ | async; let count"> @if (receiptCount$ | async; as count) {
<h4 class="receipt-header">
{{ count > 1 ? 'Belege' : 'Beleg' }} {{ count > 1 ? 'Belege' : 'Beleg' }}
</h4> </h4>
<ng-container *ngFor="let receipt of receipts$ | async"> }
<div class="detail" *ngIf="!!receipt?.receiptNumber"> @for (receipt of receipts$ | async; track receipt) {
@if (!!receipt?.receiptNumber) {
<div class="detail">
<div class="label">Belegnummer</div> <div class="label">Belegnummer</div>
<div class="value">{{ receipt?.receiptNumber }}</div> <div class="value">{{ receipt?.receiptNumber }}</div>
</div> </div>
<div class="detail" *ngIf="!!receipt?.printedDate"> }
@if (!!receipt?.printedDate) {
<div class="detail">
<div class="label">Erstellt am</div> <div class="label">Erstellt am</div>
<div class="value">{{ receipt?.printedDate | date: 'dd.MM.yy | HH:mm' }} Uhr</div> <div class="value">{{ receipt?.printedDate | date: 'dd.MM.yy | HH:mm' }} Uhr</div>
</div> </div>
<div class="detail" *ngIf="!!receipt?.receiptText"> }
@if (!!receipt?.receiptText) {
<div class="detail">
<div class="label">Rechnungstext</div> <div class="label">Rechnungstext</div>
<div class="value">{{ receipt?.receiptText || '-' }}</div> <div class="value">{{ receipt?.receiptText || '-' }}</div>
</div> </div>
<div class="detail" *ngIf="!!receipt?.receiptType"> }
@if (!!receipt?.receiptType) {
<div class="detail">
<div class="label">Belegart</div> <div class="label">Belegart</div>
<div class="value"> <div class="value">
{{ receipt?.receiptType === 1 ? 'Lieferschein' : receipt?.receiptType === 64 ? 'Zahlungsbeleg' : '-' }} {{ receipt?.receiptType === 1 ? 'Lieferschein' : receipt?.receiptType === 64 ? 'Zahlungsbeleg' : '-' }}
</div> </div>
</div> </div>
</ng-container> }
}
<div class="page-customer-order-details-item__comment flex flex-col items-start mt-[1.625rem]"> <div class="page-customer-order-details-item__comment flex flex-col items-start mt-[1.625rem]">
<div class="label mb-[0.375rem]">Anmerkung</div> <div class="label mb-[0.375rem]">Anmerkung</div>
<div class="flex flex-row w-full"> <div class="flex flex-row w-full">
<textarea <textarea
matInput matInput
@@ -222,27 +243,28 @@
[formControl]="specialCommentControl" [formControl]="specialCommentControl"
[class.inactive]="!specialCommentControl.dirty" [class.inactive]="!specialCommentControl.dirty"
></textarea> ></textarea>
<div class="comment-actions"> <div class="comment-actions">
@if (!!specialCommentControl.value?.length) {
<button <button
type="reset" type="reset"
class="clear" class="clear"
*ngIf="!!specialCommentControl.value?.length"
(click)="specialCommentControl.setValue(''); saveSpecialComment(); triggerResize()" (click)="specialCommentControl.setValue(''); saveSpecialComment(); triggerResize()"
> >
<shared-icon icon="close" [size]="24"></shared-icon> <shared-icon icon="close" [size]="24"></shared-icon>
</button> </button>
}
@if (specialCommentControl?.enabled && specialCommentControl.dirty) {
<button <button
class="cta-save" class="cta-save"
type="submit" type="submit"
*ngIf="specialCommentControl?.enabled && specialCommentControl.dirty"
(click)="saveSpecialComment()" (click)="saveSpecialComment()"
> >
Speichern Speichern
</button> </button>
}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</ng-container> }

View File

@@ -1,13 +1,14 @@
<div class="page-customer-order-details-tags__wrapper"> <div class="page-customer-order-details-tags__wrapper">
@for (tag of defaultTags; track tag) {
<button <button
class="page-customer-order-details-tags__tag" class="page-customer-order-details-tags__tag"
type="button" type="button"
[class.selected]="tag === (selected$ | async) && !inputFocus.focused" [class.selected]="tag === (selected$ | async) && !inputFocus.focused"
*ngFor="let tag of defaultTags"
(click)="setCompartmentInfo(tag)" (click)="setCompartmentInfo(tag)"
> >
{{ tag }} {{ tag }}
</button> </button>
}
<button <button
(click)="inputFocus.focus()" (click)="inputFocus.focus()"
type="button" type="button"

View File

@@ -1,4 +1,4 @@
import { NgFor, AsyncPipe } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, forwardRef } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, forwardRef } from '@angular/core';
import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import { UiCommonModule } from '@ui/common'; import { UiCommonModule } from '@ui/common';
@@ -14,7 +14,7 @@ import { PickUpShelfDetailsTagsComponent } from '../../../pickup-shelf/shared/pi
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'page-pickup-shelf-details-tags' }, host: { class: 'page-pickup-shelf-details-tags' },
standalone: true, standalone: true,
imports: [NgFor, UiCommonModule, FormsModule, AsyncPipe, MatomoModule], imports: [UiCommonModule, FormsModule, AsyncPipe, MatomoModule],
providers: [ providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => PickUpShelfDetailsTagsComponent), multi: true }, { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => PickUpShelfDetailsTagsComponent), multi: true },
], ],

View File

@@ -4,21 +4,24 @@
(handleAction)="handleAction($event)" (handleAction)="handleAction($event)"
[order]="order$ | async" [order]="order$ | async"
></page-customer-order-details-header> ></page-customer-order-details-header>
@for (item of items$ | async; track item) {
<page-customer-order-details-item <page-customer-order-details-item
class="mb-px-2" class="mb-px-2"
*ngFor="let item of items$ | async"
[orderItem]="item" [orderItem]="item"
[order]="order$ | async" [order]="order$ | async"
[selected]="true" [selected]="true"
(historyClick)="navigateToHistoryPage($event)" (historyClick)="navigateToHistoryPage($event)"
(specialCommentChanged)="onSpecialCommentChange()" (specialCommentChanged)="onSpecialCommentChange()"
></page-customer-order-details-item> ></page-customer-order-details-item>
<page-customer-order-details-tags *ngIf="showTagsComponent$ | async"></page-customer-order-details-tags> }
@if (showTagsComponent$ | async) {
<page-customer-order-details-tags></page-customer-order-details-tags>
}
</div> </div>
<div class="page-customer-order-details__action-wrapper"> <div class="page-customer-order-details__action-wrapper">
@if (addToPreviousCompartmentAction$ | async; as action) {
<button <button
[disabled]="addToPreviousCompartmentActionDisabled$ | async" [disabled]="addToPreviousCompartmentActionDisabled$ | async"
*ngIf="addToPreviousCompartmentAction$ | async; let action"
class="cta-action shadow-action" class="cta-action shadow-action"
[class.cta-action-primary]="action.selected" [class.cta-action-primary]="action.selected"
[class.cta-action-secondary]="!action.selected" [class.cta-action-secondary]="!action.selected"
@@ -28,15 +31,17 @@
{{ latestCompartmentCode$ | async | addToPreviousCompartmentCodeLabelPipe }} zubuchen {{ latestCompartmentCode$ | async | addToPreviousCompartmentCodeLabelPipe }} zubuchen
</ui-spinner> </ui-spinner>
</button> </button>
}
@for (action of mainActions$ | async; track action) {
<button <button
[disabled]="actionsDisabled$ | async" [disabled]="actionsDisabled$ | async"
class="cta-action shadow-action" class="cta-action shadow-action"
[class.cta-action-primary]="action.selected" [class.cta-action-primary]="action.selected"
[class.cta-action-secondary]="!action.selected" [class.cta-action-secondary]="!action.selected"
*ngFor="let action of mainActions$ | async"
(click)="handleAction(action)" (click)="handleAction(action)"
> >
<ui-spinner [show]="(changeActionLoader$ | async) === action.command">{{ action.label }}</ui-spinner> <ui-spinner [show]="(changeActionLoader$ | async) === action.command">{{ action.label }}</ui-spinner>
</button> </button>
}
</div> </div>

View File

@@ -1,3 +1,5 @@
<div *ngIf="items$ | async; let items"> @if (items$ | async; as items) {
<div>
<shared-goods-in-out-order-edit (navigation)="navigateToDetailsPage($event)" [items]="items"></shared-goods-in-out-order-edit> <shared-goods-in-out-order-edit (navigation)="navigateToDetailsPage($event)" [items]="items"></shared-goods-in-out-order-edit>
</div> </div>
}

View File

@@ -1,10 +1,10 @@
<div class="hidden desktop-large:block" [class.show-filter]="showFilter"> <div class="hidden desktop-large:block" [class.show-filter]="showFilter">
<ng-container *ngIf="filter$ | async; let filter"> @if (filter$ | async; as filter) {
<div class="customer-orders-search-filter-content"> <div class="customer-orders-search-filter-content">
<div class="w-full flex flex-row justify-end items-center"> <div class="w-full flex flex-row justify-end items-center">
<button (click)="clearFilter(filter)" class="text-[#0556B4] p-4">Alle Filter entfernen</button> <button (click)="clearFilter(filter)" class="text-[#0556B4] p-4">Alle Filter entfernen</button>
@if (showFilterClose$ | async) {
<a <a
*ngIf="showFilterClose$ | async"
class="text-black p-4 outline-none border-none bg-transparent" class="text-black p-4 outline-none border-none bg-transparent"
[routerLink]="closeFilterRoute" [routerLink]="closeFilterRoute"
(click)="showFilter = false" (click)="showFilter = false"
@@ -12,8 +12,8 @@
> >
<shared-icon icon="close" [size]="25"></shared-icon> <shared-icon icon="close" [size]="25"></shared-icon>
</a> </a>
}
</div> </div>
<div class="customer-orders-search-filter-content-main -mt-14 desktop-small:-mt-8 desktop-large:-mt-12"> <div class="customer-orders-search-filter-content-main -mt-14 desktop-small:-mt-8 desktop-large:-mt-12">
<h1 class="text-h3 text-[1.625rem] font-bold text-center pt-6 pb-10">Filter</h1> <h1 class="text-h3 text-[1.625rem] font-bold text-center pt-6 pb-10">Filter</h1>
<shared-filter <shared-filter
@@ -26,16 +26,14 @@
<page-order-branch-id-input *sharedFilterCustomInput="'order_branch_id'; let input" [input]="input"></page-order-branch-id-input> <page-order-branch-id-input *sharedFilterCustomInput="'order_branch_id'; let input" [input]="input"></page-order-branch-id-input>
</shared-filter> </shared-filter>
</div> </div>
<div class="cta-wrapper"> <div class="cta-wrapper">
<button class="cta-reset-filter" (click)="resetFilter()" [disabled]="loading$ | async">Filter zurücksetzen</button> <button class="cta-reset-filter" (click)="resetFilter()" [disabled]="loading$ | async">Filter zurücksetzen</button>
<button class="cta-apply-filter" (click)="applyFilter(filter)" [disabled]="(loading$ | async) || !hasSelectedOptions(filter)"> <button class="cta-apply-filter" (click)="applyFilter(filter)" [disabled]="(loading$ | async) || !hasSelectedOptions(filter)">
<ui-spinner [show]="loading$ | async">Filter anwenden</ui-spinner> <ui-spinner [show]="loading$ | async">Filter anwenden</ui-spinner>
</button> </button>
</div> </div>
</div> </div>
</ng-container> }
</div> </div>
<div class="desktop-large:hidden" [class.hidden]="showFilter"> <div class="desktop-large:hidden" [class.hidden]="showFilter">
<page-customer-order-search-main (showFilter)="showFilter = true"></page-customer-order-search-main> <page-customer-order-search-main (showFilter)="showFilter = true"></page-customer-order-search-main>

View File

@@ -11,24 +11,26 @@
<br /> <br />
oder scannen Sie die Kundenkarte. oder scannen Sie die Kundenkarte.
</p> </p>
<ng-container *ngIf="filter$ | async; let filter"> @if (filter$ | async; as filter) {
@if (!(isDesktop$ | async)) {
<shared-filter-filter-group-main <shared-filter-filter-group-main
class="mb-8 w-full" class="mb-8 w-full"
*ngIf="!(isDesktop$ | async)"
[inputGroup]="filter?.filter | group: 'main'" [inputGroup]="filter?.filter | group: 'main'"
></shared-filter-filter-group-main> ></shared-filter-filter-group-main>
}
<div class="flex flex-row px-12 justify-center desktop-large:px-0"> <div class="flex flex-row px-12 justify-center desktop-large:px-0">
@if (filter?.input | group: 'main'; as inputGroup) {
<shared-filter-input-group-main <shared-filter-input-group-main
class="block w-full mr-3 desktop-large:mx-auto" class="block w-full mr-3 desktop-large:mx-auto"
*ngIf="filter?.input | group: 'main'; let inputGroup"
[inputGroup]="inputGroup" [inputGroup]="inputGroup"
[loading]="loading$ | async" [loading]="loading$ | async"
(search)="search(filter)" (search)="search(filter)"
[hint]="message$ | async" [hint]="message$ | async"
[scanner]="true" [scanner]="true"
></shared-filter-input-group-main> ></shared-filter-input-group-main>
}
@if (!(isDesktop$ | async)) {
<button <button
*ngIf="!(isDesktop$ | async)"
(click)="showFilter.emit()" (click)="showFilter.emit()"
class="page-search-main__filter w-[6.75rem] h-14 rounded font-bold px-5 mb-4 text-lg bg-[#AEB7C1] flex flex-row flex-nowrap items-center justify-center" class="page-search-main__filter w-[6.75rem] h-14 rounded font-bold px-5 mb-4 text-lg bg-[#AEB7C1] flex flex-row flex-nowrap items-center justify-center"
[class.active]="hasFilter$ | async" [class.active]="hasFilter$ | async"
@@ -37,14 +39,15 @@
<shared-icon class="mr-2" icon="filter-variant"></shared-icon> <shared-icon class="mr-2" icon="filter-variant"></shared-icon>
Filter Filter
</button> </button>
}
</div> </div>
<div <div
class="flex flex-col items-start ml-12 desktop-large:ml-8 py-6 bg-white overflow-hidden h-[calc(100%-21rem)] desktop-large:h-[calc(100%-15rem)]" class="flex flex-col items-start ml-12 desktop-large:ml-8 py-6 bg-white overflow-hidden h-[calc(100%-21rem)] desktop-large:h-[calc(100%-15rem)]"
> >
<h3 class="text-p3 font-bold mb-3">Deine letzten Suchanfragen</h3> <h3 class="text-p3 font-bold mb-3">Deine letzten Suchanfragen</h3>
<ul class="flex flex-col justify-start overflow-hidden overflow-y-scroll items-start m-0 p-0 bg-white w-full"> <ul class="flex flex-col justify-start overflow-hidden overflow-y-scroll items-start m-0 p-0 bg-white w-full">
<li class="list-none pb-3" *ngFor="let query of history$ | async"> @for (query of history$ | async; track query) {
<li class="list-none pb-3">
<button <button
class="flex flex-row items-center outline-none border-none bg-white text-black text-p2 m-0 p-0" class="flex flex-row items-center outline-none border-none bg-white text-black text-p2 m-0 p-0"
(click)="setQueryHistory(filter, query)" (click)="setQueryHistory(filter, query)"
@@ -57,7 +60,8 @@
<p class="m-0 p-0 whitespace-nowrap overflow-hidden overflow-ellipsis max-w-[25rem]">{{ query }}</p> <p class="m-0 p-0 whitespace-nowrap overflow-hidden overflow-ellipsis max-w-[25rem]">{{ query }}</p>
</button> </button>
</li> </li>
}
</ul> </ul>
</div> </div>
</ng-container> }
</div> </div>

View File

@@ -11,13 +11,14 @@
[class.page-customer-order-item__item-grid-container-main]="primaryOutletActive" [class.page-customer-order-item__item-grid-container-main]="primaryOutletActive"
> >
<div class="page-customer-order-item__item-thumbnail text-center mr-4 w-[3.125rem] h-[4.9375rem]"> <div class="page-customer-order-item__item-thumbnail text-center mr-4 w-[3.125rem] h-[4.9375rem]">
@if (item?.product?.ean | productImage; as productImage) {
<img <img
class="page-customer-order-item__item-image w-[3.125rem] max-h-[4.9375rem]" class="page-customer-order-item__item-image w-[3.125rem] max-h-[4.9375rem]"
loading="lazy" loading="lazy"
*ngIf="item?.product?.ean | productImage; let productImage"
[src]="productImage" [src]="productImage"
[alt]="item?.product?.name" [alt]="item?.product?.name"
/> />
}
</div> </div>
<div <div
@@ -35,88 +36,111 @@
{{ item?.specialComment }} {{ item?.specialComment }}
</div> </div>
<div *ngIf="primaryOutletActive" class="page-customer-order-item__item-format desktop-small:text-p2"> @if (primaryOutletActive) {
<div *ngIf="item?.product?.format && item?.product?.formatDetail" class="font-bold flex flex-row"> <div class="page-customer-order-item__item-format desktop-small:text-p2">
@if (item?.product?.format && item?.product?.formatDetail) {
<div class="font-bold flex flex-row">
@if (item?.product?.format !== '--') {
<img <img
class="mr-3" class="mr-3"
*ngIf="item?.product?.format !== '--'"
loading="lazy" loading="lazy"
src="assets/images/Icon_{{ item?.product?.format }}.svg" src="assets/images/Icon_{{ item?.product?.format }}.svg"
[alt]="item?.product?.formatDetail" [alt]="item?.product?.formatDetail"
/> />
}
{{ item?.product?.formatDetail | substr: 30 }} {{ item?.product?.formatDetail | substr: 30 }}
</div> </div>
}
</div> </div>
}
<div *ngIf="primaryOutletActive" class="page-customer-order-item__item-ean desktop-small:text-p2"> @if (primaryOutletActive) {
<div class="page-customer-order-item__item-ean desktop-small:text-p2">
{{ item?.product?.ean }} {{ item?.product?.ean }}
</div> </div>
}
<div *ngIf="primaryOutletActive" class="page-customer-order-item__item-price desktop-small:text-p2 font-bold"> @if (primaryOutletActive) {
<div class="page-customer-order-item__item-price desktop-small:text-p2 font-bold">
{{ item.price | currency: 'EUR' : 'code' }} {{ item.price | currency: 'EUR' : 'code' }}
</div> </div>
}
<div *ngIf="primaryOutletActive" class="page-customer-order-item__item-changed desktop-small:text-p2"> @if (primaryOutletActive) {
<ng-container [ngSwitch]="showChangeDate$ | async"> <div class="page-customer-order-item__item-changed desktop-small:text-p2">
<div class="flex flex-row" *ngSwitchCase="true"> @switch (showChangeDate$ | async) {
@case (true) {
<div class="flex flex-row">
<div class="min-w-[7.5rem]">Geändert</div> <div class="min-w-[7.5rem]">Geändert</div>
<div class="font-bold">{{ item?.processingStatusDate | date: 'dd.MM.yy | HH:mm' }} Uhr</div> <div class="font-bold">{{ item?.processingStatusDate | date: 'dd.MM.yy | HH:mm' }} Uhr</div>
</div> </div>
<div class="flex flex-row" *ngSwitchCase="false"> }
@case (false) {
<div class="flex flex-row">
<div class="min-w-[7.5rem]">Bestelldatum</div> <div class="min-w-[7.5rem]">Bestelldatum</div>
<div class="font-bold">{{ item?.orderDate | date: 'dd.MM.yy | HH:mm' }} Uhr</div> <div class="font-bold">{{ item?.orderDate | date: 'dd.MM.yy | HH:mm' }} Uhr</div>
</div> </div>
</ng-container> }
}
</div> </div>
}
<div *ngIf="primaryOutletActive" class="page-customer-order-item__item-quantity flex flex-row desktop-small:text-p2"> @if (primaryOutletActive) {
<div class="page-customer-order-item__item-quantity flex flex-row desktop-small:text-p2">
<div class="min-w-[7.5rem]">Menge</div> <div class="min-w-[7.5rem]">Menge</div>
<div class="font-bold">{{ item.quantity }} x</div> <div class="font-bold">{{ item.quantity }} x</div>
</div> </div>
}
<div *ngIf="primaryOutletActive" class="page-customer-order-item__item-target-branch flex flex-row desktop-small:text-p2"> @if (primaryOutletActive) {
<ng-container *ngIf="item.orderType === 1; else showDelivery"> <div class="page-customer-order-item__item-target-branch flex flex-row desktop-small:text-p2">
@if (item.orderType === 1) {
<div class="min-w-[7.5rem]">Zielfiliale</div> <div class="min-w-[7.5rem]">Zielfiliale</div>
<div class="font-bold">{{ item.targetBranch }}</div> <div class="font-bold">{{ item.targetBranch }}</div>
</ng-container> } @else {
<ng-template #showDelivery>
<div class="min-w-[7.5rem]">Versanddatum</div> <div class="min-w-[7.5rem]">Versanddatum</div>
<div class="font-bold">{{ item?.estimatedShippingDate | date: 'dd.MM.yy | HH:mm' }} Uhr</div> <div class="font-bold">{{ item?.estimatedShippingDate | date: 'dd.MM.yy | HH:mm' }} Uhr</div>
</ng-template> }
</div> </div>
}
@if (!primaryOutletActive) {
<hr <hr
*ngIf="!primaryOutletActive"
class="page-customer-order-item__separator border-[#EDEFF0] border-solid border-[1px] -mx-[0.875rem]" class="page-customer-order-item__separator border-[#EDEFF0] border-solid border-[1px] -mx-[0.875rem]"
/> />
}
<div <div
class="page-customer-order-item__item-order-number desktop-small:text-xl justify-self-end font-bold" class="page-customer-order-item__item-order-number desktop-small:text-xl justify-self-end font-bold"
[class.page-customer-order-item__item-order-number-main]="!primaryOutletActive" [class.page-customer-order-item__item-order-number-main]="!primaryOutletActive"
> >
<ng-container *ngIf="item?.compartmentCode; else orderNumber"> @if (item?.compartmentCode) {
{{ item?.compartmentCode }}{{ item?.compartmentInfo && '_' + item?.compartmentInfo }} {{ item?.compartmentCode }}{{ item?.compartmentInfo && '_' + item?.compartmentInfo }}
</ng-container> } @else {
<ng-template #orderNumber>{{ item?.orderNumber }}</ng-template> {{ item?.orderNumber }}
}
</div> </div>
<div <div
class="page-customer-order-item__item-processing-paid-status flex flex-col font-bold desktop-small:text-p2 justify-self-end self-center" class="page-customer-order-item__item-processing-paid-status flex flex-col font-bold desktop-small:text-p2 justify-self-end self-center"
> >
<div class="page-customer-order-item__item-processing-status flex flex-row mb-[0.375rem]"> <div class="page-customer-order-item__item-processing-status flex flex-row mb-[0.375rem]">
@if (item.processingStatus | processingStatus: 'icon'; as icon) {
<shared-icon <shared-icon
class="flex items-center justify-center mr-1" class="flex items-center justify-center mr-1"
[size]="16" [size]="16"
*ngIf="item.processingStatus | processingStatus: 'icon'; let icon"
[icon]="icon" [icon]="icon"
></shared-icon> ></shared-icon>
}
{{ item.processingStatus | processingStatus }} {{ item.processingStatus | processingStatus }}
</div> </div>
<div class="page-customer-order-item__item-paid flex flex-row self-end"> <div class="page-customer-order-item__item-paid flex flex-row self-end">
<div class="font-bold w-fit desktop-small:text-p2 px-3 py-[0.125rem] rounded text-white bg-[#26830C]" *ngIf="item.features?.paid"> @if (item.features?.paid) {
<div class="font-bold w-fit desktop-small:text-p2 px-3 py-[0.125rem] rounded text-white bg-[#26830C]">
{{ item.features?.paid }} {{ item.features?.paid }}
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -4,8 +4,8 @@
[class.flex-col]="!(primaryOutletActive$ | async)" [class.flex-col]="!(primaryOutletActive$ | async)"
> >
<div class="flex flex-row w-full desktop-small:w-min" [class.desktop-large:w-full]="!(primaryOutletActive$ | async)"> <div class="flex flex-row w-full desktop-small:w-min" [class.desktop-large:w-full]="!(primaryOutletActive$ | async)">
@if (filter$ | async; as filter) {
<shared-filter-input-group-main <shared-filter-input-group-main
*ngIf="filter$ | async; let filter"
class="block mr-3 w-full desktop-small:w-[23.5rem]" class="block mr-3 w-full desktop-small:w-[23.5rem]"
[class.desktop-large:w-full]="!(primaryOutletActive$ | async)" [class.desktop-large:w-full]="!(primaryOutletActive$ | async)"
[hint]="message$ | async" [hint]="message$ | async"
@@ -15,6 +15,7 @@
[showDescription]="false" [showDescription]="false"
[scanner]="true" [scanner]="true"
></shared-filter-input-group-main> ></shared-filter-input-group-main>
}
<a <a
class="page-customer-orders-results__filter w-[6.75rem] h-14 rounded font-bold px-5 mb-4 text-lg bg-[#AEB7C1] flex flex-row flex-nowrap items-center justify-center" class="page-customer-orders-results__filter w-[6.75rem] h-14 rounded font-bold px-5 mb-4 text-lg bg-[#AEB7C1] flex flex-row flex-nowrap items-center justify-center"
@@ -27,18 +28,19 @@
</a> </a>
</div> </div>
@if (hits$ | async; as hits) {
<div <div
*ngIf="hits$ | async; let hits"
class="page-customer-order-search-results__items-count inline-flex flex-row items-center pr-5 text-p3" class="page-customer-order-search-results__items-count inline-flex flex-row items-center pr-5 text-p3"
[class.mb-4]="primaryOutletActive$ | async" [class.mb-4]="primaryOutletActive$ | async"
> >
{{ hits ?? 0 }} {{ hits ?? 0 }}
Titel Titel
</div> </div>
}
</div> </div>
@if (!(listEmpty$ | async)) {
<ui-scroll-container <ui-scroll-container
*ngIf="!(listEmpty$ | async); else emptyMessage"
class="page-customer-order-results__scroll-container m-0 p-0" class="page-customer-order-results__scroll-container m-0 p-0"
[showScrollbar]="false" [showScrollbar]="false"
[showScrollArrow]="false" [showScrollArrow]="false"
@@ -48,56 +50,63 @@
[containerHeight]="25" [containerHeight]="25"
[showSpacer]="(primaryOutletActive$ | async) || (isTablet$ | async)" [showSpacer]="(primaryOutletActive$ | async) || (isTablet$ | async)"
> >
<ng-container *ngIf="processId$ | async; let processId"> @if (processId$ | async; as processId) {
<div class="page-customer-order-results__items-list w-full" *ngFor="let bueryNumberGroup of items$ | async | groupBy: byBuyerNumberFn"> @for (bueryNumberGroup of items$ | async | groupBy: byBuyerNumberFn; track bueryNumberGroup) {
<ng-container *ngIf="bueryNumberGroup.items[0]; let firstItem"> <div class="page-customer-order-results__items-list w-full">
@if (bueryNumberGroup.items[0]; as firstItem) {
<div <div
class="page-customer-order-search__item-header-group w-full grid grid-flow-col gap-x-4 items-center justify-between bg-white text-xl rounded-t px-4 py-[0.875rem] font-bold mb-px-2" class="page-customer-order-search__item-header-group w-full grid grid-flow-col gap-x-4 items-center justify-between bg-white text-xl rounded-t px-4 py-[0.875rem] font-bold mb-px-2"
> >
<h3 class="m-0 break-words" [class.w-72]="!(primaryOutletActive$ | async)"> <h3 class="m-0 break-words" [class.w-72]="!(primaryOutletActive$ | async)">
{{ firstItem?.organisation }} {{ firstItem?.organisation }}
<ng-container *ngIf="!!firstItem?.organisation && (!!firstItem?.firstName || !!firstItem?.lastName)">-</ng-container> @if (!!firstItem?.organisation && (!!firstItem?.firstName || !!firstItem?.lastName)) {
-
}
{{ firstItem?.lastName }} {{ firstItem?.lastName }}
{{ firstItem?.firstName }} {{ firstItem?.firstName }}
</h3> </h3>
<h3 class="m-0 break-words text-right" [class.w-40]="!(primaryOutletActive$ | async)">{{ firstItem?.buyerNumber }}</h3> <h3 class="m-0 break-words text-right" [class.w-40]="!(primaryOutletActive$ | async)">{{ firstItem?.buyerNumber }}</h3>
</div> </div>
</ng-container> }
@for (orderNumberGroup of bueryNumberGroup.items | groupBy: byOrderNumberFn; track orderNumberGroup) {
<ng-container *ngFor="let orderNumberGroup of bueryNumberGroup.items | groupBy: byOrderNumberFn"> @for (processingStatusGroup of orderNumberGroup.items | groupBy: byProcessingStatusFn; track processingStatusGroup) {
<ng-container *ngFor="let processingStatusGroup of orderNumberGroup.items | groupBy: byProcessingStatusFn"> @for (compartmentCodeGroup of processingStatusGroup.items | groupBy: byCompartmentCodeFn; track compartmentCodeGroup) {
<ng-container *ngFor="let compartmentCodeGroup of processingStatusGroup.items | groupBy: byCompartmentCodeFn"> @for (item of compartmentCodeGroup.items; track trackByFn($index, item); let firstItem = $first) {
<page-customer-order-item <page-customer-order-item
*ngFor="let item of compartmentCodeGroup.items; let firstItem = first; trackBy: trackByFn"
class="page-customer-orders-results__result-item mb-[0.625rem]" class="page-customer-orders-results__result-item mb-[0.625rem]"
[class.page-customer-orders-results__result-item-main]="primaryOutletActive$ | async" [class.page-customer-orders-results__result-item-main]="primaryOutletActive$ | async"
[item]="item" [item]="item"
[primaryOutletActive]="primaryOutletActive$ | async" [primaryOutletActive]="primaryOutletActive$ | async"
></page-customer-order-item> ></page-customer-order-item>
</ng-container> }
</ng-container> }
</ng-container> }
}
</div> </div>
</ng-container> }
}
</ui-scroll-container> </ui-scroll-container>
} @else {
<ng-template #emptyMessage>
<div class="empty-message"> <div class="empty-message">
Es sind im Moment keine Bestellposten vorhanden, Es sind im Moment keine Bestellposten vorhanden,
<br /> <br />
die bearbeitet werden können. die bearbeitet werden können.
</div> </div>
</ng-template> }
<div class="actions z-fixed" *ngIf="actions$ | async; let actions">
@if (actions$ | async; as actions) {
<div class="actions z-fixed">
@for (action of actions; track action) {
<button <button
[disabled]="(loadingFetchedActionButton$ | async) || (loading$ | async)" [disabled]="(loadingFetchedActionButton$ | async) || (loading$ | async)"
class="cta-action" class="cta-action"
*ngFor="let action of actions"
[class.cta-action-primary]="action.selected" [class.cta-action-primary]="action.selected"
[class.cta-action-secondary]="!action.selected" [class.cta-action-secondary]="!action.selected"
(click)="handleAction(action)" (click)="handleAction(action)"
> >
<ui-spinner [show]="(loadingFetchedActionButton$ | async) || (loading$ | async)">{{ action.label }}</ui-spinner> <ui-spinner [show]="(loadingFetchedActionButton$ | async) || (loading$ | async)">{{ action.label }}</ui-spinner>
</button> </button>
}
</div> </div>
}

View File

@@ -12,42 +12,46 @@
<ng-template #navMenu> <ng-template #navMenu>
<div class="pt-1"> <div class="pt-1">
<shared-menu> <shared-menu>
@if (customerDetailsRoute$ | async; as customerDetailsRoute) {
<a <a
sharedMenuItem sharedMenuItem
*ngIf="customerDetailsRoute$ | async; let customerDetailsRoute"
[routerLink]="customerDetailsRoute.path" [routerLink]="customerDetailsRoute.path"
[queryParams]="customerDetailsRoute.queryParams" [queryParams]="customerDetailsRoute.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
> >
Kundendetails Kundendetails
</a> </a>
}
@if (ordersRoute$ | async; as ordersRoute) {
<a <a
sharedMenuItem sharedMenuItem
*ngIf="ordersRoute$ | async; let ordersRoute"
[routerLink]="ordersRoute.path" [routerLink]="ordersRoute.path"
[queryParams]="ordersRoute.queryParams" [queryParams]="ordersRoute.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
> >
Bestellungen Bestellungen
</a> </a>
}
@if (kundenkarteRoute$ | async; as kundenkarteRoute) {
<a <a
sharedMenuItem sharedMenuItem
*ngIf="kundenkarteRoute$ | async; let kundenkarteRoute"
[routerLink]="kundenkarteRoute.path" [routerLink]="kundenkarteRoute.path"
[queryParams]="kundenkarteRoute.queryParams" [queryParams]="kundenkarteRoute.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
> >
Kundenkarte Kundenkarte
</a> </a>
}
@if (historyRoute$ | async; as historyRoute) {
<a <a
sharedMenuItem sharedMenuItem
*ngIf="historyRoute$ | async; let historyRoute"
[routerLink]="historyRoute.path" [routerLink]="historyRoute.path"
[queryParams]="historyRoute.queryParams" [queryParams]="historyRoute.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
> >
Historie Historie
</a> </a>
}
</shared-menu> </shared-menu>
</div> </div>
</ng-template> </ng-template>

View File

@@ -8,7 +8,7 @@ import { map } from 'rxjs/operators';
import { CustomerSearchNavigation } from '@shared/services/navigation'; import { CustomerSearchNavigation } from '@shared/services/navigation';
import { ComponentStore } from '@ngrx/component-store'; import { ComponentStore } from '@ngrx/component-store';
import { RouterLink } from '@angular/router'; import { RouterLink } from '@angular/router';
import { AsyncPipe, NgIf } from '@angular/common'; import { AsyncPipe } from '@angular/common';
export interface CustomerMenuComponentState { export interface CustomerMenuComponentState {
customerId?: number; customerId?: number;
@@ -26,7 +26,7 @@ export interface CustomerMenuComponentState {
styleUrls: ['customer-menu.component.css'], styleUrls: ['customer-menu.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'page-customer-menu' }, host: { class: 'page-customer-menu' },
imports: [CdkMenuModule, SharedMenuModule, IconComponent, RouterLink, NgIf, AsyncPipe], imports: [CdkMenuModule, SharedMenuModule, IconComponent, RouterLink, AsyncPipe],
}) })
export class CustomerMenuComponent extends ComponentStore<CustomerMenuComponentState> { export class CustomerMenuComponent extends ComponentStore<CustomerMenuComponentState> {
private _navigation = inject(CustomerSearchNavigation); private _navigation = inject(CustomerSearchNavigation);

View File

@@ -1,7 +1,7 @@
@if (!compact) {
<cdk-virtual-scroll-viewport <cdk-virtual-scroll-viewport
itemSize="100" itemSize="100"
class="h-[calc(100vh-20.125rem)] desktop-small:h-[calc(100vh-18.625rem)]" class="h-[calc(100vh-20.125rem)] desktop-small:h-[calc(100vh-18.625rem)]"
*ngIf="!compact"
(scrolledIndexChange)="scrolledIndexChange($event)" (scrolledIndexChange)="scrolledIndexChange($event)"
> >
<a <a
@@ -15,15 +15,18 @@
> >
<page-customer-result-list-item-full [class.active]="rla.isActive" [customer]="customer"></page-customer-result-list-item-full> <page-customer-result-list-item-full [class.active]="rla.isActive" [customer]="customer"></page-customer-result-list-item-full>
</a> </a>
<div class="h-[6.125rem] bg-white rounded px-4 py-3" *ngIf="hits === customers?.length && !fetching"> @if (hits === customers?.length && !fetching) {
<div class="h-[6.125rem] bg-white rounded px-4 py-3">
<ng-container *ngTemplateOutlet="customerNotFound"></ng-container> <ng-container *ngTemplateOutlet="customerNotFound"></ng-container>
</div> </div>
}
</cdk-virtual-scroll-viewport> </cdk-virtual-scroll-viewport>
}
@if (compact) {
<cdk-virtual-scroll-viewport <cdk-virtual-scroll-viewport
itemSize="191" itemSize="191"
class="h-[calc(100vh-20.75rem)]" class="h-[calc(100vh-20.75rem)]"
*ngIf="compact"
(scrolledIndexChange)="scrolledIndexChange($event)" (scrolledIndexChange)="scrolledIndexChange($event)"
> >
<a <a
@@ -37,23 +40,27 @@
> >
<page-customer-result-list-item [class.active]="rla.isActive" [customer]="customer"></page-customer-result-list-item> <page-customer-result-list-item [class.active]="rla.isActive" [customer]="customer"></page-customer-result-list-item>
</a> </a>
<div class="h-[11.3125rem] bg-white rounded px-4 py-3" *ngIf="hits === customers?.length && !fetching"> @if (hits === customers?.length && !fetching) {
<div class="h-[11.3125rem] bg-white rounded px-4 py-3">
<ng-container *ngTemplateOutlet="customerNotFound"></ng-container> <ng-container *ngTemplateOutlet="customerNotFound"></ng-container>
</div> </div>
}
</cdk-virtual-scroll-viewport> </cdk-virtual-scroll-viewport>
}
<ng-template #customerNotFound> <ng-template #customerNotFound>
<div class="text-sm"> <div class="text-sm">
Hinweis: Aus Datenschutzgründen werden nur Teilinformationen dargestellt. Tab auf einen Kunden um mehr zu erfahren. Hinweis: Aus Datenschutzgründen werden nur Teilinformationen dargestellt. Tab auf einen Kunden um mehr zu erfahren.
</div> </div>
<div class="font-bold text-lg mt-3"> <div class="font-bold text-lg mt-3">
<span>Kunden nicht gefunden?</span> <span>Kunden nicht gefunden?</span>
@if (customerCreateNavigation.defaultRoute({ processId: processId }); as route) {
<a <a
*ngIf="customerCreateNavigation.defaultRoute({ processId: processId }); let route"
[routerLink]="route.path" [routerLink]="route.path"
[queryParams]="route.queryParams" [queryParams]="route.queryParams"
class="text-brand" class="text-brand"
> >
Neue Kundendaten erfassen Neue Kundendaten erfassen
</a> </a>
}
</div> </div>
</ng-template> </ng-template>

View File

@@ -1,16 +1,17 @@
<ng-container *ifRole="'Store'"> <ng-container *ifRole="'Store'">
@if (customerType !== 'b2b') {
<shared-checkbox <shared-checkbox
*ngIf="customerType !== 'b2b'"
[ngModel]="p4mUser" [ngModel]="p4mUser"
(ngModelChange)="setValue({ p4mUser: !p4mUser })" (ngModelChange)="setValue({ p4mUser: !p4mUser })"
[disabled]="p4mReadonly || readonly" [disabled]="p4mReadonly || readonly"
> >
Kundenkarte Kundenkarte
</shared-checkbox> </shared-checkbox>
}
</ng-container> </ng-container>
<ng-container *ngFor="let option of filteredOptions$ | async"> @for (option of filteredOptions$ | async; track option) {
@if (option?.enabled !== false) {
<shared-checkbox <shared-checkbox
*ngIf="option?.enabled !== false"
[ngModel]="option.value === customerType" [ngModel]="option.value === customerType"
(ngModelChange)="setValue({ customerType: $event ? option.value : undefined })" (ngModelChange)="setValue({ customerType: $event ? option.value : undefined })"
[disabled]="isOptionDisabled(option)" [disabled]="isOptionDisabled(option)"
@@ -18,4 +19,5 @@
> >
{{ option.label }} {{ option.label }}
</shared-checkbox> </shared-checkbox>
</ng-container> }
}

View File

@@ -54,9 +54,11 @@
<shared-form-control class="col-span-2" label="Land"> <shared-form-control class="col-span-2" label="Land">
<shared-select placeholder="Land" formControlName="country" [tabindex]="tabIndexStart + 5" [readonly]="readonly"> <shared-select placeholder="Land" formControlName="country" [tabindex]="tabIndexStart + 5" [readonly]="readonly">
<shared-select-option *ngFor="let country of countries || (countries$ | async)" [value]="country.isO3166_A_3"> @for (country of countries || (countries$ | async); track country) {
<shared-select-option [value]="country.isO3166_A_3">
{{ country.name }} {{ country.name }}
</shared-select-option> </shared-select-option>
}
</shared-select> </shared-select>
</shared-form-control> </shared-form-control>
</ng-container> </ng-container>

View File

@@ -7,10 +7,11 @@
> >
<ng-content></ng-content> <ng-content></ng-content>
</shared-checkbox> </shared-checkbox>
<div class="address-block" *ngIf="control.value.deviatingAddress"> @if (control.value.deviatingAddress) {
<div class="address-block">
<div class="wrapper"> <div class="wrapper">
@if (organisation) {
<app-organisation-form-block <app-organisation-form-block
*ngIf="organisation"
[tabIndexStart]="tabIndexStart + 1" [tabIndexStart]="tabIndexStart + 1"
#orgaBlock #orgaBlock
(onInit)="addOrganisationGroup($event)" (onInit)="addOrganisationGroup($event)"
@@ -22,6 +23,7 @@
[validatorFns]="organisationValidatorFns" [validatorFns]="organisationValidatorFns"
[readonly]="readonly" [readonly]="readonly"
></app-organisation-form-block> ></app-organisation-form-block>
}
<app-name-form-block <app-name-form-block
(onInit)="addNameGroup($event)" (onInit)="addNameGroup($event)"
(onDestroy)="removeNameGroup()" (onDestroy)="removeNameGroup()"
@@ -40,8 +42,8 @@
[validatorFns]="addressValidatorFns" [validatorFns]="addressValidatorFns"
[readonly]="readonly" [readonly]="readonly"
></app-address-form-block> ></app-address-form-block>
@if (email) {
<app-email-form-block <app-email-form-block
*ngIf="email"
#emailFormBlock #emailFormBlock
(onInit)="addEmailGroup($event)" (onInit)="addEmailGroup($event)"
(onDestroy)="removeEmailGroup()" (onDestroy)="removeEmailGroup()"
@@ -50,13 +52,16 @@
[validatorFns]="emailValidationFns" [validatorFns]="emailValidationFns"
[readonly]="readonly" [readonly]="readonly"
></app-email-form-block> ></app-email-form-block>
}
@if (phoneNumbers) {
<app-phone-numbers-form-block <app-phone-numbers-form-block
*ngIf="phoneNumbers"
(onInit)="addPhoneNumbersGroup($event)" (onInit)="addPhoneNumbersGroup($event)"
(onDestroy)="removePhoneNumbersGroup()" (onDestroy)="removePhoneNumbersGroup()"
[readonly]="readonly" [readonly]="readonly"
> >
[tabIndexStart]="emailFormBlock?.tabIndexEnd+1" [requiredMarks]="phoneNumbersRequiredMarks" [validatorFns]="phoneNumbersValidatorFns"> [tabIndexStart]="emailFormBlock?.tabIndexEnd+1" [requiredMarks]="phoneNumbersRequiredMarks" [validatorFns]="phoneNumbersValidatorFns">
</app-phone-numbers-form-block> </app-phone-numbers-form-block>
}
</div> </div>
</div> </div>
}

View File

@@ -1,7 +1,7 @@
<div class="interests-description">Geben Sie Interessen an, um Ihre persönlichen Kontoangaben zu verfeinern.</div> <div class="interests-description">Geben Sie Interessen an, um Ihre persönlichen Kontoangaben zu verfeinern.</div>
<div class="interests-wrapper" [formGroup]="control"> <div class="interests-wrapper" [formGroup]="control">
@for (pair of interests | keyvalue; track pair; let idx = $index) {
<shared-checkbox <shared-checkbox
*ngFor="let pair of interests | keyvalue; let idx = index"
[formControlName]="pair.key" [formControlName]="pair.key"
[tabindex]="tabIndexStart + idx" [tabindex]="tabIndexStart + idx"
[autofocus]="focusAfterInit" [autofocus]="focusAfterInit"
@@ -9,4 +9,5 @@
> >
{{ pair.value }} {{ pair.value }}
</shared-checkbox> </shared-checkbox>
}
</div> </div>

View File

@@ -7,7 +7,9 @@
[tabindex]="tabIndexStart" [tabindex]="tabIndexStart"
[autofocus]="focusAfterInit" [autofocus]="focusAfterInit"
> >
<shared-select-option *ngFor="let gender of genderSettings.genders" [value]="gender.value">{{ gender.label }}</shared-select-option> @for (gender of genderSettings.genders; track gender) {
<shared-select-option [value]="gender.value">{{ gender.label }}</shared-select-option>
}
</shared-select> </shared-select>
</shared-form-control> </shared-form-control>

View File

@@ -10,7 +10,7 @@
[readonly]="readonly" [readonly]="readonly"
/> />
</shared-form-control> </shared-form-control>
<ng-container *ngIf="appearence === 'default'"> @if (appearence === 'default') {
<shared-form-control label="Abteilung"> <shared-form-control label="Abteilung">
<input <input
placeholder="Abteilung" placeholder="Abteilung"
@@ -31,5 +31,5 @@
[readonly]="readonly" [readonly]="readonly"
/> />
</shared-form-control> </shared-form-control>
</ng-container> }
</ng-container> </ng-container>

View File

@@ -9,6 +9,8 @@
/> />
</shared-form-control> </shared-form-control>
<button type="button" *ngIf="!readonly && canScan()" (click)="scan()"> @if (!readonly && canScan()) {
<button type="button" (click)="scan()">
<shared-icon icon="barcode-scan" [size]="32"></shared-icon> <shared-icon icon="barcode-scan" [size]="32"></shared-icon>
</button> </button>
}

View File

@@ -1,38 +1,62 @@
<div class="wrapper text-center" [@cardFlip]="state" (@cardFlip.done)="flipAnimationDone($event)"> <div class="wrapper text-center" [@cardFlip]="state" (@cardFlip.done)="flipAnimationDone($event)">
<div *ngIf="cardDetails" class="card-main"> @if (cardDetails) {
<div class="card-main">
<div class="icons text-brand"> <div class="icons text-brand">
<button *ngIf="isCustomerCard && frontside" class="icon-barcode" (click)="flipCard()"> @if (isCustomerCard && frontside) {
<button class="icon-barcode" (click)="flipCard()">
<shared-icon [size]="35" icon="barcode-scanner"></shared-icon> <shared-icon [size]="35" icon="barcode-scanner"></shared-icon>
</button> </button>
<button *ngIf="isCustomerCard && !frontside" class="icon-back" (click)="flipCard()"> }
@if (isCustomerCard && !frontside) {
<button class="icon-back" (click)="flipCard()">
<shared-icon [size]="35" icon="refresh"></shared-icon> <shared-icon [size]="35" icon="refresh"></shared-icon>
</button> </button>
}
<!-- <div *ngIf="!isCustomerCard" class="icon-delete"><ui-icon (click)="onDeletePartnerCard()" size="25px" icon="trash"></ui-icon></div> --> <!-- <div *ngIf="!isCustomerCard" class="icon-delete"><ui-icon (click)="onDeletePartnerCard()" size="25px" icon="trash"></ui-icon></div> -->
</div> </div>
<div class="headline"> <div class="headline">
<p *ngIf="isCustomerCard && frontside">Ihre Lesepunkte</p> @if (isCustomerCard && frontside) {
<p *ngIf="isCustomerCard && !frontside">Kartennummer</p> <p>Ihre Lesepunkte</p>
<p *ngIf="!isCustomerCard">Partnerkartennummer</p> }
@if (isCustomerCard && !frontside) {
<p>Kartennummer</p>
}
@if (!isCustomerCard) {
<p>Partnerkartennummer</p>
}
</div> </div>
<div class="mt-2"> <div class="mt-2">
<div *ngIf="!isCustomerCard || (isCustomerCard && !frontside)" class="card-number">{{ cardDetails.code }}</div> @if (!isCustomerCard || (isCustomerCard && !frontside)) {
<div *ngIf="isCustomerCard && frontside" class="points">{{ cardDetails.totalPoints | number }}</div> <div class="card-number">{{ cardDetails.code }}</div>
}
@if (isCustomerCard && frontside) {
<div class="points">{{ cardDetails.totalPoints | number }}</div>
}
</div> </div>
<div class="barcode-button"> <div class="barcode-button">
<div *ngIf="!isCustomerCard || (isCustomerCard && !frontside)" class="barcode-field"> @if (!isCustomerCard || (isCustomerCard && !frontside)) {
<div class="barcode-field">
<img class="barcode" src="/assets/images/barcode.png" alt="Barcode" /> <img class="barcode" src="/assets/images/barcode.png" alt="Barcode" />
</div> </div>
<div *ngIf="isCustomerCard && frontside"> }
@if (isCustomerCard && frontside) {
<div>
<button class="button" (click)="onRewardShop()">Zum Prämienshop</button> <button class="button" (click)="onRewardShop()">Zum Prämienshop</button>
</div> </div>
}
</div> </div>
</div> </div>
}
<div class="card-bottom"> <div class="card-bottom">
<div *ngIf="!isCustomerCard || (isCustomerCard && !frontside)" class="customer-name"> @if (!isCustomerCard || (isCustomerCard && !frontside)) {
<div class="customer-name">
<p>{{ cardDetails.firstName }} {{ cardDetails.lastName }}</p> <p>{{ cardDetails.firstName }} {{ cardDetails.lastName }}</p>
</div> </div>
<div *ngIf="isCustomerCard && frontside" class="logo ml-2"> }
@if (isCustomerCard && frontside) {
<div class="logo ml-2">
<img class="logo-picture" src="/assets/images/Hugendubel_Logo.png" alt="Hugendubel Logo" /> <img class="logo-picture" src="/assets/images/Hugendubel_Logo.png" alt="Hugendubel Logo" />
</div> </div>
}
</div> </div>
</div> </div>

View File

@@ -1,5 +1,5 @@
import { animate, state, style, transition, trigger } from '@angular/animations'; import { animate, state, style, transition, trigger } from '@angular/animations';
import { DecimalPipe, NgIf } from '@angular/common'; import { DecimalPipe } from '@angular/common';
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input, OnInit } from '@angular/core';
import { IconComponent } from '@shared/components/icon'; import { IconComponent } from '@shared/components/icon';
import { BonusCardInfoDTO } from '@generated/swagger/crm-api'; import { BonusCardInfoDTO } from '@generated/swagger/crm-api';
@@ -8,7 +8,7 @@ import { BonusCardInfoDTO } from '@generated/swagger/crm-api';
selector: 'page-customer-kundenkarte', selector: 'page-customer-kundenkarte',
templateUrl: 'kundenkarte.component.html', templateUrl: 'kundenkarte.component.html',
styleUrls: ['kundenkarte.component.scss'], styleUrls: ['kundenkarte.component.scss'],
imports: [IconComponent, NgIf, DecimalPipe], imports: [IconComponent, DecimalPipe],
animations: [ animations: [
trigger('cardFlip', [ trigger('cardFlip', [
state( state(

View File

@@ -1,4 +1,5 @@
<form *ngIf="formData$ | async; let data" (keydown.enter)="$event.preventDefault()"> @if (formData$ | async; as data) {
<form (keydown.enter)="$event.preventDefault()">
<h1 class="title">Kundendaten erfassen</h1> <h1 class="title">Kundendaten erfassen</h1>
<p class="description"> <p class="description">
Um Ihnen den ausgewählten Service zu Um Ihnen den ausgewählten Service zu
@@ -7,14 +8,12 @@
<br /> <br />
ein Kundenkonto an. ein Kundenkonto an.
</p> </p>
<app-customer-type-selector <app-customer-type-selector
[processId]="processId$ | async" [processId]="processId$ | async"
[p4mUser]="false" [p4mUser]="false"
customerType="b2b" customerType="b2b"
(valueChanges)="customerTypeChanged($event)" (valueChanges)="customerTypeChanged($event)"
></app-customer-type-selector> ></app-customer-type-selector>
<app-organisation-form-block <app-organisation-form-block
#orga #orga
[tabIndexStart]="1" [tabIndexStart]="1"
@@ -24,7 +23,6 @@
[requiredMarks]="organisationFormBlockRequiredMarks" [requiredMarks]="organisationFormBlockRequiredMarks"
[validatorFns]="organisationFormBlockValidators" [validatorFns]="organisationFormBlockValidators"
></app-organisation-form-block> ></app-organisation-form-block>
<app-name-form-block <app-name-form-block
#name #name
[tabIndexStart]="orga.tabIndexEnd + 1" [tabIndexStart]="orga.tabIndexEnd + 1"
@@ -32,7 +30,6 @@
(dataChanges)="patchFormData('name', $event)" (dataChanges)="patchFormData('name', $event)"
(onInit)="addFormBlock('name', $event)" (onInit)="addFormBlock('name', $event)"
></app-name-form-block> ></app-name-form-block>
<app-address-form-block <app-address-form-block
#address #address
[tabIndexStart]="name.tabIndexEnd + 1" [tabIndexStart]="name.tabIndexEnd + 1"
@@ -43,7 +40,6 @@
[validatorFns]="addressValidators" [validatorFns]="addressValidators"
[defaults]="{ country: 'DEU' }" [defaults]="{ country: 'DEU' }"
></app-address-form-block> ></app-address-form-block>
<app-email-form-block <app-email-form-block
#email #email
[tabIndexStart]="address.tabIndexEnd + 1" [tabIndexStart]="address.tabIndexEnd + 1"
@@ -52,7 +48,6 @@
[validatorFns]="emailFormBlockValidators" [validatorFns]="emailFormBlockValidators"
(onInit)="addFormBlock('email', $event)" (onInit)="addFormBlock('email', $event)"
></app-email-form-block> ></app-email-form-block>
<app-phone-numbers-form-block <app-phone-numbers-form-block
#phoneNumbers #phoneNumbers
[tabIndexStart]="email.tabIndexEnd + 1" [tabIndexStart]="email.tabIndexEnd + 1"
@@ -60,7 +55,6 @@
(dataChanges)="patchFormData('phoneNumbers', $event)" (dataChanges)="patchFormData('phoneNumbers', $event)"
(onInit)="addFormBlock('phoneNumbers', $event)" (onInit)="addFormBlock('phoneNumbers', $event)"
></app-phone-numbers-form-block> ></app-phone-numbers-form-block>
<app-deviating-address-form-block <app-deviating-address-form-block
[tabIndexStart]="phoneNumbers.tabIndexEnd + 1" [tabIndexStart]="phoneNumbers.tabIndexEnd + 1"
[data]="data.deviatingDeliveryAddress" [data]="data.deviatingDeliveryAddress"
@@ -79,7 +73,6 @@
> >
Die Lieferadresse weicht von der Rechnungsadresse ab Die Lieferadresse weicht von der Rechnungsadresse ab
</app-deviating-address-form-block> </app-deviating-address-form-block>
<div class="spacer"></div> <div class="spacer"></div>
<div class="sticky w-full flex items-center justify-center"> <div class="sticky w-full flex items-center justify-center">
<button class="cta-submit" type="button" (click)="save()" [disabled]="form.invalid || form.pending"> <button class="cta-submit" type="button" (click)="save()" [disabled]="form.invalid || form.pending">
@@ -87,3 +80,4 @@
</button> </button>
</div> </div>
</form> </form>
}

View File

@@ -1,4 +1,4 @@
import { CommonModule } from '@angular/common';
import { Component, ChangeDetectionStrategy } from '@angular/core'; import { Component, ChangeDetectionStrategy } from '@angular/core';
import { ActivatedRoute, RouterModule } from '@angular/router'; import { ActivatedRoute, RouterModule } from '@angular/router';
import { CustomerCreateSideViewModule } from './customer-create-side-view'; import { CustomerCreateSideViewModule } from './customer-create-side-view';
@@ -10,7 +10,7 @@ import { SharedSplitscreenComponent } from '@shared/components/splitscreen';
templateUrl: 'create-customer.component.html', templateUrl: 'create-customer.component.html',
styleUrls: ['create-customer.component.css'], styleUrls: ['create-customer.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule, RouterModule, SharedSplitscreenComponent, CustomerCreateSideViewModule], imports: [RouterModule, SharedSplitscreenComponent, CustomerCreateSideViewModule],
}) })
export class CreateCustomerComponent { export class CreateCustomerComponent {
processId$ = this._activatedRoute.parent.data.pipe(map((data) => data.processId)); processId$ = this._activatedRoute.parent.data.pipe(map((data) => data.processId));

View File

@@ -1,4 +1,5 @@
<form *ngIf="formData$ | async; let data" (keydown.enter)="$event.preventDefault()"> @if (formData$ | async; as data) {
<form (keydown.enter)="$event.preventDefault()">
<h1 class="title">Kundendaten erfassen</h1> <h1 class="title">Kundendaten erfassen</h1>
<p class="description"> <p class="description">
Um Ihnen den ausgewählten Service Um Ihnen den ausgewählten Service
@@ -8,14 +9,12 @@
gerne ein Kundenkonto an. gerne ein Kundenkonto an.
<br /> <br />
</p> </p>
<app-customer-type-selector <app-customer-type-selector
[processId]="processId$ | async" [processId]="processId$ | async"
[p4mUser]="false" [p4mUser]="false"
customerType="guest" customerType="guest"
(valueChanges)="customerTypeChanged($event)" (valueChanges)="customerTypeChanged($event)"
></app-customer-type-selector> ></app-customer-type-selector>
<app-name-form-block <app-name-form-block
#name #name
[tabIndexStart]="1" [tabIndexStart]="1"
@@ -25,13 +24,11 @@
[requiredMarks]="nameRequiredMarks" [requiredMarks]="nameRequiredMarks"
[validatorFns]="nameValidationFns" [validatorFns]="nameValidationFns"
></app-name-form-block> ></app-name-form-block>
<p class="info"> <p class="info">
Wir werden Ihnen Werbung zu ähnlichen Produkten oder Dienstleistungen aus unserem Sortiment per E-Mail zusenden. Sie können der Wir werden Ihnen Werbung zu ähnlichen Produkten oder Dienstleistungen aus unserem Sortiment per E-Mail zusenden. Sie können der
Verwendung Ihrer Daten jederzeit z.B. mittels der in den E-Mails enthaltenen Abmeldelinks widersprechen, ohne dass hierfür andere als Verwendung Ihrer Daten jederzeit z.B. mittels der in den E-Mails enthaltenen Abmeldelinks widersprechen, ohne dass hierfür andere als
die Übermittlungskosten nach den Basistarifen entstehen. die Übermittlungskosten nach den Basistarifen entstehen.
</p> </p>
<app-email-form-block <app-email-form-block
#email #email
[tabIndexStart]="name.tabIndexEnd + 1" [tabIndexStart]="name.tabIndexEnd + 1"
@@ -41,7 +38,6 @@
[validatorFns]="emailFormBlockValidators" [validatorFns]="emailFormBlockValidators"
(onInit)="addFormBlock('email', $event)" (onInit)="addFormBlock('email', $event)"
></app-email-form-block> ></app-email-form-block>
<app-organisation-form-block <app-organisation-form-block
#orga #orga
[tabIndexStart]="email.tabIndexStart + 1" [tabIndexStart]="email.tabIndexStart + 1"
@@ -50,7 +46,6 @@
(onInit)="addFormBlock('organisation', $event)" (onInit)="addFormBlock('organisation', $event)"
appearence="compact" appearence="compact"
></app-organisation-form-block> ></app-organisation-form-block>
<app-address-form-block <app-address-form-block
#address #address
[tabIndexStart]="orga.tabIndexEnd + 1" [tabIndexStart]="orga.tabIndexEnd + 1"
@@ -61,7 +56,6 @@
[validatorFns]="addressValidators" [validatorFns]="addressValidators"
[defaults]="{ country: 'DEU' }" [defaults]="{ country: 'DEU' }"
></app-address-form-block> ></app-address-form-block>
<app-phone-numbers-form-block <app-phone-numbers-form-block
#phoneNumbers #phoneNumbers
[tabIndexStart]="address.tabIndexEnd + 1" [tabIndexStart]="address.tabIndexEnd + 1"
@@ -69,7 +63,6 @@
(dataChanges)="patchFormData('phoneNumbers', $event)" (dataChanges)="patchFormData('phoneNumbers', $event)"
(onInit)="addFormBlock('phoneNumbers', $event)" (onInit)="addFormBlock('phoneNumbers', $event)"
></app-phone-numbers-form-block> ></app-phone-numbers-form-block>
<app-birth-date-form-block <app-birth-date-form-block
#birthDate #birthDate
[tabIndexStart]="phoneNumbers.tabIndexEnd + 1" [tabIndexStart]="phoneNumbers.tabIndexEnd + 1"
@@ -77,7 +70,6 @@
[data]="data.birthDate" [data]="data.birthDate"
(dataChanges)="patchFormData('birthDate', $event)" (dataChanges)="patchFormData('birthDate', $event)"
></app-birth-date-form-block> ></app-birth-date-form-block>
<app-deviating-address-form-block <app-deviating-address-form-block
[tabIndexStart]="birthDate.tabIndexEnd + 1" [tabIndexStart]="birthDate.tabIndexEnd + 1"
[data]="data.deviatingDeliveryAddress" [data]="data.deviatingDeliveryAddress"
@@ -92,7 +84,6 @@
> >
Die Lieferadresse weicht von der Rechnungsadresse ab Die Lieferadresse weicht von der Rechnungsadresse ab
</app-deviating-address-form-block> </app-deviating-address-form-block>
<div class="spacer"></div> <div class="spacer"></div>
<div class="sticky w-full flex items-center justify-center"> <div class="sticky w-full flex items-center justify-center">
<button class="cta-submit" type="button" (click)="save()" [disabled]="form.invalid || form.pending"> <button class="cta-submit" type="button" (click)="save()" [disabled]="form.invalid || form.pending">
@@ -100,3 +91,4 @@
</button> </button>
</div> </div>
</form> </form>
}

View File

@@ -1,10 +1,10 @@
<form *ngIf="formData$ | async; let data" (keydown.enter)="$event.preventDefault()"> @if (formData$ | async; as data) {
<form (keydown.enter)="$event.preventDefault()">
<h1 class="title flex flex-row items-center justify-center"> <h1 class="title flex flex-row items-center justify-center">
Kundendaten erfassen Kundendaten erfassen
<!-- <span <!-- <span
class="rounded-full ml-4 h-8 w-8 text-xl text-center border-2 border-solid border-brand text-brand">i</span> --> class="rounded-full ml-4 h-8 w-8 text-xl text-center border-2 border-solid border-brand text-brand">i</span> -->
</h1> </h1>
<p class="description"> <p class="description">
Um Sie als Kunde beim nächsten Um Sie als Kunde beim nächsten
<br /> <br />
@@ -12,7 +12,6 @@
<br /> <br />
wir Ihnen gerne eine Kundenkarte an. wir Ihnen gerne eine Kundenkarte an.
</p> </p>
<app-customer-type-selector <app-customer-type-selector
[processId]="processId$ | async" [processId]="processId$ | async"
[p4mUser]="true" [p4mUser]="true"
@@ -20,7 +19,6 @@
(valueChanges)="customerTypeChanged($event)" (valueChanges)="customerTypeChanged($event)"
[p4mReadonly]="data?._meta?.p4mRequired" [p4mReadonly]="data?._meta?.p4mRequired"
></app-customer-type-selector> ></app-customer-type-selector>
<app-p4m-number-form-block <app-p4m-number-form-block
#p4mBlock #p4mBlock
[tabIndexStart]="1" [tabIndexStart]="1"
@@ -31,7 +29,6 @@
[focusAfterInit]="!data?._meta?.p4mRequired" [focusAfterInit]="!data?._meta?.p4mRequired"
[asyncValidatorFns]="asyncLoyaltyCardValidatorFn" [asyncValidatorFns]="asyncLoyaltyCardValidatorFn"
></app-p4m-number-form-block> ></app-p4m-number-form-block>
<app-accept-agb-form-block <app-accept-agb-form-block
[tabIndexStart]="inBlock.tabIndexEnd + 1" [tabIndexStart]="inBlock.tabIndexEnd + 1"
(onInit)="addFormBlock('agb', $event)" (onInit)="addFormBlock('agb', $event)"
@@ -40,7 +37,6 @@
[requiredMark]="true" [requiredMark]="true"
[validatorFns]="agbValidatorFns" [validatorFns]="agbValidatorFns"
></app-accept-agb-form-block> ></app-accept-agb-form-block>
<app-newsletter-form-block <app-newsletter-form-block
class="mb-4" class="mb-4"
#newsletterBlock #newsletterBlock
@@ -50,7 +46,6 @@
(dataChanges)="patchFormData('newsletter', $event)" (dataChanges)="patchFormData('newsletter', $event)"
[focusAfterInit]="data?._meta?.p4mRequired" [focusAfterInit]="data?._meta?.p4mRequired"
></app-newsletter-form-block> ></app-newsletter-form-block>
<app-name-form-block <app-name-form-block
#nameBlock #nameBlock
[tabIndexStart]="newsletterBlock.tabIndexEnd + 1" [tabIndexStart]="newsletterBlock.tabIndexEnd + 1"
@@ -60,13 +55,13 @@
[validatorFns]="nameValidationFns" [validatorFns]="nameValidationFns"
(dataChanges)="patchFormData('name', $event)" (dataChanges)="patchFormData('name', $event)"
></app-name-form-block> ></app-name-form-block>
@if (customerType === 'webshop-p4m') {
<p class="info" *ngIf="customerType === 'webshop-p4m'"> <p class="info">
Wir werden Ihnen Werbung zu ähnlichen Produkten oder Dienstleistungen aus unserem Sortiment per E-Mail zusenden. Sie können der Wir werden Ihnen Werbung zu ähnlichen Produkten oder Dienstleistungen aus unserem Sortiment per E-Mail zusenden. Sie können der
Verwendung Ihrer Daten jederzeit z.B. mittels der in den E-Mails enthaltenen Abmeldelinks widersprechen, ohne dass hierfür andere als Verwendung Ihrer Daten jederzeit z.B. mittels der in den E-Mails enthaltenen Abmeldelinks widersprechen, ohne dass hierfür andere als
die Übermittlungskosten nach den Basistarifen entstehen. die Übermittlungskosten nach den Basistarifen entstehen.
</p> </p>
}
<app-email-form-block <app-email-form-block
class="flex-grow" class="flex-grow"
#email #email
@@ -78,7 +73,6 @@
[validatorFns]="emailValidatorFn" [validatorFns]="emailValidatorFn"
[asyncValidatorFns]="asyncEmailVlaidtorFn" [asyncValidatorFns]="asyncEmailVlaidtorFn"
></app-email-form-block> ></app-email-form-block>
<app-organisation-form-block <app-organisation-form-block
#orgBlock #orgBlock
[tabIndexStart]="email.tabIndexEnd + 1" [tabIndexStart]="email.tabIndexEnd + 1"
@@ -87,7 +81,6 @@
[data]="data.organisation" [data]="data.organisation"
(dataChanges)="patchFormData('organisation', $event)" (dataChanges)="patchFormData('organisation', $event)"
></app-organisation-form-block> ></app-organisation-form-block>
<app-address-form-block <app-address-form-block
[defaults]="{ country: 'DEU' }" [defaults]="{ country: 'DEU' }"
#addressBlock #addressBlock
@@ -98,7 +91,6 @@
[requiredMarks]="addressRequiredMarks" [requiredMarks]="addressRequiredMarks"
[validatorFns]="addressValidatorFns" [validatorFns]="addressValidatorFns"
></app-address-form-block> ></app-address-form-block>
<app-deviating-address-form-block <app-deviating-address-form-block
#ddaBlock #ddaBlock
[defaults]="{ address: { country: 'DEU' } }" [defaults]="{ address: { country: 'DEU' } }"
@@ -113,7 +105,6 @@
> >
Die Lieferadresse weicht von der Rechnungsadresse ab Die Lieferadresse weicht von der Rechnungsadresse ab
</app-deviating-address-form-block> </app-deviating-address-form-block>
<app-phone-numbers-form-block <app-phone-numbers-form-block
#phoneNumbers #phoneNumbers
[tabIndexStart]="ddaBlock.tabIndexEnd + 1" [tabIndexStart]="ddaBlock.tabIndexEnd + 1"
@@ -121,7 +112,6 @@
[data]="data.phoneNumbers" [data]="data.phoneNumbers"
(dataChanges)="patchFormData('phoneNumbers', $event)" (dataChanges)="patchFormData('phoneNumbers', $event)"
></app-phone-numbers-form-block> ></app-phone-numbers-form-block>
<app-birth-date-form-block <app-birth-date-form-block
#bdBlock #bdBlock
[tabIndexStart]="phoneNumbers.tabIndexEnd + 1" [tabIndexStart]="phoneNumbers.tabIndexEnd + 1"
@@ -131,7 +121,6 @@
[requiredMark]="true" [requiredMark]="true"
[validatorFns]="birthDateValidatorFns" [validatorFns]="birthDateValidatorFns"
></app-birth-date-form-block> ></app-birth-date-form-block>
<app-interests-form-block <app-interests-form-block
#inBlock #inBlock
[tabIndexStart]="bdBlock.tabIndexEnd + 1" [tabIndexStart]="bdBlock.tabIndexEnd + 1"
@@ -139,12 +128,11 @@
[data]="data.interests" [data]="data.interests"
(dataChanges)="patchFormData('interests', $event)" (dataChanges)="patchFormData('interests', $event)"
></app-interests-form-block> ></app-interests-form-block>
<div class="spacer"></div> <div class="spacer"></div>
<div class="sticky w-full flex items-center justify-center"> <div class="sticky w-full flex items-center justify-center">
<button class="cta-submit" type="button" [disabled]="form.invalid || form.pending" (click)="save()"> <button class="cta-submit" type="button" [disabled]="form.invalid || form.pending" (click)="save()">
<ui-spinner [show]="busy$ | async">Speichern</ui-spinner> <ui-spinner [show]="busy$ | async">Speichern</ui-spinner>
</button> </button>
</div> </div>
</form> </form>
}

View File

@@ -1,14 +1,13 @@
<form *ngIf="formData$ | async; let data" (keydown.enter)="$event.preventDefault()"> @if (formData$ | async; as data) {
<form (keydown.enter)="$event.preventDefault()">
<h1 class="title">Kundendaten erfassen</h1> <h1 class="title">Kundendaten erfassen</h1>
<p class="description">Wir legen Ihnen gerne ein Kundenkonto an</p> <p class="description">Wir legen Ihnen gerne ein Kundenkonto an</p>
<app-customer-type-selector <app-customer-type-selector
[processId]="processId$ | async" [processId]="processId$ | async"
[p4mUser]="false" [p4mUser]="false"
customerType="store" customerType="store"
(valueChanges)="customerTypeChanged($event)" (valueChanges)="customerTypeChanged($event)"
></app-customer-type-selector> ></app-customer-type-selector>
<app-name-form-block <app-name-form-block
#name #name
[tabIndexStart]="1" [tabIndexStart]="1"
@@ -18,7 +17,6 @@
[data]="data.name" [data]="data.name"
(dataChanges)="patchFormData('name', $event)" (dataChanges)="patchFormData('name', $event)"
></app-name-form-block> ></app-name-form-block>
<app-email-form-block <app-email-form-block
#email #email
[tabIndexStart]="name.tabIndexEnd + 1" [tabIndexStart]="name.tabIndexEnd + 1"
@@ -27,7 +25,6 @@
[data]="data.email" [data]="data.email"
(dataChanges)="patchFormData('email', $event)" (dataChanges)="patchFormData('email', $event)"
></app-email-form-block> ></app-email-form-block>
<app-organisation-form-block <app-organisation-form-block
#orga #orga
[tabIndexStart]="email.tabIndexEnd + 1" [tabIndexStart]="email.tabIndexEnd + 1"
@@ -36,7 +33,6 @@
[data]="data.organisation" [data]="data.organisation"
(dataChanges)="patchFormData('organisation', $event)" (dataChanges)="patchFormData('organisation', $event)"
></app-organisation-form-block> ></app-organisation-form-block>
<app-address-form-block <app-address-form-block
#address #address
[tabIndexStart]="orga.tabIndexEnd + 1" [tabIndexStart]="orga.tabIndexEnd + 1"
@@ -44,7 +40,6 @@
[data]="data.address" [data]="data.address"
(dataChanges)="patchFormData('address', $event)" (dataChanges)="patchFormData('address', $event)"
></app-address-form-block> ></app-address-form-block>
<app-phone-numbers-form-block <app-phone-numbers-form-block
#phoneNumbers #phoneNumbers
[tabIndexStart]="address.tabIndexEnd + 1" [tabIndexStart]="address.tabIndexEnd + 1"
@@ -52,7 +47,6 @@
[data]="data.phoneNumbers" [data]="data.phoneNumbers"
(dataChanges)="patchFormData('phoneNumbers', $event)" (dataChanges)="patchFormData('phoneNumbers', $event)"
></app-phone-numbers-form-block> ></app-phone-numbers-form-block>
<app-birth-date-form-block <app-birth-date-form-block
#birthDate #birthDate
[tabIndexStart]="phoneNumbers.tabIndexEnd + 1" [tabIndexStart]="phoneNumbers.tabIndexEnd + 1"
@@ -60,7 +54,6 @@
[data]="data.birthDate" [data]="data.birthDate"
(dataChanges)="patchFormData('birthDate', $event)" (dataChanges)="patchFormData('birthDate', $event)"
></app-birth-date-form-block> ></app-birth-date-form-block>
<app-deviating-address-form-block <app-deviating-address-form-block
[tabIndexStart]="birthDate.tabIndexEnd + 1" [tabIndexStart]="birthDate.tabIndexEnd + 1"
(onInit)="addFormBlock('deviatingDeliveryAddress', $event)" (onInit)="addFormBlock('deviatingDeliveryAddress', $event)"
@@ -75,12 +68,11 @@
> >
Die Lieferadresse weicht von der Rechnungsadresse ab Die Lieferadresse weicht von der Rechnungsadresse ab
</app-deviating-address-form-block> </app-deviating-address-form-block>
<div class="spacer"></div> <div class="spacer"></div>
<div class="sticky w-full flex items-center justify-center"> <div class="sticky w-full flex items-center justify-center">
<button class="cta-submit" type="button" [disabled]="form.invalid || form.pending" (click)="save()"> <button class="cta-submit" type="button" [disabled]="form.invalid || form.pending" (click)="save()">
<ui-spinner [show]="busy$ | async">Speichern</ui-spinner> <ui-spinner [show]="busy$ | async">Speichern</ui-spinner>
</button> </button>
</div> </div>
</form> </form>
}

View File

@@ -1,4 +1,5 @@
<form *ngIf="formData$ | async; let data" (keydown.enter)="$event.preventDefault()"> @if (formData$ | async; as data) {
<form (keydown.enter)="$event.preventDefault()">
<h1 class="title">Kundendaten erfassen</h1> <h1 class="title">Kundendaten erfassen</h1>
<p class="description"> <p class="description">
Wenn Sie möchten legen wir Ihnen Wenn Sie möchten legen wir Ihnen
@@ -7,14 +8,12 @@
<br /> <br />
Sie Ihre Bestellungen einsehen. Sie Ihre Bestellungen einsehen.
</p> </p>
<app-customer-type-selector <app-customer-type-selector
[processId]="processId$ | async" [processId]="processId$ | async"
[p4mUser]="false" [p4mUser]="false"
customerType="webshop" customerType="webshop"
(valueChanges)="customerTypeChanged($event)" (valueChanges)="customerTypeChanged($event)"
></app-customer-type-selector> ></app-customer-type-selector>
<app-name-form-block <app-name-form-block
#name #name
[tabIndexStart]="1" [tabIndexStart]="1"
@@ -24,13 +23,11 @@
[data]="data.name" [data]="data.name"
(dataChanges)="patchFormData('name', $event)" (dataChanges)="patchFormData('name', $event)"
></app-name-form-block> ></app-name-form-block>
<p class="info"> <p class="info">
Wir werden Ihnen Werbung zu ähnlichen Produkten oder Dienstleistungen aus unserem Sortiment per E-Mail zusenden. Sie können der Wir werden Ihnen Werbung zu ähnlichen Produkten oder Dienstleistungen aus unserem Sortiment per E-Mail zusenden. Sie können der
Verwendung Ihrer Daten jederzeit z.B. mittels der in den E-Mails enthaltenen Abmeldelinks widersprechen, ohne dass hierfür andere als Verwendung Ihrer Daten jederzeit z.B. mittels der in den E-Mails enthaltenen Abmeldelinks widersprechen, ohne dass hierfür andere als
die Übermittlungskosten nach den Basistarifen entstehen. die Übermittlungskosten nach den Basistarifen entstehen.
</p> </p>
<app-email-form-block <app-email-form-block
#email #email
[tabIndexStart]="name.tabIndexEnd + 1" [tabIndexStart]="name.tabIndexEnd + 1"
@@ -41,7 +38,6 @@
[data]="data.email" [data]="data.email"
(dataChanges)="patchFormData('email', $event)" (dataChanges)="patchFormData('email', $event)"
></app-email-form-block> ></app-email-form-block>
<app-organisation-form-block <app-organisation-form-block
#org #org
[tabIndexStart]="email.tabIndexEnd + 1" [tabIndexStart]="email.tabIndexEnd + 1"
@@ -50,7 +46,6 @@
[data]="data.organisation" [data]="data.organisation"
(dataChanges)="patchFormData('organisation', $event)" (dataChanges)="patchFormData('organisation', $event)"
></app-organisation-form-block> ></app-organisation-form-block>
<app-address-form-block <app-address-form-block
#address #address
[tabIndexStart]="org.tabIndexEnd + 1" [tabIndexStart]="org.tabIndexEnd + 1"
@@ -61,9 +56,7 @@
[data]="data.address" [data]="data.address"
(dataChanges)="patchFormData('address', $event)" (dataChanges)="patchFormData('address', $event)"
></app-address-form-block> ></app-address-form-block>
<p class="info">Das Anlegen geht für Sie noch schneller, wenn wir Ihnen das initiale Passwort per SMS auf Ihr Mobilgerät schicken.</p> <p class="info">Das Anlegen geht für Sie noch schneller, wenn wir Ihnen das initiale Passwort per SMS auf Ihr Mobilgerät schicken.</p>
<app-phone-numbers-form-block <app-phone-numbers-form-block
#phoneNumbers #phoneNumbers
[tabIndexStart]="address.tabIndexEnd + 1" [tabIndexStart]="address.tabIndexEnd + 1"
@@ -71,7 +64,6 @@
[data]="data.phoneNumbers" [data]="data.phoneNumbers"
(dataChanges)="patchFormData('phoneNumbers', $event)" (dataChanges)="patchFormData('phoneNumbers', $event)"
></app-phone-numbers-form-block> ></app-phone-numbers-form-block>
<app-birth-date-form-block <app-birth-date-form-block
#birthDate #birthDate
[tabIndexStart]="phoneNumbers.tabIndexEnd + 1" [tabIndexStart]="phoneNumbers.tabIndexEnd + 1"
@@ -79,7 +71,6 @@
[data]="data.birthDate" [data]="data.birthDate"
(dataChanges)="patchFormData('birthDate', $event)" (dataChanges)="patchFormData('birthDate', $event)"
></app-birth-date-form-block> ></app-birth-date-form-block>
<app-deviating-address-form-block <app-deviating-address-form-block
[tabIndexStart]="birthDate.tabIndexEnd + 1" [tabIndexStart]="birthDate.tabIndexEnd + 1"
(onInit)="addFormBlock('deviatingDeliveryAddress', $event)" (onInit)="addFormBlock('deviatingDeliveryAddress', $event)"
@@ -94,7 +85,6 @@
> >
Die Lieferadresse weicht von der Rechnungsadresse ab Die Lieferadresse weicht von der Rechnungsadresse ab
</app-deviating-address-form-block> </app-deviating-address-form-block>
<div class="spacer"></div> <div class="spacer"></div>
<div class="sticky w-full flex items-center justify-center"> <div class="sticky w-full flex items-center justify-center">
<button class="cta-submit" type="button" [disabled]="form.invalid || form.pending" (click)="save()"> <button class="cta-submit" type="button" [disabled]="form.invalid || form.pending" (click)="save()">
@@ -102,3 +92,4 @@
</button> </button>
</div> </div>
</form> </form>
}

View File

@@ -1,4 +1,4 @@
import { CommonModule } from '@angular/common';
import { Component, ChangeDetectionStrategy } from '@angular/core'; import { Component, ChangeDetectionStrategy } from '@angular/core';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
@@ -7,7 +7,7 @@ import { RouterModule } from '@angular/router';
templateUrl: 'customer-create-side-view.component.html', templateUrl: 'customer-create-side-view.component.html',
styleUrls: ['customer-create-side-view.component.css'], styleUrls: ['customer-create-side-view.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule, RouterModule], imports: [RouterModule],
}) })
export class CustomerCreateSideViewComponent { export class CustomerCreateSideViewComponent {
constructor() {} constructor() {}

View File

@@ -1,14 +1,13 @@
<form *ngIf="formData$ | async; let data" (keydown.enter)="$event.preventDefault()"> @if (formData$ | async; as data) {
<form (keydown.enter)="$event.preventDefault()">
<h1 class="title flex flex-row items-center justify-center">Kundenkartendaten erfasen</h1> <h1 class="title flex flex-row items-center justify-center">Kundenkartendaten erfasen</h1>
<p class="description">Bitte erfassen Sie die Kundenkarte</p> <p class="description">Bitte erfassen Sie die Kundenkarte</p>
<app-customer-type-selector <app-customer-type-selector
[processId]="processId$ | async" [processId]="processId$ | async"
[p4mUser]="true" [p4mUser]="true"
customerType="webshop" customerType="webshop"
[readonly]="true" [readonly]="true"
></app-customer-type-selector> ></app-customer-type-selector>
<app-p4m-number-form-block <app-p4m-number-form-block
#p4mBlock #p4mBlock
[tabIndexStart]="1" [tabIndexStart]="1"
@@ -18,7 +17,6 @@
[focusAfterInit]="!data?._meta?.p4mRequired" [focusAfterInit]="!data?._meta?.p4mRequired"
[asyncValidatorFns]="asyncLoyaltyCardValidatorFn" [asyncValidatorFns]="asyncLoyaltyCardValidatorFn"
></app-p4m-number-form-block> ></app-p4m-number-form-block>
<app-accept-agb-form-block <app-accept-agb-form-block
[tabIndexStart]="inBlock.tabIndexEnd + 1" [tabIndexStart]="inBlock.tabIndexEnd + 1"
(onInit)="addFormBlock('agb', $event)" (onInit)="addFormBlock('agb', $event)"
@@ -27,7 +25,6 @@
[requiredMark]="true" [requiredMark]="true"
[validatorFns]="agbValidatorFns" [validatorFns]="agbValidatorFns"
></app-accept-agb-form-block> ></app-accept-agb-form-block>
<app-newsletter-form-block <app-newsletter-form-block
class="mb-4" class="mb-4"
#newsletterBlock #newsletterBlock
@@ -37,20 +34,15 @@
(dataChanges)="patchFormData('newsletter', $event)" (dataChanges)="patchFormData('newsletter', $event)"
[focusAfterInit]="data?._meta?.p4mRequired" [focusAfterInit]="data?._meta?.p4mRequired"
></app-newsletter-form-block> ></app-newsletter-form-block>
<app-name-form-block (onInit)="addFormBlock('name', $event)" [data]="data.name" readonly></app-name-form-block> <app-name-form-block (onInit)="addFormBlock('name', $event)" [data]="data.name" readonly></app-name-form-block>
<app-email-form-block (onInit)="addFormBlock('email', $event)" [data]="data.email" readonly></app-email-form-block> <app-email-form-block (onInit)="addFormBlock('email', $event)" [data]="data.email" readonly></app-email-form-block>
<app-organisation-form-block <app-organisation-form-block
(onInit)="addFormBlock('organisation', $event)" (onInit)="addFormBlock('organisation', $event)"
appearence="compact" appearence="compact"
[data]="data.organisation" [data]="data.organisation"
readonly readonly
></app-organisation-form-block> ></app-organisation-form-block>
<app-address-form-block [data]="data.address" readonly></app-address-form-block> <app-address-form-block [data]="data.address" readonly></app-address-form-block>
<div class="mt-8"> <div class="mt-8">
<h4 class="-mb-6">Rechnungsadresse</h4> <h4 class="-mb-6">Rechnungsadresse</h4>
<ui-form-control class="-mb-5" [showHint]="false"> <ui-form-control class="-mb-5" [showHint]="false">
@@ -71,7 +63,6 @@
Abweichende Rechnungsadresse anlegen Abweichende Rechnungsadresse anlegen
</app-deviating-address-form-block> </app-deviating-address-form-block>
</div> </div>
<div class="mt-8"> <div class="mt-8">
<h4 class="-mb-6">Lieferadresse</h4> <h4 class="-mb-6">Lieferadresse</h4>
<ui-form-control class="-mb-5" [showHint]="false"> <ui-form-control class="-mb-5" [showHint]="false">
@@ -92,7 +83,6 @@
Abweichende Lieferadresse anlegen Abweichende Lieferadresse anlegen
</app-deviating-address-form-block> </app-deviating-address-form-block>
</div> </div>
<app-birth-date-form-block <app-birth-date-form-block
#bdBlock #bdBlock
[tabIndexStart]="ddaBlock.tabIndexEnd + 1" [tabIndexStart]="ddaBlock.tabIndexEnd + 1"
@@ -102,7 +92,6 @@
[requiredMark]="true" [requiredMark]="true"
[validatorFns]="birthDateValidatorFns" [validatorFns]="birthDateValidatorFns"
></app-birth-date-form-block> ></app-birth-date-form-block>
<app-interests-form-block <app-interests-form-block
#inBlock #inBlock
[tabIndexStart]="bdBlock.tabIndexEnd + 1" [tabIndexStart]="bdBlock.tabIndexEnd + 1"
@@ -110,12 +99,11 @@
[data]="data.interests" [data]="data.interests"
(dataChanges)="patchFormData('interests', $event)" (dataChanges)="patchFormData('interests', $event)"
></app-interests-form-block> ></app-interests-form-block>
<div class="spacer"></div> <div class="spacer"></div>
<div class="sticky w-full flex items-center justify-center"> <div class="sticky w-full flex items-center justify-center">
<button class="cta-submit" type="button" [disabled]="form.invalid || form.pending" (click)="save()"> <button class="cta-submit" type="button" [disabled]="form.invalid || form.pending" (click)="save()">
<ui-spinner [show]="busy$ | async">Speichern</ui-spinner> <ui-spinner [show]="busy$ | async">Speichern</ui-spinner>
</button> </button>
</div> </div>
</form> </form>
}

View File

@@ -1,19 +1,22 @@
<div class="flex flex-row justify-end -mt-4 -mr-2"> <div class="flex flex-row justify-end -mt-4 -mr-2">
@if (detailsRoute$ | async; as detailsRoute) {
<a <a
*ngIf="detailsRoute$ | async; let detailsRoute"
[routerLink]="detailsRoute.path" [routerLink]="detailsRoute.path"
[queryParams]="detailsRoute.urlTree.queryParams" [queryParams]="detailsRoute.urlTree.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
> >
<shared-icon icon="close" [size]="32"></shared-icon> <shared-icon icon="close" [size]="32"></shared-icon>
</a> </a>
}
</div> </div>
<h1 class="text-2xl text-center font-bold mb-6">Rechnungsadresse hinzufügen</h1> <h1 class="text-2xl text-center font-bold mb-6">Rechnungsadresse hinzufügen</h1>
<form [formGroup]="formGroup" (ngSubmit)="save()"> <form [formGroup]="formGroup" (ngSubmit)="save()">
<shared-form-control label="Anrede"> <shared-form-control label="Anrede">
<shared-select formControlName="gender" placeholder="Anrede" tabindex="1" [autofocus]="true"> <shared-select formControlName="gender" placeholder="Anrede" tabindex="1" [autofocus]="true">
<shared-select-option *ngFor="let gender of genderSettings.genders" [value]="gender.value">{{ gender.label }}</shared-select-option> @for (gender of genderSettings.genders; track gender) {
<shared-select-option [value]="gender.value">{{ gender.label }}</shared-select-option>
}
</shared-select> </shared-select>
</shared-form-control> </shared-form-control>
@@ -62,9 +65,11 @@
<shared-form-control class="col-span-2" label="Land"> <shared-form-control class="col-span-2" label="Land">
<shared-select placeholder="Land" formControlName="country" tabindex="11"> <shared-select placeholder="Land" formControlName="country" tabindex="11">
<shared-select-option *ngFor="let country of countries$ | async" [value]="country.isO3166_A_3"> @for (country of countries$ | async; track country) {
<shared-select-option [value]="country.isO3166_A_3">
{{ country.name }} {{ country.name }}
</shared-select-option> </shared-select-option>
}
</shared-select> </shared-select>
</shared-form-control> </shared-form-control>

View File

@@ -6,7 +6,7 @@ import { FormControlComponent } from '@shared/components/form-control';
import { CrmCustomerService } from '@domain/crm'; import { CrmCustomerService } from '@domain/crm';
import { AddressDTO, Gender, PayerDTO } from '@generated/swagger/crm-api'; import { AddressDTO, Gender, PayerDTO } from '@generated/swagger/crm-api';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { AsyncPipe, NgForOf, NgIf } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { AddressSelectionModalService } from '@modal/address-selection'; import { AddressSelectionModalService } from '@modal/address-selection';
import { CustomerSearchStore } from '../store'; import { CustomerSearchStore } from '../store';
import { CustomerSearchNavigation } from '@shared/services/navigation'; import { CustomerSearchNavigation } from '@shared/services/navigation';
@@ -26,12 +26,10 @@ import { GenderSettingsService } from '@shared/services/gender';
IconComponent, IconComponent,
RouterLink, RouterLink,
AsyncPipe, AsyncPipe,
NgIf,
NgForOf,
ReactiveFormsModule, ReactiveFormsModule,
SelectModule, SelectModule,
FormControlComponent, FormControlComponent,
CheckboxComponent, CheckboxComponent
], ],
}) })
export class AddBillingAddressMainViewComponent { export class AddBillingAddressMainViewComponent {

View File

@@ -1,17 +1,18 @@
<div class="flex flex-row justify-end -mt-4 -mr-2"> <div class="flex flex-row justify-end -mt-4 -mr-2">
@if (detailsRoute$ | async; as detailsRoute) {
<a <a
*ngIf="detailsRoute$ | async; let detailsRoute"
[routerLink]="detailsRoute.path" [routerLink]="detailsRoute.path"
[queryParams]="detailsRoute.urlTree.queryParams" [queryParams]="detailsRoute.urlTree.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
> >
<shared-icon icon="close" [size]="32"></shared-icon> <shared-icon icon="close" [size]="32"></shared-icon>
</a> </a>
}
</div> </div>
<h1 class="text-2xl text-center font-bold mb-6">Lieferadresse hinzufügen</h1> <h1 class="text-2xl text-center font-bold mb-6">Lieferadresse hinzufügen</h1>
<form [formGroup]="formGroup" (ngSubmit)="save()"> <form [formGroup]="formGroup" (ngSubmit)="save()">
<ng-container *ngIf="isBusinessKonto$ | async"> @if (isBusinessKonto$ | async) {
<shared-form-control <shared-form-control
[label]="formGroup.controls.organisation.errors?.required ? 'Firma *' : 'Firma'" [label]="formGroup.controls.organisation.errors?.required ? 'Firma *' : 'Firma'"
class="col-span-2" class="col-span-2"
@@ -24,7 +25,6 @@
tabindex="1" tabindex="1"
/> />
</shared-form-control> </shared-form-control>
<shared-form-control label="Abteilung"> <shared-form-control label="Abteilung">
<input <input
class="input-control" class="input-control"
@@ -34,7 +34,6 @@
tabindex="2" tabindex="2"
/> />
</shared-form-control> </shared-form-control>
<shared-form-control label="USt-ID"> <shared-form-control label="USt-ID">
<input <input
class="input-control" class="input-control"
@@ -44,13 +43,15 @@
tabindex="3" tabindex="3"
/> />
</shared-form-control> </shared-form-control>
</ng-container> }
<shared-form-control label="Anrede"> <shared-form-control label="Anrede">
<shared-select formControlName="gender" placeholder="Anrede" tabindex="4" [autofocus]="true"> <shared-select formControlName="gender" placeholder="Anrede" tabindex="4" [autofocus]="true">
<shared-select-option *ngFor="let gender of genderSettings.genders" [value]="gender.value">{{ @for (gender of genderSettings.genders; track gender) {
<shared-select-option [value]="gender.value">{{
gender.label gender.label
}}</shared-select-option> }}</shared-select-option>
}
</shared-select> </shared-select>
</shared-form-control> </shared-form-control>
@@ -89,7 +90,7 @@
/> />
</shared-form-control> </shared-form-control>
<ng-container *ngIf="!(isBusinessKonto$ | async)"> @if (!(isBusinessKonto$ | async)) {
<shared-form-control label="Firma" class="col-span-2"> <shared-form-control label="Firma" class="col-span-2">
<input <input
class="input-control" class="input-control"
@@ -99,7 +100,7 @@
tabindex="8" tabindex="8"
/> />
</shared-form-control> </shared-form-control>
</ng-container> }
<shared-form-control label="Straße"> <shared-form-control label="Straße">
<input <input
@@ -153,12 +154,13 @@
<shared-form-control class="col-span-2" label="Land"> <shared-form-control class="col-span-2" label="Land">
<shared-select placeholder="Land" formControlName="country" tabindex="14"> <shared-select placeholder="Land" formControlName="country" tabindex="14">
@for (country of countries$ | async; track country) {
<shared-select-option <shared-select-option
*ngFor="let country of countries$ | async"
[value]="country.isO3166_A_3" [value]="country.isO3166_A_3"
> >
{{ country.name }} {{ country.name }}
</shared-select-option> </shared-select-option>
}
</shared-select> </shared-select>
</shared-form-control> </shared-form-control>

View File

@@ -6,7 +6,7 @@ import { FormControlComponent } from '@shared/components/form-control';
import { CrmCustomerService } from '@domain/crm'; import { CrmCustomerService } from '@domain/crm';
import { AddressDTO, Gender, ShippingAddressDTO } from '@generated/swagger/crm-api'; import { AddressDTO, Gender, ShippingAddressDTO } from '@generated/swagger/crm-api';
import { map, takeUntil } from 'rxjs/operators'; import { map, takeUntil } from 'rxjs/operators';
import { AsyncPipe, NgForOf, NgIf } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { AddressSelectionModalService } from '@modal/address-selection'; import { AddressSelectionModalService } from '@modal/address-selection';
import { CustomerSearchStore } from '../store'; import { CustomerSearchStore } from '../store';
import { CustomerSearchNavigation } from '@shared/services/navigation'; import { CustomerSearchNavigation } from '@shared/services/navigation';
@@ -27,12 +27,10 @@ import { validateCompanyOrPersonalInfoRequired } from '../../validators/gender-b
RouterLink, RouterLink,
IconComponent, IconComponent,
AsyncPipe, AsyncPipe,
NgIf,
NgForOf,
ReactiveFormsModule, ReactiveFormsModule,
SelectModule, SelectModule,
FormControlComponent, FormControlComponent,
CheckboxComponent, CheckboxComponent
], ],
}) })
export class AddShippingAddressMainViewComponent implements OnInit, OnDestroy { export class AddShippingAddressMainViewComponent implements OnInit, OnDestroy {

View File

@@ -1,7 +1,7 @@
<div class="grid grid-flow-col items-center justify-between px-4 py-2 border-t-2 border-solid border-surface-2"> <div class="grid grid-flow-col items-center justify-between px-4 py-2 border-t-2 border-solid border-surface-2">
<h3 class="font-bold text-xl">Rechnungsadresse</h3> <h3 class="font-bold text-xl">Rechnungsadresse</h3>
@if (addBillingAddressRoute$ | async; as addRoute) {
<a <a
*ngIf="addBillingAddressRoute$ | async; let addRoute"
type="button" type="button"
class="text-brand font-bold" class="text-brand font-bold"
[routerLink]="addRoute.path" [routerLink]="addRoute.path"
@@ -10,26 +10,28 @@
> >
Hinzufügen Hinzufügen
</a> </a>
}
</div> </div>
<div class="grid grid-flow-row"> <div class="grid grid-flow-row">
@if (showCustomerAddress$ | async) {
<label <label
class="px-4 py-3 font-bold border-t-2 border-solid border-surface-2 flex flex-row justify-between items-center" class="px-4 py-3 font-bold border-t-2 border-solid border-surface-2 flex flex-row justify-between items-center"
*ngIf="showCustomerAddress$ | async"
> >
@if (isNotBusinessKonto$ | async) {
<input <input
*ngIf="isNotBusinessKonto$ | async"
name="assigned-payer" name="assigned-payer"
type="radio" type="radio"
[checked]="!(selectedPayer$ | async)" [checked]="!(selectedPayer$ | async)"
(change)="selectCustomerAddress()" (change)="selectCustomerAddress()"
/> />
}
<div class="ml-2 flex flex-row justify-between items-start grow"> <div class="ml-2 flex flex-row justify-between items-start grow">
<span class="mr-4"> <span class="mr-4">
{{ customer$ | async | address }} {{ customer$ | async | address }}
</span> </span>
@if (editRoute$ | async; as editRoute) {
<a <a
*ngIf="editRoute$ | async; let editRoute"
[routerLink]="editRoute.path" [routerLink]="editRoute.path"
[queryParams]="editRoute.queryParams" [queryParams]="editRoute.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
@@ -38,11 +40,13 @@
> >
Bearbeiten Bearbeiten
</a> </a>
}
</div> </div>
</label> </label>
}
@for (assignedPayer of assignedPayers$ | async; track assignedPayer) {
<label <label
class="px-4 py-3 font-bold border-t-2 border-solid border-surface-2 cursor-pointer flex flex-row items-center justify-start" class="px-4 py-3 font-bold border-t-2 border-solid border-surface-2 cursor-pointer flex flex-row items-center justify-start"
*ngFor="let assignedPayer of assignedPayers$ | async"
> >
<input <input
name="assigned-payer" name="assigned-payer"
@@ -55,9 +59,9 @@
<span class="mr-4"> <span class="mr-4">
{{ assignedPayer.payer.data | address }} {{ assignedPayer.payer.data | address }}
</span> </span>
<ng-container *ngIf="canEditAddress$ | async"> @if (canEditAddress$ | async) {
@if (editRoute(assignedPayer.payer.id); as editRoute) {
<a <a
*ngIf="editRoute(assignedPayer.payer.id); let editRoute"
class="text-brand font-bold" class="text-brand font-bold"
[routerLink]="editRoute.path" [routerLink]="editRoute.path"
[queryParams]="editRoute.queryParams" [queryParams]="editRoute.queryParams"
@@ -65,7 +69,9 @@
> >
Bearbeiten Bearbeiten
</a> </a>
</ng-container> }
}
</div> </div>
</label> </label>
}
</div> </div>

View File

@@ -4,7 +4,7 @@ import { CrmCustomerService } from '@domain/crm';
import { debounceTime, map, switchMap, takeUntil } from 'rxjs/operators'; import { debounceTime, map, switchMap, takeUntil } from 'rxjs/operators';
import { Observable, Subject, combineLatest } from 'rxjs'; import { Observable, Subject, combineLatest } from 'rxjs';
import { AssignedPayerDTO, CustomerDTO, ListResponseArgsOfAssignedPayerDTO } from '@generated/swagger/crm-api'; import { AssignedPayerDTO, CustomerDTO, ListResponseArgsOfAssignedPayerDTO } from '@generated/swagger/crm-api';
import { AsyncPipe, NgFor, NgIf } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { CustomerPipesModule } from '@shared/pipes/customer'; import { CustomerPipesModule } from '@shared/pipes/customer';
import { ComponentStore } from '@ngrx/component-store'; import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators'; import { tapResponse } from '@ngrx/operators';
@@ -26,7 +26,7 @@ interface DetailsMainViewBillingAddressesComponentState {
styleUrls: ['details-main-view-billing-addresses.component.css'], styleUrls: ['details-main-view-billing-addresses.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'page-details-main-view-billing-addresses' }, host: { class: 'page-details-main-view-billing-addresses' },
imports: [NgIf, NgFor, AsyncPipe, CustomerPipesModule, RouterLink], imports: [AsyncPipe, CustomerPipesModule, RouterLink],
}) })
export class DetailsMainViewBillingAddressesComponent export class DetailsMainViewBillingAddressesComponent
extends ComponentStore<DetailsMainViewBillingAddressesComponentState> extends ComponentStore<DetailsMainViewBillingAddressesComponentState>

View File

@@ -1,7 +1,7 @@
<div class="grid grid-flow-col items-center justify-between px-4 py-2 border-t-2 border-solid border-surface-2"> <div class="grid grid-flow-col items-center justify-between px-4 py-2 border-t-2 border-solid border-surface-2">
<h3 class="font-bold text-xl">Lieferadresse</h3> <h3 class="font-bold text-xl">Lieferadresse</h3>
@if (addShippingAddressRoute$ | async; as addRoute) {
<a <a
*ngIf="addShippingAddressRoute$ | async; let addRoute"
type="button" type="button"
class="text-brand font-bold" class="text-brand font-bold"
[routerLink]="addRoute.path" [routerLink]="addRoute.path"
@@ -10,20 +10,21 @@
> >
Hinzufügen Hinzufügen
</a> </a>
}
</div> </div>
<div class="grid grid-flow-row"> <div class="grid grid-flow-row">
@if (showCustomerAddress$ | async) {
<label <label
class="px-4 py-3 font-bold border-t-2 border-solid border-surface-2 cursor-pointer flex flex-row justify-start items-center" class="px-4 py-3 font-bold border-t-2 border-solid border-surface-2 cursor-pointer flex flex-row justify-start items-center"
*ngIf="showCustomerAddress$ | async"
> >
<input name="shipping-address" type="radio" [checked]="!(selectedShippingAddress$ | async)" (change)="selectCustomerAddress()" /> <input name="shipping-address" type="radio" [checked]="!(selectedShippingAddress$ | async)" (change)="selectCustomerAddress()" />
<div class="ml-2 flex flex-row justify-between items-start grow"> <div class="ml-2 flex flex-row justify-between items-start grow">
<span class="mr-4"> <span class="mr-4">
{{ customer$ | async | address }} {{ customer$ | async | address }}
</span> </span>
@if (editRoute$ | async; as editRoute) {
<a <a
*ngIf="editRoute$ | async; let editRoute"
[routerLink]="editRoute.path" [routerLink]="editRoute.path"
[queryParams]="editRoute.queryParams" [queryParams]="editRoute.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
@@ -32,11 +33,13 @@
> >
Bearbeiten Bearbeiten
</a> </a>
}
</div> </div>
</label> </label>
}
@for (shippingAddress of shippingAddresses$ | async; track shippingAddress) {
<label <label
class="px-4 py-3 font-bold border-t-2 border-solid border-surface-2 cursor-pointer flex flex-row justify-start items-center" class="px-4 py-3 font-bold border-t-2 border-solid border-surface-2 cursor-pointer flex flex-row justify-start items-center"
*ngFor="let shippingAddress of shippingAddresses$ | async"
> >
<input <input
name="shipping-address" name="shipping-address"
@@ -49,8 +52,8 @@
<span class="mr-4"> <span class="mr-4">
{{ shippingAddress | address }} {{ shippingAddress | address }}
</span> </span>
@if (editShippingAddressRoute$(shippingAddress.id) | async; as route) {
<a <a
*ngIf="editShippingAddressRoute$(shippingAddress.id) | async; let route"
class="text-brand font-bold" class="text-brand font-bold"
type="button" type="button"
[routerLink]="route?.path" [routerLink]="route?.path"
@@ -59,6 +62,8 @@
> >
Bearbeiten Bearbeiten
</a> </a>
}
</div> </div>
</label> </label>
}
</div> </div>

View File

@@ -4,7 +4,7 @@ import { CrmCustomerService } from '@domain/crm';
import { map, switchMap, takeUntil } from 'rxjs/operators'; import { map, switchMap, takeUntil } from 'rxjs/operators';
import { Observable, Subject, combineLatest } from 'rxjs'; import { Observable, Subject, combineLatest } from 'rxjs';
import { CustomerDTO, ListResponseArgsOfAssignedPayerDTO, ShippingAddressDTO } from '@generated/swagger/crm-api'; import { CustomerDTO, ListResponseArgsOfAssignedPayerDTO, ShippingAddressDTO } from '@generated/swagger/crm-api';
import { AsyncPipe, NgFor, NgIf } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { CustomerPipesModule } from '@shared/pipes/customer'; import { CustomerPipesModule } from '@shared/pipes/customer';
import { ComponentStore } from '@ngrx/component-store'; import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators'; import { tapResponse } from '@ngrx/operators';
@@ -25,7 +25,7 @@ interface DetailsMainViewDeliveryAddressesComponentState {
styleUrls: ['details-main-view-delivery-addresses.component.css'], styleUrls: ['details-main-view-delivery-addresses.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'page-details-main-view-delivery-addresses' }, host: { class: 'page-details-main-view-delivery-addresses' },
imports: [NgIf, NgFor, AsyncPipe, CustomerPipesModule, RouterLink], imports: [AsyncPipe, CustomerPipesModule, RouterLink],
}) })
export class DetailsMainViewDeliveryAddressesComponent export class DetailsMainViewDeliveryAddressesComponent
extends ComponentStore<DetailsMainViewDeliveryAddressesComponentState> extends ComponentStore<DetailsMainViewDeliveryAddressesComponentState>

View File

@@ -23,9 +23,9 @@
{{ customerType$ | async }} {{ customerType$ | async }}
</span> </span>
</div> </div>
<ng-container *ngIf="showEditButton$ | async"> @if (showEditButton$ | async) {
@if (editRoute$ | async; as editRoute) {
<a <a
*ngIf="editRoute$ | async; let editRoute"
[routerLink]="editRoute.path" [routerLink]="editRoute.path"
[queryParams]="editRoute.queryParams" [queryParams]="editRoute.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
@@ -33,30 +33,37 @@
> >
Bearbeiten Bearbeiten
</a> </a>
</ng-container> }
}
</div> </div>
<div class="customer-details-customer-main-data px-5 py-3 grid grid-flow-row gap-3"> <div class="customer-details-customer-main-data px-5 py-3 grid grid-flow-row gap-3">
<div class="flex flex-row"> <div class="flex flex-row">
<div class="data-label">Erstellungsdatum</div> <div class="data-label">Erstellungsdatum</div>
<div *ngIf="created$ | async; let created" class="data-value"> @if (created$ | async; as created) {
<div class="data-value">
{{ created | date: 'dd.MM.yyyy' }} | {{ created | date: 'HH:mm' }} Uhr {{ created | date: 'dd.MM.yyyy' }} | {{ created | date: 'HH:mm' }} Uhr
</div> </div>
}
</div> </div>
<div class="flex flex-row"> <div class="flex flex-row">
<div class="data-label">Kundennummer</div> <div class="data-label">Kundennummer</div>
<div class="data-value">{{ customerNumber$ | async }}</div> <div class="data-value">{{ customerNumber$ | async }}</div>
</div> </div>
<div class="flex flex-row" *ngIf="customerNumberDig$ | async; let customerNumberDig"> @if (customerNumberDig$ | async; as customerNumberDig) {
<div class="flex flex-row">
<div class="data-label">Kundennummer-DIG</div> <div class="data-label">Kundennummer-DIG</div>
<div class="data-value">{{ customerNumberDig }}</div> <div class="data-value">{{ customerNumberDig }}</div>
</div> </div>
<div class="flex flex-row" *ngIf="customerNumberBeeline$ | async; let customerNumberBeeline"> }
@if (customerNumberBeeline$ | async; as customerNumberBeeline) {
<div class="flex flex-row">
<div class="data-label">Kundennummer-BEELINE</div> <div class="data-label">Kundennummer-BEELINE</div>
<div class="data-value">{{ customerNumberBeeline }}</div> <div class="data-value">{{ customerNumberBeeline }}</div>
</div> </div>
}
</div> </div>
<ng-container *ngIf="isBusinessKonto$ | async"> @if (isBusinessKonto$ | async) {
<div class="customer-details-customer-main-row"> <div class="customer-details-customer-main-row">
<div class="data-label">Firmenname</div> <div class="data-label">Firmenname</div>
<div class="data-value">{{ organisationName$ | async }}</div> <div class="data-value">{{ organisationName$ | async }}</div>
@@ -69,7 +76,7 @@
<div class="data-label">USt-ID</div> <div class="data-label">USt-ID</div>
<div class="data-value">{{ vatId$ | async }}</div> <div class="data-value">{{ vatId$ | async }}</div>
</div> </div>
</ng-container> }
<div class="customer-details-customer-main-row"> <div class="customer-details-customer-main-row">
<div class="data-label">Anrede</div> <div class="data-label">Anrede</div>
@@ -113,7 +120,9 @@
</div> </div>
<div class="customer-details-customer-main-row"> <div class="customer-details-customer-main-row">
<div class="data-label">Land</div> <div class="data-label">Land</div>
<div *ngIf="country$ | async; let country" class="data-value">{{ country | country }}</div> @if (country$ | async; as country) {
<div class="data-value">{{ country | country }}</div>
}
</div> </div>
<div class="customer-details-customer-main-row"> <div class="customer-details-customer-main-row">
<div class="data-label">Festnetznr.</div> <div class="data-label">Festnetznr.</div>
@@ -124,18 +133,18 @@
<div class="data-value">{{ mobile$ | async }}</div> <div class="data-value">{{ mobile$ | async }}</div>
</div> </div>
<ng-container *ngIf="!(isBusinessKonto$ | async)"> @if (!(isBusinessKonto$ | async)) {
<div class="customer-details-customer-main-row"> <div class="customer-details-customer-main-row">
<div class="data-label">Geburtstag</div> <div class="data-label">Geburtstag</div>
<div class="data-value">{{ dateOfBirth$ | async | date: 'dd.MM.yyyy' }}</div> <div class="data-value">{{ dateOfBirth$ | async | date: 'dd.MM.yyyy' }}</div>
</div> </div>
</ng-container> }
<ng-container *ngIf="!(isBusinessKonto$ | async) && (organisationName$ | async)"> @if (!(isBusinessKonto$ | async) && (organisationName$ | async)) {
<div class="customer-details-customer-main-row"> <div class="customer-details-customer-main-row">
<div class="data-label">Firmenname</div> <div class="data-label">Firmenname</div>
<div class="data-value">{{ organisationName$ | async }}</div> <div class="data-value">{{ organisationName$ | async }}</div>
</div> </div>
<ng-container *ngIf="!(isOnlineOrCustomerCardUser$ | async)"> @if (!(isOnlineOrCustomerCardUser$ | async)) {
<div class="customer-details-customer-main-row"> <div class="customer-details-customer-main-row">
<div class="data-label">Abteilung</div> <div class="data-label">Abteilung</div>
<div class="data-value">{{ department$ | async }}</div> <div class="data-value">{{ department$ | async }}</div>
@@ -144,8 +153,8 @@
<div class="data-label">USt-ID</div> <div class="data-label">USt-ID</div>
<div class="data-value">{{ vatId$ | async }}</div> <div class="data-value">{{ vatId$ | async }}</div>
</div> </div>
</ng-container> }
</ng-container> }
<page-details-main-view-billing-addresses></page-details-main-view-billing-addresses> <page-details-main-view-billing-addresses></page-details-main-view-billing-addresses>
<page-details-main-view-delivery-addresses></page-details-main-view-delivery-addresses> <page-details-main-view-delivery-addresses></page-details-main-view-delivery-addresses>
@@ -153,8 +162,8 @@
</div> </div>
</shared-loader> </shared-loader>
@if (shoppingCartHasNoItems$ | async) {
<button <button
*ngIf="shoppingCartHasNoItems$ | async"
type="button" type="button"
(click)="continue()" (click)="continue()"
class="text-white text-lg bg-brand rounded-full px-5 py-3 absolute top-[calc(100vh-19.375rem)] left-1/2 -translate-x-1/2 font-bold disabled:bg-inactive-branch" class="text-white text-lg bg-brand rounded-full px-5 py-3 absolute top-[calc(100vh-19.375rem)] left-1/2 -translate-x-1/2 font-bold disabled:bg-inactive-branch"
@@ -162,9 +171,10 @@
> >
<shared-loader [loading]="showLoader$ | async" spinnerSize="32">Weiter zur Artikelsuche</shared-loader> <shared-loader [loading]="showLoader$ | async" spinnerSize="32">Weiter zur Artikelsuche</shared-loader>
</button> </button>
}
@if (shoppingCartHasItems$ | async) {
<button <button
*ngIf="shoppingCartHasItems$ | async"
type="button" type="button"
(click)="continue()" (click)="continue()"
class="text-white text-lg bg-brand rounded-full px-5 py-3 absolute top-[calc(100vh-19.375rem)] left-1/2 -translate-x-1/2 font-bold disabled:bg-inactive-branch" class="text-white text-lg bg-brand rounded-full px-5 py-3 absolute top-[calc(100vh-19.375rem)] left-1/2 -translate-x-1/2 font-bold disabled:bg-inactive-branch"
@@ -172,3 +182,4 @@
> >
<shared-loader [loading]="showLoader$ | async" spinnerSize="32">Weiter zum Warenkorb</shared-loader> <shared-loader [loading]="showLoader$ | async" spinnerSize="32">Weiter zum Warenkorb</shared-loader>
</button> </button>
}

View File

@@ -1,19 +1,22 @@
<div class="flex flex-row justify-end -mt-4 -mr-2"> <div class="flex flex-row justify-end -mt-4 -mr-2">
@if (detailsRoute$ | async; as detailsRoute) {
<a <a
*ngIf="detailsRoute$ | async; let detailsRoute"
[routerLink]="detailsRoute.path" [routerLink]="detailsRoute.path"
[queryParams]="detailsRoute.urlTree.queryParams" [queryParams]="detailsRoute.urlTree.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
> >
<shared-icon icon="close" [size]="32"></shared-icon> <shared-icon icon="close" [size]="32"></shared-icon>
</a> </a>
}
</div> </div>
<h1 class="text-2xl text-center font-bold mb-6">Rechnungsadresse bearbeiten</h1> <h1 class="text-2xl text-center font-bold mb-6">Rechnungsadresse bearbeiten</h1>
<form [formGroup]="formGroup" (ngSubmit)="save()"> <form [formGroup]="formGroup" (ngSubmit)="save()">
<shared-form-control label="Anrede"> <shared-form-control label="Anrede">
<shared-select formControlName="gender" placeholder="Anrede" tabindex="1" [autofocus]="true"> <shared-select formControlName="gender" placeholder="Anrede" tabindex="1" [autofocus]="true">
<shared-select-option *ngFor="let gender of genderSettings.genders" [value]="gender.value">{{ gender.label }}</shared-select-option> @for (gender of genderSettings.genders; track gender) {
<shared-select-option [value]="gender.value">{{ gender.label }}</shared-select-option>
}
</shared-select> </shared-select>
</shared-form-control> </shared-form-control>
@@ -62,9 +65,11 @@
<shared-form-control class="col-span-2" label="Land"> <shared-form-control class="col-span-2" label="Land">
<shared-select placeholder="Land" formControlName="country" tabindex="11"> <shared-select placeholder="Land" formControlName="country" tabindex="11">
<shared-select-option *ngFor="let country of countries$ | async" [value]="country.isO3166_A_3"> @for (country of countries$ | async; track country) {
<shared-select-option [value]="country.isO3166_A_3">
{{ country.name }} {{ country.name }}
</shared-select-option> </shared-select-option>
}
</shared-select> </shared-select>
</shared-form-control> </shared-form-control>

View File

@@ -6,7 +6,7 @@ import { FormControlComponent } from '@shared/components/form-control';
import { CrmCustomerService } from '@domain/crm'; import { CrmCustomerService } from '@domain/crm';
import { AddressDTO, Gender, PayerDTO } from '@generated/swagger/crm-api'; import { AddressDTO, Gender, PayerDTO } from '@generated/swagger/crm-api';
import { map, switchMap, takeUntil } from 'rxjs/operators'; import { map, switchMap, takeUntil } from 'rxjs/operators';
import { AsyncPipe, NgForOf } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { AddressSelectionModalService } from '@modal/address-selection'; import { AddressSelectionModalService } from '@modal/address-selection';
import { CustomerSearchStore } from '../store'; import { CustomerSearchStore } from '../store';
import { CustomerSearchNavigation } from '@shared/services/navigation'; import { CustomerSearchNavigation } from '@shared/services/navigation';
@@ -32,11 +32,10 @@ export interface EditBillingAddressMainViewState {
AsyncPipe, AsyncPipe,
RouterLink, RouterLink,
IconComponent, IconComponent,
NgForOf,
ReactiveFormsModule, ReactiveFormsModule,
SelectModule, SelectModule,
FormControlComponent, FormControlComponent,
CheckboxComponent, CheckboxComponent
], ],
}) })
export class EditBillingAddressMainViewComponent export class EditBillingAddressMainViewComponent

View File

@@ -1,6 +1,6 @@
<div class="customer-edit-header-actions flex flex-row justify-end pt-1 px-1"> <div class="customer-edit-header-actions flex flex-row justify-end pt-1 px-1">
@if (detailsRoute$ | async; as route) {
<a <a
*ngIf="detailsRoute$ | async; let route"
[routerLink]="route.path" [routerLink]="route.path"
[queryParams]="route.queryParams" [queryParams]="route.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
@@ -8,12 +8,14 @@
> >
<ui-icon [icon]="'close'"></ui-icon> <ui-icon [icon]="'close'"></ui-icon>
</a> </a>
}
</div> </div>
<div class="header"> <div class="header">
<h1>Firmendetails</h1> <h1>Firmendetails</h1>
</div> </div>
<form *ngIf="control" [formGroup]="control" (ngSubmit)="submit()"> @if (control) {
<form [formGroup]="control" (ngSubmit)="submit()">
<ng-container formGroupName="organisation"> <ng-container formGroupName="organisation">
<ui-form-control label="Firmenname" variant="inline"> <ui-form-control label="Firmenname" variant="inline">
<input uiInput type="text" formControlName="name" tabindex="1" /> <input uiInput type="text" formControlName="name" tabindex="1" />
@@ -25,10 +27,11 @@
<input uiInput type="text" formControlName="vatId" tabindex="3" /> <input uiInput type="text" formControlName="vatId" tabindex="3" />
</ui-form-control> </ui-form-control>
</ng-container> </ng-container>
<ui-form-control [clearable]="true" label="Anrede" variant="inline"> <ui-form-control [clearable]="true" label="Anrede" variant="inline">
<ui-select formControlName="gender" tabindex="4"> <ui-select formControlName="gender" tabindex="4">
<ui-select-option *ngFor="let gender of genderSettings.genders" [value]="gender.value" [label]="gender.label"></ui-select-option> @for (gender of genderSettings.genders; track gender) {
<ui-select-option [value]="gender.value" [label]="gender.label"></ui-select-option>
}
</ui-select> </ui-select>
</ui-form-control> </ui-form-control>
<ui-form-control [clearable]="true" label="Titel" variant="inline"> <ui-form-control [clearable]="true" label="Titel" variant="inline">
@@ -47,12 +50,10 @@
<ui-form-control label="Vorname" variant="inline"> <ui-form-control label="Vorname" variant="inline">
<input uiInput type="text" formControlName="firstName" tabindex="7" /> <input uiInput type="text" formControlName="firstName" tabindex="7" />
</ui-form-control> </ui-form-control>
<ng-container formGroupName="communicationDetails"> <ng-container formGroupName="communicationDetails">
<ui-form-control label="E-Mail" variant="inline"> <ui-form-control label="E-Mail" variant="inline">
<input uiInput type="mail" formControlName="email" tabindex="8" /> <input uiInput type="mail" formControlName="email" tabindex="8" />
</ui-form-control> </ui-form-control>
<ui-form-control label="Festnetznummer" variant="inline"> <ui-form-control label="Festnetznummer" variant="inline">
<input uiInput type="tel" formControlName="phone" tabindex="9" /> <input uiInput type="tel" formControlName="phone" tabindex="9" />
</ui-form-control> </ui-form-control>
@@ -60,7 +61,6 @@
<input uiInput type="tel" formControlName="mobile" tabindex="10" /> <input uiInput type="tel" formControlName="mobile" tabindex="10" />
</ui-form-control> </ui-form-control>
</ng-container> </ng-container>
<ng-container formGroupName="address"> <ng-container formGroupName="address">
<ui-form-control label="Straße" variant="inline"> <ui-form-control label="Straße" variant="inline">
<input uiInput type="text" formControlName="street" tabindex="11" /> <input uiInput type="text" formControlName="street" tabindex="11" />
@@ -79,20 +79,27 @@
</ui-form-control> </ui-form-control>
<ui-form-control [clearable]="true" label="Land" variant="inline"> <ui-form-control [clearable]="true" label="Land" variant="inline">
<ui-select formControlName="country" tabindex="16"> <ui-select formControlName="country" tabindex="16">
@for (country of countries$ | async; track country) {
<ui-select-option <ui-select-option
*ngFor="let country of countries$ | async"
[label]="country.name" [label]="country.name"
[value]="country.isO3166_A_3" [value]="country.isO3166_A_3"
></ui-select-option> ></ui-select-option>
}
</ui-select> </ui-select>
</ui-form-control> </ui-form-control>
</ng-container> </ng-container>
<div class="actions"> <div class="actions">
<button class="btn-cancel" type="button" (click)="cancel()">Abbrechen</button> <button class="btn-cancel" type="button" (click)="cancel()">Abbrechen</button>
<button class="btn-save" type="submit" [disabled]="control.invalid || control.disabled" [ngSwitch]="control.enabled"> <button class="btn-save" type="submit" [disabled]="control.invalid || control.disabled">
<ng-container *ngSwitchCase="true">Speichern</ng-container> @switch (control.enabled) {
<ui-icon class="spin" icon="loading" size="18px" *ngSwitchCase="false"></ui-icon> @case (true) {
Speichern
}
@case (false) {
<ui-icon class="spin" icon="loading" size="18px"></ui-icon>
}
}
</button> </button>
</div> </div>
</form> </form>
}

View File

@@ -1,6 +1,6 @@
<div class="customer-edit-header-actions flex flex-row justify-end pt-1 px-1"> <div class="customer-edit-header-actions flex flex-row justify-end pt-1 px-1">
@if (detailsRoute$ | async; as route) {
<a <a
*ngIf="detailsRoute$ | async; let route"
[routerLink]="route.path" [routerLink]="route.path"
[queryParams]="route.queryParams" [queryParams]="route.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
@@ -8,15 +8,19 @@
> >
<ui-icon [icon]="'close'"></ui-icon> <ui-icon [icon]="'close'"></ui-icon>
</a> </a>
}
</div> </div>
<div class="header"> <div class="header">
<h1>Kundendetails</h1> <h1>Kundendetails</h1>
</div> </div>
<form *ngIf="control" [formGroup]="control" (ngSubmit)="submit()"> @if (control) {
<form [formGroup]="control" (ngSubmit)="submit()">
<ui-form-control [clearable]="true" label="Anrede" variant="inline"> <ui-form-control [clearable]="true" label="Anrede" variant="inline">
<ui-select formControlName="gender" tabindex="1"> <ui-select formControlName="gender" tabindex="1">
<ui-select-option *ngFor="let gender of genderSettings.genders" [value]="gender.value" [label]="gender.label"></ui-select-option> @for (gender of genderSettings.genders; track gender) {
<ui-select-option [value]="gender.value" [label]="gender.label"></ui-select-option>
}
</ui-select> </ui-select>
</ui-form-control> </ui-form-control>
<ui-form-control [clearable]="true" label="Titel" variant="inline"> <ui-form-control [clearable]="true" label="Titel" variant="inline">
@@ -38,7 +42,6 @@
<ui-form-control label="E-Mail" formGroupName="communicationDetails" variant="inline"> <ui-form-control label="E-Mail" formGroupName="communicationDetails" variant="inline">
<input uiInput type="mail" formControlName="email" tabindex="5" /> <input uiInput type="mail" formControlName="email" tabindex="5" />
</ui-form-control> </ui-form-control>
<ng-container formGroupName="address"> <ng-container formGroupName="address">
<ui-form-control label="Straße" variant="inline"> <ui-form-control label="Straße" variant="inline">
<input uiInput type="text" formControlName="street" tabindex="6" /> <input uiInput type="text" formControlName="street" tabindex="6" />
@@ -57,15 +60,15 @@
</ui-form-control> </ui-form-control>
<ui-form-control [clearable]="true" label="Land" variant="inline"> <ui-form-control [clearable]="true" label="Land" variant="inline">
<ui-select formControlName="country" tabindex="11"> <ui-select formControlName="country" tabindex="11">
@for (country of countries$ | async; track country) {
<ui-select-option <ui-select-option
*ngFor="let country of countries$ | async"
[label]="country.name" [label]="country.name"
[value]="country.isO3166_A_3" [value]="country.isO3166_A_3"
></ui-select-option> ></ui-select-option>
}
</ui-select> </ui-select>
</ui-form-control> </ui-form-control>
</ng-container> </ng-container>
<ng-container formGroupName="communicationDetails"> <ng-container formGroupName="communicationDetails">
<ui-form-control label="Festnetznummer" variant="inline"> <ui-form-control label="Festnetznummer" variant="inline">
<input uiInput type="tel" formControlName="phone" tabindex="12" /> <input uiInput type="tel" formControlName="phone" tabindex="12" />
@@ -81,21 +84,27 @@
<ui-form-control label="Firmenname" variant="inline"> <ui-form-control label="Firmenname" variant="inline">
<input uiInput type="text" formControlName="name" tabindex="15" /> <input uiInput type="text" formControlName="name" tabindex="15" />
</ui-form-control> </ui-form-control>
<ng-container *ngIf="!(isOnlineOrCustomerCardUser$ | async)"> @if (!(isOnlineOrCustomerCardUser$ | async)) {
<ui-form-control label="Abteilung" variant="inline"> <ui-form-control label="Abteilung" variant="inline">
<input uiInput type="text" formControlName="department" tabindex="16" /> <input uiInput type="text" formControlName="department" tabindex="16" />
</ui-form-control> </ui-form-control>
<ui-form-control label="USt ID" variant="inline"> <ui-form-control label="USt ID" variant="inline">
<input uiInput type="text" formControlName="vatId" tabindex="17" /> <input uiInput type="text" formControlName="vatId" tabindex="17" />
</ui-form-control> </ui-form-control>
}
</ng-container> </ng-container>
</ng-container>
<div class="actions"> <div class="actions">
<button class="btn-cancel" type="button" (click)="cancel()">Abbrechen</button> <button class="btn-cancel" type="button" (click)="cancel()">Abbrechen</button>
<button class="btn-save" type="submit" [disabled]="control.invalid || control.disabled" [ngSwitch]="control.enabled"> <button class="btn-save" type="submit" [disabled]="control.invalid || control.disabled">
<ng-container *ngSwitchCase="true">Speichern</ng-container> @switch (control.enabled) {
<ui-icon class="spin" icon="loading" size="18px" *ngSwitchCase="false"></ui-icon> @case (true) {
Speichern
}
@case (false) {
<ui-icon class="spin" icon="loading" size="18px"></ui-icon>
}
}
</button> </button>
</div> </div>
</form> </form>
}

View File

@@ -1,17 +1,18 @@
<div class="flex flex-row justify-end -mt-4 -mr-2"> <div class="flex flex-row justify-end -mt-4 -mr-2">
@if (detailsRoute$ | async; as detailsRoute) {
<a <a
*ngIf="detailsRoute$ | async; let detailsRoute"
[routerLink]="detailsRoute.path" [routerLink]="detailsRoute.path"
[queryParams]="detailsRoute.urlTree.queryParams" [queryParams]="detailsRoute.urlTree.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
> >
<shared-icon icon="close" [size]="32"></shared-icon> <shared-icon icon="close" [size]="32"></shared-icon>
</a> </a>
}
</div> </div>
<h1 class="text-2xl text-center font-bold mb-6">Lieferadresse bearbeiten</h1> <h1 class="text-2xl text-center font-bold mb-6">Lieferadresse bearbeiten</h1>
<form [formGroup]="formGroup" (ngSubmit)="save()"> <form [formGroup]="formGroup" (ngSubmit)="save()">
<ng-container *ngIf="isBusinessKonto$ | async"> @if (isBusinessKonto$ | async) {
<shared-form-control <shared-form-control
[label]="formGroup.controls.organisation.errors?.required ? 'Firma *' : 'Firma'" [label]="formGroup.controls.organisation.errors?.required ? 'Firma *' : 'Firma'"
class="col-span-2" class="col-span-2"
@@ -28,7 +29,6 @@
tabindex="1" tabindex="1"
/> />
</shared-form-control> </shared-form-control>
<shared-form-control label="Abteilung"> <shared-form-control label="Abteilung">
<input <input
class="input-control" class="input-control"
@@ -38,7 +38,6 @@
tabindex="2" tabindex="2"
/> />
</shared-form-control> </shared-form-control>
<shared-form-control label="USt-ID"> <shared-form-control label="USt-ID">
<input <input
class="input-control" class="input-control"
@@ -48,13 +47,15 @@
tabindex="3" tabindex="3"
/> />
</shared-form-control> </shared-form-control>
</ng-container> }
<shared-form-control label="Anrede"> <shared-form-control label="Anrede">
<shared-select formControlName="gender" placeholder="Anrede" tabindex="4" [autofocus]="true"> <shared-select formControlName="gender" placeholder="Anrede" tabindex="4" [autofocus]="true">
<shared-select-option *ngFor="let gender of genderSettings.genders" [value]="gender.value">{{ @for (gender of genderSettings.genders; track gender) {
<shared-select-option [value]="gender.value">{{
gender.label gender.label
}}</shared-select-option> }}</shared-select-option>
}
</shared-select> </shared-select>
</shared-form-control> </shared-form-control>
@@ -101,7 +102,7 @@
/> />
</shared-form-control> </shared-form-control>
<ng-container *ngIf="!(isBusinessKonto$ | async)"> @if (!(isBusinessKonto$ | async)) {
<shared-form-control label="Firma" class="col-span-2"> <shared-form-control label="Firma" class="col-span-2">
<input <input
class="input-control" class="input-control"
@@ -111,7 +112,7 @@
tabindex="8" tabindex="8"
/> />
</shared-form-control> </shared-form-control>
</ng-container> }
<shared-form-control label="Straße"> <shared-form-control label="Straße">
<input <input
@@ -165,12 +166,13 @@
<shared-form-control class="col-span-2" label="Land"> <shared-form-control class="col-span-2" label="Land">
<shared-select placeholder="Land" formControlName="country" tabindex="14"> <shared-select placeholder="Land" formControlName="country" tabindex="14">
@for (country of countries$ | async; track country) {
<shared-select-option <shared-select-option
*ngFor="let country of countries$ | async"
[value]="country.isO3166_A_3" [value]="country.isO3166_A_3"
> >
{{ country.name }} {{ country.name }}
</shared-select-option> </shared-select-option>
}
</shared-select> </shared-select>
</shared-form-control> </shared-form-control>

View File

@@ -13,7 +13,7 @@ import { FormControlComponent } from '@shared/components/form-control';
import { CrmCustomerService } from '@domain/crm'; import { CrmCustomerService } from '@domain/crm';
import { AddressDTO, Gender, ShippingAddressDTO } from '@generated/swagger/crm-api'; import { AddressDTO, Gender, ShippingAddressDTO } from '@generated/swagger/crm-api';
import { map, switchMap, takeUntil } from 'rxjs/operators'; import { map, switchMap, takeUntil } from 'rxjs/operators';
import { AsyncPipe, NgForOf, NgIf } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { AddressSelectionModalService } from '@modal/address-selection'; import { AddressSelectionModalService } from '@modal/address-selection';
import { CustomerSearchStore } from '../store'; import { CustomerSearchStore } from '../store';
import { CustomerSearchNavigation } from '@shared/services/navigation'; import { CustomerSearchNavigation } from '@shared/services/navigation';
@@ -39,12 +39,10 @@ export interface EditShippingAddressMainViewState {
IconComponent, IconComponent,
RouterLink, RouterLink,
AsyncPipe, AsyncPipe,
NgIf,
NgForOf,
ReactiveFormsModule, ReactiveFormsModule,
SelectModule, SelectModule,
FormControlComponent, FormControlComponent,
CheckboxComponent, CheckboxComponent
], ],
}) })
export class EditShippingAddressMainViewComponent export class EditShippingAddressMainViewComponent

View File

@@ -1,13 +1,15 @@
<ng-container *ngIf="fetchingFilterSettings$ | async; else filterTemplate"></ng-container> @if (fetchingFilterSettings$ | async) {
} @else {
<ng-template #filterTemplate> @if (filter$ | async; as filter) {
<div *ngIf="filter$ | async; let filter"> <div>
<div class="customer-filter-header"> <div class="customer-filter-header">
<div class="customer-filter-header-actions flex flex-row justify-end pt-1 px-1"> <div class="customer-filter-header-actions flex flex-row justify-end pt-1 px-1">
<button (click)="clearFilter(filter)" class="text-[#0556B4] mr-2 h-12">Alle Filter entfernen</button> <button (click)="clearFilter(filter)" class="text-[#0556B4] mr-2 h-12">Alle Filter entfernen</button>
<button (click)="close()" class="btn btn-label" *ngIf="!isOnMainRoute"> @if (!isOnMainRoute) {
<button (click)="close()" class="btn btn-label">
<ui-icon [icon]="'close'"></ui-icon> <ui-icon [icon]="'close'"></ui-icon>
</button> </button>
}
</div> </div>
<div class="customer-filter-header-body text-center -mt-3"> <div class="customer-filter-header-body text-center -mt-3">
<h1 class="text-[1.625rem] font-bold">Filter</h1> <h1 class="text-[1.625rem] font-bold">Filter</h1>
@@ -22,7 +24,6 @@
[scanner]="true" [scanner]="true"
></shared-filter> ></shared-filter>
</div> </div>
<div class="grid grid-flow-col gap-6 items-center justify-center mt-6"> <div class="grid grid-flow-col gap-6 items-center justify-center mt-6">
<button <button
type="button" type="button"
@@ -32,7 +33,6 @@
> >
<shared-loader [loading]="fetching$ | async">Filter zurücksetzen</shared-loader> <shared-loader [loading]="fetching$ | async">Filter zurücksetzen</shared-loader>
</button> </button>
<button <button
type="button" type="button"
(click)="search(filter)" (click)="search(filter)"
@@ -43,4 +43,6 @@
</button> </button>
</div> </div>
</div> </div>
</ng-template> }
}

View File

@@ -2,24 +2,32 @@
<page-customer-menu [customerId]="customerId$ | async" [processId]="processId$ | async" [showCustomerCard]="false"></page-customer-menu> <page-customer-menu [customerId]="customerId$ | async" [processId]="processId$ | async" [showCustomerCard]="false"></page-customer-menu>
</div> </div>
<h1 class="text-center text-2xl font-bold">Kundenkarte</h1> <h1 class="text-center text-2xl font-bold">Kundenkarte</h1>
<p class="text-center text-xl" *ngIf="!(noDataFound$ | async)"> @if (!(noDataFound$ | async)) {
<p class="text-center text-xl">
Alle Infos zu Ihrer Kundenkarte Alle Infos zu Ihrer Kundenkarte
<br /> <br />
und allen Partnerkarten. und allen Partnerkarten.
</p> </p>
<p class="text-center text-xl" *ngIf="noDataFound$ | async">Keine Kundenkarte gefunden.</p> }
@if (noDataFound$ | async) {
<p class="text-center text-xl">Keine Kundenkarte gefunden.</p>
}
@for (karte of primaryKundenkarte$ | async; track karte) {
<page-customer-kundenkarte <page-customer-kundenkarte
class="justify-self-center" class="justify-self-center"
*ngFor="let karte of primaryKundenkarte$ | async"
[cardDetails]="karte" [cardDetails]="karte"
[isCustomerCard]="true" [isCustomerCard]="true"
></page-customer-kundenkarte> ></page-customer-kundenkarte>
}
<p class="text-center text-xl font-bold" *ngIf="(partnerKundenkarte$ | async)?.length">Partnerkarten</p> @if ((partnerKundenkarte$ | async)?.length) {
<p class="text-center text-xl font-bold">Partnerkarten</p>
}
@for (karte of partnerKundenkarte$ | async; track karte) {
<page-customer-kundenkarte <page-customer-kundenkarte
class="justify-self-center" class="justify-self-center"
*ngFor="let karte of partnerKundenkarte$ | async"
[cardDetails]="karte" [cardDetails]="karte"
[isCustomerCard]="false" [isCustomerCard]="false"
></page-customer-kundenkarte> ></page-customer-kundenkarte>
}

View File

@@ -5,7 +5,7 @@ import { Subject, combineLatest, of } from 'rxjs';
import { catchError, map, share, switchMap } from 'rxjs/operators'; import { catchError, map, share, switchMap } from 'rxjs/operators';
import { CrmCustomerService } from '@domain/crm'; import { CrmCustomerService } from '@domain/crm';
import { KundenkarteComponent } from '../../components/kundenkarte'; import { KundenkarteComponent } from '../../components/kundenkarte';
import { AsyncPipe, NgFor, NgIf } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { IconComponent } from '@shared/components/icon'; import { IconComponent } from '@shared/components/icon';
import { CustomerSearchNavigation } from '@shared/services/navigation'; import { CustomerSearchNavigation } from '@shared/services/navigation';
import { BonusCardInfoDTO } from '@generated/swagger/crm-api'; import { BonusCardInfoDTO } from '@generated/swagger/crm-api';
@@ -17,7 +17,7 @@ import { CustomerMenuComponent } from '../../components/customer-menu';
styleUrls: ['kundenkarte-main-view.component.css'], styleUrls: ['kundenkarte-main-view.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'page-customer-kundenkarte-main-view' }, host: { class: 'page-customer-kundenkarte-main-view' },
imports: [CustomerMenuComponent, KundenkarteComponent, NgFor, AsyncPipe, NgIf, IconComponent, RouterLink], imports: [CustomerMenuComponent, KundenkarteComponent, AsyncPipe, IconComponent, RouterLink],
}) })
export class KundenkarteMainViewComponent implements OnInit, OnDestroy { export class KundenkarteMainViewComponent implements OnInit, OnDestroy {
private _store = inject(CustomerSearchStore); private _store = inject(CustomerSearchStore);

View File

@@ -1,17 +1,20 @@
<div class="text-center pt-10 px-8 rounded-card side-view-shadow grow"> <div class="text-center pt-10 px-8 rounded-card side-view-shadow grow">
<h1 class="text-[1.625rem] font-bold">Kundensuche</h1> <h1 class="text-[1.625rem] font-bold">Kundensuche</h1>
<p class="text-lg mt-2 mb-6">Haben Sie ein Konto bei uns?</p> <p class="text-lg mt-2 mb-6">Haben Sie ein Konto bei uns?</p>
@if (filter$ | async; as filter) {
<shared-filter-input-group-main <shared-filter-input-group-main
*ngIf="filter$ | async; let filter"
[inputGroup]="filter?.input | group: 'main'" [inputGroup]="filter?.input | group: 'main'"
(search)="search(filter)" (search)="search(filter)"
[loading]="fetching$ | async" [loading]="fetching$ | async"
[hint]="message$ | async" [hint]="message$ | async"
></shared-filter-input-group-main> ></shared-filter-input-group-main>
}
<p class="mt-6"> <p class="mt-6">
Kunde nicht gefunden? Kunde nicht gefunden?
<a class="text-brand" *ngIf="createRoute$ | async; let route" [routerLink]="route.path" [queryParams]="route.queryParams"> @if (createRoute$ | async; as route) {
<a class="text-brand" [routerLink]="route.path" [queryParams]="route.queryParams">
Neue Kundendaten erfassen Neue Kundendaten erfassen
</a> </a>
}
</p> </p>
</div> </div>

View File

@@ -1,4 +1,4 @@
import { AsyncPipe, CommonModule, NgIf } from '@angular/common'; import { AsyncPipe, CommonModule } from '@angular/common';
import { Component, ChangeDetectionStrategy, inject } from '@angular/core'; import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { Filter, FilterModule } from '@shared/components/filter'; import { Filter, FilterModule } from '@shared/components/filter';
@@ -13,7 +13,7 @@ import { CustomerInfoDTO } from '@generated/swagger/crm-api';
templateUrl: 'main-side-view.component.html', templateUrl: 'main-side-view.component.html',
styleUrls: ['main-side-view.component.css'], styleUrls: ['main-side-view.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule, RouterModule, FilterModule, AsyncPipe, NgIf], imports: [CommonModule, RouterModule, FilterModule, AsyncPipe],
}) })
export class MainSideViewComponent { export class MainSideViewComponent {
private _store = inject(CustomerSearchStore); private _store = inject(CustomerSearchStore);

View File

@@ -3,17 +3,18 @@
<h1 class="text-[1.625rem] font-bold">Kundensuche</h1> <h1 class="text-[1.625rem] font-bold">Kundensuche</h1>
<p class="text-lg mt-2 mb-6">Haben Sie ein Konto bei uns?</p> <p class="text-lg mt-2 mb-6">Haben Sie ein Konto bei uns?</p>
<div class="grid grid-cols-[1fr_auto] items-center gap-2"> <div class="grid grid-cols-[1fr_auto] items-center gap-2">
@if (filter$ | async; as filter) {
<shared-filter-input-group-main <shared-filter-input-group-main
class="grow" class="grow"
*ngIf="filter$ | async; let filter"
[inputGroup]="filter?.input | group: 'main'" [inputGroup]="filter?.input | group: 'main'"
(search)="search(filter)" (search)="search(filter)"
[loading]="fetching$ | async" [loading]="fetching$ | async"
[hint]="message$ | async" [hint]="message$ | async"
[scanner]="true" [scanner]="true"
></shared-filter-input-group-main> ></shared-filter-input-group-main>
}
@if (filterRoute$ | async; as filterRoute) {
<a <a
*ngIf="filterRoute$ | async; let filterRoute"
class="filter-btn h-14 px-4 rounded font-bold text-xl grid grid-flow-col items-center gap-2" class="filter-btn h-14 px-4 rounded font-bold text-xl grid grid-flow-col items-center gap-2"
[routerLink]="filterRoute.path" [routerLink]="filterRoute.path"
[queryParams]="filterRoute.queryParams" [queryParams]="filterRoute.queryParams"
@@ -23,12 +24,15 @@
<shared-icon icon="filter-variant"></shared-icon> <shared-icon icon="filter-variant"></shared-icon>
<span>Filter</span> <span>Filter</span>
</a> </a>
}
</div> </div>
<p class="mt-6"> <p class="mt-6">
Kunde nicht gefunden? Kunde nicht gefunden?
<a class="text-brand" *ngIf="createRoute$ | async; let route" [routerLink]="route.path" [queryParams]="route.queryParams"> @if (createRoute$ | async; as route) {
<a class="text-brand" [routerLink]="route.path" [queryParams]="route.queryParams">
Neue Kundendaten erfassen Neue Kundendaten erfassen
</a> </a>
}
</p> </p>
</div> </div>
</div> </div>

View File

@@ -2,7 +2,7 @@ import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
import { CustomerSearchStore } from '../store'; import { CustomerSearchStore } from '../store';
import { Filter, FilterModule } from '@shared/components/filter'; import { Filter, FilterModule } from '@shared/components/filter';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { AsyncPipe, NgIf } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { Router, RouterLink } from '@angular/router'; import { Router, RouterLink } from '@angular/router';
import { IconComponent } from '@shared/components/icon'; import { IconComponent } from '@shared/components/icon';
import { combineLatest } from 'rxjs'; import { combineLatest } from 'rxjs';
@@ -17,7 +17,7 @@ import { CustomerInfoDTO } from '@generated/swagger/crm-api';
styleUrls: ['main-view.component.css'], styleUrls: ['main-view.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'page-customer-main-view' }, host: { class: 'page-customer-main-view' },
imports: [AsyncPipe, RouterLink, FilterModule, NgIf, IconComponent, CustomerFilterMainViewModule], imports: [AsyncPipe, RouterLink, FilterModule, IconComponent, CustomerFilterMainViewModule],
}) })
export class CustomerMainViewComponent { export class CustomerMainViewComponent {
private _searchNavigation = inject(CustomerSearchNavigation); private _searchNavigation = inject(CustomerSearchNavigation);

View File

@@ -1,12 +1,13 @@
<ng-container *ngIf="fetching$ | async; else historyTemplate"></ng-container> @if (fetching$ | async) {
} @else {
<ng-template #historyTemplate>
<div> <div>
<div class="customer-history-header"> <div class="customer-history-header">
<div class="customer-history-header-actions flex flex-row justify-end pt-1 px-1"> <div class="customer-history-header-actions flex flex-row justify-end pt-1 px-1">
<a *ngIf="detailsRoute$ | async; let route" [routerLink]="route.path" [queryParams]="route.queryParams" class="btn btn-label"> @if (detailsRoute$ | async; as route) {
<a [routerLink]="route.path" [queryParams]="route.queryParams" class="btn btn-label">
<shared-icon [icon]="'close'" [size]="32"></shared-icon> <shared-icon [icon]="'close'" [size]="32"></shared-icon>
</a> </a>
}
</div> </div>
<div class="customer-history-header-body text-center -mt-3"> <div class="customer-history-header-body text-center -mt-3">
<h1 class="text-[1.625rem] font-bold">Historie</h1> <h1 class="text-[1.625rem] font-bold">Historie</h1>
@@ -26,4 +27,5 @@
<shared-history-list [history]="history$ | async"></shared-history-list> <shared-history-list [history]="history$ | async"></shared-history-list>
</div> </div>
</div> </div>
</ng-template> }

View File

@@ -7,7 +7,7 @@ import { Observable, Subject, combineLatest } from 'rxjs';
import { map, switchMap, takeUntil, tap } from 'rxjs/operators'; import { map, switchMap, takeUntil, tap } from 'rxjs/operators';
import { CustomerSearchStore } from '../store'; import { CustomerSearchStore } from '../store';
import { CustomerSearchNavigation } from '@shared/services/navigation'; import { CustomerSearchNavigation } from '@shared/services/navigation';
import { AsyncPipe, NgIf } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { IconModule } from '@shared/components/icon'; import { IconModule } from '@shared/components/icon';
import { SharedHistoryListModule } from '@shared/components/history'; import { SharedHistoryListModule } from '@shared/components/history';
import { ActivatedRoute, RouterLink } from '@angular/router'; import { ActivatedRoute, RouterLink } from '@angular/router';
@@ -23,7 +23,7 @@ export interface CustomerHistoryViewMainState {
templateUrl: 'order-details-history-main-view.component.html', templateUrl: 'order-details-history-main-view.component.html',
styleUrls: ['order-details-history-main-view.component.css'], styleUrls: ['order-details-history-main-view.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [AsyncPipe, RouterLink, NgIf, IconModule, SharedHistoryListModule], imports: [AsyncPipe, RouterLink, IconModule, SharedHistoryListModule],
}) })
export class CustomerOrderDetailsHistoryMainViewComponent export class CustomerOrderDetailsHistoryMainViewComponent
extends ComponentStore<CustomerHistoryViewMainState> extends ComponentStore<CustomerHistoryViewMainState>

View File

@@ -5,8 +5,8 @@
<div class="grid grid-flow-row gap-2"> <div class="grid grid-flow-row gap-2">
<div class="grid grid-flow-col justify-between items-end"> <div class="grid grid-flow-col justify-between items-end">
<span>{{ orderItem.product?.contributors }}</span> <span>{{ orderItem.product?.contributors }}</span>
@if (orderDetailsHistoryRoute$ | async; as orderDetailsHistoryRoute) {
<a <a
*ngIf="orderDetailsHistoryRoute$ | async; let orderDetailsHistoryRoute"
[routerLink]="orderDetailsHistoryRoute.path" [routerLink]="orderDetailsHistoryRoute.path"
[queryParams]="orderDetailsHistoryRoute.urlTree.queryParams" [queryParams]="orderDetailsHistoryRoute.urlTree.queryParams"
[queryParamsHandling]="'merge'" [queryParamsHandling]="'merge'"
@@ -14,6 +14,7 @@
> >
Historie Historie
</a> </a>
}
</div> </div>
<div class="font-bold text-lg"> <div class="font-bold text-lg">
{{ orderItem?.product?.name }} {{ orderItem?.product?.name }}
@@ -23,7 +24,8 @@
{{ processingStatus$ | async | orderItemProcessingStatus }} {{ processingStatus$ | async | orderItemProcessingStatus }}
</span> </span>
</div> </div>
<div class="grid grid-flow-row gap-2" *ngIf="orderItemSubsetItem$ | async; let orderItemSubsetItem"> @if (orderItemSubsetItem$ | async; as orderItemSubsetItem) {
<div class="grid grid-flow-row gap-2">
<div class="col-data"> <div class="col-data">
<div class="col-label">Menge</div> <div class="col-label">Menge</div>
<div class="col-value">{{ orderItem?.quantity?.quantity }}x</div> <div class="col-value">{{ orderItem?.quantity?.quantity }}x</div>
@@ -64,20 +66,26 @@
{{ orderItemSubsetItem?.estimatedShippingDate | date: 'dd.MM.yyyy' }} {{ orderItemSubsetItem?.estimatedShippingDate | date: 'dd.MM.yyyy' }}
</div> </div>
</div> </div>
<div class="col-data" *ngIf="orderItemSubsetItem?.preferredPickUpDate"> @if (orderItemSubsetItem?.preferredPickUpDate) {
<div class="col-data">
<div class="col-label">Zurücklegen bis</div> <div class="col-label">Zurücklegen bis</div>
<div class="col-value"> <div class="col-value">
{{ orderItemSubsetItem?.preferredPickUpDate | date: 'dd.MM.yyyy' }} {{ orderItemSubsetItem?.preferredPickUpDate | date: 'dd.MM.yyyy' }}
</div> </div>
</div> </div>
}
<hr /> <hr />
<div class="col-data" *ngIf="orderItemSubsetItem?.compartmentCode"> @if (orderItemSubsetItem?.compartmentCode) {
<div class="col-data">
<div class="col-label">Abholfachnummer</div> <div class="col-label">Abholfachnummer</div>
<div class="col-value"> <div class="col-value">
<span>{{ orderItemSubsetItem?.compartmentCode }}</span> <span>{{ orderItemSubsetItem?.compartmentCode }}</span>
<span *ngIf="orderItemSubsetItem?.compartmentInfo">_{{ orderItemSubsetItem?.compartmentInfo }}</span> @if (orderItemSubsetItem?.compartmentInfo) {
<span>_{{ orderItemSubsetItem?.compartmentInfo }}</span>
}
</div> </div>
</div> </div>
}
<div class="col-data"> <div class="col-data">
<div class="col-label">Vormerker</div> <div class="col-label">Vormerker</div>
<div class="col-value">{{ isPrebooked$ | async }}</div> <div class="col-value">{{ isPrebooked$ | async }}</div>
@@ -100,5 +108,6 @@
</div> </div>
</div> </div>
</div> </div>
}
</div> </div>
</div> </div>

View File

@@ -1,4 +1,4 @@
import { AsyncPipe, CurrencyPipe, DatePipe, NgIf } from '@angular/common'; import { AsyncPipe, CurrencyPipe, DatePipe } from '@angular/common';
import { Component, ChangeDetectionStrategy, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { Component, ChangeDetectionStrategy, Input, OnDestroy, OnInit, inject } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router'; import { ActivatedRoute, RouterLink } from '@angular/router';
import { ProductImagePipe } from '@cdn/product-image'; import { ProductImagePipe } from '@cdn/product-image';
@@ -19,7 +19,6 @@ import { PaymentTypePipe } from '@shared/pipes/customer';
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'page-customer-order-item-list-item' }, host: { class: 'page-customer-order-item-list-item' },
imports: [ imports: [
NgIf,
AsyncPipe, AsyncPipe,
DatePipe, DatePipe,
OrderProcessingStatusPipe, OrderProcessingStatusPipe,
@@ -30,7 +29,7 @@ import { PaymentTypePipe } from '@shared/pipes/customer';
IconComponent, IconComponent,
RouterLink, RouterLink,
PaymentTypePipe, PaymentTypePipe,
OrderItemProcessingStatusPipe, OrderItemProcessingStatusPipe
], ],
}) })
export class CustomerOrderItemListItemComponent implements OnInit, OnDestroy { export class CustomerOrderItemListItemComponent implements OnInit, OnDestroy {

View File

@@ -2,8 +2,9 @@
{{ customer$ | async | customerName }} {{ customer$ | async | customerName }}
</div> </div>
<div class="bg-surface-2 text-surface-2-content p-4 text-right">{{ (orderItems$ | async)?.length }} Artikel</div> <div class="bg-surface-2 text-surface-2-content p-4 text-right">{{ (orderItems$ | async)?.length }} Artikel</div>
<div class="grid grid-flow-row gap-1" *ngIf="selectedOrderItemId$ | async; let selectedOrderItemId"> @if (selectedOrderItemId$ | async; as selectedOrderItemId) {
<ng-container *ngFor="let orderItem of orderItems$ | async"> <div class="grid grid-flow-row gap-1">
@for (orderItem of orderItems$ | async; track orderItem) {
<div <div
[class.order-item-active]="selectedOrderItemId === orderItem?.id" [class.order-item-active]="selectedOrderItemId === orderItem?.id"
class="grid grid-cols-[auto_1fr] gap-4 p-4 border border-solid bg-surface text-surface-content rounded first:rounded-t-none" class="grid grid-cols-[auto_1fr] gap-4 p-4 border border-solid bg-surface text-surface-content rounded first:rounded-t-none"
@@ -20,5 +21,6 @@
</span> </span>
</div> </div>
</div> </div>
</ng-container> }
</div> </div>
}

View File

@@ -2,7 +2,7 @@ import { Component, ChangeDetectionStrategy } from '@angular/core';
import { CustomerSearchStore } from '../store'; import { CustomerSearchStore } from '../store';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { CustomerNamePipe } from '@shared/pipes/customer'; import { CustomerNamePipe } from '@shared/pipes/customer';
import { AsyncPipe, NgFor, NgIf } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { ProductImagePipe } from '@cdn/product-image'; import { ProductImagePipe } from '@cdn/product-image';
import { CustomerSearchNavigation } from '@shared/services/navigation'; import { CustomerSearchNavigation } from '@shared/services/navigation';
import { RouterLink, RouterLinkActive } from '@angular/router'; import { RouterLink, RouterLinkActive } from '@angular/router';
@@ -17,12 +17,10 @@ import { OrderItemProcessingStatusPipe } from '@shared/pipes/order';
imports: [ imports: [
CustomerNamePipe, CustomerNamePipe,
AsyncPipe, AsyncPipe,
NgFor,
ProductImagePipe, ProductImagePipe,
RouterLink, RouterLink,
NgIf,
RouterLinkActive, RouterLinkActive,
OrderItemProcessingStatusPipe, OrderItemProcessingStatusPipe
], ],
}) })
export class OrderDetailsSideViewComponent { export class OrderDetailsSideViewComponent {

Some files were not shown because too many files have changed in this diff Show More