feat: barcode templates

This commit is contained in:
2024-05-09 21:29:48 +03:00
parent 05ef4afce8
commit d82b23fbe9
19 changed files with 247 additions and 53 deletions

View File

@@ -0,0 +1,63 @@
import {BarcodeAttributeSchema} from "../../client";
import {forwardRef} from "react";
import styles from "./PrintBarcodeModal.module.css";
import {Flex, Text} from "@mantine/core";
import Barcode from "react-barcode";
type Props = {
attributes: BarcodeAttributeSchema[]
barcode?: string;
quantity: number;
}
type Ref = HTMLDivElement;
const PrintBarcodeContainer = forwardRef<Ref, Props>(function PrintBarcodeContainer(props: Props, ref) {
const {attributes, barcode, quantity} = props;
const MAX_ATTRIBUTES = 6;
const MIN_BARCODE_SIZE = 30;
const MAX_BARCODE_SIZE = 100;
const STEP = (MAX_BARCODE_SIZE - MIN_BARCODE_SIZE) / MAX_ATTRIBUTES;
const MAX_ATTRIBUTE_LENGTH = 35;
const getBarcodeHeight = () => {
return MIN_BARCODE_SIZE + (MAX_ATTRIBUTES - attributes.length) * STEP;
}
const getAttributeText = (attribute: BarcodeAttributeSchema) => {
let result = `${attribute.name}: ${attribute.value}`;
if (result.length > MAX_ATTRIBUTE_LENGTH) {
result = result.slice(0, MAX_ATTRIBUTE_LENGTH - 1) + ".";
}
return result;
}
return (
<div className={styles['print-only']} ref={ref}>
{barcode && Array.from({length: quantity}).map((_, index) => (
<>
<Flex
className={styles['barcode-container']}
key={index}
justify={"center"}
direction={"column"}
>
<Flex align={"center"} justify={"center"}>
<Barcode margin={0} height={getBarcodeHeight()} value={barcode}/>
</Flex>
{attributes.slice(0, MAX_ATTRIBUTES).map((attr) => (
<Text
key={attr.name}
className={styles['barcode-attribute-text']}
size={"xs"}
>
{getAttributeText(attr)}
</Text>
))}
</Flex>
</>
))}
</div>
)
});
export default PrintBarcodeContainer;

View File

@@ -6,4 +6,16 @@
.print-only {
display: block;
}
.barcode-container {
text-align: left;
margin: 1.25mm;
padding: 1.25mm;
background-color: white;
}
.barcode-attribute-text {
line-height: 1;
}
}

View File

@@ -1,12 +1,11 @@
import {ContextModalProps, modals} from "@mantine/modals";
import {Button, Divider, Flex, NumberInput, rem, Select, Spoiler} from "@mantine/core";
import Barcode from "react-barcode";
import {Button, Divider, Flex, NumberInput, rem, Select} from "@mantine/core";
import {useEffect, useRef, useState} from "react";
import {useReactToPrint} from "react-to-print";
import {ProductService} from "../../client";
import styles from "./PrintBarcodeModal.module.css";
import {BarcodeSchema, ProductService} from "../../client";
import {useGetProductById} from "../../api/product/useGetProductById.tsx";
import {notifications} from "../../shared/lib/notifications.ts";
import PrintBarcodeContainer from "./PrintBarcodeContainer.tsx";
type Props = {
productId: number;
@@ -18,6 +17,7 @@ const PrintBarcodeModal = ({
const {productId, defaultQuantity = 1} = innerProps;
const [quantity, setQuantity] = useState(defaultQuantity);
const [barcode, setBarcode] = useState<string | undefined>()
const [barcodeData, setBarcodeData] = useState<BarcodeSchema | undefined>();
const {product, refetch} = useGetProductById(productId);
@@ -55,11 +55,26 @@ const PrintBarcodeModal = ({
setBarcode(barcode);
})
}
const fetchBarcodeData = () => {
if (!barcode) return;
ProductService.getProductBarcode({
requestBody:
{barcode, productId}
}).then(({barcode}) => {
setBarcodeData(barcode);
})
}
useEffect(() => {
if (!product) return;
if (product.barcodes.length === 1)
setBarcode(product.barcodes[0]);
}, [product]);
useEffect(() => {
if (!barcode) return;
fetchBarcodeData();
}, [barcode]);
return (
<>
<Flex
@@ -80,21 +95,7 @@ const PrintBarcodeModal = ({
onChange={(value) => typeof value === "number" && setQuantity(value)}
min={1}
/>
<Spoiler
w={"100%"}
style={{
textAlign: "center",
}}
styles={{control: {width: "100%"}}}
showLabel={"Показать предпросмотр"}
hideLabel={"Скрыть предпросмотр"}
maxHeight={0}>
<div>
{barcode &&
<Barcode value={barcode}/>
}
</div>
</Spoiler>
<Divider
my={rem(10)}
/>
@@ -120,11 +121,13 @@ const PrintBarcodeModal = ({
>Печать</Button>
</Flex>
</Flex>
<div className={styles['print-only']} ref={barcodeRef}>
{barcode && Array.from({length: quantity}).map((_, index) => (
<Barcode key={index} value={barcode}/>
))}
</div>
<PrintBarcodeContainer
barcode={barcode}
quantity={quantity}
ref={barcodeRef}
attributes={barcodeData?.attributes || []}
/>
</>
)
}