Merge branch 'release/2.17.0'
This commit is contained in:
31
CHANGELOG.md
Normal file
31
CHANGELOG.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [2.17.0] - 2025-12-21
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- **PDF417 Barcode Generation**: Reverted from zxing-wasm library to pure JavaScript implementation due to barcode scanner compatibility issues. The barcodes generated by the zxing-wasm library were unreadable by scanners at "Tisak" kiosks in Croatia. The legacy custom PDF417 generator now ensures better compatibility with retail payment scanning infrastructure.
|
||||||
|
|
||||||
|
### Technical Details
|
||||||
|
- Restored `app/lib/pdf/pdf417.ts` - Custom PDF417 generator library
|
||||||
|
- Restored `app/lib/pdf/renderBarcode.ts` - Canvas-based barcode renderer
|
||||||
|
- Restored `app/ui/Pdf417Barcode.tsx` - React component using custom generator
|
||||||
|
- Updated all components to use legacy `Pdf417Barcode` instead of `Pdf417BarcodeWasm`
|
||||||
|
|
||||||
|
## [2.16.1] - 2025-12-20
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Minor bug fixes and improvements
|
||||||
|
|
||||||
|
## [2.16.0] - 2025-12-20
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Initial zxing-wasm integration for PDF417 barcode generation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
For older versions, please refer to git commit history.
|
||||||
1053
app/lib/pdf/pdf417.ts
Normal file
1053
app/lib/pdf/pdf417.ts
Normal file
File diff suppressed because it is too large
Load Diff
51
app/lib/pdf/renderBarcode.ts
Normal file
51
app/lib/pdf/renderBarcode.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import { BarcodeArray } from './pdf417';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a PDF417 barcode matrix to a canvas and returns it as a data URL.
|
||||||
|
*
|
||||||
|
* This function creates an HTML canvas element, draws the barcode by iterating through
|
||||||
|
* the barcode matrix, and converts the canvas to a base64-encoded PNG data URL that
|
||||||
|
* can be used as an image source.
|
||||||
|
*
|
||||||
|
* @param barcodeMatrix - The barcode array generated by the PDF417 encoder containing
|
||||||
|
* the barcode matrix data with dimensions and binary code values
|
||||||
|
* @param blockWidth - The width in pixels of each individual barcode module (bar/space unit)
|
||||||
|
* @param blockHeight - The height in pixels of each individual barcode module (bar/space unit)
|
||||||
|
*
|
||||||
|
* @returns A data URL string (base64-encoded PNG) representing the rendered barcode image,
|
||||||
|
* suitable for use in an HTML img src attribute
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* const pdf417 = createPDF417();
|
||||||
|
* pdf417.init("Hello World", 2, 2);
|
||||||
|
* const barcodeArray = pdf417.getBarcodeArray();
|
||||||
|
* const dataUrl = renderBarcode(barcodeArray, 2, 4);
|
||||||
|
* // dataUrl can now be used: <img src={dataUrl} />
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function renderBarcode(barcodeMatrix: BarcodeArray, blockWidth: number, blockHeight: number) {
|
||||||
|
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = barcodeMatrix.num_cols * blockWidth;
|
||||||
|
canvas.height = barcodeMatrix.num_rows * blockHeight;
|
||||||
|
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||||
|
|
||||||
|
let positionY = 0;
|
||||||
|
for (let row = 0; row < barcodeMatrix.num_rows; row += 1) {
|
||||||
|
let positionX = 0;
|
||||||
|
|
||||||
|
for (let col = 0; col < barcodeMatrix.num_cols; col += 1) {
|
||||||
|
if (barcodeMatrix.bcode[row][col] === 1) {
|
||||||
|
ctx.fillStyle = '#000';
|
||||||
|
} else {
|
||||||
|
ctx.fillStyle = '#FFF';
|
||||||
|
}
|
||||||
|
ctx.fillRect(positionX, positionY, blockWidth, blockHeight);
|
||||||
|
positionX += blockWidth;
|
||||||
|
}
|
||||||
|
positionY += blockHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return canvas.toDataURL();
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import { formatYearMonth } from "../lib/format";
|
|||||||
import { DecodeResult, findDecodePdf417 } from "../lib/pdf/barcodeDecoderWasm";
|
import { DecodeResult, findDecodePdf417 } from "../lib/pdf/barcodeDecoderWasm";
|
||||||
import { useLocale, useTranslations } from "next-intl";
|
import { useLocale, useTranslations } from "next-intl";
|
||||||
import { InfoBox } from "./InfoBox";
|
import { InfoBox } from "./InfoBox";
|
||||||
import { Pdf417BarcodeWasm } from "./Pdf417BarcodeWasm";
|
import { Pdf417Barcode } from "./Pdf417Barcode";
|
||||||
|
|
||||||
// Next.js does not encode an utf-8 file name correctly when sending a form with a file attachment
|
// Next.js does not encode an utf-8 file name correctly when sending a form with a file attachment
|
||||||
// This is a workaround for that
|
// This is a workaround for that
|
||||||
@@ -203,7 +203,7 @@ export const BillEditForm: FC<BillEditFormProps> = ({ location, bill }) => {
|
|||||||
hub3aText ?
|
hub3aText ?
|
||||||
<div className="form-control p-1">
|
<div className="form-control p-1">
|
||||||
<label className="label p-2 grow bg-white border border-gray-300 rounded-box justify-center">
|
<label className="label p-2 grow bg-white border border-gray-300 rounded-box justify-center">
|
||||||
<Pdf417BarcodeWasm hub3aText={hub3aText} />
|
<Pdf417Barcode hub3aText={hub3aText} />
|
||||||
</label>
|
</label>
|
||||||
<p className="text-xs my-1">{t.rich('barcode-disclaimer', { br: () => <br /> })}</p>
|
<p className="text-xs my-1">{t.rich('barcode-disclaimer', { br: () => <br /> })}</p>
|
||||||
</div> : null
|
</div> : null
|
||||||
|
|||||||
33
app/ui/Pdf417Barcode.tsx
Normal file
33
app/ui/Pdf417Barcode.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState, useEffect, FC } from 'react';
|
||||||
|
import { generateBarcode } from '../lib/pdf/pdf417';
|
||||||
|
import { renderBarcode } from '../lib/pdf/renderBarcode';
|
||||||
|
|
||||||
|
export const Pdf417Barcode:FC<{hub3aText:string, className?: string, errorCorrectionLevel?: number}> = ({ hub3aText: hub3a_text, className, errorCorrectionLevel = 3}) => {
|
||||||
|
const [bitmapData, setBitmapData] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
|
console.log("Rendering Pdf417Barcode with hub3a_text:", hub3a_text);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const aspectRatio = 3;
|
||||||
|
|
||||||
|
const barcodeMatrix = generateBarcode(hub3a_text, errorCorrectionLevel , aspectRatio);
|
||||||
|
const bitmap = renderBarcode(barcodeMatrix, 1, 1);
|
||||||
|
setBitmapData(bitmap);
|
||||||
|
}, [hub3a_text]);
|
||||||
|
|
||||||
|
// Don't render until bitmap is generated (prevents hydration mismatch)
|
||||||
|
if (!bitmapData) {
|
||||||
|
return (
|
||||||
|
<div style={{ width: "350px", height: "92px" }} className="flex items-center justify-center">
|
||||||
|
<span className="loading loading-spinner loading-lg"></span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
// eslint-disable-next-line @next/next/no-img-element
|
||||||
|
<img src={bitmapData} alt="PDF417 Barcode" className={className} />
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { PrintBarcodeData } from '../lib/actions/printActions';
|
import { PrintBarcodeData } from '../lib/actions/printActions';
|
||||||
import { Pdf417BarcodeWasm } from './Pdf417BarcodeWasm';
|
import { Pdf417Barcode } from './Pdf417Barcode';
|
||||||
|
|
||||||
export interface PrintPreviewProps {
|
export interface PrintPreviewProps {
|
||||||
data: PrintBarcodeData[];
|
data: PrintBarcodeData[];
|
||||||
@@ -132,7 +132,7 @@ export const PrintPreview: React.FC<PrintPreviewProps> = ({ data, year, month, t
|
|||||||
<td className="border-2 border-gray-800 px-3 py-1.5 text-center">
|
<td className="border-2 border-gray-800 px-3 py-1.5 text-center">
|
||||||
<div className="flex justify-center items-center">
|
<div className="flex justify-center items-center">
|
||||||
{
|
{
|
||||||
item.hub3aText ? <Pdf417BarcodeWasm hub3aText={item.hub3aText} className="print:m-[5em_auto]" /> : null
|
item.hub3aText ? <Pdf417Barcode hub3aText={item.hub3aText} /> : null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useRouter } from "next/navigation";
|
|||||||
import { formatYearMonth } from "../lib/format";
|
import { formatYearMonth } from "../lib/format";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { uploadProofOfPayment } from "../lib/actions/billActions";
|
import { uploadProofOfPayment } from "../lib/actions/billActions";
|
||||||
import { Pdf417BarcodeWasm } from "./Pdf417BarcodeWasm";
|
import { Pdf417Barcode } from "./Pdf417Barcode";
|
||||||
|
|
||||||
export interface ViewBillCardProps {
|
export interface ViewBillCardProps {
|
||||||
location: BillingLocation;
|
location: BillingLocation;
|
||||||
@@ -111,7 +111,7 @@ export const ViewBillCard: FC<ViewBillCardProps> = ({ location, bill, shareId })
|
|||||||
hub3aText ?
|
hub3aText ?
|
||||||
<div className="form-control p-1">
|
<div className="form-control p-1">
|
||||||
<label className="label p-2 grow bg-white border border-gray-300 rounded-box justify-center">
|
<label className="label p-2 grow bg-white border border-gray-300 rounded-box justify-center">
|
||||||
<Pdf417BarcodeWasm hub3aText={hub3aText} />
|
<Pdf417Barcode hub3aText={hub3aText} />
|
||||||
</label>
|
</label>
|
||||||
<p className="text-xs my-1">{t.rich('barcode-disclaimer', { br: () => <br /> })}</p>
|
<p className="text-xs my-1">{t.rich('barcode-disclaimer', { br: () => <br /> })}</p>
|
||||||
</div> : null
|
</div> : null
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { LinkIcon } from "@heroicons/react/24/outline";
|
|||||||
import { uploadUtilBillsProofOfPayment } from "../lib/actions/locationActions";
|
import { uploadUtilBillsProofOfPayment } from "../lib/actions/locationActions";
|
||||||
import QRCode from "react-qr-code";
|
import QRCode from "react-qr-code";
|
||||||
import { TicketIcon } from "@heroicons/react/24/solid";
|
import { TicketIcon } from "@heroicons/react/24/solid";
|
||||||
import { Pdf417BarcodeWasm } from "./Pdf417BarcodeWasm";
|
import { Pdf417Barcode } from "./Pdf417Barcode";
|
||||||
|
|
||||||
export interface ViewLocationCardProps {
|
export interface ViewLocationCardProps {
|
||||||
location: BillingLocation;
|
location: BillingLocation;
|
||||||
@@ -153,7 +153,7 @@ export const ViewLocationCard: FC<ViewLocationCardProps> = ({ location, userSett
|
|||||||
<li><strong>{t("payment-reference-label")}</strong><pre className="inline pl-1">{paymentParams.PozivNaBroj}</pre></li>
|
<li><strong>{t("payment-reference-label")}</strong><pre className="inline pl-1">{paymentParams.PozivNaBroj}</pre></li>
|
||||||
</ul>
|
</ul>
|
||||||
<label className="label p-2 grow bg-white border border-gray-300 rounded-box justify-center">
|
<label className="label p-2 grow bg-white border border-gray-300 rounded-box justify-center">
|
||||||
<Pdf417BarcodeWasm hub3aText={hub3aText} />
|
<Pdf417Barcode hub3aText={hub3aText} />
|
||||||
</label>
|
</label>
|
||||||
</>
|
</>
|
||||||
: null
|
: null
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "evidencija-rezija",
|
"name": "evidencija-rezija",
|
||||||
"version": "2.16.1",
|
"version": "2.17.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"version": "2.16.1",
|
"version": "2.17.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.1",
|
"@emotion/styled": "^11.14.1",
|
||||||
|
|||||||
@@ -58,5 +58,5 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.17.0"
|
"node": ">=18.17.0"
|
||||||
},
|
},
|
||||||
"version": "2.16.1"
|
"version": "2.17.0"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user