From 48ed8f45c6fd8336f720005e1df85c4d909c7b1b Mon Sep 17 00:00:00 2001 From: keannu125 Date: Mon, 6 Mar 2023 13:59:16 +0800 Subject: [PATCH 01/10] Added individual product views and fixed login session checker --- src/App.tsx | 9 +++++ src/Components/Container/Container.tsx | 10 +++-- src/Components/Login/Login.tsx | 8 +--- .../ProductsPage/BlobView/BlobView.tsx | 37 ++++++++++++++----- .../ProductsPage/TableView/TableView.tsx | 11 ++++-- src/Components/SampleData/SampleData.tsx | 4 +- src/Interfaces/Interfaces.tsx | 6 ++- src/Routes/Product/Product.tsx | 24 ++++++++++++ 8 files changed, 83 insertions(+), 26 deletions(-) create mode 100644 src/Routes/Product/Product.tsx diff --git a/src/App.tsx b/src/App.tsx index 203be88..c0f7fcc 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -9,6 +9,7 @@ import Store from "./Plugins/Redux/Store/Store"; import { Provider } from "react-redux"; import Inventory from "./Routes/Inventory/Inventory"; import Login from "./Routes/Login/Login"; +import Product from "./Routes/Product/Product"; const router = createBrowserRouter([ { @@ -56,6 +57,14 @@ const router = createBrowserRouter([ ), }, + { + path: "/Product/:id", + element: ( + + + + ), + }, ]); export default function App() { diff --git a/src/Components/Container/Container.tsx b/src/Components/Container/Container.tsx index 906ffe1..f9b553b 100644 --- a/src/Components/Container/Container.tsx +++ b/src/Components/Container/Container.tsx @@ -5,7 +5,8 @@ import styles from "../../styles"; import { CheckSavedSession, UserInfo } from "../Api/Api"; import { toggle_login } from "../../Features/Redux/Slices/Login/LoginSlice"; import { SetUser } from "../../Features/Redux/Slices/LoggedInUserSlice/LoggedInUserSlice"; -import { useDispatch } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; +import { LoginState } from "../../Interfaces/Interfaces"; export interface props { children: React.ReactNode; @@ -13,11 +14,14 @@ export interface props { export default function Container(props: props) { const dispatch = useDispatch(); + const logged_in = useSelector((state: LoginState) => state.logged_in.value); // Function to check for previous login session async function CheckPreviousSession() { if (await CheckSavedSession()) { - await dispatch(toggle_login()); - await dispatch(SetUser(await UserInfo())); + if (logged_in !== true) { + await dispatch(toggle_login()); + await dispatch(SetUser(await UserInfo())); + } } } useEffect(() => { diff --git a/src/Components/Login/Login.tsx b/src/Components/Login/Login.tsx index 0dbcc93..df42ebd 100644 --- a/src/Components/Login/Login.tsx +++ b/src/Components/Login/Login.tsx @@ -4,14 +4,10 @@ import { Button } from "@mui/material"; import styles from "../../styles"; import { useNavigate } from "react-router-dom"; import { LoggedInUserState } from "../../Interfaces/Interfaces"; +import { LoginState } from "../../Interfaces/Interfaces"; -export interface state { - logged_in: { - value: boolean; - }; -} export default function Login() { - const logged_in = useSelector((state: state) => state.logged_in.value); + const logged_in = useSelector((state: LoginState) => state.logged_in.value); const logged_in_user = useSelector( (state: LoggedInUserState) => state.logged_in_user.value ); diff --git a/src/Components/ProductsPage/BlobView/BlobView.tsx b/src/Components/ProductsPage/BlobView/BlobView.tsx index 5eddc30..3050979 100644 --- a/src/Components/ProductsPage/BlobView/BlobView.tsx +++ b/src/Components/ProductsPage/BlobView/BlobView.tsx @@ -3,16 +3,17 @@ import * as React from "react"; import styles from "../../../styles"; import { ProductList } from "../../../Interfaces/Interfaces"; import ProductIcon from "../../Icons/ProductIcon/ProductIcon"; +import { Button } from "@mui/material"; +import { useNavigate } from "react-router-dom"; export default function BlobView({ Products }: ProductList) { + const navigate = useNavigate(); return (
{Products.map((row) => (
-
- {" "} -

{row.name}

-
+
))}
diff --git a/src/Components/ProductsPage/TableView/TableView.tsx b/src/Components/ProductsPage/TableView/TableView.tsx index 5550cc9..ef020ec 100644 --- a/src/Components/ProductsPage/TableView/TableView.tsx +++ b/src/Components/ProductsPage/TableView/TableView.tsx @@ -9,8 +9,10 @@ import { } from "@mui/material"; import styles from "../../../styles"; import { ProductList } from "../../../Interfaces/Interfaces"; +import { useNavigate } from "react-router-dom"; export default function TableView({ Products }: ProductList) { + const navigate = useNavigate(); return ( - Last Modified + Date Added @@ -36,7 +38,10 @@ export default function TableView({ Products }: ProductList) { {Products.map((row) => ( navigate("/Product/" + row.id)} > {row.id} @@ -45,7 +50,7 @@ export default function TableView({ Products }: ProductList) { {row.name} - {row.last_modified} + {row.date_added} ))} diff --git a/src/Components/SampleData/SampleData.tsx b/src/Components/SampleData/SampleData.tsx index 4ceb9ef..d18907a 100644 --- a/src/Components/SampleData/SampleData.tsx +++ b/src/Components/SampleData/SampleData.tsx @@ -2,12 +2,12 @@ export const SampleProducts = [ { id: 1, name: "Zidane's Water", - last_modified: "2/24/2023 10:05AM", + date_added: "2/24/2023 10:05AM", }, { id: 2, name: "Dan's Beefed Corn", - last_modified: "2/25/2023 4:05PM", + date_added: "2/25/2023 4:05PM", }, ]; diff --git a/src/Interfaces/Interfaces.tsx b/src/Interfaces/Interfaces.tsx index e3bf52c..a95cf5e 100644 --- a/src/Interfaces/Interfaces.tsx +++ b/src/Interfaces/Interfaces.tsx @@ -5,12 +5,14 @@ export interface ProductList { export interface Product { id: number; name: string; - last_modified: string; + date_added: string; } // Redux Interfaces export interface LoginState { - Login: { logged_in: boolean }; + logged_in: { + value: boolean; + }; } export interface LoggedInUserState { diff --git a/src/Routes/Product/Product.tsx b/src/Routes/Product/Product.tsx new file mode 100644 index 0000000..fc95a47 --- /dev/null +++ b/src/Routes/Product/Product.tsx @@ -0,0 +1,24 @@ +import * as React from "react"; +import styles from "../../styles"; +import { Button } from "@mui/material"; +import { useParams } from "react-router-dom"; + +export default function Product() { + let { id } = useParams(); + return ( +
+

+ Individual Product View for id {id} +

+ +
+ ); +} From 18d9fbe1ef6a758b2b1b969866ab23a41c9256f4 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Mon, 6 Mar 2023 14:28:18 +0800 Subject: [PATCH 02/10] Polished margin of all pages and fixed logout not clearing token --- package-lock.json | 81 ++++++++++++++++++++++++++ package.json | 1 + src/App.tsx | 9 +++ src/Components/Container/Container.tsx | 12 +++- src/Components/Login/Login.tsx | 9 +-- src/Components/Logout/Logout.tsx | 1 + src/Routes/Activation/Activation.tsx | 58 ++++++++++++++++++ src/Routes/Dashboard/Dashboard.tsx | 2 +- src/Routes/Login/Login.tsx | 2 +- src/Routes/Logs/Logs.tsx | 2 +- src/Routes/Product/Product.tsx | 2 +- src/Routes/Products/Products.tsx | 4 +- src/routes/Inventory/Inventory.tsx | 2 +- 13 files changed, 169 insertions(+), 16 deletions(-) create mode 100644 src/Routes/Activation/Activation.tsx diff --git a/package-lock.json b/package-lock.json index 4ad0668..40e9e5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-fast-marquee": "^1.3.5", + "react-query": "^3.39.3", "react-redux": "^8.0.5", "react-router-dom": "^6.8.1", "react-scripts": "5.0.1", @@ -5614,6 +5615,14 @@ "node": ">= 8.0.0" } }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "engines": { + "node": ">=0.6" + } + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -5726,6 +5735,21 @@ "node": ">=8" } }, + "node_modules/broadcast-channel": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", + "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", + "dependencies": { + "@babel/runtime": "^7.7.2", + "detect-node": "^2.1.0", + "js-sha3": "0.8.0", + "microseconds": "0.2.0", + "nano-time": "1.0.0", + "oblivious-set": "1.0.0", + "rimraf": "3.0.2", + "unload": "2.2.0" + } + }, "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", @@ -11848,6 +11872,11 @@ "url": "https://opencollective.com/js-sdsl" } }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -12278,6 +12307,11 @@ "node": ">=8.6" } }, + "node_modules/microseconds": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", + "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -12443,6 +12477,14 @@ "multicast-dns": "cli.js" } }, + "node_modules/nano-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", + "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", + "dependencies": { + "big-integer": "^1.6.16" + } + }, "node_modules/nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", @@ -12704,6 +12746,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oblivious-set": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", + "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" + }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -14681,6 +14728,31 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-query": { + "version": "3.39.3", + "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", + "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "broadcast-channel": "^3.4.1", + "match-sorter": "^6.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/react-redux": { "version": "8.0.5", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", @@ -16644,6 +16716,15 @@ "node": ">= 10.0.0" } }, + "node_modules/unload": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", + "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", + "dependencies": { + "@babel/runtime": "^7.6.2", + "detect-node": "^2.0.4" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index 89af1bf..40d5e2c 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-fast-marquee": "^1.3.5", + "react-query": "^3.39.3", "react-redux": "^8.0.5", "react-router-dom": "^6.8.1", "react-scripts": "5.0.1", diff --git a/src/App.tsx b/src/App.tsx index c0f7fcc..7fa5633 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,7 @@ import { Provider } from "react-redux"; import Inventory from "./Routes/Inventory/Inventory"; import Login from "./Routes/Login/Login"; import Product from "./Routes/Product/Product"; +import Activation from "./Routes/Activation/Activation"; const router = createBrowserRouter([ { @@ -65,6 +66,14 @@ const router = createBrowserRouter([ ), }, + { + path: "/Activation/:uid/:token", + element: ( + + + + ), + }, ]); export default function App() { diff --git a/src/Components/Container/Container.tsx b/src/Components/Container/Container.tsx index f9b553b..4438b7a 100644 --- a/src/Components/Container/Container.tsx +++ b/src/Components/Container/Container.tsx @@ -7,6 +7,7 @@ import { toggle_login } from "../../Features/Redux/Slices/Login/LoginSlice"; import { SetUser } from "../../Features/Redux/Slices/LoggedInUserSlice/LoggedInUserSlice"; import { useDispatch, useSelector } from "react-redux"; import { LoginState } from "../../Interfaces/Interfaces"; +import { useNavigate } from "react-router-dom"; export interface props { children: React.ReactNode; @@ -14,6 +15,7 @@ export interface props { export default function Container(props: props) { const dispatch = useDispatch(); + const navigate = useNavigate(); const logged_in = useSelector((state: LoginState) => state.logged_in.value); // Function to check for previous login session async function CheckPreviousSession() { @@ -35,7 +37,15 @@ export default function Container(props: props) {
- {props.children} +
+ {props.children} +
diff --git a/src/Components/Login/Login.tsx b/src/Components/Login/Login.tsx index df42ebd..4b812b2 100644 --- a/src/Components/Login/Login.tsx +++ b/src/Components/Login/Login.tsx @@ -1,5 +1,4 @@ -import { useSelector, useDispatch } from "react-redux"; -import { toggle_login } from "../../Features/Redux/Slices/Login/LoginSlice"; +import { useSelector } from "react-redux"; import { Button } from "@mui/material"; import styles from "../../styles"; import { useNavigate } from "react-router-dom"; @@ -12,12 +11,6 @@ export default function Login() { (state: LoggedInUserState) => state.logged_in_user.value ); const navigate = useNavigate(); - const dispatch = useDispatch(); - async function login() { - await dispatch(toggle_login()); - await console.log("Login State Toggled " + logged_in); - } - if (logged_in) { return (

diff --git a/src/Components/Logout/Logout.tsx b/src/Components/Logout/Logout.tsx index 036f478..3c10fed 100644 --- a/src/Components/Logout/Logout.tsx +++ b/src/Components/Logout/Logout.tsx @@ -20,6 +20,7 @@ export default function Logout(props: props) { async function logout() { await dispatch(toggle_login()); + localStorage.removeItem("token"); navigate("/"); } diff --git a/src/Routes/Activation/Activation.tsx b/src/Routes/Activation/Activation.tsx new file mode 100644 index 0000000..ff5ddbb --- /dev/null +++ b/src/Routes/Activation/Activation.tsx @@ -0,0 +1,58 @@ +import styles from "../../styles"; +import { useParams } from "react-router-dom"; +import { useEffect, useState } from "react"; +import { UserActivate } from "../../Components/Api/Api"; +import { ActivationParams } from "../../Interfaces/Interfaces"; + +export default function Activation() { + let { uid, token } = useParams(); + const [status, setStatus] = useState(0); + async function verify(activation: ActivationParams) { + let status = await UserActivate(activation); + if (status) { + setStatus(1); + } else { + setStatus(2); + } + } + useEffect(() => { + if (uid && token) { + verify({ uid, token }); + } + }, [uid, token]); + if (status === 1) { + return ( +

+

User ID: {uid}

+

+ Activation Token: {token} +

+

+ Activation Successful. Please login +

+
+ ); + } + if (status === 2) { + return ( +
+

User ID: {uid}

+

+ Activation Token: {token} +

+

+ Invalid Activation Link +

+
+ ); + } + return ( +
+

User ID: {uid}

+

+ Activation Token: {token} +

+

Activating...

+
+ ); +} diff --git a/src/Routes/Dashboard/Dashboard.tsx b/src/Routes/Dashboard/Dashboard.tsx index 751c3ba..55e3fcb 100644 --- a/src/Routes/Dashboard/Dashboard.tsx +++ b/src/Routes/Dashboard/Dashboard.tsx @@ -11,7 +11,7 @@ import RecentlyAddedIcon from "../../Components/Icons/RecentlyAddedIcon/Recently export default function Dashboard() { return ( -
+

Dashboard

diff --git a/src/Routes/Login/Login.tsx b/src/Routes/Login/Login.tsx index f728fce..7e87812 100644 --- a/src/Routes/Login/Login.tsx +++ b/src/Routes/Login/Login.tsx @@ -19,7 +19,7 @@ export default function Login() { }); const [error, setError] = useState(""); return ( -
+
+

Logs

diff --git a/src/Routes/Product/Product.tsx b/src/Routes/Product/Product.tsx index fc95a47..5db76b7 100644 --- a/src/Routes/Product/Product.tsx +++ b/src/Routes/Product/Product.tsx @@ -6,7 +6,7 @@ import { useParams } from "react-router-dom"; export default function Product() { let { id } = useParams(); return ( -
+

Individual Product View for id {id}

diff --git a/src/Routes/Products/Products.tsx b/src/Routes/Products/Products.tsx index 03162d3..7641217 100644 --- a/src/Routes/Products/Products.tsx +++ b/src/Routes/Products/Products.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React from "react"; import styles from "../../styles"; import { useNavigate } from "react-router-dom"; import ProductsIcon from "../../Components/Icons/ProductsIcon/ProductsIcon"; @@ -10,7 +10,7 @@ import ViewManager from "../../Components/ProductsPage/ViewManager"; export default function Products() { const navigate = useNavigate(); return ( -
+
diff --git a/src/routes/Inventory/Inventory.tsx b/src/routes/Inventory/Inventory.tsx index 5c2ae15..38b8997 100644 --- a/src/routes/Inventory/Inventory.tsx +++ b/src/routes/Inventory/Inventory.tsx @@ -14,7 +14,7 @@ import StockRenderer from "../../Components/InventoryPage/StockRenderer/StockRen export default function Inventory() { return ( -
+

Inventory

From 9cdca33783d5d5a4a765fa86a8c7feac14a340ac Mon Sep 17 00:00:00 2001 From: keannu125 Date: Mon, 6 Mar 2023 14:42:17 +0800 Subject: [PATCH 03/10] Restrict all pages to only logged in users --- src/Components/Sidebar/Sidebar.tsx | 4 +++- src/Routes/Dashboard/Dashboard.tsx | 8 ++++++++ src/Routes/Logs/Logs.tsx | 7 +++++++ src/Routes/Product/Product.tsx | 7 +++++++ src/Routes/Products/Products.tsx | 9 ++++++++- src/routes/Inventory/Inventory.tsx | 7 +++++++ 6 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/Components/Sidebar/Sidebar.tsx b/src/Components/Sidebar/Sidebar.tsx index 7dd700c..f95da1f 100644 --- a/src/Components/Sidebar/Sidebar.tsx +++ b/src/Components/Sidebar/Sidebar.tsx @@ -45,13 +45,15 @@ export default function Sidebar() { > - navigate("/Inventory")} name="Inventory" > + navigate("/Logs")} name="Logs"> + +
diff --git a/src/Routes/Dashboard/Dashboard.tsx b/src/Routes/Dashboard/Dashboard.tsx index 55e3fcb..efbdc93 100644 --- a/src/Routes/Dashboard/Dashboard.tsx +++ b/src/Routes/Dashboard/Dashboard.tsx @@ -8,8 +8,16 @@ import styles from "../../styles"; import HomeIcon from "../../Components/Icons/HomeIcon/HomeIcon"; import ColoredCube from "../../Components/ColoredCube/ColoredCube"; import RecentlyAddedIcon from "../../Components/Icons/RecentlyAddedIcon/RecentlyAddedIcon"; +import { Navigate } from "react-router-dom"; +import { LoginState } from "../../Interfaces/Interfaces"; +import { useSelector } from "react-redux"; export default function Dashboard() { + const logged_in = useSelector((state: LoginState) => state.logged_in.value); + if (!logged_in) { + return ; + } + return (
diff --git a/src/Routes/Logs/Logs.tsx b/src/Routes/Logs/Logs.tsx index 3d601b6..ae08edc 100644 --- a/src/Routes/Logs/Logs.tsx +++ b/src/Routes/Logs/Logs.tsx @@ -10,8 +10,15 @@ import { TableRow, } from "@mui/material"; import { SampleLogData } from "../../Components/SampleData/SampleData"; +import { Navigate } from "react-router-dom"; +import { LoginState } from "../../Interfaces/Interfaces"; +import { useSelector } from "react-redux"; export default function Logs() { + const logged_in = useSelector((state: LoginState) => state.logged_in.value); + if (!logged_in) { + return ; + } return (
diff --git a/src/Routes/Product/Product.tsx b/src/Routes/Product/Product.tsx index 5db76b7..8a4f01d 100644 --- a/src/Routes/Product/Product.tsx +++ b/src/Routes/Product/Product.tsx @@ -2,9 +2,16 @@ import * as React from "react"; import styles from "../../styles"; import { Button } from "@mui/material"; import { useParams } from "react-router-dom"; +import { Navigate } from "react-router-dom"; +import { LoginState } from "../../Interfaces/Interfaces"; +import { useSelector } from "react-redux"; export default function Product() { let { id } = useParams(); + const logged_in = useSelector((state: LoginState) => state.logged_in.value); + if (!logged_in) { + return ; + } return (

diff --git a/src/Routes/Products/Products.tsx b/src/Routes/Products/Products.tsx index 7641217..bb3082e 100644 --- a/src/Routes/Products/Products.tsx +++ b/src/Routes/Products/Products.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; import styles from "../../styles"; import { useNavigate } from "react-router-dom"; import ProductsIcon from "../../Components/Icons/ProductsIcon/ProductsIcon"; @@ -6,9 +6,16 @@ import AddIcon from "../../Components/Icons/AddIcon/AddIcon"; import { Button } from "@mui/material"; import { SampleProducts } from "../../Components/SampleData/SampleData"; import ViewManager from "../../Components/ProductsPage/ViewManager"; +import { Navigate } from "react-router-dom"; +import { LoginState } from "../../Interfaces/Interfaces"; +import { useSelector } from "react-redux"; export default function Products() { const navigate = useNavigate(); + const logged_in = useSelector((state: LoginState) => state.logged_in.value); + if (!logged_in) { + return ; + } return (
diff --git a/src/routes/Inventory/Inventory.tsx b/src/routes/Inventory/Inventory.tsx index 38b8997..170358c 100644 --- a/src/routes/Inventory/Inventory.tsx +++ b/src/routes/Inventory/Inventory.tsx @@ -11,8 +11,15 @@ import { } from "@mui/material"; import { SampleInventoryData } from "../../Components/SampleData/SampleData"; import StockRenderer from "../../Components/InventoryPage/StockRenderer/StockRenderer"; +import { Navigate } from "react-router-dom"; +import { LoginState } from "../../Interfaces/Interfaces"; +import { useSelector } from "react-redux"; export default function Inventory() { + const logged_in = useSelector((state: LoginState) => state.logged_in.value); + if (!logged_in) { + return ; + } return (
From 325fbf87db119532fe3bee027f3a1c2b17afc34d Mon Sep 17 00:00:00 2001 From: keannu125 Date: Mon, 6 Mar 2023 14:55:45 +0800 Subject: [PATCH 04/10] Added initial add product page and redirect login page to dashboard if already logged in --- src/App.tsx | 9 ++++++ src/Routes/AddProduct/AddProduct.tsx | 44 ++++++++++++++++++++++++++++ src/Routes/Login/Login.tsx | 7 +++++ src/Routes/Products/Products.tsx | 2 +- 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/Routes/AddProduct/AddProduct.tsx diff --git a/src/App.tsx b/src/App.tsx index 7fa5633..c32ec4b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,6 +11,7 @@ import Inventory from "./Routes/Inventory/Inventory"; import Login from "./Routes/Login/Login"; import Product from "./Routes/Product/Product"; import Activation from "./Routes/Activation/Activation"; +import AddProduct from "./Routes/AddProduct/AddProduct"; const router = createBrowserRouter([ { @@ -74,6 +75,14 @@ const router = createBrowserRouter([ ), }, + { + path: "/AddProduct", + element: ( + + + + ), + }, ]); export default function App() { diff --git a/src/Routes/AddProduct/AddProduct.tsx b/src/Routes/AddProduct/AddProduct.tsx new file mode 100644 index 0000000..6e2c15e --- /dev/null +++ b/src/Routes/AddProduct/AddProduct.tsx @@ -0,0 +1,44 @@ +import React, { useEffect } from "react"; +import styles from "../../styles"; +import { useNavigate } from "react-router-dom"; +import ProductsIcon from "../../Components/Icons/ProductsIcon/ProductsIcon"; +import AddIcon from "../../Components/Icons/AddIcon/AddIcon"; +import { Button } from "@mui/material"; +import { Navigate } from "react-router-dom"; +import { LoginState } from "../../Interfaces/Interfaces"; +import { useSelector } from "react-redux"; + +export default function AddProduct() { + const navigate = useNavigate(); + const logged_in = useSelector((state: LoginState) => state.logged_in.value); + if (!logged_in) { + return ; + } + return ( +
+
+
+
+ +

+ Add Product +

+
+
+
+
+ +
+ ); +} diff --git a/src/Routes/Login/Login.tsx b/src/Routes/Login/Login.tsx index 7e87812..bd62753 100644 --- a/src/Routes/Login/Login.tsx +++ b/src/Routes/Login/Login.tsx @@ -5,6 +5,9 @@ import { Button } from "@mui/material"; import { useDispatch } from "react-redux"; import { useNavigate } from "react-router-dom"; import { useState } from "react"; +import { Navigate } from "react-router-dom"; +import { LoginState } from "../../Interfaces/Interfaces"; +import { useSelector } from "react-redux"; import { UserInfo, UserLogin } from "../../Components/Api/Api"; import { toggle_login } from "../../Features/Redux/Slices/Login/LoginSlice"; @@ -18,6 +21,10 @@ export default function Login() { password: "", }); const [error, setError] = useState(""); + const logged_in = useSelector((state: LoginState) => state.logged_in.value); + if (logged_in) { + return ; + } return (
-
- ); -} diff --git a/src/Routes/NewProduct/NewProduct.tsx b/src/Routes/NewProduct/NewProduct.tsx new file mode 100644 index 0000000..7ca4c90 --- /dev/null +++ b/src/Routes/NewProduct/NewProduct.tsx @@ -0,0 +1,76 @@ +import React, { useEffect, useState } from "react"; +import styles from "../../styles"; +import { useNavigate } from "react-router-dom"; +import AddIcon from "../../Components/Icons/AddIcon/AddIcon"; +import { Button } from "@mui/material"; +import { Navigate } from "react-router-dom"; +import { LoginState } from "../../Interfaces/Interfaces"; +import { useSelector } from "react-redux"; +import { AddProduct } from "../../Components/Api/Api"; +import { useMutation, useQueryClient } from "react-query"; + +export default function NewProduct() { + const navigate = useNavigate(); + const logged_in = useSelector((state: LoginState) => state.logged_in.value); + const [product, setProduct] = useState(""); + const queryClient = useQueryClient(); + const mutation = useMutation({ + mutationFn: AddProduct, + onSuccess: () => { + queryClient.invalidateQueries("products"); + }, + }); + if (!logged_in) { + return ; + } + return ( +
+
+
+ +

+ Add Product +

+
+
+
+
+
+

+ Product Name +

+ { + setProduct(e.target.value); + }} + maxLength={20} + /> +
+
+ +
+
+
+ ); +} diff --git a/src/Routes/Products/Products.tsx b/src/Routes/Products/Products.tsx index 9c37588..27af1d0 100644 --- a/src/Routes/Products/Products.tsx +++ b/src/Routes/Products/Products.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React from "react"; import styles from "../../styles"; import { useNavigate } from "react-router-dom"; import ProductsIcon from "../../Components/Icons/ProductsIcon/ProductsIcon"; @@ -9,13 +9,57 @@ import ViewManager from "../../Components/ProductsPage/ViewManager"; import { Navigate } from "react-router-dom"; import { LoginState } from "../../Interfaces/Interfaces"; import { useSelector } from "react-redux"; +import { useQuery } from "react-query"; +import { GetProducts } from "../../Components/Api/Api"; export default function Products() { const navigate = useNavigate(); const logged_in = useSelector((state: LoginState) => state.logged_in.value); + const { + data: products, + isLoading, + error, + } = useQuery("products", GetProducts, { retry: 0 }); if (!logged_in) { return ; } + if (isLoading) { + return ( +
+
+
+
+ +

+ Products +

+
+
+

+ Loading Products... +

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

+ Products +

+
+
+

+ Error loading products +

+
+
+ ); + } return (
@@ -33,7 +77,7 @@ export default function Products() { }} >
- +
); } diff --git a/src/styles.tsx b/src/styles.tsx index 5331d0e..1031cfd 100644 --- a/src/styles.tsx +++ b/src/styles.tsx @@ -152,6 +152,7 @@ const styles: { [key: string]: React.CSSProperties } = { }, content_center: { display: "flex", + flexDirection: "column", justifyContent: "center", textAlign: "center", }, From b12f205efdbe66cafe7f45e2a4529c00937c3c21 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Mon, 6 Mar 2023 18:46:30 +0800 Subject: [PATCH 06/10] Fixed Products blobview product icon being too small --- src/Components/ProductsPage/BlobView/BlobView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/ProductsPage/BlobView/BlobView.tsx b/src/Components/ProductsPage/BlobView/BlobView.tsx index 3050979..d318af9 100644 --- a/src/Components/ProductsPage/BlobView/BlobView.tsx +++ b/src/Components/ProductsPage/BlobView/BlobView.tsx @@ -33,7 +33,7 @@ export default function BlobView({ Products }: ProductList) { onClick={() => navigate("/Product/" + row.id)} >
- {" "} + {" "}

{row.name}

From c3ae196b6ca53a969b5b11baa7f18ac2cee0ae0e Mon Sep 17 00:00:00 2001 From: keannu125 Date: Mon, 6 Mar 2023 20:09:14 +0800 Subject: [PATCH 07/10] Separated session checker and page login verifier into components --- src/Components/Api/Api.tsx | 1 + src/Components/Container/Container.tsx | 18 +----- src/Components/LoginChecker/LoginChecker.tsx | 16 +++++ .../PreviousSessionChecker.tsx | 29 ++++++++++ src/Routes/Dashboard/Dashboard.tsx | 10 +--- src/Routes/Logs/Logs.tsx | 9 +-- src/Routes/NewProduct/NewProduct.tsx | 7 +-- src/Routes/Product/Product.tsx | 58 ++++++++++++++----- src/Routes/Products/Products.tsx | 9 +-- src/routes/Inventory/Inventory.tsx | 9 +-- 10 files changed, 101 insertions(+), 65 deletions(-) create mode 100644 src/Components/LoginChecker/LoginChecker.tsx create mode 100644 src/Components/PreviousSessionChecker/PreviousSessionChecker.tsx diff --git a/src/Components/Api/Api.tsx b/src/Components/Api/Api.tsx index 23696c3..2c89ce1 100644 --- a/src/Components/Api/Api.tsx +++ b/src/Components/Api/Api.tsx @@ -6,6 +6,7 @@ import { LoginParams, RegistrationParams, } from "../../Interfaces/Interfaces"; + // Product APIs export function GetProducts() { diff --git a/src/Components/Container/Container.tsx b/src/Components/Container/Container.tsx index 4438b7a..99be824 100644 --- a/src/Components/Container/Container.tsx +++ b/src/Components/Container/Container.tsx @@ -8,30 +8,16 @@ import { SetUser } from "../../Features/Redux/Slices/LoggedInUserSlice/LoggedInU import { useDispatch, useSelector } from "react-redux"; import { LoginState } from "../../Interfaces/Interfaces"; import { useNavigate } from "react-router-dom"; +import PreviousSessionChecker from "../PreviousSessionChecker/PreviousSessionChecker"; export interface props { children: React.ReactNode; } export default function Container(props: props) { - const dispatch = useDispatch(); - const navigate = useNavigate(); - const logged_in = useSelector((state: LoginState) => state.logged_in.value); - // Function to check for previous login session - async function CheckPreviousSession() { - if (await CheckSavedSession()) { - if (logged_in !== true) { - await dispatch(toggle_login()); - await dispatch(SetUser(await UserInfo())); - } - } - } - useEffect(() => { - CheckPreviousSession(); - }, []); - return (
+
diff --git a/src/Components/LoginChecker/LoginChecker.tsx b/src/Components/LoginChecker/LoginChecker.tsx new file mode 100644 index 0000000..a32ca87 --- /dev/null +++ b/src/Components/LoginChecker/LoginChecker.tsx @@ -0,0 +1,16 @@ +import * as React from "react"; +import { Navigate } from "react-router-dom"; + +import { useDispatch, useSelector } from "react-redux"; +import { LoginState } from "../../Interfaces/Interfaces"; + +export interface props {} + +export default function LoginChecker() { + const logged_in = useSelector((state: LoginState) => state.logged_in.value); + if (!logged_in) { + console.log("Not logged in. Redirecting to login page"); + return ; + } + return
; +} diff --git a/src/Components/PreviousSessionChecker/PreviousSessionChecker.tsx b/src/Components/PreviousSessionChecker/PreviousSessionChecker.tsx new file mode 100644 index 0000000..76b6dfd --- /dev/null +++ b/src/Components/PreviousSessionChecker/PreviousSessionChecker.tsx @@ -0,0 +1,29 @@ +import * as React from "react"; +import { useNavigate } from "react-router-dom"; +import { useEffect, useState } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { CheckSavedSession, UserInfo } from "../Api/Api"; +import { toggle_login } from "../../Features/Redux/Slices/Login/LoginSlice"; +import { SetUser } from "../../Features/Redux/Slices/LoggedInUserSlice/LoggedInUserSlice"; +import { LoginState } from "../../Interfaces/Interfaces"; +export default function PreviousSessionChecker() { + const dispatch = useDispatch(); + const logged_in = useSelector((state: LoginState) => state.logged_in.value); + // Function to check for previous login session + useEffect(() => { + async function check() { + if (await UserInfo()) { + if (logged_in !== true) { + console.log("Previous session found. Restoring"); + await dispatch(toggle_login()); + await dispatch(SetUser(await UserInfo())); + } + } else { + console.log("No old session found"); + localStorage.removeItem("token"); + } + } + check(); + }, []); + return
; +} diff --git a/src/Routes/Dashboard/Dashboard.tsx b/src/Routes/Dashboard/Dashboard.tsx index efbdc93..c52dfac 100644 --- a/src/Routes/Dashboard/Dashboard.tsx +++ b/src/Routes/Dashboard/Dashboard.tsx @@ -8,18 +8,12 @@ import styles from "../../styles"; import HomeIcon from "../../Components/Icons/HomeIcon/HomeIcon"; import ColoredCube from "../../Components/ColoredCube/ColoredCube"; import RecentlyAddedIcon from "../../Components/Icons/RecentlyAddedIcon/RecentlyAddedIcon"; -import { Navigate } from "react-router-dom"; -import { LoginState } from "../../Interfaces/Interfaces"; -import { useSelector } from "react-redux"; +import LoginChecker from "../../Components/LoginChecker/LoginChecker"; export default function Dashboard() { - const logged_in = useSelector((state: LoginState) => state.logged_in.value); - if (!logged_in) { - return ; - } - return (
+

Dashboard

diff --git a/src/Routes/Logs/Logs.tsx b/src/Routes/Logs/Logs.tsx index ae08edc..4bd49fe 100644 --- a/src/Routes/Logs/Logs.tsx +++ b/src/Routes/Logs/Logs.tsx @@ -10,17 +10,12 @@ import { TableRow, } from "@mui/material"; import { SampleLogData } from "../../Components/SampleData/SampleData"; -import { Navigate } from "react-router-dom"; -import { LoginState } from "../../Interfaces/Interfaces"; -import { useSelector } from "react-redux"; +import LoginChecker from "../../Components/LoginChecker/LoginChecker"; export default function Logs() { - const logged_in = useSelector((state: LoginState) => state.logged_in.value); - if (!logged_in) { - return ; - } return (
+

Logs

diff --git a/src/Routes/NewProduct/NewProduct.tsx b/src/Routes/NewProduct/NewProduct.tsx index 7ca4c90..6523f36 100644 --- a/src/Routes/NewProduct/NewProduct.tsx +++ b/src/Routes/NewProduct/NewProduct.tsx @@ -8,10 +8,9 @@ import { LoginState } from "../../Interfaces/Interfaces"; import { useSelector } from "react-redux"; import { AddProduct } from "../../Components/Api/Api"; import { useMutation, useQueryClient } from "react-query"; - +import LoginChecker from "../../Components/LoginChecker/LoginChecker"; export default function NewProduct() { const navigate = useNavigate(); - const logged_in = useSelector((state: LoginState) => state.logged_in.value); const [product, setProduct] = useState(""); const queryClient = useQueryClient(); const mutation = useMutation({ @@ -20,11 +19,9 @@ export default function NewProduct() { queryClient.invalidateQueries("products"); }, }); - if (!logged_in) { - return ; - } return (
+
diff --git a/src/Routes/Product/Product.tsx b/src/Routes/Product/Product.tsx index 8a4f01d..6ea3d2c 100644 --- a/src/Routes/Product/Product.tsx +++ b/src/Routes/Product/Product.tsx @@ -2,30 +2,58 @@ import * as React from "react"; import styles from "../../styles"; import { Button } from "@mui/material"; import { useParams } from "react-router-dom"; -import { Navigate } from "react-router-dom"; -import { LoginState } from "../../Interfaces/Interfaces"; -import { useSelector } from "react-redux"; +import LoginChecker from "../../Components/LoginChecker/LoginChecker"; +import { GetProduct } from "../../Components/Api/Api"; +import { useQuery } from "react-query"; export default function Product() { let { id } = useParams(); - const logged_in = useSelector((state: LoginState) => state.logged_in.value); - if (!logged_in) { - return ; + const { + data: product, + isLoading, + error, + } = useQuery({ + queryKey: ["product", Number(id)], + queryFn: () => GetProduct(Number(id)), + }); + if (isLoading) { + return ( +
+ +

+ Individual Product View for id {id} +

+
+

+ Loading product... +

+
+
+ ); } return (
+

Individual Product View for id {id}

- +
+

+ Product Name: {product.name} +

+

+ Date Added: {product.date_added} +

+ +
); } diff --git a/src/Routes/Products/Products.tsx b/src/Routes/Products/Products.tsx index 27af1d0..98cb5f5 100644 --- a/src/Routes/Products/Products.tsx +++ b/src/Routes/Products/Products.tsx @@ -6,26 +6,21 @@ import AddIcon from "../../Components/Icons/AddIcon/AddIcon"; import { Button } from "@mui/material"; import { SampleProducts } from "../../Components/SampleData/SampleData"; import ViewManager from "../../Components/ProductsPage/ViewManager"; -import { Navigate } from "react-router-dom"; -import { LoginState } from "../../Interfaces/Interfaces"; -import { useSelector } from "react-redux"; import { useQuery } from "react-query"; import { GetProducts } from "../../Components/Api/Api"; +import LoginChecker from "../../Components/LoginChecker/LoginChecker"; export default function Products() { const navigate = useNavigate(); - const logged_in = useSelector((state: LoginState) => state.logged_in.value); const { data: products, isLoading, error, } = useQuery("products", GetProducts, { retry: 0 }); - if (!logged_in) { - return ; - } if (isLoading) { return (
+
diff --git a/src/routes/Inventory/Inventory.tsx b/src/routes/Inventory/Inventory.tsx index 170358c..ad04eb8 100644 --- a/src/routes/Inventory/Inventory.tsx +++ b/src/routes/Inventory/Inventory.tsx @@ -11,17 +11,12 @@ import { } from "@mui/material"; import { SampleInventoryData } from "../../Components/SampleData/SampleData"; import StockRenderer from "../../Components/InventoryPage/StockRenderer/StockRenderer"; -import { Navigate } from "react-router-dom"; -import { LoginState } from "../../Interfaces/Interfaces"; -import { useSelector } from "react-redux"; +import LoginChecker from "../../Components/LoginChecker/LoginChecker"; export default function Inventory() { - const logged_in = useSelector((state: LoginState) => state.logged_in.value); - if (!logged_in) { - return ; - } return (
+

Inventory

From 9065274a18d2e75c706d5e4cc34744e3861bc4c0 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Mon, 6 Mar 2023 20:41:45 +0800 Subject: [PATCH 08/10] Polished previous session checker --- src/Components/LoginChecker/LoginChecker.tsx | 9 ++++++--- .../PreviousSessionChecker.tsx | 7 ++++--- .../Redux/Slices/OldSession/OldSessionSlice.tsx | 17 +++++++++++++++++ src/Interfaces/Interfaces.tsx | 6 ++++++ src/Plugins/Redux/Store/Store.tsx | 2 ++ 5 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 src/Features/Redux/Slices/OldSession/OldSessionSlice.tsx diff --git a/src/Components/LoginChecker/LoginChecker.tsx b/src/Components/LoginChecker/LoginChecker.tsx index a32ca87..c99bee3 100644 --- a/src/Components/LoginChecker/LoginChecker.tsx +++ b/src/Components/LoginChecker/LoginChecker.tsx @@ -1,14 +1,17 @@ import * as React from "react"; import { Navigate } from "react-router-dom"; -import { useDispatch, useSelector } from "react-redux"; -import { LoginState } from "../../Interfaces/Interfaces"; +import { useSelector } from "react-redux"; +import { LoginState, OldSessionState } from "../../Interfaces/Interfaces"; export interface props {} export default function LoginChecker() { const logged_in = useSelector((state: LoginState) => state.logged_in.value); - if (!logged_in) { + const old_session_checked = useSelector( + (state: OldSessionState) => state.old_session_checked.value + ); + if (!logged_in && old_session_checked) { console.log("Not logged in. Redirecting to login page"); return ; } diff --git a/src/Components/PreviousSessionChecker/PreviousSessionChecker.tsx b/src/Components/PreviousSessionChecker/PreviousSessionChecker.tsx index 76b6dfd..d0945af 100644 --- a/src/Components/PreviousSessionChecker/PreviousSessionChecker.tsx +++ b/src/Components/PreviousSessionChecker/PreviousSessionChecker.tsx @@ -1,11 +1,11 @@ import * as React from "react"; -import { useNavigate } from "react-router-dom"; -import { useEffect, useState } from "react"; +import { useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; -import { CheckSavedSession, UserInfo } from "../Api/Api"; +import { UserInfo } from "../Api/Api"; import { toggle_login } from "../../Features/Redux/Slices/Login/LoginSlice"; import { SetUser } from "../../Features/Redux/Slices/LoggedInUserSlice/LoggedInUserSlice"; import { LoginState } from "../../Interfaces/Interfaces"; +import { set_checked } from "../../Features/Redux/Slices/OldSession/OldSessionSlice"; export default function PreviousSessionChecker() { const dispatch = useDispatch(); const logged_in = useSelector((state: LoginState) => state.logged_in.value); @@ -22,6 +22,7 @@ export default function PreviousSessionChecker() { console.log("No old session found"); localStorage.removeItem("token"); } + await dispatch(set_checked()); } check(); }, []); diff --git a/src/Features/Redux/Slices/OldSession/OldSessionSlice.tsx b/src/Features/Redux/Slices/OldSession/OldSessionSlice.tsx new file mode 100644 index 0000000..04e37e3 --- /dev/null +++ b/src/Features/Redux/Slices/OldSession/OldSessionSlice.tsx @@ -0,0 +1,17 @@ +import { createSlice } from "@reduxjs/toolkit"; + +export const OldSessionSlice = createSlice({ + name: "old_session_checked", + initialState: { + value: false, + }, + reducers: { + set_checked: (state) => { + state.value = !state.value; + }, + }, +}); + +export const { set_checked } = OldSessionSlice.actions; + +export default OldSessionSlice.reducer; diff --git a/src/Interfaces/Interfaces.tsx b/src/Interfaces/Interfaces.tsx index 403b08f..35ce41a 100644 --- a/src/Interfaces/Interfaces.tsx +++ b/src/Interfaces/Interfaces.tsx @@ -15,6 +15,12 @@ export interface LoginState { }; } +export interface OldSessionState { + old_session_checked: { + value: boolean; + }; +} + export interface LoggedInUserState { logged_in_user: { value: { diff --git a/src/Plugins/Redux/Store/Store.tsx b/src/Plugins/Redux/Store/Store.tsx index 169e668..a7e36b1 100644 --- a/src/Plugins/Redux/Store/Store.tsx +++ b/src/Plugins/Redux/Store/Store.tsx @@ -1,10 +1,12 @@ import { configureStore } from "@reduxjs/toolkit"; import LoginReducer from "../../../Features/Redux/Slices/Login/LoginSlice"; import LoggedInUserReducer from "../../../Features/Redux/Slices/LoggedInUserSlice/LoggedInUserSlice"; +import OldSessionReducer from "../../../Features/Redux/Slices/OldSession/OldSessionSlice"; export default configureStore({ reducer: { logged_in: LoginReducer, logged_in_user: LoggedInUserReducer, + old_session_checked: OldSessionReducer, }, }); From 3ac7785c3c2c6f32756ed98685af6b444aceaa18 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Mon, 6 Mar 2023 20:45:56 +0800 Subject: [PATCH 09/10] Fixed products page error and loading status --- src/Routes/Products/Products.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Routes/Products/Products.tsx b/src/Routes/Products/Products.tsx index 98cb5f5..bd81804 100644 --- a/src/Routes/Products/Products.tsx +++ b/src/Routes/Products/Products.tsx @@ -30,8 +30,10 @@ export default function Products() {

+
+

- Loading Products... + Loading products...

@@ -48,6 +50,8 @@ export default function Products() {
+
+

Error loading products

From 57f11b024b9a4d95e0c11bc8785d429cddd58b90 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Mon, 6 Mar 2023 21:06:50 +0800 Subject: [PATCH 10/10] Made products page fully functional with delete product --- src/Components/ProductsPage/ViewManager.tsx | 12 +- src/Routes/Dashboard/Dashboard.tsx | 124 +++++++++----------- src/Routes/Login/Login.tsx | 4 +- src/Routes/Logs/Logs.tsx | 2 +- src/Routes/NewProduct/NewProduct.tsx | 4 +- src/Routes/Product/Product.tsx | 67 ++++++++--- src/Routes/Products/Products.tsx | 20 ++-- src/routes/Inventory/Inventory.tsx | 2 +- src/styles.tsx | 3 +- 9 files changed, 134 insertions(+), 104 deletions(-) diff --git a/src/Components/ProductsPage/ViewManager.tsx b/src/Components/ProductsPage/ViewManager.tsx index 0ef4659..da535a6 100644 --- a/src/Components/ProductsPage/ViewManager.tsx +++ b/src/Components/ProductsPage/ViewManager.tsx @@ -4,11 +4,21 @@ import { Switch } from "@mui/material"; import TableView from "../../Components/ProductsPage/TableView/TableView"; import BlobView from "../../Components/ProductsPage/BlobView/BlobView"; import { ProductList } from "../../Interfaces/Interfaces"; +import styles from "../../styles"; export interface props {} export default function ViewManager(props: ProductList) { - const [tableView, toggleTableView] = useState(false); + const [tableView, toggleTableView] = useState(true); + if (props.Products.length === 0) { + return ( +
+

+ No products yet. Add one! +

+
+ ); + } if (tableView) { return (
diff --git a/src/Routes/Dashboard/Dashboard.tsx b/src/Routes/Dashboard/Dashboard.tsx index c52dfac..8be0dce 100644 --- a/src/Routes/Dashboard/Dashboard.tsx +++ b/src/Routes/Dashboard/Dashboard.tsx @@ -16,7 +16,7 @@ export default function Dashboard() {
-

Dashboard

+

Dashboard

-

+

Total Products -

+

-

+

2546 Unique Items -

-

+

+

In inventory -

+

-

+

Current Session -

+

-

+

Added -

+

-

254

+

254

-

+

Removed -

+

-

118

+

118

-

+

Low Stock -

+

-

+

Canned Pagmamahal -

-

+

+

In Stock: 3 -

+

-

Recently Added -

+

-

+

Zidane's Water -

-

+

+

Added 02/17/2023 -

+

@@ -133,66 +133,58 @@ export default function Dashboard() {
-

- Recent -

-

+

Recent

+

Transactions -

+

-

+

Kopiko Blanca -

-

- Added: 96 -

-

+

+

Added: 96

+

Removed: 105 -

-

+

+

02/17/2023 -

+

-

+

Zidane's Water -

-

- Added: 49 -

-

+

+

Added: 49

+

Removed: 24 -

-

+

+

02/17/2023 -

+

-

+

Dan's Beefed Corn -

-

- Added: 32 -

-

+

+

Added: 32

+

Removed: 64 -

-

+

+

02/17/2023 -

+

-

+

Canned Pagmamahal -

+

-

Added: 0

-

+

Added: 0

+

Removed: 60 -

-

+

+

02/17/2023 -

+

diff --git a/src/Routes/Login/Login.tsx b/src/Routes/Login/Login.tsx index bd62753..e2ace97 100644 --- a/src/Routes/Login/Login.tsx +++ b/src/Routes/Login/Login.tsx @@ -36,9 +36,9 @@ export default function Login() { >
-

+

Login to Ivy -

+

Username

diff --git a/src/Routes/Logs/Logs.tsx b/src/Routes/Logs/Logs.tsx index 4bd49fe..5ef42a2 100644 --- a/src/Routes/Logs/Logs.tsx +++ b/src/Routes/Logs/Logs.tsx @@ -18,7 +18,7 @@ export default function Logs() {
-

Logs

+

Logs

-

- Add Product -

+

Add Product

diff --git a/src/Routes/Product/Product.tsx b/src/Routes/Product/Product.tsx index 6ea3d2c..5497a35 100644 --- a/src/Routes/Product/Product.tsx +++ b/src/Routes/Product/Product.tsx @@ -1,12 +1,14 @@ import * as React from "react"; import styles from "../../styles"; import { Button } from "@mui/material"; -import { useParams } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import LoginChecker from "../../Components/LoginChecker/LoginChecker"; -import { GetProduct } from "../../Components/Api/Api"; -import { useQuery } from "react-query"; +import { DeleteProduct, GetProduct } from "../../Components/Api/Api"; +import { useMutation, useQuery, useQueryClient } from "react-query"; +import ProductIcon from "../../Components/Icons/ProductIcon/ProductIcon"; export default function Product() { + const navigate = useNavigate(); let { id } = useParams(); const { data: product, @@ -16,17 +18,38 @@ export default function Product() { queryKey: ["product", Number(id)], queryFn: () => GetProduct(Number(id)), }); + const queryClient = useQueryClient(); + const mutation = useMutation({ + mutationFn: DeleteProduct, + onSuccess: () => { + queryClient.invalidateQueries("products"); + }, + }); if (isLoading) { return (
-

+

Individual Product View for id {id} -

+

-

+

Loading product... -

+

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

+ Individual Product View for id {id} +

+
+

+ Error loading product +

); @@ -34,24 +57,32 @@ export default function Product() { return (
-

- Individual Product View for id {id} -

+
+ +

Product View

+
+
-

- Product Name: {product.name} -

-

- Date Added: {product.date_added} -

+
+

+ Product Name: {product.name} +

+

+ Date Added: {product.date_added} +

+
diff --git a/src/Routes/Products/Products.tsx b/src/Routes/Products/Products.tsx index bd81804..95e6a37 100644 --- a/src/Routes/Products/Products.tsx +++ b/src/Routes/Products/Products.tsx @@ -25,16 +25,16 @@ export default function Products() {
-

+

Products -

+

-

+

Loading products... -

+

); @@ -45,16 +45,16 @@ export default function Products() {
-

+

Products -

+

-

+

Error loading products -

+

); @@ -65,9 +65,7 @@ export default function Products() {
-

- Products -

+

Products

-

Inventory

+

Inventory