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 attributesAsList() { return Object.entries(this.attributes).map(([key, value]) => { return { key, value } }) } public removeAttribute(key: string) { delete this.attributes[key]; } }