Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Remove quote requests from cart #1029

Merged
1 change: 1 addition & 0 deletions src/app/core/models/line-item/line-item.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ export interface LineItemData {
hiddenGift: boolean;
freeGift: boolean;
quantityFixed?: boolean;
quote?: string;
}
1 change: 1 addition & 0 deletions src/app/core/models/line-item/line-item.mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export class LineItemMapper {

productSKU: data.product,
editable: !data.quantityFixed,
quote: data.quote ? data.quote : undefined,
};
} else {
throw new Error(`'LineItemData' is required for the mapping`);
Expand Down
1 change: 1 addition & 0 deletions src/app/core/models/line-item/line-item.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface LineItem {
isFreeGift: boolean;

editable: boolean;
quote?: string;
}

export interface LineItemView extends LineItem {
Expand Down
15 changes: 13 additions & 2 deletions src/app/extensions/quoting/exports/quoting-exports.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { LAZY_FEATURE_MODULE } from 'ish-core/utils/module-loader/module-loader.
import { LazyBasketAddToQuoteComponent } from './lazy-basket-add-to-quote/lazy-basket-add-to-quote.component';
import { LazyProductAddToQuoteComponent } from './lazy-product-add-to-quote/lazy-product-add-to-quote.component';
import { LazyQuoteWidgetComponent } from './lazy-quote-widget/lazy-quote-widget.component';
import { LazyQuotingBasketLineItemsComponent } from './lazy-quoting-basket-line-items/lazy-quoting-basket-line-items.component';

@NgModule({
imports: [FeatureToggleModule],
Expand All @@ -19,7 +20,17 @@ import { LazyQuoteWidgetComponent } from './lazy-quote-widget/lazy-quote-widget.
multi: true,
},
],
declarations: [LazyBasketAddToQuoteComponent, LazyProductAddToQuoteComponent, LazyQuoteWidgetComponent],
exports: [LazyBasketAddToQuoteComponent, LazyProductAddToQuoteComponent, LazyQuoteWidgetComponent],
declarations: [
LazyBasketAddToQuoteComponent,
LazyProductAddToQuoteComponent,
LazyQuoteWidgetComponent,
LazyQuotingBasketLineItemsComponent,
],
exports: [
LazyBasketAddToQuoteComponent,
LazyProductAddToQuoteComponent,
LazyQuoteWidgetComponent,
LazyQuotingBasketLineItemsComponent,
],
})
export class QuotingExportsModule {}
22 changes: 19 additions & 3 deletions src/app/extensions/quoting/facades/quoting.facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { map, mapTo, sample, switchMap, switchMapTo, tap } from 'rxjs/operators'
import { whenFalsy } from 'ish-core/utils/operators';

