From a053a567d2f87af1f47458e97a2a38ca8e729ceb Mon Sep 17 00:00:00 2001 From: Reed Vogt Date: Thu, 7 Dec 2023 19:43:18 -0800 Subject: [PATCH] feat: Enhance UI and functionality in deck and product components - Implemented advanced styling for SelectDeckList component, including modern button styling, improved typography, and icon enhancements. - Added responsive pagination to the ProductGrid component using Material-UIs Pagination component. - Updated the CartProvider to fix an infinite loop issue and optimized context value updates. - Refactored and enhanced the updateExistingCardInUserCollection function to ensure synchronization with CardInCollection model and users collection data. - Cleaned and optimized various React components for better performance and readability. --- src/App.js | 2 +- .../actionButtons/CardActionButtons.jsx | 2 +- src/components/cards/CarouselCard.jsx | 187 +++ src/components/cards/GenericCard.jsx | 7 +- src/components/chart/ChartTooltip.jsx | 3 - src/components/chart/LinearChart.js | 5 +- src/components/chart/PortfolioChart.jsx | 52 +- src/components/collection/CardPortfolio.jsx | 27 +- .../collection/PortfolioContent.jsx | 8 - .../collection/SelectCollection.jsx | 136 +- .../dialogs/CreateOrEditCollectionDialog.jsx | 3 - src/components/forms/AddCardForm.jsx | 39 - src/components/forms/ProfileForm.jsx | 1 - .../grids/collectionGrids/CardList.jsx | 36 +- .../collectionGrids/SelectCollectionList.jsx | 104 +- .../{ => deckBuilderGrids}/DeckDisplay.js | 10 +- .../grids/deckBuilderGrids/SelectDeckList.jsx | 37 + src/components/grids/gridStyles.jsx | 77 +- .../storeSearchResultsGrid/ProductGrid.js | 110 +- .../other/dataDisplay/CartTotal.jsx | 4 - .../other/dataDisplay/TopCardsDisplay.jsx | 211 +-- src/components/reusable/LongMenu.jsx | 8 +- src/components/search/SearchBar.js | 11 +- .../DeckBuilderContainer.js | 2 +- src/context/AuthContext/authContext.js | 48 +- src/context/AuthContext/helpers.jsx | 34 + src/context/CardContext/CardStore.js | 73 +- src/context/CartContext/CartContext.js | 131 +- src/context/ChartContext/ChartContext.jsx | 19 +- .../ChartContext/helpers.jsx} | 45 +- .../CollectionContext/CardUpdateEffect.jsx | 50 - .../CollectionContext/CollectionContext.jsx | 1231 ++++++----------- .../CollectionContext/collectionUtility.jsx | 508 ------- src/context/CollectionContext/helpers.jsx | 496 ++++++- .../ColorModeContext/ColorModeProvider.jsx | 1 - .../CombinedContext/CombinedProvider.jsx | 30 +- src/context/CombinedContext/helpers.jsx | 7 +- src/context/StatisticsContext/helpers.jsx | 3 +- src/pages/CartPage.js | 231 +--- src/pages/CollectionPage.js | 104 -- src/pages/DeckBuilderPage.js | 40 +- src/pages/StorePage.js | 44 +- src/pages/index.js | 4 +- src/pages/{ => otherPages}/LoginPage.jsx | 0 src/pages/{ => otherPages}/NotFoundPage.js | 0 45 files changed, 1521 insertions(+), 2660 deletions(-) create mode 100644 src/components/cards/CarouselCard.jsx delete mode 100644 src/components/forms/AddCardForm.jsx rename src/components/grids/{ => deckBuilderGrids}/DeckDisplay.js (89%) create mode 100644 src/components/grids/deckBuilderGrids/SelectDeckList.jsx create mode 100644 src/context/AuthContext/helpers.jsx rename src/{components/reusable/chartUtils.jsx => context/ChartContext/helpers.jsx} (74%) delete mode 100644 src/context/CollectionContext/CardUpdateEffect.jsx delete mode 100644 src/context/CollectionContext/collectionUtility.jsx rename src/pages/{ => otherPages}/LoginPage.jsx (100%) rename src/pages/{ => otherPages}/NotFoundPage.js (100%) diff --git a/src/App.js b/src/App.js index 4f5b067..6868565 100644 --- a/src/App.js +++ b/src/App.js @@ -100,7 +100,7 @@ const App = () => { .catch((error) => console.error('Error fetching data:', error)) .finally(() => setIsPageLoading(false)); } - }, [userId, fetchAllCollectionsForUser, fetchAllDecksForUser, fetchUserCart]); + }, [userId, fetchAllCollectionsForUser, fetchAllDecksForUser]); useEffect(() => { // Check if loading takes more than 45 seconds diff --git a/src/components/buttons/actionButtons/CardActionButtons.jsx b/src/components/buttons/actionButtons/CardActionButtons.jsx index 30395ed..9e5aa84 100644 --- a/src/components/buttons/actionButtons/CardActionButtons.jsx +++ b/src/components/buttons/actionButtons/CardActionButtons.jsx @@ -142,7 +142,7 @@ const CardActionButtons = ({ switch (context) { case 'Collection': if (action === 'add') { - addOneToCollection(card); + addOneToCollection(card, selectedCollection); } else if (action === 'removeOne') { removeOneFromCollection(card); } diff --git a/src/components/cards/CarouselCard.jsx b/src/components/cards/CarouselCard.jsx new file mode 100644 index 0000000..5e4fe53 --- /dev/null +++ b/src/components/cards/CarouselCard.jsx @@ -0,0 +1,187 @@ +import React, { useContext, useEffect, useRef, useState } from 'react'; +import SwipeableViews from 'react-swipeable-views'; +import { + Box, + Button, + Container, + Grid, + MobileStepper, + Typography, +} from '@mui/material'; +import { KeyboardArrowLeft, KeyboardArrowRight } from '@mui/icons-material'; +import { useCollectionStore } from '../../context/CollectionContext/CollectionContext'; +import { useMode } from '../../context/hooks/colormode'; +import { makeStyles, styled } from '@mui/styles'; +import { ModalContext } from '../../context/ModalContext/ModalContext'; +import GenericCard from './GenericCard'; +import { + MainContainer2, + MainContainer, +} from '../../pages/pageStyles/StyledComponents'; +import { AspectRatio } from '@mui/joy'; +import { debounce } from 'lodash'; +import CardDetailsContainer from '../../containers/CardDetailsContainer'; +const useStyles = makeStyles((theme) => ({ + cardDetails: { + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + }, +})); + +const CarouselCard = ({ card }) => { + const { theme } = useMode(); + const classes = useStyles(); + const { openModalWithCard } = useContext(ModalContext); // Assuming ModalContext is imported + const cardRef = useRef(null); + const chartRef = useRef(null); + const [chartDimensions, setChartDimensions] = useState({ + width: 0, + height: 0, + }); + const HEIGHT_TO_WIDTH_RATIO = 1; // Define the ratio here + + const handleClick = () => { + openModalWithCard(card); + }; + + useEffect(() => { + const handleResize = debounce(() => { + if (chartRef.current) { + const width = chartRef.current.offsetWidth; + const height = width * HEIGHT_TO_WIDTH_RATIO; + setChartDimensions({ width, height }); + } + }, 100); + + window.addEventListener('resize', handleResize); + handleResize(); + + return () => { + window.removeEventListener('resize', handleResize); + handleResize.cancel(); + }; + }, []); + return ( + + + + handleClick()} + context={'Collection'} + ref={cardRef} + /> + + {/* Top section for card details */} + + + + + + {card?.name} + + {/* */} + {/* + Price: ${card?.latestPrice?.num || card?.price || 0} + + + Quantity: {card?.quantity} + */} + + + {/* */} + + Price: ${card?.latestPrice?.num || card?.price || 0} + + + Quantity: {card?.quantity} + + + + + {/* Bottom section for chart */} + + + + + {/* Chart component goes here */} + + + + + + + + + ); +}; + +export default CarouselCard; diff --git a/src/components/cards/GenericCard.jsx b/src/components/cards/GenericCard.jsx index 33c149f..ca7cf2c 100644 --- a/src/components/cards/GenericCard.jsx +++ b/src/components/cards/GenericCard.jsx @@ -77,7 +77,12 @@ const GenericCard = React.forwardRef((props, ref) => { const name = card?.name; const imgUrl = card?.card_images?.[0]?.image_url || placeholderImage; - const price = `Price: ${card?.card_prices?.[0]?.tcgplayer_price || 'N/A'}`; + const price = `Price: ${ + card?.latestPrice?.num || + card?.price || + card?.card_prices?.[0]?.tcgplayer_price || + 'N/A' + }`; const quantity = card?.quantity || 0; let cartQuantity = 0; diff --git a/src/components/chart/ChartTooltip.jsx b/src/components/chart/ChartTooltip.jsx index f9717a9..72064de 100644 --- a/src/components/chart/ChartTooltip.jsx +++ b/src/components/chart/ChartTooltip.jsx @@ -9,10 +9,7 @@ const useStyles = makeStyles((theme) => ({ const ChartTooltip = ({ point, lastData, hoveredData, latestData }) => { const classes = useStyles(); - if (!point) return null; - - // Formatting the date just once to be used in multiple places const formattedTime = hoveredData ? new Date(hoveredData.x).toLocaleString() : new Date((latestData || lastData).x).toLocaleString(); diff --git a/src/components/chart/LinearChart.js b/src/components/chart/LinearChart.js index f8618af..d25b306 100644 --- a/src/components/chart/LinearChart.js +++ b/src/components/chart/LinearChart.js @@ -153,16 +153,15 @@ const LinearChart = ({ tickPadding: 10, tickSize: 10, }, - pointSize: 8, + pointSize: 10, pointBorderWidth: 2, + pointBorderColor: theme.palette.primary.main, pointColor: theme.palette.success.light, colors: theme.palette.primaryDark.main, lineWidth: 3, curve: 'monotoneX', useMesh: true, theme: theme.chart, - // onMouseMove: (point) => setIsZoomed(point ? true : false), - // onMouseLeave: () => setIsZoomed(false), onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave, onClick: () => setIsZoomed(!isZoomed), diff --git a/src/components/chart/PortfolioChart.jsx b/src/components/chart/PortfolioChart.jsx index fd68170..66037a4 100644 --- a/src/components/chart/PortfolioChart.jsx +++ b/src/components/chart/PortfolioChart.jsx @@ -4,13 +4,8 @@ import LinearChart from './LinearChart'; import { useChartContext } from '../../context/ChartContext/ChartContext'; import ErrorBoundary from '../../context/ErrorBoundary'; import { useCollectionStore } from '../../context/CollectionContext/CollectionContext'; -import { useCombinedContext } from '../../context/CombinedContext/CombinedProvider'; import debounce from 'lodash/debounce'; -import { - convertDataForNivo2, - getUniqueValidData, - groupAndAverageData, -} from '../reusable/chartUtils'; +import { getFilteredData2 } from '../../context/CollectionContext/helpers'; const ChartPaper = styled(Paper)(({ theme }) => ({ borderRadius: theme.shape.borderRadius, @@ -28,6 +23,17 @@ const ChartPaper = styled(Paper)(({ theme }) => ({ margin: theme.spacing(2, 0), })); +const ResponsiveSquare = styled(Box)(({ theme }) => ({ + width: '100%', + paddingTop: '100%', + backgroundColor: theme.palette.background.paper, + borderRadius: theme.shape.borderRadius, + boxShadow: theme.shadows[5], + display: 'flex', + alignItems: 'center', + justifyContent: 'center', +})); + function handleThresholdUpdate(lastUpdateTime, setLastUpdateTime) { const currentTime = new Date().getTime(); if (!lastUpdateTime || currentTime - lastUpdateTime >= 600000) { @@ -37,16 +43,20 @@ function handleThresholdUpdate(lastUpdateTime, setLastUpdateTime) { } return lastUpdateTime; } -const getFilteredData2 = (collection, timeRange) => { - if (!collection) { - console.error('Invalid input: selectedCollection should not be null'); - return []; - } - return getUniqueValidData(collection?.chartData?.allXYValues || []); -}; + const PortfolioChart = () => { const theme = useTheme(); - const { latestData, setLatestData, timeRange } = useChartContext(); + const { + latestData, + setLatestData, + timeRange, + groupAndAverageData, + convertDataForNivo2, + // getUniqueValidData, + getTickValues, + getFilteredData, + formatDateToString, + } = useChartContext(); const [lastUpdateTime, setLastUpdateTime] = useState(null); const chartContainerRef = useRef(null); const [chartDimensions, setChartDimensions] = useState({ @@ -61,10 +71,22 @@ const PortfolioChart = () => { ); const filteredChartData2 = useMemo( - () => getFilteredData2(selectedCollection, timeRange), // Adjust to filter data based on timeRange + () => getFilteredData2(selectedCollection, timeRange), [selectedCollection, timeRange] ); + if (filteredChartData2?.length < 5) { + return ( + + + +
Not enough data points
+
+
+
+ ); + } + if (!filteredChartData2 || filteredChartData2?.length === 0) { console.warn( 'Invalid input: filteredChartData2 should not be null or empty' diff --git a/src/components/collection/CardPortfolio.jsx b/src/components/collection/CardPortfolio.jsx index a084272..bf8bf11 100644 --- a/src/components/collection/CardPortfolio.jsx +++ b/src/components/collection/CardPortfolio.jsx @@ -17,21 +17,9 @@ const CardPortfolio = ({ allCollections, onCollectionSelect }) => { const [newCardPrice, setNewCardPrice] = useState(''); const [newCardCondition, setNewCardCondition] = useState(''); const [selectedCards, setSelectedCards] = useState([]); - // Define a ref to keep track of whether handleSelectCollection has been run const hasRun = useRef(false); - const { - // allCollections, - selectedCollection, - setSelectedCollection, - // fetchAllCollectionsForUser, - addOneToCollection, - removeOneFromCollection, - } = useCollectionStore(); - - // useEffect(() => { - // fetchAllCollectionsForUser(); - // }, []); - + const { selectedCollection, setSelectedCollection, removeOneFromCollection } = + useCollectionStore(); useEffect(() => { setSelectedCards(selectedCollection?.cards?.slice(0, 30)); }, [selectedCollection]); @@ -49,36 +37,26 @@ const CardPortfolio = ({ allCollections, onCollectionSelect }) => { return; } setSelectedCollection(foundCollection); - if (selectedCollection) { setSelectedCards(selectedCollection?.cards?.slice(0, 60)); } - if (selectedCards) { setShowCollections(false); setShowPortfolio(true); } - hasRun.current = true; // Set the ref to true after the function has been run }; return ( { {showCollections ? ( diff --git a/src/components/collection/PortfolioContent.jsx b/src/components/collection/PortfolioContent.jsx index db78f12..d810939 100644 --- a/src/components/collection/PortfolioContent.jsx +++ b/src/components/collection/PortfolioContent.jsx @@ -14,8 +14,6 @@ const PortfolioContent = ({ selectedCards, removeCard }) => { const [collectionName, setCollectionName] = useState( selectedCollection?.name ); - - // Update collectionName when selectedCollection changes useEffect(() => { if (selectedCollection?.name) { setCollectionName(selectedCollection.name); @@ -32,8 +30,6 @@ const PortfolioContent = ({ selectedCards, removeCard }) => { maxWidth: '100vw', width: '100%', height: '100%', - // height: '200vh', - // margin: 'auto', margin: { xs: 0, sm: 'auto', @@ -60,8 +56,6 @@ const PortfolioContent = ({ selectedCards, removeCard }) => { flexDirection: 'column', margin: 'auto', width: '100%', - // height: '100%', - // height: '200vh', padding: { xs: theme.spacing(1), sm: theme.spacing(1), @@ -83,9 +77,7 @@ const PortfolioContent = ({ selectedCards, removeCard }) => { spacing={3} sx={{ width: '100%', - // height: '100%', maxWidth: '100vw', - // minHeight: '100%', justifyContent: 'center', margin: 'auto', }} diff --git a/src/components/collection/SelectCollection.jsx b/src/components/collection/SelectCollection.jsx index a6570cc..d18f220 100644 --- a/src/components/collection/SelectCollection.jsx +++ b/src/components/collection/SelectCollection.jsx @@ -8,107 +8,39 @@ import CreateOrEditCollectionDialog from '../dialogs/CreateOrEditCollectionDialo import { useCollectionStore } from '../../context/CollectionContext/CollectionContext'; import { useMode } from '../../context/hooks/colormode'; -// const useStyles = makeStyles((theme) => ({ -// root: { -// display: 'flex', -// flexDirection: 'column', -// justifyContent: 'space-between', -// margin: 'auto', -// padding: theme.spacing(4), -// alignItems: 'stretch', -// height: '80vh', -// width: '100%', -// backgroundColor: theme.palette.background.paper, -// borderRadius: theme.shape.borderRadius, -// // width: '50vw', -// }, -// button: { -// marginBottom: theme.spacing(2), -// margin: theme.spacing(2), -// padding: theme.spacing(2), -// }, -// list: { -// flexGrow: 1, -// overflowY: 'auto', -// overflowX: 'hidden', -// padding: theme.spacing(2), -// borderRadius: theme.shape.borderRadius, -// backgroundColor: theme.palette.success.evenLighter, -// boxShadow: theme.shadows[3], -// width: '100%', -// }, -// middleContainer: { -// display: 'flex', -// flexDirection: 'column', -// justifyContent: 'center', -// // marginTop: theme.spacing(1), -// // alignSelf: 'start', -// justifySelf: 'center', -// alignItems: 'center', -// gap: theme.spacing(2), -// padding: theme.spacing(4), -// borderRadius: theme.shape.borderRadius, -// backgroundColor: theme.palette.background.quinternary, -// boxShadow: theme.shadows[3], -// width: '100%', -// height: '100%', -// // margin: 0, -// // marginLeft: theme.spacing(2), -// // marginRight: theme.spacing(2), -// // height: '100%', -// }, -// })); - const SelectCollection = ({ handleSelectCollection, - handleCollectionSelect, setShowCollections, setShowPortfolio, }) => { const { theme } = useMode(); - // const toolbarRef = useRef(null); - // const [toolbarHeight, setToolbarHeight] = useState('50px'); // Default height - - // const classes = useStyles(theme); const [isDialogOpen, setDialogOpen] = useState(false); const [isNew, setIsNew] = useState(false); const { setSelectedCollection, selectedCollection } = useCollectionStore(); const [editedName, setEditedName] = useState(''); const [editedDescription, setEditedDescription] = useState(''); const isXSmallScreen = useMediaQuery(theme.breakpoints.down('xs')); - - // const isMediumScreen = useMediaQuery(theme.breakpoints.up('md')); - // const isLargeScreen = useMediaQuery(theme.breakpoints.up('lg')); - // const isXSmallScreen = useMediaQuery(theme.breakpoints.down('xs')); - // const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm')); - - // const isSmallCard = useMediaQuery(theme.breakpoints.down('sm')); - // const isMediumCard = useMediaQuery(theme.breakpoints.between('sm', 'md')); - // const isMediumLargeCard = useMediaQuery( - // theme.breakpoints.between('md', 'lg') - // ); - const openDialog = useCallback( - (isNewCollection) => { - setDialogOpen(true); - setIsNew(isNewCollection); - - if (isNewCollection) { - setEditedName(''); - setEditedDescription(''); - } else if (selectedCollection) { - setEditedName(selectedCollection.name); - setEditedDescription(selectedCollection.description); - } - }, - [selectedCollection] + const isSmallCard = useMediaQuery(theme.breakpoints.down('sm')); + const isMediumCard = useMediaQuery(theme.breakpoints.between('sm', 'md')); + const isMediumLargeCard = useMediaQuery( + theme.breakpoints.between('md', 'lg') ); + const buttonSize = isSmallCard ? 'small' : isMediumCard ? 'medium' : 'large'; + const buttonStyle = { + padding: buttonSize === 'small' ? theme.spacing(1) : theme.spacing(2), + fontSize: buttonSize === 'small' ? 'small' : 'default', + color: theme.palette.info.main, + }; + const handleOpenCollectionModal = useCallback(() => { - openDialog(true); - }, [openDialog]); + setDialogOpen(true); + setIsNew(true); + setEditedName(''); + setEditedDescription(''); + }, []); const closeDialog = useCallback(() => setDialogOpen(false), []); - const handleSave = useCallback( (collection) => { setSelectedCollection(collection); @@ -116,7 +48,7 @@ const SelectCollection = ({ setShowPortfolio(true); closeDialog(); }, - [setSelectedCollection, closeDialog] + [setSelectedCollection, setShowCollections, setShowPortfolio, closeDialog] ); useEffect(() => { @@ -126,21 +58,18 @@ const SelectCollection = ({ } }, [selectedCollection]); - const isSmallCard = useMediaQuery(theme.breakpoints.down('sm')); - const isMediumCard = useMediaQuery(theme.breakpoints.between('sm', 'md')); - const isMediumLargeCard = useMediaQuery( - theme.breakpoints.between('md', 'lg') + const openDialog = useCallback( + (isNewCollection) => { + setDialogOpen(true); + setIsNew(isNewCollection); + if (!isNewCollection && selectedCollection) { + setEditedName(selectedCollection.name); + setEditedDescription(selectedCollection.description); + } + }, + [selectedCollection] ); - const buttonSize = isSmallCard ? 'small' : isMediumCard ? 'medium' : 'large'; - const buttonStyle = { - padding: buttonSize === 'small' ? theme.spacing(1) : theme.spacing(2), - fontSize: buttonSize === 'small' ? 'small' : 'default', - // background: theme.palette.info.main, - color: theme.palette.info.main, - // Add other style adjustments as needed - }; - const MiddleContainer = styled(Box)(({ theme }) => ({ display: 'flex', flexDirection: 'column', @@ -170,7 +99,6 @@ const SelectCollection = ({ height: '100%', padding: isXSmallScreen ? theme.spacing(2) : theme.spacing(4), // Adjust padding })); - const ListContainer = styled('div')(({ theme }) => ({ flexGrow: 1, overflowY: 'auto', @@ -182,10 +110,9 @@ const SelectCollection = ({ height: '100%', padding: theme.spacing(isXSmallScreen ? 1 : 2), })); + return ( - // - {/* */} @@ -209,9 +136,7 @@ const SelectCollection = ({ onClick={handleOpenCollectionModal} sx={{ ...buttonStyle, - // Add other style adjustments as needed }} - // color={theme.palette.info.main} > - {/*
*/} openDialog(false)} // Indicate that this is not a new collection isXSmallScreen={isXSmallScreen} // Pass this prop to adjust styles inside the list /> - {/*
*/} - {/*
*/} - {/*
*/} ); }; diff --git a/src/components/dialogs/CreateOrEditCollectionDialog.jsx b/src/components/dialogs/CreateOrEditCollectionDialog.jsx index 1740e0b..baacd0b 100644 --- a/src/components/dialogs/CreateOrEditCollectionDialog.jsx +++ b/src/components/dialogs/CreateOrEditCollectionDialog.jsx @@ -15,7 +15,6 @@ const CreateOrEditCollectionDialog = ({ closeDialog, onSave, isNew, - // userId, editedName, setEditedName, editedDescription, @@ -23,7 +22,6 @@ const CreateOrEditCollectionDialog = ({ }) => { const { createUserCollection, - addOneToCollection, removeCollection, selectedCollection, updateCollectionDetails, @@ -48,7 +46,6 @@ const CreateOrEditCollectionDialog = ({ userId ); } else if (editedName && editedDescription) { - // addOneToCollection(newCollectionInfo); updateCollectionDetails( newCollectionInfo, userId, diff --git a/src/components/forms/AddCardForm.jsx b/src/components/forms/AddCardForm.jsx deleted file mode 100644 index 0f47efb..0000000 --- a/src/components/forms/AddCardForm.jsx +++ /dev/null @@ -1,39 +0,0 @@ -// import React from 'react'; -// import { Box, Input, Button } from '@mui/material'; - -// const AddCardForm = ({ -// newCard, -// setNewCard, -// newCardPrice, -// setNewCardPrice, -// newCardCondition, -// setNewCardCondition, // New prop for card condition -// addCard, -// }) => { -// return ( -// -// setNewCard(e.target.value)} -// /> -// setNewCardPrice(e.target.value)} -// mt={2} -// /> -// setNewCardCondition(e.target.value)} // New state setter function -// mt={2} -// /> -// -// -// ); -// }; - -// export default AddCardForm; diff --git a/src/components/forms/ProfileForm.jsx b/src/components/forms/ProfileForm.jsx index e071132..3684bf0 100644 --- a/src/components/forms/ProfileForm.jsx +++ b/src/components/forms/ProfileForm.jsx @@ -64,7 +64,6 @@ const ProfileForm = ({ userName, name, age, status, onSave }) => { fullWidth margin="normal" /> - {/* Add more TextField components as needed */} diff --git a/src/components/grids/collectionGrids/CardList.jsx b/src/components/grids/collectionGrids/CardList.jsx index 825a604..9713fe5 100644 --- a/src/components/grids/collectionGrids/CardList.jsx +++ b/src/components/grids/collectionGrids/CardList.jsx @@ -22,7 +22,7 @@ import AssessmentIcon from '@mui/icons-material/Assessment'; import TablePaginationActions from '../../reusable/TablePaginationActions'; import PropTypes from 'prop-types'; import { useCollectionStore } from '../../../context/CollectionContext/CollectionContext'; -import { makeStyles, styled } from '@mui/styles'; +import { styled } from '@mui/styles'; import { useMode } from '../../../context/hooks/colormode'; import Logger from '../../reusable/Logger'; // Instantiate logger outside of the component @@ -47,26 +47,16 @@ const StyledContainer = styled(Container)(({ theme }) => ({ borderRadius: 4, })); -// const Paper = styled(MuiPaper)(({ theme }) => ({ -// padding: theme.spacing(2), -// borderRadius: 2, -// width: '100%', -// color: '#fff', -// background: theme.palette.background.main, -// })); - const StyledButtonGroup = styled(ButtonGroup)(({ theme }) => ({ display: 'flex', width: '100%', borderRadius: '5px', overflow: 'hidden', - flexDirection: 'column', justifyContent: 'space-between', alignItems: 'center', boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', })); - const StyledTableHeader = styled(TableHead)(({ theme }) => ({ backgroundColor: '#555', // Darker shade for header color: '#fff', @@ -74,23 +64,19 @@ const StyledTableHeader = styled(TableHead)(({ theme }) => ({ const StyledTableCell = styled(TableCell)(({ theme }) => ({ color: '#ddd', // Lighter text for better readability })); -const Title = styled(TableCell)(({ theme }) => ({ - color: '#4cceac', // Green color for the title -})); -const CardList = ({ selectedCards }) => { +const CardList = () => { const { theme } = useMode(); const { - getTotalCost, selectedCollection, getTotalPrice, - totalCost, - // totalPrice, removeOneFromCollection, addOneToCollection, } = useCollectionStore(); const [page, setPage] = useState(0); const [rowsPerPage, setRowsPerPage] = useState(5); + const selectedCards = selectedCollection?.cards; + console.log('SELCTED', selectedCards); const chartContainerRef = useRef(null); const count = selectedCards?.length || 0; const [chartDimensions, setChartDimensions] = useState({ @@ -98,7 +84,6 @@ const CardList = ({ selectedCards }) => { height: 0, }); const emptyRows = useMemo(() => { - // <-- Use useMemo for better performance return page > 0 ? Math.max(0, (1 + page) * rowsPerPage - (selectedCards?.length || 0)) : 0; @@ -116,14 +101,12 @@ const CardList = ({ selectedCards }) => { }; const handleRemoveCard = (card) => { - // removeOneFromCollection(card, card.id); - removeOneFromCollection(card); + removeOneFromCollection(card, selectedCollection); cardLogger.logCardAction('Remove Card', card); }; const handleAddCard = (card) => { - // addOneToCollection(card, card.id); - addOneToCollection(card); + addOneToCollection(card, selectedCollection); cardLogger.logCardAction('Add Card', card); }; @@ -152,7 +135,6 @@ const CardList = ({ selectedCards }) => { > { {card.card_prices && card.card_prices[0] && card.card_prices[0].tcgplayer_price - ? `$${card.card_prices[0].tcgplayer_price}` + ? `$${ + card?.latestPrice?.num || + card?.price || + card.card_prices[0].tcgplayer_price + }` : 'Price not available'} diff --git a/src/components/grids/collectionGrids/SelectCollectionList.jsx b/src/components/grids/collectionGrids/SelectCollectionList.jsx index b94a198..3d2a51d 100644 --- a/src/components/grids/collectionGrids/SelectCollectionList.jsx +++ b/src/components/grids/collectionGrids/SelectCollectionList.jsx @@ -1,4 +1,4 @@ -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { List, ListItem, @@ -20,6 +20,7 @@ import { useMode } from '../../../context/hooks/colormode'; import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward'; import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; import LongMenu from '../../reusable/LongMenu'; +import { roundToNearestTenth } from '../../../context/ChartContext/helpers'; const useStyles = makeStyles((theme) => ({ listItemText: { flex: 1, @@ -93,52 +94,13 @@ const useStyles = makeStyles((theme) => ({ const SelectCollectionList = ({ onSave, openDialog, - collectionIdFromDialog, - handleCollectionSelect, + handleSelectCollection, }) => { - const { theme } = useMode(); - const theme2 = useTheme(); const classes = useStyles(); - const { - setSelectedCollection, - selectedCollection, - allCollections, - setAllCollections, - } = useCollectionStore(); - const { stats, statsByCollectionId } = useStatisticsStore(); + const { allCollections, setSelectedCollection, fetchAllCollectionsForUser } = + useCollectionStore(); + const { stats } = useStatisticsStore(); const [isLoading, setIsLoading] = useState(false); - const maxCollectionsToShow = 7; // Define the maximum number of collections to display - const placeholdersCount = maxCollectionsToShow - allCollections.length; - const placeholders = Array.from( - { length: placeholdersCount }, - (_, index) => ({ - _id: `placeholder-${index}`, - name: 'Empty Slot', - // Other properties set to default or placeholder values - }) - ); - const combinedCollections = [...allCollections, ...placeholders]; - const handleEdit = (collection) => { - handleOpenDialog(collection); - // Logic for editing the collection - console.log('Edit Collection:', collection); - }; - - const handleStats = (collection) => { - // Logic for showing stats - console.log('Collection Stats:', collection); - }; - - const handleView = (collection) => { - // Logic for quick viewing - console.log('Quick View:', collection); - }; - // console.log('STATS:', stats); - // console.log('STATS BY COLLECTION ID:', statsByCollectionId); - function roundToNearestTenth(num) { - return Math.round(num * 10) / 10; - } - // console.log('TWENTY FOUR HOUR CHANGE:', twentyFourHourChange); const handleSelect = useCallback( (selectedId) => { const selected = allCollections.find( @@ -149,20 +111,8 @@ const SelectCollectionList = ({ return; } setSelectedCollection(selected); - // handleCollectionSelect(selected); - handleCollectionSelect(true); + // handleSelectCollection(selected?._id); onSave(selected); - const selectedIndex = allCollections.findIndex( - (collection) => collection?._id === selectedId - ); - if (selectedIndex > 0) { - const reorderedCollections = [ - selected, - ...allCollections.slice(0, selectedIndex), - ...allCollections.slice(selectedIndex + 1), - ]; - setAllCollections(reorderedCollections); - } }, [allCollections, onSave, setSelectedCollection] ); @@ -170,7 +120,6 @@ const SelectCollectionList = ({ const handleOpenDialog = useCallback( (collection) => { setSelectedCollection(collection); - console.log('SELECTED COLLECTION IN LIST:', collection); openDialog(true); }, [openDialog, setSelectedCollection] @@ -183,24 +132,13 @@ const SelectCollectionList = ({ ) : ( - - {combinedCollections.map((collection, index) => { - const isPlaceholder = index >= allCollections.length; - { - /* const collectionStats = statsByCollectionId[collection?._id]; */ - } - const twentyFourHourChange = stats?.twentyFourHourAverage; - { - /* const allStats = stats; */ - } - { - /* console.log('ALL STATS:', allStats); */ - } + + {allCollections?.map((collection, index) => { + const twentyFourHourChange = stats?.twentyFourHourAverage; // Adjust according to your actual data structure + const isPlaceholder = index >= allCollections?.length; return ( - - {/* {getStatsForAllCollections(collection)} */} - + Value: - {/* Replace with actual value */} ${roundToNearestTenth(collection?.totalPrice)} @@ -252,7 +189,6 @@ const SelectCollectionList = ({ Cards: - {/* Replace with actual count */} {collection?.totalQuantity} @@ -260,19 +196,12 @@ const SelectCollectionList = ({ {!isPlaceholder && (
handleEdit(collection)} - onStats={() => handleStats(collection)} - onView={() => handleView(collection)} + onEdit={() => handleOpenDialog(collection)} + onStats={() => console.log('Stats:', collection)} + onView={() => console.log('View:', collection)} />
)} - {/* */} - {/* )} */}
@@ -287,8 +216,7 @@ const SelectCollectionList = ({ SelectCollectionList.propTypes = { onSave: PropTypes.func.isRequired, openDialog: PropTypes.func.isRequired, - collectionIdFromDialog: PropTypes.string, - handleCollectionSelect: PropTypes.func.isRequired, + handleSelectCollection: PropTypes.func.isRequired, }; export default SelectCollectionList; diff --git a/src/components/grids/DeckDisplay.js b/src/components/grids/deckBuilderGrids/DeckDisplay.js similarity index 89% rename from src/components/grids/DeckDisplay.js rename to src/components/grids/deckBuilderGrids/DeckDisplay.js index ebafdd4..18979e7 100644 --- a/src/components/grids/DeckDisplay.js +++ b/src/components/grids/deckBuilderGrids/DeckDisplay.js @@ -1,10 +1,10 @@ import React, { useContext, useEffect, useState } from 'react'; import { Paper, Button, Typography, Box } from '@mui/material'; -import { DeckContext } from '../../context/DeckContext/DeckContext'; -import DeckButtonList from './deckBuilderGrids/DeckButtonList'; -import CardsGrid from './deckBuilderGrids/CardsGrid'; -import DeckEditPanel from '../other/InputComponents/DeckEditPanel'; -import { useMode } from '../../context/hooks/colormode'; +import { DeckContext } from '../../../context/DeckContext/DeckContext'; +import DeckButtonList from './DeckButtonList'; +import CardsGrid from './CardsGrid'; +import DeckEditPanel from '../../other/InputComponents/DeckEditPanel'; +import { useMode } from '../../../context/hooks/colormode'; const DeckDisplay = ({ userDecks = [] }) => { const { theme } = useMode(); diff --git a/src/components/grids/deckBuilderGrids/SelectDeckList.jsx b/src/components/grids/deckBuilderGrids/SelectDeckList.jsx new file mode 100644 index 0000000..7e0f49b --- /dev/null +++ b/src/components/grids/deckBuilderGrids/SelectDeckList.jsx @@ -0,0 +1,37 @@ +import React, { useContext } from 'react'; +import { Grid, Button, Typography } from '@mui/material'; +import RadioButtonUncheckedIcon from '@mui/icons-material/RadioButtonUnchecked'; +import { DeckContext } from '../../../context/DeckContext/DeckContext'; +import { useDeckButtonListStyles } from '../gridStyles'; + +const SelectDeckList = ({ userDecks, handleSelectDeck }) => { + const classes = useDeckButtonListStyles(); + const { selectedDeck } = useContext(DeckContext); + // console.log('SELECTED DECK:', selectedDeck.name); + // console.log('userDecks', userDecks); + console.log('userDecks', userDecks); + console.log('selectedDeck', selectedDeck); + return ( + + {userDecks?.map((deck) => ( + + + + ))} + + ); +}; + +export default SelectDeckList; diff --git a/src/components/grids/gridStyles.jsx b/src/components/grids/gridStyles.jsx index 4c04821..e20c14d 100644 --- a/src/components/grids/gridStyles.jsx +++ b/src/components/grids/gridStyles.jsx @@ -79,33 +79,33 @@ export const useDeckButtonListStyles = makeStyles((theme) => ({ grid: { marginBottom: theme?.spacing(2), }, - deckButton: { - width: '100%', - padding: '6px 0', - borderRadius: '5px', - transition: '0.3s', - '&:hover': { - backgroundColor: 'rgba(0, 0, 0, 0.04)', - }, - margin: theme?.spacing(1), - [theme?.breakpoints?.down('xs')]: { - fontSize: '0.7rem', - padding: '5px 8px', - }, - [theme?.breakpoints?.up('sm')]: { - fontSize: '0.8rem', - }, - [theme?.breakpoints?.up('md')]: { - fontSize: '1rem', - }, - }, - icon: { - fontSize: '16px', - }, - text: { - fontSize: '12px', - fontWeight: '600', - }, + // deckButton: { + // width: '100%', + // padding: '6px 0', + // borderRadius: '5px', + // transition: '0.3s', + // '&:hover': { + // backgroundColor: 'rgba(0, 0, 0, 0.04)', + // }, + // margin: theme?.spacing(1), + // [theme?.breakpoints?.down('xs')]: { + // fontSize: '0.7rem', + // padding: '5px 8px', + // }, + // [theme?.breakpoints?.up('sm')]: { + // fontSize: '0.8rem', + // }, + // [theme?.breakpoints?.up('md')]: { + // fontSize: '1rem', + // }, + // }, + // icon: { + // fontSize: '16px', + // }, + // text: { + // fontSize: '12px', + // fontWeight: '600', + // }, root: { [theme?.breakpoints?.up('md')]: { backgroundColor: 'blue', @@ -117,4 +117,27 @@ export const useDeckButtonListStyles = makeStyles((theme) => ({ backgroundColor: 'green', }, }, + deckButton: { + padding: theme.spacing(1), + border: '1px solid', + borderColor: theme.palette.primary.main, + background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)', + boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)', + '&:hover': { + backgroundColor: theme.palette.primary.dark, + borderColor: theme.palette.primary.light, + }, + '&.selected': { + borderColor: theme.palette.secondary.main, + boxShadow: '0 3px 5px 2px rgba(0, 200, 200, .3)', + }, + }, + icon: { + color: theme.palette.secondary.main, + marginRight: theme.spacing(1), + }, + text: { + color: theme.palette.common.white, + fontWeight: 'bold', + }, })); diff --git a/src/components/grids/storeSearchResultsGrid/ProductGrid.js b/src/components/grids/storeSearchResultsGrid/ProductGrid.js index 56abf6f..8d92053 100644 --- a/src/components/grids/storeSearchResultsGrid/ProductGrid.js +++ b/src/components/grids/storeSearchResultsGrid/ProductGrid.js @@ -1,11 +1,15 @@ -import React, { useEffect, useMemo } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { Grid } from '@mui/material'; import GenericCard from '../../cards/GenericCard'; import { useCardStore } from '../../../context/CardContext/CardStore'; import StoreItem from '../StoreItem'; import { useCartStore } from '../../../context/CartContext/CartContext'; +import CustomPagination from '../../reusable/CustomPagination'; +import { Box } from '@mui/system'; +import { useMode } from '../../../context'; const ProductGrid = () => { + const { theme } = useMode(); const { searchData, setSlicedAndMergedSearchData, @@ -14,14 +18,21 @@ const ProductGrid = () => { isCardDataValid, } = useCardStore(); const { cart } = useCartStore(); + const [page, setPage] = useState(1); + const [currentStoreSearchData, setCurrentStoreSearchData] = useState(); - if (!isCardDataValid) return null; + const handlePagination = (event, value) => setPage(value); + + const itemsPerPage = 12; + const start = (page - 1) * itemsPerPage; + const end = start + itemsPerPage; + // const currentStoreSearchData = searchData?.slice(start, end); const mergedData = useMemo(() => { + if (!isCardDataValid || !searchData) return null; + return slicedSearchData.map((card) => { - // Convert card ID from string to number for accurate comparison const cardId = parseInt(card.id, 10); - // Find the cart item with a matching ID const cartItem = cart.find( (cartCard) => parseInt(cartCard.id, 10) === cardId ); @@ -33,46 +44,63 @@ const ProductGrid = () => { }, [slicedSearchData, cart]); useEffect(() => { + if (!mergedData) return; setSlicedAndMergedSearchData(mergedData); + setCurrentStoreSearchData(slicedAndMergedSearchData?.slice(start, end)); }, [mergedData, setSlicedAndMergedSearchData]); + return ( - - {isCardDataValid && - slicedAndMergedSearchData.map((card, index) => ( - theme.spacing(2), - height: 'auto', // Set a specific value if required - width: '100%', - }} - > - {/* */} - handleAddToCart(cardId)} - // onQuantityChange={(cardId, operation) => - // handleModifyItemInCart(cardId, operation) - // } - /> - - ))} - + <> + + {isCardDataValid && + slicedAndMergedSearchData.map((card, index) => ( + theme.spacing(2), + height: 'auto', // Set a specific value if required + width: '100%', + }} + > + {/* */} + handleAddToCart(cardId)} + // onQuantityChange={(cardId, operation) => + // handleModifyItemInCart(cardId, operation) + // } + /> + + ))} + + + + + ); }; diff --git a/src/components/other/dataDisplay/CartTotal.jsx b/src/components/other/dataDisplay/CartTotal.jsx index bbeb691..6d52cfd 100644 --- a/src/components/other/dataDisplay/CartTotal.jsx +++ b/src/components/other/dataDisplay/CartTotal.jsx @@ -2,10 +2,6 @@ import React from 'react'; import { Typography } from '@mui/material'; const CartTotal = ({ 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 71378dc..48213c6 100644 --- a/src/components/other/dataDisplay/TopCardsDisplay.jsx +++ b/src/components/other/dataDisplay/TopCardsDisplay.jsx @@ -1,35 +1,14 @@ -import React, { useContext, useEffect, useRef, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import SwipeableViews from 'react-swipeable-views'; -import { - Box, - Button, - Card, - CardContent, - CardMedia, - Container, - Grid, - MobileStepper, - Paper, - Typography, - useTheme, -} from '@mui/material'; +import { Box, Button, Container, Grid, MobileStepper } from '@mui/material'; import { KeyboardArrowLeft, KeyboardArrowRight } from '@mui/icons-material'; import { useCollectionStore } from '../../../context/CollectionContext/CollectionContext'; import { useMode } from '../../../context/hooks/colormode'; import { makeStyles, styled } from '@mui/styles'; -import { ModalContext } from '../../../context/ModalContext/ModalContext'; -import GenericCard from '../../cards/GenericCard'; -import { - MainContainer2b, - MainContainerb, - MainContainer2, - MainContainer, -} from '../../../pages/pageStyles/StyledComponents'; -import { AspectRatio } from '@mui/joy'; -import { debounce } from 'lodash'; +import { MainContainer } from '../../../pages/pageStyles/StyledComponents'; +import CarouselCard from '../../cards/CarouselCard'; const useStyles = makeStyles((theme) => ({ stepper: { - // backgroundColor: theme.palette.success.main, background: theme.palette.background.main, border: `1px solid ${theme.palette.background.quaternary}`, borderRadius: theme.shape.borderRadiusLarge, @@ -37,7 +16,12 @@ const useStyles = makeStyles((theme) => ({ overflow: 'hidden', padding: theme.spacing(1), height: '100%', - // marginTop: 'auto', + }, + cardDetails: { + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', }, })); @@ -46,171 +30,12 @@ const StyledContainer = styled(Container)(({ theme }) => ({ flexDirection: 'column', height: '100%', alignItems: 'center', - // background: theme.palette.background.main, background: theme.palette.background.dark, borderRadius: theme.shape.borderRadiusLarge, padding: theme.spacing(3), - color: '#fff', // White text color - // padding: 2, - // borderRadius: 4, + color: '#fff', })); -const CarouselCard = ({ card }) => { - const { theme } = useMode(); - const { openModalWithCard, closeModal, isModalOpen, modalContent } = - useContext(ModalContext); - const cardRef = useRef(null); - const chartRef = useRef(null); - const chartContainerRef = useRef(null); - const [chartDimensions, setChartDimensions] = useState({ - width: 0, - height: 0, - }); - const [chartContainerDimensions, setChartContainerDimensions] = useState({ - width: 0, - height: 0, - }); - const HEIGHT_TO_WIDTH_RATIO = 1; - - const handleClick = () => { - openModalWithCard(card); - }; - - useEffect(() => { - const handleResize = debounce(() => { - if (chartContainerRef.current) { - const width = chartContainerRef.current.offsetWidth; - const height = width * HEIGHT_TO_WIDTH_RATIO; - setChartContainerDimensions({ width, height }); - // setChartContainerDimensions({ width, height }); - } - // }, 100); - }, 100); - - const handleResize2 = debounce(() => { - if (chartRef.current) { - const width = chartRef.current.offsetWidth; - const height = width * HEIGHT_TO_WIDTH_RATIO; - setChartDimensions({ width, height }); - // setChartContainerDimensions({ width, height }); - } - // }, 100); - }, 100); - - window.addEventListener('resize', handleResize); - handleResize(); - - window.addEventListener('resize', handleResize2); - handleResize2(); - - return () => { - window.removeEventListener('resize', handleResize); - handleResize.cancel(); - - window.removeEventListener('resize', handleResize2); - handleResize2.cancel(); - }; - }, []); - return ( - - - - {/* */} - handleClick()} - context={'Collection'} - ref={cardRef} - /> - {/* */} - - {/* Top section for card details */} - - - - - - {card?.name} - - - Price: ${card?.latestPrice?.num || card?.price || 0} - - {/* - {card?.desc} - */} - - - {/* Bottom section for chart */} - - - - - {/* Chart component goes here */} - - {/* */} - - - - - - - - ); -}; - const TopCardsDisplay = () => { const { theme } = useMode(); const { selectedCollection } = useCollectionStore(); @@ -235,11 +60,8 @@ const TopCardsDisplay = () => { }, [selectedCollection]); const maxSteps = top5Cards?.length; - - const handleNext = () => - setActiveStep((prevActiveStep) => prevActiveStep + 1); - const handleBack = () => - setActiveStep((prevActiveStep) => prevActiveStep - 1); + const handleNext = () => setActiveStep((prev) => prev + 1); + const handleBack = () => setActiveStep((prev) => prev - 1); return ( @@ -247,7 +69,6 @@ const TopCardsDisplay = () => { { index={activeStep} onChangeIndex={setActiveStep} enableMouseEvents - style={{ - flexGrow: 1, - width: '100%', // Use full width of the container - background: theme.palette.background.dark, - }} + className={classes.swipeableView} > {top5Cards?.map((card, index) => ( diff --git a/src/components/reusable/LongMenu.jsx b/src/components/reusable/LongMenu.jsx index 85340d4..9c83bc2 100644 --- a/src/components/reusable/LongMenu.jsx +++ b/src/components/reusable/LongMenu.jsx @@ -36,11 +36,9 @@ export default function LongMenu({ onEdit, onStats, onView }) { anchorEl={anchorEl} open={open} onClose={handleClose} - PaperProps={{ - style: { - maxHeight: ITEM_HEIGHT * 4.5, - width: '20ch', - }, + sx={{ + maxHeight: ITEM_HEIGHT * 4.5, + width: '20ch', }} > { const { theme } = useMode(); const { initialState, filters } = search; - const [searchParams, setSearchParams] = useState({ name: '', type: '', @@ -18,17 +17,9 @@ const SearchBar = () => { race: '', }); const { handleRequest } = useCardStore(); - // const handleChange = (name, newValue) => { - // setSearchParams((prev) => ({ ...prev, [name]: newValue })); - // }; const handleChange = (name, newValue) => { setSearchParams((prev) => ({ ...prev, [name]: newValue })); }; - // Correct handleSubmit to use handleRequest with searchParams - // const handleSubmit = (event) => { - // event.preventDefault(); - // handleRequest(searchParams); - // }; const handleSubmit = () => { handleRequest(searchParams); }; @@ -63,7 +54,7 @@ const SearchBar = () => { handleChange('name', event.target.value)} /> diff --git a/src/containers/deckBuilderPageContainers/DeckBuilderContainer.js b/src/containers/deckBuilderPageContainers/DeckBuilderContainer.js index 2f1a775..8a85862 100644 --- a/src/containers/deckBuilderPageContainers/DeckBuilderContainer.js +++ b/src/containers/deckBuilderPageContainers/DeckBuilderContainer.js @@ -1,6 +1,6 @@ import React from 'react'; import { Grid } from '@mui/material'; -import DeckDisplay from '../../components/grids/DeckDisplay'; +import DeckDisplay from '../../components/grids/deckBuilderGrids/DeckDisplay'; import DeckSearch from '../../components/search/DeckSearch'; import { styled } from '@mui/styles'; import { useMode } from '../../context/hooks/colormode'; diff --git a/src/context/AuthContext/authContext.js b/src/context/AuthContext/authContext.js index f9ca446..a1cc68f 100644 --- a/src/context/AuthContext/authContext.js +++ b/src/context/AuthContext/authContext.js @@ -6,44 +6,15 @@ import React, { useContext, } from 'react'; import axios from 'axios'; -import jwt_decode from 'jwt-decode'; import { useCookies } from 'react-cookie'; import { debounce } from 'lodash'; +import { + AUTH_COOKIE, + LOGGED_IN_COOKIE, + USER_COOKIE, + processResponseData, +} from './helpers'; -const LOGGED_IN_COOKIE = 'loggedIn'; -const AUTH_COOKIE = 'authToken'; -const USER_COOKIE = 'user'; - -// Validator function -const validateData = (data, eventName, functionName) => { - if (!data || Object.keys(data).length === 0) { - console.warn(`Invalid data in ${functionName} for ${eventName}`); - return false; - } - return true; -}; - -// Process the server response based on the action type (Login/Signup) -const processResponseData = (data, type) => { - if (!validateData(data, `${type} Response`, `process${type}Data`)) - return null; - - if (type === 'Login') { - const token = data?.data?.token; - if (!token) return null; - const user = jwt_decode(token); - return { token, user }; - } - - if (type === 'Signup') { - const { success, newUser } = data; - if (success && newUser) return { success, newUser }; - } - - return null; -}; - -// Main AuthContext Provider export const AuthContext = React.createContext(); export default function AuthProvider({ children, serverUrl }) { const [cookies, setCookie, removeCookie] = useCookies([ @@ -94,7 +65,6 @@ export default function AuthProvider({ children, serverUrl }) { } }; - // In App.js or inside AuthProvider component axios.interceptors.request.use( (config) => { const token = cookies[AUTH_COOKIE]; @@ -141,9 +111,6 @@ export default function AuthProvider({ children, serverUrl }) { }, 1800000); }; - // Debounced function to reset the logout timer on user activity - // const resetLogoutTimer = useRef(debounce(startLogoutTimer, 500)).current; - const debouncedLogout = useCallback( debounce(() => { if (logoutTimerRef.current) { @@ -180,7 +147,6 @@ export default function AuthProvider({ children, serverUrl }) { window.addEventListener('scroll', resetLogoutTimer); window.addEventListener('click', resetLogoutTimer); - // Cleanup on component unmount return () => { clearTimeout(logoutTimerRef.current); window.removeEventListener('mousemove', resetLogoutTimer); @@ -189,8 +155,6 @@ export default function AuthProvider({ children, serverUrl }) { 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]; diff --git a/src/context/AuthContext/helpers.jsx b/src/context/AuthContext/helpers.jsx new file mode 100644 index 0000000..0865ad5 --- /dev/null +++ b/src/context/AuthContext/helpers.jsx @@ -0,0 +1,34 @@ +import jwt_decode from 'jwt-decode'; + +export const LOGGED_IN_COOKIE = 'loggedIn'; +export const AUTH_COOKIE = 'authToken'; +export const USER_COOKIE = 'user'; + +// Validator function +export const validateData = (data, eventName, functionName) => { + if (!data || Object.keys(data).length === 0) { + console.warn(`Invalid data in ${functionName} for ${eventName}`); + return false; + } + return true; +}; + +// Process the server response based on the action type (Login/Signup) +export const processResponseData = (data, type) => { + if (!validateData(data, `${type} Response`, `process${type}Data`)) + return null; + + if (type === 'Login') { + const token = data?.data?.token; + if (!token) return null; + const user = jwt_decode(token); + return { token, user }; + } + + if (type === 'Signup') { + const { success, newUser } = data; + if (success && newUser) return { success, newUser }; + } + + return null; +}; diff --git a/src/context/CardContext/CardStore.js b/src/context/CardContext/CardStore.js index 9d78dac..2b77009 100644 --- a/src/context/CardContext/CardStore.js +++ b/src/context/CardContext/CardStore.js @@ -14,6 +14,14 @@ export const CardProvider = ({ children }) => { const initialStore = cookies.store || []; const [cardsArray, setCardsArray] = useState(initialStore); const { allCollections, setAllCollections } = useCollectionStore(); + // const [searchParam, setSearchParam] = useState(''); + // const [searchParams, setSearchParams] = useState([]); + const [searchParams, setSearchParams] = useState({ + name: '', + type: '', + attribute: '', + race: '', + }); const { listOfMonitoredCards } = useCombinedContext(); const currentCart = cookies.cart || []; const [currenCartArray, setCurrentCartArray] = useState(currentCart); @@ -33,15 +41,16 @@ export const CardProvider = ({ children }) => { return
Loading...
; } - const handleRequest = async (searchParams) => { + const handleRequest = async (searchParamss) => { try { + // setSearchParams([searchParams]); + const response = await axios.post( `${process.env.REACT_APP_SERVER}/api/cards/ygopro`, - searchParams + searchParamss ); if (response.data.data) { - // Create a new Set with just the ids of the cards for easy lookup const ids = new Set(); // Filter out duplicate cards @@ -103,7 +112,7 @@ export const CardProvider = ({ children }) => { ) { needsUpdate = true; const response = await axios.patch( - `${process.env.REACT_APP_SERVER}/api/cards/ygopro/${card.id}`, + `${process.env.REACT_APP_SERVER}/api/cards/ygopro/${card.name}`, { id: card.id, user: user.id }, { withCredentials: true } ); @@ -152,12 +161,11 @@ export const CardProvider = ({ children }) => { }; const randomCardData = getRandomCard(); - - // In CardProvider component - useEffect(() => { - console.log('CARD CONTEXT: ', { + const contextValue = useMemo( + () => ({ cardsArray, searchData, + searchParams, deckSearchData, savedDeckData, randomCardData, @@ -172,6 +180,7 @@ export const CardProvider = ({ children }) => { isCardDataValid, slicedAndMergedSearchData, + setSearchParams, handlePatch, setSlicedAndMergedSearchData, setOrganizedSearchData, @@ -181,48 +190,22 @@ export const CardProvider = ({ children }) => { setDeckSearchData, setSavedDeckData, getCardData, - getRandomCard, setCardsArray, + getRandomCard, + setCookie, + setCurrentCartArray, handleRequest, // Add your new function to the context + }), + [cardsArray, searchData] + ); + // In CardProvider component + useEffect(() => { + console.log('CARD CONTEXT: ', { + contextValue, }); }, []); return ( - - {children} - + {children} ); }; diff --git a/src/context/CartContext/CartContext.js b/src/context/CartContext/CartContext.js index 5f00342..4de1246 100644 --- a/src/context/CartContext/CartContext.js +++ b/src/context/CartContext/CartContext.js @@ -39,7 +39,8 @@ export const CartProvider = ({ children }) => { totalPrice: 0, // Total price of items }); const [cookie, setCookie] = useCookies(['user', 'cart']); - const isMounted = useRef(true); + const [totalQuantity, setTotalQuantity] = useState(0); + const [totalPrice, setTotalPrice] = useState(0); const getCardQuantity = (cardId) => { let totalItems = 0; @@ -52,6 +53,12 @@ export const CartProvider = ({ children }) => { }); return { totalItems, quantityOfSameId }; }; + const getTotalCost = () => { + return cartData.cart.reduce( + (acc, card) => acc + card.card_prices[0].tcgplayer_price * card.quantity, + 0 + ); + }; const totalCost = useMemo( () => @@ -103,15 +110,6 @@ export const CartProvider = ({ children }) => { } }, [userId, createUserCart]); - // useEffect(() => { - // if (userId && isMounted.current) { - // fetchUserCart().catch(console.error); - // } - // return () => { - // isMounted.current = false; - // }; - // }, [userId, fetchUserCart]); - const setCartDataAndCookie = (newCartData) => { if (newCartData && Array.isArray(newCartData.cart)) { setCartData(newCartData); @@ -123,34 +121,33 @@ export const CartProvider = ({ children }) => { } }; - const getTotalCost = () => { - return cartData.cart.reduce( - (acc, card) => acc + card.card_prices[0].tcgplayer_price * card.quantity, - 0 - ); - }; - + // useEffect(() => { + // 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]); useEffect(() => { - const totalQuantity = cartData.cart.reduce( + const newTotalQuantity = cartData.cart.reduce( (total, item) => total + item.quantity, 0 ); - const calculatedTotalPrice = getTotalCost(); - - // Check if totalQuantity or calculatedTotalPrice has actually changed - if ( - cartData.quantity !== totalQuantity || - cartData.totalPrice !== calculatedTotalPrice - ) { - setCartData((prevState) => ({ - ...prevState, - quantity: totalQuantity, - totalPrice: calculatedTotalPrice, - })); - } + const newTotalPrice = getTotalCost(); + setTotalQuantity(newTotalQuantity); + setTotalPrice(newTotalPrice); }, [cartData.cart]); - // Fetch user cart on mount and userId change const updateCart = async (cartId, updatedCart) => { if (!cartId) return; const formattedCartData = { @@ -169,7 +166,6 @@ export const CartProvider = ({ children }) => { setCartDataAndCookie(data); return data; }; - const addOneToCart = async (cardInfo) => { if (!cartData._id) return; console.log('Adding one to cart', cardInfo); @@ -203,35 +199,50 @@ export const CartProvider = ({ children }) => { const updatedCartData = await updateCart(cartData._id, updatedCart); if (updatedCartData) setCartData(updatedCartData); }; + const contextValue = useMemo( + () => ({ + cartData, + totalCost, + totalQuantity, + totalPrice, + cart: cartData?.cart, + cartCardQuantity: cartData?.cart?.reduce( + (acc, card) => acc + card.quantity, + 0 + ), + cartCardCount: cartData.cart?.length, + cartValue: cartData?.cart?.reduce( + (acc, card) => + acc + card.card_prices[0].tcgplayer_price * card.quantity, + 0 + ), + getCardQuantity, + getTotalCost, + addOneToCart, + removeOneFromCart, + deleteFromCart, + fetchUserCart, + createUserCart, + }), + [ + totalQuantity, + totalPrice, + getCardQuantity, + getTotalCost, + addOneToCart, + removeOneFromCart, + deleteFromCart, + cartData, + ] + ); - const value = { - cartData, - cart: cartData.cart, - getCardQuantity, - cartCardQuantity: cartData.cart?.reduce( - (acc, card) => acc + card.quantity, - 0 - ), - cartCardCount: cartData.cart?.length, - cartValue: cartData.cart?.reduce( - (acc, card) => acc + card.card_prices[0].tcgplayer_price * card.quantity, - 0 - ), - totalPrice: cartData.totalPrice, - totalCost, - addOneToCart, - removeOneFromCart, - deleteFromCart, - getTotalCost, - fetchUserCart, - createUserCart, - }; - - // useEffect(() => { - // console.log('CART CONTEXT: ', value.cartData); - // }, [addOneToCart, removeOneFromCart, deleteFromCart]); + useEffect(() => { + console.log('CART CONTEXT: ', cartData); + }, [cartData]); - return {children}; + return ( + {children} + ); }; export const useCartStore = () => { diff --git a/src/context/ChartContext/ChartContext.jsx b/src/context/ChartContext/ChartContext.jsx index f31ac8f..598219e 100644 --- a/src/context/ChartContext/ChartContext.jsx +++ b/src/context/ChartContext/ChartContext.jsx @@ -1,4 +1,12 @@ import { createContext, useContext, useState } from 'react'; +import { + groupAndAverageData, + convertDataForNivo2, + getUniqueValidData, + getTickValues, + getFilteredData, + formatDateToString, +} from './helpers'; const ChartContext = createContext(); @@ -31,10 +39,17 @@ export const ChartProvider = ({ children }) => { value={{ currentValue, latestData, - setLatestData, timeRange, - setTimeRange, timeRanges, + + groupAndAverageData, + convertDataForNivo2, + // getUniqueValidData, + getTickValues, + getFilteredData, + formatDateToString, + setTimeRange, + setLatestData, handleChange, }} > diff --git a/src/components/reusable/chartUtils.jsx b/src/context/ChartContext/helpers.jsx similarity index 74% rename from src/components/reusable/chartUtils.jsx rename to src/context/ChartContext/helpers.jsx index 474420f..2aa3c49 100644 --- a/src/components/reusable/chartUtils.jsx +++ b/src/context/ChartContext/helpers.jsx @@ -1,45 +1,4 @@ -export const getUniqueValidData = (currentChartData) => { - if (!Array.isArray(currentChartData)) { - console.error('Invalid input: currentChartData should be an array'); - return []; - } - - const uniqueLabels = new Set(); - const uniqueXValues = new Set(); - - return currentChartData - .filter((entry) => { - // Check if entry is valid, y is a number and not zero, and label is unique - return ( - entry && - typeof entry === 'object' && - typeof entry.y === 'number' && - entry.y !== 0 && - entry.y !== null && - entry.y !== undefined && - entry.label && - !uniqueLabels.has(entry.label) - ); - }) - .filter((entry) => { - // Check if x is present, not null, not undefined, and unique - const hasValidX = - entry && 'x' in entry && entry.x !== null && entry.x !== undefined; - if (hasValidX && !uniqueXValues.has(entry.x)) { - uniqueXValues.add(entry.x); - uniqueLabels.add(entry.label); - return true; - } - return false; - }) - .map((entry) => ({ - label: entry.label, - x: entry.x, - y: entry.y, - })); -}; - -export const groupAndAverageData = (data, threshold = 600000) => { +export const groupAndAverageData = (data, threshold = 600000, timeRange) => { if (!data || data.length === 0) return []; const clusters = []; @@ -141,7 +100,7 @@ export const convertDataForNivo2 = (rawData2) => { ]; }; -const roundToNearestTenth = (value) => { +export const roundToNearestTenth = (value) => { return Math.round(value * 10) / 10; }; diff --git a/src/context/CollectionContext/CardUpdateEffect.jsx b/src/context/CollectionContext/CardUpdateEffect.jsx deleted file mode 100644 index 0b71535..0000000 --- a/src/context/CollectionContext/CardUpdateEffect.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import { useEffect } from 'react'; -import axios from 'axios'; -import { useCollectionStore } from './CollectionContext'; - -const CardUpdateEffect = ({ allCollections, user, updateCollectionData }) => { - const { updateCollection } = useCollectionStore(); - useEffect(() => { - const updateCardTotalPrice = async (card, collection) => { - try { - const updatedTotalPrice = card.price * card.quantity; - const response = await axios.patch( - `${process.env.REACT_APP_SERVER}/api/cards/ygopro/${card.id}`, - { - id: card.id, - user: user, - totalPrice: updatedTotalPrice, - // Include other fields as necessary - } - ); - - if (response.data && response.data.data) { - // Update card in the local state or context - updateCollection(response.data.data, 'update', collection, user.id); - } - } catch (error) { - console.error( - `Error updating total price for card ID ${card.id}:`, - error - ); - } - }; - - const processCollections = () => { - allCollections.forEach((collection) => { - collection.cards.forEach((card) => { - const originalTotalPrice = card.price * card.quantity; - if (card.totalPrice !== originalTotalPrice) { - updateCardTotalPrice(card, collection); - } - }); - }); - }; - - processCollections(); - }, [allCollections, user, updateCollectionData]); - - return null; // Since this component doesn't render anything -}; - -export default CardUpdateEffect; diff --git a/src/context/CollectionContext/CollectionContext.jsx b/src/context/CollectionContext/CollectionContext.jsx index 7404ad1..755992f 100644 --- a/src/context/CollectionContext/CollectionContext.jsx +++ b/src/context/CollectionContext/CollectionContext.jsx @@ -10,72 +10,69 @@ import React, { useRef, } from 'react'; import { useCookies } from 'react-cookie'; -import { - getTotalCost, - initialCollectionState, - getCardPrice, - defaultContextValue, - validateUserIdAndData, - calculateCollectionValue, -} from './collectionUtility.jsx'; import { fetchWrapper, createApiUrl } from '../Helpers.jsx'; import { handleError, removeDuplicatesFromCollection, updateCollectionArray, - replaceCardInArray, - updatePriceHistory, - determineCardPrice, - createChartDataEntry, - createPriceHistoryObject, - getFilteredChartData, - filterUniqueDataPoints, - transformPriceHistoryToXY, filterNullPriceHistoryForCollection, filterNullPriceHistory, handleCardAddition, handleCardRemoval, + handleCardUpdate, determineMethod, - determineEndpointSuffix, - createCardsPayload, - constructCardDifferencesPayload, - updateChartData, - getPriceChange, updateCollectionDataEndpoint, - getUniqueFilteredXYValues, + getTotalQuantityOfSelectedCollection, + getUpdatedCollectionPriceHistory, + getFilteredData2, + calculateCollectionValue, + getUpdatedCollectionData, + initialCollectionState, + defaultContextValue, + validateUserIdAndData, } from './helpers.jsx'; -import axios from 'axios'; export const CollectionContext = createContext(defaultContextValue); export const CollectionProvider = ({ children }) => { const [cookies] = useCookies(['user']); + const user = cookies?.user; + const userId = user?.id; + // state for the collection context const [selectedCollection, setSelectedCollection] = useState( initialCollectionState ); const [collectionData, setCollectionData] = useState(initialCollectionState); const [allCollections, setAllCollections] = useState([]); - // Refs to store the previous state of the collections - const prevAllCollectionsRef = useRef(); - const prevSelectedCollectionRef = useRef(); - const prevCollectionDataRef = useRef(); + const [collectionsFetched, setCollectionsFetched] = useState(false); + const [cardsUpdated, setCardsUpdated] = useState(false); + // state for the collection context + const [collectionPriceHistory, setCollectionPriceHistory] = useState([]); + const [currentChartDataSets2, setCurrentChartDataSets2] = useState([]); const [totalPrice, setTotalPrice] = useState(0); - const [totalCost, setTotalCost] = useState(''); + const [totalQuantity, setTotalQuantity] = useState(0); + const [lastSavedPrice, setLastSavedPrice] = useState({ + num: 0, + timestamp: new Date(), + }); + const [latestPrice, setLatestPrice] = useState({ + num: 0, + timestamp: new Date(), + }); + + // state for the card in collection context + const [quantityInCard, setQuantityInCard] = useState(0); + const [priceInCard, setPriceInCard] = useState(0); + + const lastFetchedTime = useRef(null); const [ updatedPricesFromCombinedContext, setUpdatedPricesFromCombinedContext, ] = useState([]); const [xyData, setXyData] = useState([]); - const [currentChartDataSets2, setCurrentChartDataSets2] = useState([]); - const [currentChartDataSets, setCurrentChartDataSets] = useState([]); - const [openChooseCollectionDialog, setOpenChooseCollectionDialog] = - useState(false); - const user = cookies?.user; - const userId = user?.id; - // console.log('USER ID:', userId); - const lastFetchedTime = useRef(null); + // fetch all collections for user const fetchAndSetCollections = useCallback(async () => { const shouldFetch = () => { const fetchDelay = 60000; // 1 minute @@ -98,36 +95,34 @@ export const CollectionProvider = ({ children }) => { ); const collections = response?.data || []; - console.log('FETCHED COLLECTIONS:', collections); + // console.log('FETCHED COLLECTIONS:', collections); if (collections?.length > 0) { - const uniqueCollections = collections.map( + const uniqueCollections = collections?.map( removeDuplicatesFromCollection ); setAllCollections(uniqueCollections); setCollectionData(uniqueCollections[0]); setSelectedCollection(uniqueCollections[0]); - } else { - console.warn('No collections found.'); - // Optionally, set a default or empty state if no collections are found + setCollectionsFetched(true); } } catch (error) { - console.error(`Failed to fetch collections: ${error}`); + console.error(`Failed to fetch collections: ${error}`, error.message); } }, [userId, setAllCollections, setCollectionData, setSelectedCollection]); - + // set updated state for the collections const updateCollectionData = useCallback( (newData) => { try { // Function to safely check if an object has a property - const hasOwnProperty = (obj, prop) => + const has = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop); // Determine the type of the new data if ( Array.isArray(newData) && - newData.every((item) => hasOwnProperty(item, 'cards')) + newData.every((item) => has(item, 'cards')) ) { const filteredNewData = filterNullPriceHistory(newData); @@ -138,7 +133,7 @@ export const CollectionProvider = ({ children }) => { } else if ( newData && typeof newData === 'object' && - hasOwnProperty(newData, 'cards') + has(newData, 'cards') ) { // If newData is an object with a 'cards' property, assume it's 'selectedCollection' setSelectedCollection(filterNullPriceHistoryForCollection(newData)); @@ -157,7 +152,7 @@ export const CollectionProvider = ({ children }) => { }, [setAllCollections, setSelectedCollection, setCollectionData] ); - + // create a new collection for user const createUserCollection = async ( userId, newCollectionInfo, @@ -184,11 +179,11 @@ export const CollectionProvider = ({ children }) => { userId, }; const url = createApiUrl(`${userId}/collections`); - console.log('Payload for user collection:', payload); + // console.log('Payload for user collection:', payload); const response = await fetchWrapper(url, 'POST', payload); updateCollectionData(response.data); }; - + // remove a collection for user const removeCollection = async (collection) => { if (!collection._id) { console.error('Collection ID is undefined.'); @@ -207,251 +202,125 @@ export const CollectionProvider = ({ children }) => { } }; + // update cards in collection const getUpdatedCards = (collection, cardUpdate, operation) => { - let cardsToUpdate; + if (!collection?.cards || !Array.isArray(collection.cards)) { + console.error('Invalid collection or cards data'); + return []; + } switch (operation) { case 'add': - cardsToUpdate = handleCardAddition(collection?.cards, cardUpdate); - break; + return handleCardAddition(collection.cards, cardUpdate); case 'remove': - cardsToUpdate = handleCardRemoval(collection?.cards, cardUpdate); - break; + return handleCardRemoval(collection.cards, cardUpdate); case 'update': - if ( - !collection?.cards && - !cardUpdate?.id && - !Array.isArray(collection) - ) { - console.error( - 'Missing card or collection data for update.', - collection - ); - const returnValue = Array.isArray(collection) - ? collection - : collection?.cards; - return collection?.cards; - } - // eslint-disable-next-line no-case-declarations - const cardIndex = collection?.cards?.findIndex( - (c) => c?.id?.toString() === cardUpdate?.id?.toString() - ); - - if (cardIndex === -1) { - console.error('Card not found in collection for update.'); - throw new Error('Card not found in collection for update.'); // Throw an error instead of returning - } - // eslint-disable-next-line no-case-declarations - const existingCard = collection?.cards[cardIndex]; - // console.log('EXISTING CARD:', existingCard); - // eslint-disable-next-line no-case-declarations - const updatedPriceHistory = updatePriceHistory( - existingCard, - cardUpdate - ); - // eslint-disable-next-line no-case-declarations - const updatedCard = getUpdatedCard( - existingCard, - cardUpdate, - updatedPriceHistory, - collection?._id - ); - cardsToUpdate = replaceCardInArray( - collection.cards, - updatedCard, - cardIndex - ); - break; + return handleCardUpdate(collection.cards, cardUpdate); default: console.error('Unsupported operation:', operation); - return collection?.cards; + return []; } - - return cardsToUpdate; }; - - function getUpdatedCard(card, update, priceHistory, collectionId) { - const cardPrice = determineCardPrice(card, update); - const newChartDataEntry = createChartDataEntry( - cardPrice * (update?.quantity || card?.quantity) - ); - - return { - ...card, - price: cardPrice || card.price, - quantity: update.quantity || card.quantity || 1, - collectionId: collectionId, - totalPrice: cardPrice * update.quantity || card.quantity, - lastSavedPrice: { - num: card.price || card.card_prices[0].tcgplayer_price, - timestamp: new Date(), - }, - latestPrice: update.latestPrice, - tag: 'monitored', - chart_datasets: [...(card.chart_datasets || []), newChartDataEntry], - card_prices: update.card_prices, - card_sets: update.card_sets, - card_images: update.card_images, - priceHistory: priceHistory, - }; - } - - const getUpdatedCollectionData = ( - collectionWithCards, - updatedTotalPrice, - newCollectionPriceHistoryObject, - updatedTotalQuantity, - updatedCards - ) => { - if (!collectionWithCards) { - console.error('No collection data provided'); - return null; - } - - const { - allCardPrices = [], - description = selectedCollection.description || '', - name = selectedCollection.name || '', - collectionPriceHistory = selectedCollection.collectionPriceHistory || [], - chartData = selectedCollection.chartData || {}, - cards = selectedCollection.cards || [], - currentChartDataSets2 = getUniqueFilteredXYValues( - chartData?.allXYValues - ) || [], - } = collectionWithCards; - if (!Array.isArray(collectionPriceHistory)) { - console.error( - 'collectionPriceHistory is not an array', - collectionPriceHistory - ); - return; - } - return { - allCardPrices, - description, - name, - userId: userId, - totalPrice: updatedTotalPrice, - totalCost: getTotalCost(collectionWithCards), - totalQuantity: updatedTotalQuantity || 0, - quantity: cards?.length, - lastSavedPrice: { - num: collectionWithCards?.totalPrice || 0, - timestamp: new Date(), - }, - latestPrice: { - num: updatedTotalPrice || 0, - timestamp: new Date(), - }, - dailyPriceChange: '', - // getPriceChange(chartData)[0]?.priceChange || '', - currentChartDataSets2: currentChartDataSets2, - // filterUniqueDataPoints( - // chartData?.allXYValues - // // transformPriceHistoryToXY(chartData?.allXYValues) - // ), - collectionPriceHistory: [ - ...collectionPriceHistory, - newCollectionPriceHistoryObject || { - num: updatedTotalPrice, - timestamp: new Date(), - }, - ], - cards: updatedCards, - }; - }; - + // update collection data const getUpdatedCollection = async ( collectionWithCards, - cardUpdate, + cardToUpdate, operation, userId ) => { - const collectionId = - collectionWithCards?._id || collectionData?._id || selectedCollection._id; + if ( + !collectionWithCards?.cards || + !Array.isArray(collectionWithCards.cards) + ) { + console.error('Invalid collection or cards data'); + return; + } + const collectionId = collectionWithCards?._id || ''; if (!collectionId || !userId) { - console.error('Missing collection ID or user ID.', collectionId, userId); + console.error('Missing collection ID or user ID.'); return; } - const method = determineMethod(operation, cardUpdate, collectionWithCards); + const method = determineMethod(operation); const endpoint = createApiUrl( - `${userId}/collections/${collectionId}/${determineEndpointSuffix( - operation - )}` + `${userId}/collections/${collectionId}/${operation}` ); - const updatedCards = getUpdatedCards( + let cardsPayload; + const updatedCardsData = getUpdatedCards( collectionWithCards, - cardUpdate, + cardToUpdate, operation ); - const updatedTotalPrice = calculateCollectionValue(updatedCards); - setTotalPrice(updatedTotalPrice); - - const updatedTotalQuantity = updatedCards?.reduce( - (total, card) => total + card?.quantity, - 0 - ); - const newCollectionPriceHistoryObject = - createPriceHistoryObject(updatedTotalPrice); - - let cardsPayload = createCardsPayload(operation, updatedCards, cardUpdate); - - let cardsResponse = await fetchWrapper(endpoint, method, cardsPayload); - const { cardMessage } = cardsResponse; - - const updatedChartData = getFilteredChartData( - collectionWithCards.chartData, - updatedTotalPrice - ); - const chartDataResponse = await updateChartData( - userId, - collectionId, - updatedChartData - ); - - const updatedCollection = getUpdatedCollectionData( - selectedCollection, - updatedTotalPrice, - newCollectionPriceHistoryObject, - updatedTotalQuantity, - updatedCards - ); + switch (operation) { + case 'add': + case 'update': + cardsPayload = { cards: updatedCardsData }; + break; + case 'remove': + cardsPayload = { cardIds: [updatedCardsData.id] }; + break; + default: + console.error('Unsupported operation:', operation); + return; + } - const collectionResponse = await updateCollectionDataEndpoint( - userId, - collectionId, - updatedCollection - ); + try { + const cardsResponse = await fetchWrapper(endpoint, method, cardsPayload); + const updatedCards = cardsResponse?.cards || []; + + const updatedCollectionUpdatedCards = getUpdatedCollectionData( + collectionWithCards, + calculateCollectionValue(updatedCards), + getUpdatedCollectionPriceHistory( + collectionWithCards, + calculateCollectionValue(updatedCards) + ), + getTotalQuantityOfSelectedCollection(collectionWithCards), + updatedCards, + userId + ); - // console.log('COLLECTION RESPONSE', collectionResponse); - setTotalPrice(calculateCollectionValue(updatedCards)); + const collectionResponse = await updateCollectionDataEndpoint( + userId, + collectionId, + updatedCollectionUpdatedCards + ); + const updatedCollection = { ...collectionResponse, cards: updatedCards }; - const restructuredCollection = { - ...collectionResponse?.collectionData, - cards: cardsResponse?.cards, - chartData: chartDataResponse?.chartData, - }; - const filteredRestructuredCollection = filterNullPriceHistoryForCollection( - restructuredCollection - ); - // setCurrentChartDataSets( - // getUniqueFilteredXYValues( - // filteredRestructuredCollection[0]?.chartData?.allXYValues - // ) - // ); - setCurrentChartDataSets2( - getUniqueFilteredXYValues( - filteredRestructuredCollection?.chartData?.allXYValues - ) - ); + setTotalPrice(calculateCollectionValue(updatedCollection)); + setTotalQuantity(getTotalQuantityOfSelectedCollection(updatedCollection)); + setCurrentChartDataSets2(getFilteredData2(updatedCollection, 'all')); + setLastSavedPrice({ + num: updatedCollection?.lastSavedPrice?.num || 0, + timestamp: new Date(), + }); + setLatestPrice({ + num: updatedCollection?.totalPrice || 0, + timestamp: new Date(), + }); + setCollectionPriceHistory( + getUpdatedCollectionPriceHistory( + updatedCollection, + updatedCollection?.totalPrice || 0 + ) + ); + updateCollectionData(updatedCollection); - return { filteredRestructuredCollection }; + return updatedCollection; + } catch (error) { + console.error(`Error in ${operation} operation:`, error); + } }; + + // update collection details (name, description, etc.) const updateCollectionDetails = async (updatedInfo, userId, collectionId) => { const { name, description } = updatedInfo; - if (selectedCollection && collectionId) { + if (!selectedCollection || !collectionId) { + console.error('Selected collection or collection ID is missing.'); + return; + } + if (collectionId) { const updatedCollection = { ...selectedCollection, name, @@ -466,309 +335,223 @@ export const CollectionProvider = ({ children }) => { ); try { - // Update the collection in the backend const collectionEndpoint = createApiUrl( `${userId}/collections/${collectionId}` ); - const collectionResponse = await fetchWrapper( - collectionEndpoint, - 'PUT', - { - updatedCollection, - } - ); - - const { collectionMessage } = collectionResponse; - // console.log(collectionMessage); - - // Optionally handle the response here, e.g., update the state with the response data if necessary + await fetchWrapper(collectionEndpoint, 'PUT', { updatedCollection }); } catch (error) { console.error('Error updating collection details:', error); } } else { - console.error('Selected collection or collection ID is missing.'); + console.error('Collection ID is missing.'); } }; + // handle card operations (add, remove, update) const handleCardOperation = async (card, operation, collection, userId) => { - if (!card) { - console.error('Card is undefined.', card); + if (!card || !collection) { + console.error('Card or collection is undefined.', card, collection); return; } - if (!collection) { - console.error( - `Collection with ID ${collection?._id} not found in allCollections.` + + try { + const updatedCollection = await getUpdatedCollection( + collection, + card, + operation, + userId ); - return; - } - const updatedCollection = await getUpdatedCollection( - collection, - card, - operation, - userId - ); - if (updatedCollection) { + // console.log('UPDATED COLLECTION:', updatedCollection); - updateCollectionData(updatedCollection?.filteredRestructuredCollection); - } else { - console.error('Failed to update collection.'); - } + if (updatedCollection) { + const collectionToSet = { + ...updatedCollection.collectionData, + cards: updatedCollection.cards, + }; - return updatedCollection; + updateCollectionData(collectionToSet); + return updatedCollection; + } else { + console.error('Failed to update collection.'); + } + } catch (error) { + console.error(`Error handling card operation '${operation}':`, error); + } }; + // this useEffect is for updating currentChartDatasets with allXYValues in the state if values are added and then we filter them to remove duplicate values useEffect(() => { - if (!allCollections || !user) return; - const updateCollectionWhenCardChanged = async (card, collection) => { - try { - const updatedQuantity = card.quantity; - const updatedTotalPriceForCard = card.price * card.quantity; - const newCardValueWithUpdatedPrice = { - ...card, - quantity: updatedQuantity, - totalPrice: updatedTotalPriceForCard, - }; + if (selectedCollection?.chartData?.allXYValues?.length === 0) return; + setCurrentChartDataSets2(getFilteredData2(selectedCollection, 'all')); + }, [selectedCollection?.chartData?.allXYValues]); + // useEffect to ensure a collection is always selected + useEffect(() => { + if (!allCollections || allCollections?.length === 0) return; + fetchAndSetCollections(); + if (!selectedCollection) { + setSelectedCollection(allCollections[0]); + } + }, []); + // useEffect for updating cards + useEffect(() => { + if (collectionsFetched === true) { + const updateCollectionWhenCardChanged = async (card, collection) => { + try { + if (!card || !collection) { + throw new Error('Card or collection is undefined.'); + } - // Update collection locally - const updatedCollection = collection?.cards?.map((c) => - c?.card?.id === card.id ? newCardValueWithUpdatedPrice : c - ); + const updatedQuantity = card.quantity; + const updatedTotalPriceForCard = card.price * updatedQuantity; + const newCardValueWithUpdatedPrice = { + ...card, + quantity: updatedQuantity, + totalPrice: updatedTotalPriceForCard, + }; + // Update collection locally + const updatedCollection = collection.cards.map((c) => + c.card.id === card.id ? newCardValueWithUpdatedPrice : c + ); - console.log('UPDATED CO', updatedCollection); - // Reflect the change in the local state - updateCollectionData(updatedCollection); + // console.log('UPDATED CO', updatedCollection); - // Send update to server - handleCardOperation( - newCardValueWithUpdatedPrice, - 'update', - updatedCollection, - userId - ); - } catch (error) { - console.error( - `Error updating total price for card ID ${card.id}:`, - error - ); - } - }; + // Reflect the change in the local state + updateCollectionData(updatedCollection); - const processCollections = () => { - allCollections?.forEach((collection) => { - if (!collection?._id) { - console.error('No collectionId found in collection.'); - return; + // Send update to server + handleCardOperation( + newCardValueWithUpdatedPrice, + 'update', + updatedCollection, + userId + ); + } catch (error) { + console.error( + `Error updating total price for card ID ${card?.id}: ${error.message}`, + error + ); } - collection?.cards?.forEach((card) => { - const originalTotalPrice = card?.price * card?.quantity; - if (card?.totalPrice !== originalTotalPrice) { - updateCollectionWhenCardChanged(card, collection); - } - }); - }); - }; - - processCollections(); - }, []); - useEffect(() => { - const checkCardData = (card) => { - const fields = [ - // 'name', - // 'type', - // 'desc', - // 'atk', - // 'def', - // 'level', - // 'race', - // 'attribute', - 'card_images', - 'card_prices', - 'totalPrice', - 'price', - // 'card_sets', - - // Include other card fields as necessary - ]; - return fields.filter( - (field) => - !card[field] || - card[field] === 0 || - (Array.isArray(card[field]) && card[field].length === 0) - ); - }; + }; - const updateCardData = async (card) => { - try { - const cardId = card?.id; - const response = await axios.patch( - `${process.env.REACT_APP_SERVER}/api/cards/ygopro/${cardId}`, - { - id: cardId, - user: user, - card_images: card?.card_images, - card_prices: card?.card_prices, - card_sets: card?.card_sets, - atk: card.atk, - def: card.def, - level: card.level, - attribute: card.attribute, - name: card.name, - type: card.type, - desc: card.desc, - price: card?.card_prices[0].tcgplayer_price, - totalPrice: card?.card_prices[0].tcgplayer_price * card?.quantity, - // Include other card fields as necessary + const processCollections = () => { + allCollections.forEach((collection) => { + if (!collection?._id) { + console.error('No collectionId found in collection.'); + return; } - ); - return response.data.data; - } catch (error) { - console.error('Error updating card:', card.id, error); - return null; - } - }; - - const processCollections = async () => { - for (const collection of allCollections) { - for (const card of collection.cards) { - const missingData = checkCardData(card); - if (missingData?.length > 0) { - console.log( - `Card ID ${card?.id} is missing: ${missingData.join(', ')}` - ); - const updatedCardData = await updateCardData(card); - if (updatedCardData) { - // Update the card in the corresponding collection - handleCardOperation( - updatedCardData, - 'update', - collection, - userId - ); // This function needs to be defined to handle updating the card within the state or context + collection?.cards?.forEach((card) => { + if (!card) { + console.warn('Card in collection is undefined.'); + return; } - } - } - } - }; - - processCollections(); - }, [allCollections, userId]); // Add other dependencies as needed - useEffect(() => { - // this useEffect is for updating currentChartDatasets with allXYValues in the state if values are added and then we filter them to remove duplicate values - if (!selectedCollection?.chartData?.allXYValues) return; - setCurrentChartDataSets2( - getUniqueFilteredXYValues(selectedCollection?.chartData?.allXYValues) - ); - }, [selectedCollection?.chartData?.allXYValues]); - - // Function to compare and log changes in collections - // useEffect(() => { - // const compareAndLogChanges = (oldData, newData, collectionName) => { - // const report = {}; - // for (const key in newData) { - // if (JSON.stringify(oldData[key]) !== JSON.stringify(newData[key])) { - // report[key] = { - // oldValue: oldData[key], - // newValue: newData[key], - // }; - // } - // } - // console.log(`Changes in ${collectionName}:`, report); - // }; - - // compareAndLogChanges( - // prevAllCollectionsRef.current, - // allCollections, - // 'All Collections' - // ); - // compareAndLogChanges( - // prevSelectedCollectionRef.current, - // selectedCollection, - // 'Selected Collection' - // ); - // compareAndLogChanges( - // prevCollectionDataRef.current, - // collectionData, - // 'Collection Data' - // ); + const originalTotalPrice = card.price * card.quantity; + if (card.totalPrice !== originalTotalPrice) { + updateCollectionWhenCardChanged(card, collection); + } + }); + }); + }; - // // Update refs with the current state for the next comparison - // prevAllCollectionsRef.current = allCollections; - // prevSelectedCollectionRef.current = selectedCollection; - // prevCollectionDataRef.current = collectionData; - // }, [allCollections, selectedCollection, collectionData]); - useEffect(() => { - if (!userId || !allCollections) return; - if (selectedCollection?.cards) { - setTotalPrice(calculateCollectionValue(selectedCollection)); - setTotalCost(getTotalCost(selectedCollection)); + processCollections(); } - }, [ - allCollections, - selectedCollection, - totalPrice, - totalCost, - setTotalPrice, - setTotalCost, - ]); - + setCollectionsFetched(false); + setCardsUpdated(true); + }); + // useEffect for updating collections + // useEffect(() => { + // if (!userId || !allCollections) return; + // if (cardsUpdated === true) { + // setTotalPrice(calculateCollectionValue(selectedCollection)); + // setTotalQuantity( + // getTotalQuantityOfSelectedCollection(selectedCollection) + // ); + // // setCurrentChartDataSets2(getFilteredData2(selectedCollection, 'all')); + // setLastSavedPrice({ + // num: selectedCollection?.lastSavedPrice?.num || 0, + // timestamp: new Date(), + // }); + // setLatestPrice({ + // num: selectedCollection?.totalPrice || 0, + // timestamp: new Date(), + // }); + // setCollectionPriceHistory( + // getUpdatedCollectionPriceHistory( + // selectedCollection, + // selectedCollection?.totalPrice || 0 + // ) + // ); + // } + // setCardsUpdated(false); + // }, [ + // getUpdatedCollectionData, + // getUpdatedCollectionPriceHistory, + // selectedCollection?.cards, + // selectedCollection?.totalQuantity, + // selectedCollection?.totalPrice, + // selectedCollection?.latestPrice, + // selectedCollection?.lastSavedPrice, + // selectedCollection?.chartData?.allXYValues, + // cardsUpdated, + // ]); const contextValue = useMemo( () => ({ allCollections, selectedCollection, collectionData, - currentChartDataSets2, - totalCost, - totalPrice, - totalQuantity: selectedCollection?.totalQuantity || 0, - allCardPrices: selectedCollection?.allCardPrices || [], - xys: xyData || [], - openChooseCollectionDialog, + cards: selectedCollection?.cards, + currentChartDataSets2: selectedCollection?.currentChartDataSets2, + totalPrice: selectedCollection?.totalPrice, + totalQuantity: selectedCollection?.totalQuantity, + latestPrice: selectedCollection?.latestPrice, + lastSavedPrice: selectedCollection?.lastSavedPrice, + collectionPriceHistory: selectedCollection?.collectionPriceHistory || [], + allXYValues: selectedCollection?.chartData?.allXYValues || [], + setCurrentChartData2: (data) => setCurrentChartDataSets2(data), calculateCollectionValue, setTotalPrice, setXyData, setUpdatedPricesFromCombinedContext, - setOpenChooseCollectionDialog, - getTotalPrice2: () => getCardPrice(selectedCollection), - - getTotalPrice: () => calculateCollectionValue(selectedCollection), - getNewTotalPrice: (values) => calculateCollectionValue(values), - getTotalCost: () => getTotalCost(selectedCollection), - getCardQuantity: (cardId) => - selectedCollection?.cards?.find((c) => c?.id === cardId)?.quantity || 0, - createUserCollection, - removeCollection, - addOneToCollection: (card) => - handleCardOperation(card, 'add', selectedCollection, userId), - removeOneFromCollection: (card) => - handleCardOperation(card, 'remove', selectedCollection, userId), - updateOneFromCollection: (card) => - handleCardOperation(card, 'update', selectedCollection, userId), - updateCollection: (card, operation, collection) => - handleCardOperation(card, operation, collection, userId), getUpdatedCollection, updateCollectionState: updateCollectionData, updateCollectionDetails, fetchAllCollectionsForUser: fetchAndSetCollections, - // fetchAllCollections: fetchAndSetCollections, setSelectedCollection, setAllCollections, + createUserCollection, + removeCollection, + getTotalPrice: () => calculateCollectionValue(selectedCollection), + getNewTotalPrice: (values) => calculateCollectionValue(values), + getCardQuantity: (cardId) => + selectedCollection?.cards?.find((c) => c?.id === cardId)?.quantity || 0, + addOneToCollection: (card, collection) => + handleCardOperation(card, 'add', collection, userId), + removeOneFromCollection: (card, collection) => + handleCardOperation(card, 'remove', collection, userId), + updateOneFromCollection: (card, collection) => + handleCardOperation(card, 'update', collection, userId), + updateCollection: (card, operation, collection) => + handleCardOperation(card, operation, collection, userId), }), - [allCollections, selectedCollection, totalCost, totalPrice, xyData] + [allCollections, selectedCollection, totalPrice, xyData] ); useEffect(() => { console.log('COLLECTION CONTEXT:', { - totalCost, - totalPrice, - totalQuantity: selectedCollection?.totalQuantity || 0, - selectedCollection, - allCollections, - collectionData, - updatedPricesFromCombinedContext, - xyData, + selectedCollection: contextValue.selectedCollection, + allCollections: contextValue.allCollections, + collectionData: contextValue.collectionData, + + cards: contextValue.cards, + totalPrice: contextValue.totalPrice, + totalQuantity: contextValue.totalQuantity, + currentChartDataSets2: contextValue.currentChartDataSets2, + collectionPriceHistory: contextValue.collectionPriceHistory, + lastSavedPrice: contextValue.lastSavedPrice, + latestPrice: contextValue.latestPrice, + allXYValues: contextValue.allXYValues, }); - }, []); + }, [selectedCollection]); useEffect(() => { - if (!userId || !allCollections || allCollections?.length === 0) return; + if (!userId) return; fetchAndSetCollections(); }, [userId]); @@ -789,331 +572,123 @@ export const useCollectionStore = () => { return context; }; -// const getUpdatedCards = (collection, cardUpdate, operation) => { -// let cardsToUpdate; - -// switch (operation) { -// case 'add': -// cardsToUpdate = handleCardAddition(collection?.cards, cardUpdate); -// break; -// case 'remove': -// cardsToUpdate = handleCardRemoval(collection?.cards, cardUpdate); -// console.log('CARD REMOVAL:', cardUpdate); -// console.log('CARD REMOVAL:', cardsToUpdate); -// break; -// case 'update': -// if (!collection?.cards) { -// console.error('No cards found in the collection.'); -// return collection?.cards; -// } -// if (!cardUpdate?.id) { -// console.warn('Card ID is missing.', cardUpdate); -// } -// // eslint-disable-next-line no-case-declarations -// const cards = collection?.cards; +// ! This is the old code +// useEffect(() => { +// const checkCardData = (card) => { +// const fields = [ +// // 'name', +// // 'type', +// // 'desc', +// // 'atk', +// // 'def', +// // 'level', +// // 'race', +// // 'attribute', +// 'card_images', +// 'card_prices', +// 'totalPrice', +// 'price', +// // 'card_sets', + +// // Include other card fields as necessary +// ]; +// return fields.filter( +// (field) => +// !card[field] || +// card[field] === 0 || +// (Array.isArray(card[field]) && card[field].length === 0) +// ); +// }; -// for (let i = 0; i < cards?.length; i++) { -// // eslint-disable-next-line no-case-declarations -// if (!cards[i]?.id) { -// console.warn('Card ID is missing.', cards[i]); -// continue; +// const updateCardData = async (card) => { +// try { +// const cardId = card?.id; +// const response = await axios.patch( +// `${process.env.REACT_APP_SERVER}/api/cards/ygopro/${cardId}`, +// { +// id: cardId, +// user: user, +// card_images: card?.card_images, +// card_prices: card?.card_prices, +// card_sets: card?.card_sets, +// atk: card.atk, +// def: card.def, +// level: card.level, +// attribute: card.attribute, +// name: card.name, +// type: card.type, +// desc: card.desc, +// price: card?.card_prices[0].tcgplayer_price, +// totalPrice: card?.card_prices[0].tcgplayer_price * card?.quantity, +// // Include other card fields as necessary // } -// cardUpdate = cards[i]; -// const cardIndex = selectedCollection?.cards?.findIndex( -// (c) => c?.id === cardUpdate?.id -// ); +// ); +// return response.data.data; +// } catch (error) { +// console.error('Error updating card:', card.id, error); +// return null; +// } +// }; -// if (cardIndex === -1) { -// console.error( -// 'Card not found in the collection.', -// collection?.cards[cardIndex] +// const processCollections = async () => { +// for (const collection of allCollections) { +// for (const card of collection.cards) { +// const missingData = checkCardData(card); +// if (missingData?.length > 0) { +// console.log( +// `Card ID ${card?.id} is missing: ${missingData.join(', ')}` // ); -// return collection?.cards; +// const updatedCardData = await updateCardData(card); +// if (updatedCardData) { +// // Update the card in the corresponding collection +// handleCardOperation( +// updatedCardData, +// 'update', +// collection, +// userId +// ); // This function needs to be defined to handle updating the card within the state or context +// } // } - -// // eslint-disable-next-line no-case-declarations -// const existingCard = collection?.cards[cardIndex]; -// // eslint-disable-next-line no-case-declarations -// const updatedPriceHistory = updatePriceHistory( -// existingCard, -// cardUpdate -// ); -// // eslint-disable-next-line no-case-declarations -// const updatedCard = getUpdatedCard( -// existingCard, -// cardUpdate, -// updatedPriceHistory, -// collection?._id -// ); -// cardsToUpdate = replaceCardInArray( -// collection?.cards, -// updatedCard, -// cardIndex -// ); // } -// break; -// default: -// console.error('Unsupported operation:', operation); -// return collection?.cards; -// } - -// return cardsToUpdate; -// }; - -// function getUpdatedCard(card, update, priceHistory, collectionId) { -// const cardPrice = determineCardPrice(card, update); -// const newChartDataEntry = createChartDataEntry(totalPrice); - -// return { -// ...card, -// price: cardPrice, -// quantity: update.quantity || card.quantity, -// collectionId: collectionId, -// totalPrice: cardPrice * (update?.quantity || card?.quantity), -// // totalPrice: cardPrice * (update.quantity || card.quantity), -// // lastSavedPrice: update.lastSavedPrice, -// lastSavedPrice: { -// num: card.price || card.card_prices[0].tcgplayer_price, -// timestamp: new Date(), -// }, -// latestPrice: update.latestPrice, -// tag: 'monitored', -// chart_datasets: [...(card.chart_datasets || []), newChartDataEntry], -// card_prices: update.card_prices, -// card_sets: update.card_sets, -// card_images: update.card_images, -// priceHistory: priceHistory, -// }; -// } -// const getUpdatedCollectionData = ( -// collectionWithCards, -// updatedTotalPrice, -// newCollectionPriceHistoryObject, -// updatedChartData, -// updatedTotalQuantity, -// updatedCards -// ) => { -// // Check for null or undefined collectionWithCards -// if (!collectionWithCards) { -// console.error('No collection data provided'); -// return null; // or an appropriate default object -// } - -// const { -// allCardPrices = [], -// description = '', -// name = '', -// // _id = '', -// collectionPriceHistory = [], -// cards = [], -// } = collectionWithCards; - -// return { -// allCardPrices, -// description, -// name, -// userId: userId, // Make sure 'userId' is defined in the scope -// totalPrice: updatedTotalPrice || 0, -// totalCost: getTotalCost(collectionWithCards), -// // totalCost: updatedTotalPrice ? updatedTotalPrice?.toString() : '0', -// totalQuantity: cards?.reduce( -// (acc, card) => acc + (card?.quantity || 0), -// 0 -// ), -// quantity: cards?.length, -// lastSavedPrice: { -// num: collectionWithCards?.totalPrice || 0, -// timestamp: collectionWithCards?.lastSavedPrice?.timeStamp || new Date(), -// }, -// latestPrice: { -// num: updatedTotalPrice || 0, -// timestamp: new Date(), -// }, -// dailyPriceChange: -// getPriceChange(currentChartDataSets2)[0]?.priceChange || '', -// currentChartDataSets2: filterUniqueDataPoints( -// transformPriceHistoryToXY(collectionPriceHistory) -// ), -// collectionPriceHistory: [ -// ...collectionPriceHistory, -// newCollectionPriceHistoryObject, -// ], -// }; -// }; -// const getUpdatedCollection = async ( -// collectionWithCards, // updated cards -// cardUpdate, // updated card -// operation, -// userId -// ) => { -// const collectionId = collectionWithCards?._id || collectionData?._id; -// if (!collectionId) { -// console.error('Collection ID is missing.', collectionId); -// return; -// } - -// if (!userId) { -// console.error('User ID is missing.', userId); -// return; -// } -// const cardExists = collectionWithCards?.cards?.some( -// (card) => card?.id === cardUpdate?.id -// ); - -// let multipleOfSameCard = []; -// let cardQuantity = 0; -// if (cardExists) { -// multipleOfSameCard = collectionWithCards?.cards?.filter( -// (card) => card?.id === cardUpdate?.id -// ); -// cardQuantity = multipleOfSameCard[0]?.quantity; -// } -// console.log('MULTIPLE OF SAME CARD:', multipleOfSameCard); -// console.log('CARD QUANTITY:', cardQuantity); -// console.log('CARD EXISTS:', cardExists); - -// let method; -// if (operation === 'remove' && cardQuantity === 1) { -// method = 'DELETE'; -// } else if (cardExists) { -// method = 'PUT'; -// } else { -// method = 'POST'; -// } - -// let endpointSuffix; -// if (operation === 'remove' && cardQuantity === 1) { -// endpointSuffix = 'removeCards'; -// } else { -// endpointSuffix = 'updateCards'; -// } - -// const endpoint = createApiUrl( -// `${userId}/collections/${collectionId}/${endpointSuffix}` -// ); -// console.log('CARDS BEFORE: ', collectionWithCards); -// const updatedCards = getUpdatedCards( -// collectionWithCards, -// cardUpdate, -// operation -// // collectionId -// ); -// // console.log('CARDS AFTER: ', updatedCards); -// // Call the function to get differences in cards - -// const updatedTotalPrice = calculateCollectionValue(updatedCards); -// setTotalPrice(updatedTotalPrice); - -// // const updatedTotalPrice = updatedCards.reduce( -// // (total, card) => total + card.price * card.quantity, -// // 0 -// // ); -// const updatedTotalQuantity = updatedCards?.reduce( -// (total, card) => total + card?.quantity, -// 0 -// ); -// const newCollectionPriceHistoryObject = -// createPriceHistoryObject(updatedTotalPrice); - -// let cardsResponse; -// let cardsPayload; -// if (operation === 'remove') { -// const allCardsWithIds = []; -// for (const card of updatedCards) { -// // const cardIds = updatedCards.map((card) => card.id); -// // const cardObjIds = updatedCards.map((card) => card._id); -// const cardIds = { -// id: card?.id, -// _id: card?._id, -// }; - -// allCardsWithIds?.push(cardIds); // } -// const removeCard = allCardsWithIds?.find( -// (idPair) => idPair?.id === cardUpdate?.id -// ); -// cardsPayload = { cardIds: removeCard }; -// } else { -// const allCardsWithIds = []; -// for (const card of updatedCards) { -// // const cardIds = updatedCards.map((card) => card.id); -// // const cardObjIds = updatedCards.map((card) => card._id); -// const cardIds = { -// id: card.id, -// _id: card._id, -// }; +// }; -// allCardsWithIds?.push(cardIds); +// processCollections(); +// }, [allCollections, userId]); // Add other dependencies as needed + +// Function to compare and log changes in collections +// useEffect(() => { +// const compareAndLogChanges = (oldData, newData, collectionName) => { +// const report = {}; +// for (const key in newData) { +// if (JSON.stringify(oldData[key]) !== JSON.stringify(newData[key])) { +// report[key] = { +// oldValue: oldData[key], +// newValue: newData[key], +// }; +// } // } -// const removeCard = allCardsWithIds?.find( -// (idPair) => idPair?.id === cardUpdate?.id -// ); -// cardsPayload = { cards: updatedCards, cardIds: removeCard }; -// } -// console.log('CARDS PAYLOAD:', cardsPayload); - -// 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); +// console.log(`Changes in ${collectionName}:`, report); +// }; -// const updatedChartData = getFilteredChartData( -// collectionWithCards.chartData, -// updatedTotalPrice -// ); -// const chartDataPayload = { chartData: updatedChartData }; -// const chartDataEndpoint = createApiUrl( -// `${userId}/collections/${collectionId}/updateChartData` +// compareAndLogChanges( +// prevAllCollectionsRef.current, +// allCollections, +// 'All Collections' // ); -// const chartDataResponse = await fetchWrapper( -// chartDataEndpoint, -// 'PUT', -// chartDataPayload -// ); - -// const { chartMessage } = chartDataResponse; - -// const updatedCollection = getUpdatedCollectionData( +// compareAndLogChanges( +// prevSelectedCollectionRef.current, // selectedCollection, -// updatedTotalPrice, -// newCollectionPriceHistoryObject, -// // updatedChartData, -// updatedTotalQuantity -// // updatedCards +// 'Selected Collection' // ); - -// const collectionEndpoint = createApiUrl( -// `${userId}/collections/${collectionId}` +// compareAndLogChanges( +// prevCollectionDataRef.current, +// collectionData, +// 'Collection Data' // ); -// const collectionResponse = await fetchWrapper(collectionEndpoint, 'PUT', { -// updatedCollection, -// }); -// const { collectionMessage } = collectionResponse; - -// setTotalPrice(calculateCollectionValue(updatedCards)); -// const restructuredCollection = { -// ...collectionResponse.collectionData, -// 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 { -// filteredRestructuredCollection, -// }; -// }; +// // Update refs with the current state for the next comparison +// prevAllCollectionsRef.current = allCollections; +// prevSelectedCollectionRef.current = selectedCollection; +// prevCollectionDataRef.current = collectionData; +// }, [allCollections, selectedCollection, collectionData]); diff --git a/src/context/CollectionContext/collectionUtility.jsx b/src/context/CollectionContext/collectionUtility.jsx deleted file mode 100644 index 33f21c6..0000000 --- a/src/context/CollectionContext/collectionUtility.jsx +++ /dev/null @@ -1,508 +0,0 @@ -/* eslint-disable @typescript-eslint/no-empty-function */ -const initialCollectionState = { - userId: '', // Assuming this is an ObjectId string - name: '', // Initialize as empty string if not provided - description: '', // Initialize as empty string if not provided - totalCost: '', // Initialize as empty string if not provided - totalPrice: 0, // Initialize as 0 if not provided - quantity: 0, // Initialize as 0 if not provided - totalQuantity: 0, // Initialize as 0 if not provided - previousDayTotalPrice: 0, // Initialize as 0 if not provided - lastSavedPrice: { - num: 0, - timestamp: '', - }, // Initialize as 0 if not provided - latestPrice: { - num: 0, - timestamp: '', - }, // Initialize as 0 if not provided - dailyPriceChange: 0, // Initialize as 0 if not provided - priceDifference: 0, // Initialize as 0 if not provided - priceChange: 0, // Initialize as 0 if not provided - allCardPrices: [], // Initialize as empty array if not provided - cards: [], // Initialize as empty array if not provided - currentChartDataSets2: [], // Initialize as empty array if not provided - xys: [], // Use defaultXyData or initialize as empty if not provided - chartData: { - name: '', // Initialize as empty string if not provided - userId: '', // Assuming this is an ObjectId string - datasets: [], // Initialize as empty array if not provided - xys: [], // Initialize as empty array if not provided - allXYValues: [], // Initialize as empty array if not provided - }, -}; - -/** - * Transforms the given chartData into an array of x-y points. - * @param {Object} chartData - Chart data object. - * @returns {Array} Transformed data. - */ -const transformChartData = (chartData) => { - const pointsArray = []; - - if (Array.isArray(chartData?.datasets)) { - chartData?.datasets?.forEach((dataset) => { - dataset.data?.forEach((dataEntry) => { - dataEntry.xys?.forEach((xyEntry) => { - const { x, y } = xyEntry.data; - if (x && y !== undefined) { - pointsArray.push({ x, y }); - } - }); - }); - }); - } - - return pointsArray; -}; - -/** - * Converts the given original data into a Nivo-compatible format. - * @param {Object} originalData - Original data object. - * @returns {Object} Converted data. - */ -const convertData = (originalData) => { - const finalDataForChart = []; - const { datasets } = originalData; - - if (Array.isArray(datasets) && datasets.length > 0) { - datasets.forEach((dataset, index) => { - if (Array.isArray(dataset.data) && dataset.data.length > 0) { - dataset.data.forEach((dataEntry) => { - dataEntry.xys?.forEach((xyEntry) => { - const { label, data } = xyEntry; - finalDataForChart[label] = finalDataForChart[label] || []; - - data.forEach(({ x, y }) => { - if (x && y !== undefined) { - finalDataForChart[label].push({ x, y }); - } - }); - }); - }); - } - }); - } - - const nivoData = Object.keys(finalDataForChart).map((label) => ({ - id: label, - data: finalDataForChart[label], - })); - - return { - ...originalData, - finalDataForChart: nivoData, - }; -}; - -/** - * Checks if the given object is empty. - * @param {Object} obj - Object to check. - * @returns {Boolean} True if the object is empty, false otherwise. - */ -const isEmpty = (obj) => { - return ( - [Object, Array].includes((obj || {}).constructor) && - !Object.entries(obj || {}).length - ); -}; - -/** - * Validates the given data based on its type and emptiness. - * @param {any} data - Data to validate. - * @param {String} eventName - Event that triggered the function. - * @param {String} functionName - Name of the function. - * @returns {Boolean} True if the data is valid, false otherwise. - */ -const validateData = (data, eventName, functionName) => { - if (typeof data === 'object') { - if (isEmpty(data)) { - console.error( - `The data passed to ${functionName} from ${eventName} is empty.` - ); - return false; - } - return true; - } - console.error( - `The data passed to ${functionName} from ${eventName} is not an object.` - ); - return false; -}; - -/** - * Calculates the total price from an array of card prices. - * @param {Array} allCardPrices - Array of card prices. - * @returns {Number} Total price. - */ -const calculateTotalFromAllCardPrices = (allCardPrices) => { - if (!Array.isArray(allCardPrices)) return 0; - return allCardPrices.reduce( - (total, price) => total + ensureNumber(price, 0), - 0 - ); -}; - -/** - * Ensures a value is a number, providing a default if not. - * @param {any} value - Value to check. - * @param {Number} defaultValue - Default value if check fails. - * @returns {Number} Ensured number. - */ -const ensureNumber = (value, defaultValue = 0) => { - const num = parseFloat(value); - return isNaN(num) ? defaultValue : num; -}; - -/** - * Finds the index of a collection by its ID. - * @param {Array} collections - Array of collections. - * @param {String} id - ID of the collection to find. - * @returns {Number} Index of the collection, or -1 if not found. - */ -const findCollectionIndex = (collections, id) => - collections?.findIndex((collection) => collection?._id === id) ?? -1; - -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) || card.price; - - if (!cardPrice) { - console.error( - `Failed to get price for card: ${card.name} (ID: ${card.id})` - ); - } - return total + cardPrice * card.quantity; - }, 0); -}; -const defaultContextValue = { - allCollections: [], - allCardPrices: [], - xy: [], - selectedCollection: {}, - collectionData: initialCollectionState, - officialCollectionDatasets: [], - totalCost: 0, - openChooseCollectionDialog: false, - updatedPricesFromCombinedContext: {}, - setUpdatedPricesFromCombinedContext: () => {}, - // eslint-disable-next-line @typescript-eslint/no-empty-function - setOpenChooseCollectionDialog: () => {}, - updateCollection: () => {}, - calculateTotalPrice: () => {}, - getTotalCost: () => {}, - getNewTotalPrice: () => {}, - getTotalPrice: () => {}, - createUserCollection: () => {}, - removeCollection: () => {}, - fetchAllCollectionsForUser: () => {}, - setSelectedCollection: () => {}, - setAllCollections: () => {}, - addOneToCollection: () => {}, - removeOneFromCollection: () => {}, -}; - -const logError = (source, action, error) => { - console.error( - `[${source.toUpperCase()}] Failed to ${action}: ${error.message}` - ); -}; - -const validateUserIdAndData = (userId, data, actionDescription) => { - if (!userId) { - logError( - 'validateUserIdAndData', - actionDescription, - new Error('User ID is undefined.') - ); - return false; - } - if (!validateData(data, actionDescription, actionDescription)) { - logError( - 'validateUserIdAndData', - actionDescription, - new Error('Validation failed for collection data.') - ); - return false; - } - return true; -}; - -const createPayload = (info) => { - console.log('INFO:', info); - return { - ...info, - userId: info.userId, - name: info.name, - description: info.description, - totalCost: info.totalCost || '', - totalPrice: info.totalPrice || 0, - quantity: info.quantity || 0, - totalQuantity: info.totalQuantity || 0, - previousDayTotalPrice: info.previousDayTotalPrice || 0, - dailyPriceChange: info.dailyPriceChange || 0, - priceDifference: info.priceDifference || 0, - priceChange: info.priceChange || 0, - collectionPriceHistory: info.collectionPriceHistory || [], - allCardPrices: info.allCardPrices || [], - cards: info.cards || [], - currentChartDataSets: info.currentChartDataSets || [], - xys: info.xys || [], - chartData: { - name: info.chartData?.name || `Chart for ${info.name || 'Collection'}`, - userId: info.chartData?.userId || info.userId, - datasets: info.chartData?.datasets || [], - allXYValues: info.chartData?.allXYValues || [], - xys: info.chartData?.xys || [], - }, - }; -}; - -const removeDuplicateCollections = (collections) => { - const uniqueCollections = {}; - collections?.forEach((collection) => { - uniqueCollections[collection._id] = collection; - }); - return Object.values(uniqueCollections); -}; - -const constructPayloadWithDifferences = ( - existingData, - newData, - debug = false -) => { - const payload = {}; - let logContent = '[constructPayloadWithDifferences] Differences in data:\n'; - let typeMismatchContent = ''; // String to store type mismatch messages - let nonMatchingKeys = []; // List to store non-matching keys - - Object.keys(newData).forEach((key) => { - const isTypeDifferent = typeof newData[key] !== typeof existingData[key]; - const isValueDifferent = newData[key] !== existingData[key]; - - if (isValueDifferent || isTypeDifferent) { - payload[key] = newData[key]; - nonMatchingKeys.push(key); // Add the non-matching key to the list - - if (debug) { - if (isTypeDifferent) { - typeMismatchContent += ` - Field "${key}": Expected Type: ${typeof existingData[ - key - ]}, Received Type: ${typeof newData[key]}\n`; - } - if (isValueDifferent) { - logContent += ` - Field "${key}": Old Value: ${JSON.stringify( - existingData[key] - )}, New Value: ${JSON.stringify(newData[key])}\n`; - } - } - } - }); - - if (debug) { - console.log('1. Constructing payload with differences:', logContent); - if (typeMismatchContent) { - console.log('2. Type mismatches found:', typeMismatchContent); - } - } - return { payload, nonMatchingKeys, typeMismatchContent }; // Return both the payload, the list of non-matching keys, and type mismatch messages -}; - -// function getCurrentChartDataSets(chartData) { -// if (!chartData || !chartData?.allXYValues) { -// console.error('Invalid or missing chart data'); -// return []; -// } - -// const currentChartDataSets = []; - -// // Iterate over each dataset -// chartData.allXYValues.forEach((val) => { -// // Check if dataset has 'data' array -// if (dataset.data && dataset.data.length > 0) { -// dataset.data.forEach((dataEntry) => { -// // Check if dataEntry has 'xys' array -// if (dataEntry.xys && dataEntry.xys.length > 0) { -// // Add both 'data' and 'label' from each 'xys' entry -// currentChartDataSets.push( -// ...dataEntry.xys.map((xy) => ({ -// ...xy.data, // Spread the 'data' object -// label: xy.label, // Include the 'label' -// })) -// ); -// } -// }); -// } -// }); - -// return currentChartDataSets; -// } - -// function getCurrentChartDataSets(chartData) { -// if (!chartData || !chartData.datasets) { -// console.error('Invalid or missing chart data'); -// return []; -// } - -// const currentChartDataSets = []; - -// // Iterate over each dataset -// chartData.datasets.forEach((dataset) => { -// // Check if dataset has 'data' array -// if (dataset.data && dataset.data.length > 0) { -// dataset.data.forEach((dataEntry) => { -// // Check if dataEntry has 'xys' array -// if (dataEntry.xys && dataEntry.xys.length > 0) { -// // Add both 'data' and 'label' from each 'xys' entry -// currentChartDataSets.push( -// ...dataEntry.xys.map((xy) => ({ -// ...xy.data, // Spread the 'data' object -// label: xy.label, // Include the 'label' -// })) -// ); -// } -// }); -// } -// }); - -// return currentChartDataSets; -// } - -const getAllCardPrices = (cards) => - cards.flatMap((card) => Array(card.quantity).fill(card.price)); - -const calculateCollectionValue = (cards) => { - if ( - !cards?.cards && - !Array.isArray(cards) && - !cards?.name && - !cards?.restructuredCollection - ) { - console.warn('Invalid or missing collection', cards); - return 0; - } - - if (cards?.tag === 'new') { - return 0; - } - if (cards?.restructuredCollection) { - return cards?.restructuredCollection?.cards.reduce((totalValue, card) => { - const cardPrice = card?.price || 0; - const cardQuantity = card?.quantity || 0; - return totalValue + cardPrice * cardQuantity; - }, 0); - } - if (cards?.cards && Array.isArray(cards?.cards)) { - return cards?.cards.reduce((totalValue, card) => { - const cardPrice = card?.price || 0; - const cardQuantity = card?.quantity || 0; - return totalValue + cardPrice * cardQuantity; - }, 0); - } - - return cards.reduce((totalValue, card) => { - const cardPrice = card.price || 0; - const cardQuantity = card.quantity || 0; - return totalValue + cardPrice * cardQuantity; - }, 0); -}; - -const getUpdatedChartData = (collection, newPrice) => { - const newXYValue = { - label: `Update - ${new Date().toISOString()}`, - x: new Date().toISOString(), - y: newPrice, - }; - console.log('Updating chart data with:', collection?.chartData?.allXYValues); - const allXYValues = collection?.chartData?.allXYValues || []; - console.log('ALL XY VALUES:', allXYValues); - return { - ...collection, - chartData: { - ...collection?.chartData, - allXYValues: [...(collection?.chartData?.allXYValues ?? []), newXYValue], - }, - totalPrice: newPrice, - }; -}; - -const mergeCards = (existingCards, updatedCards) => { - const updatedCardMap = new Map(updatedCards.map((card) => [card.id, card])); - return existingCards.map((card) => { - if (updatedCardMap.has(card.id)) { - return { - ...card, - ...updatedCardMap.get(card.id), - price: updatedCardMap.get(card.id).price || card.price, - quantity: updatedCardMap.get(card.id).quantity || card.quantity, - }; - } - return card; - }); -}; - -const updateCardInCollection = (cards, cardToUpdate) => { - // Validate that cards is an array - if (!Array.isArray(cards)) { - throw new TypeError('The first argument must be an array of cards.'); - } - - // Validate that cardToUpdate is an object - if (typeof cardToUpdate !== 'object' || cardToUpdate === null) { - throw new TypeError('The card to update must be an object.'); - } - - // Validate that cardToUpdate has an id property - if (!('id' in cardToUpdate)) { - throw new Error('The card to update must have an "id" property.'); - } - - try { - // Attempt to update the card within the collection - const updatedCards = cards.map( - (card) => - card.id === cardToUpdate.id ? { ...card, ...cardToUpdate } : card // Update the card if the id matches - ); - console.log('3. Updated cards in collection:', updatedCards); - return updatedCards; - } catch (error) { - console.error('3. Failed to update card in collection:', error); - throw error; - } -}; - -const getCardPrice = (collection) => - parseFloat(collection?.cards?.card_prices?.[0]?.tcgplayer_price || 0); - -module.exports = { - transformChartData, - convertData, - isEmpty, - validateData, - // handleCardAddition, - // handleCardRemoval, - calculateTotalFromAllCardPrices, - ensureNumber, - findCollectionIndex, - // fetchWrapper, - getTotalCost, - getCardPrice, - removeDuplicateCollections, - initialCollectionState, - defaultContextValue, - validateUserIdAndData, - // determineHttpMethod, - createPayload, - logError, - constructPayloadWithDifferences, - // getCurrentChartDataSets, - getUpdatedChartData, - mergeCards, - updateCardInCollection, - // canMakeRequest, - // updateLastRequestTime, - calculateCollectionValue, -}; diff --git a/src/context/CollectionContext/helpers.jsx b/src/context/CollectionContext/helpers.jsx index a13416e..615c53e 100644 --- a/src/context/CollectionContext/helpers.jsx +++ b/src/context/CollectionContext/helpers.jsx @@ -1,6 +1,70 @@ +/* eslint-disable @typescript-eslint/no-empty-function */ import moment from 'moment'; import { createApiUrl, fetchWrapper } from '../Helpers'; +export const initialCollectionState = { + userId: '', // Assuming this is an ObjectId string + name: '', // Initialize as empty string if not provided + description: '', // Initialize as empty string if not provided + totalPrice: 0, // Initialize as 0 if not provided + quantity: 0, // Initialize as 0 if not provided + totalQuantity: 0, // Initialize as 0 if not provided + previousDayTotalPrice: 0, // Initialize as 0 if not provided + lastSavedPrice: { + num: 0, + timestamp: '', + }, // Initialize as 0 if not provided + latestPrice: { + num: 0, + timestamp: '', + }, // Initialize as 0 if not provided + dailyPriceChange: 0, // Initialize as 0 if not provided + priceDifference: 0, // Initialize as 0 if not provided + priceChange: 0, // Initialize as 0 if not provided + collectionPriceHistory: [], + cards: [], // Initialize as empty array if not provided + currentChartDataSets2: [], // Initialize as empty array if not provided + chartData: { + name: '', // Initialize as empty string if not provided + userId: '', // Assuming this is an ObjectId string + datasets: [], // Initialize as empty array if not provided + xys: [], // Initialize as empty array if not provided + allXYValues: [], // Initialize as empty array if not provided + }, +}; + +export const defaultContextValue = { + allCollections: [], + selectedCollection: {}, + collectionData: initialCollectionState, + + cards: [], + currentChartDataSets2: [], + totalPrice: 0, + totalQuantity: 0, + latestPrice: {}, + lastSavedPrice: {}, + collectionPriceHistory: [], + allXYValues: [], + setCurrentChartData2: () => {}, + calculateCollectionValue: () => {}, + setUpdatedPricesFromCombinedContext: () => {}, + setOpenChooseCollectionDialog: () => {}, + updateCollection: () => {}, + calculateTotalPrice: () => {}, + getTotalCost: () => {}, + getNewTotalPrice: () => {}, + getTotalPrice: () => {}, + createUserCollection: () => {}, + removeCollection: () => {}, + fetchAllCollectionsForUser: () => {}, + setSelectedCollection: () => {}, + setAllCollections: () => {}, + addOneToCollection: () => {}, + removeOneFromCollection: () => {}, + getCardQuantity: () => {}, +}; + export const transformPriceHistoryToXY = (collectionPriceHistory) => { return collectionPriceHistory?.map((entry) => ({ x: entry?.timestamp, // x represents the timestamp @@ -9,8 +73,66 @@ export const transformPriceHistoryToXY = (collectionPriceHistory) => { })); }; -export const getAllCardPrices = (cards) => - cards.flatMap((card) => Array(card.quantity).fill(card.price)); +export const logError = (source, action, error) => { + console.error( + `[${source.toUpperCase()}] Failed to ${action}: ${error.message}` + ); +}; + +/** + * Checks if the given object is empty. + * @param {Object} obj - Object to check. + * @returns {Boolean} True if the object is empty, false otherwise. + */ +export const isEmpty = (obj) => { + return ( + [Object, Array].includes((obj || {}).constructor) && + !Object.entries(obj || {}).length + ); +}; + +/** + * Validates the given data based on its type and emptiness. + * @param {any} data - Data to validate. + * @param {String} eventName - Event that triggered the function. + * @param {String} functionName - Name of the function. + * @returns {Boolean} True if the data is valid, false otherwise. + */ +export const validateData = (data, eventName, functionName) => { + if (typeof data === 'object') { + if (isEmpty(data)) { + console.error( + `The data passed to ${functionName} from ${eventName} is empty.` + ); + return false; + } + return true; + } + console.error( + `The data passed to ${functionName} from ${eventName} is not an object.` + ); + return false; +}; + +export const validateUserIdAndData = (userId, data, actionDescription) => { + if (!userId) { + logError( + 'validateUserIdAndData', + actionDescription, + new Error('User ID is undefined.') + ); + return false; + } + if (!validateData(data, actionDescription, actionDescription)) { + logError( + 'validateUserIdAndData', + actionDescription, + new Error('Validation failed for collection data.') + ); + return false; + } + return true; +}; export const filterUniqueDataPoints = (dataArray) => { const uniqueRecords = new Map(); @@ -32,19 +154,6 @@ export const filterUniqueDataPoints = (dataArray) => { * @example calculatePriceDifference(100, { totalPrice: 200 }); * calculatePriceDifference(100, { totalPrice: 100 }); **/ -export const determineCardPrice = (card, update) => { - let price = 0; - console.log('CARD UPDATE:', update); - if (card?.price) { - price = card?.price; - } - - if (update?.latestPrice?.num) { - price = update?.latestPrice?.num; - } - return price || card?.card_prices[0]?.tcgplayer_price; -}; - export const updatePriceHistory = (card, update) => { const newPriceHistoryEntry = createPriceHistoryObject( update?.latestPrice?.num @@ -68,12 +177,12 @@ export const createChartDataEntry = (price) => { }; }; -export const createPriceHistoryObject = (price) => { - return { - num: price, - timestamp: new Date(), - }; -}; +// export const createPriceHistoryObject = (price) => { +// return { +// num: price, +// timestamp: new Date(), +// }; +// }; export const getFilteredChartData = (chartData, updatedTotalPrice) => { const filteredChartData = { @@ -117,8 +226,8 @@ export const updateCollectionArray = (collections, newData) => { export const removeDuplicatesFromCollection = (collection) => { const uniqueCardsMap = new Map(); - - collection.cards.forEach((card) => { + if (!collection?.cards) return collection; + collection?.cards.forEach((card) => { const uniqueKey = `${card.id}-${card.name}`; if (!uniqueCardsMap.has(uniqueKey)) { uniqueCardsMap.set(uniqueKey, card); @@ -214,17 +323,13 @@ export const filterNullPriceHistoryForCollection = (collection) => { * @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); + const cardToAddId = String(cardToAdd.id); + const existingCard = currentCards.find((c) => c.id === cardToAddId); - if (matchingCard) { - matchingCard.quantity++; + // console.log('CURRENT CARDS', currentCards); + if (existingCard) { + existingCard.quantity++; + existingCard.totalPrice = existingCard.price * existingCard.quantity; return [...currentCards]; } @@ -238,35 +343,138 @@ export const handleCardAddition = (currentCards, cardToAdd) => { * @returns {Array} Updated array of cards. */ export const handleCardRemoval = (currentCards, cardToRemove) => { - // Initialize currentCards to an empty array if it's not defined - currentCards = currentCards || []; + const cardToRemoveId = String(cardToRemove.id); + const updatedCards = currentCards.map((card) => { + if (card.id === cardToRemoveId) { + return card.quantity > 1 + ? { + ...card, + quantity: card.quantity - 1, + totalPrice: card.totalPrice - card.price, + } + : null; + } + return card; + }); - console.log('CURRENT CARDS:', currentCards); - console.log('CARD TO REMOVE:', cardToRemove); + return updatedCards.filter((card) => card !== null); +}; - const cardToRemoveId = - typeof cardToRemove.id === 'number' - ? String(cardToRemove.id) - : cardToRemove.id; +/** + * Handles the updating of a card in the collection. + * @param {Array} currentCards - Current array of cards. + * @param {Object} cardToUpdate - Card object to update. + * @returns {Array} Updated array of cards. + * @example handleCardUpdate([{ id: 1, quantity: 1 }], { id: 1, quantity: 2 }); + **/ +export const handleCardUpdate = (cards, cardUpdate) => { + return cards.map((card) => { + if (card.id === cardUpdate.id) { + return getUpdatedCard(card, cardUpdate); + } + return card; + }); +}; +function getUpdatedCard(card, update, priceHistory, collectionId) { + console.log('CARD UPDATE:', update); + console.log('CARD:', card); + const cardPrice = determineCardPrice(card, update); + const totalPrice = cardPrice * (update?.quantity || card?.quantity); + const quantity = update?.quantity || card?.quantity || 1; + const newChartDataEntry = createChartDataEntry( + cardPrice * (update?.quantity || card?.quantity) + ); - // Find the card to remove in the current cards array - const cardIndex = currentCards.findIndex((c) => c.id === cardToRemoveId); + console.log('UPDATE QUANTITY: ', update.quantity); + console.log('CARD QUANTITY: ', card.quantity); + console.log('TOTAL PRICE: ', totalPrice); - if (cardIndex === -1) { - console.error('Card not found in the collection.'); - return [...currentCards]; + return { + ...card, + ...update, + price: cardPrice || card.price, + quantity: quantity, + collectionId: collectionId, + totalPrice: totalPrice, + lastSavedPrice: { + num: card.price || card.card_prices[0].tcgplayer_price, + timestamp: new Date(), + }, + latestPrice: update.latestPrice, + tag: 'monitored', + chart_datasets: [...(card.chart_datasets || []), newChartDataEntry], + card_prices: update.card_prices, + card_sets: update.card_sets, + card_images: update.card_images, + priceHistory: priceHistory, + }; +} +export const getUpdatedCollectionData = ( + collectionWithCards, + updatedTotalPrice, + updatedCollectionPriceHistory, + updatedTotalQuantity, + updatedCards, + userId +) => { + if (!collectionWithCards) { + console.error('No collection data provided'); + return null; } - 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); + const { + allCardPrices = [], + description = collectionWithCards.description || '', + name = collectionWithCards.name || '', + collectionPriceHistory = [ + ...collectionWithCards.collectionPriceHistory, + ...updatedCollectionPriceHistory, + ], // collectionPriceHistory is an array of objects with 'num' and 'timestamp' properties + chartData = collectionWithCards.chartData || {}, + cards = collectionWithCards.cards || [], + currentChartDataSets2 = getUniqueFilteredXYValues(chartData?.allXYValues) || + [], + } = collectionWithCards; + if (!Array.isArray(collectionPriceHistory)) { + console.error( + 'collectionPriceHistory is not an array', + collectionPriceHistory + ); + return; } + return { + allCardPrices, + description, + name, + userId: userId, + totalPrice: updatedTotalPrice, + totalQuantity: updatedTotalQuantity || 0, + quantity: cards?.length, + lastSavedPrice: { + num: collectionWithCards?.totalPrice || 0, + timestamp: new Date(), + }, + latestPrice: { + num: updatedTotalPrice || 0, + timestamp: new Date(), + }, + dailyPriceChange: '', + // getPriceChange(chartData)[0]?.priceChange || '', + currentChartDataSets2: currentChartDataSets2, + // filterUniqueDataPoints( + // chartData?.allXYValues + // // transformPriceHistoryToXY(chartData?.allXYValues) + // ), + collectionPriceHistory: updatedCollectionPriceHistory, + // collectionPriceHistory: [ + // ...collectionPriceHistory, + // newCollectionPriceHistoryObject || { + // num: updatedTotalPrice, + // timestamp: new Date(), + // }, + // ], + cards: updatedCards, + }; }; export const constructCardDifferencesPayload = ( @@ -531,3 +739,181 @@ export const createNewDataSet = (updatedPrice, selectedCollection) => { ], }; }; + +export const getTotalQuantityOfSelectedCollection = (selectedCollection) => { + if (!selectedCollection) return 'n/a'; + return selectedCollection?.cards?.reduce( + (total, card) => total + card.quantity, + 0 + ); +}; + +// export const getUpdatedCollectionPriceHistory = ( +// selectedCollection, +// updatedPrice +// ) => { +// const updatedPriceHistory = selectedCollection?.collectionPriceHistory || []; +// console.log( +// 'RETURN VAL OF: getUpdatedCollectionPriceHistory -----> ', +// updatedPriceHistory +// ); +// const lastPriceHistoryEntry = +// updatedPriceHistory[updatedPriceHistory?.length - 1]; + +// if (!lastPriceHistoryEntry || lastPriceHistoryEntry?.num !== updatedPrice) { +// console.log('RETURN VAL OF: getUpdatedCollectionPriceHistory -----> ', [ +// // ...selectedCollection?.collectionPriceHistory, +// ...updatedPriceHistory, +// createPriceHistoryObject(updatedPrice), +// ]); +// return [...updatedPriceHistory, createPriceHistoryObject(updatedPrice)]; +// } + +// console.log( +// 'RETURN VAL OF: getUpdatedCollectionPriceHistory -----> ', +// updatedPriceHistory +// ); +// return updatedPriceHistory; +// }; +export const createPriceHistoryObject = (price) => { + return { + num: price, + timestamp: new Date(), + }; +}; + +export const getUpdatedCollectionPriceHistory = ( + selectedCollection, + updatedPrice +) => { + const updatedPriceHistory = selectedCollection?.collectionPriceHistory || []; + return [...updatedPriceHistory, createPriceHistoryObject(updatedPrice)]; +}; + +export const getUniqueValidData = (currentChartData) => { + if (!Array.isArray(currentChartData)) { + console.error('Invalid input: currentChartData should be an array'); + return []; + } + + const uniqueLabels = new Set(); + const uniqueXValues = new Set(); + + return currentChartData + .filter((entry) => { + // Check if entry is valid, y is a number and not zero, and label is unique + return ( + entry && + typeof entry === 'object' && + typeof entry.y === 'number' && + entry.y !== 0 && + entry.y !== null && + entry.y !== undefined && + entry.label && + !uniqueLabels.has(entry.label) + ); + }) + .filter((entry) => { + // Check if x is present, not null, not undefined, and unique + const hasValidX = + entry && 'x' in entry && entry.x !== null && entry.x !== undefined; + if (hasValidX && !uniqueXValues.has(entry.x)) { + uniqueXValues.add(entry.x); + uniqueLabels.add(entry.label); + return true; + } + return false; + }) + .map((entry) => ({ + label: entry.label, + x: entry.x, + y: entry.y, + })); +}; + +export const getFilteredData2 = (collection, timeRange) => { + if (!collection) { + console.error('Invalid input: selectedCollection should not be null'); + return []; + } + return getUniqueValidData(collection?.chartData?.allXYValues || []); +}; + +export const calculateCollectionValue = (cards) => { + if ( + !cards?.cards && + !Array.isArray(cards) && + !cards?.name && + !cards?.restructuredCollection + ) { + console.warn('Invalid or missing collection', cards); + return 0; + } + + if (cards?.tag === 'new') { + return 0; + } + if (cards?.restructuredCollection) { + return cards?.restructuredCollection?.cards.reduce((totalValue, card) => { + const cardPrice = card?.price || 0; + const cardQuantity = card?.quantity || 0; + return totalValue + cardPrice * cardQuantity; + }, 0); + } + if (cards?.cards && Array.isArray(cards?.cards)) { + return cards?.cards.reduce((totalValue, card) => { + const cardPrice = card?.price || 0; + const cardQuantity = card?.quantity || 0; + return totalValue + cardPrice * cardQuantity; + }, 0); + } + + return cards.reduce((totalValue, card) => { + const cardPrice = card.price || 0; + const cardQuantity = card.quantity || 0; + return totalValue + cardPrice * cardQuantity; + }, 0); +}; + +/** + * Calculates the total price from an array of card prices. + * @param {Array} allCardPrices - Array of card prices. + * @returns {Number} Total price. + */ +export const calculateTotalFromAllCardPrices = (allCardPrices) => { + if (!Array.isArray(allCardPrices)) return 0; + return allCardPrices.reduce( + (total, price) => total + ensureNumber(price, 0), + 0 + ); +}; + +/** + * Ensures a value is a number, providing a default if not. + * @param {any} value - Value to check. + * @param {Number} defaultValue - Default value if check fails. + * @returns {Number} Ensured number. + */ +export const ensureNumber = (value, defaultValue = 0) => { + const num = parseFloat(value); + return isNaN(num) ? defaultValue : num; +}; + +export const getCardPrice = (collection) => + parseFloat(collection?.cards?.card_prices?.[0]?.tcgplayer_price || 0); + +export const getAllCardPrices = (cards) => + cards.flatMap((card) => Array(card.quantity).fill(card.price)); + +export const determineCardPrice = (card, update) => { + let price = 0; + // console.log('CARD UPDATE:', update); + if (card?.price) { + price = card?.price; + } + + if (update?.latestPrice?.num) { + price = update?.latestPrice?.num; + } + return price || card?.card_prices[0]?.tcgplayer_price; +}; diff --git a/src/context/ColorModeContext/ColorModeProvider.jsx b/src/context/ColorModeContext/ColorModeProvider.jsx index 0fd24a2..c1a9e9c 100644 --- a/src/context/ColorModeContext/ColorModeProvider.jsx +++ b/src/context/ColorModeContext/ColorModeProvider.jsx @@ -7,7 +7,6 @@ export const ColorModeContext = createContext({ mode: 'dark', colorMode: {}, theme: createTheme(themeSettings('dark')), // Default theme is dark mode - // eslint-disable-next-line @typescript-eslint/no-empty-function toggleColorMode: () => {}, }); diff --git a/src/context/CombinedContext/CombinedProvider.jsx b/src/context/CombinedContext/CombinedProvider.jsx index 6bb2820..e79de7f 100644 --- a/src/context/CombinedContext/CombinedProvider.jsx +++ b/src/context/CombinedContext/CombinedProvider.jsx @@ -130,10 +130,10 @@ export const CombinedProvider = ({ children }) => { setDataFunctions.eventsTriggered(data); }; - const handleStatusUpdatePrice = (data) => { - console.log('STATUS_UPDATE_PRICE:', data); - setDataFunctions.priceDifference(data); - }; + // const handleStatusUpdatePrice = (data) => { + // console.log('STATUS_UPDATE_PRICE:', data); + // setDataFunctions.priceDifference(data); + // }; const handleStatusUpdateCron = (newData) => { const { message, data } = newData; @@ -149,10 +149,10 @@ export const CombinedProvider = ({ children }) => { setDataFunctions.error(errorData); }; - const handleExistingCollectionData = (collectionData) => { - console.log('Existing collection data:', collectionData); - setDataFunctions.collectionData(collectionData); - }; + // const handleExistingCollectionData = (collectionData) => { + // console.log('Existing collection data:', collectionData); + // setDataFunctions.collectionData(collectionData); + // }; const handleCardPricesUpdated = async (priceData) => { console.log('Card prices retrieved:', priceData); @@ -232,10 +232,10 @@ export const CombinedProvider = ({ children }) => { setDataFunctions.allCardPrices(updatedListOfMonitoredCards); }; - const handleNoPricesChanged = () => { - console.log('No prices changed'); - // Perform any necessary actions when no prices have changed - }; + // const handleNoPricesChanged = () => { + // console.log('No prices changed'); + // // Perform any necessary actions when no prices have changed + // }; useEffect(() => { if (!socket) return; @@ -245,18 +245,18 @@ export const CombinedProvider = ({ children }) => { ['MESSAGE_TO_CLIENT', handleReceive], ['SIMULATION_CRON_PRICE_RESPONSE', handleSimulationPriceResponse], ['EVENT_RESPONSE', handleEventResponse], - ['STATUS_UPDATE_PRICE', handleStatusUpdatePrice], + // ['STATUS_UPDATE_PRICE', handleStatusUpdatePrice], ['STATUS_UPDATE_CRON', handleStatusUpdateCron], // ['CHART_CRON_RESPONSE', handleChartCronResponse], // ['HANDLE_CRON_JOB_RESPONSE', handleCronJobResponse], ['ERROR', handleError], // ['EMITTED_RESPONSES', handleEmittedResponses], // ['RESPONSE_CRON_DATA', handleCronJobTracker], - ['RESPONSE_EXISTING_COLLECTION_DATA', handleExistingCollectionData], + // ['RESPONSE_EXISTING_COLLECTION_DATA', handleExistingCollectionData], // ['RESPONSE_EXISTING_CHART_DATA', handleExistingChartData], // ['CHART_DATASETS_UPDATED', handleChartDatasetsUpdated], ['SEND_PRICING_DATA_TO_CLIENT', handleCardPricesUpdated], - ['NO_PRICE_CHANGES', handleNoPricesChanged], + // ['NO_PRICE_CHANGES', handleNoPricesChanged], // ['SEND_UPDATED_DATA_TO_CLIENT', handleNewCardDataObject], // ['SEND_FINAL_UPDATE_TO_CLIENT', handleFinalUpdateToClient], // [ diff --git a/src/context/CombinedContext/helpers.jsx b/src/context/CombinedContext/helpers.jsx index a46179c..9757c6c 100644 --- a/src/context/CombinedContext/helpers.jsx +++ b/src/context/CombinedContext/helpers.jsx @@ -44,7 +44,6 @@ export const generateListOfMonitoredCards = (allCollections) => { const originalCard = cardsWithCollectionId.find((card) => card?.id === id); return { ...originalCard, - priceHistory: originalCard?.priceHistory || [], }; }); }; @@ -55,12 +54,12 @@ export const updateCardPricesInList = (listOfMonitoredCards, cardPrices) => { // } return listOfMonitoredCards.map((originalCard) => { const updatedCardInfo = - cardPrices.find((price) => price.id === originalCard.id) || {}; + cardPrices?.find((price) => price.id === originalCard.id) || {}; // If latestPrice is different, update lastSavedPrice and priceHistory if (updatedCardInfo.latestPrice?.num !== originalCard.latestPrice?.num) { - console.log('ORIGINAL CARD: ', originalCard); - console.log('UPDATED CARD: ', updatedCardInfo); + // console.log('ORIGINAL CARD: ', originalCard); + // console.log('UPDATED CARD: ', updatedCardInfo); return { ...originalCard, ...updatedCardInfo, diff --git a/src/context/StatisticsContext/helpers.jsx b/src/context/StatisticsContext/helpers.jsx index 403cb75..4f4565a 100644 --- a/src/context/StatisticsContext/helpers.jsx +++ b/src/context/StatisticsContext/helpers.jsx @@ -45,8 +45,7 @@ export const calculatePriceChanges = (data) => { }; export const calculateStatistics = (data, timeRange) => { - if (!data || !Array.isArray(data.data) || data.data.length === 0) - return {} && console.log('data', data); + if (!data || !Array.isArray(data.data) || data.data.length === 0) return {}; const filteredData = data?.data?.filter( (item) => new Date(item?.x).getTime() >= Date.now() - timeRange diff --git a/src/pages/CartPage.js b/src/pages/CartPage.js index 3e5ec9d..3725424 100644 --- a/src/pages/CartPage.js +++ b/src/pages/CartPage.js @@ -1,13 +1,6 @@ import React, { useEffect } from 'react'; import { useCookies } from 'react-cookie'; -import { - Box, - Card, - CardContent, - Grid, - Typography, - useTheme, -} from '@mui/material'; +import { Box, Card, CardContent, Grid, useTheme } from '@mui/material'; import LoadingIndicator from '../components/reusable/indicators/LoadingIndicator'; import ErrorIndicator from '../components/reusable/indicators/ErrorIndicator'; import CustomerForm from '../components/forms/customerCheckoutForm/CustomerForm'; @@ -43,7 +36,7 @@ const CartPage = () => { setIsPageLoading(true); try { if (!cartData || Object.keys(cartData).length === 0) { - fetchUserCart(userId); + fetchUserCart(); } logPageData('CartPage', cartData); } catch (e) { @@ -54,14 +47,7 @@ const CartPage = () => { }; initializeCart(); - }, [ - userId, - cartData, - fetchUserCart, - logPageData, - setPageError, - setIsPageLoading, - ]); + }, [cartData?.cart]); const handleModifyItemInCart = async (cardId, operation) => { try { @@ -96,220 +82,9 @@ const CartPage = () => {
- {/* - - {hasItems ? ( - - - - ) : ( - - No items in the cart - - )} - {hasItems && ( - - - - )} - - */}
); }; 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 14f3880..3451d56 100644 --- a/src/pages/CollectionPage.js +++ b/src/pages/CollectionPage.js @@ -13,7 +13,6 @@ import { Paper } from '@mui/material'; const CollectionPage = () => { const { theme } = useMode(); const [isCollectionSelected, setIsCollectionSelected] = useState(false); - const [collectionContainer, setCollectionContainer] = useState(true); // [true, false const { allCollections, selectedCollection } = useCollectionStore(); const { isPageLoading, @@ -30,7 +29,6 @@ const CollectionPage = () => { useEffect(() => { try { - // Logic to handle collection data logPageData('CollectionPage', selectedCollection); // Log collection data } catch (e) { setPageError(e); // Handle any errors @@ -45,9 +43,6 @@ const CollectionPage = () => { const handleCollectionSelected = (selected) => { console.log('selected', selected); setIsCollectionSelected(!!selected); - if (selected) { - setCollectionContainer(false); - } }; return ( @@ -68,12 +63,10 @@ const CollectionPage = () => { flexDirection: 'column', justifyContent: 'center', alignItems: 'center', - // height: '100vh', width: '100%', backgroundColor: theme.palette.background.paper, boxShadow: theme.shadows[4], textAlign: 'center', - // padding: theme.spacing(2.5), }} > {!isCollectionSelected && ( @@ -82,7 +75,6 @@ const CollectionPage = () => { display: 'flex', flexDirection: 'column', alignItems: 'center', - // minHeight: '20%', minHeight: { xs: '17%', sm: '25%', @@ -108,15 +100,9 @@ const CollectionPage = () => { sx={{ display: 'flex', justifyContent: 'center', - // margin: '0 auto', - // flexDirection: 'column', - // alignItems: 'center', padding: theme.spacing(1.2), minWidth: 390, - // height: '100vh', width: '100%', - // background: '#333', - backgroundColor: theme.palette.background.main, }} > @@ -133,98 +119,8 @@ const CollectionPage = () => { /> )}
- {/* )} */} ); }; export default CollectionPage; -// return ( -// -// {collectionContainer && ( -// -// {!isCollectionSelected && ( -// -// {/* */} -// -// -// {/* */} -// -// )} - -// -// -// -// {isModalOpen && ( -// -// )} -// -// )} -// -// ); -// }; - -// export default CollectionPage; diff --git a/src/pages/DeckBuilderPage.js b/src/pages/DeckBuilderPage.js index 6207c53..5441b3f 100644 --- a/src/pages/DeckBuilderPage.js +++ b/src/pages/DeckBuilderPage.js @@ -1,16 +1,13 @@ import React, { useEffect, useState, useContext } from 'react'; -import { useCookies } from 'react-cookie'; -import { DeckContext, useDeckStore } from '../context/DeckContext/DeckContext'; +import { useDeckStore } from '../context/DeckContext/DeckContext'; import LoadingIndicator from '../components/reusable/indicators/LoadingIndicator'; import ErrorIndicator from '../components/reusable/indicators/ErrorIndicator'; import DeckBuilderContainer from '../containers/deckBuilderPageContainers/DeckBuilderContainer'; import { Box, Grid, Typography } from '@mui/material'; import { ModalContext } from '../context/ModalContext/ModalContext'; import GenericCardModal from '../components/modals/cardModal/GenericCardModal'; -import HeaderTitle from '../components/reusable/HeaderTitle'; import { useMode } from '../context/hooks/colormode'; import { DeckBuilderBanner } from './pageStyles/StyledComponents'; -import useUpdateAppContext from '../context/hooks/useUpdateContext'; import UserContext, { useUserContext, } from '../context/UserContext/UserContext'; @@ -41,54 +38,21 @@ const DeckBuilderPage = () => { useEffect(() => { if (allDecks && userId && typeof userId === 'string') { const filteredDecks = allDecks?.filter((deck) => deck?.userId === userId); - // console.log('filteredDecks', filteredDecks); - logPageData('DeckBuilderPage', filteredDecks); // Log the cart data - - // console.log('DECK PAGE (FILTERED_DECKS):', filteredDecks); - + logPageData('DeckBuilderPage', filteredDecks); setUserDecks(filteredDecks); } }, [userId]); - // 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 ( - {/* */} - diff --git a/src/pages/StorePage.js b/src/pages/StorePage.js index 3b25982..bd6968c 100644 --- a/src/pages/StorePage.js +++ b/src/pages/StorePage.js @@ -13,7 +13,7 @@ import { usePageContext } from '../context/PageContext/PageContext'; const StorePage = () => { const { theme } = useMode(); - const { fetchUserCart } = useCartStore(); + const { fetchUserCart, cartData } = useCartStore(); const { searchData, slicedSearchData, slicedAndMergedSearchData } = useCardStore(); const { user, setUser } = useUserContext(); @@ -27,29 +27,29 @@ const StorePage = () => { const userId = user?.id; - useEffect(() => { - const fetchData = async () => { - if (!userId) { - setIsPageLoading(false); - return; - } + // useEffect(() => { + // const fetchData = async () => { + // if (!userId) return; - setIsPageLoading(true); - try { - fetchUserCart(); - if (searchData && slicedAndMergedSearchData) { - logPageData('StorePage', slicedAndMergedSearchData); - } - } catch (error) { - console.error('Failed to get user cart', error); - setPageError(error); - } finally { - setIsPageLoading(false); - } - }; + // if (!cartData?.cart || cartData?.cart?.length === 0) { + // setIsPageLoading(true); + // // return; + // } + // try { + // // fetchUserCart(); + // if (searchData.length > 0 && slicedAndMergedSearchData !== null) { + // logPageData('StorePage', slicedAndMergedSearchData); + // } + // } catch (error) { + // console.error('Failed to get user cart', error); + // setPageError(error); + // } finally { + // setIsPageLoading(false); + // } + // }; - fetchData(); - }, [logPageData, searchData, setUser]); + // fetchData(); + // }, []); if (isPageLoading) return ; if (pageError) return ; diff --git a/src/pages/index.js b/src/pages/index.js index 48ee758..f0ce937 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -3,8 +3,8 @@ 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 NotFoundPage } from './otherPages/NotFoundPage'; export { default as CartPage } from './CartPage'; export { default as SplashPage } from './otherPages/SplashPage'; export { default as StorePage } from './StorePage'; -export { default as LoginPage } from './LoginPage'; +export { default as LoginPage } from './otherPages/LoginPage'; diff --git a/src/pages/LoginPage.jsx b/src/pages/otherPages/LoginPage.jsx similarity index 100% rename from src/pages/LoginPage.jsx rename to src/pages/otherPages/LoginPage.jsx diff --git a/src/pages/NotFoundPage.js b/src/pages/otherPages/NotFoundPage.js similarity index 100% rename from src/pages/NotFoundPage.js rename to src/pages/otherPages/NotFoundPage.js