Compare commits
5 commits
master
...
mipca_repo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9de2f1285f | ||
|
|
eb01964622 | ||
|
|
bbdf40df47 | ||
|
|
6dbb7c3432 | ||
|
|
bced311508 |
11 changed files with 367 additions and 11 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -42,7 +42,7 @@
|
||||||
"mui-tel-input": "^7.0.0",
|
"mui-tel-input": "^7.0.0",
|
||||||
"notistack": "^3.0.1",
|
"notistack": "^3.0.1",
|
||||||
"openweathermap-ts": "^1.2.10",
|
"openweathermap-ts": "^1.2.10",
|
||||||
"protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#master",
|
"protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#mipca_reports",
|
||||||
"query-string": "^9.2.1",
|
"query-string": "^9.2.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
"react-beautiful-dnd": "^13.1.1",
|
||||||
|
|
@ -10911,7 +10911,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/protobuf-ts": {
|
"node_modules/protobuf-ts": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#d0ac088df3822c10c0497f49173d1679b4e107b0",
|
"resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#90d01d04404d6b38d3200634e194c17bae8a0737",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"protobufjs": "^6.8.8"
|
"protobufjs": "^6.8.8"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@
|
||||||
"mui-tel-input": "^7.0.0",
|
"mui-tel-input": "^7.0.0",
|
||||||
"notistack": "^3.0.1",
|
"notistack": "^3.0.1",
|
||||||
"openweathermap-ts": "^1.2.10",
|
"openweathermap-ts": "^1.2.10",
|
||||||
"protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#master",
|
"protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#mipca_reports",
|
||||||
"query-string": "^9.2.1",
|
"query-string": "^9.2.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
"react-beautiful-dnd": "^13.1.1",
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export default function CableQuote(props: Props) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const pdfDoc = () => {
|
const pdfDoc = () => {
|
||||||
return <AgPDFTemplate content={<PdfContent bin={bin} />} />;
|
return <AgPDFTemplate content={[<PdfContent bin={bin} />]} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import Header from "./components/header";
|
||||||
import Footer from "./components/footer";
|
import Footer from "./components/footer";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
content: JSX.Element;
|
content: JSX.Element[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AgPDFTemplate(props: Props) {
|
export default function AgPDFTemplate(props: Props) {
|
||||||
|
|
@ -27,15 +27,17 @@ export default function AgPDFTemplate(props: Props) {
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<Document>
|
<Document>
|
||||||
<Page size={"A4"} style={pdfStyle.page}>
|
{props.content.map(page => (
|
||||||
|
<Page size={"A4"} style={pdfStyle.page}>
|
||||||
<View style={pdfStyle.header}>
|
<View style={pdfStyle.header}>
|
||||||
<Header />
|
<Header />
|
||||||
</View>
|
</View>
|
||||||
<View style={pdfStyle.content}>{props.content}</View>
|
<View style={pdfStyle.content}>{page}</View>
|
||||||
<View style={pdfStyle.footer}>
|
<View style={pdfStyle.footer}>
|
||||||
<Footer />
|
<Footer />
|
||||||
</View>
|
</View>
|
||||||
</Page>
|
</Page>
|
||||||
|
))}
|
||||||
</Document>
|
</Document>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
src/common/pdfTemplates/MiPCA/components/footer.tsx
Normal file
31
src/common/pdfTemplates/MiPCA/components/footer.tsx
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { Image, StyleSheet, View } from "@react-pdf/renderer";
|
||||||
|
import agFooter from "common/pdfTemplates/Agriculture/components/footerImages/agFooter.png";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default function Footer() {
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
view: {
|
||||||
|
flexDirection: "row",
|
||||||
|
fontStyle: "normal",
|
||||||
|
fontWeight: 650,
|
||||||
|
borderTop: "1px solid black",
|
||||||
|
padding: 10
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
width: "20%"
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
width: "40%"
|
||||||
|
},
|
||||||
|
phone: {
|
||||||
|
width: "40%"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<View style={styles.view}>
|
||||||
|
<Image src={agFooter} />
|
||||||
|
</View>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
32
src/common/pdfTemplates/MiPCA/components/header.tsx
Normal file
32
src/common/pdfTemplates/MiPCA/components/header.tsx
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { Image, StyleSheet, Text, View } from "@react-pdf/renderer";
|
||||||
|
import moment from "moment";
|
||||||
|
import React from "react";
|
||||||
|
import logo from "assets/whitelabels/AdaptiveAgriculture/AgLogoText.png";
|
||||||
|
|
||||||
|
export default function Header() {
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
view: {
|
||||||
|
flexDirection: "row",
|
||||||
|
fontStyle: "normal",
|
||||||
|
fontWeight: 650,
|
||||||
|
borderBottom: "1px solid black"
|
||||||
|
},
|
||||||
|
logo: {
|
||||||
|
width: "55%",
|
||||||
|
textAlign: "left",
|
||||||
|
paddingBottom: 15
|
||||||
|
},
|
||||||
|
estimate: {
|
||||||
|
width: "45%",
|
||||||
|
textAlign: "right"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<View style={styles.view}>
|
||||||
|
<Image style={styles.logo} src={logo} />
|
||||||
|
<Text style={styles.estimate}>{moment().format("YYYY-MM-DD")}</Text>
|
||||||
|
</View>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
43
src/common/pdfTemplates/MiPCA/mipcaPDFTemplate.tsx
Normal file
43
src/common/pdfTemplates/MiPCA/mipcaPDFTemplate.tsx
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { Document, Page, StyleSheet, View } from "@react-pdf/renderer";
|
||||||
|
import Header from "./components/header";
|
||||||
|
import Footer from "./components/footer";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
content: JSX.Element[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function MiPCAPDFTemplate(props: Props) {
|
||||||
|
const pdfStyle = StyleSheet.create({
|
||||||
|
page: {
|
||||||
|
fontSize: 11,
|
||||||
|
padding: "5%"
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
flexDirection: "row",
|
||||||
|
height: "8%"
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
flexDirection: "row",
|
||||||
|
height: "87%"
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
height: "5%"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<Document>
|
||||||
|
{props.content.map(page => (
|
||||||
|
<Page size={"A4"} style={pdfStyle.page}>
|
||||||
|
<View style={pdfStyle.header}>
|
||||||
|
<Header />
|
||||||
|
</View>
|
||||||
|
<View style={pdfStyle.content}>{page}</View>
|
||||||
|
<View style={pdfStyle.footer}>
|
||||||
|
<Footer />
|
||||||
|
</View>
|
||||||
|
</Page>
|
||||||
|
))}
|
||||||
|
</Document>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Gate } from "models/Gate";
|
import { Gate } from "models/Gate";
|
||||||
import { Box, Card, IconButton, List, ListItem, ListItemText, Theme, Typography } from "@mui/material";
|
import { Box, Button, Card, IconButton, List, ListItem, ListItemText, Theme, Typography } from "@mui/material";
|
||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useMobile } from "hooks";
|
import { useMobile } from "hooks";
|
||||||
|
|
@ -13,6 +13,7 @@ import GateSettings from "./GateSettings";
|
||||||
import { useGateAPI, useGlobalState } from "providers";
|
import { useGateAPI, useGlobalState } from "providers";
|
||||||
import { Settings } from "@mui/icons-material";
|
import { Settings } from "@mui/icons-material";
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
|
import GateReports from "reports/MiPCA/GateReports";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
//gates: Gate[];
|
//gates: Gate[];
|
||||||
|
|
@ -54,6 +55,7 @@ export default function GateList(props: Props) {
|
||||||
const [gates, setGates] = useState<Gate[]>([])
|
const [gates, setGates] = useState<Gate[]>([])
|
||||||
const [selectedGate, setSelectedGate] = useState<Gate | undefined>()
|
const [selectedGate, setSelectedGate] = useState<Gate | undefined>()
|
||||||
const [search, setSearch] = useState("")
|
const [search, setSearch] = useState("")
|
||||||
|
const [openReports, setOpenReports] = useState(false)
|
||||||
|
|
||||||
const goToGate = (gate: Gate) => {
|
const goToGate = (gate: Gate) => {
|
||||||
let path = "/terminals/" + gate.key;
|
let path = "/terminals/" + gate.key;
|
||||||
|
|
@ -208,6 +210,8 @@ export default function GateList(props: Props) {
|
||||||
const gateTable = () => {
|
const gateTable = () => {
|
||||||
return (
|
return (
|
||||||
<ResponsiveTable<Gate>
|
<ResponsiveTable<Gate>
|
||||||
|
actions={<Button onClick={()=>{setOpenReports(true)}}>Generate Reports</Button>}
|
||||||
|
title="Terminal Gates"
|
||||||
page={tablePage}
|
page={tablePage}
|
||||||
pageSize={pageSize}
|
pageSize={pageSize}
|
||||||
columns={isMobile || props.useMobile ? mobileCols() : desktopCols()}
|
columns={isMobile || props.useMobile ? mobileCols() : desktopCols()}
|
||||||
|
|
@ -237,7 +241,8 @@ export default function GateList(props: Props) {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
return <Box>
|
return (
|
||||||
|
<React.Fragment>
|
||||||
<GateSettings
|
<GateSettings
|
||||||
open={gateDialog}
|
open={gateDialog}
|
||||||
gate={selectedGate}
|
gate={selectedGate}
|
||||||
|
|
@ -256,5 +261,7 @@ export default function GateList(props: Props) {
|
||||||
pulse={gates.length < 1}
|
pulse={gates.length < 1}
|
||||||
/>
|
/>
|
||||||
{gateTable()}
|
{gateTable()}
|
||||||
</Box>
|
<GateReports open={openReports} onClose={()=>{setOpenReports(false)}}/>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,8 @@ export interface IGateInterface {
|
||||||
end: string,
|
end: string,
|
||||||
otherTeam?: string
|
otherTeam?: string
|
||||||
) => Promise<AxiosResponse<pond.ListGateMeasurementsResponse>>;
|
) => Promise<AxiosResponse<pond.ListGateMeasurementsResponse>>;
|
||||||
|
//new call for getting report data for gates
|
||||||
|
gateReportData: (gates: string[], start: string, end: string, otherTeam?: string) => Promise<AxiosResponse<pond.GateReportDataResponse>>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GateAPIcontext = createContext<IGateInterface>({} as IGateInterface);
|
export const GateAPIcontext = createContext<IGateInterface>({} as IGateInterface);
|
||||||
|
|
@ -347,6 +349,24 @@ export default function GateProvider(props: PropsWithChildren<Props>) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const gateReportData = (
|
||||||
|
gates: string[],
|
||||||
|
start: string,
|
||||||
|
end: string,
|
||||||
|
otherTeam?: string
|
||||||
|
) => {
|
||||||
|
const view = otherTeam ? otherTeam : as
|
||||||
|
let url = pondURL("/reports/gates?gateKeys=" + gates.toString() + "&start=" + start + "&end=" + end + "&as=" + view)
|
||||||
|
return new Promise<AxiosResponse<pond.GateReportDataResponse>>((resolve, reject) => {
|
||||||
|
get<pond.GateReportDataResponse>(url).then(resp => {
|
||||||
|
resp.data = pond.GateReportDataResponse.fromObject(resp.data)
|
||||||
|
return resolve(resp)
|
||||||
|
}).catch(err => {
|
||||||
|
return reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GateAPIcontext.Provider
|
<GateAPIcontext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
|
@ -360,7 +380,8 @@ export default function GateProvider(props: PropsWithChildren<Props>) {
|
||||||
updatePrefs,
|
updatePrefs,
|
||||||
listGateAirflow,
|
listGateAirflow,
|
||||||
listGateMeasurements,
|
listGateMeasurements,
|
||||||
listGateFlowEvents
|
listGateFlowEvents,
|
||||||
|
gateReportData
|
||||||
}}>
|
}}>
|
||||||
{children}
|
{children}
|
||||||
</GateAPIcontext.Provider>
|
</GateAPIcontext.Provider>
|
||||||
|
|
|
||||||
191
src/reports/MiPCA/GateReports.tsx
Normal file
191
src/reports/MiPCA/GateReports.tsx
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
import { Box, Button, CircularProgress, DialogActions, DialogContent, DialogTitle, Typography } from "@mui/material"
|
||||||
|
import MiPCAPDFTemplate from "common/pdfTemplates/MiPCA/mipcaPDFTemplate"
|
||||||
|
import ResponsiveDialog from "common/ResponsiveDialog"
|
||||||
|
import ResponsiveTable from "common/ResponsiveTable"
|
||||||
|
import { GetDefaultDateRange } from "common/time/DateRange"
|
||||||
|
import DateSelect from "common/time/DateSelect"
|
||||||
|
import { cloneDeep } from "lodash"
|
||||||
|
import { Gate } from "models/Gate"
|
||||||
|
import { Moment } from "moment"
|
||||||
|
import { pond } from "protobuf-ts/pond"
|
||||||
|
import { useGateAPI } from "providers"
|
||||||
|
import React, { useEffect, useState } from "react"
|
||||||
|
import GateReportPDF from "./pdfComponents.tsx/GateReportPDF"
|
||||||
|
import { PDFViewer, StyleSheet } from "@react-pdf/renderer"
|
||||||
|
import { useMobile } from "hooks"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
open: boolean
|
||||||
|
onClose: () => void
|
||||||
|
gate?: string //if the gate key is passed in just generate for that gate, otherwise give the user a way of selecting which gates
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function GateReports(props: Props){
|
||||||
|
const {gate, open, onClose} = props
|
||||||
|
const gateAPI = useGateAPI()
|
||||||
|
const [allGates, setAllGates] = useState<Gate[]>([])
|
||||||
|
const [displayedGates, setDisplayedGates] = useState<Gate[]>([])
|
||||||
|
const [pagesize, setPageSize] = useState(10)
|
||||||
|
const [page, setPage] = useState(0)
|
||||||
|
const [gateKeys, setGateKeys] = useState<string[]>([])
|
||||||
|
const [selectedTableRows,setSelectedTableRows] = useState<number[]>([])
|
||||||
|
const [reportPages, setReportPages] = useState<JSX.Element[]>([])
|
||||||
|
const [loadingReportData, setLoadingReportData] = useState(false)
|
||||||
|
const defaultDateRange = GetDefaultDateRange();
|
||||||
|
const [startDate, setStartDate] = useState<Moment>(defaultDateRange.start);
|
||||||
|
const [endDate, setEndDate] = useState<Moment>(defaultDateRange.end);
|
||||||
|
const isMobile = useMobile()
|
||||||
|
const pdfStyle = StyleSheet.create({
|
||||||
|
viewerDesktop: {
|
||||||
|
height: 500 * 1.44,
|
||||||
|
width: 500
|
||||||
|
},
|
||||||
|
viewerMobile: {
|
||||||
|
height: "100%",
|
||||||
|
width: "100%"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const closeDialog = () => {
|
||||||
|
setGateKeys([])
|
||||||
|
setSelectedTableRows([])
|
||||||
|
setReportPages([])
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
//load all of the gates for the user/team
|
||||||
|
useEffect(()=>{
|
||||||
|
if(open){
|
||||||
|
if(gate) {
|
||||||
|
setGateKeys([gate])
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
gateAPI.listGates(0, 0).then(resp => {
|
||||||
|
if(resp.data.gates){
|
||||||
|
setAllGates(resp.data.gates.map(g => Gate.create(g)))
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},[gate, open])
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
let start = page*pagesize
|
||||||
|
let offset = pagesize
|
||||||
|
setDisplayedGates(allGates.slice(start, start+offset))
|
||||||
|
},[allGates, page, pagesize])
|
||||||
|
|
||||||
|
//selection table to select which gates to generate a report
|
||||||
|
const gateTable = () => {
|
||||||
|
return (
|
||||||
|
<ResponsiveTable<Gate>
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
title: "Gate",
|
||||||
|
render: row => <Typography>{row.name}</Typography>
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
selectedRows={selectedTableRows}
|
||||||
|
rowSelect={(gate, tableIndex, checked) => {
|
||||||
|
let rowIndexes = cloneDeep(selectedTableRows)
|
||||||
|
let keys = cloneDeep(gateKeys)
|
||||||
|
if(checked){
|
||||||
|
if(!selectedTableRows.includes(tableIndex)) rowIndexes.push(tableIndex)
|
||||||
|
if(!gateKeys.includes(gate.key)) keys.push(gate.key)
|
||||||
|
}else{
|
||||||
|
if(rowIndexes.includes(tableIndex)) rowIndexes.splice(rowIndexes.indexOf(tableIndex), 1)
|
||||||
|
if(keys.includes(gate.key)) keys.splice(keys.indexOf(gate.key), 1)
|
||||||
|
}
|
||||||
|
setSelectedTableRows(rowIndexes)
|
||||||
|
setGateKeys(keys)
|
||||||
|
}}
|
||||||
|
rows={displayedGates}
|
||||||
|
total={allGates.length}
|
||||||
|
pageSize={pagesize}
|
||||||
|
page={page}
|
||||||
|
setPage={(page) => {
|
||||||
|
setPage(page)
|
||||||
|
}}
|
||||||
|
handleRowsPerPageChange={(event) => {
|
||||||
|
setPageSize(event.target.value)
|
||||||
|
}} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
//two text field select boxes to select the start and end dates
|
||||||
|
const dateSelect = () => {
|
||||||
|
return (
|
||||||
|
<DateSelect
|
||||||
|
startDate={startDate}
|
||||||
|
endDate={endDate}
|
||||||
|
updateDateRange={(start, end) => {
|
||||||
|
setStartDate(start)
|
||||||
|
setEndDate(end)
|
||||||
|
}}
|
||||||
|
label="Build Reports For"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* new api call for gates that takes in an array of gate keys to build the report data for
|
||||||
|
* this call will return an array of the gate report data
|
||||||
|
* in the return loop through the data building a pdf report for each one
|
||||||
|
*/
|
||||||
|
const generateReports = () => {
|
||||||
|
setLoadingReportData(true)
|
||||||
|
gateAPI.gateReportData(gateKeys, startDate.toISOString(), endDate.toISOString()).then(resp => {
|
||||||
|
console.log(resp)
|
||||||
|
let pdfPages: JSX.Element[] = []
|
||||||
|
if(resp.data.data){
|
||||||
|
resp.data.data.forEach(reportData => {
|
||||||
|
pdfPages.push(<GateReportPDF reportData={reportData}/>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
setReportPages(pdfPages)
|
||||||
|
}).catch(err => {
|
||||||
|
|
||||||
|
}).finally(()=>{
|
||||||
|
//in the finally set the loading to false
|
||||||
|
setLoadingReportData(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ResponsiveDialog open={open} onClose={() => {closeDialog()}}>
|
||||||
|
<DialogTitle>Gate Reports</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
{loadingReportData ?
|
||||||
|
<Box display="flex" justifyContent="center">
|
||||||
|
<CircularProgress color="primary" size={100}/>
|
||||||
|
</Box>
|
||||||
|
:
|
||||||
|
<React.Fragment>
|
||||||
|
{reportPages.length > 0 ?
|
||||||
|
<Box>
|
||||||
|
<PDFViewer style={isMobile ? pdfStyle.viewerMobile : pdfStyle.viewerDesktop}>
|
||||||
|
<MiPCAPDFTemplate content={reportPages}/>
|
||||||
|
</PDFViewer>
|
||||||
|
</Box> :
|
||||||
|
<Box>
|
||||||
|
{dateSelect()}
|
||||||
|
{!gate && gateTable()}
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={()=>{
|
||||||
|
closeDialog()
|
||||||
|
}}>Close</Button>
|
||||||
|
<Button variant="contained" color="primary" disabled={loadingReportData} onClick={()=>{
|
||||||
|
generateReports()
|
||||||
|
}}>Generate Reports</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</ResponsiveDialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
29
src/reports/MiPCA/pdfComponents.tsx/GateReportPDF.tsx
Normal file
29
src/reports/MiPCA/pdfComponents.tsx/GateReportPDF.tsx
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { View, StyleSheet } from "@react-pdf/renderer";
|
||||||
|
import { pond } from "protobuf-ts/pond";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
reportData: pond.GateReportData
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function GateReportPDF(props: Props){
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
general: {
|
||||||
|
marginTop: 2,
|
||||||
|
flexDirection: "row",
|
||||||
|
borderTop: "1px solid black",
|
||||||
|
borderBottom: "1px solid black",
|
||||||
|
paddingTop: 12,
|
||||||
|
paddingBottom: 12,
|
||||||
|
fontFamily: "Helvetica-Bold",
|
||||||
|
fontSize: 20,
|
||||||
|
textAlign: "center"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<View style={styles.general}>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue