111 lines
3.2 KiB
TypeScript
111 lines
3.2 KiB
TypeScript
import uuid from "react-native-uuid";
|
|
import convert, { Area, Length } from "convert";
|
|
|
|
export type Id = string;
|
|
|
|
export type Currency = "USD";
|
|
|
|
export type ProductAttributes = {
|
|
id?: string,
|
|
name?: string,
|
|
image?: string,
|
|
description?: string,
|
|
depth?: string,
|
|
currency?: Currency,
|
|
// [index:string]: any,
|
|
}
|
|
|
|
export type ProductData = {
|
|
id?: Id,
|
|
pricePerUnit: number,
|
|
measurement: {
|
|
unit: string,
|
|
value: number,
|
|
dimension: number,
|
|
},
|
|
attributes?: ProductAttributes,
|
|
};
|
|
|
|
export type length_t = {
|
|
l: number, u: Length
|
|
}
|
|
|
|
export type area_t = length_t & {
|
|
w: number,
|
|
}
|
|
|
|
export type dimensions_t = area_t | length_t;
|
|
|
|
export type product_type_t = "area" | "length";
|
|
|
|
export const isArea = (d: dimensions_t) => ("width" in d);
|
|
export const isLength = (d: dimensions_t) => (!("width" in d));
|
|
export const dimensionType = (d: dimensions_t) => isArea(d) ? "area" : "length"
|
|
|
|
export class Product {
|
|
public id: string;
|
|
public area?: area_t;
|
|
public length?: length_t;
|
|
public presentUnits: Length;
|
|
|
|
constructor(public pricePerUnit: number, dimensions: dimensions_t, public attributes: ProductAttributes = {},) {
|
|
this.id = attributes.id || uuid.v4().toString();
|
|
this.presentUnits = dimensions.u;
|
|
if ("w" in dimensions) {
|
|
this.area = {
|
|
l: convert(dimensions.l, dimensions.u).to("meter"),
|
|
w: convert(dimensions.w, dimensions.u).to("meter"),
|
|
u: "meter"
|
|
}
|
|
} else {
|
|
this.length = {
|
|
l: convert(dimensions.l, dimensions.u).to("meter"),
|
|
u: "meter"
|
|
};
|
|
}
|
|
}
|
|
|
|
public priceFor(dimensions: dimensions_t): number {
|
|
if (this.area && "w" in dimensions) {
|
|
const thisA = this.area.l * this.area.w;
|
|
const otherA = convert(
|
|
dimensions.w,
|
|
dimensions.u
|
|
).to("meter") * convert(
|
|
dimensions.l,
|
|
dimensions.u
|
|
).to("meter");
|
|
return (otherA / thisA) * this.pricePerUnit;
|
|
} if (this.length) {
|
|
const thisL = this.length.l;
|
|
const otherL = convert(
|
|
dimensions.l,
|
|
dimensions.u
|
|
).to("meter");
|
|
return (otherL / thisL) * this.pricePerUnit;
|
|
}
|
|
throw new Error(`Invalid dimensions: ${dimensions}`);
|
|
}
|
|
|
|
get priceDisplay() {
|
|
const u = this.presentUnits;
|
|
if (this.area) {
|
|
const w = Math.round(convert(this.area.w, this.area.u).to(this.presentUnits));
|
|
const l = Math.round(convert(this.area.l, this.area.u).to(this.presentUnits));
|
|
return `$ ${this.pricePerUnit} / ${l} x ${w} ${u}`;
|
|
} else if (this.length) {
|
|
const l = Math.round(convert(this.length.l, this.length.u).to(this.presentUnits));
|
|
return `$ ${this.pricePerUnit} per ${l} ${u}`;
|
|
}
|
|
}
|
|
|
|
get attributesAsList() {
|
|
return Object.entries(this.attributes).map(([key, value]) => {
|
|
return { key, value }
|
|
})
|
|
}
|
|
|
|
public removeAttribute(key: string) {
|
|
delete this.attributes[key];
|
|
}
|
|
} |