diff --git a/src/Components/Api/Api.tsx b/src/Components/Api/Api.tsx index bcfc084..0bee75c 100644 --- a/src/Components/Api/Api.tsx +++ b/src/Components/Api/Api.tsx @@ -164,6 +164,24 @@ export function UserInfo() { }); } +export function QueryUser(id: number) { + const token = JSON.parse(localStorage.getItem("token") || "{}"); + return axios + .get("http://localhost:8000/api/v1/user_list/" + id, { + headers: { + Authorization: "Token " + token, + }, + }) + .then((response) => { + console.log("Querying one user...", response.data); + return response.data; + }) + .catch((error) => { + console.log("Error retrieving single user data", error.response); + return false; + }); +} + export function UserActivate(activation: ActivationParams) { return axios .post("http://localhost:8000/api/v1/accounts/users/activation/", activation) diff --git a/src/Components/DashboardPage/LowestStockWidget/LowestStockWidget.tsx b/src/Components/DashboardPage/LowestStockWidget/LowestStockWidget.tsx new file mode 100644 index 0000000..538cbe6 --- /dev/null +++ b/src/Components/DashboardPage/LowestStockWidget/LowestStockWidget.tsx @@ -0,0 +1,49 @@ +import * as React from "react"; +import styles from "../../../styles"; +import LowStockIcon from "../../Icons/LowStockIcon/LowStockIcon"; +import { ProductList } from "../../../Interfaces/Interfaces"; + +export interface props {} + +export default function LowestStockWidget(props: ProductList) { + if (!props.Products[0]) { + return ( +
+
+ +

Lowest Stock

+
+

+ There are no products yet... +

+

+ No worries on running out! +

+
+ ); + } + return ( +
+
+ +

Lowest Stock

+
+

+ {props.Products[0].name} +

+

+ In Stock: {props.Products[0].quantity} +

+
+ ); +} diff --git a/src/Components/DashboardPage/RecentlyAddedWidget/RecentlyAddedWidget.tsx b/src/Components/DashboardPage/RecentlyAddedWidget/RecentlyAddedWidget.tsx new file mode 100644 index 0000000..ed58e7a --- /dev/null +++ b/src/Components/DashboardPage/RecentlyAddedWidget/RecentlyAddedWidget.tsx @@ -0,0 +1,58 @@ +import * as React from "react"; +import styles from "../../../styles"; +import { ProductList } from "../../../Interfaces/Interfaces"; +import RecentlyAddedIcon from "../../Icons/RecentlyAddedIcon/RecentlyAddedIcon"; + +export default function RecentlyAddedWidget(props: ProductList) { + if (!props.Products[0]) { + return ( +
+
+ +

+ Recently Added +

+
+

+ Nothing recently added... +

+
+ ); + } + return ( +
+
+ +

+ Recently Added +

+
+

+ {props.Products[0].name} +

+

+ {props.Products[0].date_added} +

+
+ ); +} diff --git a/src/Components/DashboardPage/SessionStatsWidget/SessionStatsWidget.tsx b/src/Components/DashboardPage/SessionStatsWidget/SessionStatsWidget.tsx new file mode 100644 index 0000000..900d1b5 --- /dev/null +++ b/src/Components/DashboardPage/SessionStatsWidget/SessionStatsWidget.tsx @@ -0,0 +1,44 @@ +import * as React from "react"; +import styles from "../../../styles"; +import ColoredCube from "../../ColoredCube/ColoredCube"; +import StatsIcon from "../../Icons/StatsIcon/StatsIcon"; +import { useSelector } from "react-redux"; +import { SessionTransactions } from "../../../Interfaces/Interfaces"; + +export interface props {} + +export default function SessionStatsWidget() { + const session_added = useSelector( + (state: SessionTransactions) => state.session_transactions.added + ); + const session_removed = useSelector( + (state: SessionTransactions) => state.session_transactions.removed + ); + return ( +
+
+ +

+ Current Session +

+
+
+ +

Added

+
+

{session_added}

+
+ +

Removed

+
+

+ {session_removed} +

+
+ ); +} diff --git a/src/Components/DashboardPage/TotalProductsWidget/TotalProductsWidget.tsx b/src/Components/DashboardPage/TotalProductsWidget/TotalProductsWidget.tsx new file mode 100644 index 0000000..c4a19e6 --- /dev/null +++ b/src/Components/DashboardPage/TotalProductsWidget/TotalProductsWidget.tsx @@ -0,0 +1,37 @@ +import * as React from "react"; +import styles from "../../../styles"; +import TotalProductsIcon from "../../Icons/TotalProductsIcon/TotalProductsIcon"; +import { Product, ProductList } from "../../../Interfaces/Interfaces"; +import { useEffect, useState } from "react"; + +export interface props {} + +export default function TotalProductsWidget(props: ProductList) { + const [items, setItems] = useState("Loading..."); + useEffect(() => { + if (props.Products.length === 0) { + setItems("No products"); + } else if (props.Products.length === 1) { + setItems("1 product"); + } else { + setItems(props.Products.length + " Unique Items"); + } + }, []); + return ( +
+
+ +

+ Total Products +

+
+

{items}

+

In inventory

+
+ ); +} diff --git a/src/Components/LogsPage/RowRenderer/RowRenderer.tsx b/src/Components/LogsPage/RowRenderer/RowRenderer.tsx new file mode 100644 index 0000000..16196fd --- /dev/null +++ b/src/Components/LogsPage/RowRenderer/RowRenderer.tsx @@ -0,0 +1,99 @@ +import * as React from "react"; +import { + OldSessionState, + ProductLogEntry, +} from "../../../Interfaces/Interfaces"; +import styles from "../../../styles"; +import { TableBody, TableRow, TableCell } from "@mui/material"; +import { GetProduct, QueryUser } from "../../Api/Api"; +import { useState } from "react"; +import { useSelector } from "react-redux"; +import { useQuery } from "react-query"; + +export default function RowRenderer(props: ProductLogEntry) { + const old_session_checked = useSelector( + (state: OldSessionState) => state.old_session_checked.value + ); + const { + data: user, + isLoading, + error, + } = useQuery({ + queryKey: ["user_select_id_" + props.Product.id, props.Product.id], + queryFn: () => QueryUser(props.Product.id), + }); + if (isLoading || !old_session_checked) { + + + {props.Product.history_id} + + + {props.Product.id} + + + {props.Product.name} + + + {props.Product.quantity} + + + Loading... + + + {props.Product.history_date} + + ; + } else if (error) { + + + {props.Product.history_id} + + + {props.Product.id} + + + {props.Product.name} + + + {props.Product.quantity} + + + Loading... + + + {props.Product.history_date} + + ; + } + return ( + + + {props.Product.history_id} + + + {props.Product.id} + + + {props.Product.name} + + + {props.Product.quantity} + + + {isLoading || user.username} + + + {props.Product.history_date} + + + ); +} diff --git a/src/Interfaces/Interfaces.tsx b/src/Interfaces/Interfaces.tsx index fa27e80..70025c2 100644 --- a/src/Interfaces/Interfaces.tsx +++ b/src/Interfaces/Interfaces.tsx @@ -13,11 +13,24 @@ export interface ProductLogList { ProductLogs: ProductLog[]; } +export interface ProductLogEntry { + Product: { + history_id: number; + id: number; + name: string; + quantity: string; + history_date: string; + history_user_id: number; + }; +} + export interface ProductLog { history_id: number; + id: number; name: string; quantity: string; history_date: string; + history_user_id: number; } // Redux Interfaces diff --git a/src/Routes/Dashboard/Dashboard.tsx b/src/Routes/Dashboard/Dashboard.tsx index f52b29f..11e5df2 100644 --- a/src/Routes/Dashboard/Dashboard.tsx +++ b/src/Routes/Dashboard/Dashboard.tsx @@ -15,8 +15,16 @@ import { GetLowestStockedProduct, GetProducts, } from "../../Components/Api/Api"; -import { ProductLog, SessionTransactions } from "../../Interfaces/Interfaces"; +import { + OldSessionState, + ProductLog, + SessionTransactions, +} from "../../Interfaces/Interfaces"; import { useSelector } from "react-redux"; +import LowestStockWidget from "../../Components/DashboardPage/LowestStockWidget/LowestStockWidget"; +import RecentlyAddedWidget from "../../Components/DashboardPage/RecentlyAddedWidget/RecentlyAddedWidget"; +import TotalProductsWidget from "../../Components/DashboardPage/TotalProductsWidget/TotalProductsWidget"; +import SessionStatsWidget from "../../Components/DashboardPage/SessionStatsWidget/SessionStatsWidget"; export default function Dashboard() { const logs = useQuery("logs", GetLogs, { retry: 0 }); @@ -28,13 +36,15 @@ export default function Dashboard() { retry: 0, } ); - const session_added = useSelector( - (state: SessionTransactions) => state.session_transactions.added + const old_session_checked = useSelector( + (state: OldSessionState) => state.old_session_checked.value ); - const session_removed = useSelector( - (state: SessionTransactions) => state.session_transactions.removed - ); - if (logs.isLoading || products.isLoading || lowest_stock_product.isLoading) { + if ( + logs.isLoading || + products.isLoading || + lowest_stock_product.isLoading || + !old_session_checked + ) { return (
@@ -79,108 +89,20 @@ export default function Dashboard() { >
-
-
- -

- Total Products -

-
-

- {products.data.length} Unique Item/s -

-

- In inventory -

-
+
-
-
- -

- Current Session -

-
-
- -

- Added -

-
-

- {session_added} -

-
- -

- Removed -

-
-

- {session_removed} -

-
+
-
-
- -

- Lowest Stock -

-
-

- {lowest_stock_product.data[0].name} -

-

- In Stock: {lowest_stock_product.data[0].quantity} -

-
-
-
- -

- Recently Added -

-
-

- {products.data[0].name} -

-

- {products.data[0].date_added} -

-
+ +
diff --git a/src/Routes/Logs/Logs.tsx b/src/Routes/Logs/Logs.tsx index 5ef42a2..90a86ac 100644 --- a/src/Routes/Logs/Logs.tsx +++ b/src/Routes/Logs/Logs.tsx @@ -11,8 +11,49 @@ import { } from "@mui/material"; import { SampleLogData } from "../../Components/SampleData/SampleData"; import LoginChecker from "../../Components/LoginChecker/LoginChecker"; +import { useQuery } from "react-query"; +import { GetLogs, UserInfo } from "../../Components/Api/Api"; +import { OldSessionState, ProductLog } from "../../Interfaces/Interfaces"; +import { useState } from "react"; +import RowRenderer from "../../Components/LogsPage/RowRenderer/RowRenderer"; +import { useSelector } from "react-redux"; export default function Logs() { + const logs = useQuery("logs", GetLogs, { retry: 0 }); + const old_session_checked = useSelector( + (state: OldSessionState) => state.old_session_checked.value + ); + if (logs.isLoading || !old_session_checked) { + return ( +
+ +
+ +

Logs

+
+
+

+ Loading logs... +

+
+
+ ); + } else if (logs.error) { + return ( +
+ +
+ +

Logs

+
+
+

+ Error loading logs +

+
+
+ ); + } return (
@@ -39,7 +80,10 @@ export default function Logs() { Product - Amount Change + Quantity + + + User Timestamp @@ -47,34 +91,8 @@ export default function Logs() { - {SampleLogData.map((row) => ( - - - {row.id} - - - {row.p_id} - - - {row.p_name} - - - {row.amount_changed} - - - {row.timestamp} - - + {logs.data.map((row: ProductLog, index: number) => ( + ))} diff --git a/src/Routes/Product/Product.tsx b/src/Routes/Product/Product.tsx index 5497a35..835c874 100644 --- a/src/Routes/Product/Product.tsx +++ b/src/Routes/Product/Product.tsx @@ -6,6 +6,8 @@ import LoginChecker from "../../Components/LoginChecker/LoginChecker"; import { DeleteProduct, GetProduct } from "../../Components/Api/Api"; import { useMutation, useQuery, useQueryClient } from "react-query"; import ProductIcon from "../../Components/Icons/ProductIcon/ProductIcon"; +import { useSelector } from "react-redux"; +import { OldSessionState } from "../../Interfaces/Interfaces"; export default function Product() { const navigate = useNavigate(); @@ -25,7 +27,10 @@ export default function Product() { queryClient.invalidateQueries("products"); }, }); - if (isLoading) { + const old_session_checked = useSelector( + (state: OldSessionState) => state.old_session_checked.value + ); + if (isLoading || !old_session_checked) { return (
diff --git a/src/Routes/Products/Products.tsx b/src/Routes/Products/Products.tsx index 95e6a37..973896b 100644 --- a/src/Routes/Products/Products.tsx +++ b/src/Routes/Products/Products.tsx @@ -9,6 +9,8 @@ import ViewManager from "../../Components/ProductsPage/ViewManager"; import { useQuery } from "react-query"; import { GetProducts } from "../../Components/Api/Api"; import LoginChecker from "../../Components/LoginChecker/LoginChecker"; +import { useSelector } from "react-redux"; +import { OldSessionState } from "../../Interfaces/Interfaces"; export default function Products() { const navigate = useNavigate(); @@ -17,7 +19,10 @@ export default function Products() { isLoading, error, } = useQuery("products", GetProducts, { retry: 0 }); - if (isLoading) { + const old_session_checked = useSelector( + (state: OldSessionState) => state.old_session_checked.value + ); + if (isLoading || !old_session_checked) { return (
diff --git a/src/routes/Inventory/Inventory.tsx b/src/routes/Inventory/Inventory.tsx index afb07ad..890f91b 100644 --- a/src/routes/Inventory/Inventory.tsx +++ b/src/routes/Inventory/Inventory.tsx @@ -18,6 +18,8 @@ import { useMutation, useQuery, useQueryClient } from "react-query"; import RowRenderer from "../../Components/InventoryPage/RowRenderer/RowRenderer"; import AddIcon from "../../Components/Icons/AddIcon/AddIcon"; import { useNavigate } from "react-router-dom"; +import { useSelector } from "react-redux"; +import { OldSessionState } from "../../Interfaces/Interfaces"; export default function Inventory() { const { @@ -26,8 +28,10 @@ export default function Inventory() { error, } = useQuery("products", GetProducts, { retry: 0 }); const navigate = useNavigate(); - - if (isLoading) { + const old_session_checked = useSelector( + (state: OldSessionState) => state.old_session_checked.value + ); + if (isLoading || !old_session_checked) { return (