63 lines
2.2 KiB
JavaScript
63 lines
2.2 KiB
JavaScript
/**
|
||
* @file PickupCodeBarcode.jsx
|
||
* @description Штрих-код для кода выдачи (самовывоз) в карточке доставки клиента.
|
||
*
|
||
* Рисуется SVG-ом на клиенте, без картинок и внешних библиотек: PWA работает офлайн,
|
||
* а на печати и на экране полосы остаются резкими при любом размере.
|
||
* Значение — тот же код выдачи, который клиент называет вслух.
|
||
*/
|
||
import React from "react";
|
||
|
||
import { code128Bars } from "./barcodeCode128";
|
||
|
||
/** Тихая зона по стандарту — не меньше 10 модулей с каждой стороны. */
|
||
const QUIET_ZONE_MODULES = 10;
|
||
|
||
/** Высота полос и подписи в «единицах» viewBox — масштабируется вместе с SVG. */
|
||
const BAR_HEIGHT = 56;
|
||
const TEXT_HEIGHT = 18;
|
||
|
||
export const PickupCodeBarcode = ({ value, showText = true, className = "" }) => {
|
||
const code = String(value ?? "").trim();
|
||
if (!code) return null;
|
||
|
||
const bars = code128Bars(code);
|
||
const modules = bars.reduce((sum, bar) => sum + bar.width, 0);
|
||
const width = modules + QUIET_ZONE_MODULES * 2;
|
||
const height = BAR_HEIGHT + (showText ? TEXT_HEIGHT : 0);
|
||
|
||
let x = QUIET_ZONE_MODULES;
|
||
const rects = [];
|
||
bars.forEach((bar, index) => {
|
||
if (bar.black) {
|
||
rects.push(<rect key={index} x={x} y="0" width={bar.width} height={BAR_HEIGHT} fill="#000000" />);
|
||
}
|
||
x += bar.width;
|
||
});
|
||
|
||
return (
|
||
<svg
|
||
role="img"
|
||
aria-label={`Штрих-код кода выдачи ${code}`}
|
||
viewBox={`0 0 ${width} ${height}`}
|
||
className={["block h-auto", className].join(" ").trim()}
|
||
preserveAspectRatio="xMidYMid meet"
|
||
>
|
||
<rect x="0" y="0" width={width} height={height} fill="#ffffff" />
|
||
{rects}
|
||
{showText ? (
|
||
<text
|
||
x={width / 2}
|
||
y={BAR_HEIGHT + 14}
|
||
textAnchor="middle"
|
||
fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace"
|
||
fontSize="13"
|
||
fill="#000000"
|
||
>
|
||
{code}
|
||
</text>
|
||
) : null}
|
||
</svg>
|
||
);
|
||
};
|