mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merged PR 2021: feat(pickup-shelf): display Prämie label and Lesepunkte for reward items
feat(pickup-shelf): display Prämie label and Lesepunkte for reward items - Add "Prämie" ui-label badge below product images in both list and details views - Display Lesepunkte value instead of price for reward items - Update getOrderItemRewardFeature helper to use structural typing for better type flexibility - Apply to pickup-shelf-details-item and pickup-shelf-list-item components Fixes #5467
This commit is contained in:
committed by
Nino Righi
parent
cc186dbbe2
commit
f261fc9987
@@ -40,6 +40,11 @@
|
||||
[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]">
|
||||
@@ -117,10 +122,15 @@
|
||||
<div class="value">{{ orderItem.product?.ean }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (orderItem.price !== undefined) {
|
||||
@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) {
|
||||
|
||||
@@ -21,6 +21,8 @@ button {
|
||||
}
|
||||
|
||||
.page-pickup-shelf-details-item__thumbnail {
|
||||
@apply flex flex-col items-center gap-2;
|
||||
|
||||
img {
|
||||
@apply rounded shadow-cta w-[3.625rem] max-h-[5.9375rem];
|
||||
}
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import { CdkTextareaAutosize, TextFieldModule } from '@angular/cdk/text-field';
|
||||
import { AsyncPipe, CurrencyPipe, DatePipe } from '@angular/common';
|
||||
import { AsyncPipe, CurrencyPipe, DatePipe, DecimalPipe } from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
OnInit,
|
||||
Output,
|
||||
ViewChild,
|
||||
inject, OnDestroy,
|
||||
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 { getOrderItemRewardFeature } from '@isa/oms/data-access';
|
||||
import { UiCommonModule } from '@ui/common';
|
||||
import { LabelComponent, Labeltype, LabelPriority } from '@isa/ui/label';
|
||||
import { UiTooltipModule } from '@ui/tooltip';
|
||||
import { PickupShelfPaymentTypePipe } from '../pipes/payment-type.pipe';
|
||||
import { IconModule } from '@shared/components/icon';
|
||||
@@ -48,6 +50,7 @@ export interface PickUpShelfDetailsItemComponentState {
|
||||
ReactiveFormsModule,
|
||||
CurrencyPipe,
|
||||
DatePipe,
|
||||
DecimalPipe,
|
||||
AsyncPipe,
|
||||
ProductImageModule,
|
||||
TextFieldModule,
|
||||
@@ -56,12 +59,13 @@ export interface PickUpShelfDetailsItemComponentState {
|
||||
UiQuantityDropdownModule,
|
||||
NotificationTypePipe,
|
||||
NavigateOnClickDirective,
|
||||
MatomoModule
|
||||
MatomoModule,
|
||||
LabelComponent
|
||||
],
|
||||
})
|
||||
export class PickUpShelfDetailsItemComponent
|
||||
extends ComponentStore<PickUpShelfDetailsItemComponentState>
|
||||
implements OnInit, OnDestroy
|
||||
implements OnDestroy
|
||||
{
|
||||
private _store = inject(PickupShelfDetailsStore);
|
||||
|
||||
@@ -117,6 +121,22 @@ export class PickUpShelfDetailsItemComponent
|
||||
|
||||
hasSmsNotification$ = this.smsNotificationDates$.pipe(map((dates) => dates?.length > 0));
|
||||
|
||||
/**
|
||||
* Observable that indicates whether the order item has reward points (Lesepunkte).
|
||||
* Returns true if the item has a 'praemie' feature.
|
||||
*/
|
||||
hasRewardPoints$ = this.orderItem$.pipe(
|
||||
map((orderItem) => getOrderItemRewardFeature(orderItem) !== undefined),
|
||||
);
|
||||
|
||||
/**
|
||||
* Observable that emits the reward points (Lesepunkte) value for the order item.
|
||||
* Returns the parsed numeric value from the 'praemie' feature, or undefined if not present.
|
||||
*/
|
||||
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),
|
||||
);
|
||||
@@ -167,12 +187,12 @@ export class PickUpShelfDetailsItemComponent
|
||||
return this._store.receipts;
|
||||
}
|
||||
|
||||
readonly receipts$ = this._store.receipts$;
|
||||
|
||||
set receipts(receipts: ReceiptDTO[]) {
|
||||
this._store.updateReceipts(receipts);
|
||||
}
|
||||
|
||||
readonly receipts$ = this._store.receipts$;
|
||||
|
||||
readonly receiptCount$ = this.receipts$.pipe(map((receipts) => receipts?.length));
|
||||
|
||||
specialCommentControl = new UntypedFormControl();
|
||||
@@ -181,7 +201,11 @@ export class PickUpShelfDetailsItemComponent
|
||||
|
||||
private _onDestroy$ = new Subject<void>();
|
||||
|
||||
expanded: boolean = false;
|
||||
expanded = false;
|
||||
|
||||
// Expose to template
|
||||
Labeltype = Labeltype;
|
||||
LabelPriority = LabelPriority;
|
||||
|
||||
constructor(private _cdr: ChangeDetectorRef) {
|
||||
super({
|
||||
@@ -189,8 +213,6 @@ export class PickUpShelfDetailsItemComponent
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
ngOnDestroy() {
|
||||
// Remove Prev OrderItem from selected list
|
||||
this._store.selectOrderItem(this.orderItem, false);
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
.page-pickup-shelf-list-item__item-thumbnail {
|
||||
grid-area: thumbnail;
|
||||
@apply flex flex-col items-center gap-2;
|
||||
}
|
||||
|
||||
.page-pickup-shelf-list-item__item-image {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
[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 w-[3.125rem] h-[4.9375rem]">
|
||||
<div class="page-pickup-shelf-list-item__item-thumbnail text-center">
|
||||
@if (item?.product?.ean | productImage; as productImage) {
|
||||
<img
|
||||
class="page-pickup-shelf-list-item__item-image w-[3.125rem] max-h-[4.9375rem]"
|
||||
@@ -20,6 +20,11 @@
|
||||
[alt]="item?.product?.name"
|
||||
/>
|
||||
}
|
||||
@if (hasRewardPoints) {
|
||||
<ui-label [type]="Labeltype.Tag" [priority]="LabelPriority.High">
|
||||
Prämie
|
||||
</ui-label>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
||||
@@ -5,6 +5,8 @@ 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 { UiCommonModule } from '@ui/common';
|
||||
import { PickupShelfProcessingStatusPipe } from '../pipes/processing-status.pipe';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
@@ -29,7 +31,8 @@ import { MatomoModule } from 'ngx-matomo-client';
|
||||
UiCommonModule,
|
||||
PickupShelfProcessingStatusPipe,
|
||||
NavigateOnClickDirective,
|
||||
MatomoModule
|
||||
MatomoModule,
|
||||
LabelComponent
|
||||
],
|
||||
providers: [PickupShelfProcessingStatusPipe],
|
||||
})
|
||||
@@ -77,12 +80,24 @@ export class PickUpShelfListItemComponent {
|
||||
return { 'background-color': this._processingStatusPipe.transform(this.item?.processingStatus, true) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the order item has reward points (Lesepunkte).
|
||||
* Returns true if the item has a 'praemie' feature.
|
||||
*/
|
||||
get hasRewardPoints() {
|
||||
return getOrderItemRewardFeature(this.item) !== undefined;
|
||||
}
|
||||
|
||||
selected$ = this.store.selectedListItems$.pipe(
|
||||
map((selectedListItems) =>
|
||||
selectedListItems?.find((item) => item?.orderItemSubsetId === this.item?.orderItemSubsetId),
|
||||
),
|
||||
);
|
||||
|
||||
// Expose to template
|
||||
Labeltype = Labeltype;
|
||||
LabelPriority = LabelPriority;
|
||||
|
||||
constructor(
|
||||
private _elRef: ElementRef,
|
||||
private _environment: EnvironmentService,
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
import { OrderItemDTO, DisplayOrderItemDTO } from '@generated/swagger/oms-api';
|
||||
|
||||
/**
|
||||
* Extracts and parses the reward points (Lesepunkte) value from an order item's features.
|
||||
*
|
||||
* @param orderItem - An object containing a features property with key-value pairs
|
||||
* @returns The parsed numeric value of reward points, or undefined if not present
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const orderItem = { features: { praemie: '12.345' } };
|
||||
* const points = getOrderItemRewardFeature(orderItem); // returns 12345
|
||||
* ```
|
||||
*/
|
||||
export function getOrderItemRewardFeatureHelper(
|
||||
orderItem: OrderItemDTO | DisplayOrderItemDTO | undefined,
|
||||
orderItem: { features?: { [key: string]: string } } | undefined,
|
||||
): undefined | number {
|
||||
if (!orderItem || !orderItem.features) {
|
||||
return undefined;
|
||||
|
||||
Reference in New Issue
Block a user