diff --git a/client/src/components/AppBarMenuButton.js b/client/src/components/AppBarMenuButton.js index e6d3fd3..3a8b206 100644 --- a/client/src/components/AppBarMenuButton.js +++ b/client/src/components/AppBarMenuButton.js @@ -4,7 +4,9 @@ import MenuItem from "@mui/material/MenuItem"; import IconButton from "@mui/material/IconButton"; import MenuIcon from "@mui/icons-material/Menu"; import { useNavigate } from "react-router-dom"; - +/** + * The App bar menu button function creates the app bar nav button and incorporates the other pages into the nav bar. + */ export default function AppBarMenuButton() { const [anchorEl, setAnchorEl] = React.useState(null); const navigate = useNavigate(); diff --git a/client/src/components/GoogleTranslateButton.js b/client/src/components/GoogleTranslateButton.js index 26e9a41..4751c76 100644 --- a/client/src/components/GoogleTranslateButton.js +++ b/client/src/components/GoogleTranslateButton.js @@ -1,5 +1,7 @@ import { useEffect } from "react"; - +/** + * The GoogleTranslateButton function creates the button at the top of each page that can translate the page that it is on. + */ const GoogleTranslateButton = () => { const googleTranslateElementInit = () => { new window.google.translate.TranslateElement( diff --git a/client/src/components/PendingRestockTable.js b/client/src/components/PendingRestockTable.js index bd29efb..d01f24b 100644 --- a/client/src/components/PendingRestockTable.js +++ b/client/src/components/PendingRestockTable.js @@ -22,7 +22,7 @@ const config = { } }; -/* +/** * 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 { diff --git a/client/src/components/ReactWeatherComponent.js b/client/src/components/ReactWeatherComponent.js index da3b767..3fe08b4 100644 --- a/client/src/components/ReactWeatherComponent.js +++ b/client/src/components/ReactWeatherComponent.js @@ -1,5 +1,7 @@ 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({ diff --git a/client/src/components/RestockReportTable.js b/client/src/components/RestockReportTable.js index 2c3ee2c..6b298e9 100644 --- a/client/src/components/RestockReportTable.js +++ b/client/src/components/RestockReportTable.js @@ -23,7 +23,9 @@ const config = { "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); diff --git a/client/src/components/SalesReportTable.js b/client/src/components/SalesReportTable.js index a73e47d..6711be6 100644 --- a/client/src/components/SalesReportTable.js +++ b/client/src/components/SalesReportTable.js @@ -30,7 +30,7 @@ const config = { } }; /** - * 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. */ diff --git a/client/src/components/SignIn.jsx b/client/src/components/SignIn.jsx index 07d7e85..c50738d 100644 --- a/client/src/components/SignIn.jsx +++ b/client/src/components/SignIn.jsx @@ -2,7 +2,9 @@ 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(); diff --git a/client/src/pages/ErrorPage.js b/client/src/pages/ErrorPage.js index 4956654..7b70c81 100644 --- a/client/src/pages/ErrorPage.js +++ b/client/src/pages/ErrorPage.js @@ -1,6 +1,8 @@ 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); diff --git a/client/src/pages/LoginPage.js b/client/src/pages/LoginPage.js index 5075891..acf7358 100644 --- a/client/src/pages/LoginPage.js +++ b/client/src/pages/LoginPage.js @@ -1,6 +1,9 @@ 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 ( diff --git a/client/src/pages/RestockReportPage.js b/client/src/pages/RestockReportPage.js index 82b893d..f355db0 100644 --- a/client/src/pages/RestockReportPage.js +++ b/client/src/pages/RestockReportPage.js @@ -18,6 +18,9 @@ const Item = styled(Paper)(({ theme }) => ({ })); // The grid max xs = 12 +/** + * Function that builds the restock report page with grids and incorporates the table, app bar + */ function RestockReportPage() { return (
diff --git a/client/src/pages/SalesReportPage.js b/client/src/pages/SalesReportPage.js index c307812..fed0359 100644 --- a/client/src/pages/SalesReportPage.js +++ b/client/src/pages/SalesReportPage.js @@ -40,11 +40,8 @@ const cfa_theme = createTheme({ }); /** * - * Sales Report Page function used to build the webpage - * Has setStart, setEnd, and setSubmit vars to help store values from the date time - * selection box - * - * + * 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(''); diff --git a/client/src/pages/TestTranslatePage.js b/client/src/pages/TestTranslatePage.js index ba1ca59..ee8280d 100644 --- a/client/src/pages/TestTranslatePage.js +++ b/client/src/pages/TestTranslatePage.js @@ -1,5 +1,7 @@ import { useEffect } from "react"; - +/** + * Sets up the google translate component for our project. + */ const TestTranslatePage = () => { const googleTranslateElementInit = () => { new window.google.translate.TranslateElement( diff --git a/docs/.DS_Store b/docs/.DS_Store index eba1322..0294fc2 100644 Binary files a/docs/.DS_Store and b/docs/.DS_Store differ diff --git a/docs/Order.html b/docs/Order.html new file mode 100644 index 0000000..93634f2 --- /dev/null +++ b/docs/Order.html @@ -0,0 +1,665 @@ + + + + + JSDoc: Class: Order + + + + + + + + + + +
+ +

Class: Order

+ + + + + + +
+ +
+ +

Order()

+ +
Represents an order of menu items
+ + +
+ +
+
+ + + + +

Constructor

+ + + +

new Order()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(async) addMenuItem(menuItemKey)

+ + + + + + +
+ Adds a menu item to the order and updates inventory quantities +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
menuItemKey + + +string + + + + name of the menu item
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+ None +
+ + + + + + + + + + + + + + + +

(async) cancelOrder()

+ + + + + + +
+ Removes all of the items in the current order and resets the inventory quantities. +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+ None +
+ + + + + + + + + + + + + + + +

(async) createOrder()

+ + + + + + +
+ Creates an order from the current items in the order, updates the database data, +and initializes a new order. +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+ none +
+ + + + + + + + + + + + + + + +

(async) removeItem(menuItemKey)

+ + + + + + +
+ Removes a menu item from the order and updates inventory quantities +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
menuItemKey + + +string + + + + name of the menu item
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+ None +
+ + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/client_src_components_AppBarMenuButton.js.html b/docs/client_src_components_AppBarMenuButton.js.html new file mode 100644 index 0000000..2dc8aa0 --- /dev/null +++ b/docs/client_src_components_AppBarMenuButton.js.html @@ -0,0 +1,130 @@ + + + + + JSDoc: Source: client/src/components/AppBarMenuButton.js + + + + + + + + + + +
+ +

Source: client/src/components/AppBarMenuButton.js

+ + + + + + +
+
+
import * as React from "react";
+import Menu from "@mui/material/Menu";
+import MenuItem from "@mui/material/MenuItem";
+import IconButton from "@mui/material/IconButton";
+import MenuIcon from "@mui/icons-material/Menu";
+import { useNavigate } from "react-router-dom";
+/**
+ * The App bar menu button function creates the app bar nav button and incorporates the other pages into the nav bar. 
+     */
+export default function AppBarMenuButton() {
+  const [anchorEl, setAnchorEl] = React.useState(null);
+  const navigate = useNavigate();
+
+  const open = Boolean(anchorEl);
+  const handleClick = (event) => {
+    setAnchorEl(event.currentTarget);
+  };
+  const handleClose = () => {
+    setAnchorEl(null);
+  };
+
+  return (
+    <div>
+      <IconButton
+        size="large"
+        edge="start"
+        color="inherit"
+        aria-label="menu"
+        sx={{ mr: 2 }}
+        id="basic-button"
+        aria-controls={open ? "basic-menu" : undefined}
+        aria-haspopup="true"
+        aria-expanded={open ? "true" : undefined}
+        onClick={handleClick}
+      >
+        <MenuIcon />
+      </IconButton>
+      <Menu
+        aria-haspopup={true}
+        id="basic-menu"
+        anchorEl={anchorEl}
+        open={open}
+        onClose={handleClose}
+        MenuListProps={{
+          "aria-labelledby": "basic-button",
+        }}
+      >
+        <MenuItem onClick={() => navigate("/InventoryLevelsEndDayPage")}>
+          Inventory
+        </MenuItem>
+        <MenuItem onClick={()=> navigate("/ChangeMenuPage")}>
+          Change Menu
+        </MenuItem>
+        <MenuItem onClick={() => navigate("/RestockReportPage")}>
+          Restock Report
+        </MenuItem>
+        <MenuItem onClick={() => navigate("/serverPage")}>Server Page</MenuItem>
+        <MenuItem onClick={() => navigate("/WhatSalesTogetherPage")}>
+          What Sells Together
+        </MenuItem>
+        <MenuItem onClick={() => navigate("/ExcessReportPage")}>
+          Excess Report
+        </MenuItem>
+        <MenuItem onClick={()=> navigate("/Customer")}>
+          Customer Page
+        </MenuItem>
+        <MenuItem onClick={() => navigate("/SalesReport")}>
+          Sales Report
+        </MenuItem>
+        <MenuItem onClick={() => navigate("/XZReportPage")}>
+          Z and X Reports
+          </MenuItem>
+        <MenuItem onClick = {() => navigate("/MenuBoard")}>
+          Menu Board
+        </MenuItem>
+      </Menu>
+    </div>
+  );
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/client_src_components_CustomerMenu.js.html b/docs/client_src_components_CustomerMenu.js.html new file mode 100644 index 0000000..2f3c61a --- /dev/null +++ b/docs/client_src_components_CustomerMenu.js.html @@ -0,0 +1,269 @@ + + + + + JSDoc: Source: client/src/components/CustomerMenu.js + + + + + + + + + + +
+ +

Source: client/src/components/CustomerMenu.js

+ + + + + + +
+
+
import React from "react";
+import { useState, useEffect } from "react";
+import axios from "axios";
+import Grid from "@mui/material/Unstable_Grid2";
+import { styled } from "@mui/material/styles";
+import Paper from "@mui/material/Paper";
+import ShoppingCartOutlinedIcon from "@mui/icons-material/ShoppingCartOutlined";
+
+import { Row, Col, Button } from "antd";
+import ItemCard from "../components/ItemCard.js";
+
+const Item = styled(Paper)(({ theme }) => ({
+  backgroundColor: "#fff",
+  ...theme.typography.body2,
+  padding: theme.spacing(1),
+  textAlign: "center",
+  color: theme.palette.text.secondary,
+}));
+
+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 (CustomerPage.js)
+   * @returns Component which displays the menu for the Customer Page, and has buttons to
+   * query different menu categories.
+   */
+const CustomerMenu = (props) => {
+  const [itemsData, setItemsData] = useState([
+  ]);
+
+  useEffect(() => {
+    getAllMenu();
+  }, []);
+
+  /**
+   * Gets and displays all of the menu items through an XMLHttpRequest to the server and updates the component's state data.
+   * 
+   */
+    const getAllMenu = async() => {
+      axios.get(`https://pern-project-3.onrender.com/serverPage`, config)
+      .then(res => {
+        const menuData = res.data;
+        setItemsData(menuData);
+        console.log(menuData);
+        //this.setState({ data: menuData });
+      })
+      .catch((err) => {
+        console.error(err);
+      });
+  };
+
+    /**
+     * Gets and displays all of the Entree menu items through an XMLHttpRequest to the server and updates the component's state data.
+     * 
+     */
+    const getEntrees = async() => {
+      axios.get(`https://pern-project-3.onrender.com/serverPage/getEntrees`, config)
+      .then(res => {
+        const menuData = res.data;
+        setItemsData(menuData);
+        console.log(menuData);
+        //this.setState({ data: menuData });
+      })
+      .catch((err) => {
+        console.error(err);
+      });
+  };
+
+    /**
+    * Gets and displays all of the Side menu items through an XMLHttpRequest to the server and updates the component's state data.
+    * 
+    */
+    const getSides = async() => {
+      axios.get(`https://pern-project-3.onrender.com/serverPage/getSides`, config)
+      .then(res => {
+        const menuData = res.data;
+        setItemsData(menuData);
+        console.log(menuData);
+        //this.setState({ data: menuData });
+      })
+      .catch((err) => {
+        console.error(err);
+      });
+  };
+
+    /**
+    * Gets and displays all of the Dessert menu items through an XMLHttpRequest to the server and updates the component's state data.
+    * 
+    */
+    const getDesserts = async() => {
+      axios.get(`https://pern-project-3.onrender.com/serverPage/getDesserts`, config)
+      .then(res => {
+        const menuData = res.data;
+        setItemsData(menuData);
+        console.log(menuData);
+        //this.setState({ data: menuData });
+      })
+      .catch((err) => {
+        console.error(err);
+      });
+  };
+
+  return (
+    <div
+      className="serverPage"
+    >
+      <div className="server-tab">
+        <Button
+          aria-label="Showing Entrees only"
+          className="category-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
+          aria-label="Showing Side Dishes only"
+          className="category-button"
+          variant="outlined"
+          style={{
+            fontSize: "18px",
+            marginLeft: "2%",
+            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
+          aria-label="Showing Desserts only"
+          className="category-button"
+          variant="outlined"
+          style={{
+            fontSize: "18px",
+            marginLeft: "2%",
+            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"
+              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>
+      </div>
+      <Grid container spacing={2}>
+        <Grid xs={12}>
+          <Row>
+            {itemsData.map((item) => (
+              <Col span={4}>
+                <ItemCard item={item} AddItem={props.AddItem} />
+              </Col>
+            ))}
+          </Row>
+        </Grid>
+      </Grid>
+    </div>
+  );
+};
+
+export default CustomerMenu;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/client_src_components_GoogleTranslateButton.js.html b/docs/client_src_components_GoogleTranslateButton.js.html new file mode 100644 index 0000000..3074294 --- /dev/null +++ b/docs/client_src_components_GoogleTranslateButton.js.html @@ -0,0 +1,82 @@ + + + + + JSDoc: Source: client/src/components/GoogleTranslateButton.js + + + + + + + + + + +
+ +

Source: client/src/components/GoogleTranslateButton.js

+ + + + + + +
+
+
import { useEffect } from "react";
+/**
+ * The GoogleTranslateButton function creates the button at the top of each page that can translate the page that it is on.
+     */
+const GoogleTranslateButton = () => {
+  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>
+    </>
+  );
+};
+
+export default GoogleTranslateButton;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/client_src_components_ItemCard.js.html b/docs/client_src_components_ItemCard.js.html new file mode 100644 index 0000000..ebaa712 --- /dev/null +++ b/docs/client_src_components_ItemCard.js.html @@ -0,0 +1,127 @@ + + + + + JSDoc: Source: client/src/components/ItemCard.js + + + + + + + + + + +
+ +

Source: client/src/components/ItemCard.js

+ + + + + + +
+
+
import React from "react";
+import { Button, Card } from "antd";
+import { ToastContainer, toast } from "react-toastify";
+import "react-toastify/dist/ReactToastify.css";
+
+/**
+ * 
+ * @param {*} props - Data of an individual menu item, containing the item name, price, image link, and category. 
+ * @returns A Card display component for an individual menu item, used for the Customer Menu component. 
+ * Has a button for adding the menu item to the order.
+ */
+const ItemCard = (props) => {
+  const { Meta } = Card;
+  return (
+    <div
+      aria-label={props.item.itemname + ". Price: $" + props.item.price + " ."}
+    >
+      <Card
+        hoverable
+        style={{
+          width: 230,
+          marginBottom: 20,
+          marginLeft: 5,
+          fontSize: "16px",
+          background: "#F2F4F4",
+        }}
+        cover={
+          <img
+            alt={"Image of " + props.item.itemname}
+            src={props.item.imageLink}
+          />
+        }
+      >
+        <Meta
+          aria-label={
+            props.item.itemname + ". Price: $" + props.item.price + " ."
+          }
+          title={props.item.itemname}
+          description={
+            <div className="item-description">
+              <p>{props.item.itemname}</p>
+                        <p className="category">
+                            {props.item.category}
+                        </p>
+              <p className="price" aria-label={"Price: $" + props.item.price}>
+                {"$" + props.item.price}
+              </p>
+            </div>
+          }
+        />
+        <div className="item-button">
+          <Button
+            onClick={() => {
+              toast.success("Added" + props.item.itemname + " to order!", {
+                position: "top-center",
+                autoClose: 5000,
+                hideProgressBar: false,
+                closeOnClick: true,
+                pauseOnHover: true,
+                draggable: true,
+                progress: undefined,
+                theme: "colored",
+              });
+              props.AddItem(props.item.itemname);
+            }}
+            aria-label={"Add " + props.item.itemname + " to cart."}
+          >
+            Add Item
+          </Button>
+        </div>
+      </Card>
+    </div>
+  );
+};
+
+export default ItemCard;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/client_src_components_MenuBoardBar.js.html b/docs/client_src_components_MenuBoardBar.js.html index 5454d17..51db122 100644 --- a/docs/client_src_components_MenuBoardBar.js.html +++ b/docs/client_src_components_MenuBoardBar.js.html @@ -33,7 +33,6 @@

Source: client/src/components/MenuBoardBar.js

import Typography from '@mui/material/Typography'; import Button from '@mui/material/Button'; import { ThemeProvider, createTheme } from '@mui/material/styles'; -import AppBarMenuButton from './AppBarMenuButton'; import { UserAuth } from '../login/AuthContext'; import { useNavigate } from 'react-router'; import { useEffect } from 'react'; @@ -65,31 +64,23 @@

Source: client/src/components/MenuBoardBar.js

const navigate = useNavigate(); useEffect(() => { - if (user == null) { - navigate('/LoginPage'); - console.log("Successfully logged out") - } - }, [user]); + + }, []); const handleSignOut = async () => { try { await logOut(); + navigate('/'); } catch (error) { console.log(error); } }; -/** - * - * returns the menu board bar with all of the necessary features. - * - * - */ + return ( <ThemeProvider theme={cfa_theme}> <Box sx={{ flexGrow: 1 }}> <AppBar position="static" color='primary'> <Toolbar> - <MenuBoardBarButton/> <Typography id='bar-description' variant= "h4" padding = "10px" component="div" sx={{ flexGrow: 1, textAlign: 'center' }}> CFA Customer Kiosk </Typography> @@ -109,13 +100,13 @@

Source: client/src/components/MenuBoardBar.js


diff --git a/docs/client_src_components_MenuBoardBarButton.js.html b/docs/client_src_components_MenuBoardBarButton.js.html index f310e88..6a43322 100644 --- a/docs/client_src_components_MenuBoardBarButton.js.html +++ b/docs/client_src_components_MenuBoardBarButton.js.html @@ -51,12 +51,7 @@

Source: client/src/components/MenuBoardBarButton.js

const handleClose = () => { setAnchorEl(null); }; -/** - * - * returns the nav bar with proper navigation to the customer page, menu board, and server page. - * - * - */ + return ( <div> <IconButton @@ -102,13 +97,13 @@

Source: client/src/components/MenuBoardBarButton.js


diff --git a/docs/client_src_components_MenuBoardCards.js.html b/docs/client_src_components_MenuBoardCards.js.html index 1a43607..352e035 100644 --- a/docs/client_src_components_MenuBoardCards.js.html +++ b/docs/client_src_components_MenuBoardCards.js.html @@ -27,11 +27,13 @@

Source: client/src/components/MenuBoardCards.js

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


- 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;
+
+
+ + + + +
+ + + +
+ +
+ 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;
+
+
+
+ + + + +
+ + + +
+ +
+ 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} />;
+  }
+
+};
+
+
+
+ + + + +
+ + + +
+ +
+ 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;
+
+
+ + + + +
+ + + +
+ +
+ 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} />;
+  }
+
+};
+
+
+
+ + + + +
+ + + +
+ +
+ 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


- 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;
+
+
+ + + + +
+ + + +
+ +
+ 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;
+
+  
+
+
+
+ + + + +
+ + + +
+ +
+ 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>
+  );
+}
+
+
+ + + + +
+ + + +
+ +
+ 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>
+    );
+  }
+
+
+ + + + +
+ + + +
+ +
+ 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>
+
+  );
+}
+
+
+
+ + + + +
+ + + +
+ +
+ 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


- 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;
+
+
+
+ + + + +
+ + + +
+ +
+ 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


- 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;
+
+  
+
+
+
+ + + + +
+ + + +
+ +
+ 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;
+
+
+
+ + + + +
+ + + +
+ +
+ 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;
+
+
+
+ + + + +
+ + + +
+ +
+ 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;
+
+
+
+ + + + +
+ + + +
+ +
+ 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

-
+ + - +

CustomerMenu(props)

- - - - - - - - - -
Source:
-
- - +
Parameters:
- -
+ + + + + + + + + + + + + + - + -

(constant) cfa_theme

+ + + + + -
- theme of the page created with cfa_theme -
+ + + + + + +
NameTypeDescription
props + + +* + + 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

- +

GoogleTranslateButton()

@@ -433,7 +482,7 @@