qr code for bins re-implemented with new table

This commit is contained in:
csawatzky 2025-04-14 10:43:33 -06:00
parent 0a53a16cd7
commit d800aedcdf
2 changed files with 316 additions and 16 deletions

View file

@ -0,0 +1,300 @@
import { Box, Button, DialogActions, DialogContent, DialogTitle } from "@mui/material";
// import MaterialTable from "material-table";
import React, { useEffect, useState } from "react";
import ResponsiveDialog from "./ResponsiveDialog";
// import { getTableIcons } from "./ResponsiveTable";
import { Document, Image, Page, PDFViewer, StyleSheet, Text, View } from "@react-pdf/renderer";
import { useMobile } from "hooks";
import { cloneDeep } from "lodash";
import ResponsiveTable from "./ResponsiveTable";
export interface QrCodeKey {
name: string;
key: string;
}
interface Props {
open: boolean;
close: () => void;
keyList: QrCodeKey[];
requiredUrlAffix: string;
url?: string;
}
export default function(props: Props) {
const { open, close, url, requiredUrlAffix, keyList } = props;
const [selectedKeys, setSelectedKeys] = useState<QrCodeKey[]>([]);
const [selectedPageRows, setSelectedPageRows] = useState<Map<number, number[]>>(new Map())//key is the page value is an array of row indexes for that page
const [tablePage, setTablePage] = useState(0)
const [pageSize, setPageSize] = useState(10)
const isMobile = useMobile();
const [displayedRows, setDisplayedRows] = useState<QrCodeKey[]>([]);
const codesPerPage = 4;
const pdfStyle = StyleSheet.create({
viewerDesktop: {
height: 500 * 1.44,
width: 500
},
viewerMobile: {
height: "100%",
width: "100%"
},
page: {
padding: "3%",
textAlign: "center",
fontFamily: "Helvetica-Bold",
fontSize: 30
},
quadrant: {
width: "50%",
textAlign: "center",
//margin: 10,
borderRadius: 20
},
code: {
flexDirection: "column",
border: "2px dotted black",
margin: 10,
borderRadius: 20
},
image: {
padding: 20,
paddingBottom: 0
//height: "65%"
//border: "1px solid black", //used just to see a representation of where the view is
},
text: {
marginTop: 30,
marginBottom: 30,
textAlign: "center",
justifyContent: "center"
//border: "1px solid black", //used just to see a representation of where the view is
}
});
useEffect(()=>{
let clone: QrCodeKey[] = cloneDeep(keyList)
let rows = clone.splice(tablePage * pageSize, pageSize)
setDisplayedRows(rows)
},[keyList, tablePage, pageSize])
const handleRowsPerPageChange = (event: any) => {
const newRowsPerPage = parseInt(event.target.value, 10); // Get selected value
setPageSize(newRowsPerPage);
setTablePage(0)
//clear the selected rows
setSelectedPageRows(new Map())
//clear the selected keys
setSelectedKeys([])
}
const rowSelected = (row: QrCodeKey, index: number, checked: boolean) => {
//when a row is selected add it to the map for the page
let selected = cloneDeep(selectedKeys)
let pageMap = cloneDeep(selectedPageRows)
let pageSelect = pageMap.get(tablePage)
if(checked){ //add the page/index to the map
if(pageSelect){
pageSelect.push(index)
}else{
pageMap.set(tablePage, [index])
}
//handle the row data to add it to a list of keys that are selected
selected.push(row)
}else{ //remove the page/index from the map
if(pageSelect){
pageSelect.splice(pageSelect.indexOf(index))
}
//remove the selected object from the array
selected.forEach((codeKey, index) => {
if(row.key === codeKey.key){
selected.splice(index)
}
})
}
setSelectedKeys(selected)
setSelectedPageRows(pageMap)
}
const selectionTable = () => {
return (
<React.Fragment>
<ResponsiveTable
columns={[
{
cellStyle: {
padding: 2
},
title: "Name",
render: (row) => <Box>{row.name}</Box>
}
]}
rowSelect={rowSelected}
selectedRows={selectedPageRows.get(tablePage)}
rows={displayedRows}
page={tablePage}
pageSize={pageSize}
total={keyList.length}
setPage={(page) => {setTablePage(page)}}
handleRowsPerPageChange={handleRowsPerPageChange}
/>
{/* <MaterialTable
icons={getTableIcons()}
title={""}
data={keyList}
options={{
paging: true,
// pageSize: pageSize,
// pageSizeOptions: [5, 10, 20],
padding: "dense",
showTitle: true,
toolbar: true,
sorting: true,
columnsButton: true,
search: false,
selection: true
}}
onSelectionChange={(data, rowData) => {
setSelectedKeys(data);
}}
columns={[
{
cellStyle: {
padding: 0
},
title: "Name",
field: "name"
}
]}></MaterialTable> */}
</React.Fragment>
);
};
const generatedCodes = () => {
let numPages = Math.ceil(selectedKeys.length / codesPerPage);
let keys = cloneDeep(selectedKeys);
let pages: JSX.Element[] = [];
let location = url ?? document.URL; //document.URL will append the ending slash to the url string
if (!location.includes(requiredUrlAffix)) {
location = location + requiredUrlAffix;
}
for (let i = 0; i < numPages; i++) {
let pageKeys = keys.splice(0, codesPerPage);
pages.push(
<React.Fragment key={i}>
<View style={{ height: "50%", flexDirection: "row" }}>
{pageKeys[0] && (
<View style={pdfStyle.quadrant}>
<View style={pdfStyle.code}>
<View style={pdfStyle.image}>
<Image
src={
"https://api.qrserver.com/v1/create-qr-code/?data=" +
location +
"/" +
pageKeys[0].key +
"&amp;size=100x100"
}
/>
</View>
<View style={pdfStyle.text}>
<Text>{pageKeys[0].name}</Text>
</View>
</View>
</View>
)}
{pageKeys[1] && (
<View style={pdfStyle.quadrant}>
<View style={pdfStyle.code}>
<View style={pdfStyle.image}>
<Image
src={
"https://api.qrserver.com/v1/create-qr-code/?data=" +
location +
"/" +
pageKeys[1].key +
"&amp;size=100x100"
}
/>
</View>
<View style={pdfStyle.text}>
<Text>{pageKeys[1].name}</Text>
</View>
</View>
</View>
)}
</View>
<View style={{ height: "50%", flexDirection: "row" }}>
{pageKeys[2] && (
<View style={pdfStyle.quadrant}>
<View style={pdfStyle.code}>
<View style={pdfStyle.image}>
<Image
src={
"https://api.qrserver.com/v1/create-qr-code/?data=" +
location +
"/" +
pageKeys[2].key +
"&amp;size=100x100"
}
/>
</View>
<View style={pdfStyle.text}>
<Text>{pageKeys[2].name}</Text>
</View>
</View>
</View>
)}
{pageKeys[3] && (
<View style={pdfStyle.quadrant}>
<View style={pdfStyle.code}>
<View style={pdfStyle.image}>
<Image
src={
"https://api.qrserver.com/v1/create-qr-code/?data=" +
location +
"/" +
pageKeys[3].key +
"&amp;size=100x100"
}
/>
</View>
<View style={pdfStyle.text}>
<Text>{pageKeys[3].name}</Text>
</View>
</View>
</View>
)}
</View>
</React.Fragment>
);
}
return (
<Document>
<Page style={pdfStyle.page}>{pages}</Page>
</Document>
);
};
return (
<ResponsiveDialog open={open} onClose={close}>
<DialogTitle>Generate QR Codes</DialogTitle>
<DialogContent>
{selectionTable()}
<Box marginTop={5}>
<PDFViewer style={isMobile ? pdfStyle.viewerMobile : pdfStyle.viewerDesktop}>
{generatedCodes()}
</PDFViewer>
</Box>
</DialogContent>
<DialogActions>
<Button variant="contained" color="primary" onClick={close}>
Close
</Button>
</DialogActions>
</ResponsiveDialog>
);
}

