mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merged PR 2055: feature(ui-label, ahf, warenausgabe, customer-orders): Added and Updated Labe...
feature(ui-label, ahf, warenausgabe, customer-orders): Added and Updated Label Library and Label to the Views, Updated Positioning Ref: #5479
This commit is contained in:
committed by
Lorenz Hilpert
parent
a5bb8b2895
commit
41630d5d7c
@@ -1,29 +1,66 @@
|
||||
@if (orderItem$ | async; as orderItem) {
|
||||
<div #features class="page-customer-order-details-item__features">
|
||||
@if (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">
|
||||
<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"
|
||||
>
|
||||
Artikel wird für Sie vorgemerkt.
|
||||
</ui-tooltip>
|
||||
}
|
||||
@if (notificationsSent$ | async; as notificationsSent) {
|
||||
@if (notificationsSent?.NOTIFICATION_EMAIL) {
|
||||
<img [uiOverlayTrigger]="emailTooltip" src="/assets/images/email_bookmark.svg" />
|
||||
<ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #emailTooltip [closeable]="true">
|
||||
<img
|
||||
[uiOverlayTrigger]="emailTooltip"
|
||||
src="/assets/images/email_bookmark.svg"
|
||||
/>
|
||||
<ui-tooltip
|
||||
yPosition="above"
|
||||
xPosition="after"
|
||||
[yOffset]="-11"
|
||||
[xOffset]="-8"
|
||||
#emailTooltip
|
||||
[closeable]="true"
|
||||
>
|
||||
Per E-Mail benachrichtigt
|
||||
<br />
|
||||
@for (notification of notificationsSent?.NOTIFICATION_EMAIL; track notification) {
|
||||
@for (
|
||||
notification of notificationsSent?.NOTIFICATION_EMAIL;
|
||||
track notification
|
||||
) {
|
||||
{{ notification | date: 'dd.MM.yyyy | HH:mm' }} Uhr
|
||||
<br />
|
||||
}
|
||||
</ui-tooltip>
|
||||
}
|
||||
@if (notificationsSent?.NOTIFICATION_SMS) {
|
||||
<img [uiOverlayTrigger]="smsTooltip" src="/assets/images/sms_bookmark.svg" />
|
||||
<ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #smsTooltip [closeable]="true">
|
||||
<img
|
||||
[uiOverlayTrigger]="smsTooltip"
|
||||
src="/assets/images/sms_bookmark.svg"
|
||||
/>
|
||||
<ui-tooltip
|
||||
yPosition="above"
|
||||
xPosition="after"
|
||||
[yOffset]="-11"
|
||||
[xOffset]="-8"
|
||||
#smsTooltip
|
||||
[closeable]="true"
|
||||
>
|
||||
Per SMS benachrichtigt
|
||||
<br />
|
||||
@for (notification of notificationsSent?.NOTIFICATION_SMS; track notification) {
|
||||
@for (
|
||||
notification of notificationsSent?.NOTIFICATION_SMS;
|
||||
track notification
|
||||
) {
|
||||
{{ notification | date: 'dd.MM.yyyy | HH:mm' }} Uhr
|
||||
<br />
|
||||
}
|
||||
@@ -33,7 +70,10 @@
|
||||
</div>
|
||||
<div class="page-customer-order-details-item__item-container">
|
||||
<div class="page-customer-order-details-item__thumbnail">
|
||||
<img [src]="orderItem.product?.ean | productImage" [alt]="orderItem.product?.name" />
|
||||
<img
|
||||
[src]="orderItem.product?.ean | productImage"
|
||||
[alt]="orderItem.product?.name"
|
||||
/>
|
||||
</div>
|
||||
<div class="page-customer-order-details-item__details">
|
||||
<div class="flex flex-row justify-between items-start mb-[1.3125rem]">
|
||||
@@ -42,19 +82,29 @@
|
||||
#elementDistance="uiElementDistance"
|
||||
[style.max-width.px]="elementDistance.distanceChange | async"
|
||||
class="flex flex-col"
|
||||
>
|
||||
<div class="font-normal mb-[0.375rem]">{{ orderItem.product?.contributors }}</div>
|
||||
>
|
||||
@if (hasRewardPoints$ | async) {
|
||||
<ui-label class="w-10 mb-2">Prämie</ui-label>
|
||||
}
|
||||
<div class="font-normal mb-[0.375rem]">
|
||||
{{ orderItem.product?.contributors }}
|
||||
</div>
|
||||
<div>{{ orderItem.product?.name }}</div>
|
||||
</h3>
|
||||
<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
|
||||
[ngModel]="selected$ | async"
|
||||
(ngModelChange)="setSelected($event)"
|
||||
class="isa-select-bullet mt-4"
|
||||
type="checkbox"
|
||||
/>
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,19 +122,26 @@
|
||||
[showSpinner]="false"
|
||||
></ui-quantity-dropdown>
|
||||
}
|
||||
<span class="overall-quantity">(von {{ orderItem?.overallQuantity }})</span>
|
||||
<span class="overall-quantity"
|
||||
>(von {{ orderItem?.overallQuantity }})</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
@if (!!orderItem.product?.formatDetail) {
|
||||
<div class="detail">
|
||||
<div class="label">Format</div>
|
||||
<div class="value">
|
||||
@if (orderItem?.product?.format && orderItem?.product?.format !== 'UNKNOWN') {
|
||||
@if (
|
||||
orderItem?.product?.format &&
|
||||
orderItem?.product?.format !== 'UNKNOWN'
|
||||
) {
|
||||
<img
|
||||
class="format-icon"
|
||||
[src]="'/assets/images/Icon_' + orderItem.product?.format + '.svg'"
|
||||
[src]="
|
||||
'/assets/images/Icon_' + orderItem.product?.format + '.svg'
|
||||
"
|
||||
alt="format icon"
|
||||
/>
|
||||
/>
|
||||
}
|
||||
<span>{{ orderItem.product?.formatDetail }}</span>
|
||||
</div>
|
||||
@@ -96,10 +153,17 @@
|
||||
<div class="value">{{ orderItem.product?.ean }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (orderItem.price !== undefined) {
|
||||
@if (orderItem.price !== undefined || (hasRewardPoints$ | async)) {
|
||||
<div class="detail">
|
||||
<div class="label">Preis</div>
|
||||
<div class="value">{{ orderItem.price | currency: 'EUR' }}</div>
|
||||
@if (hasRewardPoints$ | async) {
|
||||
<div class="label">Prämie</div>
|
||||
<div class="value">
|
||||
{{ rewardPoints$ | async | number: '1.0-0' }} Lesepunkte
|
||||
</div>
|
||||
} @else {
|
||||
<div class="label">Preis</div>
|
||||
<div class="value">{{ orderItem.price | currency: 'EUR' }}</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (!!orderItem.retailPrice?.vat?.inPercent) {
|
||||
@@ -133,14 +197,23 @@
|
||||
orderItemFeature(orderItem) === 'Versand' ||
|
||||
orderItemFeature(orderItem) === 'B2B-Versand' ||
|
||||
orderItemFeature(orderItem) === 'DIG-Versand'
|
||||
) {
|
||||
{{ orderItem?.estimatedDelivery ? 'Lieferung zwischen' : 'Lieferung ab' }}
|
||||
) {
|
||||
{{
|
||||
orderItem?.estimatedDelivery
|
||||
? 'Lieferung zwischen'
|
||||
: 'Lieferung ab'
|
||||
}}
|
||||
}
|
||||
@if (orderItemFeature(orderItem) === 'Abholung' || orderItemFeature(orderItem) === 'Rücklage') {
|
||||
@if (
|
||||
orderItemFeature(orderItem) === 'Abholung' ||
|
||||
orderItemFeature(orderItem) === 'Rücklage'
|
||||
) {
|
||||
Abholung ab
|
||||
}
|
||||
</div>
|
||||
@if (!!orderItem?.estimatedDelivery || !!orderItem?.estimatedShippingDate) {
|
||||
@if (
|
||||
!!orderItem?.estimatedDelivery || !!orderItem?.estimatedShippingDate
|
||||
) {
|
||||
<div class="value bg-[#D8DFE5] rounded w-max px-2">
|
||||
@if (!!orderItem?.estimatedDelivery) {
|
||||
{{ orderItem?.estimatedDelivery?.start | date: 'dd.MM.yy' }} und
|
||||
@@ -155,14 +228,22 @@
|
||||
</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>
|
||||
@for (tracking of trackingData; track tracking) {
|
||||
@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 }}
|
||||
</a>
|
||||
} @else {
|
||||
<p class="value">{{ tracking.trackingProvider }}: {{ tracking.trackingNumber }}</p>
|
||||
<p class="value">
|
||||
{{ tracking.trackingProvider }}: {{ tracking.trackingNumber }}
|
||||
</p>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
@@ -206,7 +287,9 @@
|
||||
@if (!!receipt?.printedDate) {
|
||||
<div class="detail">
|
||||
<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>
|
||||
}
|
||||
@if (!!receipt?.receiptText) {
|
||||
@@ -219,12 +302,20 @@
|
||||
<div class="detail">
|
||||
<div class="label">Belegart</div>
|
||||
<div class="value">
|
||||
{{ receipt?.receiptType === 1 ? 'Lieferschein' : receipt?.receiptType === 64 ? 'Zahlungsbeleg' : '-' }}
|
||||
{{
|
||||
receipt?.receiptType === 1
|
||||
? 'Lieferschein'
|
||||
: receipt?.receiptType === 64
|
||||
? 'Zahlungsbeleg'
|
||||
: '-'
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<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="flex flex-row w-full">
|
||||
<textarea
|
||||
@@ -248,17 +339,23 @@
|
||||
<button
|
||||
type="reset"
|
||||
class="clear"
|
||||
(click)="specialCommentControl.setValue(''); saveSpecialComment(); triggerResize()"
|
||||
>
|
||||
(click)="
|
||||
specialCommentControl.setValue('');
|
||||
saveSpecialComment();
|
||||
triggerResize()
|
||||
"
|
||||
>
|
||||
<shared-icon icon="close" [size]="24"></shared-icon>
|
||||
</button>
|
||||
}
|
||||
@if (specialCommentControl?.enabled && specialCommentControl.dirty) {
|
||||
@if (
|
||||
specialCommentControl?.enabled && specialCommentControl.dirty
|
||||
) {
|
||||
<button
|
||||
class="cta-save"
|
||||
type="submit"
|
||||
(click)="saveSpecialComment()"
|
||||
>
|
||||
>
|
||||
Speichern
|
||||
</button>
|
||||
}
|
||||
|
||||
@@ -15,12 +15,25 @@ import { DomainOmsService, DomainReceiptService } from '@domain/oms';
|
||||
import { ComponentStore } from '@ngrx/component-store';
|
||||
import { tapResponse } from '@ngrx/operators';
|
||||
|
||||
import { OrderDTO, OrderItemListItemDTO, ReceiptDTO, ReceiptType } from '@generated/swagger/oms-api';
|
||||
import {
|
||||
OrderDTO,
|
||||
OrderItemListItemDTO,
|
||||
ReceiptDTO,
|
||||
ReceiptType,
|
||||
} from '@generated/swagger/oms-api';
|
||||
import { isEqual } from 'lodash';
|
||||
import { combineLatest, NEVER, Subject, Observable } from 'rxjs';
|
||||
import { catchError, filter, first, map, switchMap, withLatestFrom } from 'rxjs/operators';
|
||||
import {
|
||||
catchError,
|
||||
filter,
|
||||
first,
|
||||
map,
|
||||
switchMap,
|
||||
withLatestFrom,
|
||||
} from 'rxjs/operators';
|
||||
import { CustomerOrderDetailsStore } from '../customer-order-details.store';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { getOrderItemRewardFeature } from '@isa/oms/data-access';
|
||||
|
||||
export interface CustomerOrderDetailsItemComponentState {
|
||||
orderItem?: OrderItemListItemDTO;
|
||||
@@ -59,7 +72,12 @@ export class CustomerOrderDetailsItemComponent
|
||||
// Remove Prev OrderItem from selected list
|
||||
this._store.selectOrderItem(this.orderItem, false);
|
||||
|
||||
this.patchState({ orderItem, quantity: orderItem?.quantity, receipts: [], more: false });
|
||||
this.patchState({
|
||||
orderItem,
|
||||
quantity: orderItem?.quantity,
|
||||
receipts: [],
|
||||
more: false,
|
||||
});
|
||||
this.specialCommentControl.reset(orderItem?.specialComment);
|
||||
|
||||
// Add New OrderItem to selected list if selected was set to true by its input
|
||||
@@ -94,8 +112,23 @@ export class CustomerOrderDetailsItemComponent
|
||||
),
|
||||
);
|
||||
|
||||
canChangeQuantity$ = combineLatest([this.orderItem$, this._store.fetchPartial$]).pipe(
|
||||
map(([item, partialPickup]) => ([16, 8192].includes(item?.processingStatus) || partialPickup) && item.quantity > 1),
|
||||
hasRewardPoints$ = this.orderItem$.pipe(
|
||||
map((orderItem) => getOrderItemRewardFeature(orderItem) !== undefined),
|
||||
);
|
||||
|
||||
rewardPoints$ = this.orderItem$.pipe(
|
||||
map((orderItem) => getOrderItemRewardFeature(orderItem)),
|
||||
);
|
||||
|
||||
canChangeQuantity$ = combineLatest([
|
||||
this.orderItem$,
|
||||
this._store.fetchPartial$,
|
||||
]).pipe(
|
||||
map(
|
||||
([item, partialPickup]) =>
|
||||
([16, 8192].includes(item?.processingStatus) || partialPickup) &&
|
||||
item.quantity > 1,
|
||||
),
|
||||
);
|
||||
|
||||
get quantity() {
|
||||
@@ -111,7 +144,9 @@ export class CustomerOrderDetailsItemComponent
|
||||
|
||||
@Input()
|
||||
get selected() {
|
||||
return this._store.selectedeOrderItemSubsetIds.includes(this.orderItem?.orderItemSubsetId);
|
||||
return this._store.selectedeOrderItemSubsetIds.includes(
|
||||
this.orderItem?.orderItemSubsetId,
|
||||
);
|
||||
}
|
||||
set selected(selected: boolean) {
|
||||
if (this.selected !== selected) {
|
||||
@@ -120,22 +155,36 @@ export class CustomerOrderDetailsItemComponent
|
||||
}
|
||||
}
|
||||
|
||||
readonly selected$ = combineLatest([this.orderItem$, this._store.selectedeOrderItemSubsetIds$]).pipe(
|
||||
map(([orderItem, selectedItems]) => selectedItems.includes(orderItem?.orderItemSubsetId)),
|
||||
readonly selected$ = combineLatest([
|
||||
this.orderItem$,
|
||||
this._store.selectedeOrderItemSubsetIds$,
|
||||
]).pipe(
|
||||
map(([orderItem, selectedItems]) =>
|
||||
selectedItems.includes(orderItem?.orderItemSubsetId),
|
||||
),
|
||||
);
|
||||
|
||||
@Output()
|
||||
selectedChange = new EventEmitter<boolean>();
|
||||
|
||||
get selectable() {
|
||||
return this._store.itemsSelectable && this._store.items.length > 1 && this._store.fetchPartial;
|
||||
return (
|
||||
this._store.itemsSelectable &&
|
||||
this._store.items.length > 1 &&
|
||||
this._store.fetchPartial
|
||||
);
|
||||
}
|
||||
|
||||
readonly selectable$ = combineLatest([
|
||||
this._store.items$,
|
||||
this._store.itemsSelectable$,
|
||||
this._store.fetchPartial$,
|
||||
]).pipe(map(([orderItems, selectable, fetchPartial]) => orderItems.length > 1 && selectable && fetchPartial));
|
||||
]).pipe(
|
||||
map(
|
||||
([orderItems, selectable, fetchPartial]) =>
|
||||
orderItems.length > 1 && selectable && fetchPartial,
|
||||
),
|
||||
);
|
||||
|
||||
get receipts() {
|
||||
return this.get((s) => s.receipts);
|
||||
@@ -173,6 +222,7 @@ export class CustomerOrderDetailsItemComponent
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
ngOnInit() {}
|
||||
|
||||
ngOnDestroy() {
|
||||
@@ -182,37 +232,39 @@ export class CustomerOrderDetailsItemComponent
|
||||
this._onDestroy$.complete();
|
||||
}
|
||||
|
||||
loadReceipts = this.effect((done$: Observable<(receipts: ReceiptDTO[]) => void | undefined>) =>
|
||||
done$.pipe(
|
||||
withLatestFrom(this.orderItem$),
|
||||
filter(([_, orderItem]) => !!orderItem),
|
||||
switchMap(([done, orderItem]) =>
|
||||
this._domainReceiptService
|
||||
.getReceipts({
|
||||
receiptType: 65 as ReceiptType,
|
||||
ids: [orderItem.orderItemSubsetId],
|
||||
eagerLoading: 1,
|
||||
})
|
||||
.pipe(
|
||||
tapResponse(
|
||||
(res) => {
|
||||
const receipts = res.result.map((r) => r.item3?.data).filter((f) => !!f);
|
||||
this.receipts = receipts;
|
||||
loadReceipts = this.effect(
|
||||
(done$: Observable<(receipts: ReceiptDTO[]) => void | undefined>) =>
|
||||
done$.pipe(
|
||||
withLatestFrom(this.orderItem$),
|
||||
filter(([, orderItem]) => !!orderItem),
|
||||
switchMap(([done, orderItem]) =>
|
||||
this._domainReceiptService
|
||||
.getReceipts({
|
||||
receiptType: 65 as ReceiptType,
|
||||
ids: [orderItem.orderItemSubsetId],
|
||||
eagerLoading: 1,
|
||||
})
|
||||
.pipe(
|
||||
tapResponse(
|
||||
(res) => {
|
||||
const receipts = res.result
|
||||
.map((r) => r.item3?.data)
|
||||
.filter((f) => !!f);
|
||||
this.receipts = receipts;
|
||||
|
||||
if (typeof done === 'function') {
|
||||
done?.(receipts);
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
if (typeof done === 'function') {
|
||||
done?.([]);
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
if (typeof done === 'function') {
|
||||
done?.(receipts);
|
||||
}
|
||||
},
|
||||
() => {
|
||||
if (typeof done === 'function') {
|
||||
done?.([]);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
async saveSpecialComment() {
|
||||
@@ -220,7 +272,7 @@ export class CustomerOrderDetailsItemComponent
|
||||
|
||||
try {
|
||||
this.specialCommentControl.reset(this.specialCommentControl.value);
|
||||
const res = await this._omsService
|
||||
await this._omsService
|
||||
.patchComment({
|
||||
orderId,
|
||||
orderItemId,
|
||||
@@ -230,7 +282,10 @@ export class CustomerOrderDetailsItemComponent
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
this.orderItem = { ...this.orderItem, specialComment: this.specialCommentControl.value ?? '' };
|
||||
this.orderItem = {
|
||||
...this.orderItem,
|
||||
specialComment: this.specialCommentControl.value ?? '',
|
||||
};
|
||||
this._store.updateOrderItems([this.orderItem]);
|
||||
this.specialCommentChanged.emit();
|
||||
} catch (error) {
|
||||
@@ -253,8 +308,9 @@ export class CustomerOrderDetailsItemComponent
|
||||
|
||||
orderItemFeature(orderItemListItem: OrderItemListItemDTO) {
|
||||
const orderItems = this.order?.items;
|
||||
return orderItems?.find((orderItem) => orderItem.data.id === orderItemListItem.orderItemId)?.data?.features
|
||||
?.orderType;
|
||||
return orderItems?.find(
|
||||
(orderItem) => orderItem.data.id === orderItemListItem.orderItemId,
|
||||
)?.data?.features?.orderType;
|
||||
}
|
||||
|
||||
getOrderItemTrackingData(
|
||||
@@ -263,15 +319,18 @@ export class CustomerOrderDetailsItemComponent
|
||||
const orderItems = this.order?.items;
|
||||
const completeTrackingInformation = orderItems
|
||||
?.find((orderItem) => orderItem.data.id === orderItemListItem.orderItemId)
|
||||
?.data?.subsetItems?.find((subsetItem) => subsetItem.id === orderItemListItem.orderItemSubsetId)
|
||||
?.data?.trackingNumber;
|
||||
?.data?.subsetItems?.find(
|
||||
(subsetItem) => subsetItem.id === orderItemListItem.orderItemSubsetId,
|
||||
)?.data?.trackingNumber;
|
||||
|
||||
if (!completeTrackingInformation) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Beispielnummer: 'DHL: 124124' - Bei mehreren Tracking-Informationen muss noch ein Splitter eingebaut werden, je nach dem welcher Trenner verwendet wird
|
||||
const trackingInformationPairs = completeTrackingInformation.split(':').map((obj) => obj.trim());
|
||||
const trackingInformationPairs = completeTrackingInformation
|
||||
.split(':')
|
||||
.map((obj) => obj.trim());
|
||||
return this._trackingTransformationHelper(trackingInformationPairs);
|
||||
}
|
||||
|
||||
@@ -282,7 +341,10 @@ export class CustomerOrderDetailsItemComponent
|
||||
return trackingInformationPairs.reduce(
|
||||
(acc, current, index, array) => {
|
||||
if (index % 2 === 0) {
|
||||
acc.push({ trackingProvider: current, trackingNumber: array[index + 1] });
|
||||
acc.push({
|
||||
trackingProvider: current,
|
||||
trackingNumber: array[index + 1],
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
|
||||
@@ -17,6 +17,7 @@ import { ProductImageModule } from '@cdn/product-image';
|
||||
import { CustomerOrderDetailsStore } from './customer-order-details.store';
|
||||
import { UiDatepickerModule } from '@ui/datepicker';
|
||||
import { UiDropdownModule } from '@ui/dropdown';
|
||||
import { LabelComponent } from '@isa/ui/label';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -34,6 +35,7 @@ import { UiDropdownModule } from '@ui/dropdown';
|
||||
CustomerOrderPipesModule,
|
||||
ProductImageModule,
|
||||
CustomerOrderDetailsTagsComponent,
|
||||
LabelComponent,
|
||||
],
|
||||
exports: [
|
||||
CustomerOrderDetailsComponent,
|
||||
@@ -41,7 +43,11 @@ import { UiDropdownModule } from '@ui/dropdown';
|
||||
CustomerOrderDetailsHeaderComponent,
|
||||
CustomerOrderDetailsTagsComponent,
|
||||
],
|
||||
declarations: [CustomerOrderDetailsComponent, CustomerOrderDetailsItemComponent, CustomerOrderDetailsHeaderComponent],
|
||||
declarations: [
|
||||
CustomerOrderDetailsComponent,
|
||||
CustomerOrderDetailsItemComponent,
|
||||
CustomerOrderDetailsHeaderComponent,
|
||||
],
|
||||
providers: [CustomerOrderDetailsStore],
|
||||
})
|
||||
export class CustomerOrderDetailsModule {}
|
||||
|
||||
@@ -11,13 +11,11 @@
|
||||
[alt]="name"
|
||||
/>
|
||||
}
|
||||
@if (hasRewardPoints$ | async) {
|
||||
<ui-label [type]="Labeltype.Tag" [priority]="LabelPriority.High">
|
||||
Prämie
|
||||
</ui-label>
|
||||
}
|
||||
</div>
|
||||
<div class="grid grid-flow-row gap-2">
|
||||
@if (hasRewardPoints$ | async) {
|
||||
<ui-label class="w-10">Prämie</ui-label>
|
||||
}
|
||||
<div class="grid grid-flow-col justify-between items-end">
|
||||
<span>{{ orderItem.product?.contributors }}</span>
|
||||
@if (orderDetailsHistoryRoute$ | async; as orderDetailsHistoryRoute) {
|
||||
@@ -25,7 +23,7 @@
|
||||
[routerLink]="orderDetailsHistoryRoute.path"
|
||||
[queryParams]="orderDetailsHistoryRoute.urlTree.queryParams"
|
||||
[queryParamsHandling]="'merge'"
|
||||
class="text-brand font-bold text-xl"
|
||||
class="text-brand font-bold text-xl relative -top-8"
|
||||
>
|
||||
Historie
|
||||
</a>
|
||||
@@ -64,7 +62,9 @@
|
||||
<div class="col-data">
|
||||
@if (hasRewardPoints$ | async) {
|
||||
<div class="col-label">Prämie</div>
|
||||
<div class="col-value">{{ rewardPoints$ | async | number: '1.0-0' }} Lesepunkte</div>
|
||||
<div class="col-value">
|
||||
{{ rewardPoints$ | async | number: '1.0-0' }} Lesepunkte
|
||||
</div>
|
||||
} @else {
|
||||
<div class="col-label">Preis</div>
|
||||
<div class="col-value">
|
||||
|
||||
@@ -21,7 +21,7 @@ import { map, takeUntil } from 'rxjs/operators';
|
||||
import { CustomerSearchStore } from '../../store';
|
||||
import { CustomerSearchNavigation } from '@shared/services/navigation';
|
||||
import { PaymentTypePipe } from '@shared/pipes/customer';
|
||||
import { LabelComponent, Labeltype, LabelPriority } from '@isa/ui/label';
|
||||
import { LabelComponent } from '@isa/ui/label';
|
||||
import { getOrderItemRewardFeature } from '@isa/oms/data-access';
|
||||
import { IconComponent } from '@shared/components/icon';
|
||||
|
||||
@@ -113,9 +113,6 @@ export class CustomerOrderItemListItemComponent implements OnInit, OnDestroy {
|
||||
map((orderItem) => getOrderItemRewardFeature(orderItem)),
|
||||
);
|
||||
|
||||
Labeltype = Labeltype;
|
||||
LabelPriority = LabelPriority;
|
||||
|
||||
ngOnInit() {
|
||||
this.customerId$
|
||||
.pipe(takeUntil(this._onDestroy))
|
||||
|
||||
@@ -1,31 +1,75 @@
|
||||
@if (orderItem) {
|
||||
<div #features class="page-pickup-shelf-details-item__features">
|
||||
@if (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">
|
||||
<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"
|
||||
>
|
||||
Artikel wird für Sie vorgemerkt.
|
||||
</ui-tooltip>
|
||||
}
|
||||
@if (hasEmailNotification$ | async) {
|
||||
<img [uiOverlayTrigger]="emailTooltip" src="/assets/images/email_bookmark.svg" />
|
||||
<ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #emailTooltip [closeable]="true">
|
||||
<img
|
||||
[uiOverlayTrigger]="emailTooltip"
|
||||
src="/assets/images/email_bookmark.svg"
|
||||
/>
|
||||
<ui-tooltip
|
||||
yPosition="above"
|
||||
xPosition="after"
|
||||
[yOffset]="-11"
|
||||
[xOffset]="-8"
|
||||
#emailTooltip
|
||||
[closeable]="true"
|
||||
>
|
||||
Per E-Mail benachrichtigt
|
||||
<br />
|
||||
@for (notifications of emailNotificationDates$ | async; track notifications) {
|
||||
@for (notificationDate of notifications.dates; track notificationDate) {
|
||||
{{ notifications.type | notificationType }} {{ notificationDate | date: 'dd.MM.yyyy | HH:mm' }} Uhr
|
||||
@for (
|
||||
notifications of emailNotificationDates$ | async;
|
||||
track notifications
|
||||
) {
|
||||
@for (
|
||||
notificationDate of notifications.dates;
|
||||
track notificationDate
|
||||
) {
|
||||
{{ notifications.type | notificationType }}
|
||||
{{ notificationDate | date: 'dd.MM.yyyy | HH:mm' }} Uhr
|
||||
<br />
|
||||
}
|
||||
}
|
||||
</ui-tooltip>
|
||||
}
|
||||
@if (hasSmsNotification$ | async) {
|
||||
<img [uiOverlayTrigger]="smsTooltip" src="/assets/images/sms_bookmark.svg" />
|
||||
<ui-tooltip yPosition="above" xPosition="after" [yOffset]="-11" [xOffset]="-8" #smsTooltip [closeable]="true">
|
||||
<img
|
||||
[uiOverlayTrigger]="smsTooltip"
|
||||
src="/assets/images/sms_bookmark.svg"
|
||||
/>
|
||||
<ui-tooltip
|
||||
yPosition="above"
|
||||
xPosition="after"
|
||||
[yOffset]="-11"
|
||||
[xOffset]="-8"
|
||||
#smsTooltip
|
||||
[closeable]="true"
|
||||
>
|
||||
Per SMS benachrichtigt
|
||||
<br />
|
||||
@for (notifications of smsNotificationDates$ | async; track notifications) {
|
||||
@for (notificationDate of notifications.dates; track notificationDate) {
|
||||
@for (
|
||||
notifications of smsNotificationDates$ | async;
|
||||
track notifications
|
||||
) {
|
||||
@for (
|
||||
notificationDate of notifications.dates;
|
||||
track notificationDate
|
||||
) {
|
||||
{{ notificationDate | date: 'dd.MM.yyyy | HH:mm' }} Uhr
|
||||
<br />
|
||||
}
|
||||
@@ -39,280 +83,336 @@
|
||||
[productImageNavigation]="orderItem?.product?.ean"
|
||||
[src]="orderItem.product?.ean | productImage"
|
||||
[alt]="orderItem.product?.name"
|
||||
/>
|
||||
@if (hasRewardPoints$ | async) {
|
||||
<ui-label [type]="Labeltype.Tag" [priority]="LabelPriority.High">
|
||||
Prämie
|
||||
</ui-label>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div class="page-pickup-shelf-details-item__details">
|
||||
<div class="flex flex-row justify-between items-start mb-[1.3125rem]">
|
||||
<h3
|
||||
[uiElementDistance]="features"
|
||||
#elementDistance="uiElementDistance"
|
||||
[style.max-width.px]="elementDistance.distanceChange | async"
|
||||
class="flex flex-col"
|
||||
>
|
||||
@if (hasRewardPoints$ | async) {
|
||||
<ui-label class="w-10 mb-2">Prämie</ui-label>
|
||||
}
|
||||
<div class="font-normal mb-[0.375rem]">
|
||||
{{ orderItem.product?.contributors }}
|
||||
</div>
|
||||
<div>{{ orderItem.product?.name }}</div>
|
||||
</h3>
|
||||
<div class="history-wrapper flex flex-col items-end justify-center">
|
||||
<button
|
||||
class="cta-history text-p1"
|
||||
(click)="historyClick.emit(orderItem)"
|
||||
>
|
||||
Historie
|
||||
</button>
|
||||
@if (selectable$ | async) {
|
||||
<input
|
||||
[ngModel]="selected$ | async"
|
||||
(ngModelChange)="
|
||||
setSelected($event);
|
||||
tracker.trackEvent({
|
||||
category: 'pickup-shelf-list-item',
|
||||
action: 'select',
|
||||
name: orderItem?.product?.name,
|
||||
value: $event ? 1 : 0,
|
||||
})
|
||||
"
|
||||
class="isa-select-bullet mt-4"
|
||||
type="checkbox"
|
||||
matomoTracker
|
||||
#tracker="matomo"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-pickup-shelf-details-item__details">
|
||||
<div class="flex flex-row justify-between items-start mb-[1.3125rem]">
|
||||
<h3
|
||||
[uiElementDistance]="features"
|
||||
#elementDistance="uiElementDistance"
|
||||
[style.max-width.px]="elementDistance.distanceChange | async"
|
||||
class="flex flex-col"
|
||||
>
|
||||
<div class="font-normal mb-[0.375rem]">{{ orderItem.product?.contributors }}</div>
|
||||
<div>{{ orderItem.product?.name }}</div>
|
||||
</h3>
|
||||
<div class="history-wrapper flex flex-col items-end justify-center">
|
||||
<button class="cta-history text-p1" (click)="historyClick.emit(orderItem)">Historie</button>
|
||||
@if (selectable$ | async) {
|
||||
<input
|
||||
[ngModel]="selected$ | async"
|
||||
(ngModelChange)="
|
||||
setSelected($event);
|
||||
tracker.trackEvent({
|
||||
category: 'pickup-shelf-list-item',
|
||||
action: 'select',
|
||||
name: orderItem?.product?.name,
|
||||
value: $event ? 1 : 0,
|
||||
})
|
||||
"
|
||||
class="isa-select-bullet mt-4"
|
||||
type="checkbox"
|
||||
matomoTracker
|
||||
#tracker="matomo"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
<div class="detail">
|
||||
<div class="label">Menge</div>
|
||||
<div class="value">
|
||||
@if (!(canChangeQuantity$ | async)) {
|
||||
{{ orderItem?.quantity }}x
|
||||
}
|
||||
@if (canChangeQuantity$ | async) {
|
||||
<ui-quantity-dropdown
|
||||
[showTrash]="false"
|
||||
[range]="orderItem?.quantity"
|
||||
[(ngModel)]="quantity"
|
||||
(ngModelChange)="
|
||||
tracker.trackEvent({
|
||||
category: 'pickup-shelf-list-item',
|
||||
action: 'quantity',
|
||||
name: orderItem?.product?.name,
|
||||
value: $event,
|
||||
})
|
||||
"
|
||||
[showSpinner]="false"
|
||||
matomoTracker
|
||||
#tracker="matomo"
|
||||
></ui-quantity-dropdown>
|
||||
}
|
||||
<span class="overall-quantity"
|
||||
>(von {{ orderItem?.overallQuantity }})</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
@if (!!orderItem.product?.formatDetail) {
|
||||
<div class="detail">
|
||||
<div class="label">Menge</div>
|
||||
<div class="label">Format</div>
|
||||
<div class="value">
|
||||
@if (!(canChangeQuantity$ | async)) {
|
||||
{{ orderItem?.quantity }}x
|
||||
@if (
|
||||
orderItem?.product?.format &&
|
||||
orderItem?.product?.format !== 'UNKNOWN'
|
||||
) {
|
||||
<img
|
||||
class="format-icon"
|
||||
[src]="
|
||||
'/assets/images/Icon_' + orderItem.product?.format + '.svg'
|
||||
"
|
||||
alt="format icon"
|
||||
/>
|
||||
}
|
||||
@if (canChangeQuantity$ | async) {
|
||||
<ui-quantity-dropdown
|
||||
[showTrash]="false"
|
||||
[range]="orderItem?.quantity"
|
||||
[(ngModel)]="quantity"
|
||||
(ngModelChange)="
|
||||
tracker.trackEvent({ category: 'pickup-shelf-list-item', action: 'quantity', name: orderItem?.product?.name, value: $event })
|
||||
"
|
||||
[showSpinner]="false"
|
||||
matomoTracker
|
||||
#tracker="matomo"
|
||||
></ui-quantity-dropdown>
|
||||
}
|
||||
<span class="overall-quantity">(von {{ orderItem?.overallQuantity }})</span>
|
||||
<span>{{ orderItem.product?.formatDetail }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@if (!!orderItem.product?.formatDetail) {
|
||||
<div class="detail">
|
||||
<div class="label">Format</div>
|
||||
}
|
||||
@if (!!orderItem.product?.ean) {
|
||||
<div class="detail">
|
||||
<div class="label">ISBN/EAN</div>
|
||||
<div class="value">{{ orderItem.product?.ean }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (orderItem.price !== undefined || (hasRewardPoints$ | async)) {
|
||||
<div class="detail">
|
||||
@if (hasRewardPoints$ | async) {
|
||||
<div class="label">Prämie</div>
|
||||
<div class="value">
|
||||
@if (orderItem?.product?.format && orderItem?.product?.format !== 'UNKNOWN') {
|
||||
<img
|
||||
class="format-icon"
|
||||
[src]="'/assets/images/Icon_' + orderItem.product?.format + '.svg'"
|
||||
alt="format icon"
|
||||
/>
|
||||
}
|
||||
<span>{{ orderItem.product?.formatDetail }}</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (!!orderItem.product?.ean) {
|
||||
<div class="detail">
|
||||
<div class="label">ISBN/EAN</div>
|
||||
<div class="value">{{ orderItem.product?.ean }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (orderItem.price !== undefined || (hasRewardPoints$ | async)) {
|
||||
<div class="detail">
|
||||
@if (hasRewardPoints$ | async) {
|
||||
<div class="label">Prämie</div>
|
||||
<div class="value">{{ rewardPoints$ | async | number: '1.0-0' }} Lesepunkte</div>
|
||||
} @else {
|
||||
<div class="label">Preis</div>
|
||||
<div class="value">{{ orderItem.price | currency: 'EUR' }}</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (!!orderItem.retailPrice?.vat?.inPercent) {
|
||||
<div class="detail">
|
||||
<div class="label">MwSt</div>
|
||||
<div class="value">{{ orderItem.retailPrice?.vat?.inPercent }}%</div>
|
||||
</div>
|
||||
}
|
||||
<hr class="border-[#EDEFF0] border-t-2 my-4" />
|
||||
@if (orderItem.supplier) {
|
||||
<div class="detail">
|
||||
<div class="label">Lieferant</div>
|
||||
<div class="value">{{ orderItem.supplier }}</div>
|
||||
@if (!expanded) {
|
||||
<button
|
||||
(click)="expanded = !expanded"
|
||||
type="button"
|
||||
class="page-pickup-shelf-details-item__more text-[#0556B4] font-bold flex flex-row items-center justify-center"
|
||||
[class.flex-row-reverse]="!expanded"
|
||||
>
|
||||
<shared-icon class="mr-1" icon="arrow-back" [size]="20" [class.ml-1]="!expanded" [class.rotate-180]="!expanded"></shared-icon>
|
||||
{{ expanded ? 'Weniger' : 'Mehr' }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (!!orderItem.ssc || !!orderItem.sscText) {
|
||||
<div class="detail">
|
||||
<div class="label">Meldenummer</div>
|
||||
<div class="value">{{ orderItem.ssc }} - {{ orderItem.sscText }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (expanded) {
|
||||
@if (!!orderItem.targetBranch) {
|
||||
<div class="detail">
|
||||
<div class="label">Zielfiliale</div>
|
||||
<div class="value">{{ orderItem.targetBranch }}</div>
|
||||
{{ rewardPoints$ | async | number: '1.0-0' }} Lesepunkte
|
||||
</div>
|
||||
} @else {
|
||||
<div class="label">Preis</div>
|
||||
<div class="value">{{ orderItem.price | currency: 'EUR' }}</div>
|
||||
}
|
||||
<div class="detail">
|
||||
<div class="label">
|
||||
@if (
|
||||
orderItemFeature(orderItem) === 'Versand' ||
|
||||
orderItemFeature(orderItem) === 'B2B-Versand' ||
|
||||
orderItemFeature(orderItem) === 'DIG-Versand'
|
||||
) {
|
||||
{{ orderItem?.estimatedDelivery ? 'Lieferung zwischen' : 'Lieferung ab' }}
|
||||
}
|
||||
@if (orderItemFeature(orderItem) === 'Abholung' || orderItemFeature(orderItem) === 'Rücklage') {
|
||||
Abholung ab
|
||||
}
|
||||
</div>
|
||||
@if (!!orderItem?.estimatedDelivery || !!orderItem?.estimatedShippingDate) {
|
||||
<div class="value bg-[#D8DFE5] rounded w-max px-2">
|
||||
@if (!!orderItem?.estimatedDelivery) {
|
||||
{{ orderItem?.estimatedDelivery?.start | date: 'dd.MM.yy' }} und
|
||||
{{ orderItem?.estimatedDelivery?.stop | date: 'dd.MM.yy' }}
|
||||
} @else {
|
||||
@if (!!orderItem?.estimatedShippingDate) {
|
||||
{{ orderItem?.estimatedShippingDate | date: 'dd.MM.yy' }}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<hr class="border-[#EDEFF0] border-t-2 my-4" />
|
||||
@if (!!orderItem?.compartmentCode) {
|
||||
<div class="detail">
|
||||
<div class="label">Abholfachnr.</div>
|
||||
<div class="value">{{ orderItem?.compartmentCode }}</div>
|
||||
</div>
|
||||
}
|
||||
<div class="detail">
|
||||
<div class="label">Vormerker</div>
|
||||
<div class="value">{{ orderItem.isPrebooked ? 'Ja' : 'Nein' }}</div>
|
||||
</div>
|
||||
<hr class="border-[#EDEFF0] border-t-2 my-4" />
|
||||
@if (!!orderItem.paymentProcessing) {
|
||||
<div class="detail">
|
||||
<div class="label">Zahlungsweg</div>
|
||||
<div class="value">{{ orderItem.paymentProcessing || '-' }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (!!orderItem.paymentType) {
|
||||
<div class="detail">
|
||||
<div class="label">Zahlungsart</div>
|
||||
<div class="value">{{ orderItem.paymentType | paymentType }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (receiptCount$ | async; as count) {
|
||||
<h4 class="receipt-header">
|
||||
{{ count > 1 ? 'Belege' : 'Beleg' }}
|
||||
</h4>
|
||||
}
|
||||
@for (receipt of receipts$ | async; track receipt) {
|
||||
@if (!!receipt?.receiptNumber) {
|
||||
<div class="detail">
|
||||
<div class="label">Belegnummer</div>
|
||||
<div class="value">{{ receipt?.receiptNumber }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (!!receipt?.printedDate) {
|
||||
<div class="detail">
|
||||
<div class="label">Erstellt am</div>
|
||||
<div class="value">{{ receipt?.printedDate | date: 'dd.MM.yy | HH:mm' }} Uhr</div>
|
||||
</div>
|
||||
}
|
||||
@if (!!receipt?.receiptText) {
|
||||
<div class="detail">
|
||||
<div class="label">Rechnungstext</div>
|
||||
<div class="value">{{ receipt?.receiptText || '-' }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (!!receipt?.receiptType) {
|
||||
<div class="detail">
|
||||
<div class="label">Belegart</div>
|
||||
<div class="value">
|
||||
{{ receipt?.receiptType === 1 ? 'Lieferschein' : receipt?.receiptType === 64 ? 'Zahlungsbeleg' : '-' }}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@if (!!orderItem.paymentProcessing || !!orderItem.paymentType || !!(receiptCount$ | async)) {
|
||||
<hr
|
||||
class="border-[#EDEFF0] border-t-2 my-4"
|
||||
/>
|
||||
}
|
||||
@if (expanded) {
|
||||
</div>
|
||||
}
|
||||
@if (!!orderItem.retailPrice?.vat?.inPercent) {
|
||||
<div class="detail">
|
||||
<div class="label">MwSt</div>
|
||||
<div class="value">{{ orderItem.retailPrice?.vat?.inPercent }}%</div>
|
||||
</div>
|
||||
}
|
||||
<hr class="border-[#EDEFF0] border-t-2 my-4" />
|
||||
@if (orderItem.supplier) {
|
||||
<div class="detail">
|
||||
<div class="label">Lieferant</div>
|
||||
<div class="value">{{ orderItem.supplier }}</div>
|
||||
@if (!expanded) {
|
||||
<button
|
||||
(click)="expanded = !expanded"
|
||||
type="button"
|
||||
class="page-pickup-shelf-details-item__less text-[#0556B4] font-bold flex flex-row items-center justify-center"
|
||||
>
|
||||
<shared-icon class="mr-1" icon="arrow-back" [size]="20"></shared-icon>
|
||||
Weniger
|
||||
class="page-pickup-shelf-details-item__more text-[#0556B4] font-bold flex flex-row items-center justify-center"
|
||||
[class.flex-row-reverse]="!expanded"
|
||||
>
|
||||
<shared-icon
|
||||
class="mr-1"
|
||||
icon="arrow-back"
|
||||
[size]="20"
|
||||
[class.ml-1]="!expanded"
|
||||
[class.rotate-180]="!expanded"
|
||||
></shared-icon>
|
||||
{{ expanded ? 'Weniger' : 'Mehr' }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (!!orderItem.ssc || !!orderItem.sscText) {
|
||||
<div class="detail">
|
||||
<div class="label">Meldenummer</div>
|
||||
<div class="value">{{ orderItem.ssc }} - {{ orderItem.sscText }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (expanded) {
|
||||
@if (!!orderItem.targetBranch) {
|
||||
<div class="detail">
|
||||
<div class="label">Zielfiliale</div>
|
||||
<div class="value">{{ orderItem.targetBranch }}</div>
|
||||
</div>
|
||||
}
|
||||
<div class="page-pickup-shelf-details-item__comment flex flex-col items-start mt-[1.625rem]">
|
||||
<div class="label mb-[0.375rem]">Anmerkung</div>
|
||||
<div class="flex flex-row w-full">
|
||||
<textarea
|
||||
matInput
|
||||
cdkTextareaAutosize
|
||||
#autosize="cdkTextareaAutosize"
|
||||
cdkAutosizeMinRows="1"
|
||||
cdkAutosizeMaxRows="5"
|
||||
maxlength="200"
|
||||
#specialCommentInput
|
||||
(keydown.delete)="triggerResize()"
|
||||
(keydown.backspace)="triggerResize()"
|
||||
type="text"
|
||||
name="comment"
|
||||
placeholder="Eine Anmerkung hinzufügen"
|
||||
[formControl]="specialCommentControl"
|
||||
[class.inactive]="!specialCommentControl.dirty"
|
||||
></textarea>
|
||||
<div class="comment-actions">
|
||||
@if (!!specialCommentControl.value?.length) {
|
||||
<button
|
||||
type="reset"
|
||||
class="clear"
|
||||
(click)="specialCommentControl.setValue(''); saveSpecialComment(); triggerResize()"
|
||||
>
|
||||
<shared-icon icon="close" [size]="24"></shared-icon>
|
||||
</button>
|
||||
}
|
||||
@if (specialCommentControl?.enabled && specialCommentControl.dirty) {
|
||||
<button
|
||||
class="cta-save"
|
||||
type="submit"
|
||||
(click)="saveSpecialComment()"
|
||||
matomoClickCategory="pickup-shelf-details-item"
|
||||
matomoClickAction="save"
|
||||
matomoClickName="special-comment"
|
||||
>
|
||||
Speichern
|
||||
</button>
|
||||
<div class="detail">
|
||||
<div class="label">
|
||||
@if (
|
||||
orderItemFeature(orderItem) === 'Versand' ||
|
||||
orderItemFeature(orderItem) === 'B2B-Versand' ||
|
||||
orderItemFeature(orderItem) === 'DIG-Versand'
|
||||
) {
|
||||
{{
|
||||
orderItem?.estimatedDelivery
|
||||
? 'Lieferung zwischen'
|
||||
: 'Lieferung ab'
|
||||
}}
|
||||
}
|
||||
@if (
|
||||
orderItemFeature(orderItem) === 'Abholung' ||
|
||||
orderItemFeature(orderItem) === 'Rücklage'
|
||||
) {
|
||||
Abholung ab
|
||||
}
|
||||
</div>
|
||||
@if (
|
||||
!!orderItem?.estimatedDelivery || !!orderItem?.estimatedShippingDate
|
||||
) {
|
||||
<div class="value bg-[#D8DFE5] rounded w-max px-2">
|
||||
@if (!!orderItem?.estimatedDelivery) {
|
||||
{{ orderItem?.estimatedDelivery?.start | date: 'dd.MM.yy' }} und
|
||||
{{ orderItem?.estimatedDelivery?.stop | date: 'dd.MM.yy' }}
|
||||
} @else {
|
||||
@if (!!orderItem?.estimatedShippingDate) {
|
||||
{{ orderItem?.estimatedShippingDate | date: 'dd.MM.yy' }}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<hr class="border-[#EDEFF0] border-t-2 my-4" />
|
||||
@if (!!orderItem?.compartmentCode) {
|
||||
<div class="detail">
|
||||
<div class="label">Abholfachnr.</div>
|
||||
<div class="value">{{ orderItem?.compartmentCode }}</div>
|
||||
</div>
|
||||
}
|
||||
<div class="detail">
|
||||
<div class="label">Vormerker</div>
|
||||
<div class="value">{{ orderItem.isPrebooked ? 'Ja' : 'Nein' }}</div>
|
||||
</div>
|
||||
<hr class="border-[#EDEFF0] border-t-2 my-4" />
|
||||
@if (!!orderItem.paymentProcessing) {
|
||||
<div class="detail">
|
||||
<div class="label">Zahlungsweg</div>
|
||||
<div class="value">{{ orderItem.paymentProcessing || '-' }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (!!orderItem.paymentType) {
|
||||
<div class="detail">
|
||||
<div class="label">Zahlungsart</div>
|
||||
<div class="value">{{ orderItem.paymentType | paymentType }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (receiptCount$ | async; as count) {
|
||||
<h4 class="receipt-header">
|
||||
{{ count > 1 ? 'Belege' : 'Beleg' }}
|
||||
</h4>
|
||||
}
|
||||
@for (receipt of receipts$ | async; track receipt) {
|
||||
@if (!!receipt?.receiptNumber) {
|
||||
<div class="detail">
|
||||
<div class="label">Belegnummer</div>
|
||||
<div class="value">{{ receipt?.receiptNumber }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (!!receipt?.printedDate) {
|
||||
<div class="detail">
|
||||
<div class="label">Erstellt am</div>
|
||||
<div class="value">
|
||||
{{ receipt?.printedDate | date: 'dd.MM.yy | HH:mm' }} Uhr
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (!!receipt?.receiptText) {
|
||||
<div class="detail">
|
||||
<div class="label">Rechnungstext</div>
|
||||
<div class="value">{{ receipt?.receiptText || '-' }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (!!receipt?.receiptType) {
|
||||
<div class="detail">
|
||||
<div class="label">Belegart</div>
|
||||
<div class="value">
|
||||
{{
|
||||
receipt?.receiptType === 1
|
||||
? 'Lieferschein'
|
||||
: receipt?.receiptType === 64
|
||||
? 'Zahlungsbeleg'
|
||||
: '-'
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@if (
|
||||
!!orderItem.paymentProcessing ||
|
||||
!!orderItem.paymentType ||
|
||||
!!(receiptCount$ | async)
|
||||
) {
|
||||
<hr class="border-[#EDEFF0] border-t-2 my-4" />
|
||||
}
|
||||
@if (expanded) {
|
||||
<button
|
||||
(click)="expanded = !expanded"
|
||||
type="button"
|
||||
class="page-pickup-shelf-details-item__less text-[#0556B4] font-bold flex flex-row items-center justify-center"
|
||||
>
|
||||
<shared-icon
|
||||
class="mr-1"
|
||||
icon="arrow-back"
|
||||
[size]="20"
|
||||
></shared-icon>
|
||||
Weniger
|
||||
</button>
|
||||
}
|
||||
}
|
||||
<div
|
||||
class="page-pickup-shelf-details-item__comment flex flex-col items-start mt-[1.625rem]"
|
||||
>
|
||||
<div class="label mb-[0.375rem]">Anmerkung</div>
|
||||
<div class="flex flex-row w-full">
|
||||
<textarea
|
||||
matInput
|
||||
cdkTextareaAutosize
|
||||
#autosize="cdkTextareaAutosize"
|
||||
cdkAutosizeMinRows="1"
|
||||
cdkAutosizeMaxRows="5"
|
||||
maxlength="200"
|
||||
#specialCommentInput
|
||||
(keydown.delete)="triggerResize()"
|
||||
(keydown.backspace)="triggerResize()"
|
||||
type="text"
|
||||
name="comment"
|
||||
placeholder="Eine Anmerkung hinzufügen"
|
||||
[formControl]="specialCommentControl"
|
||||
[class.inactive]="!specialCommentControl.dirty"
|
||||
></textarea>
|
||||
<div class="comment-actions">
|
||||
@if (!!specialCommentControl.value?.length) {
|
||||
<button
|
||||
type="reset"
|
||||
class="clear"
|
||||
(click)="
|
||||
specialCommentControl.setValue('');
|
||||
saveSpecialComment();
|
||||
triggerResize()
|
||||
"
|
||||
>
|
||||
<shared-icon icon="close" [size]="24"></shared-icon>
|
||||
</button>
|
||||
}
|
||||
@if (
|
||||
specialCommentControl?.enabled && specialCommentControl.dirty
|
||||
) {
|
||||
<button
|
||||
class="cta-save"
|
||||
type="submit"
|
||||
(click)="saveSpecialComment()"
|
||||
matomoClickCategory="pickup-shelf-details-item"
|
||||
matomoClickAction="save"
|
||||
matomoClickName="special-comment"
|
||||
>
|
||||
Speichern
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { CdkTextareaAutosize, TextFieldModule } from '@angular/cdk/text-field';
|
||||
import { AsyncPipe, CurrencyPipe, DatePipe, DecimalPipe } from '@angular/common';
|
||||
import {
|
||||
AsyncPipe,
|
||||
CurrencyPipe,
|
||||
DatePipe,
|
||||
DecimalPipe,
|
||||
} from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
@@ -11,12 +16,23 @@ import {
|
||||
inject,
|
||||
OnDestroy,
|
||||
} from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
|
||||
import { NavigateOnClickDirective, ProductImageModule } from '@cdn/product-image';
|
||||
import { DBHOrderItemListItemDTO, OrderDTO, ReceiptDTO } from '@generated/swagger/oms-api';
|
||||
import {
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
UntypedFormControl,
|
||||
} from '@angular/forms';
|
||||
import {
|
||||
NavigateOnClickDirective,
|
||||
ProductImageModule,
|
||||
} from '@cdn/product-image';
|
||||
import {
|
||||
DBHOrderItemListItemDTO,
|
||||
OrderDTO,
|
||||
ReceiptDTO,
|
||||
} from '@generated/swagger/oms-api';
|
||||
import { getOrderItemRewardFeature } from '@isa/oms/data-access';
|
||||
import { UiCommonModule } from '@ui/common';
|
||||
import { LabelComponent, Labeltype, LabelPriority } from '@isa/ui/label';
|
||||
import { LabelComponent } from '@isa/ui/label';
|
||||
import { UiTooltipModule } from '@ui/tooltip';
|
||||
import { PickupShelfPaymentTypePipe } from '../pipes/payment-type.pipe';
|
||||
import { IconModule } from '@shared/components/icon';
|
||||
@@ -60,8 +76,8 @@ export interface PickUpShelfDetailsItemComponentState {
|
||||
NotificationTypePipe,
|
||||
NavigateOnClickDirective,
|
||||
MatomoModule,
|
||||
LabelComponent
|
||||
],
|
||||
LabelComponent,
|
||||
],
|
||||
})
|
||||
export class PickUpShelfDetailsItemComponent
|
||||
extends ComponentStore<PickUpShelfDetailsItemComponentState>
|
||||
@@ -88,7 +104,11 @@ export class PickUpShelfDetailsItemComponent
|
||||
this._store.selectOrderItem(this.orderItem, false);
|
||||
}
|
||||
|
||||
this.patchState({ orderItem, quantity: orderItem?.quantity, more: false });
|
||||
this.patchState({
|
||||
orderItem,
|
||||
quantity: orderItem?.quantity,
|
||||
more: false,
|
||||
});
|
||||
this.specialCommentControl.reset(orderItem?.specialComment);
|
||||
// Add New OrderItem to selected list if selected was set to true by its input
|
||||
if (this.get((s) => s.selected)) {
|
||||
@@ -110,16 +130,24 @@ export class PickUpShelfDetailsItemComponent
|
||||
readonly orderItem$ = this.select((s) => s.orderItem);
|
||||
|
||||
emailNotificationDates$ = this.orderItem$.pipe(
|
||||
switchMap((orderItem) => this._store.getEmailNotificationDate$(orderItem?.orderItemSubsetId)),
|
||||
switchMap((orderItem) =>
|
||||
this._store.getEmailNotificationDate$(orderItem?.orderItemSubsetId),
|
||||
),
|
||||
);
|
||||
|
||||
hasEmailNotification$ = this.emailNotificationDates$.pipe(map((dates) => dates?.length > 0));
|
||||
hasEmailNotification$ = this.emailNotificationDates$.pipe(
|
||||
map((dates) => dates?.length > 0),
|
||||
);
|
||||
|
||||
smsNotificationDates$ = this.orderItem$.pipe(
|
||||
switchMap((orderItem) => this._store.getSmsNotificationDate$(orderItem?.orderItemSubsetId)),
|
||||
switchMap((orderItem) =>
|
||||
this._store.getSmsNotificationDate$(orderItem?.orderItemSubsetId),
|
||||
),
|
||||
);
|
||||
|
||||
hasSmsNotification$ = this.smsNotificationDates$.pipe(map((dates) => dates?.length > 0));
|
||||
hasSmsNotification$ = this.smsNotificationDates$.pipe(
|
||||
map((dates) => dates?.length > 0),
|
||||
);
|
||||
|
||||
/**
|
||||
* Observable that indicates whether the order item has reward points (Lesepunkte).
|
||||
@@ -137,8 +165,15 @@ export class PickUpShelfDetailsItemComponent
|
||||
map((orderItem) => getOrderItemRewardFeature(orderItem)),
|
||||
);
|
||||
|
||||
canChangeQuantity$ = combineLatest([this.orderItem$, this._store.fetchPartial$]).pipe(
|
||||
map(([item, partialPickup]) => ([16, 8192].includes(item?.processingStatus) || partialPickup) && item.quantity > 1),
|
||||
canChangeQuantity$ = combineLatest([
|
||||
this.orderItem$,
|
||||
this._store.fetchPartial$,
|
||||
]).pipe(
|
||||
map(
|
||||
([item, partialPickup]) =>
|
||||
([16, 8192].includes(item?.processingStatus) || partialPickup) &&
|
||||
item.quantity > 1,
|
||||
),
|
||||
);
|
||||
|
||||
get quantity() {
|
||||
@@ -147,7 +182,10 @@ export class PickUpShelfDetailsItemComponent
|
||||
set quantity(quantity: number) {
|
||||
if (this.quantity !== quantity) {
|
||||
this.patchState({ quantity });
|
||||
this._store.setSelectedOrderItemQuantity({ orderItemSubsetId: this.orderItem.orderItemSubsetId, quantity });
|
||||
this._store.setSelectedOrderItemQuantity({
|
||||
orderItemSubsetId: this.orderItem.orderItemSubsetId,
|
||||
quantity,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +193,9 @@ export class PickUpShelfDetailsItemComponent
|
||||
|
||||
@Input()
|
||||
get selected() {
|
||||
return this._store.selectedOrderItemIds.includes(this.orderItem?.orderItemSubsetId);
|
||||
return this._store.selectedOrderItemIds.includes(
|
||||
this.orderItem?.orderItemSubsetId,
|
||||
);
|
||||
}
|
||||
set selected(selected: boolean) {
|
||||
if (this.selected !== selected) {
|
||||
@@ -164,23 +204,40 @@ export class PickUpShelfDetailsItemComponent
|
||||
}
|
||||
}
|
||||
|
||||
readonly selected$ = combineLatest([this.orderItem$, this._store.selectedOrderItemIds$]).pipe(
|
||||
map(([orderItem, selectedItems]) => selectedItems.includes(orderItem?.orderItemSubsetId)),
|
||||
readonly selected$ = combineLatest([
|
||||
this.orderItem$,
|
||||
this._store.selectedOrderItemIds$,
|
||||
]).pipe(
|
||||
map(([orderItem, selectedItems]) =>
|
||||
selectedItems.includes(orderItem?.orderItemSubsetId),
|
||||
),
|
||||
);
|
||||
|
||||
@Output()
|
||||
selectedChange = new EventEmitter<boolean>();
|
||||
|
||||
get isItemSelectable() {
|
||||
return this._store.orderItems?.some((item) => !!item?.actions && item?.actions?.length > 0);
|
||||
return this._store.orderItems?.some(
|
||||
(item) => !!item?.actions && item?.actions?.length > 0,
|
||||
);
|
||||
}
|
||||
|
||||
get selectable() {
|
||||
return this.isItemSelectable && this._store.orderItems.length > 1 && this._store.fetchPartial;
|
||||
return (
|
||||
this.isItemSelectable &&
|
||||
this._store.orderItems.length > 1 &&
|
||||
this._store.fetchPartial
|
||||
);
|
||||
}
|
||||
|
||||
readonly selectable$ = combineLatest([this._store.orderItems$, this._store.fetchPartial$]).pipe(
|
||||
map(([orderItems, fetchPartial]) => orderItems.length > 1 && this.isItemSelectable && fetchPartial),
|
||||
readonly selectable$ = combineLatest([
|
||||
this._store.orderItems$,
|
||||
this._store.fetchPartial$,
|
||||
]).pipe(
|
||||
map(
|
||||
([orderItems, fetchPartial]) =>
|
||||
orderItems.length > 1 && this.isItemSelectable && fetchPartial,
|
||||
),
|
||||
);
|
||||
|
||||
get receipts() {
|
||||
@@ -193,7 +250,9 @@ export class PickUpShelfDetailsItemComponent
|
||||
|
||||
readonly receipts$ = this._store.receipts$;
|
||||
|
||||
readonly receiptCount$ = this.receipts$.pipe(map((receipts) => receipts?.length));
|
||||
readonly receiptCount$ = this.receipts$.pipe(
|
||||
map((receipts) => receipts?.length),
|
||||
);
|
||||
|
||||
specialCommentControl = new UntypedFormControl();
|
||||
|
||||
@@ -203,10 +262,6 @@ export class PickUpShelfDetailsItemComponent
|
||||
|
||||
expanded = false;
|
||||
|
||||
// Expose to template
|
||||
Labeltype = Labeltype;
|
||||
LabelPriority = LabelPriority;
|
||||
|
||||
constructor(private _cdr: ChangeDetectorRef) {
|
||||
super({
|
||||
more: false,
|
||||
@@ -239,8 +294,9 @@ export class PickUpShelfDetailsItemComponent
|
||||
|
||||
orderItemFeature(orderItemListItem: DBHOrderItemListItemDTO) {
|
||||
const orderItems = this.order?.items;
|
||||
return orderItems?.find((orderItem) => orderItem.data.id === orderItemListItem.orderItemId)?.data?.features
|
||||
?.orderType;
|
||||
return orderItems?.find(
|
||||
(orderItem) => orderItem.data.id === orderItemListItem.orderItemId,
|
||||
)?.data?.features?.orderType;
|
||||
}
|
||||
|
||||
triggerResize() {
|
||||
|
||||
@@ -4,12 +4,16 @@
|
||||
[routerLinkActive]="!isTablet && !primaryOutletActive ? 'active' : ''"
|
||||
queryParamsHandling="preserve"
|
||||
(click)="onDetailsClick()"
|
||||
>
|
||||
>
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-grid-container"
|
||||
[class.page-pickup-shelf-list-item__item-grid-container-main]="primaryOutletActive"
|
||||
[class.page-pickup-shelf-list-item__item-grid-container-secondary]="primaryOutletActive && isItemSelectable === undefined"
|
||||
>
|
||||
[class.page-pickup-shelf-list-item__item-grid-container-main]="
|
||||
primaryOutletActive
|
||||
"
|
||||
[class.page-pickup-shelf-list-item__item-grid-container-secondary]="
|
||||
primaryOutletActive && isItemSelectable === undefined
|
||||
"
|
||||
>
|
||||
<div class="page-pickup-shelf-list-item__item-thumbnail text-center">
|
||||
@if (item?.product?.ean | productImage; as productImage) {
|
||||
<img
|
||||
@@ -18,88 +22,126 @@
|
||||
[productImageNavigation]="item?.product?.ean"
|
||||
[src]="productImage"
|
||||
[alt]="item?.product?.name"
|
||||
/>
|
||||
}
|
||||
@if (hasRewardPoints) {
|
||||
<ui-label [type]="Labeltype.Tag" [priority]="LabelPriority.High">
|
||||
Prämie
|
||||
</ui-label>
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-title-contributors flex flex-col"
|
||||
[class.mr-32]="showCompartmentCode && item.features?.paid && (isTablet || isDesktopSmall || primaryOutletActive)"
|
||||
>
|
||||
[class.mr-32]="
|
||||
showCompartmentCode &&
|
||||
item.features?.paid &&
|
||||
(isTablet || isDesktopSmall || primaryOutletActive)
|
||||
"
|
||||
>
|
||||
@if (hasRewardPoints) {
|
||||
<ui-label class="w-10 mb-2">Prämie</ui-label>
|
||||
}
|
||||
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-contributors text-p2 font-normal text-ellipsis overflow-hidden max-w-[24rem] whitespace-nowrap mb-[0.375rem]"
|
||||
>
|
||||
@for (contributor of contributors; track contributor; let last = $last) {
|
||||
>
|
||||
@for (
|
||||
contributor of contributors;
|
||||
track contributor;
|
||||
let last = $last
|
||||
) {
|
||||
{{ contributor }}{{ last ? '' : ';' }}
|
||||
}
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-title font-bold text-p1 desktop-small:text-p2"
|
||||
[class.page-pickup-shelf-list-item__item-title-bigger-text-size]="!primaryOutletActive"
|
||||
>
|
||||
[class.page-pickup-shelf-list-item__item-title-bigger-text-size]="
|
||||
!primaryOutletActive
|
||||
"
|
||||
>
|
||||
{{ item?.product?.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-pickup-shelf-list-item__item-ean-quantity-changed flex flex-col">
|
||||
<div class="page-pickup-shelf-list-item__item-ean text-p2 flex flex-row mb-[0.375rem]" [attr.data-ean]="item?.product?.ean">
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-ean-quantity-changed flex flex-col"
|
||||
>
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-ean text-p2 flex flex-row mb-[0.375rem]"
|
||||
[attr.data-ean]="item?.product?.ean"
|
||||
>
|
||||
<div class="min-w-[7.5rem]">EAN</div>
|
||||
<div class="font-bold">{{ item?.product?.ean }}</div>
|
||||
</div>
|
||||
|
||||
<div class="page-pickup-shelf-list-item__item-quantity flex flex-row text-p2 mb-[0.375rem]" [attr.data-menge]="item.quantity">
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-quantity flex flex-row text-p2 mb-[0.375rem]"
|
||||
[attr.data-menge]="item.quantity"
|
||||
>
|
||||
<div class="min-w-[7.5rem]">Menge</div>
|
||||
<div class="font-bold">{{ item.quantity }} x</div>
|
||||
</div>
|
||||
|
||||
<div class="page-pickup-shelf-list-item__item-changed text-p2" [attr.data-geaendert]="item?.processingStatusDate">
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-changed text-p2"
|
||||
[attr.data-geaendert]="item?.processingStatusDate"
|
||||
>
|
||||
@if (showChangeDate) {
|
||||
<div class="flex flex-row">
|
||||
<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>
|
||||
} @else {
|
||||
<div class="flex flex-row" [attr.data-bestelldatum]="item?.orderDate">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div class="page-pickup-shelf-list-item__item-order-number-processing-status-paid flex flex-col">
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-order-number-processing-status-paid flex flex-col"
|
||||
>
|
||||
@if (showCompartmentCode) {
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-order-number text-h3 mb-[0.375rem] self-end font-bold break-all text-right"
|
||||
[attr.data-compartment-code]="item?.compartmentCode"
|
||||
[attr.data-compartment-info]="item?.compartmentInfo"
|
||||
>
|
||||
{{ item?.compartmentCode }}{{ item?.compartmentInfo && '_' + item?.compartmentInfo }}
|
||||
>
|
||||
{{ item?.compartmentCode
|
||||
}}{{ item?.compartmentInfo && '_' + item?.compartmentInfo }}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="page-pickup-shelf-list-item__item-processing-paid-status flex flex-col font-bold self-end text-p2 mb-[0.375rem]">
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-processing-paid-status flex flex-col font-bold self-end text-p2 mb-[0.375rem]"
|
||||
>
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-processing-status flex flex-row mb-[0.375rem] rounded p-3 py-[0.125rem] text-white"
|
||||
[style]="processingStatusColor"
|
||||
[attr.data-processing-status]="item.processingStatus"
|
||||
>
|
||||
>
|
||||
{{ item.processingStatus | processingStatus }}
|
||||
</div>
|
||||
|
||||
<div class="page-pickup-shelf-list-item__item-paid self-end flex flex-row">
|
||||
@if (item.features?.paid && (isTablet || isDesktopSmall || primaryOutletActive)) {
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-paid self-end flex flex-row"
|
||||
>
|
||||
@if (
|
||||
item.features?.paid &&
|
||||
(isTablet || isDesktopSmall || primaryOutletActive)
|
||||
) {
|
||||
<div
|
||||
class="font-bold flex flex-row items-center justify-center text-p2 text-[#26830C]"
|
||||
[attr.data-paid]="item.features?.paid"
|
||||
>
|
||||
<shared-icon class="flex items-center justify-center mr-[0.375rem]" [size]="24" icon="credit-card"></shared-icon>
|
||||
>
|
||||
<shared-icon
|
||||
class="flex items-center justify-center mr-[0.375rem]"
|
||||
[size]="24"
|
||||
icon="credit-card"
|
||||
></shared-icon>
|
||||
{{ item.features?.paid }}
|
||||
</div>
|
||||
}
|
||||
@@ -110,28 +152,35 @@
|
||||
@if (isItemSelectable) {
|
||||
<div
|
||||
class="page-pickup-shelf-list-item__item-select-bullet justify-self-end self-center mb-2"
|
||||
[class.page-pickup-shelf-list-item__item-select-bullet-primary]="primaryOutletActive"
|
||||
>
|
||||
[class.page-pickup-shelf-list-item__item-select-bullet-primary]="
|
||||
primaryOutletActive
|
||||
"
|
||||
>
|
||||
<input
|
||||
(click)="$event.stopPropagation()"
|
||||
[ngModel]="selectedItem"
|
||||
(ngModelChange)="
|
||||
setSelected();
|
||||
tracker.trackEvent({ category: 'pickup-shelf-list-item', action: 'select', name: item?.product?.name, value: $event ? 1 : 0 })
|
||||
"
|
||||
(ngModelChange)="
|
||||
setSelected();
|
||||
tracker.trackEvent({
|
||||
category: 'pickup-shelf-list-item',
|
||||
action: 'select',
|
||||
name: item?.product?.name,
|
||||
value: $event ? 1 : 0,
|
||||
})
|
||||
"
|
||||
class="isa-select-bullet"
|
||||
type="checkbox"
|
||||
matomoTracker
|
||||
#tracker="matomo"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div
|
||||
[attr.data-special-comment]="item?.specialComment"
|
||||
class="page-pickup-shelf-list-item__item-special-comment break-words font-bold text-p2 mt-[0.375rem] text-[#996900]"
|
||||
>
|
||||
{{ item?.specialComment }}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div
|
||||
[attr.data-special-comment]="item?.specialComment"
|
||||
class="page-pickup-shelf-list-item__item-special-comment break-words font-bold text-p2 mt-[0.375rem] text-[#996900]"
|
||||
>
|
||||
{{ item?.specialComment }}
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, Input, inject } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
Input,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { RouterLink, RouterLinkActive } from '@angular/router';
|
||||
import { NavigateOnClickDirective, ProductImageModule } from '@cdn/product-image';
|
||||
import {
|
||||
NavigateOnClickDirective,
|
||||
ProductImageModule,
|
||||
} from '@cdn/product-image';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { IconModule } from '@shared/components/icon';
|
||||
import { DBHOrderItemListItemDTO } from '@generated/swagger/oms-api';
|
||||
import { getOrderItemRewardFeature } from '@isa/oms/data-access';
|
||||
import { LabelComponent, Labeltype, LabelPriority } from '@isa/ui/label';
|
||||
import { LabelComponent } from '@isa/ui/label';
|
||||
import { UiCommonModule } from '@ui/common';
|
||||
import { PickupShelfProcessingStatusPipe } from '../pipes/processing-status.pipe';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
@@ -32,8 +41,8 @@ import { MatomoModule } from 'ngx-matomo-client';
|
||||
PickupShelfProcessingStatusPipe,
|
||||
NavigateOnClickDirective,
|
||||
MatomoModule,
|
||||
LabelComponent
|
||||
],
|
||||
LabelComponent,
|
||||
],
|
||||
providers: [PickupShelfProcessingStatusPipe],
|
||||
})
|
||||
export class PickUpShelfListItemComponent {
|
||||
@@ -45,6 +54,7 @@ export class PickUpShelfListItemComponent {
|
||||
|
||||
@Input() primaryOutletActive = false;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@Input() itemDetailsLink: any[] = [];
|
||||
|
||||
@Input() isItemSelectable?: boolean = undefined;
|
||||
@@ -64,7 +74,9 @@ export class PickUpShelfListItemComponent {
|
||||
}
|
||||
|
||||
get contributors() {
|
||||
return this.item?.product?.contributors?.split(';').map((val) => val.trim());
|
||||
return this.item?.product?.contributors
|
||||
?.split(';')
|
||||
.map((val) => val.trim());
|
||||
}
|
||||
|
||||
get showChangeDate() {
|
||||
@@ -73,11 +85,19 @@ export class PickUpShelfListItemComponent {
|
||||
|
||||
// Zeige nur CompartmentCode an wenn verfügbar
|
||||
get showCompartmentCode() {
|
||||
return !!this.item?.compartmentCode && (this.isTablet || this.isDesktopSmall || this.primaryOutletActive);
|
||||
return (
|
||||
!!this.item?.compartmentCode &&
|
||||
(this.isTablet || this.isDesktopSmall || this.primaryOutletActive)
|
||||
);
|
||||
}
|
||||
|
||||
get processingStatusColor() {
|
||||
return { 'background-color': this._processingStatusPipe.transform(this.item?.processingStatus, true) };
|
||||
return {
|
||||
'background-color': this._processingStatusPipe.transform(
|
||||
this.item?.processingStatus,
|
||||
true,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,14 +110,12 @@ export class PickUpShelfListItemComponent {
|
||||
|
||||
selected$ = this.store.selectedListItems$.pipe(
|
||||
map((selectedListItems) =>
|
||||
selectedListItems?.find((item) => item?.orderItemSubsetId === this.item?.orderItemSubsetId),
|
||||
selectedListItems?.find(
|
||||
(item) => item?.orderItemSubsetId === this.item?.orderItemSubsetId,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Expose to template
|
||||
Labeltype = Labeltype;
|
||||
LabelPriority = LabelPriority;
|
||||
|
||||
constructor(
|
||||
private _elRef: ElementRef,
|
||||
private _environment: EnvironmentService,
|
||||
@@ -125,7 +143,9 @@ export class PickUpShelfListItemComponent {
|
||||
store: 'PickupShelfDetailsStore',
|
||||
})) ?? [];
|
||||
|
||||
return items.some((i) => i.orderItemSubsetId === this.item.orderItemSubsetId);
|
||||
return items.some(
|
||||
(i) => i.orderItemSubsetId === this.item.orderItemSubsetId,
|
||||
);
|
||||
}
|
||||
|
||||
addOrderItemIntoCache() {
|
||||
@@ -144,7 +164,10 @@ export class PickUpShelfListItemComponent {
|
||||
}
|
||||
|
||||
scrollIntoView() {
|
||||
this._elRef.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
this._elRef.nativeElement.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'center',
|
||||
});
|
||||
}
|
||||
|
||||
setSelected() {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
@import "../../../libs/ui/skeleton-loader/src/skeleton-loader.scss";
|
||||
@import "../../../libs/ui/tooltip/src/tooltip.scss";
|
||||
@import "../../../libs/ui/label/src/label.scss";
|
||||
@import "../../../libs/ui/notice/src/notice.scss";
|
||||
@import "../../../libs/ui/switch/src/switch.scss";
|
||||
|
||||
.input-control {
|
||||
|
||||
@@ -1,33 +1,25 @@
|
||||
import { argsToTemplate, type Meta, type StoryObj } from '@storybook/angular';
|
||||
import { Labeltype, LabelPriority, LabelComponent } from '@isa/ui/label';
|
||||
import { LabelComponent } from '@isa/ui/label';
|
||||
|
||||
type UiLabelInputs = {
|
||||
type: Labeltype;
|
||||
priority: LabelPriority;
|
||||
type LabelInputs = {
|
||||
active: boolean;
|
||||
};
|
||||
|
||||
const meta: Meta<UiLabelInputs> = {
|
||||
const meta: Meta<LabelInputs> = {
|
||||
component: LabelComponent,
|
||||
title: 'ui/label/Label',
|
||||
argTypes: {
|
||||
type: {
|
||||
control: { type: 'select' },
|
||||
options: Object.values(Labeltype),
|
||||
description: 'Determines the label type',
|
||||
},
|
||||
priority: {
|
||||
control: { type: 'select' },
|
||||
options: Object.values(LabelPriority),
|
||||
description: 'Determines the label priority',
|
||||
active: {
|
||||
control: { type: 'boolean' },
|
||||
description: 'Determines if the label is active (hover/pressed state)',
|
||||
},
|
||||
},
|
||||
args: {
|
||||
type: 'tag',
|
||||
priority: 'high',
|
||||
active: false,
|
||||
},
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: `<ui-label ${argsToTemplate(args)}>Prio 1</ui-label>`,
|
||||
template: `<ui-label ${argsToTemplate(args)}>Prämie</ui-label>`,
|
||||
}),
|
||||
};
|
||||
export default meta;
|
||||
@@ -37,3 +29,21 @@ type Story = StoryObj<LabelComponent>;
|
||||
export const Default: Story = {
|
||||
args: {},
|
||||
};
|
||||
|
||||
export const Active: Story = {
|
||||
args: {
|
||||
active: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const RewardExample: Story = {
|
||||
args: {},
|
||||
render: () => ({
|
||||
template: `
|
||||
<div style="display: flex; gap: 1rem; align-items: center;">
|
||||
<ui-label>Prämie</ui-label>
|
||||
<ui-label [active]="true">Active</ui-label>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
};
|
||||
|
||||
59
apps/isa-app/stories/ui/label/ui-prio-label.stories.ts
Normal file
59
apps/isa-app/stories/ui/label/ui-prio-label.stories.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { argsToTemplate, type Meta, type StoryObj } from '@storybook/angular';
|
||||
import { PrioLabelComponent } from '@isa/ui/label';
|
||||
|
||||
type PrioLabelInputs = {
|
||||
priority: 1 | 2;
|
||||
};
|
||||
|
||||
const meta: Meta<PrioLabelInputs> = {
|
||||
component: PrioLabelComponent,
|
||||
title: 'ui/label/PrioLabel',
|
||||
argTypes: {
|
||||
priority: {
|
||||
control: { type: 'select' },
|
||||
options: [1, 2],
|
||||
description: 'The priority level (1 = high, 2 = low)',
|
||||
},
|
||||
},
|
||||
args: {
|
||||
priority: 1,
|
||||
},
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: `<ui-prio-label ${argsToTemplate(args)}>Pflicht</ui-prio-label>`,
|
||||
}),
|
||||
};
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<PrioLabelComponent>;
|
||||
|
||||
export const Priority1: Story = {
|
||||
args: {
|
||||
priority: 1,
|
||||
},
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: `<ui-prio-label [priority]="priority">Pflicht</ui-prio-label>`,
|
||||
}),
|
||||
};
|
||||
|
||||
export const Priority2: Story = {
|
||||
args: {
|
||||
priority: 2,
|
||||
},
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: `<ui-prio-label [priority]="priority">Prio 2</ui-prio-label>`,
|
||||
}),
|
||||
};
|
||||
|
||||
export const AllPriorities: Story = {
|
||||
render: () => ({
|
||||
template: `
|
||||
<div style="display: flex; gap: 1rem; align-items: center;">
|
||||
<ui-prio-label [priority]="1">Pflicht</ui-prio-label>
|
||||
<ui-prio-label [priority]="2">Prio 2</ui-prio-label>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
};
|
||||
70
apps/isa-app/stories/ui/notice/ui-notice.stories.ts
Normal file
70
apps/isa-app/stories/ui/notice/ui-notice.stories.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { argsToTemplate, type Meta, type StoryObj } from '@storybook/angular';
|
||||
import { NoticeComponent, NoticePriority } from '@isa/ui/notice';
|
||||
|
||||
type NoticeInputs = {
|
||||
priority: NoticePriority;
|
||||
};
|
||||
|
||||
const meta: Meta<NoticeInputs> = {
|
||||
component: NoticeComponent,
|
||||
title: 'ui/notice/Notice',
|
||||
argTypes: {
|
||||
priority: {
|
||||
control: { type: 'select' },
|
||||
options: Object.values(NoticePriority),
|
||||
description: 'The priority level (high, medium, low)',
|
||||
},
|
||||
},
|
||||
args: {
|
||||
priority: NoticePriority.High,
|
||||
},
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: `<ui-notice ${argsToTemplate(args)}>Important message</ui-notice>`,
|
||||
}),
|
||||
};
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<NoticeComponent>;
|
||||
|
||||
export const High: Story = {
|
||||
args: {
|
||||
priority: NoticePriority.High,
|
||||
},
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: `<ui-notice [priority]="priority">Action Required</ui-notice>`,
|
||||
}),
|
||||
};
|
||||
|
||||
export const Medium: Story = {
|
||||
args: {
|
||||
priority: NoticePriority.Medium,
|
||||
},
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: `<ui-notice [priority]="priority">Secondary Information</ui-notice>`,
|
||||
}),
|
||||
};
|
||||
|
||||
export const Low: Story = {
|
||||
args: {
|
||||
priority: NoticePriority.Low,
|
||||
},
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: `<ui-notice [priority]="priority">Info Message</ui-notice>`,
|
||||
}),
|
||||
};
|
||||
|
||||
export const AllPriorities: Story = {
|
||||
render: () => ({
|
||||
template: `
|
||||
<div style="display: flex; flex-direction: column; gap: 1rem;">
|
||||
<ui-notice priority="high">High Priority</ui-notice>
|
||||
<ui-notice priority="medium">Medium Priority</ui-notice>
|
||||
<ui-notice priority="low">Low Priority</ui-notice>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
};
|
||||
Reference in New Issue
Block a user