Skip to content

Commit

Permalink
Refactor and optimize collection update mechanism
Browse files Browse the repository at this point in the history
- Enhanced PATCH endpoint in router to ensure comprehensive data integrity checks and preservation of key card attributes like quantity, priceHistory, and latestPrice.
- Implemented useEffect in context to automatically update local and server state when cards are added, removed, or their quantity changes in a collection.
- Improved cron job logic to trigger only when specific conditions are met, enhancing efficiency.
- Fixed issue with disappearing header title in the PortfolioContent component during chart re-renders.
  • Loading branch information
reedoooo committed Dec 2, 2023
1 parent e701a60 commit 3186d48
Show file tree
Hide file tree
Showing 19 changed files with 1,248 additions and 689 deletions.
10 changes: 10 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
// ThreeJsCube,
// CardDeckAnimation,
NotFoundPage,
LoginPage,
} from './pages';

import {
Expand Down Expand Up @@ -107,6 +108,14 @@ const App = () => {
}
}, [userId, fetchAllCollectionsForUser, fetchAllDecksForUser, fetchUserCart]);

useEffect(() => {
// if the user is redirected to the login page, show the login dialog and set the loading state to false
if (window.location.pathname === '/login') {
setShowLoginDialog(true);
setIsLoading(false);
}
}, []);

