sozsoft-platform/ui/src/components/shared/BarcodeViewer.tsx
2026-09-21 22:53:48 +03:00

76 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect, useState } from 'react'
import classNames from 'classnames'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { writeBarcodeSvg, type BarcodeWriteFormat } from '@/utils/barcode'
export type BarcodeViewerProps = {
/** Barkoda çevrilecek veri. Form içinde kolona bağlanan alan budur. */
value?: string
format?: BarcodeWriteFormat
label?: string
/** Kodun altına okunabilir metni de basar. */
showText?: boolean
/** Modül (en ince çubuk) kalınlığı; büyüdükçe kod büyür. */
scale?: number
/** Kodu kapsayıcının genişliğine yayar; kapalıyken `scale` boyutu korunur. */
fitWidth?: boolean
className?: string
}
/**
* Herhangi bir veriyi barkod/QR olarak çizer. Tasarımcıdan sürüklenip bırakılan
* düğüm ve üretilen kod aynı bileşeni kullanır; `value` bir Form'un kaydına
* bağlandığında alan değiştikçe kod da yeniden çizilir.
*
* Kod SVG olarak üretilir: baskıda ve büyütmede kırılmaz, karanlık temada da
* okunabilir kalsın diye beyaz zemin üstünde çizilir.
*/
const BarcodeViewer = ({
value,
format = 'QRCode',
label,
showText = false,
scale = 4,
fitWidth = false,
className,
}: BarcodeViewerProps) => {
const { translate } = useLocalization()
const [svg, setSvg] = useState('')
const [error, setError] = useState('')
const text = value === undefined || value === null ? '' : String(value)
useEffect(() => {
let cancelled = false
void writeBarcodeSvg(text, { format, scale, showText }).then((result) => {
if (cancelled) return
setSvg(result.svg)
setError(result.error)
})
return () => {
cancelled = true
}
}, [text, format, scale, showText])
return (
<div className={className}>
{label && <label className="mb-1 block text-sm font-semibold">{label}</label>}
{!text ? (
<span className="text-sm opacity-70">{translate('::App.BarcodeViewer.NoValue')}</span>
) : error ? (
<span className="text-sm text-red-500">{error}</span>
) : (
<div
// zxing'in ürettiği SVG'dir, kullanıcı verisi değil: metin HRI içine
// kaçışlanarak yazılır, bu yüzden gömmek güvenlidir.
dangerouslySetInnerHTML={{ __html: svg }}
className={classNames(
'inline-block rounded bg-white p-2',
fitWidth && 'block w-full [&>svg]:h-auto [&>svg]:w-full',
)}
/>
)}
</div>
)
}
export default BarcodeViewer