Implement biz info form

This commit is contained in:
Rene Vergara 2022-01-22 07:49:22 -06:00
parent 5f80b1d912
commit f5a14bf7d7
11 changed files with 225 additions and 57 deletions

View file

@ -82,7 +82,7 @@ function hexToString(hexString) {
function sendPin(pin, address) {
//var memo = URLSafeBase64.encode(Buffer.from('ZGO pin: '.concat(pin)));
var memo = Buffer.from('ZGO pin: '.concat(pin)).toString('hex');
var memo = Buffer.from('ZGo PIN: '.concat(pin)).toString('hex');
//console.log(typeof(memo));
var amounts = [
{
@ -175,7 +175,8 @@ var blockInterval = setInterval( function() {
address: doc.address,
blocktime: txData.blocktime,
expiration: new Date(exptime * 1000),
amount: txData.amount
amount: txData.amount,
session: doc.session
});
payment.save(function(error) {
@ -350,9 +351,8 @@ app.get('/api/getowner', (req, res, next) => {
});
app.post('/api/addowner', (req, res, next) => {
// TODO: confirm passing owner works
console.log('Post: /api/addowner');
const owner = new ownermodel(req.body);
const owner = new ownermodel(req.body.owner);
owner.save();
res.status(201).json({
message: 'Owner added successfully'

View file

@ -13,7 +13,7 @@ const ownerSchema = mongoose.Schema({
city: {type: String, required: true},
state: {type: String, required: true},
postal: {type: String, required: true},
phone: {type: String, required: true},
phone: {type: String},
website: {type: String},
paid: {type: Boolean, required: true, default: false}
});

View file

@ -4,7 +4,8 @@ const paymentSchema = mongoose.Schema({
address: {type: String, required: true},
blocktime: {type: Number, required: true},
expiration: {type: Date, required: true},
amount: {type: Number, required: true}
amount: {type: Number, required: true},
session: {type: String, required: true}
});
module.exports = mongoose.model('Payment', paymentSchema);

View file

@ -34,6 +34,7 @@ import { ScanComponent } from './scan/scan.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { BusinessComponent } from './business/business.component';
import { SearchOptionsPipe } from './searchoptions.pipe';
import { PaymentComponent } from './payment/payment.component';
@NgModule({
declarations: [
@ -52,7 +53,8 @@ import { SearchOptionsPipe } from './searchoptions.pipe';
ScanComponent,
ListOrdersComponent,
BusinessComponent,
SearchOptionsPipe
SearchOptionsPipe,
PaymentComponent
],
imports: [
BrowserModule,

View file

@ -2,6 +2,10 @@
font-family: 'Spartan', sans-serif;
}
mat-card.centercard{
max-width: 450px;
max-width: 500px;
border: 1px solid #CCCCCC;
}
::ng-deep .mat-step-label{
font-size: 13px;
}

View file

@ -1,43 +1,78 @@
<app-header></app-header>
<div align="center">
<mat-card class="centercard" [formGroup]="bizForm">
<p>Business Information</p>
<mat-form-field appearance="outline">
<mat-label>Business Name</mat-label>
<input matInput placeholder="Business Name" formControlName="name">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Address</mat-label>
<input matInput placeholder="Address" formControlName="street">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>City</mat-label>
<input matInput placeholder="City" formControlName="city">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>State/Province</mat-label>
<input matInput placeholder="State or Province" formControlName="state">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Postal Code</mat-label>
<input matInput placeholder="Postal Code" formControlName="postal">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Country</mat-label>
<input matInput placeholder="Country" formControlName="country" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let ctry of countries | searchOptions:bizForm.get('country')!.value" [value]="ctry.name">
{{ctry.name}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>E-mail</mat-label>
<input matInput placeholder="E-mail" formControlName="email">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Website</mat-label>
<input matInput placeholder="Website" formControlName="website">
</mat-form-field>
<mat-card class="centercard">
<h3>Business sign-up</h3>
<mat-vertical-stepper #stepper linear>
<mat-step label="Provide business info" editable="false">
<p>We do not have a business associated with this Zcash address, please enter your information below:</p>
<mat-card [formGroup]="bizForm">
<mat-form-field appearance="outline">
<mat-label>Business Name</mat-label>
<input matInput placeholder="Business Name" formControlName="name">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Address</mat-label>
<input matInput placeholder="Address" formControlName="street">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>City</mat-label>
<input matInput placeholder="City" formControlName="city">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>State/Province</mat-label>
<input matInput placeholder="State or Province" formControlName="state">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Postal Code</mat-label>
<input matInput placeholder="Postal Code" formControlName="postal">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Country</mat-label>
<input matInput placeholder="Country" formControlName="country" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let ctry of countries | searchOptions:bizForm.get('country')!.value" [value]="ctry.name">
{{ctry.name}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>E-mail</mat-label>
<input matInput type="email" placeholder="E-mail" formControlName="email">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Website</mat-label>
<input matInput placeholder="Website" formControlName="website">
</mat-form-field>
<mat-card-actions>
<button mat-raised-button color="primary" [disabled]="bizForm.invalid" (click)="save()">Save</button>
</mat-card-actions>
</mat-card>
</mat-step>
<mat-step label="Select your session" editable="false">
<p>Please select the length of session that you need:</p>
<mat-card [formGroup]="payForm">
<mat-form-field appearance="outline">
<mat-label>Session</mat-label>
<mat-select formControlName="session">
<mat-option *ngFor="let ticket of tickets" [value]="ticket.value">
{{ticket.viewValue}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-card-actions>
<button mat-raised-button color="primary" [disabled]="payForm.invalid" (click)="pay()">Pay</button>
</mat-card-actions>
</mat-card>
</mat-step>
<mat-step label="ZGo confirms your payment" editable="false">
<p>{{barMessage}}</p>
<mat-progress-bar
[mode]="barMode"
[value]="barValue">
</mat-progress-bar>
</mat-step>
</mat-vertical-stepper>
</mat-card>
</div>

View file

@ -1,11 +1,18 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { FormBuilder, Validators, FormGroup, FormControl } from '@angular/forms';
import { MatDialog, MatDialogConfig} from '@angular/material/dialog';
import { ProgressBarMode } from '@angular/material/progress-bar';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { filter, startWith, map, switchMap } from 'rxjs/operators';
import { MatStepper } from '@angular/material/stepper';
import { Country } from '../country.model';
import { Owner } from '../owner.model';
import { User } from '../user.model';
import { UserService } from '../user.service';
import { FullnodeService } from '../fullnode.service';
import { SearchOptionsPipe } from '../searchoptions.pipe';
import { ScanComponent } from '../scan/scan.component';
@Component({
selector: 'app-business',
@ -14,16 +21,68 @@ import { SearchOptionsPipe } from '../searchoptions.pipe';
})
export class BusinessComponent implements OnInit {
@ViewChild('stepper', { static: false}) stepper: MatStepper|undefined;
nodeAddress: string = '';
tickets = [
{
value: 0.005,
viewValue: '1 day: 0.005 ZEC'
},{
value: 0.025,
viewValue: '1 week: 0.025 ZEC'
},{
value: 0.1,
viewValue: '1 month: 0.1 ZEC'
}
];
bizForm: FormGroup;
payForm: FormGroup;
barMessage = 'Awaiting for transaction';
barMode: ProgressBarMode = 'indeterminate';
barValue = 0;
countries: Country[] = [];
owner: Owner = {
address: '',
currency: 'usd',
tax: false,
taxValue: 0,
vat: false,
vatValue: 0,
phone: '',
paid: false,
name: '',
street: '',
city: '',
state: '',
postal: '',
country: '',
email: '',
website: ''
}
public countriesUpdate: Observable<Country[]>;
testSearch = 'uni';
public ownerUpdate: Observable<Owner>;
public addrUpdate: Observable<string>;
public userUpdate: Observable<User>;
sessionId = '';
ownerKnown = false;
constructor(
private fb: FormBuilder,
private userService: UserService
private userService: UserService,
private fullnodeService: FullnodeService,
private dialog: MatDialog,
private router: Router
) {
this.countriesUpdate = userService.countriesUpdate;
this.ownerUpdate = userService.ownerUpdate;
this.userUpdate = userService.userUpdate;
this.userUpdate.subscribe(userInfo => {
this.sessionId = userInfo.session;
});
this.addrUpdate = fullnodeService.addrUpdate;
this.addrUpdate.subscribe(nodeAdd => {
this.nodeAddress = nodeAdd;
});
this.bizForm = fb.group({
name: ['', Validators.required],
street: ['', Validators.required],
@ -31,16 +90,74 @@ export class BusinessComponent implements OnInit {
state: ['', Validators.required],
postal: ['', Validators.required],
country: ['', Validators.required],
email: ['', Validators.required],
website: ['', Validators.required]
email: ['', [Validators.email, Validators.required]],
website: ['']
});
this.payForm= fb.group({
session: ['', Validators.required]
});
this.userService.getCountries();
this.countriesUpdate.subscribe((countries) => {
this.countries = countries;
});
this.ownerUpdate.subscribe((owner) => {
this.owner = owner;
});
}
ngOnInit(): void {
}
ngAfterViewInit(): void {
this.ownerUpdate.subscribe(ownerData => {
if(ownerData.name.length > 0 && this.stepper!.selectedIndex == 0){
this.stepper!.next();
}
});
}
save() {
this.owner = {
address: '',
currency: 'usd',
tax: false,
taxValue: 0,
vat: false,
vatValue: 0,
phone: '',
paid: false,
name: this.bizForm.get('name')!.value,
street: this.bizForm.get('street')!.value,
city: this.bizForm.get('city')!.value,
state: this.bizForm.get('state')!.value,
postal: this.bizForm.get('postal')!.value,
country: this.bizForm.get('country')!.value,
email: this.bizForm.get('email')!.value,
website: this.bizForm.get('website')!.value
};
this.userService.addOwner(this.owner);
this.stepper!.next();
}
pay(){
const dialogConfig = new MatDialogConfig();
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.data = {
totalZec: this.payForm.get('session')!.value,
addr: this.nodeAddress,
session: this.sessionId,
pay: true
};
const dialogRef = this.dialog.open(ScanComponent, dialogConfig);
dialogRef.afterClosed().subscribe(val => {
console.log('Awaiting payment');
if(val){
this.stepper!.next();
}
});
}
}

View file

@ -172,7 +172,7 @@ export class LoginComponent implements OnInit, AfterViewInit {
});
if (this.txs.length > 0) {
this.barMode = 'determinate';
this.barValue = (this.txs[0].confirmations / 6) * 100;
this.barValue = (this.txs[0].confirmations / 2) * 100;
this.confirmedMemo = true;
this.barMessage = 'Login memo found, awaiting confirmations';
}
@ -187,7 +187,8 @@ export class LoginComponent implements OnInit, AfterViewInit {
dialogConfig.data = {
totalZec: 1e-8,
addr: this.nodeAddress,
session: this.localToken
session: this.localToken,
pay: false
};
const dialogRef = this.dialog.open(ScanComponent, dialogConfig);

View file

@ -1,5 +1,5 @@
<div align="center" mat-dialog-title>
<h4 class="text">Scan to connect your wallet</h4>
<h4 class="text">Scan the QR code</h4>
</div>
<mat-dialog-content>

View file

@ -17,17 +17,23 @@ export class ScanComponent implements OnInit{
total: number;
session: string;
codeString: string = '';
pay: boolean = false;
zcashUrl: SafeUrl;
constructor(
private dialogRef: MatDialogRef<ScanComponent>,
private sanitizer: DomSanitizer,
@Inject(MAT_DIALOG_DATA) public data: { totalZec: number, addr: string, session: string}
@Inject(MAT_DIALOG_DATA) public data: { totalZec: number, addr: string, session: string, pay: boolean}
) {
this.address = data.addr;
this.total = data.totalZec;
this.session = data.session;
this.codeString = `zcash:${this.address}?amount=${this.total.toFixed(8)}&memo=${URLSafeBase64.encode(Buffer.from('ZGO::'.concat(this.session)))}`;
this.pay = data.pay;
if (this.pay) {
this.codeString = `zcash:${this.address}?amount=${this.total.toFixed(8)}&memo=${URLSafeBase64.encode(Buffer.from('ZGOp::'.concat(this.session)))}`;
} else {
this.codeString = `zcash:${this.address}?amount=${this.total.toFixed(8)}&memo=${URLSafeBase64.encode(Buffer.from('ZGO::'.concat(this.session)))}`;
}
this.zcashUrl = this.sanitizer.bypassSecurityTrustUrl(this.codeString);
}

View file

@ -143,10 +143,12 @@ export class UserService{
}
addOwner(owner: Owner) {
owner.address = this.dataStore.user.address;
let obs = this.http.post<{message: string}>(this.beUrl+'api/addowner', {owner: owner}, {headers: this.reqHeaders});
obs.subscribe((responseData) => {
console.log(responseData.message);
this.getOwner(this.dataStore.user.address);
});
return obs;