return (
<>
<Helmet>{/* Helmet Configuration */}</Helmet>
Expand Down Expand Up @@ -158,6 +167,7 @@ const App = () => {
}
/>
<Route path="/profile" element={<ProfilePage />} />
<Route path="/login" element={<LoginPage />} />
{/* <Route path="/threejs" element={<ThreeJsCube />} /> */}
{/* <Route path="/cardDeck" element={<CardDeckAnimation />} /> */}
<Route path="*" element={<NotFoundPage />} />{' '}
Expand Down
8 changes: 3 additions & 5 deletions src/components/buttons/actionButtons/CardActionButtons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ const CardActionButtons = ({
const isCardInContext = useCallback(() => {
switch (context) {
case 'Collection':
return !!selectedCollection?.cards?.find(
(c) => c?.card?.id === card?.id
);
return !!selectedCollection?.cards?.find((c) => c?.id === card?.id);
case 'Deck':
return !!selectedDeck?.cards?.find((c) => c?.id === card?.id);
case 'Cart':
Expand Down Expand Up @@ -126,9 +124,9 @@ const CardActionButtons = ({
switch (context) {
case 'Collection':
if (action === 'add') {
addOneToCollection(card, card.id);
addOneToCollection(card);
} else if (action === 'removeOne') {
removeOneFromCollection(card, card.id);
removeOneFromCollection(card);
}
break;
case 'Deck':
Expand Down
44 changes: 16 additions & 28 deletions src/components/chart/PortfolioChart.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ function handleThresholdUpdate(lastUpdateTime, setLastUpdateTime) {
}
return lastUpdateTime;
}
const getFilteredData2 = (collection) => {
const getFilteredData2 = (collection, timeRange) => {
if (!collection) {
console.error('Invalid input: selectedCollection should not be null');
return [];
}
return getUniqueValidData(collection.currentChartDataSets2 || []);
return getUniqueValidData(collection?.chartData?.allXYValues || []);
};
const PortfolioChart = () => {
const theme = useTheme();
Expand All @@ -59,36 +59,33 @@ const PortfolioChart = () => {
() => handleThresholdUpdate(lastUpdateTime, setLastUpdateTime),
[lastUpdateTime]
);
// const filteredChartData2 = useMemo(
// () => getFilteredData2(selectedCollection),
// [selectedCollection]
// );
// const rawData2 = useMemo(
// () => groupAndAverageData(filteredChartData2, threshold),
// [filteredChartData2, threshold]
// );
// const nivoReadyData2 = useMemo(
// () => convertDataForNivo2(rawData2),
// [rawData2]
// );

const filteredChartData2 = useMemo(
() => getFilteredData2(selectedCollection, timeRange), // Adjust to filter data based on timeRange
[selectedCollection, timeRange]
);

if (!filteredChartData2 || filteredChartData2?.length === 0) {
console.warn(
'Invalid input: filteredChartData2 should not be null or empty'
);
return filteredChartData2;
}
const rawData2 = useMemo(
() => groupAndAverageData(filteredChartData2, threshold, timeRange), // Adjust to group and average data based on timeRange
[filteredChartData2, threshold, timeRange]
);

if (!rawData2 || rawData2?.length === 0) {
console.warn('Invalid input: rawData2 should not be null or empty');
return rawData2;
}

const nivoReadyData2 = useMemo(
() => convertDataForNivo2(rawData2),
[rawData2]
);
console.log('Selected Collection:', selectedCollection);
console.log('Filtered Chart Data:', filteredChartData2);
console.log('Raw Data:', rawData2);
console.log('Nivo Ready Data:', nivoReadyData2);

const HEIGHT_TO_WIDTH_RATIO = 7 / 10;

useEffect(() => {
Expand Down Expand Up @@ -118,23 +115,14 @@ const PortfolioChart = () => {
alignItems: 'center',
padding: theme.spacing(2),
gap: theme.spacing(2),
// backgroundColor: theme.palette.background.paper,
background: '#333', // Darker background for Paper

color: '#fff', // White text color
border: '1px solid #555',
borderRadius: 2,
// color: theme.palette.text.primary,
}}
>
<ErrorBoundary>
<Grid
container
spacing={2}
// sx={{
// // background: '#222', // Darker background for Paper
// }}
>
<Grid container spacing={2}>
<Grid
item
xs={12}
Expand Down
14 changes: 12 additions & 2 deletions src/components/collection/PortfolioContent.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { Box, Container, Grid, Paper, useTheme } from '@mui/material';
import HeaderTitle from '../reusable/HeaderTitle';
import { useCollectionStore } from '../../context/CollectionContext/CollectionContext';
Expand All @@ -11,6 +11,16 @@ import CollectionPortfolioListContainer from '../../containers/collectionPageCon
const PortfolioContent = ({ selectedCards, removeCard }) => {
const { theme } = useMode();
const { selectedCollection } = useCollectionStore();
const [collectionName, setCollectionName] = useState(
selectedCollection?.name
);

// Update collectionName when selectedCollection changes
useEffect(() => {
if (selectedCollection?.name) {
setCollectionName(selectedCollection.name);
}
}, [selectedCollection]);

return (
<Box
Expand Down Expand Up @@ -42,7 +52,7 @@ const PortfolioContent = ({ selectedCards, removeCard }) => {
}}
>
<HeaderTitle
title={selectedCollection?.name}
title={collectionName}
size="large"
location="center"
theme={theme}
Expand Down
27 changes: 3 additions & 24 deletions src/components/grids/collectionGrids/SelectCollectionList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,29 +84,8 @@ const SelectCollectionList = ({
} = useCollectionStore();
const { stats, statsByCollectionId } = useStatisticsStore();
const [isLoading, setIsLoading] = useState(false);
// const twentyFourHourChange = stats.twentyFourHourAverage;

// let collectionStats;
// let twentyFourHourChange;
// const getStatsForAllCollections = (collection) => {
// if (!collection) {
// console.error('Invalid input: selectedCollection should not be null');
// return [];
// }
// if (!statsByCollectionId) {
// console.error('Invalid input: statsByCollectionId should not be null');
// return [];
// }

// collectionStats = statsByCollectionId[collection?._id];
// twentyFourHourChange = collectionStats?.twentyFourHourAverage;

// return { collectionStats, twentyFourHourChange };
// };
console.log('STATS:', stats);
console.log('STATS BY COLLECTION ID:', statsByCollectionId);
console.log('SELECTED COLLECTION:', selectedCollection);
console.log('ALL COLLECTIONS:', allCollections);
// console.log('STATS:', stats);
// console.log('STATS BY COLLECTION ID:', statsByCollectionId);
function roundToNearestTenth(num) {
return Math.round(num * 10) / 10;
}
Expand Down Expand Up @@ -142,7 +121,7 @@ const SelectCollectionList = ({
const handleOpenDialog = useCallback(
(collection) => {
setSelectedCollection(collection);
console.log('SELECTED COLLECTION:', collection);
console.log('SELECTED COLLECTION IN LIST:', collection);
openDialog(true);
},
[openDialog, setSelectedCollection]
Expand Down
21 changes: 16 additions & 5 deletions src/components/media/CardMediaAndDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,33 @@ import axios from 'axios';
import { Grid } from '@mui/material';
import CardMediaSection from './CardMediaSection';
import CardDetailsContainer from '../modals/cardModal/CardDetailsContainer';
import { useCardStore } from '../../context';
import {
useCardStore,
useCollectionStore,
useUserContext,
} from '../../context';

const CardMediaAndDetails = ({ card }) => {
const [updatedCard, setUpdatedCard] = useState(card);
const { updateCardInCollection } = useCardStore(); // Method to update the card in the collection

const { updateCollection, selectedCollection } = useCollectionStore(); // Method to update the card in the collection
const [imgUrl, setImgUrl] = useState(updatedCard?.card_images[0]?.image_url); // [1
const { user } = useUserContext();
useEffect(() => {
const updateCardData = async () => {
if (!card.card_images || card.card_images.length === 0) {
const cardId = card.id;
try {
const response = await axios.patch(
`${process.env.REACT_APP_SERVER}/api/cards/ygopro/${card.id}`
`${process.env.REACT_APP_SERVER}/api/cards/ygopro/${cardId}`,
{ id: card.id, name: card.name, card: card, user: user }
);
if (response.data && response.data.data) {
console.log('RESPONSE DATA', response.data.data);
setUpdatedCard(response.data.data);
updateCardInCollection(response.data.data); // Update the card in the corresponding collection
setImgUrl(response?.data?.data?.card_images[0]?.image_url); // [1
// updateCardInCollection(response.data.data); // Update the card in the corresponding collection
updateCollection(response.data.data, 'update', selectedCollection);
}
} catch (err) {
console.error('Error fetching card images:', err);
Expand All @@ -35,7 +46,7 @@ const CardMediaAndDetails = ({ card }) => {
<CardMediaSection
isRequired={false}
card={updatedCard}
imgUrl={updatedCard?.card_images[0]?.image_url}
imgUrl={imgUrl}
/>
</Grid>
<Grid item xs={12} sm={6}>
Expand Down
12 changes: 3 additions & 9 deletions src/components/other/dataDisplay/TopCardsDisplay.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ const CarouselCard = ({ card }) => {
const { theme } = useMode();
const classes = useStyles();
const placeholderImage = '../../assets/images/placeholder.jpeg';
const imgUrl = card?.card_images?.[0]?.image_url || placeholderImage;
const { openModalWithCard, closeModal, isModalOpen, modalContent } =
useContext(ModalContext);
const cardRef = useRef(null);
Expand Down Expand Up @@ -86,12 +85,7 @@ const TopCardsDisplay = () => {
const latestPrice = card?.latestPrice?.num ?? 0;
const lastSavedPrice = card?.lastSavedPrice?.num ?? 0;

if (
latestPrice === 0 ||
latestPrice === undefined ||
lastSavedPrice === 0 ||
lastSavedPrice === undefined
) {
if (latestPrice === undefined) {
console.warn(`Price missing for card: ${card.name}`);
return { ...card, diff: 0 };
}
Expand All @@ -107,7 +101,7 @@ const TopCardsDisplay = () => {
setTop5Cards(sortedCards);
}, [selectedCollection]);

const maxSteps = top5Cards.length;
const maxSteps = top5Cards?.length;

const handleNext = () =>
setActiveStep((prevActiveStep) => prevActiveStep + 1);
Expand All @@ -126,7 +120,7 @@ const TopCardsDisplay = () => {
width: '100%', // Use full width of the container
}}
>
{top5Cards.map((card, index) => (
{top5Cards?.map((card, index) => (
<MainContainer key={index}>
<CarouselCard card={card} />
</MainContainer>
Expand Down
12 changes: 9 additions & 3 deletions src/context/CardContext/CardStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const CardProvider = ({ children }) => {
setOrganizedSearchData(limitedCardsToRender);

if (limitedCardsToRender.length >= 1) {
console.log('LIMITED CARDS TO RENDER: ', limitedCardsToRender[0]);
// console.log('LIMITED CARDS TO RENDER: ', limitedCardsToRender[0]);
setSlicedSearchData(limitedCardsToRender);
}
}
Expand Down Expand Up @@ -95,11 +95,17 @@ export const CardProvider = ({ children }) => {

for (const collection of allCollections) {
for (const card of collection.cards) {
if (!card.card_images || !card.card_sets || !card.card_prices) {
if (
!user.id ||
!card.card_images ||
!card.card_sets ||
!card.card_prices
) {
needsUpdate = true;
const response = await axios.patch(
`${process.env.REACT_APP_SERVER}/api/cards/ygopro/${card.id}`,
{ id: card.id, user: user, _id: user._id }
{ id: card.id, user: user.id },
{ withCredentials: true }
);
if (response.data && response.data.data) {
const updatedCard = response.data.data;
Expand Down
6 changes: 3 additions & 3 deletions src/context/CartContext/CartContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,9 @@ export const CartProvider = ({ children }) => {
createUserCart,
};

useEffect(() => {
console.log('CART CONTEXT: ', value.cartData);
}, [addOneToCart, removeOneFromCart, deleteFromCart]);
// useEffect(() => {
// console.log('CART CONTEXT: ', value.cartData);
// }, [addOneToCart, removeOneFromCart, deleteFromCart]);

return <CartContext.Provider value={value}>{children}</CartContext.Provider>;
};
Expand Down
50 changes: 50 additions & 0 deletions src/context/CollectionContext/CardUpdateEffect.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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;
Loading

0 comments on commit 3186d48

Please sign in to comment.