From 1baf1ab5d241104dc52d106113e2650bf4f689c6 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Sat, 11 Mar 2023 20:22:18 +0800 Subject: [PATCH 01/11] Polished logout sidebar button and added dailyview page --- src/App.tsx | 9 ++ src/Components/Icons/TodayIcon/TodayIcon.tsx | 27 ++++ src/Components/Sidebar/Sidebar.tsx | 137 ++++++++----------- src/Routes/DailyView/DailyView.tsx | 90 ++++++++++++ 4 files changed, 180 insertions(+), 83 deletions(-) create mode 100644 src/Components/Icons/TodayIcon/TodayIcon.tsx create mode 100644 src/Routes/DailyView/DailyView.tsx diff --git a/src/App.tsx b/src/App.tsx index 1f8b4a5..567eb03 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -22,6 +22,7 @@ import Activation from "./Routes/Activation/Activation"; import { QueryClient, QueryClientProvider } from "react-query"; import NewProduct from "./Routes/NewProduct/NewProduct"; import Register from "./Routes/Register/Register"; +import DailyView from "./Routes/DailyView/DailyView"; const queryClient = new QueryClient(); @@ -103,6 +104,14 @@ const router = createHashRouter([ ), }, + { + path: "/ActivityToday", + element: ( + + + + ), + }, ]); export default function App() { diff --git a/src/Components/Icons/TodayIcon/TodayIcon.tsx b/src/Components/Icons/TodayIcon/TodayIcon.tsx new file mode 100644 index 0000000..e6fe11f --- /dev/null +++ b/src/Components/Icons/TodayIcon/TodayIcon.tsx @@ -0,0 +1,27 @@ +import React from "react"; + +export interface props { + size: number; + color: string; +} +export default function TodayIcon(props: props) { + return ( + + + + + + + + + ); +} diff --git a/src/Components/Sidebar/Sidebar.tsx b/src/Components/Sidebar/Sidebar.tsx index f95da1f..971a402 100644 --- a/src/Components/Sidebar/Sidebar.tsx +++ b/src/Components/Sidebar/Sidebar.tsx @@ -9,6 +9,7 @@ import Logout from "../Logout/Logout"; import InventoryIcon from "../Icons/InventoryIcon/InventoryIcon"; import LogsIcon from "../Icons/LogsIcon/LogsIcon"; import LogoutIcon from "../Icons/LogoutIcon/LogoutIcon"; +import TodayIcon from "../Icons/TodayIcon/TodayIcon"; export interface state { logged_in: { @@ -18,88 +19,58 @@ export interface state { export default function Sidebar() { const navigate = useNavigate(); const logged_in = useSelector((state: state) => state.logged_in.value); - if (!logged_in) { - return ( -
-
-
- navigate("/")} name="Dashboard"> - - - navigate("/Products")} - name="Products" - > - - - navigate("/Inventory")} - name="Inventory" - > - - - navigate("/Logs")} name="Logs"> - - -
-
-
- ); - } else { - return ( -
-
-
- navigate("/")} name="Dashboard"> - - - navigate("/Products")} - name="Products" - > - - - navigate("/Inventory")} - name="Inventory" - > - - - navigate("/Logs")} name="Logs"> - - - - - -
-
-
- ); + function LogoutButton() { + if (!logged_in) { + return
; + } else { + return ( + + + + ); + } } + return ( +
+
+
+ navigate("/")} name="Dashboard"> + + + navigate("/Products")} name="Products"> + + + navigate("/Inventory")} + name="Inventory" + > + + + navigate("/ActivityToday")} + name="Daily View" + > + + + navigate("/Logs")} name="Logs"> + + + +
+
+
+ ); } diff --git a/src/Routes/DailyView/DailyView.tsx b/src/Routes/DailyView/DailyView.tsx new file mode 100644 index 0000000..d26f460 --- /dev/null +++ b/src/Routes/DailyView/DailyView.tsx @@ -0,0 +1,90 @@ +import React, { useState } from "react"; +import TotalProductsIcon from "../../Components/Icons/TotalProductsIcon/TotalProductsIcon"; +import LowStockIcon from "../../Components/Icons/LowStockIcon/LowStockIcon"; +import StatsIcon from "../../Components/Icons/StatsIcon/StatsIcon"; +import LogsIcon from "../../Components/Icons/LogsIcon/LogsIcon"; +import "../../index.css"; +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 LoginChecker from "../../Components/LoginChecker/LoginChecker"; +import { useQuery } from "react-query"; +import { + GetLogs, + GetLowestStockedProduct, + GetProducts, +} from "../../Components/Api/Api"; +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"; +import TodayIcon from "../../Components/Icons/TodayIcon/TodayIcon"; + +export default function DailyView() { + const logs = useQuery("logs", GetLogs, { retry: 0 }); + const products = useQuery("products", GetProducts, { retry: 0 }); + const lowest_stock_product = useQuery( + "lowest_stock_product", + GetLowestStockedProduct, + { + retry: 0, + } + ); + const old_session_checked = useSelector( + (state: OldSessionState) => state.old_session_checked.value + ); + if ( + logs.isLoading || + products.isLoading || + lowest_stock_product.isLoading || + !old_session_checked + ) { + return ( +
+ +
+ +

Daily View

+
+
+

+ Loading today's summary... +

+
+
+ ); + } + if (logs.error || products.error || lowest_stock_product.isError) { +
+ +
+ +

Daily View

+
+
+

+ Error loading today's summary +

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

Daily View

+
+
+

Heh

+
+
+ ); +} From a0a05e2df36db0a93ea17a09744665abeff93af8 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Sun, 12 Mar 2023 00:09:32 +0800 Subject: [PATCH 02/11] Separated recent transactions on dashboard into its own widget. Also added initial daily view page --- .../RecentTransactionsWidget.tsx | 42 +++++++++++++++++++ src/Components/GetToday/GetToday.tsx | 11 +++++ src/Routes/Dashboard/Dashboard.tsx | 34 +-------------- 3 files changed, 55 insertions(+), 32 deletions(-) create mode 100644 src/Components/DashboardPage/RecentTransactionsWidget/RecentTransactionsWidget.tsx create mode 100644 src/Components/GetToday/GetToday.tsx diff --git a/src/Components/DashboardPage/RecentTransactionsWidget/RecentTransactionsWidget.tsx b/src/Components/DashboardPage/RecentTransactionsWidget/RecentTransactionsWidget.tsx new file mode 100644 index 0000000..1465f57 --- /dev/null +++ b/src/Components/DashboardPage/RecentTransactionsWidget/RecentTransactionsWidget.tsx @@ -0,0 +1,42 @@ +import * as React from "react"; +import { ProductLog, ProductLogList } from "../../../Interfaces/Interfaces"; +import styles from "../../../styles"; +import LogsIcon from "../../Icons/LogsIcon/LogsIcon"; +import Moment from "react-moment"; + +export default function RecentTransactionsWidget(props: ProductLogList) { + return ( +
+
+
+ +
+

Recent

+

+ Transactions +

+
+
+ {props.ProductLogs.slice(0, 5).map((log: ProductLog, index: number) => { + return ( +
+
+

+ {log.name} +

+

+ Quantity: {log.quantity} +

+

+ {log.history_date} +

+

+ Transaction ID: {log.history_id} +

+
+ ); + })} +
+
+ ); +} diff --git a/src/Components/GetToday/GetToday.tsx b/src/Components/GetToday/GetToday.tsx new file mode 100644 index 0000000..be17d04 --- /dev/null +++ b/src/Components/GetToday/GetToday.tsx @@ -0,0 +1,11 @@ +export default function GetToday() { + const current = new Date(); + const date = + ("0" + (current.getMonth() + 1)).slice(-2) + + "-" + + ("0" + current.getDate()).slice(-2) + + "-" + + current.getFullYear(); + console.log("Today is " + date); + return date; +} diff --git a/src/Routes/Dashboard/Dashboard.tsx b/src/Routes/Dashboard/Dashboard.tsx index 11e5df2..fdf1d57 100644 --- a/src/Routes/Dashboard/Dashboard.tsx +++ b/src/Routes/Dashboard/Dashboard.tsx @@ -25,6 +25,7 @@ import LowestStockWidget from "../../Components/DashboardPage/LowestStockWidget/ import RecentlyAddedWidget from "../../Components/DashboardPage/RecentlyAddedWidget/RecentlyAddedWidget"; import TotalProductsWidget from "../../Components/DashboardPage/TotalProductsWidget/TotalProductsWidget"; import SessionStatsWidget from "../../Components/DashboardPage/SessionStatsWidget/SessionStatsWidget"; +import RecentTransactionsWidget from "../../Components/DashboardPage/RecentTransactionsWidget/RecentTransactionsWidget"; export default function Dashboard() { const logs = useQuery("logs", GetLogs, { retry: 0 }); @@ -107,38 +108,7 @@ export default function Dashboard() {
-
-
-
- -
-

Recent

-

- Transactions -

