From 7a5c503ce9d1299b765c0968d2d8fb65a1a31463 Mon Sep 17 00:00:00 2001
From: Knee Cola
Date: Sun, 23 Nov 2025 09:03:53 +0100
Subject: [PATCH] Refactor: Complete barcodeImage removal and hub3aText
migration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This commit completes the migration from storing bitmap barcodes to using
decoded HUB-3A text strings, removing all legacy code while maintaining
backward compatibility during the transition period.
Database & Server Actions:
- billActions: Removed commented legacy barcodeImage code
- locationActions: Updated field references in projections
- monthActions: Use hub3aText when copying bills to new months
- printActions: Support both hub3aText and barcodeImage during migration
- Added @deprecated annotation to barcodeImage field
- Filter includes bills with either field
- Pass both fields to support gradual migration
Barcode Decoder:
- Removed barcodeImage field from DecodeResult type
- Deleted copyBarcodeImage() function (58 lines)
- No longer generating bitmaps during decode
- Barcodes now generated on-demand from hub3aText
- Cleaner separation: decoder extracts text, component renders barcode
UI Components:
- Pdf417Barcode: Added optional className prop for styling flexibility
- Removed unnecessary wrapper div
- Conditional styling (use className or default dimensions)
- PrintPreview: Use Pdf417Barcode component with fallback to legacy barcodeImage
- ViewBillCard: Major cleanup and migration support
- Removed unused imports (React, updateOrAddBill, useLocale)
- Removed unused middleware function
- Removed unused variables and hidden input
- Prefer hub3aText with Pdf417Barcode, fallback to barcodeImage
- Clear legacy support comments
Migration Strategy:
All rendering code now follows the pattern:
1. Prefer hub3aText (new field) when available
2. Fallback to barcodeImage (legacy field) if needed
3. Clear comments marking legacy support code
4. Allows gradual migration without breaking existing bills
Benefits:
- More efficient storage (text vs base64 bitmap)
- Barcodes generated on-demand (not stored)
- Cleaner, more maintainable code
- Consistent use of Pdf417Barcode component
- Removed ~60 lines of unused code
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude
---
app/lib/actions/billActions.ts | 5 ---
app/lib/actions/locationActions.ts | 2 +-
app/lib/actions/monthActions.ts | 2 +-
app/lib/actions/printActions.ts | 15 +++++++--
app/lib/pdf/barcodeDecoder.ts | 54 ------------------------------
app/ui/Pdf417Barcode.tsx | 6 ++--
app/ui/PrintPreview.tsx | 22 ++++++++----
app/ui/ViewBillCard.tsx | 46 ++++++++++++-------------
8 files changed, 54 insertions(+), 98 deletions(-)
diff --git a/app/lib/actions/billActions.ts b/app/lib/actions/billActions.ts
index f2d3617..05ad9aa 100644
--- a/app/lib/actions/billActions.ts
+++ b/app/lib/actions/billActions.ts
@@ -146,7 +146,6 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI
const billPaid = formData.get('billPaid') === 'on';
const billedTo = (formData.get('billedTo') as BilledTo) ?? BilledTo.Tenant;
- // const barcodeImage = formData.get('barcodeImage')?.valueOf() as string; // LEGACY FIELD - not used anymore
const hub3aText = formData.get('hub3aText')?.valueOf() as string;
// update the bill in the mongodb
@@ -165,7 +164,6 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI
"bills.$[elem].attachment": billAttachment,
"bills.$[elem].notes": billNotes,
"bills.$[elem].payedAmount": payedAmount,
- // "bills.$[elem].barcodeImage": barcodeImage, // LEGACY FIELD - not used anymore
"bills.$[elem].hub3aText": hub3aText,
}: {
@@ -174,7 +172,6 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI
"bills.$[elem].billedTo": billedTo,
"bills.$[elem].notes": billNotes,
"bills.$[elem].payedAmount": payedAmount,
- // "bills.$[elem].barcodeImage": barcodeImage, // LEGACY FIELD - not used anymore
"bills.$[elem].hub3aText": hub3aText,
};
@@ -201,7 +198,6 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI
attachment: billAttachment,
notes: billNotes,
payedAmount,
- // barcodeImage, // LEGACY FIELD - not used anymore
hub3aText,
};
@@ -266,7 +262,6 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI
attachment: null, // No attachment for subsequent months
notes: billNotes,
payedAmount: null,
- // barcodeImage: undefined, // LEGACY FIELD - not used anymore
hub3aText: undefined,
}
}
diff --git a/app/lib/actions/locationActions.ts b/app/lib/actions/locationActions.ts
index 61831af..3994865 100644
--- a/app/lib/actions/locationActions.ts
+++ b/app/lib/actions/locationActions.ts
@@ -432,7 +432,7 @@ export const fetchAllLocations = withUser(async (user:AuthenticatedUser, year:nu
"seenByTenant": 1,
// "bills.attachment": 0,
// "bills.notes": 0,
- // "bills.barcodeImage": 1,
+ // "bills.hub3aText": 1,
},
},
{
diff --git a/app/lib/actions/monthActions.ts b/app/lib/actions/monthActions.ts
index b8fc6b4..8e4157d 100644
--- a/app/lib/actions/monthActions.ts
+++ b/app/lib/actions/monthActions.ts
@@ -53,7 +53,7 @@ export const addMonth = withUser(async (user:AuthenticatedUser, { year, month }:
attachment: null,
notes: null,
payedAmount: null,
- barcodeImage: undefined,
+ hub3aText: undefined,
} as Bill
})
} as BillingLocation);
diff --git a/app/lib/actions/printActions.ts b/app/lib/actions/printActions.ts
index 60fdfbc..a44d3c4 100644
--- a/app/lib/actions/printActions.ts
+++ b/app/lib/actions/printActions.ts
@@ -9,7 +9,12 @@ import { unstable_noStore as noStore } from 'next/cache';
export interface PrintBarcodeData {
locationName: string;
billName: string;
- barcodeImage: string;
+ /**
+ * LEGACY SUPPORT ... untill all bills have been migrated
+ * @deprecated Use `hub3aText` instead.
+ */
+ barcodeImage?: string;
+ hub3aText?: string;
payedAmount?: number | null;
}
@@ -42,11 +47,15 @@ export const fetchBarcodeDataForPrint = withUser(async (user: AuthenticatedUser,
for (const location of locations) {
for (const bill of location.bills) {
// Only include bills that have barcode images
- if (bill.barcodeImage && bill.barcodeImage.trim() !== "") {
+ if ( ( bill.hub3aText && bill.hub3aText.trim() !== "") ||
+ // LEGACY SUPPORT ... untill all bills have been migrated
+ (bill.barcodeImage && bill.barcodeImage.trim() !== "")
+ ) {
printData.push({
locationName: location.name,
billName: bill.name,
- barcodeImage: bill.barcodeImage,
+ barcodeImage: bill.barcodeImage, // LEGACY SUPPORT ... untill all bills have been migrated
+ hub3aText: bill.hub3aText,
payedAmount: bill.payedAmount
});
}
diff --git a/app/lib/pdf/barcodeDecoder.ts b/app/lib/pdf/barcodeDecoder.ts
index 595f303..68c20ce 100644
--- a/app/lib/pdf/barcodeDecoder.ts
+++ b/app/lib/pdf/barcodeDecoder.ts
@@ -206,7 +206,6 @@ const pdf2canvas = async function (pdfFile:File): Promise {
-
- // get coordinates of bar code
- const points = decoderResult.getResultPoints();
-
- // get outter coordinates of the bar code
- const codeLocation = points.reduce((acc, point) => {
-
- const x = point.getX();
- const y = point.getY();
- let result = {
- top: y < acc.top ? y: acc.top,
- left: x < acc.left ? x: acc.left,
- bottom: y > acc.bottom ? y: acc.bottom,
- right: x > acc.right ? x: acc.right
- };
-
- return({
- ...result,
- width: result.right - result.left,
- height: result.bottom - result.top,
- });
- }, {
- top: Number.MAX_SAFE_INTEGER,
- left: Number.MAX_SAFE_INTEGER,
- bottom: 0,
- right: 0,
- width: 0,
- height: 0
- });
-
- // copy section of the canvas containing bar code to another canvas
- const tempCanvas = document.createElement('canvas');
- const tempContext = tempCanvas.getContext('2d');
-
- tempCanvas.width = codeLocation.width;
- tempCanvas.height = codeLocation.height;
-
- // Draw the portion of the original canvas onto the temporary canvas
- // Assuming you want to copy a 100x100 pixels square starting from (50, 50) of the original canvas
- tempContext?.drawImage(canvas, codeLocation.left, codeLocation.top, codeLocation.width, codeLocation.height, 0, 0, codeLocation.width, codeLocation.height);
-
- // Convert the temporary canvas to a data URL
- const dataURL = tempCanvas.toDataURL();
-
- return(dataURL);
-}
-
/** Finds PDF417 code within a base64 encoded image and decodes it */
export const decodeFromImage = async (imageBase64:string): Promise => {
return(await decodeFromCanvas( await image2canvas(imageBase64) ));
diff --git a/app/ui/Pdf417Barcode.tsx b/app/ui/Pdf417Barcode.tsx
index 27ac0c4..fa24a72 100644
--- a/app/ui/Pdf417Barcode.tsx
+++ b/app/ui/Pdf417Barcode.tsx
@@ -5,7 +5,7 @@ import { generateBarcode } from '../lib/pdf/pdf417';
import { renderBarcode } from '../lib/pdf/renderBarcode';
import { EncodePayment, PaymentParams } from 'hub-3a-payment-encoder';
-export const Pdf417Barcode:FC<{hub3aText:string}> = ({hub3aText: hub3a_text}) => {
+export const Pdf417Barcode:FC<{hub3aText:string, className?: string}> = ({hub3aText: hub3a_text, className}) => {
const [bitmapData, setBitmapData] = useState(undefined);
useEffect(() => {
@@ -24,8 +24,6 @@ export const Pdf417Barcode:FC<{hub3aText:string}> = ({hub3aText: hub3a_text}) =>
}
return (
-
-

-
+
);
}
\ No newline at end of file
diff --git a/app/ui/PrintPreview.tsx b/app/ui/PrintPreview.tsx
index 79109e5..923b09d 100644
--- a/app/ui/PrintPreview.tsx
+++ b/app/ui/PrintPreview.tsx
@@ -1,6 +1,7 @@
'use client';
import { PrintBarcodeData } from '../lib/actions/printActions';
+import { Pdf417Barcode } from './Pdf417Barcode';
export interface PrintPreviewProps {
data: PrintBarcodeData[];
@@ -141,12 +142,21 @@ export const PrintPreview: React.FC = ({ data, year, month, t
- )
+ {
+ item.hub3aText ?
+
+ : (
+ // LEGACY SUPPORT ... untill all bills have been migrated
+ item.barcodeImage ?
+ ) : null
+ )
+ }
+
|
diff --git a/app/ui/ViewBillCard.tsx b/app/ui/ViewBillCard.tsx
index 5b85c81..6bace88 100644
--- a/app/ui/ViewBillCard.tsx
+++ b/app/ui/ViewBillCard.tsx
@@ -2,20 +2,11 @@
import { DocumentIcon, CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/outline";
import { Bill, BillingLocation } from "../lib/db-types";
-import React, { FC } from "react";
-import { updateOrAddBill } from "../lib/actions/billActions";
+import { FC } from "react";
import Link from "next/link";
import { formatYearMonth } from "../lib/format";
-import { useLocale, useTranslations } from "next-intl";
-
-// 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
-const updateOrAddBillMiddleware = (locationId: string, billId:string|undefined, billYear:number|undefined, billMonth:number|undefined, prevState:any, formData: FormData) => {
- // URL encode the file name of the attachment so it is correctly sent to the server
- const billAttachment = formData.get('billAttachment') as File;
- formData.set('billAttachment', billAttachment, encodeURIComponent(billAttachment.name));
- return updateOrAddBill(locationId, billId, billYear, billMonth, prevState, formData);
-}
+import { useTranslations } from "next-intl";
+import { Pdf417Barcode } from "./Pdf417Barcode";
export interface ViewBillCardProps {
location: BillingLocation,
@@ -25,11 +16,9 @@ export interface ViewBillCardProps {
export const ViewBillCard:FC = ({ location, bill }) => {
const t = useTranslations("bill-edit-form");
- const locale = useLocale();
- const { _id: billID, name, paid, attachment, notes, payedAmount, barcodeImage } = bill ?? { _id:undefined, name:"", paid:false, notes:"" };
-
- const { yearMonth:{year: billYear, month: billMonth}, _id: locationID } = location;
+ const { _id: billID, name, paid, attachment, notes, payedAmount, barcodeImage, hub3aText } = bill ?? { _id:undefined, name:"", paid:false, notes:"" };
+ const { _id: locationID } = location;
return(
@@ -48,7 +37,6 @@ export const ViewBillCard:FC = ({ location, bill }) => {
{t("payed-amount")}
{payedAmount ? payedAmount/100 : ""}
-
{
notes ?
@@ -71,13 +59,23 @@ export const ViewBillCard:FC = ({ location, bill }) => {
: null
}
{
- barcodeImage ?
-
-
-
{t.rich('barcode-disclaimer', { br: () =>
})}
-
: null
+ hub3aText ?
+
+
+
{t.rich('barcode-disclaimer', { br: () =>
})}
+
:
+ (
+ // LEGACY SUPPORT ... untill all bills have been migrated
+ barcodeImage ?
+
+
+
{t.rich('barcode-disclaimer', { br: () =>
})}
+
: null
+ )
}