import { QuotingHelper } from '../models/quoting/quoting.helper';
import { QuotingEntity } from '../models/quoting/quoting.model';
import { Quote, QuoteRequest, QuotingEntity } from '../models/quoting/quoting.model';
import {
createQuoteRequestFromBasket,
deleteQuoteFromBasket,
deleteQuotingEntity,
getQuotingEntities,
getQuotingEntity,
Expand All @@ -26,7 +27,7 @@ export class QuotingFacade {

quotingEntities$() {
// update on subscription
this.store.dispatch(loadQuoting());
this.loadQuoting();

return this.store.pipe(
select(getQuotingEntities),
Expand All @@ -36,7 +37,7 @@ export class QuotingFacade {
timer(0, 60_000).pipe(
tap(count => {
if (count) {
this.store.dispatch(loadQuoting());
this.loadQuoting();
}
}),
mapTo(entities)
Expand All @@ -58,11 +59,26 @@ export class QuotingFacade {
);
}
dhhyi marked this conversation as resolved.
Show resolved Hide resolved

name$(quoteId: string) {
return this.store.pipe(
select(getQuotingEntity(quoteId)),
map((quote: Quote | QuoteRequest) => quote?.displayName)
);
}

delete(entity: QuotingEntity) {
this.store.dispatch(deleteQuotingEntity({ entity }));
}

createQuoteRequestFromBasket() {
this.store.dispatch(createQuoteRequestFromBasket());
}

loadQuoting() {
this.store.dispatch(loadQuoting());
}

deleteQuoteFromBasket(quoteId: string) {
this.store.dispatch(deleteQuoteFromBasket({ id: quoteId }));
}
}
3 changes: 3 additions & 0 deletions src/app/extensions/quoting/quoting.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { QuoteLineItemListComponent } from './shared/quote-line-item-list/quote-
import { QuoteStateComponent } from './shared/quote-state/quote-state.component';
import { QuoteViewComponent } from './shared/quote-view/quote-view.component';
import { QuoteWidgetComponent } from './shared/quote-widget/quote-widget.component';
import { QuotingBasketLineItemsComponent } from './shared/quoting-basket-line-items/quoting-basket-line-items.component';

@NgModule({
imports: [SharedModule],
Expand All @@ -28,6 +29,7 @@ import { QuoteWidgetComponent } from './shared/quote-widget/quote-widget.compone
QuoteStateComponent,
QuoteViewComponent,
QuoteWidgetComponent,
QuotingBasketLineItemsComponent,
],
exports: [
ProductAddToQuoteComponent,
Expand All @@ -37,6 +39,7 @@ import { QuoteWidgetComponent } from './shared/quote-widget/quote-widget.compone
QuoteStateComponent,
QuoteViewComponent,
QuoteWidgetComponent,
QuotingBasketLineItemsComponent,
SharedModule,
],
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<ng-container *ngFor="let item of lineItems$ | async">
<div class="row" *ngIf="item[0] !== 'undefined'">
<div class="col-12 col-sm-10 my-auto">
<h2>{{ 'quote.basket_items.label' | translate: { quoteId: getName(item[0]) | async } }}</h2>
</div>
<div class="col-12 col-sm-2 my-auto text-right">
<a
class="btn-tool"
title="{{ 'shopping_cart.remove.item.button.label' | translate }}"
(click)="onDeleteQuote(item[0])"
>
<fa-icon [icon]="['fas', 'trash-alt']"></fa-icon>
</a>
</div>
</div>
<ish-line-item-list [lineItems]="item[1]"></ish-line-item-list>
</ng-container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { EMPTY } from 'rxjs';
import { instance, mock, when } from 'ts-mockito';

import { CheckoutFacade } from 'ish-core/facades/checkout.facade';

import { QuotingFacade } from '../../facades/quoting.facade';

import { QuotingBasketLineItemsComponent } from './quoting-basket-line-items.component';

describe('QuotingBasketLineItemsComponent', () => {
let component: QuotingBasketLineItemsComponent;
let fixture: ComponentFixture<QuotingBasketLineItemsComponent>;
let element: HTMLElement;

let checkoutFacade: CheckoutFacade;
let quotingFacade: QuotingFacade;

beforeEach(async () => {
checkoutFacade = mock(CheckoutFacade);
quotingFacade = mock(QuotingFacade);
when(checkoutFacade.basket$).thenReturn(EMPTY);
await TestBed.configureTestingModule({
declarations: [QuotingBasketLineItemsComponent],
providers: [
{ provide: CheckoutFacade, useFactory: () => instance(checkoutFacade) },
{ provide: QuotingFacade, useFactory: () => instance(quotingFacade) },
],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(QuotingBasketLineItemsComponent);
component = fixture.componentInstance;
element = fixture.nativeElement;
});

it('should be created', () => {
expect(component).toBeTruthy();
expect(element).toBeTruthy();
expect(() => fixture.detectChanges()).not.toThrow();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { groupBy } from 'lodash-es';
import { Observable, map } from 'rxjs';

import { CheckoutFacade } from 'ish-core/facades/checkout.facade';
import { LineItem } from 'ish-core/models/line-item/line-item.model';
import { GenerateLazyComponent } from 'ish-core/utils/module-loader/generate-lazy-component.decorator';

import { QuotingFacade } from '../../facades/quoting.facade';

@Component({
selector: 'ish-quoting-basket-line-items',
templateUrl: './quoting-basket-line-items.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
@GenerateLazyComponent()
export class QuotingBasketLineItemsComponent implements OnInit {
lineItems$: Observable<[string, LineItem[]][]>;

constructor(private checkoutFacade: CheckoutFacade, private quotingFacade: QuotingFacade) {}

ngOnInit() {
this.quotingFacade.loadQuoting();
this.lineItems$ = this.checkoutFacade.basket$.pipe(
map(basket => Object.entries(groupBy(basket.lineItems, 'quote')).sort((a, _) => (a[0] === 'undefined' ? -1 : 0)))
);
}

getName(quoteId: string) {
return this.quotingFacade.name$(quoteId);
}

onDeleteQuote(quoteId: string) {
this.quotingFacade.deleteQuoteFromBasket(quoteId);
}
}
2 changes: 2 additions & 0 deletions src/app/extensions/quoting/store/quoting/quoting.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export const deleteQuotingEntitySuccess = createAction(
payload<IdPayloadType>()
);

export const deleteQuoteFromBasket = createAction('[Quoting] Delete Quote From Basket', payload<IdPayloadType>());

export const rejectQuote = createAction('[Quoting] Reject Quote', payload<IdPayloadType>());

export const rejectQuoteFail = createAction('[Quoting API] Reject Quote Fail', httpError<IdPayloadType>());
Expand Down
24 changes: 21 additions & 3 deletions src/app/extensions/quoting/store/quoting/quoting.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ import { BasketService } from 'ish-core/services/basket/basket.service';
import { displaySuccessMessage } from 'ish-core/store/core/messages';
import { selectRouteParam, selectUrl } from 'ish-core/store/core/router';
import { setBreadcrumbData } from 'ish-core/store/core/viewconf';
import { getCurrentBasketId, updateBasket } from 'ish-core/store/customer/basket';
import { mapErrorToAction, mapToPayload, mapToPayloadProperty, mapToProperty } from 'ish-core/utils/operators';
import { deleteBasketItem, getCurrentBasket, getCurrentBasketId, updateBasket } from 'ish-core/store/customer/basket';
import {
mapErrorToAction,
mapToPayload,
mapToPayloadProperty,
mapToProperty,
whenTruthy,
} from 'ish-core/utils/operators';

import { QuotingHelper } from '../../models/quoting/quoting.helper';
import { QuotingService } from '../../services/quoting/quoting.service';
Expand Down Expand Up @@ -40,6 +46,7 @@ import {
submitQuoteRequestSuccess,
updateQuoteRequest,
updateQuoteRequestSuccess,
deleteQuoteFromBasket,
} from './quoting.actions';
import { getQuotingEntity } from './quoting.selectors';

Expand All @@ -56,7 +63,7 @@ export class QuotingEffects {
loadQuoting$ = createEffect(() =>
this.actions$.pipe(
ofType(loadQuoting),
switchMap(() =>
mergeMap(() =>
this.quotingService.getQuotes().pipe(
map(quoting => loadQuotingSuccess({ quoting })),
mapErrorToAction(loadQuotingFail)
Expand Down Expand Up @@ -111,6 +118,17 @@ export class QuotingEffects {
)
);

deleteQuoteFromBasket$ = createEffect(() =>
this.actions$.pipe(
ofType(deleteQuoteFromBasket),
mapToPayloadProperty('id'),
withLatestFrom(this.store.pipe(select(getCurrentBasket))),
map(([quoteId, basket]) => basket?.lineItems?.find(li => li.quote === quoteId)?.id),
whenTruthy(),
map(itemId => deleteBasketItem({ itemId }))
)
);

addQuoteToBasket$ = createEffect(() =>
this.actions$.pipe(
ofType(addQuoteToBasket),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,15 @@ <h1 class="d-flex flex-wrap align-items-baseline">
</div>

<ish-basket-cost-center-selection></ish-basket-cost-center-selection>

<div class="section">
<ish-line-item-list *ngIf="basket" [lineItems]="basket.lineItems"></ish-line-item-list>
<ng-container *ishFeature="'quoting'; else elseTemplate">
<ish-lazy-quoting-basket-line-items></ish-lazy-quoting-basket-line-items>
</ng-container>
<ng-template #elseTemplate>
<ish-line-item-list *ngIf="basket" [lineItems]="basket.lineItems"></ish-line-item-list>
</ng-template>

<div class="button-group">
<div class="button-group" *ngIf="!basketContainsQuote">
<ish-lazy-basket-add-to-quote></ish-lazy-basket-add-to-quote>
<ish-lazy-basket-create-order-template
*ngIf="basket"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';

import { BasketView } from 'ish-core/models/basket/basket.model';
import { HttpError } from 'ish-core/models/http-error/http-error.model';
Expand All @@ -25,14 +25,20 @@ import { HttpError } from 'ish-core/models/http-error/http-error.model';
templateUrl: './shopping-basket.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ShoppingBasketComponent {
export class ShoppingBasketComponent implements OnChanges {
@Input() basket: BasketView;
@Input() error: HttpError;

@Output() nextStep = new EventEmitter<void>();

submitted = false;

basketContainsQuote = false;

ngOnChanges() {
this.basketContainsQuote = this.basket.lineItems?.some(x => x.quote);
}

/**
* checkout button leads to checkout address page if basket is valid
*/
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,7 @@
"quickorder.page.title": "Quick Order & Order by File",
"quote.add_product_to_quote.button.add_to_quote.label": "Add to Quote Request",
"quote.already_in_basket.error": "The quote is already in the cart.",
"quote.basket_items.label": "Your Quote Items - {{quoteId}}",
"quote.delete.message": "Your quote has been deleted.",
"quote.edit.back_to_quotes.link": "Back to Quotes",
"quote.edit.button.add_quote_to_cart.label": "Add Quote to Cart",
Expand Down