chore: upload parte 1 - logica
DevSecOps Enterprise Pipeline / security-gate-and-deploy (push) Failing after 41s
DevSecOps Enterprise Pipeline / security-gate-and-deploy (push) Failing after 41s
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
import jsPDF from "jspdf";
|
||||
import QRCode from "qrcode";
|
||||
|
||||
interface LabelData {
|
||||
partNumber: string;
|
||||
quantity: number;
|
||||
}
|
||||
|
||||
/** Load an image from a URL and return its base64 data URL */
|
||||
async function loadImageAsBase64(url: string): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.crossOrigin = "anonymous";
|
||||
img.onload = () => {
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = img.naturalWidth;
|
||||
canvas.height = img.naturalHeight;
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (!ctx) return reject(new Error("Canvas not supported"));
|
||||
ctx.drawImage(img, 0, 0);
|
||||
resolve(canvas.toDataURL("image/png"));
|
||||
};
|
||||
img.onerror = () => reject(new Error("Failed to load image"));
|
||||
img.src = url;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a 49mm x 12mm label PDF with:
|
||||
* - Company icon (left, square)
|
||||
* - Code, Quantity, Count date (center)
|
||||
* - QR code (right) containing "PartNumber,Quantity"
|
||||
*/
|
||||
export async function generateLabelPdf(data: LabelData): Promise<jsPDF> {
|
||||
const labelW = 49; // mm
|
||||
const labelH = 12; // mm
|
||||
const contentLeft = 1; // small padding
|
||||
const contentRight = labelW - 1;
|
||||
|
||||
const doc = new jsPDF({
|
||||
orientation: "landscape",
|
||||
unit: "mm",
|
||||
format: [labelW, labelH],
|
||||
});
|
||||
|
||||
const now = new Date();
|
||||
const countDate = `${String(now.getDate()).padStart(2, "0")}/${String(now.getMonth() + 1).padStart(2, "0")}/${now.getFullYear()}`;
|
||||
|
||||
// --- Icon (left side, square, filling most of the label height) ---
|
||||
const iconSize = 9;
|
||||
const iconX = contentLeft;
|
||||
const iconY = (labelH - iconSize) / 2;
|
||||
try {
|
||||
const iconBase64 = await loadImageAsBase64("/images/linse-icon.png");
|
||||
doc.addImage(iconBase64, "PNG", iconX, iconY, iconSize, iconSize);
|
||||
} catch {
|
||||
// If icon fails, skip
|
||||
}
|
||||
|
||||
// --- Text (center, maximised for 12mm height) ---
|
||||
const textX = iconX + iconSize + 1.5;
|
||||
|
||||
// Code
|
||||
doc.setFontSize(7);
|
||||
doc.setFont("helvetica", "bold");
|
||||
doc.setTextColor(0, 0, 0);
|
||||
doc.text(`Code: ${data.partNumber}`, textX, 3.8);
|
||||
|
||||
// Quantity
|
||||
doc.text(`Quantity: ${data.quantity}`, textX, 7.2);
|
||||
|
||||
// Count date
|
||||
doc.setFontSize(5.5);
|
||||
doc.setFont("helvetica", "normal");
|
||||
doc.text(`Count date: ${countDate}`, textX, 10.4);
|
||||
|
||||
// --- QR Code (right side, filling most of the label height) ---
|
||||
const qrContent = `${data.partNumber},${data.quantity}`;
|
||||
try {
|
||||
const qrDataUrl = await QRCode.toDataURL(qrContent, {
|
||||
width: 200,
|
||||
margin: 0,
|
||||
errorCorrectionLevel: "M",
|
||||
color: { dark: "#000000", light: "#ffffff" },
|
||||
});
|
||||
|
||||
const qrSize = 10;
|
||||
const qrX = contentRight - qrSize;
|
||||
const qrY = (labelH - qrSize) / 2;
|
||||
doc.addImage(qrDataUrl, "PNG", qrX, qrY, qrSize, qrSize);
|
||||
} catch {
|
||||
doc.setFontSize(4);
|
||||
doc.text("QR Error", contentRight - 10, labelH / 2);
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
Reference in New Issue
Block a user