-
-
- {logs.data.slice(0, 5).map((log: ProductLog, index: number) => { - return ( -
-
-

- {log.name} -

-

- Quantity: {log.quantity} -

-

- Date: {log.history_date} -

-

- Transaction ID: {log.history_id} -

-
- ); - })} -
-
+
); From b7e91c345ffd7c679620bbee79e3ea208e795420 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Sun, 12 Mar 2023 11:43:42 +0800 Subject: [PATCH 03/11] Added daily view page --- package-lock.json | 20 +++++++ package.json | 1 + src/Components/Api/Api.tsx | 85 ++++++++++++------------------ src/Interfaces/Interfaces.tsx | 6 +++ src/Routes/DailyView/DailyView.tsx | 55 ++++++++++++------- 5 files changed, 97 insertions(+), 70 deletions(-) diff --git a/package-lock.json b/package-lock.json index f2fcfb9..1744336 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-moment": "^1.1.3", "react-query": "^3.39.3", "react-redux": "^8.0.5", "react-router-dom": "^6.8.1", @@ -12592,6 +12593,15 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "peer": true, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -14881,6 +14891,16 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-moment": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/react-moment/-/react-moment-1.1.3.tgz", + "integrity": "sha512-8EPvlUL8u6EknPp1ISF5MQ3wx2OHJVXIP/iZc4wRh3iV3XozftZERDv9ANZeAtMlhNNQHdFoqcZHFUkBSTONfA==", + "peerDependencies": { + "moment": "^2.29.0", + "prop-types": "^15.7.0", + "react": "^16.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-query": { "version": "3.39.3", "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", diff --git a/package.json b/package.json index 17997f8..9e40098 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-fast-marquee": "^1.3.5", + "react-moment": "^1.1.3", "react-query": "^3.39.3", "react-redux": "^8.0.5", "react-router-dom": "^6.8.1", diff --git a/src/Components/Api/Api.tsx b/src/Components/Api/Api.tsx index 0cfc1f5..db8d4fb 100644 --- a/src/Components/Api/Api.tsx +++ b/src/Components/Api/Api.tsx @@ -8,11 +8,14 @@ import { } from "../../Interfaces/Interfaces"; // Product APIs +const instance = axios.create({ + baseURL: "https://keannu125.pythonanywhere.com", +}); export function GetProducts() { const token = JSON.parse(localStorage.getItem("token") || "{}"); - return axios - .get("https://keannu125.pythonanywhere.com/api/v1/products/", { + return instance + .get("api/v1/products/", { headers: { Authorization: "Token " + token, }, @@ -24,8 +27,8 @@ export function GetProducts() { export function GetProduct(id: number) { const token = JSON.parse(localStorage.getItem("token") || "{}"); - return axios - .get("https://keannu125.pythonanywhere.com/api/v1/products/" + id + "/", { + return instance + .get("api/v1/products/" + id + "/", { headers: { Authorization: "Token " + token, }, @@ -37,18 +40,12 @@ export function GetProduct(id: number) { export function UpdateProduct(product: UpdateProductParams) { const token = JSON.parse(localStorage.getItem("token") || "{}"); - return axios - .patch( - "https://keannu125.pythonanywhere.com/api/v1/products/" + - product.id + - "/", - product, - { - headers: { - Authorization: "Token " + token, - }, - } - ) + return instance + .patch("api/v1/products/" + product.id + "/", product, { + headers: { + Authorization: "Token " + token, + }, + }) .then((response) => { console.log("Product update successful"); return response.data; @@ -61,8 +58,8 @@ export function UpdateProduct(product: UpdateProductParams) { export function GetLowestStockedProduct() { const token = JSON.parse(localStorage.getItem("token") || "{}"); - return axios - .get("https://keannu125.pythonanywhere.com/api/v1/lowest_stock_product/", { + return instance + .get("api/v1/lowest_stock_product/", { headers: { Authorization: "Token " + token, }, @@ -74,8 +71,8 @@ export function GetLowestStockedProduct() { export function GetLogs() { const token = JSON.parse(localStorage.getItem("token") || "{}"); - return axios - .get("https://keannu125.pythonanywhere.com/api/v1/logs/", { + return instance + .get("api/v1/logs/", { headers: { Authorization: "Token " + token, }, @@ -87,8 +84,8 @@ export function GetLogs() { export function AddProduct(note: AddProductParams) { const token = JSON.parse(localStorage.getItem("token") || "{}"); - return axios - .post("https://keannu125.pythonanywhere.com/api/v1/products/", note, { + return instance + .post("api/v1/products/", note, { headers: { Authorization: "Token " + token, }, @@ -104,15 +101,12 @@ export function AddProduct(note: AddProductParams) { export function DeleteProduct(id: number) { const token = JSON.parse(localStorage.getItem("token") || "{}"); - return axios - .delete( - "https://keannu125.pythonanywhere.com/api/v1/products/" + id + "/", - { - headers: { - Authorization: "Token " + token, - }, - } - ) + return instance + .delete("api/v1/products/" + id + "/", { + headers: { + Authorization: "Token " + token, + }, + }) .catch((error) => { console.log("Error deleting product"); return error; @@ -122,11 +116,8 @@ export function DeleteProduct(id: number) { // User APIs export function UserRegister(register: RegistrationParams) { - return axios - .post( - "https://keannu125.pythonanywhere.com/api/v1/accounts/users/", - register - ) + return instance + .post("api/v1/accounts/users/", register) .then(async (response) => { console.log(response.data); return true; @@ -138,11 +129,8 @@ export function UserRegister(register: RegistrationParams) { } export function UserLogin(user: LoginParams) { - return axios - .post( - "https://keannu125.pythonanywhere.com/api/v1/accounts/token/login/", - user - ) + return instance + .post("api/v1/accounts/token/login/", user) .then(async (response) => { localStorage.setItem("token", JSON.stringify(response.data.auth_token)); console.log("Login Success "); @@ -156,8 +144,8 @@ export function UserLogin(user: LoginParams) { export function UserInfo() { const token = JSON.parse(localStorage.getItem("token") || "{}"); - return axios - .get("https://keannu125.pythonanywhere.com/api/v1/accounts/users/me/", { + return instance + .get("api/v1/accounts/users/me/", { headers: { Authorization: "Token " + token, }, @@ -174,8 +162,8 @@ export function UserInfo() { export function QueryUser(id: number) { const token = JSON.parse(localStorage.getItem("token") || "{}"); - return axios - .get("https://keannu125.pythonanywhere.com/api/v1/user_list/" + id, { + return instance + .get("api/v1/user_list/" + id, { headers: { Authorization: "Token " + token, }, @@ -191,11 +179,8 @@ export function QueryUser(id: number) { } export function UserActivate(activation: ActivationParams) { - return axios - .post( - "https://keannu125.pythonanywhere.com/api/v1/accounts/users/activation/", - activation - ) + return instance + .post("api/v1/accounts/users/activation/", activation) .then(async (response) => { console.log("Activation Success"); return true; diff --git a/src/Interfaces/Interfaces.tsx b/src/Interfaces/Interfaces.tsx index c831f44..a6519c7 100644 --- a/src/Interfaces/Interfaces.tsx +++ b/src/Interfaces/Interfaces.tsx @@ -7,6 +7,12 @@ export interface Product { name: string; date_added: string; quantity: number; + history: ProductHistoryEntry[]; +} + +export interface ProductHistoryEntry { + quantity: number; + history_date: string; } export interface ProductLogList { diff --git a/src/Routes/DailyView/DailyView.tsx b/src/Routes/DailyView/DailyView.tsx index d26f460..ab35d0c 100644 --- a/src/Routes/DailyView/DailyView.tsx +++ b/src/Routes/DailyView/DailyView.tsx @@ -1,13 +1,6 @@ -import React, { useState } from "react"; -import TotalProductsIcon from "../../Components/Icons/TotalProductsIcon/TotalProductsIcon"; -import LowStockIcon from "../../Components/Icons/LowStockIcon/LowStockIcon"; -import StatsIcon from "../../Components/Icons/StatsIcon/StatsIcon"; -import LogsIcon from "../../Components/Icons/LogsIcon/LogsIcon"; +import React from "react"; import "../../index.css"; 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 LoginChecker from "../../Components/LoginChecker/LoginChecker"; import { useQuery } from "react-query"; import { @@ -15,17 +8,14 @@ import { GetLowestStockedProduct, GetProducts, } from "../../Components/Api/Api"; -import { - OldSessionState, - ProductLog, - SessionTransactions, -} from "../../Interfaces/Interfaces"; +import { OldSessionState, Product } 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"; import TodayIcon from "../../Components/Icons/TodayIcon/TodayIcon"; +import moment from "moment"; +import GetToday from "../../Components/GetToday/GetToday"; +import Moment from "react-moment"; +import { useNavigate } from "react-router-dom"; +import { Button } from "@mui/material"; export default function DailyView() { const logs = useQuery("logs", GetLogs, { retry: 0 }); @@ -40,6 +30,7 @@ export default function DailyView() { const old_session_checked = useSelector( (state: OldSessionState) => state.old_session_checked.value ); + const navigate = useNavigate(); if ( logs.isLoading || products.isLoading || @@ -80,10 +71,34 @@ export default function DailyView() {
-

