New component for receipts on order lists

This commit is contained in:
Rene V. Vergara A. 2022-07-25 16:42:56 -05:00
parent 7ef92aee12
commit 7930d6410b
12 changed files with 572 additions and 178 deletions

View File

@ -42,6 +42,7 @@ import { ReceiptQRComponent } from './receipt-qr/receipt-qr.component';
import { InvoiceComponent } from './invoice/invoice.component';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { PromptInvoiceComponent } from './prompt-invoice/prompt-invoice.component';
import { PromptReceiptComponent } from './prompt-receipt/prompt-receipt.component';
import { NotifierComponent } from './notifier/notifier.component';
@NgModule({
@ -67,6 +68,7 @@ import { NotifierComponent } from './notifier/notifier.component';
ReceiptQRComponent,
InvoiceComponent,
PromptInvoiceComponent,
PromptReceiptComponent,
NotifierComponent
],
imports: [

View File

@ -3,6 +3,12 @@
font-family: Roboto Mono !important;
}
.zecSign {
margin-bottom: -4px;
font-size: 18px;
height: 18px;
}
.invoiceHeader {
display: flex;
font-family: Spartan;
@ -21,7 +27,6 @@
font-family: Roboto Mono !important;
padding: 10px;
max-width: 600px;
background: #ebecf0;
}
.invoiceHdrTxt1 {
@ -98,8 +103,6 @@
float: right;
}
.zecData {
width: auto;
font-family: Spartan !important;

View File

@ -1,111 +1,116 @@
<div class="invoiceHeader">
<img class="logo" src="/assets/logo-new-white.png" height="40px" />
{{name}}
</div>
<div class="invoiceDetail"
*ngIf="!error"
id="invoice">
<div class="invoiceHdrTxt1">Invoice</div>
<div class="invoiceHdrTxt2">Order ID: {{orderId}}</div>
<div class="invoiceHdrTxt3">Date:{{order.timestamp | date}}
<div style="display: flex;
justify-content: center;
align-items: center;">
<div class="container">
<div class="invoiceHeader">
<img class="logo" src="/assets/logo-new-white.png" height="40px" />
{{name}}
</div>
<div style="height: 10px;"></div>
<div class="zecData">Zcash Price: {{order.price | number: '1.02' | currency: order.currency.toUpperCase()}}</div>
<div style="height: 2px;"></div>
<div class="zecData">Total: <img class="total" src="/assets/zec_rv.png" height="18px" />{{order.totalZec | number: '1.08'}}
<div class="invoiceDetail"
*ngIf="!error"
id="invoice">
<div class="invoiceHdrTxt1">Invoice</div>
<div class="invoiceHdrTxt2">Order ID: {{orderId}}</div>
<div class="invoiceHdrTxt3">Date:{{order.timestamp | date}}
</div>
<div>
<div style="height: 10px;"></div>
<table style="width: 100%;"
cellspacing="0">
<tr class="invoice-title">
<th width="55%"
class="detailTitle1">
Item
</th>
<th width="15%"
class="detailTitle1">
Qty.
</th>
<th width="30%"
class="detailTitle2">
Price ({{order.currency.toUpperCase()}})
</th>
</tr>
<tr class="invoice-detail"
*ngFor="let item of order.lines">
<td width="55%"
align="left">
{{item.name}}
</td>
<td width="15%"
align="center">
{{item.qty}}
</td>
<td width="30%"
align="right">
{{( item.qty * item.cost ) | number : '1.02' | currency: order.currency.toUpperCase()}}
</td>
</tr>
<tr class="invoice-title">
<th width="55%"
class="detailLineRight">
Invoice Total:
</th>
<th width="15%"
class="detailLineLeft">
<div style="height: 10px;"></div>
<div class="zecData">Zcash Price: {{order.price | number: '1.02' | currency: order.currency.toUpperCase()}}</div>
<div style="height: 2px;"></div>
<div class="zecData">Total: <img class="zecSign" src="/assets/zec_rv.png" />{{order.totalZec | number: '1.08'}}
</div>
<div>
<div style="height: 10px;"></div>
<table style="width: 100%;"
cellspacing="0">
<tr class="invoice-title">
<th width="55%"
class="detailTitle1">
Item
</th>
<th width="15%"
class="detailTitle1">
Qty.
</th>
<th width="30%"
class="detailTitle2">
Price ({{order.currency.toUpperCase()}})
</th>
</tr>
<tr class="invoice-detail"
*ngFor="let item of order.lines">
<td width="55%"
align="left">
{{item.name}}
</td>
<td width="15%"
align="center">
{{item.qty}}
</td>
<td width="30%"
align="right">
{{( item.qty * item.cost ) | number : '1.02' | currency: order.currency.toUpperCase()}}
</td>
</tr>
<tr class="invoice-title">
<th width="55%"
class="detailLineRight">
Invoice Total:
</th>
<th width="15%"
class="detailLineLeft">
</th>
<th width="30%"
class="detailLineRight">
{{ order.total | number : '1.02' | currency: order.currency.toUpperCase()}}
</th>
</tr>
</table>
<div style="height: 15px;"></div>
<table>
<tr>
<td width="75%"
style="font-size: 20px;
font-weight: 700;
font-style: italic;
text-align: center;">
<p *ngIf="order.paid">
<fa-icon [icon]="faCheck"
color="primary"></fa-icon>&nbsp;Payment confirmed</p>
<p *ngIf="!order.paid">
<fa-icon [style]="getIconStyle(order)"
[icon]="faHourglass"></fa-icon>&nbsp;Payment pending!!</p>
</td>
<td width="25%">
<div style="text-align: right;"
id="payment-qr"
*ngIf="!order.paid"></div>
</td>
</tr>
</table>
</th>
<th width="30%"
class="detailLineRight">
{{ order.total | currency: order.currency.toUpperCase()}}
</th>
</tr>
</table>
<div style="height: 15px;"></div>
<table>
<tr>
<td width="75%"
style="font-size: 20px;
font-weight: 700;
font-style: italic;
text-align: center;">
<p *ngIf="order.paid">
<fa-icon [icon]="faCheck"
color="primary"></fa-icon>&nbsp;Payment confirmed</p>
<p *ngIf="!order.paid">
<fa-icon [style]="getIconStyle(order)"
[icon]="faHourglass"></fa-icon>&nbsp;Payment pending!!</p>
</td>
<td width="25%">
<div style="text-align: right;"
id="payment-qr"
*ngIf="!order.paid"></div>
</td>
</tr>
</table>
</div>
</div>
<div align="center" *ngIf="error">
<div style="height: 10px;"></div>
<div style="font-family: Spartan !important;
font-size: 20px;
padding: 4px;
height: 24px;">
Incorrect Invoice ID.
</div>
<div style="font-family: Spartan !important;
font-size: 16px;
padding: 4px;">
No information available.
</div>
<div style="height: 10px;"></div>
<mat-card-actions>
<div align="center">
<button mat-raised-button [routerLink]="['/']" color="primary">OK</button>
</div>
</mat-card-actions>
</div>
<div align="center" *ngIf="error">
<div style="height: 10px;"></div>
<div style="font-family: Spartan !important;
font-size: 20px;
padding: 4px;
height: 24px;">
Incorrect Invoice ID.
</div>
<div style="font-family: Spartan !important;
font-size: 16px;
padding: 4px;">
No information available.
</div>
<div style="height: 10px;"></div>
<mat-card-actions>
<div align="center">
<button mat-raised-button [routerLink]="['/']" color="primary">OK</button>
</div>
</mat-card-actions>
</div>
</div>
</div>

View File

@ -122,6 +122,20 @@
</tr>
</tbody>
</table>
<div style="display: flex;
justify-content: space-between;
padding: 5px;
height: 25px;
background: lightblue;
cursor: pointer;">
<button style="background: #ff5722;
color: white;"
(click)="invoice(order)">Invoice</button>
<button style="background: #ff5722;
color: white;"
(click)="receipt(order)">Receipt</button>
</div>
</mat-expansion-panel>
</mat-accordion>
<p class="text" *ngIf = "orders.length <= 0">No orders</p>

View File

@ -3,9 +3,13 @@ import { Observable } from 'rxjs';
import { Order } from '../order/order.model';
import { FullnodeService } from '../fullnode.service';
import { UserService } from '../user.service';
import {Owner} from '../owner.model';
import { Owner } from '../owner.model';
import { OrderService } from '../order/order.service';
import { MatDialog, MatDialogConfig} from '@angular/material/dialog';
import { PromptInvoiceComponent } from '../prompt-invoice/prompt-invoice.component';
import { PromptReceiptComponent } from '../prompt-receipt/prompt-receipt.component';
import { faTimes } from '@fortawesome/free-solid-svg-icons';
import { faTimesCircle } from '@fortawesome/free-solid-svg-icons';
import { faCheck } from '@fortawesome/free-solid-svg-icons';
@ -20,12 +24,14 @@ import { faTrash } from '@fortawesome/free-solid-svg-icons';
})
export class ListOrdersComponent implements OnInit, OnDestroy{
// orderId;
public todayTotal: number = 0;
public total: number = 0;
public orders: Order[] = [];
public ownerUpdate: Observable<Owner>;
public ordersUpdate: Observable<Order[]>;
// ------------------------------------
//
faTimes = faTimes;
@ -40,8 +46,9 @@ export class ListOrdersComponent implements OnInit, OnDestroy{
constructor(
public orderService: OrderService,
public userService: UserService
){
public userService: UserService,
private dialog: MatDialog)
{
this.ownerUpdate = userService.ownerUpdate;
this.orderService.getAllOrders();
this.ordersUpdate = orderService.allOrdersUpdate;
@ -83,4 +90,46 @@ export class ListOrdersComponent implements OnInit, OnDestroy{
}
invoice(order : Order) {
// var zec = this.total/this.price;
// this.order.totalZec = parseFloat(zec.toFixed(8));
const dialogConfig = new MatDialogConfig();
console.log("Order data:");
console.log(order);
console.log("order.total = " + order.total);
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.data = {
orderId: order._id
};
const dialogRef = this.dialog.open(PromptInvoiceComponent, dialogConfig);
dialogRef.afterClosed().subscribe((val) => {
console.log('Returning to order list');
});
}
receipt(order : Order) {
// var zec = this.total/this.price;
// this.order.totalZec = parseFloat(zec.toFixed(8));
const dialogConfig = new MatDialogConfig();
console.log("Order data:");
console.log(order);
console.log("order.total = " + order.total);
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.data = {
orderId: order._id
};
const dialogRef = this.dialog.open(PromptReceiptComponent, dialogConfig);
dialogRef.afterClosed().subscribe((val) => {
console.log('Returning to order list');
});
}
}

View File

@ -0,0 +1,49 @@
::ng-deep .invoice {
font-family: "Spartan";
background: #ff5722;
font-weight: 700;
font-size: 18px;
text-align: center;
color: white;
line-height: 20px;
padding: 10px;
}
::ng-deep .invoice-content {
font-family: Roboto mono;
display: flex;
justify-content: center;
font-size: 16px;
}
.copy-button {
color: dodgerblue;
font-size: 20px;
margin: auto;
}
.urlLabel {
font-family: "Spartan";
font-size: 14px;
color: dimgray;
}
.urlDetail {
font-family: "Spartan";
font-size: 14px;
color: black;
}
.urlCopyBtn {
cursor: pointer;
}
.qr-code{
border-radius: 0.5rem;
border-bottom-left-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
}

View File

@ -0,0 +1,57 @@
<div class="container" style="margin-top: 10px;">
<div class="invoice" >
Send the receipt link to your client:
</div>
<table style="width:100%;
margin-top: 10px;">
<thead style="width: 100%;">
<tr>
<th class="urlLabel"
style="text-align: left;"
width="94%">Receipt URL:
</th>
<th></th>
</tr>
</thead>
<tbody>
<td class="urlDetail"
style="text-align: left;"
width="94%">
<div>
<textarea
style="border: none;
outline: none;
width: 95%;"
cdkTextareaAutosize
cdkAutosizeMinRows="1"
cdkAutosizeMaxRows="4">{{ receiptUrl }}
</textarea>
</div>
</td>
<td class="urlCopyBtn">
<a (click)='copyUrl()' >
<fa-icon [icon]="faCopy"
class="copy-button">
</fa-icon>
</a>
</td>
</tbody>
</table>
<mat-dialog-actions>
<table cellspacing="0" width="100%">
<tr>
<td align="right">
<button mat-raised-button class="text" (click)="close()">
<mat-icon class="icon">close</mat-icon>Close
</button>
</td>
</tr>
</table>
</mat-dialog-actions>
</div>

View File

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PromptReceiptComponent } from './prompt-receipt.component';
describe('PromptReceiptComponent', () => {
let component: PromptReceiptComponent;
let fixture: ComponentFixture<PromptReceiptComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PromptReceiptComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(PromptReceiptComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,62 @@
import { Inject, Component, OnInit} from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog';
import { NotifierService } from '../notifier.service';
import { faCopy } from '@fortawesome/free-solid-svg-icons';
var URLSafeBase64 = require('urlsafe-base64');
var Buffer = require('buffer/').Buffer;
@Component({
selector: 'app-prompt-receipt',
templateUrl: './prompt-receipt.component.html',
styleUrls: ['./prompt-receipt.component.css']
})
export class PromptReceiptComponent implements OnInit {
orderId: string;
receiptUrl: string;
// ------------------------------------
//
faCopy = faCopy;
// ------------------------------------
constructor(
private dialogRef: MatDialogRef<PromptReceiptComponent>,
@Inject(MAT_DIALOG_DATA) public data: {orderId: string},
private notifierService : NotifierService ) {
this.orderId = data.orderId;
this.receiptUrl = 'https://app.zgo.cash/receipt/'+this.orderId;
}
ngOnInit(): void {
}
confirm() {
this.dialogRef.close(true);
}
close() {
this.dialogRef.close(false);
}
copyUrl() {
// console.log("Inside copyUrl()");
if (navigator.clipboard) {
};
try {
navigator.clipboard.writeText(this.receiptUrl);
this.notifierService
.showNotification("Receipt's URL copied to Clipboard!!","Close",'success');
} catch (err) {
// console.error("Error", err);
this.notifierService
.showNotification("Functionality not available for your browser. Use send button instead.","Close",'error');
}
}
}

View File

@ -1,36 +1,112 @@
* {
font-family: 'Spartan', sans-serif;
.invoice {
font-family: Roboto Mono !important;
}
.spacer{
flex: 1 1 auto;
.zecSign {
margin-bottom: -4px;
font-size: 18px;
height: 18px;
}
.mat-card{
font-family: 'Spartan', sans-serif;
border: 1px solid #FF7522;
width: 80%;
text-align: left;
margin: 5px;
max-width: 500px;
.invoiceHeader {
display: flex;
font-family: Spartan;
font-weight: 700;
font-size: 26px;
color: white;
justify-content: space-between;
line-height: 40px;
padding: 10px;
vertical-align: center;
max-width: 600px;
background: #ff5722;
}
.mat-card-title{
font-size: 16px;
.invoiceDetail {
font-family: Roboto Mono !important;
padding: 10px;
max-width: 600px;
}
.invoiceHdrTxt1 {
font-family: Spartan !important;
text-align: center;
font-size: 30px;
font-weight: 700;
}
.mat-card-subtitle{
font-size: 12px;
font-weight: 200;
.invoiceHdrTxt2 {
font-family: Spartan !important;
text-align: center;
font-size: 16px;
font-weight: 400;
}
.mat-card-content{
font-size: 14px;
text-align: justify;
.invoiceHdrTxt3 {
font-family: Spartan !important;
text-align: center;
font-size: 12px;
font-weight: 300;
}
span.tt{
font-family: 'Roboto-Mono', monospace;
.detailTitle1 {
border-top: solid 2px;
border-bottom: solid 2px;
border-color: navy;
text-align: left;
}
img.total{
margin-bottom:-2px;
.detailTitle2 {
border-top: solid 2px;
border-bottom: solid 2px;
border-color: navy;
text-align: right;
}
.small{
font-size: 10px;
.detailLineRight {
border-top: solid 2px;
border-bottom: solid 2px;
border-color: navy;
text-align: right;
}
.detailLineLeft {
border-top: solid 2px;
border-bottom: solid 2px;
border-color: navy;
text-align: right;
}
.invoice-title {
font-size: 16px;
font-weight: 700;
background: lightcyan;
line-height: 30px;
padding: 5px;
}
.invoice-detail {
line-height: 20px;
font-size: 16px;
font-weight: 400;
padding-top: 4px;
padding-bottom: 4px;
}
.invoice-total {
margin-top: 40px;
}
.qrcode {
display: flex;
float: right;
}
.zecData {
width: auto;
font-family: Spartan !important;
font-size: 16px;
font-weight: 700;
text-align: right;
}

View File

@ -1,44 +1,95 @@
<mat-toolbar color="primary">
<span align="center">
<img class="logo" src="/assets/logo-new-white.png" height="40px" />
</span>
<span class="spacer"></span>
<span align="center">
<p class="text">{{name}}</p>
</span>
</mat-toolbar>
<div align="center">
<mat-card>
<mat-card-title>
Total: <img class="total" src="/assets/spartan-zec.png" height="18px" />{{order.totalZec | number: '1.0-6'}}
</mat-card-title>
<mat-card-subtitle>
{{order.timestamp | date}}
</mat-card-subtitle>
<mat-card-content>
<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 style="display: flex;
justify-content: center;
align-items: center;">
<div class="container">
<div class="invoiceHeader">
<img class="logo" src="/assets/logo-new-white.png" height="40px" />
{{name}}
</div>
<div class="invoiceDetail"
*ngIf="!error"
id="invoice">
<div class="invoiceHdrTxt1">Receipt</div>
<div class="invoiceHdrTxt2">Order ID: {{orderId}}</div>
<div class="invoiceHdrTxt3">Date:{{order.timestamp | date}}
</div>
<div style="height: 10px;"></div>
<div class="zecData">Zcash Price: {{order.price | number: '1.02' | currency: order.currency.toUpperCase()}}</div>
<div style="height: 2px;"></div>
<div class="zecData">Total: <img class="zecSign" src="/assets/zec_rv.png" />{{order.totalZec | number: '1.08'}}
</div>
<div>
<div style="height: 10px;"></div>
<table style="width: 100%;"
cellspacing="0">
<tr class="invoice-title">
<th width="55%"
class="detailTitle1">
Item
</th>
<th width="15%"
class="detailTitle1">
Qty.
</th>
<th width="30%"
class="detailTitle2">
Price ({{order.currency.toUpperCase()}})
</th>
</tr>
<tr class="invoice-detail"
*ngFor="let item of order.lines">
<td width="55%"
align="left">
{{item.name}}
</td>
<td width="15%"
align="center">
{{item.qty}}
</td>
<td width="30%"
align="right">
{{( item.qty * item.cost ) | number : '1.02' | currency: order.currency.toUpperCase()}}
</td>
</tr>
<tr class="invoice-title">
<th width="55%"
class="detailLineRight">
Total:
</th>
<th width="15%"
class="detailLineLeft">
</th>
<th width="30%"
class="detailLineRight">
{{ order.total | currency: order.currency.toUpperCase()}}
</th>
</tr>
</table>
<div style="height: 15px;"></div>
</div>
</div>
</mat-card-content>
</mat-card>
</div>
<div align="center" *ngIf="error">
<div style="height: 10px;"></div>
<div style="font-family: Spartan !important;
font-size: 20px;
padding: 4px;
height: 24px;">
Incorrect Receipt ID.
</div>
<div style="font-family: Spartan !important;
font-size: 16px;
padding: 4px;">
No information available.
</div>
<div style="height: 10px;"></div>
<mat-card-actions>
<div align="center">
<button mat-raised-button [routerLink]="['/']" color="primary">OK</button>
</div>
</mat-card-actions>
</div>
</div>
</div>

View File

@ -14,6 +14,7 @@ export class ReceiptComponent implements OnInit {
public orderUpdate: Observable<Order>;
public nameUpdate: Observable<string>;
name: string = '';
error: boolean = false;
order:Order = {
address: '',
session: '',