Add coupon to web app
This commit is contained in:
parent
8d7f61538b
commit
44f0a41fed
@ -106,6 +106,10 @@
|
||||
background-color: $color-brightest;
|
||||
}
|
||||
|
||||
&-coupon {
|
||||
width: 7rem;
|
||||
}
|
||||
|
||||
&-checkout-title {
|
||||
font-weight: $font-weight-semibold;
|
||||
text-align: center;
|
||||
|
@ -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<ICoupon> {
|
||||
let url = this.purchaseUrl + `/cp/api/v1/coupon/${code}`;
|
||||
|
||||
return this.service
|
||||
.get(url)
|
||||
.pipe<ICoupon>(map<Response, ICoupon>((response) => {
|
||||
console.log(`Coupon: ${response.json()} (${response.ok})`);
|
||||
var item = <ICoupon>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 = <IBasketCheckout>{};
|
||||
|
||||
@ -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;
|
||||
|
||||
|
@ -34,6 +34,15 @@
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<div class="d-flex align-items-center justify-content-end mt-4 mb-4 text-uppercase">
|
||||
<div>Subtotal</div>
|
||||
<div class="ml-3">${{order.subtotal | number:'.2-2'}}</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center justify-content-end mt-4 mb-4 text-uppercase">
|
||||
<div>{{order.coupon}}</div>
|
||||
<div class="ml-3">- ${{order.discount | number:'.2-2'}}</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center justify-content-end mt-4 mb-4 text-uppercase u-text-xl">
|
||||
<div>Total</div>
|
||||
<div class="ml-3">${{order.total | number:'.2-2'}}</div>
|
||||
|
@ -84,9 +84,41 @@
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<div class="d-flex align-items-center justify-content-end mt-4 mb-4 text-uppercase">
|
||||
<div>Subtotal</div>
|
||||
<div class="ml-3">${{order.total | number:'.2-2'}}</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-nowrap justify-content-between align-items-center mb-3 mt-3">
|
||||
<div>
|
||||
<div *ngIf="!coupon">
|
||||
<div class="u-text-uppercase">Have a discount code?</div>
|
||||
<div class="d-flex flex-nowrap justify-content-between align-items-center mt-1">
|
||||
<input #discountcode
|
||||
class="esh-orders_new-coupon mr-2 form-control"
|
||||
type="text"
|
||||
placeholder="Coupon number"
|
||||
(keydown)="keyDownValidationCoupon($event, discountcode.value)">
|
||||
<button type="button"
|
||||
(click)="checkValidationCoupon(discountcode.value)"
|
||||
class="btn btn-secondary u-minwidth-unset">
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-1" *ngIf="couponValidationMessage">{{couponValidationMessage}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center justify-content-end text-uppercase">
|
||||
<div *ngIf="coupon?.code">{{coupon?.code}}</div>
|
||||
<div>
|
||||
<div class="text-right ml-3" *ngIf="coupon?.discount">-${{coupon?.discount | number:'.2-2'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider d-flex align-items-center justify-content-end mb-4 pt-4 text-uppercase u-text-xl">
|
||||
<div>Total</div>
|
||||
<div class="ml-3">${{ order.total | number:'.2-2'}}</div>
|
||||
<div class="ml-3">${{ (coupon?.discount ? ((order.total - coupon?.discount) < 0 ? 0 : (order.total - coupon?.discount)) : order.total) | number:'.2-2'}}</div>
|
||||
</div>
|
||||
|
||||
<div class="esh-orders_new-buttons d-flex justify-content-end align-items-center">
|
||||
|
@ -33,6 +33,10 @@
|
||||
width: auto;
|
||||
}
|
||||
|
||||
&-coupon {
|
||||
width: 15rem;
|
||||
}
|
||||
|
||||
&-buttons {
|
||||
margin-top: 5rem;
|
||||
}
|
||||
|
@ -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) => {
|
||||
|
@ -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<ICoupon> {
|
||||
let url = this.ordersUrl + `/cp/api/v1/coupon/${code}`;
|
||||
|
||||
return this.service.get(url).pipe<ICoupon>(tap((response: any) => {
|
||||
return response;
|
||||
}));
|
||||
}
|
||||
|
||||
mapOrderAndIdentityInfoNewOrder(): IOrder {
|
||||
let order = <IOrder>{};
|
||||
let basket = this.basketService.basket;
|
||||
|
@ -12,5 +12,7 @@
|
||||
cardtypeid: number;
|
||||
buyer: string;
|
||||
ordernumber: string;
|
||||
coupon: string;
|
||||
total: number;
|
||||
discount: number;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
export interface ICoupon {
|
||||
discount: number;
|
||||
code: string;
|
||||
message: string
|
||||
}
|
@ -10,6 +10,9 @@ export interface IOrderDetail {
|
||||
state: string;
|
||||
zipcode: string;
|
||||
country: number;
|
||||
subtotal: number;
|
||||
coupon: string;
|
||||
discount: number;
|
||||
total: number;
|
||||
orderitems: IOrderItem[];
|
||||
}
|
||||
|
@ -14,6 +14,9 @@ export interface IOrder {
|
||||
cardtypeid: number;
|
||||
buyer: string;
|
||||
ordernumber: string;
|
||||
subtotal: number,
|
||||
coupon: string;
|
||||
discount: number;
|
||||
total: number;
|
||||
orderItems: IOrderItem[];
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user