Implement checkout

This commit is contained in:
Rene Vergara 2021-10-28 13:22:54 -05:00
parent dce8da391e
commit 251fa5d327
11 changed files with 150 additions and 18 deletions

View file

@ -21,6 +21,7 @@ import { ItemDeleteComponent } from './items/item-delete/item-delete.component';
import { ItemAddComponent} from './items/item-add/item-add.component'; import { ItemAddComponent} from './items/item-add/item-add.component';
import { OrderComponent } from './order/order.component'; import { OrderComponent } from './order/order.component';
import { CancelComponent } from './cancel/cancel.component'; import { CancelComponent } from './cancel/cancel.component';
import { CheckoutComponent } from './checkout/checkout.component';
//import { NameDialogComponent } from './namedialog/namedialog.component'; //import { NameDialogComponent } from './namedialog/namedialog.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@ -35,8 +36,8 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
ItemCreateComponent, ItemCreateComponent,
ItemDeleteComponent, ItemDeleteComponent,
ItemAddComponent, ItemAddComponent,
CancelComponent CancelComponent,
//NameDialogComponent, CheckoutComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,
@ -58,6 +59,6 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
], ],
providers: [], providers: [],
bootstrap: [AppComponent], bootstrap: [AppComponent],
entryComponents: [ItemCreateComponent, ItemDeleteComponent, ItemAddComponent, CancelComponent] entryComponents: [ItemCreateComponent, ItemDeleteComponent, ItemAddComponent, CancelComponent, CheckoutComponent]
}) })
export class AppModule { } export class AppModule { }

View file

@ -0,0 +1,3 @@
.text {
font-family: "Roboto-Mono", monospace;
}

View file

@ -0,0 +1,25 @@
<div align="center" mat-dialog-title>
<h2 class="text">Scan to make payment</h2>
</div>
<mat-dialog-content>
<div align="center" id="checkout-qr"></div>
</mat-dialog-content>
<mat-dialog-actions>
<table cellspacing="0" width="100%">
<tr>
<td>
<button mat-raised-button color="primary" (click)="confirm()">
<mat-icon>verified_user</mat-icon>
</button>
</td>
<td align="right">
<button mat-raised-button (click)="close()">
<mat-icon>close</mat-icon>
</button>
</td>
</tr>
</table>
</mat-dialog-actions>

View file

@ -0,0 +1,45 @@
import { Inject, Component, OnInit, ViewEncapsulation} from '@angular/core';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog';
var QRCode = require('easyqrcodejs');
var URLSafeBase64 = require('urlsafe-base64');
var Buffer = require('buffer/').Buffer;
@Component({
selector: 'app-checkout',
templateUrl: './checkout.component.html',
styleUrls: ['./checkout.component.css']
})
export class CheckoutComponent implements OnInit{
address: string;
total: number;
orderId: string;
codeString: string = '';
constructor(
private dialogRef: MatDialogRef<CheckoutComponent>,
@Inject(MAT_DIALOG_DATA) public data: { totalZec: number, addr: string, orderId: string}
) {
this.address = data.addr;
this.total = data.totalZec;
this.orderId = data.orderId;
}
ngOnInit() {
this.codeString = `zcash:${this.address}?amount=${this.total.toFixed(6)}&memo=${URLSafeBase64.encode(Buffer.from('Z-Go Order '.concat(this.orderId)))}`;
var qrcode = new QRCode(document.getElementById("checkout-qr"), {
text: this.codeString,
logo: "/assets/zcash.png",
logoWidth: 80,
logoHeight: 80
});
}
confirm() {
this.dialogRef.close(true);
}
close() {
this.dialogRef.close(false);
}
}

View file

@ -1,13 +1,12 @@
<mat-toolbar color="primary"> <mat-toolbar color="primary">
<span> <span>
<a routerLink = "/"> <a routerLink = "/">
Zgo! Z Go!
</a> </a>
<p class="mini">Last block seen: {{heightUpdate | async}}</p> <p class="mini">Last block seen: {{heightUpdate | async}}</p>
</span> </span>
<span class="spacer"></span> <span class="spacer"></span>
<span align="center"> <span align="center">
<div>{{(ownerUpdate | async)!.name}}</div> <div>{{ shortenZaddr((ownerUpdate | async)!.address) }}</div>
<div class="mini">{{ shortenZaddr((ownerUpdate | async)!.address) }}</div>
</span> </span>
</mat-toolbar> </mat-toolbar>

View file

@ -50,6 +50,9 @@ export class ItemListComponent implements OnInit{
} }
ngOnInit(){ ngOnInit(){
this.itemsUpdate.subscribe((items) => {
this.items = items;
});
} }
openDialog(){ openDialog(){
@ -67,6 +70,9 @@ export class ItemListComponent implements OnInit{
this.itemService.addItem(item); this.itemService.addItem(item);
} }
this.itemService.getItems(this.owner.address); this.itemService.getItems(this.owner.address);
this.itemsUpdate.subscribe((items) => {
this.items = items;
});
}); });
} }
@ -114,8 +120,12 @@ export class ItemListComponent implements OnInit{
if (val != null) { if (val != null) {
console.log('Deleting', val); console.log('Deleting', val);
this.itemService.deleteItem(val); this.itemService.deleteItem(val);
this.items = [];
} }
this.itemService.getItems(this.owner.address); this.itemService.getItems(this.owner.address);
this.itemsUpdate.subscribe((items) => {
this.items = items;
});
}); });
} }

