src/app/pages/checkout-page/checkout-page.component.ts
Checkout page component
selector | app-checkout-page |
styleUrls | checkout-page.component.scss |
templateUrl | ./checkout-page.component.html |
Properties |
|
Methods |
constructor(afs: FirebaseFirestoreService, auth: FirebaseAuthService, navigation: NavigationService)
|
||||||||||||||||
Constructor
Parameters :
|
loadPaypalScript |
loadPaypalScript()
|
Load paypal checkout script into DOM
Returns :
Promise<any>
|
ngOnInit |
ngOnInit()
|
Initalize component
Returns :
void
|
renderPaypalButton |
renderPaypalButton()
|
Render paypal button
Returns :
void
|
setTemplate | ||||||||
setTemplate(template: string)
|
||||||||
Set template
Parameters :
Returns :
void
|
Public cartItems |
cartItems:
|
Type : ShoppingCartItem[]
|
Cart items |
Public checkOrderStatus |
checkOrderStatus:
|
Type : string
|
checkOrderStatus |
checkoutCheckOrder |
checkoutCheckOrder:
|
Type : TemplateRef<any>
|
Decorators : ViewChild
|
checkoutCheckOrder |
checkoutContactDetails |
checkoutContactDetails:
|
Type : TemplateRef<any>
|
Decorators : ViewChild
|
checkoutContactDetails |
checkoutPaymentDelivery |
checkoutPaymentDelivery:
|
Type : TemplateRef<any>
|
Decorators : ViewChild
|
checkoutPaymentDelivery |
Public checkType |
checkType:
|
Type : any
|
Default value : SHOPPINGCARTITEMTYPE
|
checkType variable |
Public contactDetailsStatus |
contactDetailsStatus:
|
Type : string
|
contactDetailsStatus |
Public didPaypalScriptLoad |
didPaypalScriptLoad:
|
Default value : false
|
Display loading |
Public invoice_number |
invoice_number:
|
Type : string
|
Invoice number |
Public loading |
loading:
|
Default value : true
|
Loading |
loadingTmpl |
loadingTmpl:
|
Type : TemplateRef<any>
|
Decorators : ViewChild
|
loadingTmpl |
Private log |
log:
|
Default value : Log.create('CheckoutPageComponent')
|
Logger |
Public paymentDeliveryStatus |
paymentDeliveryStatus:
|
Type : string
|
paymentDeliveryStatus |
Public paypalConfig |
paypalConfig:
|
Type : any
|
paypal config |
Public paypalItems |
paypalItems:
|
Type : TransactionItem[]
|
Default value : []
|
Public shipping |
shipping:
|
Default value : 0
|
Public subTotal |
subTotal:
|
Default value : 0
|
Public template |
template:
|
Type : TemplateRef<any>
|
template |
Public transaction |
transaction:
|
Type : Transaction
|
Public user |
user:
|
Type : User
|
User |
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import * as localforage from 'localforage';
import { Log } from 'ng2-logger';
import { environment } from '../../../environments/environment';
import { User } from '../../classes/user';
import { COUNTRY } from '../../enums/country';
import { CURRENCY } from '../../enums/currency';
import { SHOPPINGCARTITEMTYPE } from '../../enums/shopping-cart-item-type';
import { ShoppingCartItem } from '../../interfaces/shopping-cart-item';
import { Transaction, TransactionItem } from '../../interfaces/transaction';
import { FirebaseAuthService } from '../../services/auth/firebase-auth/firebase-auth.service';
import { FirebaseFirestoreService } from '../../services/firebase/firestore/firebase-firestore.service';
import { FirebaseStorageService } from '../../services/firebase/storage/firebase-storage.service';
import { NavigationService } from '../../services/navigation/navigation.service';
declare let paypal: any;
/**
* Checkout page component
* @author Daniel Sogl, Anna Riesch
*/
@Component({
selector: 'app-checkout-page',
templateUrl: './checkout-page.component.html',
styleUrls: ['./checkout-page.component.scss']
})
export class CheckoutPageComponent implements OnInit {
/** Logger */
private log = Log.create('CheckoutPageComponent');
/** User */
public user: User;
/** Cart items */
public cartItems: ShoppingCartItem[];
public paypalItems: TransactionItem[] = [];
/** contactDetailsStatus */
public contactDetailsStatus: string;
/** paymentDeliveryStatus */
public paymentDeliveryStatus: string;
/** checkOrderStatus */
public checkOrderStatus: string;
/** Display loading */
public didPaypalScriptLoad = false;
/** Loading */
public loading = true;
/** paypal config */
public paypalConfig: any;
/** Invoice number */
public invoice_number: string;
/** checkType variable */
public checkType: any = SHOPPINGCARTITEMTYPE;
public transaction: Transaction;
public shipping = 0;
public subTotal = 0;
/** template */
public template: TemplateRef<any>;
/** loadingTmpl */
@ViewChild('loadingTmpl') loadingTmpl: TemplateRef<any>;
/** checkoutContactDetails */
@ViewChild('checkoutContactDetails') checkoutContactDetails: TemplateRef<any>;
/** checkoutPaymentDelivery */
@ViewChild('checkoutPaymentDelivery')
checkoutPaymentDelivery: TemplateRef<any>;
/** checkoutCheckOrder */
@ViewChild('checkoutCheckOrder') checkoutCheckOrder: TemplateRef<any>;
/**
* Constructor
* @param {FirebaseStorageService} afs Firebase Storage Service
* @param {FirebaseAuthService} auth Firebase Auth Service
* @param {NavigationService} navigation Navigation Service
*/
constructor(
private afs: FirebaseFirestoreService,
private auth: FirebaseAuthService,
private navigation: NavigationService
) {}
/**
* Initalize component
*/
ngOnInit() {
this.log.color = 'orange';
this.log.d('Component initialized');
this.setTemplate('contactDetails');
localforage
.getItem('cart-items')
.then((items: ShoppingCartItem[]) => {
this.cartItems = items;
this.auth.user.subscribe(user => {
if (user) {
this.user = user;
this.log.d('Loaded user', this.user);
this.invoice_number = this.afs.getId();
for (let i = 0; i < this.cartItems.length; i++) {
if (
this.cartItems[i].itemType === SHOPPINGCARTITEMTYPE.PRINT &&
this.shipping === 0
) {
this.shipping = 4.95;
}
this.paypalItems.push({
currency: CURRENCY.EUR,
description: JSON.stringify(this.cartItems[i].info),
name: `${this.cartItems[i].eventname}/${
this.cartItems[i].name
}`,
price: this.cartItems[i].price,
quantity: this.cartItems[i].amount,
sku: this.cartItems[i].itemType,
tax: 0.19
});
this.subTotal +=
this.cartItems[i].price * this.cartItems[i].amount;
}
this.transaction = {
invoice_number: this.invoice_number,
description: 'EventPicking Bestellung',
reference_id: this.auth.getCurrentFirebaseUser().uid,
amount: {
currency: CURRENCY.EUR,
total: this.subTotal + this.shipping,
details: {
tax: 0,
shipping: this.shipping,
subtotal: this.subTotal
}
},
item_list: {
items: this.paypalItems,
shipping_address: {
city: this.user.deliveryAdress.city,
country_code: COUNTRY.GERMANY,
line1: `${this.user.deliveryAdress.street} ${
this.user.deliveryAdress.streetnumber
}`,
phone: this.user.deliveryAdress.phone,
postal_code: this.user.deliveryAdress.zip,
recipient_name: `${this.user.deliveryAdress.name} ${
this.user.deliveryAdress.lastname
}`
},
shipping_method: 'DHL oder EMail',
shipping_phone_number: this.user.deliveryAdress.phone
}
};
this.log.d('Translaction', this.transaction);
this.paypalConfig = {
env: 'sandbox',
locale: 'de_DE',
client: {
sandbox: environment.paypal_sandbox
},
style: {
label: 'paypal',
size: 'responsive', // small | medium | large | responsive
shape: 'rect', // pill | rect
color: 'blue', // gold | blue | silver | black
tagline: false
},
commit: true,
payment: (data, actions) => {
return actions.payment.create({
payment: {
transactions: [this.transaction]
}
});
},
onAuthorize: (data, actions) => {
return actions.payment.execute().then(payment => {
// Save transaction into firestore
this.transaction.date = new Date().toDateString();
this.transaction.status = 'pending';
this.transaction.email = this.auth.getCurrentFirebaseUser().email;
this.transaction.photographer = this.cartItems[0].photographer;
this.afs
.saveTransaction(this.transaction)
.then(() => {
this.log.d('Saved transaction');
localforage.setItem('cart-items', []);
this.navigation.navigateTo('payment-success');
})
.catch(err => {
this.log.er('Error saving transaction', err);
});
});
},
onCancel: (data, actions) => {
// Buyer cancelled the payment
return;
},
onError: err => {
// An error occurred during the transaction
console.log('Error', err);
return;
}
};
}
});
})
.catch(err => {
this.log.er('Error loading local storage items');
});
}
/**
* Set template
* @param {string} template Template name
*/
setTemplate(template: string) {
switch (template) {
case 'contactDetails':
this.template = this.checkoutContactDetails;
break;
case 'paymentDelivery':
this.template = this.checkoutPaymentDelivery;
break;
case 'checkOrder':
this.template = this.checkoutCheckOrder;
break;
default:
this.template = this.loadingTmpl;
break;
}
}
/**
* Render paypal button
*/
renderPaypalButton() {
if (!this.didPaypalScriptLoad) {
this.loadPaypalScript().then(() => {
paypal.Button.render(this.paypalConfig, '#paypal-button');
this.loading = false;
});
}
}
/**
* Load paypal checkout script into DOM
* @returns {Promise<any>}
*/
loadPaypalScript(): Promise<any> {
this.didPaypalScriptLoad = true;
return new Promise((resolve, reject) => {
const scriptElement = document.createElement('script');
scriptElement.src = 'https://www.paypalobjects.com/api/checkout.js';
scriptElement.onload = resolve;
document.body.appendChild(scriptElement);
});
}
}
<div class="row mt-5 pt-5">
<div class="col-sm-12">
<ul class="stepper stepper-horizontal">
<li [class.active]="template === checkoutContactDetails">
<a>
<span class="circle">1</span>
<span class="label">{{ 'NAV.CONTACT_DETAILS' | translate }}</span>
</a>
</li>
<li [class.active]="template === checkoutPaymentDelivery">
<a>
<span class="circle">2</span>
<span class="label">{{ 'NAV.PAYMENT_DELIVERY' | translate }}</span>
</a>
</li>
<li [class.active]="template === checkoutCheckOrder">
<a>
<span class="circle">
3
</span>
<span class="label">{{ 'NAV.CHECK_ORDER' | translate }}</span>
</a>
</li>
</ul>
<div class="row m-5">
<ng-container *ngTemplateOutlet="template"></ng-container>
</div>
</div>
<!--checkout-templates-->
<ng-template #loadingTmpl>
<mdb-spinner spinnerType="big" spinnerColor="blue"></mdb-spinner>
</ng-template>
<ng-template #checkoutContactDetails>
<div class="container" *ngIf="user">
<h2>{{ 'LABELS.CONTACT_DETAILS' | translate }}</h2>
<p>{{ user.email }}</p>
<br>
<div class="row">
<div class="col-6">
<h2>{{ 'LABELS.DELIVERY_ADDRESS' | translate }}</h2>
<p>{{ user.name }} {{ user.lastname }}</p>
<p>{{ user.deliveryAdress.street }} {{ user.deliveryAdress.streetnumber }}</p>
<p>{{ user.deliveryAdress.zip }} {{ user.deliveryAdress.city }}</p>
</div>
<!--col1-->
<div class="col-6">
<h2>{{ 'LABELS.BILLING_ADDRESS' | translate }}</h2>
<p>{{ user.name }} {{ user.lastname }}</p>
<p>{{ user.billingAdress.street }} {{ user.billingAdress.streetnumber }}</p>
<p>{{ user.billingAdress.zip }} {{ user.billingAdress.city }}</p>
</div>
<!--col1-->
</div>
<!--row-->
<div class="row justify-content-end">
<p>
<button id="checkout3_send_order" type="button" class="btn pink waves-effect" (click)="setTemplate('paymentDelivery')" mdbRippleRadius>{{ 'BUTTONS.NEXT' | translate }}</button>
</p>
</div>
</div>
<!--container-->
</ng-template>
<ng-template #checkoutPaymentDelivery>
<div class="container">
<h2>{{ 'LABELS.PAYMENT_SHIPPING_DETAILS' | translate }}</h2>
<br>
<div class="row justify-content-left">
<div class="col-12">
<h3>{{ 'LABELS.PAYMENT_METHOD' | translate }}</h3>
<!-- PayPal Logo -->
<a href="https://www.paypal.com/de/webapps/mpp/paypal-popup" title="So funktioniert PayPal">
<img src="https://www.paypalobjects.com/webstatic/de_DE/i/de-pp-logo-150px.png" border="0" alt="PayPal Logo" />
</a>
<!-- PayPal Logo -->
</div>
<!--col1-->
</div>
<!--row-->
<div class="row justify-content-left">
<div class="col-8">
<p class="padded">Nach dem Abschicken des Auftrags werden Sie auf die offizielle PayPal-Seite geleitet, um dort komfortabel und sicher
zu bezahlen.
</p>
</div>
<!--col1-->
</div>
<!--row-->
<div class="row justify-content-left">
<div class="col-12">
<h3>{{ 'LABELS.DELIVERY_COSTS' | translate }}</h3>
</div>
<!--col1-->
</div>
<!--row-->
<div class="row">
<div class="col-9">
<p>Druckerei: Lieferung in 7-10 Tagen</p>
<p>Download: Lieferung in 5-15 Minuten</p>
</div>
<!--col1-->
<div class="col-3">
<p class="price">4,95€</p>
<p class="price">Kostenlos</p>
</div>
<!--col2-->
</div>
<!--row-->
<!-- Buttons to previous or next step -->
<div class="row justify-content-end">
<button id="checkout3_back" type="button" class="btn pink waves-effect" (click)="setTemplate('contactDetails')" mdbRippleRadius>{{ 'BUTTONS.BACK' | translate }}</button>
<button id="checkout3_send_order" type="button" class="btn pink waves-effect" (click)="setTemplate('checkOrder'); renderPaypalButton()"
mdbRippleRadius>{{ 'BUTTONS.NEXT' | translate }}</button>
<!-- END buttons -->
</div>
<!--row-->
</div>
<!--container-->
</ng-template>
<ng-template #checkoutCheckOrder>
<div class="container">
<h2>{{ 'LABELS.ORDER_DETAILS' | translate }}</h2>
<br>
<div class="row">
<div class="col-12">
<table class="table table-striped table-responsive-sm">
<thead id="sum_row" class="indigo">
<tr>
<th scope="col">{{ 'NAV.CART_QUANTITY' | translate }}</th>
<th scope="col">{{ 'NAV.CART_ITEM' | translate }}</th>
<th scope="col">{{ 'NAV.CART_TYPE' | translate }}</th>
<th scope="col">{{ 'NAV.CART_SIZE' | translate }}</th>
<th scope="col">{{ 'NAV.CART_PRICE' | translate }}</th>
</tr>
</thead>
<tbody>
<tr class="table-bordered" *ngFor="let item of cartItems; let i = index">
<td>{{ item?.amount }}</td>
<td>{{ item?.name }}</td>
<td>
<i *ngIf="item.itemType === checkType.PRINT" class="fa fa-print fa-lg" aria-hidden="true"></i>
<i *ngIf="item.itemType === checkType.DOWNLOAD" class="fa fa-download fa-lg" aria-hidden="true"></i>
</td>
<td>{{ item?.format }}</td>
<td>{{ item?.price | number:'0.2' }}€</td>
</tr>
<tr class="table background-white">
<td>Zwischensumme</td>
<td></td>
<td></td>
<td></td>
<td>{{ subTotal | number:'0.2-2' }}€</td>
</tr>
<tr class="table background-white">
<td>+ Versandkosten</td>
<td></td>
<td></td>
<td></td>
<td>{{ shipping | number:'0.2-2' }}€</td>
</tr>
<tr class="table background-white">
<td>{{'LABELS.TOTAL'|translate}}</td>
<td></td>
<td></td>
<td></td>
<td>{{ subTotal + shipping | number:'0.2-2' }}€</td>
</tr>
</tbody>
</table>
</div>
<!--col1-->
</div>
<!--row-->
<div class="row">
<div class="col-12">
<br> Indem Sie Ihre Bestellung aufgeben, akzeptieren Sie unsere
<a class="pink-text" target="_blank" href="./gtc">Allgemeinen Geschäftsbedingungen</a> und unsere
<a class="pink-text" target="_blank" href="./data-protection">Datenschutzrichtlinie</a>.
<br>
</div>
<!--col-->
</div>
<!--row-->
<!-- Buttons to previous or next step -->
<div class="row justify-content-end">
<button id="checkout3_back" type="button" class="btn pink waves-effect" (click)="setTemplate('paymentDelivery')" mdbRippleRadius>{{ 'BUTTONS.BACK' | translate }}</button>
<div id="paypal-button"></div>
<!-- END buttons -->
</div>
<!--row-->
</div>
<!--container-->
</ng-template>
<!--END checkout-templates-->
</div>