Files
qqq-frontend-material-dashb…/src/qqq/pages/dashboards/Overview.tsx

362 lines
13 KiB
TypeScript

/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2022. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance";
import Grid from "@mui/material/Grid";
import Icon from "@mui/material/Icon";
import Tooltip from "@mui/material/Tooltip";
import {useContext, useEffect, useState} from "react";
import QContext from "QContext";
import DashboardLayout from "qqq/components/DashboardLayout";
import Footer from "qqq/components/Footer";
import Navbar from "qqq/components/Navbar";
import MDBox from "qqq/components/Temporary/MDBox";
import MDTypography from "qqq/components/Temporary/MDTypography";
import BarChart from "qqq/pages/dashboards/Widgets/BarChart";
import {GenericChartDataSingleDataset} from "qqq/pages/dashboards/Widgets/Data/GenericChartDataSingleDataset";
import LocationCard, {LocationCardData} from "qqq/pages/dashboards/Widgets/LocationCard";
import {PieChartData} from "qqq/pages/dashboards/Widgets/PieChart";
import PieChartCard from "qqq/pages/dashboards/Widgets/PieChartCard";
import ShipmentsByWarehouse from "qqq/pages/dashboards/Widgets/ShipmentsByWarehouse";
import SmallLineChart from "qqq/pages/dashboards/Widgets/SmallLineChart";
import StatisticsCard, {StatisticsCardData} from "qqq/pages/dashboards/Widgets/StatisticsCard";
import QClient from "qqq/utils/QClient";
const qController = QClient.getInstance();
function Overview(): JSX.Element
{
//////////////////////////////////
// shipments by day widget data //
//////////////////////////////////
const [shipmentsByDayTitle, setShipmentsByDayTitle] = useState("");
const [shipmentsByDayDescription, setShipmentsByDayDescription] = useState("");
const [shipmentsByDayData, setShipmentsByDayData] = useState({} as GenericChartDataSingleDataset);
const [shipmentsByMonthTitle, setShipmentsByMonthTitle] = useState("");
const [shipmentsByMonthDescription, setShipmentsByMonthDescription] = useState("");
const [shipmentsByMonthData, setShipmentsByMonthData] = useState({} as GenericChartDataSingleDataset);
const [shipmentsByCarrierTitle, setShipmentsByCarrierTitle] = useState("");
const [shipmentsByCarrierDescription, setShipmentsByCarrierDescription] = useState("");
const [shipmentsByCarrierData, setShipmentsByCarrierData] = useState({} as PieChartData);
const [todaysShipmentsData, setTodaysShipmentsData] = useState({} as StatisticsCardData);
const [shipmentsInTransitData, setShipmentsInTransitData] = useState({} as StatisticsCardData);
const [openOrdersData, setOpenOrdersData] = useState({} as StatisticsCardData);
const [shippingExceptionsData, setShippingExceptionsData] = useState({} as StatisticsCardData);
const [warehouseData, setWarehouseData] = useState([] as LocationCardData[]);
const [qInstance, setQInstance] = useState(null as QInstance);
const {pageHeader, setPageHeader} = useContext(QContext);
//////////////////////////
// load meta data first //
//////////////////////////
useEffect(() =>
{
setPageHeader("Overview");
(async () =>
{
const newQInstance = await qController.loadMetaData();
setQInstance(newQInstance);
})();
}, []);
///////////////////////////////////////////////////
// once meta data has loaded, load widgets' data //
///////////////////////////////////////////////////
useEffect(() =>
{
if (!qInstance)
{
return;
}
loadShipmentsByDayData();
loadShipmentsByMonthData();
loadYTDShipmentsByCarrierData();
loadTodaysShipmentsData();
loadShipmentsInTransitData();
loadOpenOrdersData();
loadShippingExceptionsData();
loadWarehouseData();
}, [qInstance]);
function loadShipmentsByDayData()
{
(async () =>
{
const widgetData = await qController.widget("TotalShipmentsByDayBarChart");
////////////////////////////////////////////////////////////
// calculate average and number of days over that average //
////////////////////////////////////////////////////////////
let dataValues = widgetData.chartData.dataset.data;
let totalShipments = 0;
for (let i = 0; i < dataValues.length; i++)
{
totalShipments += dataValues[i];
}
let daysOverAverage = 0;
let average = Math.floor(totalShipments / 7);
for (let i = 0; i < dataValues.length; i++)
{
if (dataValues[i] > average)
{
daysOverAverage++;
}
}
const description = "Over the last week there have been <strong>" + daysOverAverage.toLocaleString() + (daysOverAverage == 1 ? " day" : " days") + "</strong> with total shipments greater than the daily average of <strong>" + average.toLocaleString() + " shipments</strong>.";
setShipmentsByDayTitle(widgetData.title);
setShipmentsByDayData(widgetData.chartData);
setShipmentsByDayDescription(description);
})();
}
function loadShipmentsByMonthData()
{
(async () =>
{
const widgetData = await qController.widget("TotalShipmentsByMonthLineChart");
/////////////////////////////////////////////
// calculate if 'increasing or decreasing' //
/////////////////////////////////////////////
let dataValues = widgetData.chartData.dataset.data;
let firstHalf = 0;
let secondHalf = 0;
for (let i = 0; i < dataValues.length; i++)
{
if (i < dataValues.length / 2)
{
firstHalf += dataValues[i];
}
else
{
secondHalf += dataValues[i];
}
}
const description = "Total shipments have been <strong>" + ((secondHalf >= firstHalf) ? "increasing" : "decreasing") + "</strong> over the last eight months.";
setShipmentsByMonthTitle(widgetData.title);
setShipmentsByMonthDescription(description);
setShipmentsByMonthData(widgetData.chartData);
})();
}
function loadYTDShipmentsByCarrierData()
{
(async () =>
{
const widgetData = await qController.widget("YTDShipmentsByCarrierPieChart");
setShipmentsByCarrierTitle(widgetData.title);
setShipmentsByCarrierDescription(widgetData.description);
setShipmentsByCarrierData(widgetData.chartData);
})();
}
function loadTodaysShipmentsData()
{
(async () =>
{
const widgetData = await qController.widget("TodaysShipmentsStatisticsCard");
setTodaysShipmentsData(widgetData);
})();
}
function loadShipmentsInTransitData()
{
(async () =>
{
const widgetData = await qController.widget("ShipmentsInTransitStatisticsCard");
setShipmentsInTransitData(widgetData);
})();
}
function loadOpenOrdersData()
{
(async () =>
{
const widgetData = await qController.widget("OpenOrdersStatisticsCard");
setOpenOrdersData(widgetData);
})();
}
function loadShippingExceptionsData()
{
(async () =>
{
const widgetData = await qController.widget("ShippingExceptionsStatisticsCard");
setShippingExceptionsData(widgetData);
})();
}
function loadWarehouseData()
{
(async () =>
{
const widgetData = await qController.widget("WarehouseLocationCards");
setWarehouseData(widgetData);
})();
}
const actionButtons = (
<>
<Tooltip title="Refresh" placement="bottom">
<MDTypography
variant="body1"
color="primary"
lineHeight={1}
sx={{cursor: "pointer", mx: 3}}
>
<Icon color="inherit">refresh</Icon>
</MDTypography>
</Tooltip>
<Tooltip title="Edit" placement="bottom">
<MDTypography variant="body1" color="info" lineHeight={1} sx={{cursor: "pointer", mx: 3}}>
<Icon color="inherit">edit</Icon>
</MDTypography>
</Tooltip>
</>
);
return (
<DashboardLayout>
<Navbar />
<MDBox py={3}>
<Grid container>
<ShipmentsByWarehouse />
</Grid>
<MDBox mt={6}>
<Grid container spacing={3}>
<Grid item xs={12} md={6} lg={4}>
<MDBox mb={3}>
<BarChart
color="info"
title={qInstance?.widgets?.get("TotalShipmentsByDayBarChart").label}
description={shipmentsByDayDescription}
date="Updated 3 minutes ago"
data={shipmentsByDayData}
/>
</MDBox>
</Grid>
<Grid item xs={12} md={6} lg={4}>
<MDBox mb={3}>
<PieChartCard
title={qInstance?.widgets?.get("YTDShipmentsByCarrierPieChart").label}
description={shipmentsByCarrierDescription}
data={shipmentsByCarrierData}
/>
</MDBox>
</Grid>
<Grid item xs={12} md={6} lg={4}>
<MDBox mb={3}>
<SmallLineChart
color="dark"
title={qInstance?.widgets?.get("TotalShipmentsByMonthLineChart").label}
description={shipmentsByMonthDescription}
date=""
chart={shipmentsByMonthData}
/>
</MDBox>
</Grid>
</Grid>
</MDBox>
<MDBox mt={1.5}>
<Grid container spacing={3}>
<Grid item xs={12} md={6} lg={3}>
<MDBox mb={1.5}>
<StatisticsCard
icon="widgets"
data={todaysShipmentsData}
increaseIsGood={true}
/>
</MDBox>
</Grid>
<Grid item xs={12} md={6} lg={3}>
<MDBox mb={1.5}>
<StatisticsCard
icon="local_shipping"
data={shipmentsInTransitData}
increaseIsGood={true}
/>
</MDBox>
</Grid>
<Grid item xs={12} md={6} lg={3}>
<MDBox mb={1.5}>
<StatisticsCard
color="warning"
icon="receipt"
data={openOrdersData}
increaseIsGood={true}
/>
</MDBox>
</Grid>
<Grid item xs={12} md={6} lg={3}>
<MDBox mb={1.5}>
<StatisticsCard
color="error"
icon="error"
data={shippingExceptionsData}
increaseIsGood={false}
/>
</MDBox>
</Grid>
</Grid>
</MDBox>
<MDBox mt={2}>
<Grid container spacing={3}>
{
warehouseData && warehouseData.map((data) => (
<Grid item xs={12} md={6} lg={4} key={data.title}>
<MDBox mt={3}>
<LocationCard
locationData={data}
action={actionButtons}
/>
</MDBox>
</Grid>
))
}
</Grid>
</MDBox>
</MDBox>
<Footer />
</DashboardLayout>
);
}
export default Overview;