Daily View

+

+ Products Modified Today +

-
-

Heh

+
+ {products.data + .filter( + (Product: Product) => + moment(Product.history[0].history_date).format("MM-DD-YYYY") === + GetToday() + ) + .map((Product: Product) => ( + + ))}
); From 7b25dc13dddadaee34342ef47a1d30beeed93ba3 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Sun, 12 Mar 2023 11:45:24 +0800 Subject: [PATCH 04/11] Polished blobview button per product --- src/Components/ProductsPage/BlobView/BlobView.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Components/ProductsPage/BlobView/BlobView.tsx b/src/Components/ProductsPage/BlobView/BlobView.tsx index d318af9..e88e7e9 100644 --- a/src/Components/ProductsPage/BlobView/BlobView.tsx +++ b/src/Components/ProductsPage/BlobView/BlobView.tsx @@ -21,7 +21,7 @@ export default function BlobView({ Products }: ProductList) { padding: 16, }} > - + ))} From fc22234c6fbf2eaeeb624e72c25227b62a0adf46 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Sun, 12 Mar 2023 12:17:07 +0800 Subject: [PATCH 05/11] Renamed daily view to summary --- src/Components/Sidebar/Sidebar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Sidebar/Sidebar.tsx b/src/Components/Sidebar/Sidebar.tsx index 971a402..1da4f53 100644 --- a/src/Components/Sidebar/Sidebar.tsx +++ b/src/Components/Sidebar/Sidebar.tsx @@ -61,7 +61,7 @@ export default function Sidebar() { navigate("/ActivityToday")} - name="Daily View" + name="Summary" > From 89c31cd1accb2b1644f793896bf16e1adffe5591 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Sun, 12 Mar 2023 12:39:18 +0800 Subject: [PATCH 06/11] Added functionality to daily view page --- src/Routes/DailyView/DailyView.tsx | 66 +++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/Routes/DailyView/DailyView.tsx b/src/Routes/DailyView/DailyView.tsx index ab35d0c..dd2aef1 100644 --- a/src/Routes/DailyView/DailyView.tsx +++ b/src/Routes/DailyView/DailyView.tsx @@ -15,7 +15,14 @@ import moment from "moment"; import GetToday from "../../Components/GetToday/GetToday"; import Moment from "react-moment"; import { useNavigate } from "react-router-dom"; -import { Button } from "@mui/material"; +import { + Button, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, +} from "@mui/material"; export default function DailyView() { const logs = useQuery("logs", GetLogs, { retry: 0 }); @@ -84,7 +91,10 @@ export default function DailyView() { ) .map((Product: Product) => ( ))} From 8fdb589e6788f775b08010c1666f996a2a1874a3 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Sun, 12 Mar 2023 12:43:06 +0800 Subject: [PATCH 07/11] Added individual transaction log to product page --- src/Routes/Product/Product.tsx | 57 ++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/Routes/Product/Product.tsx b/src/Routes/Product/Product.tsx index f26a575..a45d1dd 100644 --- a/src/Routes/Product/Product.tsx +++ b/src/Routes/Product/Product.tsx @@ -1,13 +1,24 @@ import * as React from "react"; import styles from "../../styles"; -import { Button } from "@mui/material"; +import { + Button, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, +} from "@mui/material"; import { useNavigate, useParams } from "react-router-dom"; 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"; +import { + OldSessionState, + ProductHistoryEntry, +} from "../../Interfaces/Interfaces"; +import moment from "moment"; export default function Product() { const navigate = useNavigate(); @@ -91,6 +102,48 @@ export default function Product() { > Delete Product +