View file

@ -46,7 +46,7 @@ import BinsList from "bin/BinsList";
// import BinYard from "bin/BinYard";
import BinInventoryChart, { GrainAmount } from "charts/BinInventoryChart";
import BinUtilizationChart from "charts/BinUtilizationChart";
// import QrCodeGenerator, { QrCodeKey } from "common/QrCodeGenerator";
import QrCodeGenerator, { QrCodeKey } from "common/QrCodeGenerator";
import GrainDescriber, { grainName } from "grain/GrainDescriber";
// import GrainBagList from "grainBag/grainBagList";
// import GrainBagSettings from "grainBag/grainBagSettings";
@ -184,7 +184,7 @@ export default function Bins(props: Props) {
const [expandUtilization, setExpandUtilization] = useState(false);
const [expandFanTable, setExpandFanTable] = useState(false);
const [openQrGenerator, setOpenQrGenerator] = useState(false);
// const [qrKeyList, setQrKeyList] = useState<QrCodeKey[]>([]);
const [qrKeyList, setQrKeyList] = useState<QrCodeKey[]>([]);
const [totalFanControllers, setTotalFanControllers] = useState(0);
const [totalFanControllersOn, setTotalFanControllersOn] = useState(0);
const [yardsLoading, setYardsLoading] = useState(false);
@ -313,7 +313,7 @@ export default function Bins(props: Props) {
let grain: Bin[] = [];
let empty: Bin[] = [];
let fert: Bin[] = [];
// let qr: QrCodeKey[] = [];
let qr: QrCodeKey[] = [];
let b = resp.data.bins.map(b => Bin.any(b));
b.forEach(bin => {
if (bin.empty()) {
@ -324,12 +324,12 @@ export default function Bins(props: Props) {
grain.push(bin);
}
//build qr keys here
// qr.push({
// key: bin.key(),
// name: bin.name()
// });
qr.push({
key: bin.key(),
name: bin.name()
});
});
// setQrKeyList(qr);
setQrKeyList(qr);
setGrainBins(grain);
if (fert.length > 0) {
setDisplayFert(true);
@ -428,7 +428,7 @@ export default function Bins(props: Props) {
let empty: Bin[] = offset ? emptyBins : [];
let fert: Bin[] = offset ? fertilizerBins : [];
let grain: Bin[] = offset ? grainBins : [];
// let newKeyList: QrCodeKey[] = qrKeyList;
let newKeyList: QrCodeKey[] = qrKeyList;
newBins.forEach(bin => {
if (bin.empty()) {
empty.push(bin);
@ -437,10 +437,10 @@ export default function Bins(props: Props) {
} else {
grain.push(bin);
}
// newKeyList.push({
// key: bin.key(),
// name: bin.name()
// });
newKeyList.push({
key: bin.key(),
name: bin.name()
});
});
if (fert.length > 0) {
setDisplayFert(true);
@ -451,7 +451,7 @@ export default function Bins(props: Props) {
setGrainBins([...grain]);
setEmptyBins([...empty]);
setFertilizerBins([...fert]);
// setQrKeyList([...newKeyList]);
setQrKeyList([...newKeyList]);
})
.catch(err => {
setPaginatedBins({ bins: [], binsOffset: 0, binsTotal: 0 });
@ -1390,14 +1390,14 @@ export default function Bins(props: Props) {
setAddBagOpen(false);
}}
/>
{/* <QrCodeGenerator
<QrCodeGenerator
open={openQrGenerator}
close={() => {
setOpenQrGenerator(false);
}}
keyList={qrKeyList}
requiredUrlAffix={"bins"}
/> */}
/>
{binMenu()}
<AddBinFab onClick={() => setAddBinOpen(true)} pulse={binsTotal < 1 && !allLoading} />
</Box>