PliWould/lib/product.ts
2024-06-28 17:04:30 -07:00

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];
}
}