+ Individual Transaction Log +

+
+ + + + + Time + + + Quantity + + + + + {product.history.map( + (history_entry: ProductHistoryEntry, index: number) => ( + + + {moment(history_entry.history_date).format( + "MM-DD-YYYY hh:mm A" + )} + + + {history_entry.quantity} + + + ) + )} + + +
); From 9b29f050b6cf073bc1821152b026d4a97450fafc Mon Sep 17 00:00:00 2001 From: keannu125 Date: Sun, 12 Mar 2023 14:18:14 +0800 Subject: [PATCH 08/11] Added email validation to see if email exists on register page --- src/Components/Api/Api.tsx | 16 ++++++++++++++++ src/Routes/Register/Register.tsx | 22 ++++++++++++++-------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/Components/Api/Api.tsx b/src/Components/Api/Api.tsx index db8d4fb..e9e1499 100644 --- a/src/Components/Api/Api.tsx +++ b/src/Components/Api/Api.tsx @@ -206,3 +206,19 @@ export async function CheckSavedSession() { console.log("No previous session found"); return false; } + +export function VerifyEmail(email: string) { + return axios + .get( + "https://emailvalidation.abstractapi.com/v1/?api_key=d7abfb5f41b7476faaebe37ceba8ae37&email=" + + email + ) + .then((response) => { + console.log("Email valid?" + response.data); + return true; + }) + .catch((error) => { + console.log("Email valid?" + error); + return false; + }); +} diff --git a/src/Routes/Register/Register.tsx b/src/Routes/Register/Register.tsx index 1224982..984bcd1 100644 --- a/src/Routes/Register/Register.tsx +++ b/src/Routes/Register/Register.tsx @@ -5,7 +5,7 @@ import { Button } from "@mui/material"; import { useDispatch } from "react-redux"; import { useNavigate } from "react-router-dom"; import { useState } from "react"; -import { UserRegister } from "../../Components/Api/Api"; +import { UserRegister, VerifyEmail } from "../../Components/Api/Api"; export default function Register() { const navigate = useNavigate(); const dispatch = useDispatch(); @@ -65,18 +65,24 @@ export default function Register() { style={styles.login_button} variant="contained" onClick={async () => { + console.log("Email valid?" + (await VerifyEmail(user.email))); + if (await VerifyEmail(user.email)) { + if (await UserRegister(user)) { + setFeedback( + "Registration success. Please check your email address for activation" + ); + } else { + setFeedback("Invalid credentials specified"); + } + } else { + setFeedback("Email does not exist"); + } + setUser({ email: "", username: "", password: "", }); - if (await UserRegister(user)) { - setFeedback( - "Registration success. Please check your email address for activation" - ); - } else { - setFeedback("Invalid credentials specified"); - } }} > Register From 3e9a8909a7eb06643cae08f9d5605751ca98462b Mon Sep 17 00:00:00 2001 From: keannu125 Date: Mon, 13 Mar 2023 00:37:25 +0800 Subject: [PATCH 09/11] Remove email verification --- src/Components/Api/Api.tsx | 16 ---------------- src/Routes/Register/Register.tsx | 23 ++++++----------------- 2 files changed, 6 insertions(+), 33 deletions(-) diff --git a/src/Components/Api/Api.tsx b/src/Components/Api/Api.tsx index e9e1499..db8d4fb 100644 --- a/src/Components/Api/Api.tsx +++ b/src/Components/Api/Api.tsx @@ -206,19 +206,3 @@ export async function CheckSavedSession() { console.log("No previous session found"); return false; } - -export function VerifyEmail(email: string) { - return axios - .get( - "https://emailvalidation.abstractapi.com/v1/?api_key=d7abfb5f41b7476faaebe37ceba8ae37&email=" + - email - ) - .then((response) => { - console.log("Email valid?" + response.data); - return true; - }) - .catch((error) => { - console.log("Email valid?" + error); - return false; - }); -} diff --git a/src/Routes/Register/Register.tsx b/src/Routes/Register/Register.tsx index 984bcd1..287d69b 100644 --- a/src/Routes/Register/Register.tsx +++ b/src/Routes/Register/Register.tsx @@ -1,14 +1,9 @@ import * as React from "react"; import styles from "../../styles"; -import LoginIcon from "../../Components/Icons/LoginIcon/LoginIcon"; import { Button } from "@mui/material"; -import { useDispatch } from "react-redux"; -import { useNavigate } from "react-router-dom"; import { useState } from "react"; -import { UserRegister, VerifyEmail } from "../../Components/Api/Api"; +import { UserRegister } from "../../Components/Api/Api"; export default function Register() { - const navigate = useNavigate(); - const dispatch = useDispatch(); const [user, setUser] = useState({ email: "", username: "", @@ -65,19 +60,13 @@ export default function Register() { style={styles.login_button} variant="contained" onClick={async () => { - console.log("Email valid?" + (await VerifyEmail(user.email))); - if (await VerifyEmail(user.email)) { - if (await UserRegister(user)) { - setFeedback( - "Registration success. Please check your email address for activation" - ); - } else { - setFeedback("Invalid credentials specified"); - } + if (await UserRegister(user)) { + setFeedback( + "Registration success. Please check your email address for activation" + ); } else { - setFeedback("Email does not exist"); + setFeedback("Invalid credentials specified"); } - setUser({ email: "", username: "", From 6082c572d2fe4c117ff3cc664ce48ec362ddc4ff Mon Sep 17 00:00:00 2001 From: keannu125 Date: Wed, 15 Mar 2023 22:50:32 +0800 Subject: [PATCH 10/11] Polished and removed redundant type interfaces for redux states --- .../SessionStatsWidget/SessionStatsWidget.tsx | 6 ++-- src/Components/Login/Login.tsx | 7 ++-- src/Components/LoginChecker/LoginChecker.tsx | 6 ++-- .../PreviousSessionChecker.tsx | 36 ++++++++++--------- src/Components/Sidebar/Sidebar.tsx | 8 ++--- src/Interfaces/Interfaces.tsx | 30 ---------------- src/Plugins/Redux/Store/Store.tsx | 9 ++++- src/Routes/DailyView/DailyView.tsx | 6 ++-- src/Routes/Dashboard/Dashboard.tsx | 16 ++------- src/Routes/Logs/Logs.tsx | 12 +++---- src/Routes/Product/Product.tsx | 8 ++--- src/Routes/Products/Products.tsx | 7 ++-- src/routes/Inventory/Inventory.tsx | 11 +++--- 13 files changed, 58 insertions(+), 104 deletions(-) diff --git a/src/Components/DashboardPage/SessionStatsWidget/SessionStatsWidget.tsx b/src/Components/DashboardPage/SessionStatsWidget/SessionStatsWidget.tsx index 900d1b5..32bf35c 100644 --- a/src/Components/DashboardPage/SessionStatsWidget/SessionStatsWidget.tsx +++ b/src/Components/DashboardPage/SessionStatsWidget/SessionStatsWidget.tsx @@ -3,16 +3,16 @@ 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"; +import { RootState } from "../../../Plugins/Redux/Store/Store"; export interface props {} export default function SessionStatsWidget() { const session_added = useSelector( - (state: SessionTransactions) => state.session_transactions.added + (state: RootState) => state.session_transactions.added ); const session_removed = useSelector( - (state: SessionTransactions) => state.session_transactions.removed + (state: RootState) => state.session_transactions.removed ); return (
state.logged_in.value); + const logged_in = useSelector((state: RootState) => state.logged_in.value); const logged_in_user = useSelector( - (state: LoggedInUserState) => state.logged_in_user.value + (state: RootState) => state.logged_in_user.value ); const navigate = useNavigate(); if (logged_in) { diff --git a/src/Components/LoginChecker/LoginChecker.tsx b/src/Components/LoginChecker/LoginChecker.tsx index 07d8bed..c273127 100644 --- a/src/Components/LoginChecker/LoginChecker.tsx +++ b/src/Components/LoginChecker/LoginChecker.tsx @@ -2,14 +2,14 @@ import * as React from "react"; import { Navigate } from "react-router-dom"; import { useSelector } from "react-redux"; -import { LoginState, OldSessionState } from "../../Interfaces/Interfaces"; +import { RootState } from "../../Plugins/Redux/Store/Store"; export interface props {} export default function LoginChecker() { - const logged_in = useSelector((state: LoginState) => state.logged_in.value); + const logged_in = useSelector((state: RootState) => state.logged_in.value); const old_session_checked = useSelector( - (state: OldSessionState) => state.old_session_checked.value + (state: RootState) => state.old_session_checked.value ); if (!logged_in && !old_session_checked) { } else if (!logged_in && old_session_checked) { diff --git a/src/Components/PreviousSessionChecker/PreviousSessionChecker.tsx b/src/Components/PreviousSessionChecker/PreviousSessionChecker.tsx index d0945af..1513740 100644 --- a/src/Components/PreviousSessionChecker/PreviousSessionChecker.tsx +++ b/src/Components/PreviousSessionChecker/PreviousSessionChecker.tsx @@ -1,30 +1,32 @@ import * as React from "react"; -import { useEffect } from "react"; +import { useEffect, useCallback } from "react"; import { useDispatch, useSelector } from "react-redux"; 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"; +import { RootState } from "../../Plugins/Redux/Store/Store"; export default function PreviousSessionChecker() { const dispatch = useDispatch(); - const logged_in = useSelector((state: LoginState) => state.logged_in.value); + const logged_in = useSelector((state: RootState) => 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"); + const check = useCallback(async () => { + if (await UserInfo()) { + if (logged_in !== true) { + console.log("Previous session found. Restoring"); + await dispatch(toggle_login()); + await dispatch(SetUser(await UserInfo())); } - await dispatch(set_checked()); + } else { + console.log("No old session found"); + localStorage.removeItem("token"); } - check(); - }, []); + await dispatch(set_checked()); + }, [dispatch, logged_in]); + useEffect(() => { + if (!logged_in) { + check(); + } + }, [check, logged_in]); return
; } diff --git a/src/Components/Sidebar/Sidebar.tsx b/src/Components/Sidebar/Sidebar.tsx index 1da4f53..b6c622e 100644 --- a/src/Components/Sidebar/Sidebar.tsx +++ b/src/Components/Sidebar/Sidebar.tsx @@ -10,15 +10,11 @@ import InventoryIcon from "../Icons/InventoryIcon/InventoryIcon"; import LogsIcon from "../Icons/LogsIcon/LogsIcon"; import LogoutIcon from "../Icons/LogoutIcon/LogoutIcon"; import TodayIcon from "../Icons/TodayIcon/TodayIcon"; +import { RootState } from "../../Plugins/Redux/Store/Store"; -export interface state { - logged_in: { - value: boolean; - }; -} export default function Sidebar() { const navigate = useNavigate(); - const logged_in = useSelector((state: state) => state.logged_in.value); + const logged_in = useSelector((state: RootState) => state.logged_in.value); function LogoutButton() { if (!logged_in) { return
; diff --git a/src/Interfaces/Interfaces.tsx b/src/Interfaces/Interfaces.tsx index a6519c7..5cb725c 100644 --- a/src/Interfaces/Interfaces.tsx +++ b/src/Interfaces/Interfaces.tsx @@ -39,36 +39,6 @@ export interface ProductLog { history_user: string; } -// Redux Interfaces -export interface LoginState { - logged_in: { - value: boolean; - }; -} - -export interface OldSessionState { - old_session_checked: { - value: boolean; - }; -} - -export interface LoggedInUserState { - logged_in_user: { - value: { - email: string; - id: number; - username: string; - }; - }; -} - -export interface SessionTransactions { - session_transactions: { - added: number; - removed: number; - }; -} - // Component Props Interfaces export interface IconProps { diff --git a/src/Plugins/Redux/Store/Store.tsx b/src/Plugins/Redux/Store/Store.tsx index 1a1fdf9..d7d9c0e 100644 --- a/src/Plugins/Redux/Store/Store.tsx +++ b/src/Plugins/Redux/Store/Store.tsx @@ -4,7 +4,7 @@ import LoggedInUserReducer from "../../../Features/Redux/Slices/LoggedInUserSlic import OldSessionReducer from "../../../Features/Redux/Slices/OldSession/OldSessionSlice"; import TransactionsThisSessionReducer from "../../../Features/Redux/Slices/TransactionsThisSessionSlice/TransactionsThisSessionSlice"; -export default configureStore({ +const store = configureStore({ reducer: { logged_in: LoginReducer, logged_in_user: LoggedInUserReducer, @@ -12,3 +12,10 @@ export default configureStore({ session_transactions: TransactionsThisSessionReducer, }, }); + +export default store; + +// Infer the `RootState` and `AppDispatch` types from the store itself +export type RootState = ReturnType; +// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState} +export type AppDispatch = typeof store.dispatch; diff --git a/src/Routes/DailyView/DailyView.tsx b/src/Routes/DailyView/DailyView.tsx index dd2aef1..8f8e23f 100644 --- a/src/Routes/DailyView/DailyView.tsx +++ b/src/Routes/DailyView/DailyView.tsx @@ -8,7 +8,7 @@ import { GetLowestStockedProduct, GetProducts, } from "../../Components/Api/Api"; -import { OldSessionState, Product } from "../../Interfaces/Interfaces"; +import { Product } from "../../Interfaces/Interfaces"; import { useSelector } from "react-redux"; import TodayIcon from "../../Components/Icons/TodayIcon/TodayIcon"; import moment from "moment"; @@ -16,13 +16,13 @@ import GetToday from "../../Components/GetToday/GetToday"; import Moment from "react-moment"; import { useNavigate } from "react-router-dom"; import { - Button, TableBody, TableCell, TableContainer, TableHead, TableRow, } from "@mui/material"; +import { RootState } from "../../Plugins/Redux/Store/Store"; export default function DailyView() { const logs = useQuery("logs", GetLogs, { retry: 0 }); @@ -35,7 +35,7 @@ export default function DailyView() { } ); const old_session_checked = useSelector( - (state: OldSessionState) => state.old_session_checked.value + (state: RootState) => state.old_session_checked.value ); const navigate = useNavigate(); if ( diff --git a/src/Routes/Dashboard/Dashboard.tsx b/src/Routes/Dashboard/Dashboard.tsx index fdf1d57..a9f2117 100644 --- a/src/Routes/Dashboard/Dashboard.tsx +++ b/src/Routes/Dashboard/Dashboard.tsx @@ -1,13 +1,7 @@ -import React, { useState } from "react"; -import TotalProductsIcon from "../../Components/Icons/TotalProductsIcon/TotalProductsIcon"; -import LowStockIcon from "../../Components/Icons/LowStockIcon/LowStockIcon"; -import StatsIcon from "../../Components/Icons/StatsIcon/StatsIcon"; -import LogsIcon from "../../Components/Icons/LogsIcon/LogsIcon"; +import React from "react"; import "../../index.css"; 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 LoginChecker from "../../Components/LoginChecker/LoginChecker"; import { useQuery } from "react-query"; import { @@ -15,17 +9,13 @@ import { GetLowestStockedProduct, GetProducts, } from "../../Components/Api/Api"; -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"; import RecentTransactionsWidget from "../../Components/DashboardPage/RecentTransactionsWidget/RecentTransactionsWidget"; +import { RootState } from "../../Plugins/Redux/Store/Store"; export default function Dashboard() { const logs = useQuery("logs", GetLogs, { retry: 0 }); @@ -38,7 +28,7 @@ export default function Dashboard() { } ); const old_session_checked = useSelector( - (state: OldSessionState) => state.old_session_checked.value + (state: RootState) => state.old_session_checked.value ); if ( logs.isLoading || diff --git a/src/Routes/Logs/Logs.tsx b/src/Routes/Logs/Logs.tsx index 7376047..9b47957 100644 --- a/src/Routes/Logs/Logs.tsx +++ b/src/Routes/Logs/Logs.tsx @@ -10,23 +10,19 @@ import { TableHead, TableRow, } 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, - ProductLogEntry, -} from "../../Interfaces/Interfaces"; +import { GetLogs } from "../../Components/Api/Api"; +import { ProductLog } from "../../Interfaces/Interfaces"; import { useState } from "react"; import { useSelector } from "react-redux"; import GetToday from "../../Components/LogsPage/GetToday/GetToday"; +import { RootState } from "../../Plugins/Redux/Store/Store"; export default function Logs() { const logs = useQuery("logs", GetLogs, { retry: 0 }); const old_session_checked = useSelector( - (state: OldSessionState) => state.old_session_checked.value + (state: RootState) => state.old_session_checked.value ); const [searchTerm, setSearchTerm] = useState(""); const [searchToday, setSearchToday] = useState(""); diff --git a/src/Routes/Product/Product.tsx b/src/Routes/Product/Product.tsx index a45d1dd..0f9f41b 100644 --- a/src/Routes/Product/Product.tsx +++ b/src/Routes/Product/Product.tsx @@ -14,11 +14,9 @@ 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, - ProductHistoryEntry, -} from "../../Interfaces/Interfaces"; +import { ProductHistoryEntry } from "../../Interfaces/Interfaces"; import moment from "moment"; +import { RootState } from "../../Plugins/Redux/Store/Store"; export default function Product() { const navigate = useNavigate(); @@ -41,7 +39,7 @@ export default function Product() { }, }); const old_session_checked = useSelector( - (state: OldSessionState) => state.old_session_checked.value + (state: RootState) => 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 a48a69a..23d1dc5 100644 --- a/src/Routes/Products/Products.tsx +++ b/src/Routes/Products/Products.tsx @@ -1,16 +1,15 @@ -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"; 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 { 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"; +import { RootState } from "../../Plugins/Redux/Store/Store"; export default function Products() { const navigate = useNavigate(); @@ -20,7 +19,7 @@ export default function Products() { error, } = useQuery("products", GetProducts, { retry: 0 }); const old_session_checked = useSelector( - (state: OldSessionState) => state.old_session_checked.value + (state: RootState) => 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 23b0803..a0aaa79 100644 --- a/src/routes/Inventory/Inventory.tsx +++ b/src/routes/Inventory/Inventory.tsx @@ -4,22 +4,19 @@ import InventoryIcon from "../../Components/Icons/InventoryIcon/InventoryIcon"; import { Button, Table, - TableBody, TableCell, TableContainer, TableHead, TableRow, } from "@mui/material"; -import { SampleInventoryData } from "../../Components/SampleData/SampleData"; -import StockRenderer from "../../Components/InventoryPage/StockRenderer/StockRenderer"; import LoginChecker from "../../Components/LoginChecker/LoginChecker"; -import { GetProducts, UpdateProduct } from "../../Components/Api/Api"; -import { useMutation, useQuery, useQueryClient } from "react-query"; +import { GetProducts } from "../../Components/Api/Api"; +import { useQuery } 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"; +import { RootState } from "../../Plugins/Redux/Store/Store"; export default function Inventory() { const { @@ -29,7 +26,7 @@ export default function Inventory() { } = useQuery("products", GetProducts, { retry: 0 }); const navigate = useNavigate(); const old_session_checked = useSelector( - (state: OldSessionState) => state.old_session_checked.value + (state: RootState) => state.old_session_checked.value ); if (isLoading || !old_session_checked) { return ( From 4d65efa169fdbcb6b930d8b524157be23a5454b0 Mon Sep 17 00:00:00 2001 From: keannu125 Date: Wed, 15 Mar 2023 22:55:55 +0800 Subject: [PATCH 11/11] Made daily product log date format easier to read --- src/Routes/Product/Product.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Routes/Product/Product.tsx b/src/Routes/Product/Product.tsx index 0f9f41b..4f183d5 100644 --- a/src/Routes/Product/Product.tsx +++ b/src/Routes/Product/Product.tsx @@ -128,7 +128,7 @@ export default function Product() { style={{ ...styles.text_white, ...styles.text_S }} > {moment(history_entry.history_date).format( - "MM-DD-YYYY hh:mm A" + "MMMM DD, YYYY hh:mm A" )}