Implement receipt QR code
This commit is contained in:
parent
934e28446c
commit
8e98bff2ae
13 changed files with 172 additions and 14 deletions
|
@ -540,7 +540,7 @@ app.get('/api/receipt', (req, res, next) => {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
res.status(204).json({
|
res.status(204).json({
|
||||||
message: 'no session received',
|
message: 'no valid ID received',
|
||||||
order: null
|
order: null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import { BusinessComponent } from './business/business.component';
|
||||||
import { SearchOptionsPipe } from './searchoptions.pipe';
|
import { SearchOptionsPipe } from './searchoptions.pipe';
|
||||||
import { TermsComponent } from './terms/terms.component';
|
import { TermsComponent } from './terms/terms.component';
|
||||||
import { ReceiptComponent } from './receipt/receipt.component';
|
import { ReceiptComponent } from './receipt/receipt.component';
|
||||||
|
import { ReceiptQRComponent } from './receipt-qr/receipt-qr.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -57,7 +58,8 @@ import { ReceiptComponent } from './receipt/receipt.component';
|
||||||
BusinessComponent,
|
BusinessComponent,
|
||||||
SearchOptionsPipe,
|
SearchOptionsPipe,
|
||||||
TermsComponent,
|
TermsComponent,
|
||||||
ReceiptComponent
|
ReceiptComponent,
|
||||||
|
ReceiptQRComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { UserService } from '../user.service';
|
||||||
import { OrderService } from './order.service';
|
import { OrderService } from './order.service';
|
||||||
import { CancelComponent } from '../cancel/cancel.component';
|
import { CancelComponent } from '../cancel/cancel.component';
|
||||||
import { CheckoutComponent} from '../checkout/checkout.component';
|
import { CheckoutComponent} from '../checkout/checkout.component';
|
||||||
|
import { ReceiptQRComponent} from '../receipt-qr/receipt-qr.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-order',
|
selector: 'app-order',
|
||||||
|
@ -97,8 +98,20 @@ export class OrderComponent implements OnInit{
|
||||||
const dialogRef = this.dialog.open(CheckoutComponent, dialogConfig);
|
const dialogRef = this.dialog.open(CheckoutComponent, dialogConfig);
|
||||||
dialogRef.afterClosed().subscribe((val) => {
|
dialogRef.afterClosed().subscribe((val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
|
const dialogConfig2 = new MatDialogConfig();
|
||||||
|
dialogConfig2.disableClose = true;
|
||||||
|
dialogConfig2.autoFocus = true;
|
||||||
|
dialogConfig2.data = {
|
||||||
|
order: this.order._id
|
||||||
|
};
|
||||||
console.log('Payment confirmed!');
|
console.log('Payment confirmed!');
|
||||||
this.orderService.closeOrder();
|
this.orderService.closeOrder();
|
||||||
|
const dialogRef2 = this.dialog.open(ReceiptQRComponent, dialogConfig2);
|
||||||
|
dialogRef2.afterClosed().subscribe( val => {
|
||||||
|
if (val) {
|
||||||
|
console.log('Receipt closed.');
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log('Returning to order');
|
console.log('Returning to order');
|
||||||
}
|
}
|
||||||
|
|
4
src/app/receipt-qr/receipt-qr.component.css
Normal file
4
src/app/receipt-qr/receipt-qr.component.css
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-family: 'Spartan', sans-serif;
|
||||||
|
}
|
13
src/app/receipt-qr/receipt-qr.component.html
Normal file
13
src/app/receipt-qr/receipt-qr.component.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<div align="center" mat-dialog-title>
|
||||||
|
<h4 class="text">Scan for your Receipt</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<mat-dialog-content>
|
||||||
|
<div class="qrcode" id="receipt-qr"> </div>
|
||||||
|
</mat-dialog-content>
|
||||||
|
|
||||||
|
<mat-dialog-actions>
|
||||||
|
<button mat-raised-button class="text" (click)="close()">
|
||||||
|
<mat-icon class="icon">close</mat-icon>Close
|
||||||
|
</button>
|
||||||
|
</mat-dialog-actions>
|
25
src/app/receipt-qr/receipt-qr.component.spec.ts
Normal file
25
src/app/receipt-qr/receipt-qr.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ReceiptQRComponent } from './receipt-qr.component';
|
||||||
|
|
||||||
|
describe('ReceiptQRComponent', () => {
|
||||||
|
let component: ReceiptQRComponent;
|
||||||
|
let fixture: ComponentFixture<ReceiptQRComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ ReceiptQRComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ReceiptQRComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
38
src/app/receipt-qr/receipt-qr.component.ts
Normal file
38
src/app/receipt-qr/receipt-qr.component.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { Inject, Component, OnInit, ViewEncapsulation} from '@angular/core';
|
||||||
|
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog';
|
||||||
|
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
var QRCode = require('easyqrcodejs');
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-receipt-qr',
|
||||||
|
templateUrl: './receipt-qr.component.html',
|
||||||
|
styleUrls: ['./receipt-qr.component.css']
|
||||||
|
})
|
||||||
|
export class ReceiptQRComponent implements OnInit {
|
||||||
|
receiptUrl: SafeUrl;
|
||||||
|
codeString: string = '';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private dialogRef: MatDialogRef<ReceiptQRComponent>,
|
||||||
|
private sanitizer: DomSanitizer,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: { order: string}
|
||||||
|
) {
|
||||||
|
this.codeString = `https://zgo.cash/receipt/${data.order}`;
|
||||||
|
this.receiptUrl = this.sanitizer.bypassSecurityTrustUrl(this.codeString);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
var qrcode = new QRCode(document.getElementById("receipt-qr"), {
|
||||||
|
text: this.codeString,
|
||||||
|
logo: "/assets/zgo-prp.png",
|
||||||
|
logoWidth: 80,
|
||||||
|
logoHeight: 80
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.dialogRef.close(true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ import { Injectable } from '@angular/core';
|
||||||
import { Subject, BehaviorSubject, Observable } from 'rxjs';
|
import { Subject, BehaviorSubject, Observable } from 'rxjs';
|
||||||
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
|
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
|
||||||
import { Order } from './order/order.model';
|
import { Order } from './order/order.model';
|
||||||
|
import { Owner } from './owner.model';
|
||||||
|
import { UserService } from './user.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
@ -51,7 +53,9 @@ export class ReceiptService {
|
||||||
};
|
};
|
||||||
private _orderUpdated: BehaviorSubject<Order> = new BehaviorSubject(this.dataStore.order);
|
private _orderUpdated: BehaviorSubject<Order> = new BehaviorSubject(this.dataStore.order);
|
||||||
public readonly orderUpdate: Observable<Order> = this._orderUpdated.asObservable();
|
public readonly orderUpdate: Observable<Order> = this._orderUpdated.asObservable();
|
||||||
public ownerUpdate: Observable<Owner>;
|
public _nameUpdated: BehaviorSubject<string> = new BehaviorSubject(this.dataStore.owner.name);
|
||||||
|
public readonly nameUpdate: Observable<string>= this._nameUpdated.asObservable();
|
||||||
|
public readonly ownerUpdate;
|
||||||
private apiKey = 'Le2adeic8Thah4Aeng4daem6i';
|
private apiKey = 'Le2adeic8Thah4Aeng4daem6i';
|
||||||
private reqHeaders: HttpHeaders;
|
private reqHeaders: HttpHeaders;
|
||||||
|
|
||||||
|
@ -61,19 +65,21 @@ export class ReceiptService {
|
||||||
) {
|
) {
|
||||||
this.reqHeaders = new HttpHeaders().set('Authorization', this.apiKey);
|
this.reqHeaders = new HttpHeaders().set('Authorization', this.apiKey);
|
||||||
this.ownerUpdate = userService.ownerUpdate;
|
this.ownerUpdate = userService.ownerUpdate;
|
||||||
this.ownerUpdate.subscribe((owner) => {
|
|
||||||
this.dataStore.owner = owner;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getOrderById(id:string) {
|
getOrderById(id:string) {
|
||||||
const params = new HttpParams().append('id', id);
|
const params = new HttpParams().append('id', id);
|
||||||
let obs = this.http.get<{message: string, order: any}>(this.beUrl+'api/order', { headers:this.reqHeaders, params:params, observe: 'response'});
|
let obs = this.http.get<{message: string, order: any}>(this.beUrl+'api/receipt', { headers:this.reqHeaders, params:params, observe: 'response'});
|
||||||
|
|
||||||
obs.subscribe((OrderDataResponse) => {
|
obs.subscribe((OrderDataResponse) => {
|
||||||
if (OrderDataResponse.status == 200) {
|
if (OrderDataResponse.status == 200) {
|
||||||
this.dataStore.order = OrderDataResponse.body!.order;
|
this.dataStore.order = OrderDataResponse.body!.order;
|
||||||
this._orderUpdated.next(Object.assign({}, this.dataStore).order);
|
this._orderUpdated.next(Object.assign({}, this.dataStore).order);
|
||||||
|
this.userService.getOwner(this.dataStore.order.address);
|
||||||
|
this.ownerUpdate.subscribe((owner) => {
|
||||||
|
this.dataStore.owner = owner;
|
||||||
|
this._nameUpdated.next(Object.assign({}, this.dataStore).owner.name);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log('No order found');
|
console.log('No order found');
|
||||||
}
|
}
|
||||||
|
@ -81,4 +87,5 @@ export class ReceiptService {
|
||||||
|
|
||||||
return obs;
|
return obs;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,3 +28,9 @@
|
||||||
span.tt{
|
span.tt{
|
||||||
font-family: 'Roboto-Mono', monospace;
|
font-family: 'Roboto-Mono', monospace;
|
||||||
}
|
}
|
||||||
|
img.total{
|
||||||
|
margin-bottom:-2px;
|
||||||
|
}
|
||||||
|
.small{
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
|
@ -4,19 +4,40 @@
|
||||||
</span>
|
</span>
|
||||||
<span class="spacer"></span>
|
<span class="spacer"></span>
|
||||||
<span align="center">
|
<span align="center">
|
||||||
<p class="text">Name</p>
|
<p class="text">{{name}}</p>
|
||||||
</span>
|
</span>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-title>
|
<mat-card-title>
|
||||||
Receipt
|
Total: <img class="total" src="/assets/spartan-zec.png" height="18px" />{{order.totalZec | number: '1.0-6'}}
|
||||||
</mat-card-title>
|
</mat-card-title>
|
||||||
<mat-card-subtitle>
|
<mat-card-subtitle>
|
||||||
Date
|
{{order.timestamp | date}}
|
||||||
</mat-card-subtitle>
|
</mat-card-subtitle>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<p>receipt works! orderID:{{orderId}}</p>
|
<p class="small">Order ID: {{orderId}}</p>
|
||||||
|
<p>Zcash Price: {{order.price | currency: order.currency.toUpperCase()}}</p>
|
||||||
|
<div align="center">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th align="left">
|
||||||
|
Item
|
||||||
|
</th>
|
||||||
|
<th align="center">
|
||||||
|
Qty.
|
||||||
|
</th>
|
||||||
|
<th align="right">
|
||||||
|
Price ({{order.currency.toUpperCase()}})
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
<tr *ngFor="let item of order.lines">
|
||||||
|
<td align="left">{{item.name}}</td>
|
||||||
|
<td align="center">{{item.qty}}</td>
|
||||||
|
<td align="right">{{(item.qty * item.cost) | currency: order.currency.toUpperCase()}} </td>
|
||||||
|
<tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { Order} from '../order/order.model';
|
import { Order} from '../order/order.model';
|
||||||
import { OrderService } from '../order/order.service';
|
import { ReceiptService } from '../receipt.service';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-receipt',
|
selector: 'app-receipt',
|
||||||
|
@ -10,14 +11,42 @@ import { OrderService } from '../order/order.service';
|
||||||
})
|
})
|
||||||
export class ReceiptComponent implements OnInit {
|
export class ReceiptComponent implements OnInit {
|
||||||
orderId;
|
orderId;
|
||||||
//order:Order;
|
public orderUpdate: Observable<Order>;
|
||||||
|
public nameUpdate: Observable<string>;
|
||||||
|
name: string = '';
|
||||||
|
order:Order = {
|
||||||
|
address: '',
|
||||||
|
session: '',
|
||||||
|
timestamp: '',
|
||||||
|
closed: false,
|
||||||
|
currency: '',
|
||||||
|
price: 0,
|
||||||
|
total: 0,
|
||||||
|
totalZec: 0,
|
||||||
|
lines: [
|
||||||
|
{
|
||||||
|
qty: 1,
|
||||||
|
name: '',
|
||||||
|
cost:0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _ActiveRoute:ActivatedRoute,
|
private _ActiveRoute:ActivatedRoute,
|
||||||
public orderService: OrderService
|
public receiptService: ReceiptService
|
||||||
) {
|
) {
|
||||||
this.orderId = this._ActiveRoute.snapshot.paramMap.get("orderId");
|
this.orderId = this._ActiveRoute.snapshot.paramMap.get("orderId");
|
||||||
|
this.orderUpdate = receiptService.orderUpdate;
|
||||||
|
this.nameUpdate = receiptService.nameUpdate;
|
||||||
|
receiptService.getOrderById(this.orderId!);
|
||||||
|
this.orderUpdate.subscribe(order => {
|
||||||
|
this.order = order;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.nameUpdate.subscribe(name => {
|
||||||
|
this.name = name;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 13 KiB |
BIN
src/assets/zgo-prp.png
Normal file
BIN
src/assets/zgo-prp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 529 KiB |
Loading…
Reference in a new issue