feat(barcode gen): added in lane exports both single and multiple intial release

This commit is contained in:
2025-05-31 02:17:00 -05:00
parent a6844d9455
commit 2672e89005
15 changed files with 1112 additions and 3 deletions

View File

@@ -1,4 +1,4 @@
import { Cylinder, Package, Truck } from "lucide-react";
import { Barcode, Cylinder, Package, Truck } from "lucide-react";
import {
SidebarGroup,
SidebarGroupContent,
@@ -15,6 +15,7 @@ const iconMap: any = {
Package: Package,
Truck: Truck,
Cylinder: Cylinder,
Barcode: Barcode,
};
export function LogisticsSideBar({

View File

@@ -0,0 +1,150 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { CardContent, CardFooter, CardHeader } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Collapsible, CollapsibleContent } from "@/components/ui/collapsible";
import { getLanes } from "@/utils/querys/logistics/getWarehouseLanes";
import { CollapsibleTrigger } from "@radix-ui/react-collapsible";
import { useQuery } from "@tanstack/react-query";
import { useState } from "react";
import Barcode from "react-barcode";
import { BarcodePDFExport } from "./BarcodeExport";
import { BulkBarcodePDFExport } from "./BulkExport";
export default function BGPage() {
const { data, isError, isLoading } = useQuery(getLanes());
const [checked, setChecked] = useState([]);
if (isLoading) return <div>Loading Data</div>;
if (isError)
return <div>There was an error getting the warehouse lane data.</div>;
/**
* get the warehouse names only
*/
const warhouses = new Map();
data?.forEach((item: any) => {
// if the warhouse is not already included add it to the map
if (!warhouses.has(item.warehouseId)) {
warhouses.set(item.warehouseId, item.warehouseDescription);
}
});
// convert the map to an array
const warehouseArray = Array.from(warhouses).map(([wid, wname]) => ({
warehouseId: wid,
warehouseDescription: wname,
}));
//console.log(warehouseArray);
// handle the onchange
const changeBox = (d: any) => {
setChecked((prev: any) => {
if (prev.includes(d)) {
return prev.filter((name: any) => name !== d);
} else {
return [...prev, d];
}
});
};
return (
<div className="flex flex-row m-2">
<div className="m-2">
<LstCard>
<CardHeader>Warehouse Barcodes</CardHeader>
<CardContent>
{warehouseArray.map((i: any) => {
const lanes = data?.filter(
(wid: any) => wid.warehouseId === i.warehouseId
);
return (
<div className="m-2" key={i.warehouseId}>
<Collapsible>
<CollapsibleTrigger>
{i.warehouseDescription}
</CollapsibleTrigger>
<CollapsibleContent>
<div className="ml-2">
{lanes?.map((l: any) => {
return (
<div key={l.laneId}>
<Checkbox
id={l.laneId}
// checked={checked.includes(
// l
// )}
onCheckedChange={() =>
changeBox(l)
}
/>
<label
id={l.laneId}
className="ml-2"
>
{
l.laneDescription
}
</label>
</div>
);
})}
</div>
</CollapsibleContent>
</Collapsible>
</div>
);
})}
</CardContent>
</LstCard>
</div>
{checked.length > 0 && (
<div className="m-2">
<LstCard>
<CardHeader>Current selected lanes</CardHeader>
<CardContent>
{checked.map((c: any) => {
return (
<div
className="flex justify-center"
key={`${c.warehouseId}-${c.laneId}`}
>
<div>
<Barcode
value={`loc#${c.warehouseId}#${c.laneId}`}
width={2}
height={50}
displayValue={false}
/>
<p className="flex justify-center">
Lane: {c.laneDescription}
</p>
</div>
<div className="ml-2 mt-4">
<BarcodePDFExport
barcodeValue={`loc#${c.warehouseId}#${c.laneId}`}
data={c}
/>
</div>
</div>
);
})}
</CardContent>
<CardFooter>
<div className="flex justify-end">
{checked.length > 1 && (
<div>
<BulkBarcodePDFExport data={checked} />
</div>
)}
</div>
</CardFooter>
</LstCard>
</div>
)}
</div>
);
}

View File

@@ -0,0 +1,100 @@
import { Button } from "@/components/ui/button";
import {
pdf,
Page,
Text,
View,
Document,
StyleSheet,
Image,
} from "@react-pdf/renderer";
import JsBarcode from "jsbarcode";
export const BarcodePDFExport = ({
barcodeValue,
data,
}: {
barcodeValue: any;
data: any;
}) => {
const generatePDF = () => {
//const barcodeValue = data; // Barcode value
const canvas = document.createElement("canvas");
// Generate barcode on the canvas
JsBarcode(canvas, barcodeValue, {
format: "CODE128",
displayValue: false,
});
// Convert canvas to base64 image data
const barcodeImage = canvas.toDataURL("image/png");
// Define the document styles using @react-pdf/renderer
const styles = StyleSheet.create({
page: {
padding: 30,
},
centerContent: {
display: "flex",
justifyContent: "center", // Center horizontally
alignItems: "center", // Center vertically
flexDirection: "column", // Stack items (barcode and description) vertically
height: "75%", // Ensure the container takes full page height
textAlign: "center",
},
section: {
marginBottom: 10,
textAlign: "center",
},
barcode: {
width: 800, // Width of the barcode
height: 200, // Height of the barcode
marginBottom: 10,
},
description: {
fontSize: 28,
fontWeight: "bold",
marginTop: 10,
marginBottom: 20, // Ensure there's space below the text
},
});
// Create the document
const MyDocument = (
<Document>
<Page style={styles.page} orientation="landscape" size="A4">
<View style={styles.centerContent}>
<View style={styles.section}>
<Image src={barcodeImage} style={styles.barcode} />
</View>
<View style={styles.section}>
<Text style={styles.description}>
Lane: {data.laneDescription}
</Text>
</View>
</View>
</Page>
</Document>
);
// Generate the PDF and trigger download
pdf(MyDocument)
.toBlob()
.then((blob) => {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = `${data.warehouseDescription}-${data.laneDescription}.pdf`;
link.click();
});
};
return (
<div>
<Button onClick={() => generatePDF()} color="primary">
Export
</Button>
</div>
);
};

View File

@@ -0,0 +1,127 @@
import { Button } from "@/components/ui/button";
import {
pdf,
Page,
Text,
View,
Document,
StyleSheet,
Image,
} from "@react-pdf/renderer";
import JsBarcode from "jsbarcode";
export const BulkBarcodePDFExport = ({ data }: { data: any }) => {
const createBarcode = (barcodeValue: any) => {
//const barcodeValue = data; // Barcode value
const canvas = document.createElement("canvas");
// Generate barcode on the canvas
JsBarcode(canvas, barcodeValue, {
format: "CODE128",
displayValue: false,
});
// Convert canvas to base64 image data
const barcodeImage = canvas.toDataURL("image/png");
return barcodeImage;
};
const generatePDF = () => {
// Define the document styles using @react-pdf/renderer
const styles = StyleSheet.create({
page: {
padding: 30,
},
centerContent: {
display: "flex",
justifyContent: "flex-start", // Center horizontally
alignItems: "center", // Center vertically
flexDirection: "row", // Stack items (barcode and description) vertically
//height: "5%", // Ensure the container takes full page height
textAlign: "center",
},
section: {
marginBottom: 10,
textAlign: "center",
},
barcode: {
width: 275, // Width of the barcode
height: 75, // Height of the barcode
marginBottom: 10,
},
description: {
fontSize: 14,
fontWeight: "bold",
marginTop: 10,
marginBottom: 20, // Ensure there's space below the text
},
headerText: {
fontSize: 28,
fontWeight: "bold",
marginTop: 10,
marginBottom: 20, // Ensure there's space below the text
display: "flex",
justifyContent: "center",
//height: "15%", // Ensure the container takes full page height
textAlign: "center",
},
horizontalLine: {
borderBottom: "#000000",
borderBottomWidth: 1,
},
});
// Create the document
const MyDocument = (
<Document>
<Page style={styles.page} orientation="portrait" size="A4">
<View style={styles.headerText}>
<Text>Multi Lane export.</Text>
</View>
<View style={styles.horizontalLine} />
{data.map((i: any, index: any) => {
return (
<View style={styles.centerContent} key={index}>
<View style={styles.section}>
<Image
src={createBarcode(
`loc#${i.warehouseId}#${i.laneId}`
)}
style={styles.barcode}
/>
</View>
<View style={styles.section}>
<Text style={styles.description}>
Lane: {i.laneDescription}
</Text>
</View>
</View>
);
})}
</Page>
</Document>
);
// Generate the PDF and trigger download
pdf(MyDocument)
.toBlob()
.then((blob) => {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = `MultipleBarcodes.pdf`;
link.click();
});
};
return (
<div>
<Button onClick={() => generatePDF()} color="primary">
Export All Selected
</Button>
</div>
);
};

View File

@@ -35,6 +35,7 @@ import { Route as logisticsOpenOrdersIndexImport } from './routes/(logistics)/op
import { Route as logisticsMaterialHelperIndexImport } from './routes/(logistics)/materialHelper/index'
import { Route as logisticsHelperCommandsIndexImport } from './routes/(logistics)/helperCommands/index'
import { Route as logisticsDmIndexImport } from './routes/(logistics)/dm/index'
import { Route as logisticsBarcodegenIndexImport } from './routes/(logistics)/barcodegen/index'
import { Route as EomArticleAvImport } from './routes/_eom/article/$av'
import { Route as logisticsSiloAdjustmentsHistImport } from './routes/(logistics)/siloAdjustments/$hist'
import { Route as logisticsMaterialHelperSiloLinkIndexImport } from './routes/(logistics)/materialHelper/siloLink/index'
@@ -187,6 +188,12 @@ const logisticsDmIndexRoute = logisticsDmIndexImport.update({
getParentRoute: () => rootRoute,
} as any)
const logisticsBarcodegenIndexRoute = logisticsBarcodegenIndexImport.update({
id: '/(logistics)/barcodegen/',
path: '/barcodegen/',
getParentRoute: () => rootRoute,
} as any)
const EomArticleAvRoute = EomArticleAvImport.update({
id: '/article/$av',
path: '/article/$av',
@@ -365,6 +372,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof EomArticleAvImport
parentRoute: typeof EomImport
}
'/(logistics)/barcodegen/': {
id: '/(logistics)/barcodegen/'
path: '/barcodegen'
fullPath: '/barcodegen'
preLoaderRoute: typeof logisticsBarcodegenIndexImport
parentRoute: typeof rootRoute
}
'/(logistics)/dm/': {
id: '/(logistics)/dm/'
path: '/dm'
@@ -494,6 +508,7 @@ export interface FileRoutesByFullPath {
'/ocp': typeof OcpIndexRoute
'/siloAdjustments/$hist': typeof logisticsSiloAdjustmentsHistRoute
'/article/$av': typeof EomArticleAvRoute
'/barcodegen': typeof logisticsBarcodegenIndexRoute
'/dm': typeof logisticsDmIndexRoute
'/helperCommands': typeof logisticsHelperCommandsIndexRoute
'/materialHelper': typeof logisticsMaterialHelperIndexRoute
@@ -524,6 +539,7 @@ export interface FileRoutesByTo {
'/ocp': typeof OcpIndexRoute
'/siloAdjustments/$hist': typeof logisticsSiloAdjustmentsHistRoute
'/article/$av': typeof EomArticleAvRoute
'/barcodegen': typeof logisticsBarcodegenIndexRoute
'/dm': typeof logisticsDmIndexRoute
'/helperCommands': typeof logisticsHelperCommandsIndexRoute
'/materialHelper': typeof logisticsMaterialHelperIndexRoute
@@ -557,6 +573,7 @@ export interface FileRoutesById {
'/ocp/': typeof OcpIndexRoute
'/(logistics)/siloAdjustments/$hist': typeof logisticsSiloAdjustmentsHistRoute
'/_eom/article/$av': typeof EomArticleAvRoute
'/(logistics)/barcodegen/': typeof logisticsBarcodegenIndexRoute
'/(logistics)/dm/': typeof logisticsDmIndexRoute
'/(logistics)/helperCommands/': typeof logisticsHelperCommandsIndexRoute
'/(logistics)/materialHelper/': typeof logisticsMaterialHelperIndexRoute
@@ -589,6 +606,7 @@ export interface FileRouteTypes {
| '/ocp'
| '/siloAdjustments/$hist'
| '/article/$av'
| '/barcodegen'
| '/dm'
| '/helperCommands'
| '/materialHelper'
@@ -618,6 +636,7 @@ export interface FileRouteTypes {
| '/ocp'
| '/siloAdjustments/$hist'
| '/article/$av'
| '/barcodegen'
| '/dm'
| '/helperCommands'
| '/materialHelper'
@@ -649,6 +668,7 @@ export interface FileRouteTypes {
| '/ocp/'
| '/(logistics)/siloAdjustments/$hist'
| '/_eom/article/$av'
| '/(logistics)/barcodegen/'
| '/(logistics)/dm/'
| '/(logistics)/helperCommands/'
| '/(logistics)/materialHelper/'
@@ -673,6 +693,7 @@ export interface RootRouteChildren {
userPasswordChangeRoute: typeof userPasswordChangeRoute
OcpIndexRoute: typeof OcpIndexRoute
logisticsSiloAdjustmentsHistRoute: typeof logisticsSiloAdjustmentsHistRoute
logisticsBarcodegenIndexRoute: typeof logisticsBarcodegenIndexRoute
logisticsDmIndexRoute: typeof logisticsDmIndexRoute
logisticsHelperCommandsIndexRoute: typeof logisticsHelperCommandsIndexRoute
logisticsMaterialHelperIndexRoute: typeof logisticsMaterialHelperIndexRoute
@@ -696,6 +717,7 @@ const rootRouteChildren: RootRouteChildren = {
userPasswordChangeRoute: userPasswordChangeRoute,
OcpIndexRoute: OcpIndexRoute,
logisticsSiloAdjustmentsHistRoute: logisticsSiloAdjustmentsHistRoute,
logisticsBarcodegenIndexRoute: logisticsBarcodegenIndexRoute,
logisticsDmIndexRoute: logisticsDmIndexRoute,
logisticsHelperCommandsIndexRoute: logisticsHelperCommandsIndexRoute,
logisticsMaterialHelperIndexRoute: logisticsMaterialHelperIndexRoute,
@@ -731,6 +753,7 @@ export const routeTree = rootRoute
"/(user)/passwordChange",
"/ocp/",
"/(logistics)/siloAdjustments/$hist",
"/(logistics)/barcodegen/",
"/(logistics)/dm/",
"/(logistics)/helperCommands/",
"/(logistics)/materialHelper/",
@@ -826,6 +849,9 @@ export const routeTree = rootRoute
"filePath": "_eom/article/$av.tsx",
"parent": "/_eom"
},
"/(logistics)/barcodegen/": {
"filePath": "(logistics)/barcodegen/index.tsx"
},
"/(logistics)/dm/": {
"filePath": "(logistics)/dm/index.tsx"
},

View File

@@ -0,0 +1,14 @@
import BGPage from "@/components/logistics/barcodeGenerator/BGPage";
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/(logistics)/barcodegen/")({
component: RouteComponent,
});
function RouteComponent() {
return (
<div>
<BGPage />
</div>
);
}

View File

@@ -0,0 +1,20 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getLanes() {
return queryOptions({
queryKey: ["getLanes"],
queryFn: () => fetch(),
//enabled:
staleTime: 1000,
refetchInterval: 60 * 1000,
refetchOnWindowFocus: true,
});
}
const fetch = async () => {
const { data } = await axios.get(`/api/logistics/getactivelanes`);
// // if we are not localhost ignore the devDir setting.
// //const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};