Skip to content

Commit

Permalink
feat: Use tabs instead of radio group for pickup options (#19406)
Browse files Browse the repository at this point in the history
  • Loading branch information
sdrozdsap authored Nov 5, 2024
1 parent 4847222 commit f299a3a
Show file tree
Hide file tree
Showing 24 changed files with 918 additions and 330 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<ng-template
[cxOutlet]="CartOutlets.ADD_TO_CART_PICKUP_OPTION"
[(cxComponentRef)]="pickupOptionCompRef"
(cxComponentRefChange)="onPickupOptionsCompLoaded()"
></ng-template>
</ng-container>

Expand All @@ -41,7 +42,7 @@
: 'btn btn-primary btn-block'
"
type="submit"
[disabled]="quantity <= 0 || quantity > maxQuantity"
[disabled]="disabled || quantity <= 0 || quantity > maxQuantity"
>
<span
*ngIf="
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class AddToCartComponent implements OnInit, OnDestroy {
@ViewChild('addToCartDialogTriggerEl') addToCartDialogTriggerEl: ElementRef;

maxQuantity: number;

disabled: boolean = false;
hasStock: boolean = false;
inventoryThreshold: boolean = false;

Expand All @@ -73,7 +73,7 @@ export class AddToCartComponent implements OnInit, OnDestroy {

quantity = 1;

subscription: Subscription;
subscription = new Subscription();

addToCartForm = new UntypedFormGroup({
quantity: new UntypedFormControl(1, { updateOn: 'blur' }),
Expand Down Expand Up @@ -128,17 +128,18 @@ export class AddToCartComponent implements OnInit, OnDestroy {
this.hasStock = true;
this.cd.markForCheck();
} else {
this.subscription = (
this.productListItemContext
this.subscription.add(
(this.productListItemContext
? this.productListItemContext.product$
: this.currentProductService.getProduct()
)
.pipe(filter(isNotNullable))
.subscribe((product) => {
this.productCode = product.code ?? '';
this.setStockInfo(product);
this.cd.markForCheck();
});
)
.pipe(filter(isNotNullable))
.subscribe((product) => {
this.productCode = product.code ?? '';
this.setStockInfo(product);
this.cd.markForCheck();
})
);
}
}

Expand Down Expand Up @@ -242,9 +243,25 @@ export class AddToCartComponent implements OnInit, OnDestroy {
return newEvent;
}

ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
onPickupOptionsCompLoaded() {
if (this.featureConfigService.isEnabled('a11yPickupOptionsTabs')) {
this.subscription.add(
this.pickupOptionCompRef.instance.intendedPickupChange.subscribe(
(
intendedPickupLocation:
| { pickupOption?: 'pickup' | 'delivery'; displayName?: string }
| undefined
) => {
this.disabled =
intendedPickupLocation?.pickupOption === 'pickup' &&
!intendedPickupLocation.displayName;
}
)
);
}
}

ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export class CartItemListComponent implements OnInit, OnDestroy {
) {
useFeatureStyles('a11yPreventHorizontalScroll');
useFeatureStyles('a11yQTY2Quantity');
useFeatureStyles('a11yPickupOptionsTabs');
}

ngOnInit(): void {
Expand Down
33 changes: 33 additions & 0 deletions feature-libs/cart/base/styles/components/_cart-item-list.scss
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,39 @@

cx-cart-pickup-options-container {
margin-inline-start: 6rem;

@include forFeature('a11yPickupOptionsTabs') {
cx-pickup-options {
&,
& button {
@include type('7');
}

.cx-pickup-options-legend {
@include type('8');
}

.cx-pickup-options-container {
padding: 0.5rem;
}

.cx-pickup-options {
width: 75%;
}

cx-tab {
--cx-tab-panel-bg: var(--cx-color-inverse);
--cx-tab-panel-padding: 0.5rem 1rem;
--cx-tab-gap: 0.5rem;
--cx-tab-btn-bg-color: var(--cx-color-inverse);
--cx-tab-panel-margin-top: 0.5rem;

.tab-btn:after {
margin-top: 5px;
}
}
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
"changeStore": "Change Store",
"delivery": "Ship It (Free Return)",
"pickup": "Free Pickup In Store",
"selectStore": "Select Store"
"shipIt": "Ship It",
"selectStore": "Select Store",
"freeReturn": "Free Return",
"storeIsNotSelected": "Store for pickup is not selected."
},
"setPreferredStore": {
"makeThisMyStore": "Make This My Store",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,10 @@ export class CartPickupOptionsContainerComponent implements OnInit, OnDestroy {
);
});

if (!this.displayNameIsSet) {
if (
!this.featureConfigService.isEnabled('a11yPickupOptionsTabs') &&
!this.displayNameIsSet
) {
this.openDialog(event.triggerElement);
}
} else if (typeof event === 'string') {
Expand Down Expand Up @@ -344,7 +347,10 @@ export class CartPickupOptionsContainerComponent implements OnInit, OnDestroy {
);
});

if (!this.displayNameIsSet) {
if (
!this.featureConfigService.isEnabled('a11yPickupOptionsTabs') &&
!this.displayNameIsSet
) {
this.openDialog();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ describe('PdpPickupOptionsComponent', () => {
let intendedPickupLocationService: IntendedPickupLocationFacade;
let currentProductService: CurrentProductService;
let preferredStoreFacade: PreferredStoreFacade;
let featureConfigService: FeatureConfigService;

const configureTestingModule = () =>
TestBed.configureTestingModule({
Expand Down Expand Up @@ -145,6 +146,7 @@ describe('PdpPickupOptionsComponent', () => {
preferredStoreFacade = TestBed.inject(PreferredStoreFacade);

currentProductService = TestBed.inject(CurrentProductService);
featureConfigService = TestBed.inject(FeatureConfigService);

spyOn(currentProductService, 'getProduct').and.callThrough();
spyOn(launchDialogService, 'openDialog').and.callThrough();
Expand Down Expand Up @@ -218,13 +220,23 @@ describe('PdpPickupOptionsComponent', () => {
expect(component.openDialog).not.toHaveBeenCalled();
});

it('should open dialog if displayName is not set on pickup option change', () => {
it('should open dialog if displayName is not set and a11yPickupOptionsTabs disabled', () => {
spyOn(featureConfigService, 'isEnabled').and.returnValue(false);
spyOn(component, 'openDialog');
component['displayNameIsSet'] = false;
const option = 'pickup';
component.onPickupOptionChange(option);
expect(component.openDialog).toHaveBeenCalled();
});

it('should NOT open dialog if displayName is not set and a11yPickupOptionsTabs enabled', () => {
spyOn(featureConfigService, 'isEnabled').and.returnValue(true);
spyOn(component, 'openDialog');
component['displayNameIsSet'] = false;
const option = 'pickup';
component.onPickupOptionChange(option);
expect(component.openDialog).not.toHaveBeenCalled();
});
});
describe('without current product', () => {
beforeEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import {
Component,
ElementRef,
inject,
EventEmitter,
OnDestroy,
OnInit,
Output,
ViewChild,
ViewContainerRef,
} from '@angular/core';
Expand Down Expand Up @@ -63,6 +65,9 @@ export class PdpPickupOptionsContainerComponent implements OnInit, OnDestroy {
* The 'triggerElement' is passed through 'PickupOptionChange' event instead.
*/
@ViewChild('open') element: ElementRef;
@Output() intendedPickupChange = new EventEmitter<
AugmentedPointOfService | undefined
>();
subscription = new Subscription();

availableForPickup = false;
Expand Down Expand Up @@ -147,6 +152,10 @@ export class PdpPickupOptionsContainerComponent implements OnInit, OnDestroy {
)
);

this.subscription.add(
this.intendedPickupLocation$.subscribe(this.intendedPickupChange)
);

this.subscription.add(
combineLatest([
productCode$,
Expand Down Expand Up @@ -202,6 +211,19 @@ export class PdpPickupOptionsContainerComponent implements OnInit, OnDestroy {
onPickupOptionChange(
event: { option: PickupOption; triggerElement: ElementRef } | PickupOption
): void {
const handleChange = (
option: PickupOption,
triggerElement?: ElementRef
) => {
if (!this.featureConfigService.isEnabled('a11yPickupOptionsTabs')) {
if (option === 'delivery') {
return;
}
if (!this.displayNameIsSet) {
this.openDialog(triggerElement);
}
}
};
if (
this.featureConfigService.isEnabled('a11yDialogTriggerRefocus') &&
typeof event === 'object'
Expand All @@ -211,23 +233,13 @@ export class PdpPickupOptionsContainerComponent implements OnInit, OnDestroy {
this.productCode,
option
);
if (option === 'delivery') {
return;
}
if (!this.displayNameIsSet) {
this.openDialog(triggerElement);
}
handleChange(option, triggerElement);
} else if (typeof event === 'string') {
this.intendedPickupLocationService.setPickupOption(
this.productCode,
event
);
if (event === 'delivery') {
return;
}
if (!this.displayNameIsSet) {
this.openDialog();
}
handleChange(event);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,25 +164,27 @@ export class PickupOptionDialogComponent implements OnInit, OnDestroy {
close(reason: string): void {
this.launchDialogService.closeDialog(reason);
if (reason === this.CLOSE_WITHOUT_SELECTION) {
this.intendedPickupLocationService
.getIntendedLocation(this.productCode)
.pipe(
filter(
(store: AugmentedPointOfService | undefined) =>
typeof store !== 'undefined'
),
map((store) => store as AugmentedPointOfService),
filter((store) => !store.name),
take(1),
tap(() =>
this.intendedPickupLocationService.setPickupOption(
this.productCode,
'delivery'
if (!this.featureConfigService.isEnabled('a11yPickupOptionsTabs')) {
this.intendedPickupLocationService
.getIntendedLocation(this.productCode)
.pipe(
filter(
(store: AugmentedPointOfService | undefined) =>
typeof store !== 'undefined'
),
map((store) => store as AugmentedPointOfService),
filter((store) => !store.name),
take(1),
tap(() =>
this.intendedPickupLocationService.setPickupOption(
this.productCode,
'delivery'
)
)
)
)
.subscribe();
this.pickupOptionFacade.setPickupOption(this.entryNumber, 'delivery');
.subscribe();
this.pickupOptionFacade.setPickupOption(this.entryNumber, 'delivery');
}
return;
}
this.subscription.add(
Expand Down
Loading

0 comments on commit f299a3a

Please sign in to comment.