{isRequired && isHovered && (
{
+const GenericCardModal = ({ open, card, context, imgUrl }) => {
const classes = useStyles();
const { contextProps, isContextAvailable } = useAppContext(context);
const [snackbar, handleSnackbar, handleCloseSnackbar] = useSnackbar();
@@ -60,7 +60,11 @@ const GenericCardModal = ({ open, card, context }) => {
>
{card?.name}
-
+
<>
{
+ // console.log('STRIPE CHECKOUT MODAL PURCHASES:', purchases);
+ // console.log('STRIPE CHECKOUT MODAL TOTAL:', total);
return (
{
- console.log('CARTSUMMARY QUANTITY:', quantity);
- console.log('CARTSUMMARY GETTOTALCOST:', totalCost);
return (
-
-
- Items:
- {`${quantity}`}
-
-
- Grand Total:
- ${totalCost}
-
+
+
+ Items: {quantity}
+
+
+ Grand Total: ${totalCost}
+
);
};
diff --git a/src/components/other/dataDisplay/CartTotal.jsx b/src/components/other/dataDisplay/CartTotal.jsx
index 32db62d..bbeb691 100644
--- a/src/components/other/dataDisplay/CartTotal.jsx
+++ b/src/components/other/dataDisplay/CartTotal.jsx
@@ -2,8 +2,12 @@ import React from 'react';
import { Typography } from '@mui/material';
const CartTotal = ({ total }) => (
-
- Total: ${total}
+ //
+ // Total: ${total}
+ //
+ // console.log(total),
+
+ {`Total: $${total}`} {/* Ensure this is a string or number */}
);
diff --git a/src/components/other/dataDisplay/TopCardsDisplay.jsx b/src/components/other/dataDisplay/TopCardsDisplay.jsx
index e0aa429..3812892 100644
--- a/src/components/other/dataDisplay/TopCardsDisplay.jsx
+++ b/src/components/other/dataDisplay/TopCardsDisplay.jsx
@@ -51,7 +51,7 @@ const CarouselCard = ({ card }) => {
handleClick()}
context={'Collection'}
ref={cardRef}
/>
@@ -64,7 +64,7 @@ const CarouselCard = ({ card }) => {
{card?.description}
- Price: ${card?.latestPrice?.num ?? 'N/A'}
+ Price: ${card?.latestPrice?.num || card?.price || 0}
{/* Additional statistics */}
@@ -83,8 +83,8 @@ const TopCardsDisplay = () => {
useEffect(() => {
const sortedCards = selectedCollection?.cards
?.map((card) => {
- const latestPrice = card.latestPrice?.num ?? 0;
- const lastSavedPrice = card.lastSavedPrice?.num ?? 0;
+ const latestPrice = card?.latestPrice?.num ?? 0;
+ const lastSavedPrice = card?.lastSavedPrice?.num ?? 0;
if (
latestPrice === 0 ||
@@ -96,8 +96,8 @@ const TopCardsDisplay = () => {
return { ...card, diff: 0 };
}
- console.log('latestPrice', latestPrice);
- console.log('lastSavedPrice', lastSavedPrice);
+ // console.log('latestPrice', latestPrice);
+ // console.log('lastSavedPrice', lastSavedPrice);
return { ...card, diff: Math.abs(latestPrice - lastSavedPrice) };
})
.sort((a, b) => b.diff - a.diff || b.price - a.price)
diff --git a/src/components/grids/collectionGrids/Logger.jsx b/src/components/reusable/Logger.jsx
similarity index 100%
rename from src/components/grids/collectionGrids/Logger.jsx
rename to src/components/reusable/Logger.jsx
diff --git a/src/components/grids/collectionGrids/TablePaginationActions.jsx b/src/components/reusable/TablePaginationActions.jsx
similarity index 97%
rename from src/components/grids/collectionGrids/TablePaginationActions.jsx
rename to src/components/reusable/TablePaginationActions.jsx
index 9477839..5fbc74a 100644
--- a/src/components/grids/collectionGrids/TablePaginationActions.jsx
+++ b/src/components/reusable/TablePaginationActions.jsx
@@ -7,7 +7,7 @@ import FirstPageIcon from '@mui/icons-material/FirstPage';
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
import LastPageIcon from '@mui/icons-material/LastPage';
-import { useMode } from '../../../context/hooks/colormode';
+import { useMode } from '../../context/hooks/colormode';
const TablePaginationActions = (props) => {
const { theme } = useMode();
diff --git a/src/components/reusable/icons/DeckBuilderIcon.jsx b/src/components/reusable/icons/DeckBuilderIcon.jsx
new file mode 100644
index 0000000..9fbf281
--- /dev/null
+++ b/src/components/reusable/icons/DeckBuilderIcon.jsx
@@ -0,0 +1,59 @@
+import * as React from 'react';
+import { SvgIcon } from '@material-ui/core';
+
+export default function DeckBuilderIcon(props) {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/reusable/icons/DeckOfCardsIcon.jsx b/src/components/reusable/icons/DeckOfCardsIcon.jsx
index 32afe04..fcfb4f4 100644
--- a/src/components/reusable/icons/DeckOfCardsIcon.jsx
+++ b/src/components/reusable/icons/DeckOfCardsIcon.jsx
@@ -1,28 +1,20 @@
import React from 'react';
-import { IconButton } from '@mui/material';
-import deckIcon1 from '../../../assets/deckIcon2.png';
+import ReusableIconButton from './ReusableIconButton';
+import deckIcon from '../../../assets/deckIcon2.png';
const DeckOfCardsIcon = () => {
return (
-
-
-
+ console.log('Deck icon clicked')}
+ color={'rgba(0, 0, 0, 0.54)'}
+ // size={48}
+ // width={40}
+ // height={40}
+ // hoverColor="rgba(0, 0, 0, 0.1)"
+ // background-color={'#333'}
+ />
);
};
diff --git a/src/components/reusable/icons/MoneyIcon.jsx b/src/components/reusable/icons/MoneyIcon.jsx
index f7e37c7..b8b6db2 100644
--- a/src/components/reusable/icons/MoneyIcon.jsx
+++ b/src/components/reusable/icons/MoneyIcon.jsx
@@ -8,7 +8,7 @@ const MoneyIcon = () => {
sx={{
width: 48, // Standard navbar icon size, adjust as needed
height: 48, // Standard navbar icon size, adjust as needed
- padding: '8px', // Padding to provide some space around the icon
+ // padding: '8px', // Padding to provide some space around the icon
margin: '0', // Adjust margin as needed based on navbar layout
'&:hover': {
backgroundColor: 'rgba(0, 0, 0, 0.04)', // Slight effect on hover
diff --git a/src/components/reusable/icons/ReusableIconButton.jsx b/src/components/reusable/icons/ReusableIconButton.jsx
new file mode 100644
index 0000000..26fb162
--- /dev/null
+++ b/src/components/reusable/icons/ReusableIconButton.jsx
@@ -0,0 +1,40 @@
+import React from 'react';
+import { IconButton } from '@mui/material';
+
+const ReusableIconButton = ({ icon, altText, onClick, size, hoverColor }) => {
+ const defaultSize = size || 48; // Default size if not provided
+ const defaultHoverColor = hoverColor || 'rgba(0, 0, 0, 0.04)'; // Default hover color
+
+ return (
+
+
+
+ );
+};
+
+export default ReusableIconButton;
diff --git a/src/components/search/DeckSearch.js b/src/components/search/DeckSearch.js
index b024742..2e94b3d 100644
--- a/src/components/search/DeckSearch.js
+++ b/src/components/search/DeckSearch.js
@@ -1,13 +1,5 @@
import React, { useState } from 'react';
-import {
- TextField,
- Button,
- Grid,
- Box,
- Fade,
- useMediaQuery,
- Pagination,
-} from '@mui/material';
+import { Box, Fade } from '@mui/material';
import { useCardStore } from '../../context/CardContext/CardStore';
import SearchForm from '../forms/SearchForm';
import DeckSearchCardGrid from '../grids/searchResultGrids/DeckSearchCardGrid';
diff --git a/src/containers/cartPageContainers/CartContainer.jsx b/src/containers/cartPageContainers/CartContainer.jsx
index f2555bb..0f5a4cf 100644
--- a/src/containers/cartPageContainers/CartContainer.jsx
+++ b/src/containers/cartPageContainers/CartContainer.jsx
@@ -1,24 +1,34 @@
import React from 'react';
-import { Box, Typography } from '@mui/material';
+import { Box, Typography, useTheme } from '@mui/material';
-const CartContainer = ({ children }) => (
-
- {
+ const theme = useTheme();
+
+ return (
+
- Your Cart
-
- {children}
-
-);
+
+ Your Cart
+
+ {children}
+
+ );
+};
export default CartContainer;
diff --git a/src/containers/cartPageContainers/CartContent.js b/src/containers/cartPageContainers/CartContent.js
index c95db93..8bafe9c 100644
--- a/src/containers/cartPageContainers/CartContent.js
+++ b/src/containers/cartPageContainers/CartContent.js
@@ -1,35 +1,36 @@
import React from 'react';
-import { Typography } from '@mui/material';
+import { Typography, useTheme } from '@mui/material';
import { useCartStore } from '../../context/CartContext/CartContext';
import CartContainer from './CartContainer';
import CartItem from '../../components/grids/CartItem';
import CartTotal from '../../components/other/dataDisplay/CartTotal';
+import { useMode } from '../../context';
const CartContent = () => {
+ const { theme } = useMode();
const { cartData, getTotalCost } = useCartStore();
- const page = 'cart';
return (
- {cartData.cart && cartData.cart.length > 0 ? (
- cartData.cart.map((card, index) =>
- card ? (
-
- ) : null
+ {cartData?.cart && cartData?.cart.length > 0 ? (
+ cartData.cart.map(
+ (card, index) =>
+ card && (
+
+ )
)
) : (
-
+
Your cart is empty.
)}
- {cartData.cart && cartData.cart.length > 0 && (
-
+ {cartData?.cart && cartData?.cart.length > 0 && (
+
)}
);
diff --git a/src/containers/cartPageContainers/CartContentContainer.js b/src/containers/cartPageContainers/CartContentContainer.js
deleted file mode 100644
index 5dd3823..0000000
--- a/src/containers/cartPageContainers/CartContentContainer.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react';
-import { Box } from '@mui/system';
-import LoadingIndicator from '../../components/reusable/indicators/LoadingIndicator';
-import CartContent from './CartContent';
-
-const CartContentContainer = ({
- cartData,
- calculateTotalPrice,
- onQuantityChange,
-}) => {
- return (
-
- {cartData.length > 0 ? (
-
- ) : (
-
- )}
-
- );
-};
-
-export default CartContentContainer;
diff --git a/src/containers/cartPageContainers/CustomerFormContainer.js b/src/containers/cartPageContainers/CustomerFormContainer.js
deleted file mode 100644
index 46d79bb..0000000
--- a/src/containers/cartPageContainers/CustomerFormContainer.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react';
-import { Box } from '@mui/system';
-import CustomerForm from '../../components/forms/customerCheckoutForm/CustomerForm';
-
-const CustomerFormContainer = () => {
- return (
-
-
-
- );
-};
-
-export default CustomerFormContainer;
diff --git a/src/containers/collectionPageContainers/CollectionPortfolioChartContainer.jsx b/src/containers/collectionPageContainers/CollectionPortfolioChartContainer.jsx
index c5352d2..9895782 100644
--- a/src/containers/collectionPageContainers/CollectionPortfolioChartContainer.jsx
+++ b/src/containers/collectionPageContainers/CollectionPortfolioChartContainer.jsx
@@ -6,7 +6,7 @@ import UpdateStatusBox2 from '../../components/other/InputComponents/UpdateStatu
import TopCardsDisplay from '../../components/other/dataDisplay/TopCardsDisplay';
import { useChartContext } from '../../context/ChartContext/ChartContext';
import { useCollectionStore } from '../../context/CollectionContext/CollectionContext';
-import { useCombinedContext } from '../../context/CombinedProvider';
+import { useCombinedContext } from '../../context/CombinedContext/CombinedProvider';
import { calculateStatistics } from '../../context/StatisticsContext/helpers';
import CollectionStatisticsSelector from '../../components/other/InputComponents/CollectionStatisticsSelector';
import { useStatisticsStore } from '../../context/StatisticsContext/StatisticsContext';
diff --git a/src/context/AppContext/AppContextProvider.jsx b/src/context/AppContext/AppContextProvider.jsx
index 295d4ff..2bc0772 100644
--- a/src/context/AppContext/AppContextProvider.jsx
+++ b/src/context/AppContext/AppContextProvider.jsx
@@ -24,6 +24,14 @@ export const AppContextProvider = ({ children }) => {
);
};
+export const useAppContext = () => {
+ const context = useContext(AppContext);
+ if (context === undefined) {
+ throw new Error('useAppContext must be used within a AppContextProvider');
+ }
+ return context;
+};
+
// import React, { createContext, useContext, useState } from 'react';
// import { DeckContext } from '../DeckContext/DeckContext';
// import { CartContext } from '../CartContext/CartContext';
diff --git a/src/context/Auth/authContext.js b/src/context/AuthContext/authContext.js
similarity index 55%
rename from src/context/Auth/authContext.js
rename to src/context/AuthContext/authContext.js
index 5a7381d..85b23c0 100644
--- a/src/context/Auth/authContext.js
+++ b/src/context/AuthContext/authContext.js
@@ -1,7 +1,14 @@
-import React, { useState, useEffect, useRef, useCallback } from 'react';
+import React, {
+ useState,
+ useEffect,
+ useRef,
+ useCallback,
+ useContext,
+} from 'react';
import axios from 'axios';
import jwt_decode from 'jwt-decode';
import { useCookies } from 'react-cookie';
+import { debounce } from 'lodash';
const LOGGED_IN_COOKIE = 'loggedIn';
const AUTH_COOKIE = 'authToken';
@@ -38,7 +45,6 @@ const processResponseData = (data, type) => {
// Main AuthContext Provider
export const AuthContext = React.createContext();
-
export default function AuthProvider({ children, serverUrl }) {
const [cookies, setCookie, removeCookie] = useCookies([
LOGGED_IN_COOKIE,
@@ -46,10 +52,20 @@ export default function AuthProvider({ children, serverUrl }) {
USER_COOKIE,
]);
const [isLoading, setIsLoading] = useState(false);
- const [isLoggedIn, setisLoggedIn] = useState(false);
- const [user, setUser] = useState({});
- const [error, setError] = useState(null);
+ const [isLoggedIn, setIsLoggedIn] = useState(false);
+
+ const [user, setUser] = useState({
+ username: '',
+ email: '',
+ id: '',
+ role: '',
+ cart: [],
+ decks: [],
+ collections: [],
+ });
+ const [updatedUser, setUpdatedUser] = useState({});
const [token, setToken] = useState(null);
+ const [error, setError] = useState(null);
const REACT_APP_SERVER = serverUrl || process.env.REACT_APP_SERVER;
@@ -66,7 +82,7 @@ export default function AuthProvider({ children, serverUrl }) {
setCookie(AUTH_COOKIE, token, { path: '/' });
setCookie(USER_COOKIE, user || newUser, { path: '/' });
setCookie(LOGGED_IN_COOKIE, true, { path: '/' });
- setisLoggedIn(true);
+ setIsLoggedIn(true);
setToken(token);
setUser(user || newUser);
}
@@ -106,30 +122,71 @@ export default function AuthProvider({ children, serverUrl }) {
// Logout function
const logout = () => {
removeCookie(AUTH_COOKIE);
- setisLoggedIn(false);
+ setIsLoggedIn(false);
setToken(null);
setUser({});
};
- // // Validate token
- // const validateToken = useCallback(async () => {
- // // Validation logic here
- // }, []);
+ const logoutTimerRef = useRef(null);
+
+ // Function to start the logout timer
+ const startLogoutTimer = () => {
+ // Clear existing timer if any
+ if (logoutTimerRef.current) clearTimeout(logoutTimerRef.current);
+
+ // Set a new timer for 30 minutes (1800000 milliseconds)
+ logoutTimerRef.current = setTimeout(() => {
+ logout(); // Call your logout function
+ }, 1800000);
+ };
+
+ // Debounced function to reset the logout timer on user activity
+ const resetLogoutTimer = useRef(debounce(startLogoutTimer, 500)).current;
+ // Attach debounced event listeners for user activity
+ useEffect(() => {
+ const events = ['mousemove', 'keypress', 'scroll', 'click'];
+ events.forEach((event) => window.addEventListener(event, resetLogoutTimer));
+
+ return () => {
+ clearTimeout(logoutTimerRef.current);
+ events.forEach((event) =>
+ window.removeEventListener(event, resetLogoutTimer)
+ );
+ };
+ }, [resetLogoutTimer]);
+
+ // Attach event listeners for user activity
+ useEffect(() => {
+ startLogoutTimer();
+
+ window.addEventListener('mousemove', resetLogoutTimer);
+ window.addEventListener('keypress', resetLogoutTimer);
+ window.addEventListener('scroll', resetLogoutTimer);
+ window.addEventListener('click', resetLogoutTimer);
+
+ // Cleanup on component unmount
+ return () => {
+ clearTimeout(logoutTimerRef.current);
+ window.removeEventListener('mousemove', resetLogoutTimer);
+ window.removeEventListener('keypress', resetLogoutTimer);
+ window.removeEventListener('scroll', resetLogoutTimer);
+ window.removeEventListener('click', resetLogoutTimer);
+ };
+ }, []);
// Initialization logic to set user and token from cookies
+ // Initialization logic to set user and token from cookies and log login state
useEffect(() => {
const storedToken = cookies[AUTH_COOKIE];
const storedUser = cookies[USER_COOKIE];
-
if (storedToken && storedUser) {
setToken(storedToken);
setUser(storedUser);
- setisLoggedIn(true);
+ setIsLoggedIn(true);
+ } else {
+ setIsLoggedIn(false);
}
-
- // isMounted.current = false;
}, [cookies]);
-
return (
);
}
+
+// // Custom hook to use the AuthContext
+// export const useAuthContext = () => {
+// const context = React.useContext(AuthContext);
+// if (context === undefined) {
+// throw new Error('useAuthContext must be used within a AuthProvider');
+// }
+// return context;
+// };
+export const useAuthContext = () => {
+ const context = useContext(AuthContext);
+
+ if (!context) {
+ throw new Error('useAuth must be used within an AuthProvider');
+ }
+
+ return context;
+};
diff --git a/src/context/CardContext/CardStore.js b/src/context/CardContext/CardStore.js
index c818256..0f31636 100644
--- a/src/context/CardContext/CardStore.js
+++ b/src/context/CardContext/CardStore.js
@@ -1,17 +1,30 @@
import axios from 'axios';
-import { createContext, useContext, useState, useEffect } from 'react';
+import { createContext, useContext, useState, useEffect, useMemo } from 'react';
import { useCookies } from 'react-cookie';
+import { useCombinedContext } from '../CombinedContext/CombinedProvider';
+import { useCollectionStore } from '../CollectionContext/CollectionContext';
+import { useUserContext } from '../UserContext/UserContext';
// Create a context for the cardStore
const CardContext = createContext();
export const CardProvider = ({ children }) => {
+ const { user } = useUserContext();
const [cookies, setCookie] = useCookies(['cart'], ['deckData']);
const initialStore = cookies.store || [];
const [cardsArray, setCardsArray] = useState(initialStore);
+ const { allCollections, setAllCollections } = useCollectionStore();
+ const { listOfMonitoredCards } = useCombinedContext();
const currentCart = cookies.cart || [];
const [currenCartArray, setCurrentCartArray] = useState(currentCart);
const [searchData, setSearchData] = useState([]);
+ const [isCardDataValid, setIsCardDataValid] = useState(false);
+ const [rawSearchData, setRawSearchData] = useState([]);
+ const [organizedSearchData, setOrganizedSearchData] = useState([]);
+ const [slicedSearchData, setSlicedSearchData] = useState([]);
+ const [slicedAndMergedSearchData, setSlicedAndMergedSearchData] = useState(
+ []
+ );
const currentDeckData = cookies.deck || [];
const [savedDeckData, setSavedDeckData] = useState(currentDeckData);
const [deckSearchData, setDeckSearchData] = useState([]);
@@ -37,25 +50,88 @@ export const CardProvider = ({ children }) => {
return false;
} else {
ids.add(card.id);
- // ids.add(card.cardId);
return true;
}
});
+ // Check if the uniqueCards is an array
+ const validCardData = uniqueCards && Array.isArray(uniqueCards);
+
+ // Set the state to the unique cards
+ setIsCardDataValid(validCardData);
+
+ if (validCardData) {
+ const limitedCardsToRender = Array.from(uniqueCards).slice(0, 30);
+ setOrganizedSearchData(limitedCardsToRender);
+
+ if (limitedCardsToRender.length >= 1) {
+ console.log('LIMITED CARDS TO RENDER: ', limitedCardsToRender[0]);
+ setSlicedSearchData(limitedCardsToRender);
+ }
+ }
+
setSearchData(uniqueCards);
setDeckSearchData(uniqueCards);
+ setRawSearchData(uniqueCards);
// Set the cookie to hold the current searchData
setCookie('searchData', uniqueCards, { path: '/' });
setCookie('deckSearchData', uniqueCards, { path: '/' });
+ setCookie('rawSearchData', uniqueCards, { path: '/' });
+ // setCookie('organizedSearchData', limitedCardsToRender, { path: '/' });
} else {
setSearchData([]);
+ setDeckSearchData([]);
+ setRawSearchData([]);
+ setOrganizedSearchData([]);
}
} catch (err) {
console.error(err);
}
};
+ const handlePatch = async () => {
+ let needsUpdate = false;
+
+ for (const collection of allCollections) {
+ for (const card of collection.cards) {
+ if (!card.card_images || !card.card_sets || !card.card_prices) {
+ needsUpdate = true;
+ const response = await axios.patch(
+ `${process.env.REACT_APP_SERVER}/api/cards/ygopro/${card.id}`,
+ { id: card.id, user: user, _id: user._id }
+ );
+ if (response.data && response.data.data) {
+ const updatedCard = response.data.data;
+ const cardIndex = collection.cards.findIndex(
+ (c) => c.id === updatedCard.id
+ );
+ if (cardIndex !== -1) {
+ collection.cards[cardIndex] = updatedCard;
+ }
+ }
+ }
+ }
+ }
+
+ if (needsUpdate) {
+ setAllCollections([...allCollections]);
+ }
+ };
+
+ useEffect(() => {
+ // Check if there's any collection that requires an update
+ const hasMissingData = allCollections.some((collection) =>
+ collection.cards.some(
+ (card) => !card.card_images || !card.card_sets || !card.card_prices
+ )
+ );
+
+ if (hasMissingData) {
+ handlePatch();
+ }
+ }, [allCollections]); // Keep the dependency array, but now it only triggers when necessary
+
const getCardData = (cardId) => {
if (Array.isArray(currenCartArray)) {
return currenCartArray.find((card) => card.id === cardId);
@@ -78,6 +154,23 @@ export const CardProvider = ({ children }) => {
searchData,
deckSearchData,
savedDeckData,
+ randomCardData,
+ currenCartArray,
+ initialStore,
+ cookies,
+ currentCart,
+ currentDeckData,
+ slicedSearchData,
+ rawSearchData,
+ organizedSearchData,
+ isCardDataValid,
+ slicedAndMergedSearchData,
+
+ handlePatch,
+ setSlicedAndMergedSearchData,
+ setOrganizedSearchData,
+ setRawSearchData,
+ setSlicedSearchData,
setSearchData,
setDeckSearchData,
setSavedDeckData,
@@ -99,6 +192,18 @@ export const CardProvider = ({ children }) => {
initialStore,
cookies,
currentCart,
+ currentDeckData,
+ slicedSearchData,
+ rawSearchData,
+ organizedSearchData,
+ isCardDataValid,
+ slicedAndMergedSearchData,
+
+ handlePatch,
+ setSlicedAndMergedSearchData,
+ setOrganizedSearchData,
+ setRawSearchData,
+ setSlicedSearchData,
setSearchData,
setDeckSearchData,
setSavedDeckData,
diff --git a/src/context/CartContext/CartContext.js b/src/context/CartContext/CartContext.js
index 19e5afc..c9dea80 100644
--- a/src/context/CartContext/CartContext.js
+++ b/src/context/CartContext/CartContext.js
@@ -29,16 +29,16 @@ export const CartContext = createContext({
});
export const CartProvider = ({ children }) => {
- const { user } = useUserContext();
+ const { user, setUser } = useUserContext();
+ const userId = user?.id;
+
const [cartData, setCartData] = useState({
_id: '', // Cart id
cart: [], // Cart items
quantity: 0, // Total quantity of items
totalPrice: 0, // Total price of items
});
- const [cookies, setCookie] = useCookies(['user', 'cart']);
-
- const userId = user?.id;
+ const [cookie, setCookie] = useCookies(['user', 'cart']);
const isMounted = useRef(true);
const getCardQuantity = (cardId) => {
@@ -52,12 +52,6 @@ export const CartProvider = ({ children }) => {
});
return { totalItems, quantityOfSameId };
};
- // const getTotalCost = useCallback(() => {
- // return cartData.cart.reduce(
- // (acc, card) => acc + card.card_prices[0].tcgplayer_price * card.quantity,
- // 0
- // );
- // }, [cartData.cart]);
const totalCost = useMemo(
() =>
@@ -109,14 +103,14 @@ export const CartProvider = ({ children }) => {
}
}, [userId, createUserCart]);
- useEffect(() => {
- if (userId && isMounted.current) {
- fetchUserCart().catch(console.error);
- }
- return () => {
- isMounted.current = false;
- };
- }, [userId, fetchUserCart]);
+ // useEffect(() => {
+ // if (userId && isMounted.current) {
+ // fetchUserCart().catch(console.error);
+ // }
+ // return () => {
+ // isMounted.current = false;
+ // };
+ // }, [userId, fetchUserCart]);
const setCartDataAndCookie = (newCartData) => {
if (newCartData && Array.isArray(newCartData.cart)) {
@@ -143,6 +137,7 @@ export const CartProvider = ({ children }) => {
);
const calculatedTotalPrice = getTotalCost();
+ // Check if totalQuantity or calculatedTotalPrice has actually changed
if (
cartData.quantity !== totalQuantity ||
cartData.totalPrice !== calculatedTotalPrice
@@ -154,6 +149,7 @@ export const CartProvider = ({ children }) => {
}));
}
}, [cartData.cart]);
+
// Fetch user cart on mount and userId change
const updateCart = async (cartId, updatedCart) => {
if (!cartId) return;
@@ -207,19 +203,10 @@ export const CartProvider = ({ children }) => {
const updatedCartData = await updateCart(cartData._id, updatedCart);
if (updatedCartData) setCartData(updatedCartData);
};
- // const setCartDataAndCookie = (newCartData) => {
- // if (newCartData && Array.isArray(newCartData.cart)) {
- // setCartData(newCartData);
- // setCookie('cart', newCartData.cart, {
- // path: '/',
- // secure: true,
- // sameSite: 'none',
- // });
- // }
- // };
const value = {
cartData,
+ cart: cartData.cart,
getCardQuantity,
cartCardQuantity: cartData.cart?.reduce(
(acc, card) => acc + card.quantity,
@@ -232,55 +219,17 @@ export const CartProvider = ({ children }) => {
),
totalPrice: cartData.totalPrice,
totalCost,
- addOneToCart: addOneToCart,
- removeOneFromCart: removeOneFromCart,
+ addOneToCart,
+ removeOneFromCart,
deleteFromCart,
getTotalCost,
fetchUserCart,
createUserCart,
};
- // useEffect(() => {
- // if (userId && typeof userId === 'string') {
- // fetchUserCart(userId)
- // .then((data) => {
- // if (isMounted.current && data && data.cart) {
- // setCartData(data); // Assuming data has the same structure as cartData
- // }
- // })
- // .catch((error) => console.log('Error fetching user cart:', error));
- // }
- // return () => {
- // isMounted.current = false;
- // };
- // }, [userId, fetchUserCart]);
-
- // // Update cartData quantity and totalPrice when cart changes
- // useEffect(() => {
- // if (!isMounted.current) return;
-
- // const totalQuantity = cartData.cart.reduce(
- // (total, item) => total + item.quantity,
- // 0
- // );
- // const calculatedTotalPrice = getTotalCost();
-
- // if (
- // cartData.quantity !== totalQuantity ||
- // cartData.totalPrice !== calculatedTotalPrice
- // ) {
- // setCartData((prevState) => ({
- // ...prevState,
- // quantity: totalQuantity,
- // totalPrice: calculatedTotalPrice,
- // }));
- // }
- // }, [cartData.cart, getTotalCost]);
useEffect(() => {
- console.log('CART CONTEXT: ', {
- value,
- });
- }, [value]);
+ console.log('CART CONTEXT: ', value.cartData);
+ }, [addOneToCart, removeOneFromCart, deleteFromCart]);
return {children};
};
diff --git a/src/context/CollectionContext/CollectionContext.jsx b/src/context/CollectionContext/CollectionContext.jsx
index eb393c5..e80f81c 100644
--- a/src/context/CollectionContext/CollectionContext.jsx
+++ b/src/context/CollectionContext/CollectionContext.jsx
@@ -11,21 +11,15 @@ import React, {
} from 'react';
import { useCookies } from 'react-cookie';
import {
- handleCardAddition,
- handleCardRemoval,
- createApiUrl,
- fetchWrapper,
getTotalCost,
initialCollectionState,
getCardPrice,
defaultContextValue,
validateUserIdAndData,
- getUpdatedChartData,
getPriceChange,
- constructPayloadWithDifferences,
- getCurrentChartDataSets,
calculateCollectionValue,
} from './collectionUtility.jsx';
+import { fetchWrapper, createApiUrl } from '../Helpers.jsx';
import {
handleError,
removeDuplicatesFromCollection,
@@ -38,7 +32,10 @@ import {
getFilteredChartData,
filterUniqueDataPoints,
transformPriceHistoryToXY,
- getAllCardPrices,
+ filterNullPriceHistoryForCollection,
+ filterNullPriceHistory,
+ handleCardAddition,
+ handleCardRemoval,
} from './helpers.jsx';
export const CollectionContext = createContext(defaultContextValue);
@@ -117,21 +114,26 @@ export const CollectionProvider = ({ children }) => {
Array.isArray(newData) &&
newData.every((item) => hasOwnProperty(item, 'cards'))
) {
+ const filteredNewData = filterNullPriceHistory(newData);
+
// If newData is an array of objects each containing 'cards', assume it's 'allCollections'
- setAllCollections((prev) => updateCollectionArray(prev, newData));
+ setAllCollections((prev) =>
+ updateCollectionArray(prev, filteredNewData)
+ );
} else if (
newData &&
typeof newData === 'object' &&
hasOwnProperty(newData, 'cards')
) {
// If newData is an object with a 'cards' property, assume it's 'selectedCollection'
- setSelectedCollection(newData);
+ setSelectedCollection(filterNullPriceHistoryForCollection(newData));
} else if (newData && typeof newData === 'object') {
// If newData is a general object, assume it's 'collectionData'
- setCollectionData(newData);
+ setCollectionData(filterNullPriceHistoryForCollection(newData));
} else {
console.warn(
- 'Unable to determine the type of collection data for update.'
+ 'Unable to determine the type of collection data for update.',
+ newData
);
}
} catch (error) {
@@ -313,7 +315,8 @@ export const CollectionProvider = ({ children }) => {
name,
userId: userId, // Make sure 'userId' is defined in the scope
totalPrice: updatedTotalPrice || 0,
- totalCost: updatedTotalPrice ? updatedTotalPrice?.toString() : '0',
+ totalCost: getTotalCost(collectionWithCards),
+ // totalCost: updatedTotalPrice ? updatedTotalPrice?.toString() : '0',
totalQuantity: cards?.reduce(
(acc, card) => acc + (card?.quantity || 0),
0
@@ -338,6 +341,34 @@ export const CollectionProvider = ({ children }) => {
],
};
};
+ const constructCardDifferencesPayload = (
+ oldCollection,
+ newCollection,
+ debug = false
+ ) => {
+ const differences = {};
+
+ newCollection.cards.forEach((newCard) => {
+ const oldCard =
+ oldCollection.cards.find((card) => card.id === newCard.id) || {};
+
+ Object.keys(newCard).forEach((key) => {
+ if (newCard[key] !== oldCard[key]) {
+ if (!differences[newCard.id]) {
+ differences[newCard.id] = { old: {}, new: {} };
+ }
+ differences[newCard.id].old[key] = oldCard[key];
+ differences[newCard.id].new[key] = newCard[key];
+ }
+ });
+ });
+
+ if (debug && Object.keys(differences).length > 0) {
+ console.log('Card Differences:', differences);
+ }
+
+ return differences;
+ };
const getUpdatedCollection = async (
collectionWithCards, // updated cards
@@ -397,7 +428,8 @@ export const CollectionProvider = ({ children }) => {
operation
// collectionId
);
- console.log('CARDS AFTER: ', updatedCards);
+ // console.log('CARDS AFTER: ', updatedCards);
+ // Call the function to get differences in cards
const updatedTotalPrice = calculateCollectionValue(updatedCards);
setTotalPrice(updatedTotalPrice);
@@ -452,6 +484,13 @@ export const CollectionProvider = ({ children }) => {
cardsResponse = await fetchWrapper(endpoint, method, cardsPayload);
const { cardMessage } = cardsResponse;
+ console.log('CARDS AFTER: ', cardsResponse.cards);
+ const cardDifferences = constructCardDifferencesPayload(
+ collectionWithCards,
+ { cards: cardsResponse.cards },
+ true
+ );
+ console.log('CARD DIFFERENCES:', cardDifferences);
const updatedChartData = getFilteredChartData(
collectionWithCards.chartData,
@@ -493,10 +532,19 @@ export const CollectionProvider = ({ children }) => {
cards: cardsResponse.cards,
chartData: chartDataResponse.chartData,
};
-
+ console.log('COLLECTION MESSAGE:', collectionMessage);
console.log('RESTRUCTURED COLLECTION:', restructuredCollection);
+
+ const filteredRestructuredCollection = filterNullPriceHistoryForCollection(
+ restructuredCollection
+ );
+
+ console.log(
+ 'FILTERED RESTRUCTURED COLLECTION:',
+ filteredRestructuredCollection
+ );
return {
- restructuredCollection,
+ filteredRestructuredCollection,
};
};
@@ -569,7 +617,7 @@ export const CollectionProvider = ({ children }) => {
if (updatedCollection) {
console.log('UPDATED COLLECTION:', updatedCollection);
- updateCollectionData(updatedCollection?.restructuredCollection);
+ updateCollectionData(updatedCollection?.filteredRestructuredCollection);
} else {
console.error('Failed to update collection.');
}
@@ -594,6 +642,7 @@ export const CollectionProvider = ({ children }) => {
setUpdatedPricesFromCombinedContext,
setOpenChooseCollectionDialog,
getTotalPrice2: () => getCardPrice(selectedCollection),
+
getTotalPrice: () => calculateCollectionValue(selectedCollection),
getNewTotalPrice: (values) => calculateCollectionValue(values),
getTotalCost: () => getTotalCost(selectedCollection),
@@ -621,7 +670,7 @@ export const CollectionProvider = ({ children }) => {
);
useEffect(() => {
- console.log('CONTEXT STATE:', {
+ console.log('COLLECTION CONTEXT:', {
totalCost,
totalPrice,
totalQuantity: selectedCollection?.totalQuantity || 0,
@@ -631,7 +680,7 @@ export const CollectionProvider = ({ children }) => {
updatedPricesFromCombinedContext,
xyData,
});
- }, [allCollections, selectedCollection, totalCost, totalPrice, xyData]);
+ }, [userId, selectedCollection]);
useEffect(() => {
if (userId) fetchAndSetCollections();
diff --git a/src/context/CollectionContext/collectionUtility.jsx b/src/context/CollectionContext/collectionUtility.jsx
index 75ff649..ed9a205 100644
--- a/src/context/CollectionContext/collectionUtility.jsx
+++ b/src/context/CollectionContext/collectionUtility.jsx
@@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/no-empty-function */
-const BASE_API_URL = `${process.env.REACT_APP_SERVER}/api/users`;
const initialCollectionState = {
userId: '', // Assuming this is an ObjectId string
name: '', // Initialize as empty string if not provided
@@ -147,68 +146,6 @@ const validateData = (data, eventName, functionName) => {
return false;
};
-/**
- * Handles the addition of a new card to the collection.
- * @param {Array} currentCards - Current array of cards.
- * @param {Object} cardToAdd - Card object to add.
- * @returns {Array} Updated array of cards.
- */
-const handleCardAddition = (currentCards, cardToAdd) => {
- // Initialize currentCards to an empty array if it's not defined
- currentCards = currentCards || [];
-
- console.log('CURRENT CARDS:', currentCards);
- console.log('CARD TO ADD:', cardToAdd);
- const cardToAddId =
- typeof cardToAdd.id === 'number' ? String(cardToAdd.id) : cardToAdd.id;
- const matchingCard = currentCards.find((c) => c.id === cardToAddId);
-
- if (matchingCard) {
- matchingCard.quantity++;
- return [...currentCards];
- }
-
- return [...currentCards, { ...cardToAdd, id: cardToAddId, quantity: 1 }];
-};
-
-/**
- * Handles the removal of a card from the collection.
- * @param {Array} currentCards - Current array of cards.
- * @param {Object} cardToRemove - Card object to remove.
- * @returns {Array} Updated array of cards.
- */
-const handleCardRemoval = (currentCards, cardToRemove) => {
- // Initialize currentCards to an empty array if it's not defined
- currentCards = currentCards || [];
-
- console.log('CURRENT CARDS:', currentCards);
- console.log('CARD TO REMOVE:', cardToRemove);
-
- const cardToRemoveId =
- typeof cardToRemove.id === 'number'
- ? String(cardToRemove.id)
- : cardToRemove.id;
-
- // Find the card to remove in the current cards array
- const cardIndex = currentCards.findIndex((c) => c.id === cardToRemoveId);
-
- if (cardIndex === -1) {
- console.error('Card not found in the collection.');
- return [...currentCards];
- }
-
- const matchingCard = currentCards[cardIndex];
-
- // If the card has a quantity greater than 1, decrement it
- if (matchingCard.quantity > 1) {
- matchingCard.quantity--;
- return [...currentCards];
- } else {
- // Remove the card from the collection if quantity is 1 or less
- return currentCards.filter((card) => card.id !== cardToRemoveId);
- }
-};
-
/**
* Filters unique XY values with Y not equal to 0.
* @param {Array} allXYValues - Array of XY value objects.
@@ -245,11 +182,6 @@ const getUniqueFilteredXYValues = (allXYValues) => {
});
};
-// Example usage:
-// console.log(getUniqueFilteredXYValues(null)); // Should return []
-// console.log(getUniqueFilteredXYValues(undefined)); // Should return []
-// console.log(getUniqueFilteredXYValues([{ x: 1, y: 0 }, { x: 2, y: 3 }])); // Should return [{ x: 2, y: 3 }]
-
/**
* Calculates the total price from an array of card prices.
* @param {Array} allCardPrices - Array of card prices.
@@ -283,13 +215,6 @@ const ensureNumber = (value, defaultValue = 0) => {
const findCollectionIndex = (collections, id) =>
collections?.findIndex((collection) => collection?._id === id) ?? -1;
-/**
- * Creates a full API URL from a given path.
- * @param {String} path - API path.
- * @returns {String} Full API URL.
- */
-const createApiUrl = (path) => `${BASE_API_URL}/${path}`;
-
// To prevent making the same type of request within 10 seconds
const lastRequestTime = {
POST: 0,
@@ -345,35 +270,18 @@ const fetchWrapper = async (url, method, body = null) => {
}
};
-const handleApiResponse = async (response) => {
- if (!(response instanceof Response)) {
- const error = new Error(
- "The response object is not an instance of the Fetch API's Response class."
- );
- console.error(error.message, response);
- throw error;
- }
-
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
-
- try {
- const jsonResponse = await response.json();
- return jsonResponse;
- } catch (e) {
- const error = new Error(`Failed to parse JSON from the response: ${e}`);
- console.error(error.message);
- throw error;
- }
-};
-
const getTotalCost = (selectedCollection) => {
if (!selectedCollection || !Array.isArray(selectedCollection.cards)) return 0;
return selectedCollection.cards.reduce((total, card) => {
const cardPrice =
- (card.card_prices && card.card_prices[0]?.tcgplayer_price) || 0;
+ (card.card_prices && card.card_prices[0]?.tcgplayer_price) || card.price;
+
+ if (!cardPrice) {
+ console.error(
+ `Failed to get price for card: ${card.name} (ID: ${card.id})`
+ );
+ }
return total + cardPrice * card.quantity;
}, 0);
};
@@ -906,15 +814,12 @@ module.exports = {
convertData,
isEmpty,
validateData,
- handleCardAddition,
- handleCardRemoval,
+ // handleCardAddition,
+ // handleCardRemoval,
getUniqueFilteredXYValues,
calculateTotalFromAllCardPrices,
ensureNumber,
findCollectionIndex,
- createApiUrl,
- BASE_API_URL,
- handleApiResponse,
fetchWrapper,
getTotalCost,
getCardPrice,
diff --git a/src/context/CollectionContext/helpers.jsx b/src/context/CollectionContext/helpers.jsx
index 4a045a8..ce5a9bb 100644
--- a/src/context/CollectionContext/helpers.jsx
+++ b/src/context/CollectionContext/helpers.jsx
@@ -123,3 +123,133 @@ export const handleError = (condition, errorMessage) => {
}
return true;
};
+
+export const filterNullPriceHistory = (allCollections) => {
+ return allCollections.map((collection) => {
+ const filteredCards = collection.cards.map((card) => {
+ if (card.priceHistory) {
+ // Remove nulls and duplicates with less than 24 hours difference
+ const filteredPriceHistory = card.priceHistory.filter(
+ (price, index, array) => {
+ if (!price) return false; // Filter out null values
+ // Check for duplicates with less than 24 hours difference
+ const nextPrice = array[index + 1];
+ if (nextPrice) {
+ const timeDiff =
+ new Date(nextPrice.timestamp) - new Date(price.timestamp);
+ const lessThan24Hours = timeDiff < 24 * 60 * 60 * 1000; // 24 hours in milliseconds
+ return !(price.num === nextPrice.num && lessThan24Hours);
+ }
+ return true;
+ }
+ );
+
+ return {
+ ...card,
+ priceHistory: filteredPriceHistory,
+ };
+ }
+ return card;
+ });
+
+ return {
+ ...collection,
+ cards: filteredCards,
+ };
+ });
+};
+
+export const filterNullPriceHistoryForCollection = (collection) => {
+ const filteredCards = collection.cards.map((card) => {
+ if (card.priceHistory) {
+ // Remove null values, duplicates with less than 24 hours difference, and entries with num = 0
+ const filteredPriceHistory = card.priceHistory.filter(
+ (price, index, array) => {
+ if (!price || price.num === 0) return false; // Filter out null values and num = 0
+
+ // Check for duplicates with less than 24 hours difference
+ const nextPrice = array[index + 1];
+ if (nextPrice) {
+ const timeDiff =
+ new Date(nextPrice.timestamp) - new Date(price.timestamp);
+ const lessThan24Hours = timeDiff < 24 * 60 * 60 * 1000; // 24 hours in milliseconds
+ return !(price.num === nextPrice.num && lessThan24Hours);
+ }
+ return true;
+ }
+ );
+
+ return {
+ ...card,
+ priceHistory: filteredPriceHistory,
+ };
+ }
+ return card;
+ });
+
+ return {
+ ...collection,
+ cards: filteredCards,
+ };
+};
+/**
+ * Handles the addition of a new card to the collection.
+ * @param {Array} currentCards - Current array of cards.
+ * @param {Object} cardToAdd - Card object to add.
+ * @returns {Array} Updated array of cards.
+ */
+export const handleCardAddition = (currentCards, cardToAdd) => {
+ // Initialize currentCards to an empty array if it's not defined
+ currentCards = currentCards || [];
+
+ console.log('CURRENT CARDS:', currentCards);
+ console.log('CARD TO ADD:', cardToAdd);
+ const cardToAddId =
+ typeof cardToAdd.id === 'number' ? String(cardToAdd.id) : cardToAdd.id;
+ const matchingCard = currentCards.find((c) => c.id === cardToAddId);
+
+ if (matchingCard) {
+ matchingCard.quantity++;
+ return [...currentCards];
+ }
+
+ return [...currentCards, { ...cardToAdd, id: cardToAddId, quantity: 1 }];
+};
+
+/**
+ * Handles the removal of a card from the collection.
+ * @param {Array} currentCards - Current array of cards.
+ * @param {Object} cardToRemove - Card object to remove.
+ * @returns {Array} Updated array of cards.
+ */
+export const handleCardRemoval = (currentCards, cardToRemove) => {
+ // Initialize currentCards to an empty array if it's not defined
+ currentCards = currentCards || [];
+
+ console.log('CURRENT CARDS:', currentCards);
+ console.log('CARD TO REMOVE:', cardToRemove);
+
+ const cardToRemoveId =
+ typeof cardToRemove.id === 'number'
+ ? String(cardToRemove.id)
+ : cardToRemove.id;
+
+ // Find the card to remove in the current cards array
+ const cardIndex = currentCards.findIndex((c) => c.id === cardToRemoveId);
+
+ if (cardIndex === -1) {
+ console.error('Card not found in the collection.');
+ return [...currentCards];
+ }
+
+ const matchingCard = currentCards[cardIndex];
+
+ // If the card has a quantity greater than 1, decrement it
+ if (matchingCard.quantity > 1) {
+ matchingCard.quantity--;
+ return [...currentCards];
+ } else {
+ // Remove the card from the collection if quantity is 1 or less
+ return currentCards.filter((card) => card.id !== cardToRemoveId);
+ }
+};
diff --git a/src/context/ColorModeProvider.jsx b/src/context/ColorModeContext/ColorModeProvider.jsx
similarity index 96%
rename from src/context/ColorModeProvider.jsx
rename to src/context/ColorModeContext/ColorModeProvider.jsx
index 9084db9..0fd24a2 100644
--- a/src/context/ColorModeProvider.jsx
+++ b/src/context/ColorModeContext/ColorModeProvider.jsx
@@ -1,7 +1,7 @@
import { useState, useMemo, createContext, useEffect } from 'react';
import { createTheme } from '@mui/material/styles';
import { useCookies } from 'react-cookie';
-import { themeSettings } from '../assets/themeSettings';
+import { themeSettings } from '../../assets/themeSettings';
export const ColorModeContext = createContext({
mode: 'dark',
diff --git a/src/context/CombinedProvider.jsx b/src/context/CombinedContext/CombinedProvider.jsx
similarity index 89%
rename from src/context/CombinedProvider.jsx
rename to src/context/CombinedContext/CombinedProvider.jsx
index 56fea34..94add7e 100644
--- a/src/context/CombinedProvider.jsx
+++ b/src/context/CombinedContext/CombinedProvider.jsx
@@ -7,9 +7,12 @@ import React, {
useState,
} from 'react';
import { useCookies } from 'react-cookie';
-import { CollectionContext } from './CollectionContext/CollectionContext';
-import { useSocketContext } from './SocketProvider';
-import { validateData } from './Helpers';
+import { CollectionContext } from '../CollectionContext/CollectionContext';
+import { useSocketContext } from '../SocketContext/SocketProvider';
+import {
+ filterNullPriceHistory,
+ filterNullPriceHistoryForCollection,
+} from '../CollectionContext/helpers';
export const CombinedContext = createContext();
const initialState = {
@@ -44,12 +47,12 @@ const initialState = {
export const CombinedProvider = ({ children }) => {
const [cookies] = useCookies(['user']);
- // const { user } = useCookies(['user']);
const [state, setState] = useState(initialState);
const user = cookies.user;
- // console.log('USER ID:', user.id);
+ const userId = user?.id;
const {
selectedCollection,
+ updateCollection,
allCollections,
getNewTotalPrice,
getUpdatedCollection,
@@ -167,6 +170,7 @@ export const CombinedProvider = ({ children }) => {
// If latestPrice is different, update lastSavedPrice and priceHistory
if (updatedCardInfo.latestPrice?.num !== originalCard.latestPrice?.num) {
+ console.log('ORIGINAL PRICE HISTOY', originalCard.priceHistory);
return {
...originalCard,
...updatedCardInfo,
@@ -179,7 +183,10 @@ export const CombinedProvider = ({ children }) => {
new Date().toISOString(),
},
priceHistory: [
+ // Add the previous price to the price history
...originalCard.priceHistory,
+
+ // Add the latest price to the price history
updatedCardInfo?.latestPrice,
],
};
@@ -304,16 +311,25 @@ export const CombinedProvider = ({ children }) => {
cards: updatedSelectedCollectionCards,
};
+ const filteredUpdatedCollection =
+ filterNullPriceHistoryForCollection(updatedCollection);
+
+ console.log('FILTERED UPDATED COLLECTION:', filteredUpdatedCollection);
try {
const updatedCollectionResult = await getUpdatedCollection(
- updatedCollection,
+ filteredUpdatedCollection,
null, // No specific card to update
'update', // Operation type
userId
);
-
+ // for (const card of filteredUpdatedCollection.cards) {
+ // const updatedCollectionResult = await updateCollection(
+ // card,
+ // 'update',
+ // selectedCollection
+ // );
if (updatedCollectionResult) {
- console.log('Updated Collection:', updatedCollectionResult);
+ console.log('UPDATED COLLECTION RESULT:', updatedCollectionResult);
// setDataFunctions.collectionData(updatedCollectionResult);
setDataFunctions.listOfSimulatedCards(updatedCollectionResult);
}
@@ -442,14 +458,31 @@ export const CombinedProvider = ({ children }) => {
) => {
if (!userId)
return console.error('Missing userId or listOfMonitoredCards.');
- if (!listOfMonitoredCards)
+ if (!listOfMonitoredCards || listOfMonitoredCards.length === 0)
return console.error('Missing retrievedListOfMonitoredCards.');
-
+ let attempt2;
+ if (!Array.isArray(listOfMonitoredCards)) {
+ console.warn(
+ 'INITIAL LISTOFMONITOREDCARDSVALUE NOT AN ARRAY, ATTEMPTING TO RETREIVE AND TRY AGAIN',
+ listOfMonitoredCards
+ );
+ attempt2 = generateListOfMonitoredCards(allCollections);
+ console.log('ATTEMPT 2', attempt2);
+
+ if (!attempt2 || attempt2.length === 0) {
+ console.error(
+ 'ATTEMPT 2 FAILED, listOfMonitoredCards IS NOT AN ARRAY'
+ );
+ return;
+ }
+ }
console.log(
'SENDING CHECK AND UPDATE CARD PRICES',
listOfMonitoredCards
);
- const selectedList = listOfMonitoredCards;
+ const selectedList = listOfMonitoredCards
+ ? listOfMonitoredCards
+ : attempt2;
socket?.emit('REQUEST_CRON_UPDATED_CARDS_IN_COLLECTION', {
userId,
data: {
@@ -468,13 +501,14 @@ export const CombinedProvider = ({ children }) => {
if (!listOfMonitoredCards)
return console.log('Missing retrievedListOfMonitoredCards.');
if (!allCollections) return console.log('Missing allCollections.');
+ const filteredAllCollections = filterNullPriceHistory(allCollections);
const selectedList = listOfMonitoredCards;
socket.emit('REQUEST_PRICES_ACTIVATE_CRON', {
userId,
data: {
userId,
selectedList,
- allCollections,
+ allCollections: filteredAllCollections,
cardsWithChangedPrice,
},
});
@@ -507,7 +541,9 @@ export const CombinedProvider = ({ children }) => {
JSON.stringify(allCollections) !==
JSON.stringify(state.allCollectionData)
) {
- setDataFunctions.allCollectionData(allCollections);
+ const filteredAllCollections = filterNullPriceHistory(allCollections);
+ console.log('FILTERED ALL COLLECTIONS:', filteredAllCollections);
+ setDataFunctions.allCollectionData(filteredAllCollections);
}
}
}, [allCollections]);
@@ -550,8 +586,8 @@ export const CombinedProvider = ({ children }) => {
// Log combined context value for debugging
useEffect(() => {
- console.log('COMBINED CONTEXT VALUE:', state);
- }, [state]);
+ console.log('COMBINED CONTEXT:', state);
+ }, [userId, setDataFunctions.allCollectionData]);
return (
diff --git a/src/context/CronJobContext/CronJobContext.jsx b/src/context/CronJobContext/CronJobContext.jsx
index 4c00b02..4a6e49c 100644
--- a/src/context/CronJobContext/CronJobContext.jsx
+++ b/src/context/CronJobContext/CronJobContext.jsx
@@ -1,7 +1,7 @@
import React, { createContext, useContext, useEffect, useState } from 'react';
import { useUserContext } from '../UserContext/UserContext';
import { useCollectionStore } from '../CollectionContext/CollectionContext';
-import { useCombinedContext } from '../CombinedProvider';
+import { useCombinedContext } from '../CombinedContext/CombinedProvider';
const CronJobContext = createContext();
@@ -9,8 +9,8 @@ export const useCronJobContext = () => useContext(CronJobContext);
export const CronJobProvider = ({ children }) => {
const { user } = useUserContext();
- const { allCollections } = useCollectionStore();
- const { handleSendAllCardsInCollections } = useCombinedContext();
+ const { handleSendAllCardsInCollections, listOfMonitoredCards } =
+ useCombinedContext();
const [lastCronJobTriggerTime, setLastCronJobTriggerTime] = useState(
new Date().getTime()
);
@@ -23,20 +23,20 @@ export const CronJobProvider = ({ children }) => {
if (timeDifference >= 60000) {
// 60 seconds
setLastCronJobTriggerTime(currentTime);
- if (user && user.userID) {
+
+ if (user?.id && listOfMonitoredCards?.length > 0) {
console.log('Triggering cron job actions');
- // Call your functions here
- handleSendAllCardsInCollections(user.userID);
+ handleSendAllCardsInCollections(user.id, listOfMonitoredCards);
}
}
};
- const interval = setInterval(handleTriggerCronJob, 1000); // Check every second
+ const interval = setInterval(handleTriggerCronJob, 60000); // Trigger every minute
return () => clearInterval(interval);
}, [
lastCronJobTriggerTime,
user,
- allCollections,
+ listOfMonitoredCards,
handleSendAllCardsInCollections,
]);
diff --git a/src/context/DeckContext/DeckContext.js b/src/context/DeckContext/DeckContext.js
index 7983db8..cde7cc4 100644
--- a/src/context/DeckContext/DeckContext.js
+++ b/src/context/DeckContext/DeckContext.js
@@ -8,11 +8,18 @@ import React, {
} from 'react';
import { useCookies } from 'react-cookie';
import { useCardStore } from '../CardContext/CardStore';
-
+import { fetchWrapper } from '../Helpers.jsx';
+import { BASE_API_URL, createApiUrl } from '../Helpers.jsx';
+import {
+ calculateAndUpdateTotalPrice,
+ removeDuplicateDecks,
+} from './helpers.jsx';
export const DeckContext = createContext({
deckData: {}, // Provide default values for context properties
allDecks: [],
selectedDeck: {},
+ userDecks: [],
+ totalQuantity: () => 0,
setSelectedDeck: () => {},
addOneToDeck: () => {},
removeOneFromDeck: () => {},
@@ -21,24 +28,7 @@ export const DeckContext = createContext({
updateAndSyncDeck: () => {},
fetchAllDecksForUser: () => {},
});
-const apiBase = `${process.env.REACT_APP_SERVER}/api/users`;
-
-const fetchWrapper = async (url, method, body = null) => {
- const options = {
- method,
- headers: { 'Content-Type': 'application/json' },
- ...(body && { body: JSON.stringify(body) }),
- };
- const response = await fetch(url, options);
- if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
- return response.json();
-};
-const removeDuplicateDecks = (decks) => {
- const uniqueDecks = {};
- decks.forEach((deck) => (uniqueDecks[deck._id] = deck));
- return Object.values(uniqueDecks);
-};
export const DeckProvider = ({ children }) => {
const { getCardData } = useCardStore();
const [cookies] = useCookies(['user']);
@@ -47,15 +37,15 @@ export const DeckProvider = ({ children }) => {
const [selectedDeck, setSelectedDeck] = useState({});
const userId = cookies?.user?.id;
- const calculateAndUpdateTotalPrice = (deck) => {
- let totalPrice = 0;
- if (deck && deck.cards) {
- totalPrice = deck.cards.reduce((total, card) => {
- return total + card.price * card.quantity;
- }, 0);
- }
- return totalPrice;
- };
+ // const calculateAndUpdateTotalPrice = (deck) => {
+ // let totalPrice = 0;
+ // if (deck && deck.cards) {
+ // totalPrice = deck.cards.reduce((total, card) => {
+ // return total + card.price * card.quantity;
+ // }, 0);
+ // }
+ // return totalPrice;
+ // };
const fetchDecksForUser = useCallback(async () => {
if (!userId) {
@@ -63,7 +53,7 @@ export const DeckProvider = ({ children }) => {
return null;
}
try {
- const url = `${apiBase}/${userId}/decks`;
+ const url = `${BASE_API_URL}/${userId}/decks`;
return await fetchWrapper(url, 'GET');
} catch (error) {
console.error(`Failed to fetch decks for user: ${error.message}`);
@@ -77,7 +67,7 @@ export const DeckProvider = ({ children }) => {
if (userDecks.data && userDecks.data.length > 0) {
const uniqueDecks = removeDuplicateDecks(userDecks.data);
- console.log('UNIQUE DECKS:', uniqueDecks);
+ // console.log('UNIQUE DECKS:', uniqueDecks);
setAllDecks((prevDecks) =>
removeDuplicateDecks([...prevDecks, ...uniqueDecks])
);
@@ -143,7 +133,7 @@ export const DeckProvider = ({ children }) => {
}
try {
- const url = `${apiBase}/${userId}/decks/${selectedDeck._id}`; // Removed deckId from the URL
+ const url = `${BASE_API_URL}/${userId}/decks/${selectedDeck._id}`; // Removed deckId from the URL
const bodyData = {
...newDeckData,
deckId: newDeckData._id, // Included deckId in the body
@@ -156,7 +146,7 @@ export const DeckProvider = ({ children }) => {
const createUserDeck = async (userId, newDeckInfo) => {
try {
- const url = `${apiBase}/${userId}/decks`;
+ const url = `${BASE_API_URL}/${userId}/decks`;
const cards = Array.isArray(newDeckInfo.cards)
? newDeckInfo.cards.map(formatCardData)
: [];
@@ -226,7 +216,7 @@ export const DeckProvider = ({ children }) => {
});
try {
- const url = `${apiBase}/${userId}/decks/${selectedDeck._id}`;
+ const url = `${BASE_API_URL}/${userId}/decks/${selectedDeck._id}`;
const updatedDeck = await fetchWrapper(url, 'PUT', {
cards: currentCards,
totalPrice: currentTotalPrice,
@@ -271,11 +261,10 @@ export const DeckProvider = ({ children }) => {
useEffect(() => {
console.log('DECKCONTEXT:', contextValue);
- const userId = cookies?.user?.id;
if (userId && typeof userId === 'string') {
fetchAndSetDecks();
}
- }, [cookies?.user?.id, fetchAndSetDecks]);
+ }, [userId, fetchAndSetDecks]);
return (
{children}
diff --git a/src/context/DeckContext/helpers.jsx b/src/context/DeckContext/helpers.jsx
new file mode 100644
index 0000000..35c0d5d
--- /dev/null
+++ b/src/context/DeckContext/helpers.jsx
@@ -0,0 +1,27 @@
+/**
+ * Wraps fetch API calls and implements a rate limit for each HTTP method type.
+ * @param {String} url - The API URL to make the request to.
+ * @param {String} method - The HTTP method for the request.
+ * @param {Object} [body=null] - The request payload if needed.
+ * @returns {Promise
);
};
export default CartPage;
+// return (
+//
+//
+//
+//
+//
+// {hasItems ? (
+//
+// ) : (
+//
+// No items in the cart
+//
+// )}
+//
+// {hasItems && (
+//
+//
+//
+// )}
+//
+//
+//
+//
+// );
+// };
+
+// export default CartPage;
+
+// import React, { useEffect } from 'react';
+// import { useCookies } from 'react-cookie';
+// import {
+// Box,
+// Card as CardElement,
+// CardContent,
+// Container,
+// Grid,
+// } from '@mui/material';
+// import LoadingIndicator from '../components/reusable/indicators/LoadingIndicator';
+// import ErrorIndicator from '../components/reusable/indicators/ErrorIndicator';
+// // import CartContentContainer from '../containers/cartPageContainers/CartContentContainer';
+// import { usePageContext } from '../context/PageContext/PageContext';
+// import { useCartStore, useMode } from '../context';
+// import { styled } from '@mui/styles';
+// import CustomerForm from '../components/forms/customerCheckoutForm/CustomerForm';
+// import CartContent from '../containers/cartPageContainers/CartContent';
+// import { CartBox, CartContainer } from './pageStyles/StyledComponents';
+
+// const CartPage = () => {
+// const [cookies] = useCookies(['user']);
+// const theme = useMode();
+// const user = cookies.user;
+// const userId = user?.id;
+
+// const {
+// cartData,
+// addOneToCart,
+// removeOneFromCart,
+// fetchUserCart,
+// cartCardQuantity,
+// getTotalCost,
+// } = useCartStore();
+
+// const {
+// isPageLoading,
+// setIsPageLoading,
+// pageError,
+// setPageError,
+// logPageData,
+// } = usePageContext();
+
+// // CartBox;
+// useEffect(() => {
+// setIsPageLoading(true); // Start the loading state
+// try {
+// if (!userId) {
+// setIsPageLoading(false); // End the loading state
+// return;
+// }
+
+// // if theres no cartData or cartData object is empty, fetch the user's cart
+// if (!cartData || Object.keys(cartData).length === 0) {
+// // fetchUserCart(userId);
+// setIsPageLoading(false); // End the loading state
+// return;
+// }
+// // Your logic to check cart data
+// if (userId && cartData.cart && cartData.cart.length > 0) {
+// logPageData('CartPage', cartData); // Log the cart data
+// console.log('CART PAGE (CART_QUANTITY):', cartCardQuantity);
+// }
+// } catch (e) {
+// setPageError(e); // Handle any errors
+// } finally {
+// setIsPageLoading(false); // End the loading state
+// }
+// }, [userId, cartData, setPageError]);
+
+// const calculateTotalPrice = getTotalCost;
+// const hasItems = cartData?.cart?.length > 0;
+
+// const handleModifyItemInCart = async (cardId, operation) => {
+// try {
+// if (operation === 'add') {
+// addOneToCart(cardId);
+// } else if (operation === 'remove') {
+// removeOneFromCart(cardId);
+// }
+// } catch (e) {
+// console.error('Failed to adjust quantity in cart:', e);
+// setPageError(e); // Set the error
+// }
+// };
+
+// if (isPageLoading) return ;
+// if (pageError) return ;
+
+// return (
+//
+//
+//
+//
+//
+//
+//
+//
+// {hasItems ? (
+//
+// ) : (
+//
+// )}
+//
+//
+// {hasItems && (
+//
+//
+//
+// )}
+//
+//
+//
+//
+//
+//
+// );
+// };
+
+// export default CartPage;
diff --git a/src/pages/CollectionPage.js b/src/pages/CollectionPage.js
index 08e1908..c949826 100644
--- a/src/pages/CollectionPage.js
+++ b/src/pages/CollectionPage.js
@@ -1,4 +1,4 @@
-import React, { useContext } from 'react';
+import React, { useContext, useEffect, useState } from 'react';
import { useCookies } from 'react-cookie';
import LoadingIndicator from '../components/reusable/indicators/LoadingIndicator';
import ErrorIndicator from '../components/reusable/indicators/ErrorIndicator';
@@ -14,90 +14,66 @@ import {
CollectionContents,
} from './pageStyles/StyledComponents';
import { useMode } from '../context/hooks/colormode';
+import { usePageContext } from '../context/PageContext/PageContext';
+import HeroCenter from './pageStyles/HeroCenter';
-const HeroCenter = ({ decorative, title, subtitle }) => (
-
-
- {decorative}
-
-
- {title}
-
-
- {subtitle}
-
-
-);
-
-// Default props for the HeroCenter component for ease of use and maintainability
-HeroCenter.defaultProps = {
- decorative: 'All-in-One',
- title: "Your Collection's Home",
- subtitle:
- // eslint-disable-next-line max-len
- 'Welcome to your collection! Here you can view all of your cards, add new cards, and remove cards from your collection.',
-};
-
-// Main collection page component
const CollectionPage = () => {
const { theme } = useMode();
- const { allCollections, selectedCollection, loading, error } =
- useCollectionStore();
+ const [isCollectionSelected, setIsCollectionSelected] = useState(false);
+ const { allCollections, selectedCollection } = useCollectionStore();
+ const {
+ isPageLoading,
+ setIsPageLoading,
+ pageError,
+ setPageError,
+ logPageData,
+ } = usePageContext();
+
const { openModalWithCard, closeModal, isModalOpen, modalContent } =
useContext(ModalContext);
- if (loading) return ;
- if (error) return ;
+ useEffect(() => {
+ setIsPageLoading(true);
+ try {
+ // Logic to handle collection data
+ logPageData('CollectionPage', selectedCollection); // Log collection data
+ } catch (e) {
+ setPageError(e); // Handle any errors
+ } finally {
+ setIsPageLoading(false); // End the loading state
+ }
+ }, [selectedCollection, setIsPageLoading, setPageError, logPageData]);
+
+ if (isPageLoading) return ;
+ if (pageError) return ;
+
+ const handleCollectionSelected = (selected) => {
+ console.log('selected', selected);
+ setIsCollectionSelected(!!selected);
+ };
return (
-
-
-
-
-
-
+ {!isCollectionSelected && (
+
+
+
+
+
+
+ )}
+
- {/* */}
-
- {/* */}
+
{isModalOpen && (
(
-
-
- {title}
-
-
- {subtitle}
-
-
-);
-
-HeroCenter2.defaultProps = {
- title: 'Welcome to Deck Builder',
- subtitle: 'Craft, refine, and explore your deck strategies in one place.',
-};
+import { usePageContext } from '../context/PageContext/PageContext';
+import HeroCenter from './pageStyles/HeroCenter';
const DeckBuilderPage = () => {
const [userDecks, setUserDecks] = useState([]);
const { theme } = useMode();
- const { fetchAllDecksForUser, allDecks, loading, error } = useDeckStore();
+ const { fetchAllDecksForUser, allDecks, loading } = useDeckStore();
+ const {
+ isPageLoading,
+ setIsPageLoading,
+ pageError,
+ setPageError,
+ logPageData,
+ } = usePageContext();
const { user } = useUserContext();
const { openModalWithCard, closeModal, isModalOpen, modalContent } =
useContext(ModalContext);
@@ -70,24 +41,62 @@ const DeckBuilderPage = () => {
useEffect(() => {
if (allDecks && userId && typeof userId === 'string') {
const filteredDecks = allDecks?.filter((deck) => deck?.userId === userId);
- console.log('filteredDecks', filteredDecks);
+ // console.log('filteredDecks', filteredDecks);
+ logPageData('DeckBuilderPage', filteredDecks); // Log the cart data
+
+ // console.log('DECK PAGE (FILTERED_DECKS):', filteredDecks);
+
setUserDecks(filteredDecks);
}
- }, [allDecks, userId]);
+ }, [userId]);
- if (loading) return ;
- if (error) return ;
+ // useEffect(() => {
+ // setIsPageLoading(true);
+ // try {
+ // // Logic to handle deck data
+ // if (!userId) {
+ // setIsPageLoading(false); // End the loading state
+ // return;
+ // }
+
+ // // if theres no cartData or cartData object is empty, fetch the user's cart
+ // if (!cartData || Object.keys(cartData).length === 0) {
+ // fetchUserCart(userId);
+ // return;
+ // }
+ // // Your logic to check cart data
+ // if (userId && cartData.cart && cartData.cart.length > 0) {
+ // logPageData('CartPage', cartData); // Log the cart data
+ // console.log('CART PAGE (CART_QUANTITY):', cartCardQuantity);
+ // }
+ // logPageData('DeckBuilderPage', allDecks); // Log deck data
+ // } catch (e) {
+ // setPageError(e);
+ // } finally {
+ // setIsPageLoading(false);
+ // }
+ // }, [allDecks, setIsPageLoading, setPageError, logPageData]);
+
+ if (isPageLoading) return ;
+ if (pageError) return ;
return (
-
+ {/* */}
+
+
+ {pageError && }
+
{isModalOpen && (
{
const HomePage = () => {
// const theme = useTheme();
- const { theme, setMode } = useMode();
+ const { theme } = useMode();
const classes = useStyles(theme);
- const { openModalWithCard, closeModal, isModalOpen, modalContent } =
- useContext(ModalContext);
- const { initialState, carouselImages, tiers } = pages;
+ const { closeModal, isModalOpen, modalContent } = useContext(ModalContext);
+ const { initialState, carouselImages, tiers, introText } = pages;
const getIconForTitle = (title) => {
switch (title) {
case 'Deck Builder':
@@ -99,7 +98,7 @@ const HomePage = () => {
color="text.primary"
gutterBottom
>
- Enhanced Cardstore
+ {introText.mainTitle}
{
color="text.secondary"
paragraph
>
- The purpose of this site is to provide an enhanced user experience
- for competitive and novice card collectors alike. We provide an
- advanced collection tracker and deck builder which allows users to
- build decks and track the prices of the cards they need so they can
- make the best financial decisions when buying and selling cards.
+ {introText.description}
{
+ const navigate = useNavigate();
+
+ // Handler to navigate back to the home page
+ const handleGoHome = () => {
+ navigate('/');
+ };
+
+ return (
+
+
+ 404 - Page Not Found
+
+
+ Sorry, the page you are looking for does not exist.
+
+
+
+ );
+};
+
+export default NotFoundPage;
diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js
index 039ca34..4ebd576 100644
--- a/src/pages/ProfilePage.js
+++ b/src/pages/ProfilePage.js
@@ -17,7 +17,7 @@ import UserStats from '../components/other/dataDisplay/UserStats';
import { useUserContext } from '../context/UserContext/UserContext';
import { useCookies } from 'react-cookie';
import ThemeToggleButton from '../components/buttons/other/ThemeToggleButton';
-import { useCombinedContext } from '../context/CombinedProvider';
+import { useCombinedContext } from '../context/CombinedContext/CombinedProvider';
import {
AvatarStyled,
TypographyStyled,
@@ -44,10 +44,6 @@ const ProfilePage = () => {
handleRequestChartData,
handleRequestCollectionData,
handleRequestCronStop,
- handleSendAllCardsInCollections,
- listOfMonitoredCards,
- handleRetreiveListOfMonitoredCards,
- retrievedListOfMonitoredCards,
} = useCombinedContext();
const openSnackbar = (message) => {
@@ -85,14 +81,6 @@ const ProfilePage = () => {
}
};
- // const handleTriggerCronJob = () => {
- // if (userId && listOfMonitoredCards) {
- // handleSendAllCardsInCollections(userId, listOfMonitoredCards);
- // console.log('SENDING ALL CARDS IN COLLECTIONS');
- // openSnackbar('Triggered the cron job.');
- // }
- // };
-
const handleStopCronJob = () => {
if (userId && typeof userId === 'string') {
handleRequestCronStop(userId);
@@ -158,7 +146,7 @@ const ProfilePage = () => {
diff --git a/src/pages/StorePage.js b/src/pages/StorePage.js
index 0929dc2..025a2c2 100644
--- a/src/pages/StorePage.js
+++ b/src/pages/StorePage.js
@@ -1,119 +1,65 @@
-import React, { useState, useContext, useEffect } from 'react';
-import { Box, Grid, Typography } from '@mui/material';
-import { useCookies } from 'react-cookie';
+import React, { useEffect } from 'react';
+import { Grid } from '@mui/material';
import SearchBar from '../components/search/SearchBar';
import ProductGrid from '../components/grids/storeSearchResultsGrid/ProductGrid';
import { useCardStore } from '../context/CardContext/CardStore';
import { useCartStore } from '../context/CartContext/CartContext';
import LoadingIndicator from '../components/reusable/indicators/LoadingIndicator';
import ErrorIndicator from '../components/reusable/indicators/ErrorIndicator';
-import { StoreBanner, StoreTitle } from './pageStyles/StyledComponents';
-import { themeSettings } from '../assets/themeSettings';
import { useMode } from '../context/hooks/colormode';
import { useUserContext } from '../context/UserContext/UserContext';
-
-const SearchContainer = () => {
- return (
-
-
-
- );
-};
-
-const CardContainer = () => {
- const { theme } = useMode();
-
- return (
-
-
-
- );
-};
-
-const HeroCenter3 = ({ decorative, title, subtitle, theme }) => (
-
-
- {decorative}
-
-
- {title}
-
-
- {subtitle}
-
-
-);
-
-HeroCenter3.defaultProps = {
- title: 'Welcome to Store',
- subtitle: 'Search for cards and add them to your cart.',
-};
+import HeroCenter from './pageStyles/HeroCenter';
+import { usePageContext } from '../context/PageContext/PageContext';
const StorePage = () => {
const { theme } = useMode();
- const { fetchUserCart, loading, error } = useCartStore();
- const { searchData } = useCardStore();
- const { user } = useUserContext();
+ const { fetchUserCart } = useCartStore();
+ const { searchData, slicedSearchData, slicedAndMergedSearchData } =
+ useCardStore();
+ const { user, setUser } = useUserContext();
+ const {
+ isPageLoading,
+ setIsPageLoading,
+ pageError,
+ setPageError,
+ logPageData,
+ } = usePageContext();
+
const userId = user?.id;
+
useEffect(() => {
- if (userId && typeof userId === 'string') {
- fetchUserCart(userId).catch((error) =>
- console.error('Failed to get user cart', error)
- );
- console.log('(STORE PAGE) -- (SEARCHDATA):', searchData);
- }
- }, [userId, fetchUserCart]);
+ const fetchData = async () => {
+ if (!userId) {
+ setIsPageLoading(false);
+ return;
+ }
+
+ setIsPageLoading(true);
+ try {
+ fetchUserCart(userId);
+ if (searchData && slicedAndMergedSearchData) {
+ logPageData('StorePage', slicedAndMergedSearchData);
+ }
+ } catch (error) {
+ console.error('Failed to get user cart', error);
+ setPageError(error);
+ } finally {
+ setIsPageLoading(false);
+ }
+ };
- if (loading) {
- return ;
- }
+ fetchData();
+ }, [logPageData, searchData, setUser]);
- if (error) {
- return ;
- }
+ if (isPageLoading) return ;
+ if (pageError) return ;
return (
-
+
{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
- // maxWidth: '100vw',
padding: theme.spacing(3),
width: '100%',
- // margin: 'auto',
- // padding: theme.spacing(3),
+ height: '100%',
backgroundColor: theme.palette.background.paper,
color: theme.palette.text.primary,
}}
>
-
-
+
+
+ {' '}
+
+
+ {' '}
);
diff --git a/src/pages/index.js b/src/pages/index.js
new file mode 100644
index 0000000..a28ad10
--- /dev/null
+++ b/src/pages/index.js
@@ -0,0 +1,9 @@
+// pages/index.js
+export { default as HomePage } from './HomePage';
+export { default as ProfilePage } from './ProfilePage';
+export { default as DeckBuilderPage } from './DeckBuilderPage';
+export { default as CollectionPage } from './CollectionPage';
+export { default as NotFoundPage } from './NotFoundPage';
+export { default as CartPage } from './CartPage';
+export { default as SplashPage } from './SplashPage';
+export { default as StorePage } from './StorePage';
diff --git a/src/pages/pageStyles/CarouselImage.jsx b/src/pages/pageStyles/CarouselImage.jsx
new file mode 100644
index 0000000..e69de29
diff --git a/src/pages/pageStyles/HeroCenter.jsx b/src/pages/pageStyles/HeroCenter.jsx
new file mode 100644
index 0000000..a886ea3
--- /dev/null
+++ b/src/pages/pageStyles/HeroCenter.jsx
@@ -0,0 +1,60 @@
+import React from 'react';
+import { Box, Typography } from '@mui/material';
+
+const HeroCenter = ({ decorative, title, subtitle, theme }) => (
+
+ {decorative && (
+
+ {decorative}
+
+ )}
+
+ {title}
+
+
+ {subtitle}
+
+
+);
+
+HeroCenter.defaultProps = {
+ decorative: '',
+ title: '',
+ subtitle: '',
+ theme: null,
+};
+
+export default HeroCenter;
diff --git a/src/pages/pageStyles/StyledComponents.jsx b/src/pages/pageStyles/StyledComponents.jsx
index dc8bb21..04aa606 100644
--- a/src/pages/pageStyles/StyledComponents.jsx
+++ b/src/pages/pageStyles/StyledComponents.jsx
@@ -1,4 +1,11 @@
-import { Avatar, Box, Button, IconButton, Typography } from '@mui/material';
+import {
+ Avatar,
+ Box,
+ Button,
+ Container,
+ IconButton,
+ Typography,
+} from '@mui/material';
import { styled } from '@mui/styles';
// export const AppContainer = styled.div`
@@ -14,6 +21,7 @@ const StyledContainer = styled('div')(({ theme }) => ({
alignItems: 'center',
justifyContent: 'center',
marginLeft: theme.spacing(2),
+ borderRadius: theme.shape.borderRadiusLarge,
marginRight: theme.spacing(2),
// minHeight: '250vh',
flexGrow: 1,
@@ -27,7 +35,27 @@ const StyledContainer = styled('div')(({ theme }) => ({
export const CollectionContainer = ({ children }) => {
return {children};
};
+const StyledContainer2 = styled('div')(({ theme }) => ({
+ display: 'flex',
+ flexDirection: 'column',
+ alignSelf: 'start',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginLeft: theme.spacing(2),
+ borderRadius: theme.shape.borderRadiusLarge,
+ marginRight: theme.spacing(2),
+ // minHeight: '250vh',
+ flexGrow: 1,
+ // minHeight: '100%',
+ background: '#333',
+ // backgroundColor: '#f1f1f1',
+ padding: theme.spacing(4),
+ width: '100%',
+}));
+export const CollectionContainer2 = ({ children }) => {
+ return {children};
+};
export const MainContainer = styled('div')(({ theme }) => ({
background: '#222', // Dark background
padding: theme.spacing(2),
@@ -140,6 +168,7 @@ export const DeckBuilderBanner = styled(Box)(({ theme }) => ({
maxWidth: '1600px',
margin: 'auto',
padding: theme.spacing(6, 2),
+ height: '100%',
boxShadow: theme.shadows[4],
textAlign: 'center',
}));
@@ -209,6 +238,35 @@ export const DeckBuilderTitle = styled(Typography)(({ theme }) => ({
marginBottom: theme.spacing(2.5),
}));
+export const CartContainer = styled(Container)(({ theme }) => ({
+ overflow: 'auto',
+ display: 'flex',
+ flexDirection: 'row',
+ margin: 'auto',
+ flexWrap: 'wrap', // Ensure wrapping on smaller screens
+ // overflowY: 'auto', // Enable vertical scrolling
+ // overflowX: 'hidden', // Prevent horizontal scrolling
+ // maxHeight: '400px',
+ backgroundColor: theme.palette.background.main,
+ padding: theme.spacing(3),
+ borderRadius: theme.shape.borderRadius,
+ boxShadow: theme.shadows[5],
+ width: '100%',
+}));
+
+export const CartBox = styled(Box)(({ theme }) => ({
+ overflow: 'auto',
+ display: 'flex',
+ flexDirection: 'row',
+ flexWrap: 'wrap', // Ensure wrapping on smaller screens
+ backgroundColor: theme.palette.background.secondary,
+ padding: theme.spacing(3),
+ borderRadius: theme.shape.borderRadius,
+ boxShadow: theme.shadows[5],
+ height: '100%',
+ width: '100%',
+}));
+
export const CollectionTitle = styled(Typography)(({ theme }) => ({
color: '#333',
fontSize: '1.5rem',
@@ -219,12 +277,18 @@ export const CollectionTitle = styled(Typography)(({ theme }) => ({
export const CollectionBanner = styled(Box)(({ theme }) => ({
display: 'flex',
justifyContent: 'center',
- margin: '0 auto',
+ // margin: '0 auto',
flexDirection: 'column',
alignItems: 'center',
- padding: theme.spacing(2.5),
+ // padding: theme.spacing(2.5),
+ padding: theme.spacing(6, 2),
// height: '100%',
width: '100%',
+ // height: '100%',
+ maxWidth: '1600px',
+ margin: 'auto',
+ boxShadow: theme.shadows[4],
+ textAlign: 'center',
backgroundColor: theme.palette.background.paper,
// backgroundColor: '#f7f7f7',
}));
diff --git a/src/pages/pages.json b/src/pages/pages.json
index ed27827..522be24 100644
--- a/src/pages/pages.json
+++ b/src/pages/pages.json
@@ -1,4 +1,8 @@
{
+ "introText": {
+ "mainTitle": "Enhanced Cardstore",
+ "description": "The purpose of this site is to provide an enhanced user experience for competitive and novice card collectors alike. We provide an advanced collection tracker and deck builder which allows users to build decks and track the prices of the cards they need so they can make the best financial decisions when buying and selling cards."
+ },
"carouselImages": [
{ "image": "/images/yugioh.jpeg", "caption": "Yu-Gi-Oh!" },
{ "image": "/images/pokemon.jpeg", "caption": "Pokemon" },
@@ -16,7 +20,8 @@
"Deck performance analytics",
"Community deck sharing and rating"
],
- "buttonText": "Get Started",
+ "buttonText": "View Details",
+ "buttonText2": "Get Started",
"buttonVariant": "outlined"
},
{
@@ -28,7 +33,8 @@
"Real-time market price tracking",
"Exclusive member discounts"
],
- "buttonText": "Shop now",
+ "buttonText": "View Details",
+ "buttonText2": "Shop now",
"buttonVariant": "contained"
},
{
@@ -39,7 +45,8 @@
"Automatic collection organization",
"Trade and wishlist creation tools"
],
- "buttonText": "Track Collection",
+ "buttonText": "View Details",
+ "buttonText2": "Track Collection",
"buttonVariant": "outlined"
}
]