diff --git a/src/Web/WebSPA/Client/src/modules/basket/basket.component.scss b/src/Web/WebSPA/Client/src/modules/basket/basket.component.scss index 10edb11ec..ca6733158 100644 --- a/src/Web/WebSPA/Client/src/modules/basket/basket.component.scss +++ b/src/Web/WebSPA/Client/src/modules/basket/basket.component.scss @@ -106,6 +106,10 @@ background-color: $color-brightest; } + &-coupon { + width: 7rem; + } + &-checkout-title { font-weight: $font-weight-semibold; text-align: center; diff --git a/src/Web/WebSPA/Client/src/modules/basket/basket.service.ts b/src/Web/WebSPA/Client/src/modules/basket/basket.service.ts index b14ff3e9b..0306f8f0d 100644 --- a/src/Web/WebSPA/Client/src/modules/basket/basket.service.ts +++ b/src/Web/WebSPA/Client/src/modules/basket/basket.service.ts @@ -13,6 +13,7 @@ import { StorageService } from '../shared/services/storage.service'; import { Observable, Observer, Subject } from 'rxjs'; import { map, catchError, tap } from 'rxjs/operators'; +import { ICoupon } from '../shared/models/coupon.model'; @Injectable() export class BasketService { @@ -95,6 +96,26 @@ export class BasketService { })); } + checkValidationCoupon(code: string): Observable { + let url = this.purchaseUrl + `/cp/api/v1/coupon/${code}`; + + return this.service + .get(url) + .pipe(map((response) => { + console.log(`Coupon: ${response.json()} (${response.ok})`); + var item = response.json[0]; + + if (response.ok) { + item.message = "Valid coupon"; + } + else { + item.message = "The coupon is not valid or has already been used"; + } + + return item; + })); + } + mapBasketInfoCheckout(order: IOrder): IBasketCheckout { let basketCheckout = {}; @@ -108,6 +129,8 @@ export class BasketService { basketCheckout.cardsecuritynumber = order.cardsecuritynumber; basketCheckout.cardtypeid = order.cardtypeid; basketCheckout.cardholdername = order.cardholdername; + basketCheckout.coupon = order.coupon; + basketCheckout.discount = order.discount; basketCheckout.total = 0; basketCheckout.expiration = order.expiration; diff --git a/src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.html b/src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.html index e0ea4f722..743e0a35f 100644 --- a/src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.html +++ b/src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.html @@ -34,6 +34,15 @@ +
+
Subtotal
+
${{order.subtotal | number:'.2-2'}}
+
+
+
{{order.coupon}}
+
- ${{order.discount | number:'.2-2'}}
+
+
Total
${{order.total | number:'.2-2'}}
diff --git a/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.html b/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.html index 18311597a..39c1be95a 100644 --- a/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.html +++ b/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.html @@ -84,9 +84,41 @@
+
+
Subtotal
+
${{order.total | number:'.2-2'}}
+
+ +
+
+
+
Have a discount code?
+
+ + +
+
{{couponValidationMessage}}
+
+
+
+
{{coupon?.code}}
+
+
-${{coupon?.discount | number:'.2-2'}}
+
+
+
+
Total
-
${{ order.total | number:'.2-2'}}
+
${{ (coupon?.discount ? ((order.total - coupon?.discount) < 0 ? 0 : (order.total - coupon?.discount)) : order.total) | number:'.2-2'}}
diff --git a/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.scss b/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.scss index 25bdc60af..91b73c6ed 100644 --- a/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.scss +++ b/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.scss @@ -33,6 +33,10 @@ width: auto; } + &-coupon { + width: 15rem; + } + &-buttons { margin-top: 5rem; } diff --git a/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.ts b/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.ts index ff84b7638..b93cb4bf1 100644 --- a/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.ts +++ b/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.ts @@ -7,6 +7,8 @@ import { BasketService } from '../../basket/basket.service'; import { IOrder } from '../../shared/models/order.model'; import { BasketWrapperService } from '../../shared/services/basket.wrapper.service'; +import { ICoupon } from '../../shared/models/coupon.model'; + import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { Router } from '@angular/router'; @@ -20,6 +22,9 @@ export class OrdersNewComponent implements OnInit { isOrderProcessing: boolean; errorReceived: boolean; order: IOrder; + coupon: ICoupon; + discountCode: string; + couponValidationMessage: string; constructor(private orderService: OrdersService, private basketService: BasketService, fb: FormBuilder, private router: Router) { // Obtain user profile information @@ -39,6 +44,23 @@ export class OrdersNewComponent implements OnInit { ngOnInit() { } + keyDownValidationCoupon(event: KeyboardEvent, discountCode: string) { + if (event.keyCode === 13) { + event.preventDefault(); + this.checkValidationCoupon(discountCode); + } + } + + checkValidationCoupon(discountCode: string) { + this.couponValidationMessage = null; + this.coupon = null; + this.orderService + .checkValidationCoupon(discountCode) + .subscribe( + coupon => this.coupon = coupon, + error => this.couponValidationMessage = 'The coupon is not valid or it\'s been redeemed already!'); + } + submitForm(value: any) { this.order.street = this.newOrderForm.controls['street'].value; this.order.city = this.newOrderForm.controls['city'].value; @@ -49,6 +71,14 @@ export class OrdersNewComponent implements OnInit { this.order.cardholdername = this.newOrderForm.controls['cardholdername'].value; this.order.cardexpiration = new Date(20 + this.newOrderForm.controls['expirationdate'].value.split('/')[1], this.newOrderForm.controls['expirationdate'].value.split('/')[0]); this.order.cardsecuritynumber = this.newOrderForm.controls['securitycode'].value; + + if (this.coupon) { + console.log(`Coupon: ${this.coupon.code} (${this.coupon.discount})`); + + this.order.coupon = this.coupon.code; + this.order.discount = this.coupon.discount; + } + let basketCheckout = this.basketService.mapBasketInfoCheckout(this.order); this.basketService.setBasketCheckout(basketCheckout) .pipe(catchError((errMessage) => { diff --git a/src/Web/WebSPA/Client/src/modules/orders/orders.service.ts b/src/Web/WebSPA/Client/src/modules/orders/orders.service.ts index e81d6da64..1b9508e62 100644 --- a/src/Web/WebSPA/Client/src/modules/orders/orders.service.ts +++ b/src/Web/WebSPA/Client/src/modules/orders/orders.service.ts @@ -10,6 +10,7 @@ import { BasketWrapperService } from '../shared/services/basket.wrapper.service' import { Observable } from 'rxjs'; import { tap, map } from 'rxjs/operators'; +import { ICoupon } from '../shared/models/coupon.model'; @Injectable() export class OrdersService { @@ -48,6 +49,14 @@ export class OrdersService { })); } + checkValidationCoupon(code: string): Observable { + let url = this.ordersUrl + `/cp/api/v1/coupon/${code}`; + + return this.service.get(url).pipe(tap((response: any) => { + return response; + })); + } + mapOrderAndIdentityInfoNewOrder(): IOrder { let order = {}; let basket = this.basketService.basket; diff --git a/src/Web/WebSPA/Client/src/modules/shared/models/basketCheckout.model.ts b/src/Web/WebSPA/Client/src/modules/shared/models/basketCheckout.model.ts index 2f7cfbf62..2ba0f0da1 100644 --- a/src/Web/WebSPA/Client/src/modules/shared/models/basketCheckout.model.ts +++ b/src/Web/WebSPA/Client/src/modules/shared/models/basketCheckout.model.ts @@ -12,5 +12,7 @@ cardtypeid: number; buyer: string; ordernumber: string; + coupon: string; total: number; + discount: number; } \ No newline at end of file diff --git a/src/Web/WebSPA/Client/src/modules/shared/models/coupon.model.ts b/src/Web/WebSPA/Client/src/modules/shared/models/coupon.model.ts new file mode 100644 index 000000000..2b12b6a47 --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/shared/models/coupon.model.ts @@ -0,0 +1,5 @@ +export interface ICoupon { + discount: number; + code: string; + message: string +} diff --git a/src/Web/WebSPA/Client/src/modules/shared/models/order-detail.model.ts b/src/Web/WebSPA/Client/src/modules/shared/models/order-detail.model.ts index 5631d8807..b5cec7e4d 100644 --- a/src/Web/WebSPA/Client/src/modules/shared/models/order-detail.model.ts +++ b/src/Web/WebSPA/Client/src/modules/shared/models/order-detail.model.ts @@ -10,6 +10,9 @@ export interface IOrderDetail { state: string; zipcode: string; country: number; + subtotal: number; + coupon: string; + discount: number; total: number; orderitems: IOrderItem[]; } diff --git a/src/Web/WebSPA/Client/src/modules/shared/models/order.model.ts b/src/Web/WebSPA/Client/src/modules/shared/models/order.model.ts index 9780f40ad..220f05bde 100644 --- a/src/Web/WebSPA/Client/src/modules/shared/models/order.model.ts +++ b/src/Web/WebSPA/Client/src/modules/shared/models/order.model.ts @@ -14,6 +14,9 @@ export interface IOrder { cardtypeid: number; buyer: string; ordernumber: string; + subtotal: number, + coupon: string; + discount: number; total: number; orderItems: IOrderItem[]; } diff --git a/src/Web/WebSPA/Client/src/modules/shared/services/security.service.ts b/src/Web/WebSPA/Client/src/modules/shared/services/security.service.ts index cf8a3fd17..2cb1ea010 100644 --- a/src/Web/WebSPA/Client/src/modules/shared/services/security.service.ts +++ b/src/Web/WebSPA/Client/src/modules/shared/services/security.service.ts @@ -82,7 +82,7 @@ export class SecurityService { let client_id = 'js'; let redirect_uri = location.origin + '/'; let response_type = 'id_token token'; - let scope = 'openid profile orders basket webshoppingagg orders.signalrhub'; + let scope = 'openid profile orders basket webshoppingagg orders.signalrhub coupon'; let nonce = 'N' + Math.random() + '' + Date.now(); let state = Date.now() + '' + Math.random();