import React from "react";
-import { Button, Card } from "antd";
+import { Card } from "antd";
+import { blueGrey } from "@mui/material/colors";
+
/**
*
* MenuBoardItemCard function is used to generate the item cards used in the menu board.
- *
+ * @return A Card display component for an individual menu item, used for the menu board component.
*
*/
const MenuBoardItemCard = ({item}) => {
@@ -40,28 +42,21 @@ Source: client/src/components/MenuBoardCards.js
<div >
<Card
hoverable
- style ={{width:250,marginBottom: 20, marginLeft: 20, fontSize: '8px', background: '#F2F4F4'}}
+ style ={{background: '#F2F4F4', height:210, lineHeight:1}}
cover={
<img
+ style ={{width:130, marginLeft:'60px'}}
alt={item.itemname}
src={item.imageLink}
/>
}
>
- <Meta title={item.itemname}
- description = {
- <div className="item-description">
- <p>
- {item.itemname}
- </p>
- <p className="price">
- {"$" + item.price}
- </p>
- </div>
-
- } />
-
-
+ <div style ={{fontSize:'16px'}}>
+ {item.itemname}
+ </div>
+ <div className="price" style ={{fontSize:'13px', color: '#FF0000'}} >
+ {"$" + item.price}
+ </div>
</Card>
</div>
)
@@ -77,13 +72,13 @@ Source: client/src/components/MenuBoardCards.js
- Classes Global
+ Classes Global
- Documentation generated by JSDoc 4.0.2 on Mon May 01 2023 12:40:59 GMT-0500 (Central Daylight Time)
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
diff --git a/docs/client_src_components_MenuItemTable.js.html b/docs/client_src_components_MenuItemTable.js.html
new file mode 100644
index 0000000..0fce9f0
--- /dev/null
+++ b/docs/client_src_components_MenuItemTable.js.html
@@ -0,0 +1,264 @@
+
+
+
+
+ JSDoc: Source: client/src/components/MenuItemTable.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/components/MenuItemTable.js
+
+
+
+
+
+
+
+
+ import React, { useState,useEffect } from 'react';
+import MaterialReactTable from 'material-react-table';
+import axios from 'axios';
+import Box from '@mui/material/Box'
+import Button from '@mui/material/Button'
+import ShoppingCartOutlinedIcon from '@mui/icons-material/ShoppingCartOutlined';
+
+const config = {
+ headers: {
+ "Access-Control-Allow-Origin": "*",
+ "Access-Control-Allow-Methods": "GET,PUT,POST,DELETE,PATCH,OPTIONS"
+ }
+};
+
+/**
+ *
+ * @param {*} props - Functions/data to use from the parent component (ServerPage.js)
+ * @returns The Menu Item Table component for the CFA Employee to use. Contains buttons to switch categories,
+ * and a Material React table which displays the menu items to view/add menu items to an order.
+ */
+const MenuItemTable = (props) => {
+
+ const [MenuData, setMenuData] = useState([]);
+
+ useEffect(() => {
+ getAllMenu()
+ },[])
+
+ const columns = [
+ {
+ id: 'menuItem', //id is still required when using accessorFn instead of accessorKey
+ header: 'Menu Item',
+ accessorKey: 'itemname',
+ size: 100,
+
+ Cell: ({ renderedCellValue, row }) => (
+ <Box
+ sx={{
+ display: 'flex',
+ alignItems: 'center',
+ gap: '1rem',
+ }}
+ >
+ <Button variant = "contained"
+ style = {{width: '100px', fontSize: '12px'}}
+ onClick={() => {
+ alert("Adding " + row.original.itemname + " to order!")
+ props.AddItem(row.original.itemname);
+ }
+ }>
+ Add Item
+ </Button>
+ <img
+ alt="avatar"
+ height={50}
+ src={(row.original.imageLink)}
+ loading="lazy"
+ style={{ borderRadius: '50%' }}
+ />
+ {/* using renderedCellValue instead of cell.getValue() preserves filter match highlighting */}
+ <span>{renderedCellValue}</span>
+ </Box>
+ ),
+ },
+ {
+ size: 50,
+ accessorKey: 'price',
+ header: 'Price($)',
+ },
+ {
+ size: 50,
+ accessorKey: 'category',
+ header: 'Category',
+ },
+
+ ];
+
+ const getAllMenu = async() => {
+ axios.get(`https://pern-project-3.onrender.com/serverPage`, config)
+ .then(res => {
+ const menuData = res.data;
+ setMenuData(menuData);
+ //console.log(menuData);
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+ const getEntrees = async() => {
+ axios.get(`https://pern-project-3.onrender.com/serverPage/getEntrees`, config)
+ .then(res => {
+ const menuData = res.data;
+ setMenuData(menuData);
+ //console.log(menuData);
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+ const getSides = async() => {
+ axios.get(`https://pern-project-3.onrender.com/serverPage/getSides`, config)
+ .then(res => {
+ const menuData = res.data;
+ setMenuData(menuData);
+ //console.log(menuData);
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+ const getDesserts = async() => {
+ axios.get(`https://pern-project-3.onrender.com/serverPage/getDesserts`, config)
+ .then(res => {
+ const menuData = res.data;
+ setMenuData(menuData);
+ //console.log(menuData);
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+
+ return (
+ <div>
+ <div className = "server-tab">
+ <Button
+ variant = "outlined"
+ style={{fontSize : '18px',paddingLeft : '3%', paddingRight : '3%', alignContent : 'center', flexDirection : 'column', marginBottom : '10px', textTransform : 'capitalize'}}
+ onClick={getEntrees}
+ >
+ <script src="https://cdn.lordicon.com/ritcuqlt.js"></script>
+ <lord-icon
+ src="https://cdn.lordicon.com/xnfkhcfn.json"
+ trigger="hover"
+ colors="primary:#c71f16,secondary:#121331"
+ style={{width:'75px' ,height:'75px'}}>
+ </lord-icon>
+ <p>
+ Entrees
+ </p>
+ </Button>
+
+ <Button
+ variant = "outlined"
+ style={{fontSize : '18px' ,marginLeft : '3%', paddingLeft : '3%', paddingRight : '3%', alignContent : 'center', flexDirection : 'column', marginBottom : '10px', textTransform : 'capitalize'}}
+ onClick = {getSides}
+ >
+ <script src="https://cdn.lordicon.com/ritcuqlt.js"></script>
+ <lord-icon
+ src="https://cdn.lordicon.com/fkytfmrm.json"
+ trigger="hover"
+ colors="primary:#121331,secondary:#c71f16"
+ style={{width:'75px',height:'75px'}}>
+ </lord-icon>
+ <p>
+ Sides
+ </p>
+ </Button>
+
+ <Button
+ variant = "outlined"
+ style={{fontSize : '18px' , marginLeft : '3%', paddingLeft : '3%', paddingRight : '3%', alignContent : 'center', flexDirection : 'column', marginBottom : '10px', textTransform : 'capitalize'}}
+ onClick = {getDesserts}
+ >
+ <script src="https://cdn.lordicon.com/ritcuqlt.js"></script>
+ <lord-icon
+ src="https://cdn.lordicon.com/elzyzcar.json"
+ trigger="hover"
+ colors="primary:#121331,secondary:#c71f16"
+ style={{width:'75px',height:'75px'}}>
+ </lord-icon>
+ <p>
+ Desserts
+ </p>
+ </Button>
+ <div className='order-info'>
+ <div className = 'shopping-cart'>
+ <div id = 'num-items'>
+ {props.OrderItems.length}
+ </div>
+ <ShoppingCartOutlinedIcon></ShoppingCartOutlinedIcon>
+ </div>
+ <h2 id = "total" >
+ Order Total: {props.OrderTotal}
+ </h2>
+ </div>
+ </div>
+ <MaterialReactTable
+ columns={columns}
+ data={MenuData}
+ muiTableHeadCellProps={{
+ //simple styling with the `sx` prop, works just like a style prop in this example
+ sx: {
+ textDecoration: 'underline',
+ fontSize: '22px'
+ },
+ }}
+ muiTableBodyCellProps={{
+ sx: {
+ fontSize : '18px',
+ color : '#1A5276',
+ }
+ }}
+ />
+
+ </div>
+ );
+};
+
+export default MenuItemTable;
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_components_OrderCart.js.html b/docs/client_src_components_OrderCart.js.html
new file mode 100644
index 0000000..1756445
--- /dev/null
+++ b/docs/client_src_components_OrderCart.js.html
@@ -0,0 +1,156 @@
+
+
+
+
+ JSDoc: Source: client/src/components/OrderCart.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/components/OrderCart.js
+
+
+
+
+
+
+
+
+ import React from "react";
+import MaterialReactTable from "material-react-table";
+import Box from "@mui/material/Box";
+import ShoppingCartOutlinedIcon from "@mui/icons-material/ShoppingCartOutlined";
+import { IconButton, Tooltip } from "@mui/material";
+import { Delete } from "@mui/icons-material";
+import { toast } from "react-toastify";
+
+
+const columns = [
+ {
+ accessorKey: "itemname",
+ header: "Menu Item",
+ size: 50,
+ },
+ {
+ size: 50,
+ accessorKey: "price",
+ header: "Price($)",
+ },
+];
+
+/**
+ *
+ * @param {*} props - Functions/data to use from the parent component (ServerPage.js or CustomerPage.js)
+ * @returns Order cart component which displays the current order information to the user and provides
+ * functionalities for removing items, cancelling the order, and creating an order.
+ */
+const OrderCart = (props) => {
+ return (
+ <div>
+ <div className="order-info">
+ <div className="shopping-cart">
+ <div
+ id="num-items"
+ aria-label={"Your cart has " + props.OrderItems.length + " items."}
+ >
+ {props.OrderItems.length}
+ </div>
+ <ShoppingCartOutlinedIcon></ShoppingCartOutlinedIcon>
+ </div>
+ <h2 id="total">Order Total: {props.OrderTotal}</h2>
+ </div>
+ <button className="checkout-button" onClick={props.SendOrder}>
+ Send Order
+ </button>
+ <button className="cancelOrder-button" onClick={props.CancelOrder}>
+ Cancel Order
+ </button>
+ <MaterialReactTable
+ columns={columns}
+ data={props.OrderItems}
+ enableEditing
+ enableRowVirtualization
+ renderRowActions={({ row, table }) => (
+ <Box sx={{ display: "flex", gap: "1rem" }}>
+ <Tooltip
+ arrow
+ placement="right"
+ title="Remove Item"
+ aria-label={"Remove " + row.original.itemname + " from order."}
+ >
+ <IconButton
+ color="error"
+ onClick={() => {
+ toast.success(
+ "Removing " + row.original.itemname + " from order!",
+ {
+ position: "top-center",
+ autoClose: 5000,
+ hideProgressBar: false,
+ closeOnClick: true,
+ pauseOnHover: true,
+ draggable: true,
+ progress: undefined,
+ theme: "colored",
+ }
+ );
+ props.RemoveItem(row.original.itemname);
+ }}
+ >
+ <Delete />
+ </IconButton>
+ </Tooltip>
+ </Box>
+ )}
+ muiTableHeadCellProps={{
+ //simple styling with the `sx` prop, works just like a style prop in this example
+ sx: {
+ fontSize: "22px",
+ textDecoration: "underline",
+ },
+ }}
+ muiTableBodyCellProps={{
+ sx: {
+ fontSize: "18px",
+ color: "#1A5276",
+ },
+ }}
+ ></MaterialReactTable>
+ </div>
+ );
+};
+
+export default OrderCart;
+
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_components_PendingRestockTable.js.html b/docs/client_src_components_PendingRestockTable.js.html
new file mode 100644
index 0000000..26edb61
--- /dev/null
+++ b/docs/client_src_components_PendingRestockTable.js.html
@@ -0,0 +1,113 @@
+
+
+
+
+ JSDoc: Source: client/src/components/PendingRestockTable.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/components/PendingRestockTable.js
+
+
+
+
+
+
+
+
+ import React from 'react';
+import MaterialReactTable from 'material-react-table';
+import axios from 'axios';
+
+const columns = [
+ {
+ accessorKey: 'id',
+ header: 'ID',
+ size:10
+ },
+ {
+ accessorKey: 'created',
+ header: 'Timestamp Created',
+ size:50
+ },
+];
+
+const config = {
+ headers: {
+ "Access-Control-Allow-Origin": "*",
+ "Access-Control-Allow-Methods": "GET,PUT,POST,DELETE,PATCH,OPTIONS"
+ }
+};
+
+/**
+* UI for a material react table populated with restock orders that have not been marked as arrived in the database
+*/
+export default class PendingRestockTable extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ data : [],
+ };
+ }
+
+ componentDidMount() {
+ axios.get(`https://pern-project-3.onrender.com/PendingRestock`, config)
+ .then(res => {
+ const reportData = res.data;
+ this.setState({ data: reportData });
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+
+ }
+
+ render() {
+ console.log(this.state.data.at(0));
+ return <MaterialReactTable
+ muiTableProps={{sx :{tableLayout:'fixed'}}}
+ defaultColumn={{
+ minSize: 10,
+ maxSize: 100,
+ size: 50,
+ }}
+ columns={columns}
+ data={this.state.data} />;
+ }
+
+};
+
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_components_ReactWeatherComponent.js.html b/docs/client_src_components_ReactWeatherComponent.js.html
new file mode 100644
index 0000000..4adfdfc
--- /dev/null
+++ b/docs/client_src_components_ReactWeatherComponent.js.html
@@ -0,0 +1,106 @@
+
+
+
+
+ JSDoc: Source: client/src/components/ReactWeatherComponent.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/components/ReactWeatherComponent.js
+
+
+
+
+
+
+
+
+ import ReactWeather, { useVisualCrossing } from 'react-open-weather';
+/**
+ * The react weather component function incorporates the weather api into our project that can be used on necessary pages.
+ */
+const ReactWeatherComponent = () => {
+ /*
+ const { data, isLoading, errorMessage } = useWeatherBit({
+ key: '046f513311a64da882b6a3704b15843f',
+ lat: '30.6280',
+ lon: '96.3344',
+ lang: 'en',
+ unit: 'I', // values are (M,S,I)
+ });
+ */
+ const { data, isLoading, errorMessage } = useVisualCrossing({
+ key: '2TT6CDXG43PBKCTEWSF5HNA7J',
+ lat: '30.6280',
+ lon: '-96.314445',
+ lang: 'en',
+ unit: 'us', // values are (metric,us,uk)
+ });
+ const customStyles = {
+ fontFamily: 'Helvetica, sans-serif',
+ gradientStart: '#0181C2',
+ gradientMid: '#04A7F9',
+ gradientEnd: '#4BC4F7',
+ locationFontColor: '#FFF',
+ todayTempFontColor: '#FFF',
+ todayDateFontColor: '#B5DEF4',
+ todayRangeFontColor: '#B5DEF4',
+ todayDescFontColor: '#B5DEF4',
+ todayInfoFontColor: '#B5DEF4',
+ todayIconColor: '#FFF',
+ forecastBackgroundColor: '#FFF',
+ forecastSeparatorColor: '#DDD',
+ forecastDateColor: '#777',
+ forecastDescColor: '#777',
+ forecastRangeColor: '#777',
+ forecastIconColor: '#4BC4F7',
+ };
+ return (
+ <ReactWeather
+ isLoading={isLoading}
+ errorMessage={errorMessage}
+ data={data}
+ lang="en"
+ locationLabel="College Station"
+ unitsLabels={{ temperature: 'F', windSpeed: 'mph' }}
+ showForecast
+ theme={customStyles}
+ height='250px'
+ />
+ );
+};
+
+export default ReactWeatherComponent;
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_components_RestockReportTable.js.html b/docs/client_src_components_RestockReportTable.js.html
new file mode 100644
index 0000000..321a523
--- /dev/null
+++ b/docs/client_src_components_RestockReportTable.js.html
@@ -0,0 +1,106 @@
+
+
+
+
+ JSDoc: Source: client/src/components/RestockReportTable.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/components/RestockReportTable.js
+
+
+
+
+
+
+
+
+ import React, { useMemo } from 'react';
+import MaterialReactTable from 'material-react-table';
+import axios from 'axios';
+
+const columns = [
+ {
+ accessorKey: 'itemname',
+ header: 'Item Name',
+ },
+ {
+ accessorKey: 'currentquantity',
+ header: 'Current Quantity',
+ },
+ {
+ accessorKey: 'minquantity',
+ header: 'Minimum Recommended Quantity',
+ },
+];
+
+const config = {
+ headers: {
+ "Access-Control-Allow-Origin": "*",
+ "Access-Control-Allow-Methods": "GET,PUT,POST,DELETE,PATCH,OPTIONS"
+ }
+};
+/**
+ * The Restock Report Table function builds the table used in the restock report and queries the database for the report.
+ */
+export default class RestockReportTable extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ data : [],
+ };
+ }
+
+ componentDidMount() {
+ axios.get(`https://pern-project-3.onrender.com/RestockReport`, config)
+ .then(res => {
+ const reportData = res.data;
+ this.setState({ data: reportData });
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+
+ }
+
+ render() {
+ console.log(this.state.data.at(0));
+ return <MaterialReactTable columns={columns} data={this.state.data} />;
+ }
+
+};
+
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_components_SalesReportTable.js.html b/docs/client_src_components_SalesReportTable.js.html
index 01e9ae5..6749103 100644
--- a/docs/client_src_components_SalesReportTable.js.html
+++ b/docs/client_src_components_SalesReportTable.js.html
@@ -31,11 +31,7 @@ Source: client/src/components/SalesReportTable.js
import axios from 'axios';
import Moment from 'react-moment';
import moment from 'moment/moment.js';
-/**
- *
- *columns var set up to store the columns of the sales report table from the database
- *
- */
+
const columns = [
{
accessorKey: 'id',
@@ -62,7 +58,7 @@ Source: client/src/components/SalesReportTable.js
}
};
/**
- * SalesReportTable class sets up the table of the sales report page.
+ * @class SalesReportTable class sets up the table of the sales report page.
* This class also queries the database with the values from the date time pickers on the web page.
* It also displays the data.
*/
@@ -75,7 +71,6 @@ Source: client/src/components/SalesReportTable.js
data : [],
};
}
- /** This is a description of the foo function. */
componentDidMount() {
var t = new Date(this.state.start);
var t2 = new Date(this.state.end);
@@ -91,7 +86,6 @@ Source: client/src/components/SalesReportTable.js
console.error(err);
});
};
- /** This is a description of the foo function. */
render(){
console.log(this.state.data.at(0));
return <MaterialReactTable columns={columns} data={this.state.data} />;
@@ -106,13 +100,13 @@ Source: client/src/components/SalesReportTable.js
- Classes Global
+ Classes Global
- Documentation generated by JSDoc 4.0.2 on Mon May 01 2023 12:40:59 GMT-0500 (Central Daylight Time)
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
diff --git a/docs/client_src_components_SignIn.jsx.html b/docs/client_src_components_SignIn.jsx.html
new file mode 100644
index 0000000..3ecdc37
--- /dev/null
+++ b/docs/client_src_components_SignIn.jsx.html
@@ -0,0 +1,94 @@
+
+
+
+
+ JSDoc: Source: client/src/components/SignIn.jsx
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/components/SignIn.jsx
+
+
+
+
+
+
+
+
+ import React, { useEffect } from 'react';
+import { GoogleButton } from 'react-google-button';
+import { UserAuth } from '../login/AuthContext';
+import { useNavigate } from 'react-router-dom';
+/**
+ * The sign in function creates the sign in functionalities and manages them
+ */
+const SignIn = () => {
+ const { googleSignIn, user } = UserAuth();
+ const navigate = useNavigate();
+
+ const handleGoogleSignIn = async () => {
+ try {
+ await googleSignIn();
+ } catch (error) {
+ console.log(error);
+ }
+ };
+
+ useEffect(() => {
+ if (user != null) {
+ if (String(user.email).endsWith('@tamu.edu')) {
+ navigate('/InventoryLevelsEndDayPage');
+ } else {
+ navigate('/ServerPage');
+ }
+ console.log("Successfully logged in");
+ }
+ else {
+ navigate('/');
+ }
+ }, [user]);
+
+ return (
+ <div className='emp-signin'>
+ <h2 className='empHeader-signin'>Employee Sign In</h2>
+ <div>
+ <GoogleButton onClick={handleGoogleSignIn} />
+ </div>
+ </div>
+ );
+};
+
+export default SignIn;
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_pages_CustomerPage.js.html b/docs/client_src_pages_CustomerPage.js.html
new file mode 100644
index 0000000..e3fe326
--- /dev/null
+++ b/docs/client_src_pages_CustomerPage.js.html
@@ -0,0 +1,271 @@
+
+
+
+
+ JSDoc: Source: client/src/pages/CustomerPage.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/pages/CustomerPage.js
+
+
+
+
+
+
+
+
+ import React from 'react';
+import axios from 'axios';
+import { useEffect} from "react";
+import Grid from '@mui/material/Unstable_Grid2';
+import CustomerMenu from '../components/CustomerMenu.js'
+import OrderCart from '../components/OrderCart.js';
+import {ThemeProvider, createTheme } from '@mui/material';
+import lottie from 'lottie-web';
+import { defineElement } from 'lord-icon-element';
+import {Tabs} from 'antd';
+import MenuBoardBar from '../components/MenuBoardBar.js';
+import { ToastContainer, toast } from "react-toastify";
+import "react-toastify/dist/ReactToastify.css";
+
+const config = {
+ headers: {
+ "Access-Control-Allow-Origin": "*",
+ "Access-Control-Allow-Methods": "GET,PUT,POST,DELETE,PATCH,OPTIONS"
+ }
+};
+
+// For the button icons
+document.querySelectorAll('lord-icon').forEach((element) => {
+ element.addEventListener('ready', () => {
+ element.classList.add('ready');
+ });
+});
+defineElement(lottie.loadAnimation);
+
+const theme = createTheme({
+ palette: {
+ primary: {
+ main : '#E51636',
+ }
+ }
+})
+
+/**
+ * Front end implementation of Chick-Fil-A customer kiosk interface
+ * @returns Component with all the functionalities needed for a self-serve Kiosk
+ */
+const CustomerPage = () => {
+
+ /**
+ * Adds a menu item to the order through an XMLHttpRequest to the server and updates the component's state data
+ *
+ * @param {*} ItemName
+ */
+ function addItemHandler(ItemName) {
+ axios.get(`https://pern-project-3.onrender.com/addItem?menuitem=` + ItemName, config)
+ .then(res => {
+ const orderData = res.data.itemsOrdered;
+ const OrderTot = res.data.totalprice;
+ setOrderItems(orderData);
+ setOrderTotal("$"+ OrderTot/100);
+
+ document.getElementById('num-items').innerText = orderItems.length;
+ document.getElementById('total').innerText = "Total price: $" + OrderTot/100;
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+ /**
+ * Removes a menu item from the order through an XMLHttpRequest to the server and updates the component's state data.
+ *
+ * @param {*} ItemName
+ */
+ function removeItemHandler(ItemName) {
+ axios.get(`https://pern-project-3.onrender.com/removeItem?menuitem=` + ItemName, config)
+ .then(res => {
+ const orderData = res.data.itemsOrdered;
+ const OrderTot = res.data.totalprice;
+ setOrderItems(orderData);
+ setOrderTotal("$"+ OrderTot/100);
+
+ document.getElementById('num-items').innerText = orderItems.length;
+ document.getElementById('total').innerText = "Total price: $" + OrderTot/100;
+ })
+ .catch((err) => {
+ console.log(err);
+ })
+ }
+
+ /**
+ * Gets the current order through an XMLHttpRequest to the server and updates the component's state data.
+ *
+ * @param {*} ItemName
+ */
+ function getCurrentOrder() {
+ axios.get(`https://pern-project-3.onrender.com/getOrder`, config)
+ .then(res => {
+ const orderData = res.data.itemsOrdered;
+ const OrderTot = res.data.totalprice;
+ setOrderItems(orderData);
+ setOrderTotal("$"+ OrderTot/100);
+
+ document.getElementById('num-items').innerText = orderItems.length;
+ document.getElementById('total').innerText = "Total price: $" + OrderTot/100;
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+ /**
+ * Creates an order through an XMLHttpRequest to the server and updates the component's state data.
+ *
+ * @param {*} ItemName
+ */
+ function sendOrderHandler() {
+ axios.get(`https://pern-project-3.onrender.com/storeOrder`, config)
+ .then(res => {
+ alert("Your order will now be sent and made!")
+ const orderData = res.data.itemsOrdered;
+ const OrderTot = res.data.totalprice;
+ setOrderItems(orderData);
+ setOrderTotal("$"+ OrderTot/100);
+
+ document.getElementById('num-items').innerText = orderItems.length;
+ document.getElementById('total').innerText = "Total price: $" + OrderTot/100;
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+ /**
+ * Deletes the current order through an XMLHttpRequest to the server and updates the component's state data.
+ *
+ * @param {*} ItemName
+ */
+ function cancelOrderHandler() {
+ axios.get(`https://pern-project-3.onrender.com/cancelOrder`, config)
+ .then(res => {
+ alert("Cancelling order and removing items.")
+ const orderData = res.data.itemsOrdered;
+ const OrderTot = res.data.totalprice;
+ setOrderItems(orderData);
+ setOrderTotal("$"+ OrderTot/100);
+
+ document.getElementById('num-items').innerText = orderItems.length;
+ document.getElementById('total').innerText = "Total price: $" + OrderTot/100;
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+ const [orderItems, setOrderItems] = React.useState([]);
+ const [ordertotal, setOrderTotal] = React.useState("$0");
+
+ useEffect(() => {
+ getCurrentOrder();
+ },[])
+
+ const items = [
+ {
+ label: 'Menu',
+ key: '1',
+ children: <CustomerMenu
+ OrderItems = {orderItems}
+ OrderTotal = {ordertotal}
+ AddItem = {addItemHandler}>
+ </CustomerMenu>
+ },
+ {
+ label: 'View Order',
+ key: '2',
+ children: <OrderCart
+ OrderItems = {orderItems}
+ OrderTotal = {ordertotal}
+ RemoveItem = {removeItemHandler}
+ SendOrder = {sendOrderHandler}
+ CancelOrder = {cancelOrderHandler}
+ >
+
+ </OrderCart>
+ }
+ ]
+
+ return (
+ <ThemeProvider theme={theme}>
+ <div className="serverPage" role="order page">
+ <ToastContainer
+ position="top-center"
+ autoClose={5000}
+ hideProgressBar={false}
+ newestOnTop={false}
+ closeOnClick
+ rtl={false}
+ pauseOnFocusLoss
+ draggable
+ pauseOnHover
+ theme="colored"
+ />
+ <Grid container spacing={2}>
+ <Grid xs={12}>
+ <MenuBoardBar></MenuBoardBar>
+ </Grid>
+ <Grid xs = {12}>
+ <Tabs
+ tabPosition='left'
+ defaultActiveKey='1'
+ items = {items}
+ >
+ </Tabs>
+ </Grid>
+ </Grid>
+
+ </div>
+ </ThemeProvider>
+ );
+
+}
+
+export default CustomerPage;
+
+
+
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_pages_ErrorPage.js.html b/docs/client_src_pages_ErrorPage.js.html
new file mode 100644
index 0000000..de3dfb9
--- /dev/null
+++ b/docs/client_src_pages_ErrorPage.js.html
@@ -0,0 +1,70 @@
+
+
+
+
+ JSDoc: Source: client/src/pages/ErrorPage.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/pages/ErrorPage.js
+
+
+
+
+
+
+
+
+ import { useRouteError } from "react-router-dom";
+import React from 'react';
+/**
+ * The Error Page function builds the error page that shows up when there is an issue with the javascript
+ */
+export default function ErrorPage() {
+ const error = useRouteError();
+ console.error(error);
+
+ return (
+ <div id="error-page">
+ <h1>Oops!</h1>
+ import MenuBoardBar from '../components/MenuBoardBar.js';
+ <p>Sorry, an unexpected error has occurred.</p>
+ <p>
+ <i>{error.statusText || error.message}</i>
+ </p>
+ </div>
+ );
+}
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_pages_LandingPage.js.html b/docs/client_src_pages_LandingPage.js.html
new file mode 100644
index 0000000..362e119
--- /dev/null
+++ b/docs/client_src_pages_LandingPage.js.html
@@ -0,0 +1,85 @@
+
+
+
+
+ JSDoc: Source: client/src/pages/LandingPage.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/pages/LandingPage.js
+
+
+
+
+
+
+
+
+ import React from 'react';
+import ReactWeatherComponent from '../components/ReactWeatherComponent';
+import { Button } from 'antd';
+import { useNavigate } from 'react-router-dom';
+import SignIn from '../components/SignIn';
+
+/**
+ * Frontend implementation of the Landing Page for all users.
+ * @returns Landing page component.
+ */
+export default function LandingPage() {
+ const navigate = useNavigate();
+ return (
+
+ <div className='landing-body'>
+ <div>
+ <div className='CFA-logo'>
+ </div>
+ <h1 className='welcome-header'>
+ Welcome to Chick-Fil-A!
+ </h1>
+ <div className='login-buttons'>
+ <Button className='customer-button'
+ onClick={()=> navigate("/Customer")}>
+ Customers
+ </Button>
+ <SignIn></SignIn>
+ </div>
+ </div>
+ <div id="weather-component">
+ <ReactWeatherComponent />
+ </div>
+ </div>
+ );
+ }
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_pages_LoginPage.js.html b/docs/client_src_pages_LoginPage.js.html
new file mode 100644
index 0000000..8d76d40
--- /dev/null
+++ b/docs/client_src_pages_LoginPage.js.html
@@ -0,0 +1,68 @@
+
+
+
+
+ JSDoc: Source: client/src/pages/LoginPage.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/pages/LoginPage.js
+
+
+
+
+
+
+
+
+ import React from 'react';
+import SignIn from '../components/SignIn';
+/**
+ * Login Page function that sets up the login page and incorporates the sign in component
+ *
+ */
+export default function LoginPage() {
+ return (
+
+ <div id="login-page">
+ <h1>This is a WIP login page</h1>
+ <SignIn></SignIn>
+
+ </div>
+
+ );
+}
+
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_pages_MenuBoard.js.html b/docs/client_src_pages_MenuBoard.js.html
index 3043675..321c840 100644
--- a/docs/client_src_pages_MenuBoard.js.html
+++ b/docs/client_src_pages_MenuBoard.js.html
@@ -34,7 +34,7 @@ Source: client/src/pages/MenuBoard.js
import { styled } from '@mui/material/styles';
import Paper from '@mui/material/Paper';
-import {Row, Col, Button, Card} from 'antd';
+import {Row, Col} from 'antd';
import ItemCard from "../components/MenuBoardCards.js";
import ReactWeatherComponent from "../components/ReactWeatherComponent.js";
@@ -110,8 +110,7 @@ Source: client/src/pages/MenuBoard.js
</Grid>
<Grid xs={12}>
- <ReactWeatherComponent>
- </ReactWeatherComponent>
+ <ReactWeatherComponent />
</Grid>
</Grid>
@@ -130,13 +129,13 @@ Source: client/src/pages/MenuBoard.js
- Classes Global
+ Classes Global
- Documentation generated by JSDoc 4.0.2 on Mon May 01 2023 12:40:59 GMT-0500 (Central Daylight Time)
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
diff --git a/docs/client_src_pages_RestockReportPage.js.html b/docs/client_src_pages_RestockReportPage.js.html
new file mode 100644
index 0000000..ed16263
--- /dev/null
+++ b/docs/client_src_pages_RestockReportPage.js.html
@@ -0,0 +1,103 @@
+
+
+
+
+ JSDoc: Source: client/src/pages/RestockReportPage.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/pages/RestockReportPage.js
+
+
+
+
+
+
+
+
+ import RestockReportTable from '../components/RestockReportTable.js';
+import React from 'react';
+
+import { styled } from '@mui/material/styles';
+//import Box from '@mui/material/Box';
+import Paper from '@mui/material/Paper';
+import Grid from '@mui/material/Unstable_Grid2';
+import MainAppBar from '../components/MainAppBar.js';
+
+import { Typography } from '@mui/material';
+
+const Item = styled(Paper)(({ theme }) => ({
+ backgroundColor: '#fff',
+ ...theme.typography.body2,
+ padding: theme.spacing(1),
+ textAlign: 'center',
+ color: theme.palette.text.secondary,
+}));
+
+// The grid max xs = 12
+/**
+ * Function that builds the restock report page with grids and incorporates the table, app bar
+ */
+function RestockReportPage() {
+ return (
+ <div className="RestockReportPage">
+ <Grid container spacing={2}>
+ <Grid xs={12}>
+ <MainAppBar>
+ </MainAppBar>
+ </Grid>
+
+ <Grid xs={12}>
+ <Item>
+ <Typography variant="h4" component="div" sx={{ flexGrow: 1 }}>
+ Restock Report Table
+ </Typography>
+ </Item>
+ </Grid>
+
+ <Grid xs={12}>
+ <Item>
+ <RestockReportTable />
+ </Item>
+ </Grid>
+
+ </Grid>
+ </div>
+ );
+}
+
+export default RestockReportPage;
+
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_pages_SalesReportPage.js.html b/docs/client_src_pages_SalesReportPage.js.html
index 1852fc0..b0693d2 100644
--- a/docs/client_src_pages_SalesReportPage.js.html
+++ b/docs/client_src_pages_SalesReportPage.js.html
@@ -40,16 +40,7 @@ Source: client/src/pages/SalesReportPage.js
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import SalesReportTable from '../components/SalesReportTable.js';
-/**
- * The request body should be an object with the following properties:
- *
- * {
- * start: int, // 0-23
- * end: int, // 0-23
- * salesWith: "menu_item_id" , //optional (default null)
- * limit: int //optional number of results to return (default 100)
- * }
- */
+
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
@@ -57,22 +48,14 @@ Source: client/src/pages/SalesReportPage.js
textAlign: 'center',
color: theme.palette.text.secondary,
}));
-/**
- *
- * Title created with specific configs
- *
- */
+
const Title = styled(Paper)(({ theme }) => ({
...theme.typography.heading,
padding: theme.spacing(1),
textAlign: 'center',
color: 'black',
}));
-/**
- *
- * theme of the page created with cfa_theme
- *
- */
+
const cfa_theme = createTheme({
palette: {
primary: {
@@ -85,10 +68,8 @@ Source: client/src/pages/SalesReportPage.js
});
/**
*
- * Sales Report Page function used to build the webpage
- * Has setStart, setEnd, and setSubmit vars to help store values from the date timer
- *
- *
+ * Sales Report Page function used to build the sales report page that holds the sales report table
+ * and the date time pickers used to query for that table.
*/
export default function SalesReportPage(){
const [start, setStart] = useState('');
@@ -154,13 +135,13 @@ Source: client/src/pages/SalesReportPage.js
- Classes Global
+ Classes Global
- Documentation generated by JSDoc 4.0.2 on Mon May 01 2023 12:40:59 GMT-0500 (Central Daylight Time)
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
diff --git a/docs/client_src_pages_ServerPage.js.html b/docs/client_src_pages_ServerPage.js.html
new file mode 100644
index 0000000..986c6d7
--- /dev/null
+++ b/docs/client_src_pages_ServerPage.js.html
@@ -0,0 +1,235 @@
+
+
+
+
+ JSDoc: Source: client/src/pages/ServerPage.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/pages/ServerPage.js
+
+
+
+
+
+
+
+
+ import React from 'react';
+import axios from 'axios';
+import { useEffect} from "react";
+import Grid from '@mui/material/Unstable_Grid2';
+import MenuBoardBar from '../components/MenuBoardBar.js';
+import MenuItemTable from '../components/MenuItemTable.js';
+import OrderCart from '../components/OrderCart.js';
+import {ThemeProvider, createTheme } from '@mui/material';
+
+import lottie from 'lottie-web';
+import { defineElement } from 'lord-icon-element';
+import {Tabs} from 'antd';
+
+const config = {
+ headers: {
+ "Access-Control-Allow-Origin": "*",
+ "Access-Control-Allow-Methods": "GET,PUT,POST,DELETE,PATCH,OPTIONS"
+ }
+};
+
+// For the button icons
+document.querySelectorAll('lord-icon').forEach((element) => {
+ element.addEventListener('ready', () => {
+ element.classList.add('ready');
+ });
+});
+defineElement(lottie.loadAnimation);
+
+const theme = createTheme({
+ palette: {
+ primary: {
+ main : '#E51636',
+ }
+ }
+})
+
+/**
+ * Front end implementation of the Chick-Fil-A employee interface.
+ * @returns Component with all of the functionalities required to create a custom order.
+ */
+const ServerPage = () => {
+
+ function addItemHandler(ItemName) {
+ axios.get(`https://pern-project-3.onrender.com/addItem?menuitem=` + ItemName, config)
+ .then(res => {
+ const orderData = res.data.itemsOrdered;
+ const OrderTot = res.data.totalprice;
+ setOrderItems(orderData);
+ setOrderTotal("$"+ OrderTot/100);
+
+ document.getElementById('num-items').innerText = orderItems.length;
+ document.getElementById('total').innerText = "Total price: $" + OrderTot/100;
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+ function removeItemHandler(ItemName) {
+ axios.get(`https://pern-project-3.onrender.com/removeItem?menuitem=` + ItemName, config)
+ .then(res => {
+ const orderData = res.data.itemsOrdered;
+ const OrderTot = res.data.totalprice;
+ setOrderItems(orderData);
+ setOrderTotal("$"+ OrderTot/100);
+
+ document.getElementById('num-items').innerText = orderItems.length;
+ document.getElementById('total').innerText = "Total price: $" + OrderTot/100;
+ })
+ .catch((err) => {
+ console.log(err);
+ })
+ }
+
+ function getCurrentOrder() {
+ axios.get(`https://pern-project-3.onrender.com/getOrder`, config)
+ .then(res => {
+ const orderData = res.data.itemsOrdered;
+ const OrderTot = res.data.totalprice;
+ setOrderItems(orderData);
+ setOrderTotal("$"+ OrderTot/100);
+
+ document.getElementById('num-items').innerText = orderItems.length;
+ document.getElementById('total').innerText = "Total price: $" + OrderTot/100;
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+ function sendOrderHandler() {
+ axios.get(`https://pern-project-3.onrender.com/storeOrder`, config)
+ .then(res => {
+ alert("Your order will now be sent and made!")
+ const orderData = res.data.itemsOrdered;
+ const OrderTot = res.data.totalprice;
+ setOrderItems(orderData);
+ setOrderTotal("$"+ OrderTot/100);
+
+ document.getElementById('num-items').innerText = orderItems.length;
+ document.getElementById('total').innerText = "Total price: $" + OrderTot/100;
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+ function cancelOrderHandler() {
+ axios.get(`https://pern-project-3.onrender.com/cancelOrder`, config)
+ .then(res => {
+ alert("Cancelling order and removing items.")
+ const orderData = res.data.itemsOrdered;
+ const OrderTot = res.data.totalprice;
+ setOrderItems(orderData);
+ setOrderTotal("$"+ OrderTot/100);
+
+ document.getElementById('num-items').innerText = orderItems.length;
+ document.getElementById('total').innerText = "Total price: $" + OrderTot/100;
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
+
+ const [orderItems, setOrderItems] = React.useState([]);
+ const [ordertotal, setOrderTotal] = React.useState("$0");
+
+ useEffect(() => {
+ getCurrentOrder();
+ document.getElementById('bar-description').innerText = "CFA Employee";
+ },[])
+
+ const items = [
+ {
+ label: 'Menu',
+ key: '1',
+ children: <MenuItemTable
+ OrderItems = {orderItems}
+ OrderTotal = {ordertotal}
+ AddItem = {addItemHandler}>
+ </MenuItemTable>
+ },
+ {
+ label: 'View Order',
+ key: '2',
+ children: <OrderCart
+ OrderItems = {orderItems}
+ OrderTotal = {ordertotal}
+ RemoveItem = {removeItemHandler}
+ SendOrder = {sendOrderHandler}
+ CancelOrder = {cancelOrderHandler}
+ >
+
+ </OrderCart>
+ }
+ ]
+
+ return (
+ <ThemeProvider theme={theme}>
+ <div className="serverPage">
+ <Grid container spacing={2}>
+ <Grid xs={12}>
+ <MenuBoardBar>
+ </MenuBoardBar>
+ </Grid>
+ <Grid xs = {12}>
+ <Tabs
+ tabPosition='left'
+ defaultActiveKey='1'
+ items = {items}
+ >
+ </Tabs>
+ </Grid>
+ </Grid>
+
+ </div>
+ </ThemeProvider>
+ );
+
+}
+
+export default ServerPage;
+
+
+
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_pages_TestTranslatePage.js.html b/docs/client_src_pages_TestTranslatePage.js.html
new file mode 100644
index 0000000..2a37b86
--- /dev/null
+++ b/docs/client_src_pages_TestTranslatePage.js.html
@@ -0,0 +1,83 @@
+
+
+
+
+ JSDoc: Source: client/src/pages/TestTranslatePage.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/pages/TestTranslatePage.js
+
+
+
+
+
+
+
+
+ import { useEffect } from "react";
+/**
+ * Sets up the google translate component for our project.
+ */
+const TestTranslatePage = () => {
+ const googleTranslateElementInit = () => {
+ new window.google.translate.TranslateElement(
+ {
+ pageLanguage: "en",
+ autoDisplay: false
+ },
+ "google_translate_element"
+ );
+ };
+ useEffect(() => {
+ var addScript = document.createElement("script");
+ addScript.setAttribute(
+ "src",
+ "//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"
+ );
+ document.body.appendChild(addScript);
+ window.googleTranslateElementInit = googleTranslateElementInit;
+ }, []);
+ return (
+ <>
+ <div id="google_translate_element"></div>
+ <h4>Start building your app. Happy Coding!</h4>
+ </>
+ );
+};
+
+export default TestTranslatePage;
+
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_pages_WhatSalesTogetherPage.js.html b/docs/client_src_pages_WhatSalesTogetherPage.js.html
new file mode 100644
index 0000000..7ba50ab
--- /dev/null
+++ b/docs/client_src_pages_WhatSalesTogetherPage.js.html
@@ -0,0 +1,359 @@
+
+
+
+
+ JSDoc: Source: client/src/pages/WhatSalesTogetherPage.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/pages/WhatSalesTogetherPage.js
+
+
+
+
+
+
+
+
+ import React, { useEffect } from "react";
+
+import { styled } from "@mui/material/styles";
+//import Box from '@mui/material/Box';
+import Paper from "@mui/material/Paper";
+import Grid from "@mui/material/Unstable_Grid2";
+import MainAppBar from "../components/MainAppBar.js";
+import {
+ Button,
+ Card,
+ InputLabel,
+ MenuItem,
+ Select,
+ TextField,
+} from "@mui/material";
+import { width } from "@mui/system";
+import axios from "axios";
+
+/**
+ * Styled item for theme
+ */
+const Item = styled(Paper)(({ theme }) => ({
+ backgroundColor: "#fff",
+ ...theme.typography.body2,
+ padding: theme.spacing(1),
+ textAlign: "center",
+ color: theme.palette.text.secondary,
+}));
+
+/**
+ * Search UI component. Handles user interactions with the search input.
+ * It has two number input field, one dropdown and a search button.
+ * Handles inter states of the input fields and dropdown, filter outs wrong value.
+ * Calls the supplied search function with 3 input parameter
+ *
+ * @param {Function} search- An Async function that takes three parameter
+ *
+ */
+const SearchUI = ({ search }) => {
+
+ /**
+ * Maintains the value of the 3 search UI components
+ */
+ const [startHour, setStartHour] = React.useState(null);
+ const [endHour, setEndHour] = React.useState(null);
+ const [selected, setSelected] = React.useState("");
+
+ /**
+ * Array of menu items to populate the select
+ */
+ const [options, setOptions] = React.useState([]);
+
+
+ /**
+ * This state will hold the error message if the first input field (startHour)
+ * is invalid.
+ */
+ const [error1, setError1] = React.useState(null);
+
+
+ /**
+ * This state will hold the error message if the second input field (EndHour)
+ * is invalid.
+ */
+ const [error2, setError2] = React.useState(null);
+
+ /**
+ * This state will hold the error message to show to the user when
+ * user presses 'search' with invalid inputs
+ */
+ const [error3, setError3] = React.useState(null);
+
+
+ /**
+ *
+ * Handles click on the search button.
+ * validates the input before calling search
+ */
+ const handleSearch = () => {
+ let salesWith = selected;
+ if(selected == "Any Items")
+ salesWith = "";
+
+ if (!error1 && !error2) {
+ if (startHour == null || endHour == null) {
+ setError3("Please choose valid hours first");
+ return;
+ }
+ setError3(null);
+ search(startHour, endHour, salesWith);
+ } else {
+ setError3("Please choose valid hours");
+ }
+ };
+
+ /**
+ * get the list of the menu items to populate the <select>
+ */
+ useEffect(() => {
+ axios
+ .get("http://localhost:3001/menuCustomerView")
+ .then((res) => {
+ setOptions(res.data);
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }, []);
+
+ return (
+ <Card
+ style={{ width: "50%", padding: "20px", maxWidth: "700px" }}
+ variant="elevation"
+ >
+ {/* Starting hour input field */}
+ <Grid container>
+ <Grid xs={6}>
+ <Item>
+ <TextField
+ style={{ width: "100%" }}
+ onChange={(e) => {
+ if (e.target.value > 24) {
+ setError1("Starting hour must be less than 24");
+ } else {
+ setError1(null);
+ setStartHour(e.target.value);
+ }
+ }}
+ label="Starting Hour"
+ type="number"
+ inputProps={{ min: "0", max: "24" }}
+ error={error1 == null ? false : true}
+ helperText={error1}
+ />
+ </Item>
+ </Grid>
+
+ {/* Ending hour input field */}
+ <Grid xs={6}>
+ <Item>
+ <TextField
+ style={{ width: "100%" }}
+ onChange={(e) => {
+ if (e.target.value > 24) {
+ setError2("Ending hour must be less than 24");
+ } else if (e.target.value < startHour) {
+ setError2("Ending hour must be greater than starting hour");
+ } else {
+ setError2(null);
+ setEndHour(e.target.value);
+ }
+ }}
+ error={error2 == null ? false : true}
+ helperText={error2}
+ label="Ending hour"
+ type="number"
+ inputProps={{ min: "0", max: "23" }}
+ />
+ </Item>
+ </Grid>
+
+ {/* Dropdown */}
+ <Grid xs={12}>
+ <Item>
+ <InputLabel>Items that sales with</InputLabel>
+ <Select
+ value={selected}
+ style={{ width: "100%" }}
+ onChange={(e) => {
+ setSelected(e.target.value);
+ }}
+ >
+ <MenuItem value="Any Items">Any items</MenuItem>
+ {options.map((option, i) => {
+ return (
+ <MenuItem key={i} value={option.itemname}>
+ {option.itemname}
+ </MenuItem>
+ );
+ })}
+ </Select>
+ </Item>
+ </Grid>
+ </Grid>
+
+ {/* Search button */}
+ <center>
+ <Button
+ style={{ padding: "10px", margin: "5px" }}
+ onClick={handleSearch}
+ >
+ Get Result
+ </Button>{" "}
+ <br></br>
+ <span style={{ color: "red", fontSize: "14px" }}>{error3}</span>
+ </center>
+ </Card>
+ );
+};
+
+
+
+/**
+ * React component:
+ * Holds an search component consisting of two input field and a dropdown.
+ * Shows A table consisting of pairs of menu items that sales together in a given timeframe.
+ * User can additionally select a menu item to see what sold with that specific menu item in that timeframe
+ *
+ */
+function WhatSalesTogetherPage() {
+
+ /**
+ * Holds the data to show in the table. The data is fetched from the server based
+ * on the search parameters
+ */
+ const [data, setData] = React.useState([]);
+
+ /**
+ * State used to show user that search result is currently being fetched from
+ * server
+ */
+ const [searching, setSearching] = React.useState(false);
+
+
+ /**
+ * Gets the search result from the server
+ * the result is an array of objects, each object has three properties:
+ * item1, item2, and count
+ *
+ * @param {Number} start - starting hour of the timeframe (0-23)
+ * @param {Number} end - ending hour of the timeframe (0-23)
+ * @param {String} salesWith - empty string if we want to get all pairs of menu items that
+ * are sold in that time frame OR a menu item name if we want to
+ * get all pairs of menu items that are sold with that specific menu item
+ */
+ const search = (start, end, salesWith) => {
+ setSearching(true);
+ setData([]);
+ axios
+ .get(
+ `http://localhost:3001/WhatSalesTogether?start=${start}&end=${end}&salesWith=${salesWith}`
+ )
+ .then((res) => {
+ setSearching(false);
+ setData(res.data);
+ })
+ .catch((err) => {
+ console.error(err);
+ searching(false);
+ });
+ };
+
+ return (
+ <div className="RestockReportPage">
+ <Grid container spacing={2}>
+ <Grid xs={12}>
+ <MainAppBar></MainAppBar>
+ </Grid>
+
+ {/* Set the Search UI*/}
+ <Grid xs={12}>
+ <center>
+ <SearchUI search={search} />
+ </center>
+ </Grid>
+
+ <Grid xs={12}>
+ <center>
+ <h2>
+ {searching
+ ? "Getting Result...."
+ : data.length == 0
+ ? "No Result Found!"
+ : "Result"}
+ </h2>
+ </center>
+ {searching || data.length == 0 ? null : (
+ <center>
+ <Item style={{ width: "50%", maxWidth: "500px" }}>
+ {/* Show the search result in a table */}
+ <table border={"black"} style={{ width: "100%" }}>
+ <tr>
+ <th>Pairs</th>
+ <th>Quantity</th>
+ </tr>
+ {data.map((item, i) => {
+ return (
+ <tr key={i}>
+ <td>
+ <span style={{ color: "red" }}>{item.item1}</span>
+ <br></br>
+ <span style={{ color: "red" }}>{item.item2}</span>
+ </td>
+ <td>{item.count}</td>
+ </tr>
+ );
+ })}
+ </table>
+ </Item>
+ </center>
+ )}
+ </Grid>
+ </Grid>
+ </div>
+ );
+}
+
+export default WhatSalesTogetherPage;
+
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/client_src_pages_XZReportPage.js.html b/docs/client_src_pages_XZReportPage.js.html
new file mode 100644
index 0000000..caadafe
--- /dev/null
+++ b/docs/client_src_pages_XZReportPage.js.html
@@ -0,0 +1,127 @@
+
+
+
+
+ JSDoc: Source: client/src/pages/XZReportPage.js
+
+
+
+
+
+
+
+
+
+
+
+
+
Source: client/src/pages/XZReportPage.js
+
+
+
+
+
+
+
+
+ import ZReportTable from '../components/ZReportTable.js';
+import XReportTable from '../components/XReportTable.js';
+import React, {useState} from 'react';
+import { styled, ThemeProvider, createTheme } from '@mui/material/styles';
+import Paper from '@mui/material/Paper';
+import Grid from '@mui/material/Unstable_Grid2';
+import MainAppBar from '../components/MainAppBar.js';
+import Button from '@mui/material/Button';
+import { Typography } from '@mui/material';
+
+const Item = styled(Paper)(({ theme }) => ({
+ backgroundColor: '#fff',
+ ...theme.typography.body2,
+ padding: theme.spacing(1),
+ textAlign: 'center',
+ color: theme.palette.text.secondary,
+}));
+
+
+const cfa_theme = createTheme({
+ palette: {
+ primary: {
+ main: '#E51636',
+ },
+ secondary: {
+ main: '#E51636',
+ },
+ },
+});
+
+/**
+ * UI for the X and Z report page using boolean logic to display either a button to create a new X/Z report or the current X/Z report
+ */
+function XZReportPage() {
+ const [createdX, setCreatedX]= useState(false);
+ const [createdZ, setCreatedZ]= useState(false);
+ return (
+ <ThemeProvider theme={cfa_theme}>
+ <div className="XZPage">
+ <Grid xs={12} >
+ <MainAppBar />
+ <Item />
+ <Item />
+ </Grid>
+ <Grid container spacing = {2}>
+ <Item>
+ <Typography variant="h6" component="Grid" >
+ Last Z Report
+ </Typography>
+ <ZReportTable createZ = {false}/>
+ </Item>
+ <Item>
+ <Typography variant="h6" >
+ Current Z Report
+ </Typography>
+ <div>
+ Note: The Z report acts like a day summary and therefore makes the most logical sense when created at the end of each day
+ </div>
+ {createdZ ? <ZReportTable createZ = {true}/>
+ : <Button variant = 'contained' onClick = {()=>setCreatedZ(true)}>Show Updated Z Report</Button>}
+ </Item>
+ <Item>
+ <Typography variant="h6">
+ X Report
+ </Typography>
+ {createdX ?<XReportTable/>
+ : <Button variant = 'contained' onClick = {()=>setCreatedX(true)}>Create X Report</Button>}
+ </Item>
+ </Grid>
+
+ </div>
+ </ThemeProvider>
+ );
+}
+
+export default XZReportPage;
+
+
+
+
+
+
+
+
+
+
+ Classes Global
+
+
+
+
+
+ Documentation generated by JSDoc 4.0.2 on Tue May 02 2023 21:03:36 GMT-0500 (Central Daylight Time)
+
+
+
+
+
+
diff --git a/docs/fonts/OpenSans-Bold-webfont.svg b/docs/fonts/OpenSans-Bold-webfont.svg
index 9740d59..3ed7be4 100644
--- a/docs/fonts/OpenSans-Bold-webfont.svg
+++ b/docs/fonts/OpenSans-Bold-webfont.svg
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/docs/fonts/OpenSans-BoldItalic-webfont.svg b/docs/fonts/OpenSans-BoldItalic-webfont.svg
index 3e749d2..6a2607b 100644
--- a/docs/fonts/OpenSans-BoldItalic-webfont.svg
+++ b/docs/fonts/OpenSans-BoldItalic-webfont.svg
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/docs/fonts/OpenSans-Italic-webfont.svg b/docs/fonts/OpenSans-Italic-webfont.svg
index 253ccc8..e1075dc 100644
--- a/docs/fonts/OpenSans-Italic-webfont.svg
+++ b/docs/fonts/OpenSans-Italic-webfont.svg
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/docs/fonts/OpenSans-Light-webfont.svg b/docs/fonts/OpenSans-Light-webfont.svg
index dc1fe66..11a472c 100644
--- a/docs/fonts/OpenSans-Light-webfont.svg
+++ b/docs/fonts/OpenSans-Light-webfont.svg
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/docs/fonts/OpenSans-LightItalic-webfont.svg b/docs/fonts/OpenSans-LightItalic-webfont.svg
index aa42762..431d7e3 100644
--- a/docs/fonts/OpenSans-LightItalic-webfont.svg
+++ b/docs/fonts/OpenSans-LightItalic-webfont.svg
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/docs/fonts/OpenSans-Regular-webfont.svg b/docs/fonts/OpenSans-Regular-webfont.svg
index 3c0d245..25a3952 100644
--- a/docs/fonts/OpenSans-Regular-webfont.svg
+++ b/docs/fonts/OpenSans-Regular-webfont.svg
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/docs/global.html b/docs/global.html
index cfeedf0..672ea3f 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -104,14 +104,7 @@ (constant) Item
- The request body should be an object with the following properties:
-
-{
- start: int, // 0-23
- end: int, // 0-23
- salesWith: "menu_item_id" , //optional (default null)
- limit: int //optional number of results to return (default 100)
-}
+ Styled item for theme
@@ -149,7 +142,7 @@ (constant) ItemSource:
@@ -167,13 +160,13 @@ (constant) Item(constant) Title
+(constant) cfa_theme
- Title created with specific configs
+ cfa_theme used to create the theme of the menu board app bar
@@ -211,7 +204,7 @@ (constant) Title
Source:
@@ -228,78 +221,79 @@ (constant) Title
-
-(constant) cfa_theme
-
-
-
-
-
- cfa_theme used to create the theme of the menu board app bar
-
-
-
-
-
-
+
+
+ Methods
-
+
+
-
+
-
-
-
-
-
-
-
-
-
- Source:
-
-
-
+ Parameters:
-
-
+
+
+
+
+ Name
+
+ Type
+
+
+ Description
+
+
+
+
-
+
-(constant) cfa_theme
+ props
+
+
+
+
+
+*
+
+
+
-
- theme of the page created with cfa_theme
-
+
+
+ Functions/data to use from the parent component (CustomerPage.js)
+
+
+
+
@@ -335,7 +329,7 @@ (constant) c
Source:
@@ -351,15 +345,46 @@ (constant) c
+
+
+
+
+
+
+
+
+
+Returns:
+
+
+
+ Component which displays the menu for the Customer Page, and has buttons to
+query different menu categories.
+
+
+
+
+
+
+
+
+
+
-(constant) columns
+
+
+
+ CustomerPage()
+
+
+
- columns var set up to store the columns of the sales report table from the database
+ Front end implementation of Chick-Fil-A customer kiosk interface
@@ -368,6 +393,12 @@ (constant) col
+
+
+
+
+
+
@@ -397,7 +428,7 @@ (constant) col
Source:
@@ -413,11 +444,29 @@ (constant) col
+
+
+
+
+
+
+
+
+
+Returns:
+
-
+
+ Component with all the functionalities needed for a self-serve Kiosk
+
+
+
- Methods
+
+
+
+
@@ -425,7 +474,7 @@ Methods
-
+
@@ -433,7 +482,7 @@