PliWould/components/ProductCalculatorSelector.tsx

208 lines
5.8 KiB
TypeScript
Raw Normal View History

import { Product, productPriceFor } from '@/lib/product';
import { dimensions_t } from "@/lib/dimensions";
2024-07-01 04:49:41 +02:00
import { useState, useEffect } from 'react';
import { View, Text, StyleSheet } from 'react-native';
2024-07-01 04:49:41 +02:00
import { SafeAreaView } from 'react-native-safe-area-context';
import PriceDisplay from './Price';
import { AreaInput } from './AreaInput';
import { MeasurementInput } from './MeasurementInput';
2024-07-01 17:05:24 +02:00
import ProductList from './ProductList';
import UnitChooser from './UnitChooser';
import convert, { Length } from 'convert';
import PercentDamage from './PercentDamange';
2024-07-01 04:49:41 +02:00
export default function ProductCalculatorSelector() {
const [activeProduct, setActiveProduct] = useState(null as Product | null);
const [price, setPrice] = useState(0);
const [measurement, setMeasurement] = useState({ l: 0, w: 0, u: "ft" } as dimensions_t);
const [percentDamage, setPercentDamange] = useState(0.0);
2024-07-01 04:49:41 +02:00
useEffect(function () {
const iv = setInterval(function () {
if (!(activeProduct && measurement)) return;
setPrice(
productPriceFor(activeProduct, measurement, percentDamage)
2024-07-01 04:49:41 +02:00
)
}, 50);
return function () {
clearInterval(iv);
};
}, [activeProduct, measurement, percentDamage]);
2024-07-01 04:49:41 +02:00
function onMeasurementSet(dimensions: dimensions_t) {
setMeasurement(dimensions);
activeProduct && setPrice(
productPriceFor(activeProduct, measurement, percentDamage)
)
2024-07-01 04:49:41 +02:00
}
function onUnitChosen(unit: Length) {
2024-07-01 17:05:24 +02:00
setMeasurement({
...measurement,
u: unit,
});
}
function onSetPercentDamage(pct: number) {
setPercentDamange(pct);
}
function onProductSelected(product: Product) {
setActiveProduct(product);
setMeasurement(
{
l: convert(
product.dimensions.l,
product.dimensions.u,
).to(measurement.u),
u: measurement.u,
...(
("w" in measurement && "w" in product.dimensions) ? {
w: convert(
product.dimensions.w,
product.dimensions.u,
).to(measurement.u),
u: measurement.u,
} : {}
)
}
);
}
2024-07-01 04:49:41 +02:00
return (
<SafeAreaView style={styles.wrapper}>
<PriceDisplay price={price} />
<View style={styles.inputAndUnitWrapper}>
<View style={styles.inputWrapper}>
{
activeProduct ? (
"w" in activeProduct.dimensions ?
<AreaInput
2024-07-01 17:05:24 +02:00
defaultValue={activeProduct.dimensions}
2024-07-01 04:49:41 +02:00
onMeasurementSet={onMeasurementSet}
2024-07-01 17:05:24 +02:00
widthLabel='enter width'
lengthLabel='enter length'
units={measurement.u}
2024-07-01 04:49:41 +02:00
/>
:
<MeasurementInput
2024-07-01 17:05:24 +02:00
defaultValue={activeProduct.dimensions}
2024-07-01 04:49:41 +02:00
onValueSet={onMeasurementSet}
2024-07-01 17:05:24 +02:00
label="enter length"
units={measurement.u}
2024-07-01 04:49:41 +02:00
/>
) : (
<Text>Please select a product</Text>
)
}
2024-07-01 17:05:24 +02:00
{
activeProduct && <UnitChooser choices={["in", "ft"]} onChoicePressed={onUnitChosen} />
}
2024-07-01 04:49:41 +02:00
</View>
</View>
{activeProduct &&
(<View style={styles.damageWrapper}>
<PercentDamage
onSetPercentage={onSetPercentDamage}
/>
</View>)
}
<ProductList onProductSelected={onProductSelected} />
2024-07-01 04:49:41 +02:00
</SafeAreaView>
);
}
export const styles = StyleSheet.create({
wrapper: {
overflow: "scroll"
2024-07-01 04:49:41 +02:00
},
bigPriceWrapper: {
alignContent: "center",
},
bigPrice: {
alignSelf: "center",
fontSize: 40,
marginTop: 100,
marginBottom: 100,
},
inputWrapper: {
flexDirection: "row",
alignItems: "flex-start",
verticalAlign: "middle",
2024-07-01 04:49:41 +02:00
},
unitSelector: {
},
inputAndUnitWrapper: {
flexDirection: "row",
alignSelf: "center",
},
widthInput: {
width: 200,
borderWidth: 1,
borderRadius: 4,
borderColor: "grey",
padding: 4,
margin: 4,
fontSize: 30,
},
activeProduct: {
borderWidth: 2,
borderColor: "black",
borderStyle: "solid",
},
inactiveProduct: {
},
titleContainer: {
flexDirection: 'row',
gap: 8,
},
stepContainer: {
gap: 8,
marginBottom: 8,
},
reactLogo: {
height: 178,
width: 290,
bottom: 0,
left: 0,
},
productTileTouchable: {
margin: 10,
padding: 20,
backgroundColor: "grey",
},
productTileTouchableActive: {
borderWidth: 2,
borderStyle: "solid",
borderColor: "black",
margin: 10,
padding: 20,
},
productTileText: {
textAlign: "center",
color: "white",
},
productTileTextActive: {
textAlign: "center",
color: "black",
},
productTileCover: {
padding: 4,
},
damageWrapper: {
paddingVertical: 10,
paddingHorizontal: 10,
},
2024-07-01 04:49:41 +02:00
});