View file

@ -9,11 +9,13 @@ export class ItemService{
private dataStore: { items: Item[] } = { items: [] } ; private dataStore: { items: Item[] } = { items: [] } ;
private _itemsUpdated: BehaviorSubject<Item[]> = new BehaviorSubject(this.dataStore.items); private _itemsUpdated: BehaviorSubject<Item[]> = new BehaviorSubject(this.dataStore.items);
public readonly itemsUpdated: Observable<Item[]> = this._itemsUpdated.asObservable(); public readonly itemsUpdated: Observable<Item[]> = this._itemsUpdated.asObservable();
private address:string = '';
constructor(private http: HttpClient){ constructor(private http: HttpClient){
} }
getItems(addr: string){ getItems(addr: string){
this.address = addr;
const params = new HttpParams().append('address', addr); const params = new HttpParams().append('address', addr);
let obs = this.http.get<{message: string, items: any}>('http://localhost:3000/api/getitems', { headers:{}, params: params, observe: 'response'}); let obs = this.http.get<{message: string, items: any}>('http://localhost:3000/api/getitems', { headers:{}, params: params, observe: 'response'});
@ -35,6 +37,7 @@ export class ItemService{
obs.subscribe((ItemResponse) => { obs.subscribe((ItemResponse) => {
console.log('Item added'); console.log('Item added');
this.getItems(this.address);
}); });
return obs; return obs;
@ -45,6 +48,7 @@ export class ItemService{
obs.subscribe((ItemResponse) => { obs.subscribe((ItemResponse) => {
console.log('Item deleted'); console.log('Item deleted');
this.getItems(this.address);
}); });
return obs; return obs;

View file

@ -1,3 +1,7 @@
* { * {
font-family: 'Roboto Mono', monospace; font-family: 'Roboto-Mono', monospace;
}
mat-card.coolcard{
background-color: #FF5722;
color: #FFFFFF;
} }

View file

@ -1,27 +1,46 @@
<br> <br>
<div align="center"> <div align="center" class="text">
<h1>Welcome to Zgo!</h1> <mat-card class="coolcard">
<h3>
<pre>
__||__ _____ _
|___ / / ____| | |
/ / | | __ ___ | |
/ / | | |_ |/ _ \| |
/ /__ | |__| | (_) |_|
/__ _| \_____|\___/(_)
||
</pre>
</h3>
</mat-card>
</div> </div>
<table> <div align="center">
<table width="80%">
<colgroup> <colgroup>
<col span="1" style="width: 75%;"> <col span="1" style="width: 75%;">
<col span="1" style="width: 25%;"> <col span="1" style="width: 25%;">
</colgroup> </colgroup>
<tr> <tr>
<td> <td>
<p>A non-custodial point-of-sale application, powered by Zcash.</p> <mat-card>
<p>A non-custodial point-of-sale application, powered by Zcash!</p>
<ul>
<li>Your Zcash shielded address is your login.</li>
<li>Your customer pays directly to your wallet.</li>
</ul>
</mat-card>
</td> </td>
<td> <td>
<mat-card>
<div align="center" id="info"> <div align="center" id="info">
<p> <p>
Ensure you include your Reply-To shielded address! Ensure you include your Reply-To shielded address!
</p> </p>
<p>
Your shielded address is your username and all payments will be sent to it.
</p>
</div>
<br> <br>
<div align="center" id="qrcode"></div> <div align="center" id="qrcode"></div>
</div>
</mat-card>
</td> </td>
</tr> </tr>
</table> </table>
</div>

View file

@ -1,8 +1,9 @@
<div align="center">
<p *ngIf="order.address.length == 0">No open order!</p> <p *ngIf="order.address.length == 0">No open order!</p>
</div>
<mat-card class="text" *ngIf="order.address.length > 0"> <mat-card class="text" *ngIf="order.address.length > 0">
<div align="center"> <div align="center">
<mat-card-title> <mat-card-title>
{{order._id}}
<table cellspacing="0" width="100%"> <table cellspacing="0" width="100%">
<tr> <tr>
<td>Order Total:</td> <td>Order Total:</td>
@ -31,8 +32,7 @@
<button mat-raised-button class="text" (click)="cancelOrder()">Cancel</button> <button mat-raised-button class="text" (click)="cancelOrder()">Cancel</button>
</td> </td>
<td align="right"> <td align="right">
<button mat-raised-button class="text" color="primary">Checkout</button> <button mat-raised-button class="text" color="primary" (click)="checkout()">Checkout</button>
</td> </td>
</tr> </tr>
</table> </table>

View file

@ -6,6 +6,7 @@ import { FullnodeService } from '../fullnode.service';
import { UserService } from '../user.service'; 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';
@Component({ @Component({
selector: 'app-order', selector: 'app-order',
@ -62,4 +63,25 @@ export class OrderComponent implements OnInit{
this.orderService.getOrder(); this.orderService.getOrder();
}); });
} }
checkout() {
const dialogConfig = new MatDialogConfig();
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.data = {
totalZec: this.total/this.price,
addr: this.order.address,
orderId: this.order._id
};
const dialogRef = this.dialog.open(CheckoutComponent, dialogConfig);
dialogRef.afterClosed().subscribe((val) => {
if (val) {
console.log('Payment confirmed!');
} else {
console.log('Returning to order');
}
});
}
} }