Added the ability to have mutliple buy options for product

This commit is contained in:
Zakary Timson 2018-08-19 19:07:17 -04:00
parent 538c585cc1
commit d94df9f206
9 changed files with 268 additions and 197 deletions

View File

@ -6,8 +6,9 @@ import { MatDialog } from '@angular/material';
import { LoginComponent } from './login/login.component';
import { LocalStorage } from 'webstorage-decorators';
import { AppStore } from './app.store';
import { AngularFireAuth } from '../../node_modules/angularfire2/auth';
import { SwUpdate } from '../../node_modules/@angular/service-worker';
import { AngularFireAuth } from 'angularfire2/auth';
import { SwUpdate } from '@angular/service-worker';
import { POption } from './store/products/product';
@Component({
selector: 'app-root',
@ -15,7 +16,7 @@ import { SwUpdate } from '../../node_modules/@angular/service-worker';
})
export class AppComponent implements OnInit {
@LocalStorage({ defaultValue: [], encryptionKey: 'HmRoBFUEVWqW5uvy' })
cart: { id: string; item: string; price: number; currency: 'CAD' | 'USD'; quantity: number }[];
cart: { id: string; item: string; option: POption, quantity: number}[];
constructor(
private router: Router,
@ -30,8 +31,8 @@ export class AppComponent implements OnInit {
});
}
cartAdd(id: string, item: string, price: number, currency: 'CAD' | 'USD', quantity: number) {
this.cart = [{ id: id, item: item, price: Number(price), currency: currency, quantity: Number(quantity) }].concat(
cartAdd(id: string, name: string, option: POption, quantity: number) {
this.cart = [{ id: id, item: name, option: option, quantity: Number(quantity)}].concat(
this.cart
);
}

View File

@ -76,9 +76,8 @@ export class AppStore {
temp.originalImage = temp.image;
temp.image = this.domSanitizer.bypassSecurityTrustUrl(temp.image);
temp.originalDescription = temp.description;
temp.description = this.domSanitizer.bypassSecurityTrustHtml(
temp.description.replace(/(\r\n|\r|\n)/g, '<br>')
);
temp.description = this.domSanitizer.bypassSecurityTrustHtml(temp.description);
return <Product>temp;
})
),

View File

