qr code for bins re-implemented with new table
This commit is contained in:
parent
0a53a16cd7
commit
d800aedcdf
2 changed files with 316 additions and 16 deletions
300
src/common/QrCodeGenerator.tsx
Normal file
300
src/common/QrCodeGenerator.tsx
Normal 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 +
|
||||||
|
"&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 +
|
||||||
|
"&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 +
|
||||||
|
"&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 +
|
||||||
|
"&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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -46,7 +46,7 @@ import BinsList from "bin/BinsList";
|
||||||
// import BinYard from "bin/BinYard";
|
// import BinYard from "bin/BinYard";
|
||||||
import BinInventoryChart, { GrainAmount } from "charts/BinInventoryChart";
|
import BinInventoryChart, { GrainAmount } from "charts/BinInventoryChart";
|
||||||
import BinUtilizationChart from "charts/BinUtilizationChart";
|
import BinUtilizationChart from "charts/BinUtilizationChart";
|
||||||
// import QrCodeGenerator, { QrCodeKey } from "common/QrCodeGenerator";
|
import QrCodeGenerator, { QrCodeKey } from "common/QrCodeGenerator";
|
||||||
import GrainDescriber, { grainName } from "grain/GrainDescriber";
|
import GrainDescriber, { grainName } from "grain/GrainDescriber";
|
||||||
// import GrainBagList from "grainBag/grainBagList";
|
// import GrainBagList from "grainBag/grainBagList";
|
||||||
// import GrainBagSettings from "grainBag/grainBagSettings";
|
// import GrainBagSettings from "grainBag/grainBagSettings";
|
||||||
|
|
@ -184,7 +184,7 @@ export default function Bins(props: Props) {
|
||||||
const [expandUtilization, setExpandUtilization] = useState(false);
|
const [expandUtilization, setExpandUtilization] = useState(false);
|
||||||
const [expandFanTable, setExpandFanTable] = useState(false);
|
const [expandFanTable, setExpandFanTable] = useState(false);
|
||||||
const [openQrGenerator, setOpenQrGenerator] = useState(false);
|
const [openQrGenerator, setOpenQrGenerator] = useState(false);
|
||||||
// const [qrKeyList, setQrKeyList] = useState<QrCodeKey[]>([]);
|
const [qrKeyList, setQrKeyList] = useState<QrCodeKey[]>([]);
|
||||||
const [totalFanControllers, setTotalFanControllers] = useState(0);
|
const [totalFanControllers, setTotalFanControllers] = useState(0);
|
||||||
const [totalFanControllersOn, setTotalFanControllersOn] = useState(0);
|
const [totalFanControllersOn, setTotalFanControllersOn] = useState(0);
|
||||||
const [yardsLoading, setYardsLoading] = useState(false);
|
const [yardsLoading, setYardsLoading] = useState(false);
|
||||||
|
|
@ -313,7 +313,7 @@ export default function Bins(props: Props) {
|
||||||
let grain: Bin[] = [];
|
let grain: Bin[] = [];
|
||||||
let empty: Bin[] = [];
|
let empty: Bin[] = [];
|
||||||
let fert: Bin[] = [];
|
let fert: Bin[] = [];
|
||||||
// let qr: QrCodeKey[] = [];
|
let qr: QrCodeKey[] = [];
|
||||||
let b = resp.data.bins.map(b => Bin.any(b));
|
let b = resp.data.bins.map(b => Bin.any(b));
|
||||||
b.forEach(bin => {
|
b.forEach(bin => {
|
||||||
if (bin.empty()) {
|
if (bin.empty()) {
|
||||||
|
|
@ -324,12 +324,12 @@ export default function Bins(props: Props) {
|
||||||
grain.push(bin);
|
grain.push(bin);
|
||||||
}
|
}
|
||||||
//build qr keys here
|
//build qr keys here
|
||||||
// qr.push({
|
qr.push({
|
||||||
// key: bin.key(),
|
key: bin.key(),
|
||||||
// name: bin.name()
|
name: bin.name()
|
||||||
// });
|
});
|
||||||
});
|
});
|
||||||
// setQrKeyList(qr);
|
setQrKeyList(qr);
|
||||||
setGrainBins(grain);
|
setGrainBins(grain);
|
||||||
if (fert.length > 0) {
|
if (fert.length > 0) {
|
||||||
setDisplayFert(true);
|
setDisplayFert(true);
|
||||||
|
|
@ -428,7 +428,7 @@ export default function Bins(props: Props) {
|
||||||
let empty: Bin[] = offset ? emptyBins : [];
|
let empty: Bin[] = offset ? emptyBins : [];
|
||||||
let fert: Bin[] = offset ? fertilizerBins : [];
|
let fert: Bin[] = offset ? fertilizerBins : [];
|
||||||
let grain: Bin[] = offset ? grainBins : [];
|
let grain: Bin[] = offset ? grainBins : [];
|
||||||
// let newKeyList: QrCodeKey[] = qrKeyList;
|
let newKeyList: QrCodeKey[] = qrKeyList;
|
||||||
newBins.forEach(bin => {
|
newBins.forEach(bin => {
|
||||||
if (bin.empty()) {
|
if (bin.empty()) {
|
||||||
empty.push(bin);
|
empty.push(bin);
|
||||||
|
|
@ -437,10 +437,10 @@ export default function Bins(props: Props) {
|
||||||
} else {
|
} else {
|
||||||
grain.push(bin);
|
grain.push(bin);
|
||||||
}
|
}
|
||||||
// newKeyList.push({
|
newKeyList.push({
|
||||||
// key: bin.key(),
|
key: bin.key(),
|
||||||
// name: bin.name()
|
name: bin.name()
|
||||||
// });
|
});
|
||||||
});
|
});
|
||||||
if (fert.length > 0) {
|
if (fert.length > 0) {
|
||||||
setDisplayFert(true);
|
setDisplayFert(true);
|
||||||
|
|
@ -451,7 +451,7 @@ export default function Bins(props: Props) {
|
||||||
setGrainBins([...grain]);
|
setGrainBins([...grain]);
|
||||||
setEmptyBins([...empty]);
|
setEmptyBins([...empty]);
|
||||||
setFertilizerBins([...fert]);
|
setFertilizerBins([...fert]);
|
||||||
// setQrKeyList([...newKeyList]);
|
setQrKeyList([...newKeyList]);
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
setPaginatedBins({ bins: [], binsOffset: 0, binsTotal: 0 });
|
setPaginatedBins({ bins: [], binsOffset: 0, binsTotal: 0 });
|
||||||
|
|
@ -1390,14 +1390,14 @@ export default function Bins(props: Props) {
|
||||||
setAddBagOpen(false);
|
setAddBagOpen(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/* <QrCodeGenerator
|
<QrCodeGenerator
|
||||||
open={openQrGenerator}
|
open={openQrGenerator}
|
||||||
close={() => {
|
close={() => {
|
||||||
setOpenQrGenerator(false);
|
setOpenQrGenerator(false);
|
||||||
}}
|
}}
|
||||||
keyList={qrKeyList}
|
keyList={qrKeyList}
|
||||||
requiredUrlAffix={"bins"}
|
requiredUrlAffix={"bins"}
|
||||||
/> */}
|
/>
|
||||||
{binMenu()}
|
{binMenu()}
|
||||||
<AddBinFab onClick={() => setAddBinOpen(true)} pulse={binsTotal < 1 && !allLoading} />
|
<AddBinFab onClick={() => setAddBinOpen(true)} pulse={binsTotal < 1 && !allLoading} />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue