From d4125b1bb0b78b4902ad19b0d6fb88d5729158b9 Mon Sep 17 00:00:00 2001 From: Susanne Schneider Date: Fri, 23 Aug 2024 17:13:35 +0200 Subject: [PATCH] feat: implement switch component and use it for the active status of recurring orders --- src/app/core/facades/account.facade.ts | 4 +++ .../recurring-orders.service.ts | 26 +++++++++++++++++- .../recurring-orders.actions.ts | 3 +++ .../recurring-orders.effects.ts | 18 +++++++++++-- .../recurring-order-list.component.html | 18 ++++--------- .../recurring-order-list.component.ts | 7 +++++ .../common/switch/switch.component.html | 12 +++++++++ .../common/switch/switch.component.scss | 15 +++++++++++ .../common/switch/switch.component.spec.ts | 27 +++++++++++++++++++ .../common/switch/switch.component.ts | 22 +++++++++++++++ src/app/shared/shared.module.ts | 2 ++ 11 files changed, 138 insertions(+), 16 deletions(-) create mode 100644 src/app/shared/components/common/switch/switch.component.html create mode 100644 src/app/shared/components/common/switch/switch.component.scss create mode 100644 src/app/shared/components/common/switch/switch.component.spec.ts create mode 100644 src/app/shared/components/common/switch/switch.component.ts diff --git a/src/app/core/facades/account.facade.ts b/src/app/core/facades/account.facade.ts index f9c19c164f..6b2ed274d7 100644 --- a/src/app/core/facades/account.facade.ts +++ b/src/app/core/facades/account.facade.ts @@ -212,6 +212,10 @@ export class AccountFacade { recurringOrdersError$ = this.store.pipe(select(getRecurringOrdersError)); selectedRecurringOrder$ = this.store.pipe(select(getSelectedRecurringOrder)); + switchActiveStatusRecurringOrder(recurringOrderId: string, active: boolean) { + this.store.dispatch(recurringOrdersActions.updateRecurringOrder({ recurringOrderId, active })); + } + // PAYMENT private eligiblePaymentMethods$ = this.store.pipe(select(getUserPaymentMethods)); diff --git a/src/app/core/services/recurring-orders/recurring-orders.service.ts b/src/app/core/services/recurring-orders/recurring-orders.service.ts index 17dce41e58..5961cbb94b 100644 --- a/src/app/core/services/recurring-orders/recurring-orders.service.ts +++ b/src/app/core/services/recurring-orders/recurring-orders.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { Store, select } from '@ngrx/store'; -import { iif, map, switchMap, take } from 'rxjs'; +import { iif, map, switchMap, take, throwError } from 'rxjs'; import { RecurringOrderData, RecurringOrderLinkData } from 'ish-core/models/recurring-order/recurring-order.interface'; import { RecurringOrderMapper } from 'ish-core/models/recurring-order/recurring-order.mapper'; @@ -48,4 +48,28 @@ export class RecurringOrdersService { ) ); } + + updateRecurringOrder(recurringOrderId: string, active: boolean) { + if (!recurringOrderId) { + return throwError(() => new Error('updateRecurringOrder() called without recurringOrderId')); + } + return this.currentCustomer$.pipe( + switchMap(customer => + iif( + () => customer.isBusinessCustomer, + this.apiService + .b2bUserEndpoint() + .put(`recurringorders/${this.apiService.encodeResourceId(recurringOrderId)}`, { + active, + }), + this.apiService.put( + `privatecustomers/${this.apiService.encodeResourceId( + customer.customerNo + )}/recurringorders/${this.apiService.encodeResourceId(recurringOrderId)}`, + { active } + ) + ).pipe(map(data => RecurringOrderMapper.fromData(data))) + ) + ); + } } diff --git a/src/app/core/store/customer/recurring-orders/recurring-orders.actions.ts b/src/app/core/store/customer/recurring-orders/recurring-orders.actions.ts index b85a7dccdc..dab0f7af93 100644 --- a/src/app/core/store/customer/recurring-orders/recurring-orders.actions.ts +++ b/src/app/core/store/customer/recurring-orders/recurring-orders.actions.ts @@ -8,6 +8,7 @@ export const recurringOrdersActions = createActionGroup({ events: { 'Load Recurring Orders': emptyProps(), 'Load Recurring Order': payload<{ recurringOrderId: string }>(), + 'Update Recurring Order': payload<{ recurringOrderId: string; active: boolean }>(), }, }); @@ -18,5 +19,7 @@ export const recurringOrdersApiActions = createActionGroup({ 'Load Recurring Orders Fail': httpError<{}>(), 'Load Recurring Order Success': payload<{ recurringOrder: RecurringOrder }>(), 'Load Recurring Order Fail': httpError<{}>(), + 'Update Recurring Order Success': payload<{ recurringOrder: RecurringOrder }>(), + 'Update Recurring Order Fail': httpError<{}>(), }, }); diff --git a/src/app/core/store/customer/recurring-orders/recurring-orders.effects.ts b/src/app/core/store/customer/recurring-orders/recurring-orders.effects.ts index 1b4af7e4a4..cb5dd7744a 100644 --- a/src/app/core/store/customer/recurring-orders/recurring-orders.effects.ts +++ b/src/app/core/store/customer/recurring-orders/recurring-orders.effects.ts @@ -1,11 +1,11 @@ import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { Store, select } from '@ngrx/store'; -import { map, switchMap } from 'rxjs/operators'; +import { map, mergeMap, switchMap } from 'rxjs/operators'; import { RecurringOrdersService } from 'ish-core/services/recurring-orders/recurring-orders.service'; import { selectRouteParam } from 'ish-core/store/core/router'; -import { mapErrorToAction, mapToPayloadProperty, whenTruthy } from 'ish-core/utils/operators'; +import { mapErrorToAction, mapToPayload, mapToPayloadProperty, whenTruthy } from 'ish-core/utils/operators'; import { recurringOrdersActions, recurringOrdersApiActions } from './recurring-orders.actions'; @@ -49,4 +49,18 @@ export class RecurringOrdersEffects { map(recurringOrderId => recurringOrdersActions.loadRecurringOrder({ recurringOrderId })) ) ); + + updateProductNotification$ = createEffect(() => + this.actions$.pipe( + ofType(recurringOrdersActions.updateRecurringOrder), + mapToPayload(), + whenTruthy(), + mergeMap(payload => + this.recurringOrdersService.updateRecurringOrder(payload.recurringOrderId, payload.active).pipe( + mergeMap(recurringOrder => [recurringOrdersApiActions.updateRecurringOrderSuccess({ recurringOrder })]), + mapErrorToAction(recurringOrdersApiActions.updateRecurringOrderFail) + ) + ) + ) + ); } diff --git a/src/app/pages/account-recurring-orders/recurring-order-list/recurring-order-list.component.html b/src/app/pages/account-recurring-orders/recurring-order-list/recurring-order-list.component.html index 9f65e02046..671d7021fb 100644 --- a/src/app/pages/account-recurring-orders/recurring-order-list/recurring-order-list.component.html +++ b/src/app/pages/account-recurring-orders/recurring-order-list/recurring-order-list.component.html @@ -98,19 +98,11 @@ - - - - - - + diff --git a/src/app/pages/account-recurring-orders/recurring-order-list/recurring-order-list.component.ts b/src/app/pages/account-recurring-orders/recurring-order-list/recurring-order-list.component.ts index 203d0e1450..08e474ee9d 100644 --- a/src/app/pages/account-recurring-orders/recurring-order-list/recurring-order-list.component.ts +++ b/src/app/pages/account-recurring-orders/recurring-order-list/recurring-order-list.component.ts @@ -1,5 +1,6 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { AccountFacade } from 'ish-core/facades/account.facade'; import { RecurringOrder } from 'ish-core/models/recurring-order/recurring-order.model'; export type RecurringOrderColumnsType = @@ -19,4 +20,10 @@ export type RecurringOrderColumnsType = export class RecurringOrderListComponent { @Input() recurringOrders: RecurringOrder[]; @Input() columnsToDisplay: RecurringOrderColumnsType[]; + + constructor(private accountFacade: AccountFacade) {} + + switchActiveStatus(recurringOrder: { id: string; active: boolean }) { + this.accountFacade.switchActiveStatusRecurringOrder(recurringOrder.id, recurringOrder.active); + } } diff --git a/src/app/shared/components/common/switch/switch.component.html b/src/app/shared/components/common/switch/switch.component.html new file mode 100644 index 0000000000..ab4659f6c2 --- /dev/null +++ b/src/app/shared/components/common/switch/switch.component.html @@ -0,0 +1,12 @@ + + + + diff --git a/src/app/shared/components/common/switch/switch.component.scss b/src/app/shared/components/common/switch/switch.component.scss new file mode 100644 index 0000000000..bcb1fa93f9 --- /dev/null +++ b/src/app/shared/components/common/switch/switch.component.scss @@ -0,0 +1,15 @@ +@import 'variables'; + +.custom-control-input ~ .custom-control-label::before { + background-color: #999; + border-color: #999; +} + +.custom-control-input:checked ~ .custom-control-label::before { + background-color: $color-corporate; + border-color: $color-corporate; +} + +.custom-switch .custom-control-label::after { + background-color: #fff; +} diff --git a/src/app/shared/components/common/switch/switch.component.spec.ts b/src/app/shared/components/common/switch/switch.component.spec.ts new file mode 100644 index 0000000000..7e0b085014 --- /dev/null +++ b/src/app/shared/components/common/switch/switch.component.spec.ts @@ -0,0 +1,27 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SwitchComponent } from './switch.component'; + +describe('Switch Component', () => { + let component: SwitchComponent; + let fixture: ComponentFixture; + let element: HTMLElement; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SwitchComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SwitchComponent); + component = fixture.componentInstance; + element = fixture.nativeElement; + }); + + it('should be created', () => { + expect(component).toBeTruthy(); + expect(element).toBeTruthy(); + expect(() => fixture.detectChanges()).not.toThrow(); + }); +}); diff --git a/src/app/shared/components/common/switch/switch.component.ts b/src/app/shared/components/common/switch/switch.component.ts new file mode 100644 index 0000000000..44f3153ca8 --- /dev/null +++ b/src/app/shared/components/common/switch/switch.component.ts @@ -0,0 +1,22 @@ +import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; +import { FormControl } from '@angular/forms'; + +@Component({ + selector: 'ish-switch', + templateUrl: './switch.component.html', + styleUrls: ['./switch.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class SwitchComponent { + @Input({ required: true }) id: string; + @Input() active = false; + @Input() label = ''; + + @Output() switchActiveStatus = new EventEmitter<{ id: string; active: boolean }>(); + + activeSwitch: FormControl = new FormControl(); + + switchActive(id: string, active: boolean) { + this.switchActiveStatus.emit({ id, active }); + } +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 163b4e012b..16cffff23f 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -99,6 +99,7 @@ import { ModalDialogLinkComponent } from './components/common/modal-dialog-link/ import { ModalDialogComponent } from './components/common/modal-dialog/modal-dialog.component'; import { PagingComponent } from './components/common/paging/paging.component'; import { SuccessMessageComponent } from './components/common/success-message/success-message.component'; +import { SwitchComponent } from './components/common/switch/switch.component'; import { FilterCheckboxComponent } from './components/filter/filter-checkbox/filter-checkbox.component'; import { FilterCollapsibleComponent } from './components/filter/filter-collapsible/filter-collapsible.component'; import { FilterDropdownComponent } from './components/filter/filter-dropdown/filter-dropdown.component'; @@ -321,6 +322,7 @@ const exportedComponents = [ PromotionRemoveComponent, SearchBoxComponent, SuccessMessageComponent, + SwitchComponent, ]; @NgModule({