@ -1,7 +1,7 @@
import { Component, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { AngularFirestore } from 'angularfire2/firestore';
import {LocalStorage} from '../../../../node_modules/webstorage-decorators';
import { LocalStorage } from 'webstorage-decorators';
import { AppStore } from '../../app.store';
import { ConvertToGPipe } from '../units.pipe';

View File

@ -15,6 +15,7 @@ export class CartComponent {
constructor(public app: AppComponent) {}
ngOnInit() {
console.log(this.app.cart);
if (this.app.cartCount()) {
window['paypal'].Button.render(
{

View File

@ -13,20 +13,52 @@
<mat-form-field class="w-100">
<textarea matInput rows="5" placeholder="Description" name="description" [(ngModel)]="description"></textarea>
</mat-form-field>
<div class="mt-3 p-3 border rounded border-muted">
<h5 mat-subheader class="mb-4 pl-0">Buying Options</h5>
<button mat-stroked-button class="mb-4" color="accent" (click)="addOption()">Add</button>
<mat-accordion>
<mat-expansion-panel *ngFor="let o of options; let i = index">
<mat-expansion-panel-header>
<mat-panel-title>
{{o.name || 'Option'}}
</mat-panel-title>
<mat-panel-description>
{{o.currency}} {{o.price | currency}}
</mat-panel-description>
</mat-expansion-panel-header>
<div class="row">
<div class="col-4">
<mat-form-field>
<input matInput placeholder="Name" [(ngModel)]="o.name">
</mat-form-field>
</div>
<div class="col-4 text-center">
<mat-form-field>
<span matPrefix>$&nbsp;</span>
<input matInput placeholder="Price" type="number" name="price" [(ngModel)]="price">
<input matInput placeholder="Price" type="number" name="price" [(ngModel)]="o.price">
<mat-hint *ngIf="!price" align="start">0 will display "Contact For Price"</mat-hint>
</mat-form-field>
<mat-radio-group [(ngModel)]="currency" name="currency">
<mat-radio-group [(ngModel)]="o.currency" name="currency">
<mat-radio-button value="CAD" class="pl-3">CAD</mat-radio-button>
<mat-radio-button value="USD" class="pl-3">USD</mat-radio-button>
</mat-radio-group>
<input #fileInput type="file" (change)="imageChanged($event)" hidden>
</div>
<div class="col-4">
<mat-form-field class="float-right" style="width: 150px">
<input matInput type="number" placeholder="Weight For Shipping" [(ngModel)]="weight">
<input matInput type="number" placeholder="Weight For Shipping" [(ngModel)]="o.weight">
<span matSuffix>lb</span>
</mat-form-field>
</div>
</div>
<input #fileInput type="file" (change)="imageChanged($event)" hidden>
<mat-action-row>
<button mat-button color="warn" (click)="options.splice(i, 1)">
Delete
</button>
</mat-action-row>
</mat-expansion-panel>
</mat-accordion>
</div>
<div class="mt-3 p-3 border rounded border-muted">
<h5 mat-subheader class="pl-0">Uploads</h5>
<mat-progress-bar *ngIf="uploading" mode="indeterminate"></mat-progress-bar>

View File

@ -2,7 +2,7 @@ import {Component, Inject} from '@angular/core';
import { AngularFirestore } from 'angularfire2/firestore';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { AppStore } from '../../app.store';
import {AngularFireStorage} from '../../../../node_modules/angularfire2/storage';
import { AngularFireStorage } from 'angularfire2/storage';
@Component({
selector: 'new-item',
@ -10,14 +10,12 @@ import {AngularFireStorage} from '../../../../node_modules/angularfire2/storage'
})
export class NewProductComponent {
category;
currency = 'CAD';
description: string;
files: { name: string; link: string; type: string }[] = [];
image: string;
linkError = false;
name: string;
price: number = 0.0;
weight: number = 0;
options: { name: string, price: number, currency: 'CAD' | 'USD', weight: number }[] = [];
uploading = false;
constructor(
@ -31,12 +29,12 @@ export class NewProductComponent {
if (data.product) {
this.category = data.product.category;
this.currency = data.product.currency;
this.description = data.product.originalDescription;
this.files = data.product.files;
this.name = data.product.name;
this.price = data.product.price;
this.weight = data.product.weight;
this.options = data.product.options;
} else {
this.addOption();
}
}
@ -64,6 +62,10 @@ export class NewProductComponent {
return !!valid;
}
addOption() {
this.options.push({ name: '', price: 0, currency: 'CAD', weight: 0 });
}
imageChanged(event) {
let reader = new FileReader();
reader.readAsDataURL(event.target.files[0]);
@ -73,12 +75,14 @@ export class NewProductComponent {
submit() {
let newProduct = {
category: this.category,
currency: this.currency,
description: this.description,
files: this.files,
name: this.name,
price: Number(this.price),
weight: Number(this.weight) || 0
options: this.options.map(row => {
row.price = <number>row.price;
row.weight = <number>row.weight;
return row;
})
};
if (this.image) newProduct['image'] = this.image;

View File

@ -0,0 +1,25 @@
import { SafeUrl, SafeHtml } from "@angular/platform-browser";
export interface PFile {
link: string;
name: string;
type: 'link' | 'other' | 'preview';
}
export interface POption {
currency: 'CAD' | 'USD';
name: string;
price: number;
weight: number;
}
export interface Product {
category: string;
description: string | SafeHtml;
files: any[]
image: string | SafeUrl;
name: string;
options: POption[];
originalDescription: string;
originalImage: string;
}

View File

@ -16,18 +16,26 @@
</div>
<div class="col-12 col-md-9">
<h2 class="roboto">{{product.name}}</h2>
<h5 *ngIf="product.price" class="text-muted">{{product.currency}} {{product.price | currency}}</h5>
<h5 *ngIf="!product.price" class="text-muted">Contact For Price</h5>
<mat-divider class="my-3"></mat-divider>
<p style="overflow: hidden;" [innerHtml]="product.description"></p>
<div class="float-right">
<mat-form-field *ngIf="product.options.length > 1">
<mat-select placeholder="Buying Options" [(ngModel)]="option">
<mat-option *ngFor="let o of product.options" [value]="o">
{{o.name}} <span class="float-right text-muted">{{o.currency}} {{o.price | currency}}</span>
</mat-option>
</mat-select>
</mat-form-field>
<div class="d-inline ml-3">
<mat-form-field class="mr-1" style="width: 40px">
<span matPrefix>x</span>
<input #quantity matInput type="number" value="1" min="1">
</mat-form-field>
<button mat-raised-button color="primary" [disabled]="quantity.value < 1" (click)="app.cartAdd(product.id, product.name, product.price, product.currency, quantity.value)">
<button mat-raised-button color="primary" [disabled]="quantity.value < 1" (click)="app.cartAdd(product.id, product.name, option, quantity.value)">
<mat-icon>add_shopping_cart</mat-icon> Buy
</button>
</div>
<h5 *ngIf="product.options.length == 1 && product.options[0].price > 0" class="text-muted">{{product.options[0].currency}} {{product.options[0].price | currency}}</h5>
<h5 *ngIf="product.options.length == 1 && product.options[0].price == 0" class="text-muted">Contact For Price</h5>
<mat-divider class="my-3"></mat-divider>
<p style="overflow: hidden;" [innerHtml]="product.description"></p>
<mat-divider class="my-3"></mat-divider>
<div *ngIf="attachments?.length">
<h5 class="ml-3">

View File

@ -4,7 +4,7 @@ import {AppComponent} from '../../app.component';
import { map } from 'rxjs/operators';
import { AppStore } from '../../app.store';
import { Product } from '../product';
import {SafeUrl, DomSanitizer} from '../../../../node_modules/@angular/platform-browser';
import { SafeUrl, DomSanitizer } from '@angular/platform-browser';
@Component({
selector: 'products',
@ -15,6 +15,7 @@ export class ProductsComponent {
preview: SafeUrl[];
links: { name: string; link: string; type: string }[];
attachments: { name: string; link: string; type: string }[];
option;
constructor(
private store: AppStore,