From b9a10c0bb974505671de797f5f325ce9b4568fca Mon Sep 17 00:00:00 2001 From: Reed Vogt Date: Thu, 14 Mar 2024 10:57:00 -0700 Subject: [PATCH 01/10] Completed styling for the collection selection statboard row as well as the minutiae of the data layout --- src/App.js | 48 ++-- src/Main.jsx | 4 - src/assets/themes/GlobalStyles.js | 27 -- src/assets/themes/base/colors.jsx | 24 +- src/assets/themes/{ => base}/colors/Azure.jsx | 0 src/assets/themes/{ => base}/colors/Cyan.jsx | 0 src/assets/themes/{ => base}/colors/Dark.jsx | 0 .../themes/{ => base}/colors/DeepPurple.jsx | 0 .../themes/{ => base}/colors/Default.jsx | 0 .../themes/{ => base}/colors/Indigo.jsx | 0 src/assets/themes/{ => base}/colors/Light.jsx | 0 .../themes/{ => base}/colors/LightBlue.jsx | 0 .../themes/base/customColorPalettes.jsx | 18 +- src/assets/themes/base/typography.jsx | 241 +++++++++++++---- src/assets/themes/components/index.jsx | 125 ++++----- .../styleOverride/compStyleOverride.jsx | 187 ------------- src/assets/themes/themeSettings.jsx | 250 ++---------------- src/assets/themes/tokens.jsx | 132 --------- src/assets/themes/typography/typography.js | 133 ---------- .../buttons/other/ReusableLoadingButton.jsx | 58 ++++ src/components/componentHelpers.jsx | 2 - src/components/dialogs/CollectionDialog.jsx | 153 +++++------ src/components/dialogs/DeckEditPanel.js | 193 +------------- src/components/dialogs/LoginDialog.jsx | 27 +- src/components/forms/AddCollectionForm.jsx | 78 +++--- src/components/forms/LoginForm.jsx | 73 ++--- src/components/forms/SearchForm.jsx | 14 +- src/components/forms/SignupForm.jsx | 28 +- src/components/forms/formsConfig.jsx | 59 ++++- .../forms/hooks/useSubmitHandler.jsx | 36 +++ src/components/forms/index.jsx | 22 +- src/components/forms/reusable/Select.jsx | 4 +- .../forms/selectors/ThemeSelector.jsx | 3 +- .../forms/selectors/TimeRangeSelector.jsx | 170 ++---------- .../forms/selectors/useTimeRange.jsx | 71 ++--- .../MAIN_CONTEXT/AuthContext/authContext.js | 4 - .../PageContext/PageContext.jsx | 17 +- .../SnackbarContext/SnackbarContext.jsx | 49 ++++ src/context/hooks/useCustomSnackbar.jsx | 31 +++ src/context/hooks/useDialog.jsx | 16 +- src/context/hooks/useFetchWrapper.jsx | 147 +++++----- src/context/hooks/useSnackBar.jsx | 144 +++++----- src/context/index.js | 2 + src/{tests => data}/initialCardData.jsx | 0 src/data/messages.json | 29 ++ src/index.js | 96 +++---- src/{tests => layout}/CardChart.jsx | 73 +---- src/layout/CardLinearChart.jsx | 85 ++++++ src/layout/REUSABLE_COMPONENTS/BoxHeader.jsx | 23 +- .../REUSABLE_COMPONENTS/CustomSnackbar.jsx | 31 +++ src/layout/REUSABLE_COMPONENTS/Icons.jsx | 20 +- .../REUSABLE_COMPONENTS/SkeletonVariants.jsx | 1 - .../REUSABLE_COMPONENTS}/SplashPage2.jsx | 15 +- src/layout/REUSABLE_COMPONENTS/StatBox.jsx | 12 +- .../unique/SimpleSectionHeader.jsx | 66 +++-- .../collectionGrids/ChartGridLayout.jsx | 107 ++++++-- .../cards-chart/ChartConfigs.jsx | 220 ++------------- .../cards-chart/ChartErrorBoundary.jsx | 61 +++-- .../CollectionPortfolioChartContainer.jsx | 165 ------------ .../cards-chart/LinearChart.js | 34 --- .../cards-chart/UpdaterAndStatisticsRow.jsx | 10 +- .../SelectCollectionHeader.jsx | 9 +- .../collections-list/SelectCollectionList.jsx | 123 +++------ .../collections-list/StatBoard.jsx | 169 ++++++++---- .../statItems/PerformanceStatBox.jsx | 86 ++++++ .../statItems/PricedCardList.jsx | 234 +++++++++------- .../statItems/TotalPriceStatBox.jsx | 60 ++++- .../statItems/ValuDistributionCircle.jsx | 101 +++++-- .../GenerateNivoTestData.jsx | 0 src/layout/collection/data/topCards.jsx | 107 ++++---- src/layout/collection/index.jsx | 36 +-- src/{tests => layout}/useCardCronJob.jsx | 33 +-- src/pages/HomePage.js | 50 +--- src/pages/pageStyles/StyledComponents.jsx | 2 +- src/pages/sections/HeroSection.jsx | 154 +---------- src/pages/sections/MainContentSection.jsx | 7 +- .../statItems => save}/PieChart.jsx | 4 +- .../statItems => save}/ValueDistPieChart.jsx | 0 src/save/tokens.jsx | 132 +++++++++ src/{assets => }/serviceWorker.js | 0 src/tests/CardLinearChart.jsx | 215 --------------- .../styleOverride/compStyleOverride.jsx | 187 +++++++++++++ 82 files changed, 2304 insertions(+), 3043 deletions(-) rename src/assets/themes/{ => base}/colors/Azure.jsx (100%) rename src/assets/themes/{ => base}/colors/Cyan.jsx (100%) rename src/assets/themes/{ => base}/colors/Dark.jsx (100%) rename src/assets/themes/{ => base}/colors/DeepPurple.jsx (100%) rename src/assets/themes/{ => base}/colors/Default.jsx (100%) rename src/assets/themes/{ => base}/colors/Indigo.jsx (100%) rename src/assets/themes/{ => base}/colors/Light.jsx (100%) rename src/assets/themes/{ => base}/colors/LightBlue.jsx (100%) delete mode 100644 src/assets/themes/styleOverride/compStyleOverride.jsx delete mode 100644 src/assets/themes/tokens.jsx delete mode 100644 src/assets/themes/typography/typography.js create mode 100644 src/components/buttons/other/ReusableLoadingButton.jsx create mode 100644 src/components/forms/hooks/useSubmitHandler.jsx create mode 100644 src/context/UTILITIES_CONTEXT/SnackbarContext/SnackbarContext.jsx create mode 100644 src/context/hooks/useCustomSnackbar.jsx rename src/{tests => data}/initialCardData.jsx (100%) create mode 100644 src/data/messages.json rename src/{tests => layout}/CardChart.jsx (79%) create mode 100644 src/layout/CardLinearChart.jsx create mode 100644 src/layout/REUSABLE_COMPONENTS/CustomSnackbar.jsx rename src/{pages => layout/REUSABLE_COMPONENTS}/SplashPage2.jsx (88%) delete mode 100644 src/layout/collection/collectionGrids/cards-chart/CollectionPortfolioChartContainer.jsx delete mode 100644 src/layout/collection/collectionGrids/cards-chart/LinearChart.js create mode 100644 src/layout/collection/collectionGrids/collections-list/statItems/PerformanceStatBox.jsx rename src/layout/collection/{collectionGrids/cards-chart => data}/GenerateNivoTestData.jsx (100%) rename src/{tests => layout}/useCardCronJob.jsx (65%) rename src/{layout/collection/collectionGrids/collections-list/statItems => save}/PieChart.jsx (97%) rename src/{layout/collection/collectionGrids/collections-list/statItems => save}/ValueDistPieChart.jsx (100%) create mode 100644 src/save/tokens.jsx rename src/{assets => }/serviceWorker.js (100%) delete mode 100644 src/tests/CardLinearChart.jsx create mode 100644 src/zcleanup/styleOverride/compStyleOverride.jsx diff --git a/src/App.js b/src/App.js index 20a69a0..db4d970 100644 --- a/src/App.js +++ b/src/App.js @@ -22,6 +22,7 @@ import { ErrorBoundary, ConfiguratorProvider, VisibilityProvider, + SnackbarContextProvider, } from './context'; import { ThemeProvider } from 'styled-components'; import { SnackbarProvider, useSnackbar } from 'notistack'; @@ -40,9 +41,6 @@ const App = () => { const { returnDisplay } = usePageContext(); const { isLoading, isPageLoading, error } = useLoading(); - // useEffect(() => { - // if (!isLoggedIn && !isPageLoading) navigate('/login'); - // }, [isLoggedIn, navigate, isPageLoading]); if (isPageLoading || error) { return returnDisplay(); } @@ -57,29 +55,27 @@ const App = () => { - - - - - - - - - - - -
- - - - - - - - - - - + + + + + + + + + + +
+ + + + + + + + + + diff --git a/src/Main.jsx b/src/Main.jsx index f58dade..9c15ff8 100644 --- a/src/Main.jsx +++ b/src/Main.jsx @@ -8,10 +8,7 @@ import PageLayout from './layout/Containers/PageLayout.jsx'; import Navigation from './layout/navigation/Navigation.jsx'; import LoadingIndicator from './components/reusable/indicators/LoadingIndicator.js'; import Configurator from './layout/REUSABLE_COMPONENTS/Configurator/index.jsx'; -import { useCardStoreHook } from './context/hooks/useCardStore.jsx'; -import { AppContainer } from './pages/pageStyles/StyledComponents.jsx'; -// Define all routes in a single array including the component name for laziness const ROUTE_CONFIG = [ { path: '/', componentName: 'HomePage', isPrivate: false }, { path: '/home', componentName: 'HomePage', isPrivate: false }, @@ -29,7 +26,6 @@ const ROUTE_CONFIG = [ { path: '*', componentName: 'NotFoundPage', isPrivate: false }, ]; -// Dynamically import page components based on route configuration const LazyRoute = ({ componentName, ...rest }) => { const Component = lazy(() => import(`./pages/${componentName}`)); return ; diff --git a/src/assets/themes/GlobalStyles.js b/src/assets/themes/GlobalStyles.js index cd518fd..1c12c75 100644 --- a/src/assets/themes/GlobalStyles.js +++ b/src/assets/themes/GlobalStyles.js @@ -24,10 +24,6 @@ const MyGlobalStyles = () => ( textDecoration: 'none', // remove underline from all links color: 'inherit', // links will inherit their parent color }, - // '*::-webkit-scrollbar': { - // visibility: 'hidden', - // // width: '8px', - // }, '*::-webkit-scrollbar-track': { backgroundColor: 'gray.200', }, @@ -35,29 +31,6 @@ const MyGlobalStyles = () => ( backgroundColor: 'gray.500', borderRadius: '20px', }, - // h1: { - // fontSize: '2.5rem', // styling for h1 tags - // fontWeight: 'bold', - // }, - // h2: { - // fontSize: '2rem', // styling for h2 tags - // fontWeight: 'bold', - // }, - // h3: { - // fontSize: '1.75rem', // styling for h3 tags - // }, - // h4: { - // fontSize: '1.5rem', // styling for h4 tags - // }, - // h5: { - // fontSize: '1.25rem', // styling for h5 tags - // }, - // h6: { - // fontSize: '1rem', // styling for h6 tags - // }, - // p: { - // fontSize: '1rem', // styling for p tags - // }, }} /> ); diff --git a/src/assets/themes/base/colors.jsx b/src/assets/themes/base/colors.jsx index 3bd6619..bbeecae 100644 --- a/src/assets/themes/base/colors.jsx +++ b/src/assets/themes/base/colors.jsx @@ -15,9 +15,15 @@ import { text, divider, action, + primary, + secondary, } from './customColorPalettes'; const colors = { chartTheme: chartTheme, + background: { + default: '#f0f2f5', + paper: '#fff', + }, // PRIMARY COLORS backgroundA, backgroundD: { @@ -67,9 +73,6 @@ const colors = { qcr: hexToRgba(rarity.qcr, 0.5), // Add more rarities as needed }, - background: { - default: '#f0f2f5', - }, // TEXT COLORS text, // DIVIDER COLORS @@ -117,20 +120,9 @@ const colors = { focus: '#05386B', }, - primary: { - main: '#5CDB95', - focus: '#379683', - }, + primary, - // primary: { - // main: '#e91e63', - // focus: '#e91e63', - // }, - - secondary: { - main: '#7b809a', - focus: '#8f93a9', - }, + secondary, light: { main: '#f0f2f5', focus: '#f0f2f5', diff --git a/src/assets/themes/colors/Azure.jsx b/src/assets/themes/base/colors/Azure.jsx similarity index 100% rename from src/assets/themes/colors/Azure.jsx rename to src/assets/themes/base/colors/Azure.jsx diff --git a/src/assets/themes/colors/Cyan.jsx b/src/assets/themes/base/colors/Cyan.jsx similarity index 100% rename from src/assets/themes/colors/Cyan.jsx rename to src/assets/themes/base/colors/Cyan.jsx diff --git a/src/assets/themes/colors/Dark.jsx b/src/assets/themes/base/colors/Dark.jsx similarity index 100% rename from src/assets/themes/colors/Dark.jsx rename to src/assets/themes/base/colors/Dark.jsx diff --git a/src/assets/themes/colors/DeepPurple.jsx b/src/assets/themes/base/colors/DeepPurple.jsx similarity index 100% rename from src/assets/themes/colors/DeepPurple.jsx rename to src/assets/themes/base/colors/DeepPurple.jsx diff --git a/src/assets/themes/colors/Default.jsx b/src/assets/themes/base/colors/Default.jsx similarity index 100% rename from src/assets/themes/colors/Default.jsx rename to src/assets/themes/base/colors/Default.jsx diff --git a/src/assets/themes/colors/Indigo.jsx b/src/assets/themes/base/colors/Indigo.jsx similarity index 100% rename from src/assets/themes/colors/Indigo.jsx rename to src/assets/themes/base/colors/Indigo.jsx diff --git a/src/assets/themes/colors/Light.jsx b/src/assets/themes/base/colors/Light.jsx similarity index 100% rename from src/assets/themes/colors/Light.jsx rename to src/assets/themes/base/colors/Light.jsx diff --git a/src/assets/themes/colors/LightBlue.jsx b/src/assets/themes/base/colors/LightBlue.jsx similarity index 100% rename from src/assets/themes/colors/LightBlue.jsx rename to src/assets/themes/base/colors/LightBlue.jsx diff --git a/src/assets/themes/base/customColorPalettes.jsx b/src/assets/themes/base/customColorPalettes.jsx index 931a134..c590a75 100644 --- a/src/assets/themes/base/customColorPalettes.jsx +++ b/src/assets/themes/base/customColorPalettes.jsx @@ -112,7 +112,6 @@ const backgroundF = { lighter: hexToRgba(backgroundE.lighter, 0.4), lightest: hexToRgba(backgroundE.lightest, 0.3), }; - const backgroundG = { darkest: '#073b4cff', // --midnight-green-- darker: '#0c637fff', // --cerulean-- @@ -133,7 +132,6 @@ const backgroundGSecondary = { lightest: '#facbb0ff', // --navajo-white-- contrastText: '#fff', }; - const grey = { darkest: '#141414', darkert: '#292929', @@ -145,18 +143,23 @@ const grey = { evenLighter: '#c2c2c2', contrastText: '#e0e0e0', }; - const primary = { darkest: '#040509', darker: '#040509', dark: '#040509', default: '#f2f0f0', + main: '#5CDB95', + focus: '#379683', light: '#141b2d', lighter: '#1F2A40', lightest: '#727681', - evenLighter: '#a1a4ab', + evenLighter: '#8c8c8c', contrastText: '#e0e0e0', }; +const secondary = { + main: '#8c8c8c', + focus: '#8f93a9', +}; const greenAccent = { darkest: '#0f2922', // Assuming this is the darkest @@ -169,7 +172,6 @@ const greenAccent = { evenLighter: '#b7ebde', // Even lighter than the lightest contrastText: '#dbf5ee', // Most contrasting or lightest, could be adjusted }; - const redAccent = { darkest: '#2c100f', darker: '#58201e', @@ -181,7 +183,6 @@ const redAccent = { evenLighter: '#f1b9b7', contrastText: '#f8dcdb', }; - const blueAccent = { darkest: '#151632', darker: '#2a2d64', @@ -193,7 +194,6 @@ const blueAccent = { evenLighter: '#c3c6fd', contrastText: '#e1e2fe', }; - const chartTheme = { primary, grey, @@ -201,7 +201,6 @@ const chartTheme = { redAccent, blueAccent, }; - const rarity = { common: '#C0C0C0', // Silver uncommon: '#B8860B', // DarkGoldenRod @@ -218,7 +217,6 @@ const rarity = { qcr: '#FF4500', // OrangeRed // Add more rarities as needed }; - export { chartTheme, backgroundA, @@ -237,6 +235,8 @@ export { text, divider, action, + primary, + secondary, }; // error: { // main: colorsA.redAccent[500], diff --git a/src/assets/themes/base/typography.jsx b/src/assets/themes/base/typography.jsx index 846a45e..7bd293d 100644 --- a/src/assets/themes/base/typography.jsx +++ b/src/assets/themes/base/typography.jsx @@ -5,32 +5,16 @@ import colors from './colors'; const { dark } = colors; -// const baseProperties = { -// fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', -// fontWeightLighter: 100, -// fontWeightLight: 300, -// fontWeightRegular: 400, -// fontWeightMedium: 600, -// fontWeightBold: 700, -// fontSizeXXS: pxToRem(10.4), -// fontSizeXS: pxToRem(12), -// fontSizeSM: pxToRem(14), -// fontSizeMD: pxToRem(16), -// fontSizeLG: pxToRem(18), -// fontSizeXL: pxToRem(20), -// fontSize2XL: pxToRem(24), -// fontSize3XL: pxToRem(30), -// }; const baseProperties = { - // fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', fontFamily: 'Poppins, sans-serif', fontWeightLighter: 100, fontWeightLight: 300, fontWeightRegular: 400, fontWeightMedium: 600, fontWeightBold: 700, - // Define font sizes as functions to include responsive behavior - fontSizeXXS: () => `clamp(${pxToRem(8)}, 1vw, ${pxToRem(10)})`, + + fontSize3XS: () => `clamp(${pxToRem(6)}, 1vw, ${pxToRem(8)})`, + fontSize2XS: () => `clamp(${pxToRem(8)}, 1vw, ${pxToRem(10)})`, fontSizeXS: () => `clamp(${pxToRem(10)}, 1.25vw, ${pxToRem(12)})`, fontSizeSM: () => `clamp(${pxToRem(12)}, 1.5vw, ${pxToRem(14)})`, fontSizeMD: () => `clamp(${pxToRem(14)}, 1.75vw, ${pxToRem(16)})`, @@ -38,17 +22,15 @@ const baseProperties = { fontSizeXL: () => `clamp(${pxToRem(18)}, 2.25vw, ${pxToRem(20)})`, fontSize2XL: () => `clamp(${pxToRem(20)}, 2.5vw, ${pxToRem(24)})`, fontSize3XL: () => `clamp(${pxToRem(24)}, 2.75vw, ${pxToRem(30)})`, + fontSize4XL: () => `clamp(${pxToRem(30)}, 3vw, ${pxToRem(36)})`, + fontSize5XL: () => `clamp(${pxToRem(36)}, 3.25vw, ${pxToRem(42)})`, + fontSize6XL: () => `clamp(${pxToRem(42)}, 3.5vw, ${pxToRem(48)})`, }; -// const baseHeadingProperties = { -// fontFamily: baseProperties.fontFamily, -// color: dark.main, -// fontWeight: baseProperties.fontWeightBold, -// }; + const baseHeadingProperties = { fontFamily: baseProperties.fontFamily, color: dark.main, fontWeight: baseProperties.fontWeightBold, - // Include responsive font sizes in base properties fontSize: baseProperties.fontSizeXL(), // Call the function for default size '@media (max-width:600px)': { fontSize: baseProperties.fontSizeMD(), // Adjust size for smaller screens @@ -72,53 +54,76 @@ const typography = { h1: { ...baseHeadingProperties, - fontSize: baseProperties.fontSize3XL(), + fontSize: baseProperties.fontSize6XL(), '@media (max-width:900px)': { - fontSize: baseProperties.fontSize2XL(), + fontSize: baseProperties.fontSize5XL(), }, }, h2: { - fontSize: baseProperties.fontSize2XL(), ...baseHeadingProperties, + fontSize: baseProperties.fontSize5XL(), + '@media (max-width:900px)': { + fontSize: baseProperties.fontSize4XL(), + }, }, h3: { - fontSize: baseProperties.fontSizeXL(), ...baseHeadingProperties, + fontSize: baseProperties.fontSize4XL(), '@media (max-width:600px)': { - fontSize: baseProperties.fontSizeLG(), + fontSize: baseProperties.fontSize3XL(), }, }, - // h2: { - // fontSize: pxToRem(36), - // lineHeight: 1.3, - // ...baseHeadingProperties, - // }, - - // h3: { - // fontSize: pxToRem(30), - // lineHeight: 1.375, - // ...baseHeadingProperties, - // }, - h4: { - fontSize: pxToRem(24), - lineHeight: 1.375, ...baseHeadingProperties, + fontSize: baseProperties.fontSize3XL(), + '@media (max-width:600px)': { + fontSize: baseProperties.fontSize2XL(), + }, }, h5: { - fontSize: pxToRem(20), - lineHeight: 1.375, ...baseHeadingProperties, + fontSize: baseProperties.fontSize2XL(), + '@media (max-width:600px)': { + fontSize: baseProperties.fontSizeXL(), + }, }, h6: { - fontSize: pxToRem(16), - lineHeight: 1.625, ...baseHeadingProperties, + fontSize: baseProperties.fontSizeXL(), + '@media (max-width:600px)': { + fontSize: baseProperties.fontSizeLG(), + }, + }, + + p1: { + fontFamily: baseProperties.fontFamily, + fontWeight: baseProperties.fontWeightLight, + fontSize: baseProperties.fontSizeSM(), + lineHeight: 1.5, + '@media (max-width:600px)': { + fontSize: baseProperties.fontSizeXS(), + }, + '@media (max-width:900px)': { + fontSize: baseProperties.fontSizeSM(), + }, + }, + + p2: { + fontFamily: baseProperties.fontFamily, + fontWeight: baseProperties.fontWeightLight, + fontSize: baseProperties.fontSizeSM(), + lineHeight: 1.5, + '@media (max-width:600px)': { + fontSize: baseProperties.fontSizeXS(), + }, + '@media (max-width:900px)': { + fontSize: baseProperties.fontSizeSM(), + }, }, subtitle1: { @@ -210,10 +215,146 @@ const typography = { }, lineHeight: { - sm: 1.25, - md: 1.5, + xs: 1.25, + sm: 1.5, + md: 1.75, lg: 2, + xl: 2, }, }; export default typography; + +// /** +// * Typography used in theme +// * @param {JsonObject} theme theme customization object +// */ + +// export default function themeTypography(theme) { +// return { +// fontFamily: theme?.customization?.fontFamily, +// h6: { +// fontWeight: 500, +// color: theme.heading, +// fontSize: '0.75rem', +// }, +// h5: { +// fontSize: '0.875rem', +// color: theme.heading, +// fontWeight: 500, +// }, +// h4: { +// fontSize: '1rem', +// color: theme.heading, +// fontWeight: 600, +// }, +// h3: { +// fontSize: '1.25rem', +// color: theme.heading, +// fontWeight: 600, +// }, +// h2: { +// fontSize: '1.5rem', +// color: theme.heading, +// fontWeight: 700, +// }, +// h1: { +// fontSize: '2.125rem', +// color: theme.heading, +// fontWeight: 700, +// }, +// subtitle1: { +// fontSize: '0.875rem', +// fontWeight: 500, +// color: theme.textDark, +// }, +// subtitle2: { +// fontSize: '0.75rem', +// fontWeight: 400, +// color: theme.darkTextSecondary, +// }, +// caption: { +// fontSize: '0.75rem', +// color: theme.darkTextSecondary, +// fontWeight: 400, +// }, +// body1: { +// fontSize: '0.875rem', +// fontWeight: 400, +// lineHeight: '1.334em', +// }, +// body2: { +// letterSpacing: '0em', +// fontWeight: 400, +// lineHeight: '1.5em', +// color: theme.darkTextPrimary, +// }, +// button: { +// textTransform: 'capitalize', +// }, +// customInput: { +// marginTop: 1, +// marginBottom: 1, +// '& > label': { +// top: 23, +// left: 0, +// color: theme.grey500, +// '&[data-shrink="false"]': { +// top: 5, +// }, +// }, +// '& > div > input': { +// padding: '30.5px 14px 11.5px !important', +// }, +// '& legend': { +// display: 'none', +// }, +// '& fieldset': { +// top: 0, +// }, +// }, +// mainContent: { +// backgroundColor: theme.background, +// width: '100%', +// minHeight: 'calc(100vh - 88px)', +// flexGrow: 1, +// padding: '20px', +// marginTop: '88px', +// marginRight: '20px', +// borderRadius: `${theme?.customization?.borderRadius}px`, +// }, +// menuCaption: { +// fontSize: '0.875rem', +// fontWeight: 500, +// color: theme.heading, +// padding: '6px', +// textTransform: 'capitalize', +// marginTop: '10px', +// }, +// subMenuCaption: { +// fontSize: '0.6875rem', +// fontWeight: 500, +// color: theme.darkTextSecondary, +// textTransform: 'capitalize', +// }, +// commonAvatar: { +// cursor: 'pointer', +// borderRadius: '8px', +// }, +// smallAvatar: { +// width: '22px', +// height: '22px', +// fontSize: '1rem', +// }, +// mediumAvatar: { +// width: '34px', +// height: '34px', +// fontSize: '1.2rem', +// }, +// largeAvatar: { +// width: '44px', +// height: '44px', +// fontSize: '1.5rem', +// }, +// }; +// } diff --git a/src/assets/themes/components/index.jsx b/src/assets/themes/components/index.jsx index d4f730c..f60b1f4 100644 --- a/src/assets/themes/components/index.jsx +++ b/src/assets/themes/components/index.jsx @@ -20,83 +20,74 @@ const cssbaseline = { `, }; -// const container = { +// const listItemButton = { // styleOverrides: { // root: { -// margin: 0, -// padding: 0, +// color: '#4cceac', +// paddingTop: '10px', +// paddingBottom: '10px', +// '&.Mui-selected': { +// color: '#3da58a', +// backgroundColor: '#4cceac', +// '&:hover': { +// backgroundColor: '#3da58a', +// }, +// '& .MuiListItemIcon-root': { +// color: '#3da58a', +// }, +// }, +// '&:hover': { +// backgroundColor: '#3da58a', +// color: '#3da58a', +// '& .MuiListItemIcon-root': { +// color: '#3da58a', +// }, +// }, // }, // }, // }; -const listItemButton = { - styleOverrides: { - root: { - color: '#4cceac', - paddingTop: '10px', - paddingBottom: '10px', - '&.Mui-selected': { - color: '#3da58a', - backgroundColor: '#4cceac', - '&:hover': { - backgroundColor: '#3da58a', - }, - '& .MuiListItemIcon-root': { - color: '#3da58a', - }, - }, - '&:hover': { - backgroundColor: '#3da58a', - color: '#3da58a', - '& .MuiListItemIcon-root': { - color: '#3da58a', - }, - }, - }, - }, -}; - -const outlinedInput = { - styleOverrides: { - root: { - background: '#ffffff', - borderRadius: '4px', - '& .MuiOutlinedInput-notchedOutline': { - borderColor: '#333', - }, - '&:hover $notchedOutline': { - borderColor: '#4cceac', - }, - '&.MuiInputBase-multiline': { - padding: '1px', - }, - }, +// const outlinedInput = { +// styleOverrides: { +// root: { +// background: '#ffffff', +// borderRadius: '4px', +// '& .MuiOutlinedInput-notchedOutline': { +// borderColor: '#333', +// }, +// '&:hover $notchedOutline': { +// borderColor: '#4cceac', +// }, +// '&.MuiInputBase-multiline': { +// padding: '1px', +// }, +// }, - input: { - fontWeight: 500, - background: '#ffffff', - padding: '15.5px 14px', - borderRadius: '4px', - '&.MuiInputBase-inputSizeSmall': { - padding: '10px 14px', - '&.MuiInputBase-inputAdornedStart': { - paddingLeft: 0, - }, - }, - }, - inputAdornedStart: { - paddingLeft: '4px', - }, - notchedOutline: { - borderRadius: '4px', - }, - }, -}; +// input: { +// fontWeight: 500, +// background: '#ffffff', +// padding: '15.5px 14px', +// borderRadius: '4px', +// '&.MuiInputBase-inputSizeSmall': { +// padding: '10px 14px', +// '&.MuiInputBase-inputAdornedStart': { +// paddingLeft: 0, +// }, +// }, +// }, +// inputAdornedStart: { +// paddingLeft: '4px', +// }, +// notchedOutline: { +// borderRadius: '4px', +// }, +// }, +// }; export const components = { MuiCssBaseline: cssbaseline, MuiButton: button, - MuiListItemButton: listItemButton, + // MuiListItemButton: listItemButton, MuiContainer: container, MuiDivider: divider, @@ -104,7 +95,7 @@ export const components = { MuiTableCell: tableCell, MuiTableHead: tableHead, - MuiOutlinedInput: outlinedInput, + // MuiOutlinedInput: outlinedInput, MuiInput: input, MuiInputLabel: inputLabel, diff --git a/src/assets/themes/styleOverride/compStyleOverride.jsx b/src/assets/themes/styleOverride/compStyleOverride.jsx deleted file mode 100644 index e5b65ab..0000000 --- a/src/assets/themes/styleOverride/compStyleOverride.jsx +++ /dev/null @@ -1,187 +0,0 @@ -export default function componentStyleOverrides(theme) { - const bgColor = theme.colors?.grey50; - return { - MuiButton: { - styleOverrides: { - root: { - fontWeight: 500, - borderRadius: '4px', - }, - }, - }, - MuiPaper: { - defaultProps: { - elevation: 0, - }, - styleOverrides: { - root: { - backgroundImage: 'none', - }, - rounded: { - borderRadius: `${theme?.customization?.borderRadius}px`, - }, - }, - }, - MuiCardHeader: { - styleOverrides: { - root: { - color: theme.colors?.textDark, - padding: '24px', - }, - title: { - fontSize: '1.125rem', - }, - }, - }, - MuiCardContent: { - styleOverrides: { - root: { - padding: '24px', - }, - }, - }, - MuiCardActions: { - styleOverrides: { - root: { - padding: '24px', - }, - }, - }, - MuiListItemButton: { - styleOverrides: { - root: { - color: theme.darkTextPrimary, - paddingTop: '10px', - paddingBottom: '10px', - '&.Mui-selected': { - color: theme.menuSelected, - backgroundColor: theme.menuSelectedBack, - '&:hover': { - backgroundColor: theme.menuSelectedBack, - }, - '& .MuiListItemIcon-root': { - color: theme.menuSelected, - }, - }, - '&:hover': { - backgroundColor: theme.menuSelectedBack, - color: theme.menuSelected, - '& .MuiListItemIcon-root': { - color: theme.menuSelected, - }, - }, - }, - }, - }, - MuiListItemIcon: { - styleOverrides: { - root: { - color: theme.darkTextPrimary, - minWidth: '36px', - }, - }, - }, - MuiListItemText: { - styleOverrides: { - primary: { - color: theme.textDark, - }, - }, - }, - MuiInputBase: { - styleOverrides: { - input: { - color: theme.textDark, - '&::placeholder': { - color: theme.darkTextSecondary, - fontSize: '0.875rem', - }, - }, - }, - }, - MuiOutlinedInput: { - styleOverrides: { - root: { - background: bgColor, - borderRadius: `${theme?.customization?.borderRadius}px`, - '& .MuiOutlinedInput-notchedOutline': { - borderColor: theme.colors?.grey400, - }, - '&:hover $notchedOutline': { - borderColor: theme.colors?.primaryLight, - }, - '&.MuiInputBase-multiline': { - padding: 1, - }, - }, - input: { - fontWeight: 500, - background: bgColor, - padding: '15.5px 14px', - borderRadius: `${theme?.customization?.borderRadius}px`, - '&.MuiInputBase-inputSizeSmall': { - padding: '10px 14px', - '&.MuiInputBase-inputAdornedStart': { - paddingLeft: 0, - }, - }, - }, - inputAdornedStart: { - paddingLeft: 4, - }, - notchedOutline: { - borderRadius: `${theme?.customization?.borderRadius}px`, - }, - }, - }, - MuiSlider: { - styleOverrides: { - root: { - '&.Mui-disabled': { - color: theme.colors?.grey300, - }, - }, - mark: { - backgroundColor: theme.paper, - width: '4px', - }, - valueLabel: { - color: theme?.colors?.primaryLight, - }, - }, - }, - MuiDivider: { - styleOverrides: { - root: { - borderColor: theme.divider, - opacity: 1, - }, - }, - }, - MuiAvatar: { - styleOverrides: { - root: { - color: theme.colors?.primaryDark, - background: theme.colors?.primary200, - }, - }, - }, - MuiChip: { - styleOverrides: { - root: { - '&.MuiChip-deletable .MuiChip-deleteIcon': { - color: 'inherit', - }, - }, - }, - }, - MuiTooltip: { - styleOverrides: { - tooltip: { - color: theme.paper, - background: theme.colors?.grey700, - }, - }, - }, - }; -} diff --git a/src/assets/themes/themeSettings.jsx b/src/assets/themes/themeSettings.jsx index 7d2f144..730386f 100644 --- a/src/assets/themes/themeSettings.jsx +++ b/src/assets/themes/themeSettings.jsx @@ -1,12 +1,5 @@ -import { tokens } from './tokens'; -// import themeTypography from './typography/typography'; -// import themeColors from '../scss/_theme-vars.modules.scss'; -import DeckOfCardsIcon from '../../components/reusable/icons/DeckOfCardsIcon'; -import MoneyIcon from '../../components/reusable/icons/MoneyIcon'; -import ChartsIcon from '../../components/reusable/icons/ChartsIcon'; import colors from './base/colors'; import components from './components/index'; -import { backgroundA, backgroundC } from './base/customColorPalettes'; import borders from './base/borders'; import boxShadows from './base/boxShadows'; import typography from './base/typography'; @@ -15,27 +8,9 @@ import hexToRgb from './functions/hexToRgb'; import linearGradient from './functions/linearGradient'; import pxToRem from './functions/pxToRem'; import rgba from './functions/rgba'; +import breakpoints from './base/breakpoints'; export const themeSettings = (mode) => { - const colorsA = tokens(mode); - const specialBreakpoints = { - isSmUp: (breakpoints) => breakpoints.up('sm'), - isMdUp: (breakpoints) => breakpoints.up('md'), - isLgUp: (breakpoints) => breakpoints.up('lg'), - isXlUp: (breakpoints) => breakpoints.up('xl'), - isSmDown: (breakpoints) => breakpoints.down('sm'), - isMdDown: (breakpoints) => breakpoints.down('md'), - isLgDown: (breakpoints) => breakpoints.down('lg'), - isXlDown: (breakpoints) => breakpoints.down('xl'), - - isXSmall: (breakpoints) => breakpoints.down('xs'), - isSmall: (breakpoints) => breakpoints.down('sm'), - isSmallMedium: (breakpoints) => breakpoints.up('sm'), - isMedium: (breakpoints) => breakpoints.down('md'), - isMediumLarge: (breakpoints) => breakpoints.up('md'), - isLarge: (breakpoints) => breakpoints.up('lg'), - isXLarge: (breakpoints) => breakpoints.up('xl'), - }; return { components: components, functions: { @@ -47,11 +22,9 @@ export const themeSettings = (mode) => { }, palette: { ...colors, - ...colorsA, mode: mode, }, - specialBreakpoints: specialBreakpoints, - // components, + breakpoints: breakpoints.values, borders, boxShadows, spacing: (factor) => `${0.25 * factor}rem`, @@ -77,7 +50,6 @@ export const themeSettings = (mode) => { '0px 5px 15px rgba(0,0,0,0.1)', // example for theme.shadows[10] ], typography, - // LAYOUTS skeletonLayouts: { tertiaryContent: { xs: 12, @@ -112,206 +84,24 @@ export const themeSettings = (mode) => { }, }, }; - // MuiListItemButton: { - // styleOverrides: { - // root: { - // color: colorsA.greenAccent[500], - // paddingTop: '10px', - // paddingBottom: '10px', - // '&.Mui-selected': { - // color: colorsA.greenAccent[200], - // backgroundColor: colorsA.greenAccent[300], - // '&:hover': { - // backgroundColor: colorsA.greenAccent[700], - // }, - // '& .MuiListItemIcon-root': { - // color: colorsA.greenAccent[400], - // }, - // }, - // '&:hover': { - // backgroundColor: colorsA.greenAccent[400], - // color: colorsA.greenAccent[200], - // '& .MuiListItemIcon-root': { - // color: colorsA.greenAccent[400], - // }, - // }, - // }, - // }, - // }, - // MuiOutlinedInput: { - // styleOverrides: { - // root: { - // background: backgroundA.default, - // borderRadius: `${themeColors?.borderRadius}px`, - // '& .MuiOutlinedInput-notchedOutline': { - // borderColor: themeColors?.colors?.grey400, - // }, - // '&:hover $notchedOutline': { - // borderColor: themeColors?.primaryLight, - // }, - // '&.MuiInputBase-multiline': { - // padding: 1, - // }, - // }, - // input: { - // fontWeight: 500, - // background: backgroundA.default, - // padding: '15.5px 14px', - // borderRadius: `${themeColors?.borderRadius}px`, - // '&.MuiInputBase-inputSizeSmall': { - // padding: '10px 14px', - // '&.MuiInputBase-inputAdornedStart': { - // paddingLeft: 0, - // }, - // }, - // }, - // inputAdornedStart: { - // paddingLeft: 4, - // }, - // notchedOutline: { - // borderRadius: `${themeColors?.customization?.borderRadius}px`, - // }, - // }, - // }, }; -// const createColorGradient = (color1, color2, steps) => { -// const gradient = []; -// const stepFactor = 1 / (steps - 1); -// for (let i = 0; i < steps; i++) { -// gradient.push(shadeBlendConvert(i * stepFactor, color1, color2)); -// } -// return gradient; -// }; - -// TODO: TEST BOTH HEAX CONVERSION FUNCTIONS -// Utility function to convert Hex to RGBA -// const hexToRgba = (hex, alpha = 1) => { -// let shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; -// hex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b); -// let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); -// return result -// ? `rgba(${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt( -// result[3], -// 16 -// )}, ${alpha})` -// : null; -// }; -// function convertHexToRGBA(hex, alpha) { -// const r = parseInt(hex.slice(1, 3), 16); -// const g = parseInt(hex.slice(3, 5), 16); -// const b = parseInt(hex.slice(5, 7), 16); - -// return `rgba(${r}, ${g}, ${b}, ${alpha})`; -// } -// Utility functions -// const pxToRem = (number, baseNumber = 16) => { -// return `${number / baseNumber}rem`; -// }; +// specialBreakpoints: specialBreakpoints, +// const colorsA = tokens(mode); +// const specialBreakpoints = { +// isSmUp: (breakpoints) => breakpoints.up('sm'), +// isMdUp: (breakpoints) => breakpoints.up('md'), +// isLgUp: (breakpoints) => breakpoints.up('lg'), +// isXlUp: (breakpoints) => breakpoints.up('xl'), +// isSmDown: (breakpoints) => breakpoints.down('sm'), +// isMdDown: (breakpoints) => breakpoints.down('md'), +// isLgDown: (breakpoints) => breakpoints.down('lg'), +// isXlDown: (breakpoints) => breakpoints.down('xl'), -// const hexToRgba = (hex, alpha = 1) => { -// let shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; -// hex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b); -// let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); -// return result -// ? `rgba(${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}, ${alpha})` -// : null; +// isXSmall: (breakpoints) => breakpoints.down('xs'), +// isSmall: (breakpoints) => breakpoints.down('sm'), +// isSmallMedium: (breakpoints) => breakpoints.up('sm'), +// isMedium: (breakpoints) => breakpoints.down('md'), +// isMediumLarge: (breakpoints) => breakpoints.up('md'), +// isLarge: (breakpoints) => breakpoints.up('lg'), +// isXLarge: (breakpoints) => breakpoints.up('xl'), // }; - -// const rgba = (color, opacity) => { -// return hexToRgba(color, opacity); -// }; - -// const linearGradient = (color, colorState, angle = 195) => { -// return `linear-gradient(${angle}deg, ${color}, ${colorState})`; -// }; -// chart: { -// axis: { -// domain: { -// line: { -// stroke: colors.greenAccent[800], -// strokeWidth: 1, -// }, -// }, -// ticks: { -// line: { -// stroke: colors.greenAccent[700], -// strokeWidth: 1, -// }, -// text: { -// fill: colors.greenAccent[900], -// fontSize: 12, -// }, -// }, -// }, -// grid: { -// line: { -// stroke: colors.greenAccent[200], -// strokeWidth: 1, -// }, -// }, -// legends: { -// text: { -// fill: colors.greenAccent[800], -// fontSize: 12, -// }, -// }, -// tooltip: { -// container: { -// background: colors.greenAccent[100], -// color: colors.greenAccent[800], -// fontSize: 12, -// borderRadius: 4, -// boxShadow: '0 2px 4px rgba(0,0,0,0.25)', -// }, -// }, -// points: { -// borderColor: colors.greenAccent[800], -// }, -// }, -// getHeaderStyle: { -// fontWeight: 'bold', -// color: 'text.primary', -// marginBottom: 2, // theme.spacing(2) -// '@media (maxWidth:599.95px)': { -// fontSize: '1.25rem', -// }, -// '@media (minWidth:600px) and (maxWidth:899.95px)': { -// fontSize: '1.5rem', -// }, -// '@media (minWidth:900px)': { -// fontSize: '1.75rem', -// }, -// }, - -// getStyledGridStyle: { -// '@media (maxWidth:599.95px)': { -// margin: 0.5, // theme.spacing(0.5) -// }, -// '@media (minWidth:600px) and (maxWidth:1199.95px)': { -// margin: 1, // theme.spacing(1) -// }, -// '@media (minWidth:1200px)': { -// margin: 2, // theme.spacing(2) -// }, -// '@media (minWidth:1800px)': { -// margin: 2, // theme.spacing(2) -// }, -// }, - -// getStyledGridItemStyle: { -// display: 'flex', -// flexDirection: 'column', -// alignItems: 'stretch', -// '@media (maxWidth:599.95px)': { -// padding: 1, // theme.spacing(1) -// }, -// '@media (minWidth:600px)': { -// padding: 0.25, // theme.spacing(0.25) -// }, -// '@media (minWidth:1200px)': { -// padding: 1, // theme.spacing(1) -// }, -// '@media (minWidth:1800px)': { -// padding: 2, // theme.spacing(2) -// }, -// }, diff --git a/src/assets/themes/tokens.jsx b/src/assets/themes/tokens.jsx deleted file mode 100644 index e195906..0000000 --- a/src/assets/themes/tokens.jsx +++ /dev/null @@ -1,132 +0,0 @@ -export const tokens = (mode) => ({ - ...(mode === 'dark' - ? { - grey: { - 100: '#e0e0e0', - 200: '#c2c2c2', - 300: '#a3a3a3', - 400: '#858585', - 500: '#666666', - 600: '#525252', - 700: '#3d3d3d', - 800: '#292929', - 900: '#141414', - }, - primary: { - 100: '#d0d1d5', - 200: '#a1a4ab', - 300: '#727681', - 400: '#1F2A40', - 500: '#141b2d', - 600: '#101624', - 700: '#0c101b', - 800: '#080b12', - 900: '#040509', - }, - blueGreenAccent: { - 100: '#dbf5f2', // Lightest shade, more towards blue - 200: '#b7ebe6', - 300: '#93e1da', - 400: '#6fd7ce', - 500: '#4bcdc2', // Mid-value, a balanced blue-green - 600: '#39a59b', - 700: '#2b7d76', - 800: '#1d5551', - 900: '#0f2d28', // Darkest shade, deeper blue-green - }, - greenAccent: { - 100: '#dbf5ee', - 200: '#b7ebde', - 300: '#94e2cd', - 400: '#70d8bd', - 500: '#4cceac', - 600: '#3da58a', - 700: '#2e7c67', - 800: '#1e5245', - 900: '#0f2922', - }, - redAccent: { - 100: '#f8dcdb', - 200: '#f1b9b7', - 300: '#e99592', - 400: '#e2726e', - 500: '#db4f4a', - 600: '#af3f3b', - 700: '#832f2c', - 800: '#58201e', - 900: '#2c100f', - }, - blueAccent: { - 100: '#e1e2fe', - 200: '#c3c6fd', - 300: '#a4a9fc', - 400: '#868dfb', - 500: '#6870fa', - 600: '#535ac8', - 700: '#3e4396', - 800: '#2a2d64', - 900: '#151632', - }, - } - : { - grey: { - 100: '#141414', - 200: '#292929', - 300: '#3d3d3d', - 400: '#525252', - 500: '#666666', - 600: '#858585', - 700: '#a3a3a3', - 800: '#c2c2c2', - 900: '#e0e0e0', - }, - primary: { - 100: '#040509', - 200: '#080b12', - 300: '#0c101b', - 400: '#f2f0f0', // manually changed - 500: '#141b2d', - 600: '#1F2A40', - 700: '#727681', - 800: '#a1a4ab', - 900: '#d0d1d5', - }, - // secondary: { - // 100: '#ff7961', - // 200: '#f44336', - // }, - greenAccent: { - 100: '#0f2922', - 200: '#1e5245', - 300: '#2e7c67', - 400: '#3da58a', - 500: '#4cceac', - 600: '#70d8bd', - 700: '#94e2cd', - 800: '#b7ebde', - 900: '#dbf5ee', - }, - redAccent: { - 100: '#2c100f', - 200: '#58201e', - 300: '#832f2c', - 400: '#af3f3b', - 500: '#db4f4a', - 600: '#e2726e', - 700: '#e99592', - 800: '#f1b9b7', - 900: '#f8dcdb', - }, - blueAccent: { - 100: '#151632', - 200: '#2a2d64', - 300: '#3e4396', - 400: '#535ac8', - 500: '#6870fa', - 600: '#868dfb', - 700: '#a4a9fc', - 800: '#c3c6fd', - 900: '#e1e2fe', - }, - }), -}); diff --git a/src/assets/themes/typography/typography.js b/src/assets/themes/typography/typography.js deleted file mode 100644 index f620e1b..0000000 --- a/src/assets/themes/typography/typography.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - * Typography used in theme - * @param {JsonObject} theme theme customization object - */ - -export default function themeTypography(theme) { - return { - fontFamily: theme?.customization?.fontFamily, - h6: { - fontWeight: 500, - color: theme.heading, - fontSize: '0.75rem', - }, - h5: { - fontSize: '0.875rem', - color: theme.heading, - fontWeight: 500, - }, - h4: { - fontSize: '1rem', - color: theme.heading, - fontWeight: 600, - }, - h3: { - fontSize: '1.25rem', - color: theme.heading, - fontWeight: 600, - }, - h2: { - fontSize: '1.5rem', - color: theme.heading, - fontWeight: 700, - }, - h1: { - fontSize: '2.125rem', - color: theme.heading, - fontWeight: 700, - }, - subtitle1: { - fontSize: '0.875rem', - fontWeight: 500, - color: theme.textDark, - }, - subtitle2: { - fontSize: '0.75rem', - fontWeight: 400, - color: theme.darkTextSecondary, - }, - caption: { - fontSize: '0.75rem', - color: theme.darkTextSecondary, - fontWeight: 400, - }, - body1: { - fontSize: '0.875rem', - fontWeight: 400, - lineHeight: '1.334em', - }, - body2: { - letterSpacing: '0em', - fontWeight: 400, - lineHeight: '1.5em', - color: theme.darkTextPrimary, - }, - button: { - textTransform: 'capitalize', - }, - customInput: { - marginTop: 1, - marginBottom: 1, - '& > label': { - top: 23, - left: 0, - color: theme.grey500, - '&[data-shrink="false"]': { - top: 5, - }, - }, - '& > div > input': { - padding: '30.5px 14px 11.5px !important', - }, - '& legend': { - display: 'none', - }, - '& fieldset': { - top: 0, - }, - }, - mainContent: { - backgroundColor: theme.background, - width: '100%', - minHeight: 'calc(100vh - 88px)', - flexGrow: 1, - padding: '20px', - marginTop: '88px', - marginRight: '20px', - borderRadius: `${theme?.customization?.borderRadius}px`, - }, - menuCaption: { - fontSize: '0.875rem', - fontWeight: 500, - color: theme.heading, - padding: '6px', - textTransform: 'capitalize', - marginTop: '10px', - }, - subMenuCaption: { - fontSize: '0.6875rem', - fontWeight: 500, - color: theme.darkTextSecondary, - textTransform: 'capitalize', - }, - commonAvatar: { - cursor: 'pointer', - borderRadius: '8px', - }, - smallAvatar: { - width: '22px', - height: '22px', - fontSize: '1rem', - }, - mediumAvatar: { - width: '34px', - height: '34px', - fontSize: '1.2rem', - }, - largeAvatar: { - width: '44px', - height: '44px', - fontSize: '1.5rem', - }, - }; -} diff --git a/src/components/buttons/other/ReusableLoadingButton.jsx b/src/components/buttons/other/ReusableLoadingButton.jsx new file mode 100644 index 0000000..1f2b66e --- /dev/null +++ b/src/components/buttons/other/ReusableLoadingButton.jsx @@ -0,0 +1,58 @@ +// ReusableLoadingButton.js +import React from 'react'; +import { LoadingButton } from '@mui/lab'; +import LoginIcon from '@mui/icons-material/Login'; + +const baseButtonStyles = { + bgcolor: '#6a59ff', + borderColor: '#6a59ff', + borderWidth: 2, + borderStyle: 'solid', + display: 'flex', + flexGrow: 1, + alignItems: 'center', + justifyContent: 'center', + marginLeft: 'auto', + marginRight: 'auto', + marginBottom: '16px', + marginTop: '16px', + position: 'relative', + bottom: 0, + cursor: 'pointer', + transition: 'background-color 0.3s, border-color 0.3s, color 0.3s', + ':hover': { + fontWeight: 'bold', + bgcolor: '#4a6da7', + borderColor: '#34597f', + }, + ':focus': { + outline: '2px solid #62a4ff', + outlineOffset: 2, + }, +}; + +const ReusableLoadingButton = ({ + loading, + label, + icon, + onClick, + style, + fullWidth, + sx, +}) => ( + } + fullWidth={fullWidth} + sx={sx} + onClick={onClick} + > + {label} + +); + +export default ReusableLoadingButton; diff --git a/src/components/componentHelpers.jsx b/src/components/componentHelpers.jsx index c5ce162..cf5f519 100644 --- a/src/components/componentHelpers.jsx +++ b/src/components/componentHelpers.jsx @@ -1,4 +1,3 @@ -// Desc: Helper functions for components export const getQuantity = ({ card, cartData, @@ -7,7 +6,6 @@ export const getQuantity = ({ selectedDeck, allDecks, }) => { - // Helper function to find the quantity of a card in a list of collections or decks const findCardQuantity = (collectionsOrDecks, cardId) => collectionsOrDecks?.reduce( (acc, item) => diff --git a/src/components/dialogs/CollectionDialog.jsx b/src/components/dialogs/CollectionDialog.jsx index 5147405..b2cb527 100644 --- a/src/components/dialogs/CollectionDialog.jsx +++ b/src/components/dialogs/CollectionDialog.jsx @@ -6,6 +6,8 @@ import { CssBaseline, Dialog, DialogContent, + DialogTitle, + Divider, Grid, Paper, } from '@mui/material'; @@ -16,6 +18,12 @@ import UpdateCollectionForm from '../forms/UpdateCollectionForm'; import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; import { withDynamicSnackbar } from '../../layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; +import { + DialogPaper, + StyledDialog, + StyledDialogContent, +} from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; +import MDAvatar from '../../layout/REUSABLE_COMPONENTS/MDAVATAR'; const CollectionDialog = ({ open, onClose, @@ -23,7 +31,14 @@ const CollectionDialog = ({ collectionData, collectionMode, }) => { - const { currentForm, setCurrentForm } = useFormContext(); + const { + formMethods, + onSubmit, + setFormSchema, + currentSchemaKey, + currentForm, + setCurrentForm, + } = useFormContext(); const { theme } = useMode(); useEffect(() => { @@ -33,100 +48,66 @@ const CollectionDialog = ({ }, [collectionMode, setCurrentForm]); return ( - - - + + - {/* */} - - - - - - - - {currentForm === 'addCollectionForm' - ? 'Add a Collection' - : 'Update a Collection'} - - - - {currentForm === 'addCollectionForm' ? ( - - ) : ( - - )} - - - - - - - - + + + + + {currentForm === 'addCollectionForm' + ? 'Add a Collection' + : 'Update a Collection'} + + + {' '} + + + + + {currentForm === 'addCollectionForm' ? ( + + ) : ( + + )} + + ); }; CollectionDialog.propTypes = { - // open: PropTypes.bool.isRequired, - // onClose: PropTypes.func.isRequired, + open: PropTypes.bool.isRequired, + onClose: PropTypes.func.isRequired, isNew: PropTypes.bool, collectionData: PropTypes.shape({ name: PropTypes.string, diff --git a/src/components/dialogs/DeckEditPanel.js b/src/components/dialogs/DeckEditPanel.js index 532d924..9cbf4ed 100644 --- a/src/components/dialogs/DeckEditPanel.js +++ b/src/components/dialogs/DeckEditPanel.js @@ -20,10 +20,8 @@ import { FormBox } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledC import FormField from '../forms/reusable/FormField'; const DeckEditPanel = ({ selectedDeck, showSnackbar }) => { const { theme } = useMode(); - // const { showSnackbar } = useSnackBar(); // Assuming snackbar hook for user notifications const { formMethods, - // formStates: { errors, isSubmitting, ...formStates }, register, handleSubmit, setValue, @@ -32,9 +30,7 @@ const DeckEditPanel = ({ selectedDeck, showSnackbar }) => { reset, setFormSchema, onSubmit, - // Removal of onSubmit from destructuring as we will define a local handler } = useFormContext(); - // Local state for dynamic fields like tags const [newTag, setNewTag] = useState(''); const tags = watch('tags', selectedDeck?.tags || []); const color = watch('color'); @@ -67,8 +63,7 @@ const DeckEditPanel = ({ selectedDeck, showSnackbar }) => { }; const handleFormSubmit = async (data) => { try { - // Assuming `onSubmit` is a function passed via context or props that handles the actual submission - await onSubmit(data); // Adjust based on actual implementation + await onSubmit(data); showSnackbar({ message: 'Deck updated successfully', variant: 'success', @@ -80,22 +75,6 @@ const DeckEditPanel = ({ selectedDeck, showSnackbar }) => { }); } }; - // const handleDeleteClick = async () => { - // try { - // // await deleteDeck(selectedDeck._id); - // showSnackbar({ - // message: 'Deck deleted successfully', - // variant: 'warning', - // }); - // reset(); // Optionally reset form state - // } catch (error) { - // showSnackbar({ - // message: error.message || 'Failed to delete deck', - // variant: 'error', - // }); - // } - // }; - return ( { Color setColor(e.target.value)} -// > -// Red -// Blue -// Green -// Yellow -// -// -// -// -// -// -// -// -// ); -// }; -// export default DeckEditPanel; +export default withDynamicSnackbar(DeckEditPanel); diff --git a/src/components/dialogs/LoginDialog.jsx b/src/components/dialogs/LoginDialog.jsx index 7649763..a4b22a5 100644 --- a/src/components/dialogs/LoginDialog.jsx +++ b/src/components/dialogs/LoginDialog.jsx @@ -42,7 +42,7 @@ import { AuthModeSwitch } from '../../layout/REUSABLE_STYLED_COMPONENTS/Specific import AuthSwitch from '../buttons/other/AuthSwitch'; import SimpleButton from '../../layout/REUSABLE_COMPONENTS/unique/SimpleButton'; -function LoginDialog({ showSnackbar }) { +function LoginDialog() { const { theme, toggleColorMode, mode } = useMode(); const { toggleLoginDialog, isLoggedIn, logout } = useAuthDialog(); // const { currentForm, setFormSchema } = useFormContext(); @@ -122,36 +122,17 @@ function LoginDialog({ showSnackbar }) { {formTitle} - {/* */} - {/* */} {currentSchemaKey === 'loginForm' ? ( - + ) : ( - + )} - {/* */} } label="Remember me" @@ -177,4 +158,4 @@ function LoginDialog({ showSnackbar }) { ); } -export default withDynamicSnackbar(LoginDialog); +export default LoginDialog; diff --git a/src/components/forms/AddCollectionForm.jsx b/src/components/forms/AddCollectionForm.jsx index b64b9d8..fa91a53 100644 --- a/src/components/forms/AddCollectionForm.jsx +++ b/src/components/forms/AddCollectionForm.jsx @@ -14,6 +14,7 @@ import { FormBox, FormFieldBox, } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; +import ReusableLoadingButton from '../buttons/other/ReusableLoadingButton'; const AddCollectionForm = ({ showSnackbar }) => { const formId = 'addCollectionForm'; @@ -29,12 +30,25 @@ const AddCollectionForm = ({ showSnackbar }) => { }); const fields = [ - { name: 'name', label: 'Name', type: 'text' }, - { name: 'description', label: 'Description', type: 'text' }, + { + name: 'name', + label: 'Name', + type: 'text', + required: true, + multiline: false, + }, + { + name: 'description', + label: 'Description', + type: 'text', + required: true, + multiline: true, + rows: 4, + }, ]; + const onFormSubmit = async (data) => { try { - // Simulate form submission await new Promise((resolve) => setTimeout(resolve, 2000)); // Simulated delay onSubmit(data, formId); showSnackbar( @@ -60,42 +74,34 @@ const AddCollectionForm = ({ showSnackbar }) => { component={'form'} theme={theme} onSubmit={handleSubmit(onFormSubmit)} - style={{ - display: 'flex', - flexDirection: 'column', - flexGrow: 1, - margin: 2, - padding: 2, - }} > - - - - - - - ( + + + + ))} + - Create Collection - + sx={{ + mt: 2, // Adjust spacing as needed + background: theme.palette.backgroundG.light, + borderColor: theme.palette.backgroundG.light, + borderWidth: 2, + '&:hover': { background: theme.palette.backgroundG.default }, + '&:focus': { background: theme.palette.backgroundG.default }, + }} + /> ); }; diff --git a/src/components/forms/LoginForm.jsx b/src/components/forms/LoginForm.jsx index 06fcbe1..32ae609 100644 --- a/src/components/forms/LoginForm.jsx +++ b/src/components/forms/LoginForm.jsx @@ -10,10 +10,6 @@ import { import FormField from './reusable/FormField'; import { LoadingButton } from '@mui/lab'; import { useFormContext, useMode } from '../../context'; -import { withDynamicSnackbar } from '../../layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; -import { CopyrightOutlined } from '@mui/icons-material'; -import LockOutlinedIcon from '@material-ui/icons/LockOutlined'; -import AuthSwitch from '../buttons/other/AuthSwitch'; import LoginIcon from '@mui/icons-material/Login'; import PersonIcon from '@mui/icons-material/Person'; import LockIcon from '@mui/icons-material/Lock'; @@ -21,7 +17,9 @@ import { FormBox, FormFieldBox, } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; -import SimpleButton from '../../layout/REUSABLE_COMPONENTS/unique/SimpleButton'; +import ReusableLoadingButton from '../buttons/other/ReusableLoadingButton'; +// import useSubmitHandler from './hooks/useSubmitHandler'; +// import useCustomSnackbar from '../../context/hooks/useCustomSnackbar'; const baseButtonStyles = { bgcolor: '#6a59ff', // background-color borderColor: '#6a59ff', @@ -49,7 +47,9 @@ const baseButtonStyles = { outlineOffset: 2, }, }; -const LoginForm = ({ showSnackbar, signupMode, toggleAuthMode, formLabel }) => { +const LoginForm = () => { + // const showSnackbar = useCustomSnackbar(); + const { formMethods, onSubmit, setFormSchema } = useFormContext(); const { theme } = useMode(); const { @@ -75,21 +75,28 @@ const LoginForm = ({ showSnackbar, signupMode, toggleAuthMode, formLabel }) => { icon: , }, ]; - + // const onFormSubmit = useSubmitHandler( + // onSubmit(data, 'loginForm'), // Assuming this is the function that performs the submission logic + // 'Success', // Title for the success message + // "You've successfully logged in.", // Success description + // 'Login failed. Please try again.' // Error description + // ); const onFormSubmit = (data) => { - onSubmit(data, 'loginForm') - .then(() => { - showSnackbar( - { title: 'Success', description: "You've successfully logged in." }, - 'success' - ); - }) - .catch((error) => { - showSnackbar( - { title: 'Error', description: 'Login failed. Please try again.' }, - 'error' - ); - }); + // showSnackbar('Loading...', 'Logging in...', { variant: 'info' }); + onSubmit(data, 'loginForm'); + // .then(() => { + // showSnackbar('Success!', "You've successfully logged in.", { + // variant: 'success', + // persist: true, + // }); + // }) + // .catch((error) => { + // showSnackbar( + // 'Error', + // 'Login failed. Please try again.' + `: ${error}`, + // { variant: 'error', persist: true } + // ); + // }); }; return ( { )} ))} - {/* */} - { }} > Login - + */} + } + fullWidth + sx={{ + mt: 2, // margin-top: Adjust if necessary + background: theme.palette.backgroundG.light, + '&:hover': { background: theme.palette.backgroundG.default }, + }} + /> ); }; -export default withDynamicSnackbar(LoginForm); +export default LoginForm; diff --git a/src/components/forms/SearchForm.jsx b/src/components/forms/SearchForm.jsx index 2902961..7b583a8 100644 --- a/src/components/forms/SearchForm.jsx +++ b/src/components/forms/SearchForm.jsx @@ -9,16 +9,15 @@ import { FormBox } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledC import { LoadingButton } from '@mui/lab'; import FormField from './reusable/FormField'; -const SearchForm = ({ onFocus, onBlur }) => { +const SearchForm = () => { const { theme } = useMode(); - const formId = 'searchForm'; // Define the form ID for schema selection + const formId = 'searchForm'; const { formMethods, formStates: { errors, isSubmitting, ...formStates }, onSubmit, handleFieldChange, handleSearchTermChange, - // handleChange, handleBlur, handleFocus, forms, @@ -30,15 +29,6 @@ const SearchForm = ({ onFocus, onBlur }) => { setFormSchema(formId); }, [setFormSchema]); - // const handleChange = (e) => { - // const { name, value } = e.target; - // if (name === 'searchTerm') { - // handleSearchTermChange(value); // Call the method when searchTerm changes - // } - // handleFieldChange(formId, name, value); // Continue to update the form state as before - // }; - - // const { searchTerm } = formStates?.searchForm; const handleKeyPress = (e) => { if (e.key === 'Enter') { e.preventDefault(); diff --git a/src/components/forms/SignupForm.jsx b/src/components/forms/SignupForm.jsx index 3e6e74f..c569194 100644 --- a/src/components/forms/SignupForm.jsx +++ b/src/components/forms/SignupForm.jsx @@ -45,7 +45,7 @@ const baseButtonStyles = { }, }; const SignupForm = ({ - showSnackbar, + // showSnackbar, signupMode, toggleAuthMode, formLabel, @@ -72,19 +72,19 @@ const SignupForm = ({ // Updated onFormSubmit to directly use onSubmit from context const onFormSubmit = (data) => { - onSubmit(data, 'signupForm') - .then(() => { - showSnackbar( - { title: 'Success', description: "You've successfully signed up." }, - 'success' - ); - }) - .catch((error) => { - showSnackbar( - { title: 'Error', description: 'Signup failed. Please try again.' }, - 'error' - ); - }); + onSubmit(data, 'signupForm'); + // .then(() => { + // showSnackbar( + // { title: 'Success', description: "You've successfully signed up." }, + // 'success' + // ); + // }) + // .catch((error) => { + // showSnackbar( + // { title: 'Error', description: 'Signup failed. Please try again.' }, + // 'error' + // ); + // }); }; // useEffect(() => { // setIsFormDataLoading(isSubmitting); diff --git a/src/components/forms/formsConfig.jsx b/src/components/forms/formsConfig.jsx index a2757f4..9780bdd 100644 --- a/src/components/forms/formsConfig.jsx +++ b/src/components/forms/formsConfig.jsx @@ -1,11 +1,56 @@ +import LoginIcon from '@mui/icons-material/Login'; +import PersonIcon from '@mui/icons-material/Person'; +import LockIcon from '@mui/icons-material/Lock'; +// TODO: ADD EMAIL ICON +// TODO: ADD First ICON +// TODO: ADD Last ICON +// TODO: ADD General Name ICON +// TODO: ADD Description ICON + const auth = [ - { name: 'firstName', label: 'First Name', type: 'text' }, - { name: 'lastName', label: 'Last Name', type: 'text' }, - { name: 'email', label: 'Email', type: 'email' }, - { name: 'username', label: 'Username', type: 'text' }, - { name: 'password', label: 'Password', type: 'password' }, + { name: 'firstName', label: 'First Name', type: 'text', icon: <> }, + { name: 'lastName', label: 'Last Name', type: 'text', icon: <> }, + { name: 'email', label: 'Email', type: 'email', icon: <> }, + { + name: 'username', + label: 'Username', + type: 'text', + icon: , + }, + { + name: 'password', + label: 'Password', + type: 'password', + icon: , + }, ]; const collection = [ - { name: 'name', label: 'Name', type: 'text' }, - { name: 'description', label: 'Description', type: 'text' }, + { + name: 'name', + label: 'Name', + type: 'text', + icon: <>, + required: true, + multiline: false, + }, + { + name: 'description', + label: 'Description', + type: 'text', + icon: <>, + required: true, + multiline: true, + rows: 4, + }, ]; +const deck = [ + { name: 'name', label: 'Name', type: 'text', icon: <> }, + { name: 'description', label: 'Description', type: 'text', icon: <> }, +]; +const formData = { + auth, + collection, + deck, +}; + +export default formData; diff --git a/src/components/forms/hooks/useSubmitHandler.jsx b/src/components/forms/hooks/useSubmitHandler.jsx new file mode 100644 index 0000000..52e5725 --- /dev/null +++ b/src/components/forms/hooks/useSubmitHandler.jsx @@ -0,0 +1,36 @@ +import { useCallback } from 'react'; +import useCustomSnackbar from '../../../context/hooks/useCustomSnackbar'; + +function useSubmitHandler( + onSubmit, + successTitle, + successDescription, + errorDescription +) { + const showSnackbar = useCustomSnackbar(); + + return useCallback( + (data, formType) => { + onSubmit(data, formType) + .then(() => { + showSnackbar( + successTitle, + successDescription.replace('{timeRange}', data?.timeRange), + { variant: 'success' } + ); + }) + .catch((error) => { + showSnackbar( + 'Error', + errorDescription.replace('{timeRange}', data?.timeRange) + + `: ${error}`, + { variant: 'error' } + ); + }); + }, + // `showSnackbar` is now a dependency of useCallback + [onSubmit, showSnackbar, successTitle, successDescription, errorDescription] + ); +} + +export default useSubmitHandler; diff --git a/src/components/forms/index.jsx b/src/components/forms/index.jsx index f8ca92c..53c6b15 100644 --- a/src/components/forms/index.jsx +++ b/src/components/forms/index.jsx @@ -1,2 +1,20 @@ -import CollectionForm from './CollectionForm'; -import ProfileForm from './ProfileForm'; +import SignupForm from './SignupForm'; +import LoginForm from './LoginForm'; +import SearchForm from './SearchForm'; +import UpdateCollectionForm from './UpdateCollectionForm'; +import AddCollectionForm from './AddCollectionForm'; +import AddDeckForm from './AddDeckForm'; +import UpdateDeckForm from './UpdateDeckForm'; +import SearchSettingsForm from './SearchSettingsForm'; + +const forms = { + signup: SignupForm, + login: LoginForm, + search: SearchForm, + updateCollection: UpdateCollectionForm, + addCollection: AddCollectionForm, + updateDeck: UpdateDeckForm, + addDeck: AddDeckForm, +}; + +export default forms; diff --git a/src/components/forms/reusable/Select.jsx b/src/components/forms/reusable/Select.jsx index cf0e3c6..8fc0a9d 100644 --- a/src/components/forms/reusable/Select.jsx +++ b/src/components/forms/reusable/Select.jsx @@ -71,7 +71,7 @@ const SelectComponent = React.forwardRef( }, }} > - + {/* Select Option - + */} {options.map((option) => ( {option.label} diff --git a/src/components/forms/selectors/ThemeSelector.jsx b/src/components/forms/selectors/ThemeSelector.jsx index 25e6fca..ef64bd1 100644 --- a/src/components/forms/selectors/ThemeSelector.jsx +++ b/src/components/forms/selectors/ThemeSelector.jsx @@ -3,10 +3,9 @@ import { FormControl, InputLabel } from '@mui/material'; import { Controller } from 'react-hook-form'; import { useSnackbar } from 'notistack'; -import SelectComponent from '../reusable/Select'; import { useFormContext, useMode } from '../../../context'; import { StyledChartBox } from '../../../pages/pageStyles/StyledComponents'; -import MDTypography from '../../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; +import SelectComponent from '../reusable/Select'; const ThemeSelector = ({ setTheme }) => { const { theme } = useMode(); diff --git a/src/components/forms/selectors/TimeRangeSelector.jsx b/src/components/forms/selectors/TimeRangeSelector.jsx index ef4f184..49b66f7 100644 --- a/src/components/forms/selectors/TimeRangeSelector.jsx +++ b/src/components/forms/selectors/TimeRangeSelector.jsx @@ -2,10 +2,11 @@ import { useMemo } from 'react'; import { useFormContext, useMode } from '../../../context'; import useSelectedCollection from '../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; import { StyledChartBox } from '../../../pages/pageStyles/StyledComponents'; -import { FormControl, InputLabel } from '@mui/material'; +import { FormControl, InputLabel, Typography } from '@mui/material'; import { Controller } from 'react-hook-form'; import SelectComponent from '../reusable/Select'; import useTimeRange from './useTimeRange'; +import MDTypography from '../../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; const TimeRangeSelector = ({ showSnackbar }) => { const { theme } = useMode(); @@ -25,7 +26,20 @@ const TimeRangeSelector = ({ showSnackbar }) => { error={!!errors.timeRange} sx={{ width: '100%' }} > - Time Range + + {/* */} + Time Range + {/* */} + { ); }; export default TimeRangeSelector; - -// // const TimeRangeSelector = ({ showSnackbar }) => { -// // const { theme } = useMode(); -// // const { formMethods, onSubmit } = useFormContext(); -// // const { selectedCollection } = useSelectedCollection(); -// // const averagedChartData = selectedCollection?.averagedChartData; - -// // const timeRangeOptions = useMemo(() => { -// // const options = []; -// // averagedChartData?.forEach((value, key) => { -// // options.push({ -// // value: key, -// // label: key.toUpperCase(), -// // }); -// // }); -// // return options; -// // }, [averagedChartData]); - -// // const { -// // control, -// // handleSubmit, -// // formState: { errors }, -// // } = formMethods; - -// // const onFormSubmit = (data) => { -// // onSubmit(data, 'timeRangeSelector') -// // .then(() => { -// // showSnackbar( -// // { -// // title: 'Success', -// // description: `Now viewing chart data for ${data?.timeRange}`, -// // }, -// // 'success' -// // ); -// // }) -// // .catch((error) => { -// // showSnackbar( -// // { -// // title: 'Error', -// // description: `Failed to view chart data for ${data?.timeRange}: ${error}`, -// // }, -// // 'error' -// // ); -// // }); -// // }; - -// // return ( -// // -// // -// // Time Range -// // ( -// // -// // )} -// // /> -// // -// // -// // ); -// // }; - -// // export default TimeRangeSelector; -// // import React, { useMemo } from 'react'; -// // import { useFormContext, Controller } from 'react-hook-form'; -// // import { FormControl, InputLabel } from '@mui/material'; -// // import { useMode } from '../../../../context'; -// // import useSelectedCollection from '../../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; -// // import SelectComponent from '../../../REUSABLE_COMPONENTS/SelectComponent'; -// // import StyledChartBox from '../../../REUSABLE_COMPONENTS/StyledChartBox'; - -// const TimeRangeSelector = ({ showSnackbar }) => { -// const { theme } = useMode(); -// const { formMethods, onSubmit } = useFormContext(); -// const { selectedCollection } = useSelectedCollection(); -// const averagedChartData = selectedCollection?.averagedChartData; - -// // Convert the Map to an array of options for the select component -// const timeRangeOptions = useMemo(() => { -// return Array.from(averagedChartData?.entries() || []).map( -// ([key, value]) => ({ -// value: key, -// label: value.name.toUpperCase(), -// }) -// ); -// }, [averagedChartData]); - -// const { -// control, -// handleSubmit, -// formState: { errors }, -// } = formMethods; - -// const onFormSubmit = (data) => { -// onSubmit(data, 'timeRangeSelector') -// .then(() => { -// showSnackbar( -// { -// title: 'Success', -// description: `Now viewing chart data for ${data?.timeRange}`, -// }, -// 'success' -// ); -// }) -// .catch((error) => { -// showSnackbar( -// { -// title: 'Error', -// description: `Failed to view chart data for ${data?.timeRange}: ${error}`, -// }, -// 'error' -// ); -// }); -// }; - -// return ( -// -// -// Time Range -// ( -// -// )} -// /> -// -// -// ); -// }; - -// export default TimeRangeSelector; diff --git a/src/components/forms/selectors/useTimeRange.jsx b/src/components/forms/selectors/useTimeRange.jsx index 497d24a..ef35901 100644 --- a/src/components/forms/selectors/useTimeRange.jsx +++ b/src/components/forms/selectors/useTimeRange.jsx @@ -1,46 +1,53 @@ import { useMemo, useCallback } from 'react'; import { useFormContext } from '../../../context'; import useSelectedCollection from '../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; +import useSubmitHandler from '../hooks/useSubmitHandler'; function useTimeRange(showSnackbar) { const { formMethods, onSubmit } = useFormContext(); const { selectedCollection } = useSelectedCollection(); const averagedChartData = selectedCollection?.averagedChartData; - + const selectedTimeRange = formMethods.watch('timeRange', '24hr'); const timeRangeOptions = useMemo(() => { - return Object.keys(averagedChartData || {}).map((key) => ({ - value: key, - label: key.toUpperCase(), - })); + return Object.entries(averagedChartData || {}).map(([key, value]) => { + // console.log(`Key: ${key}, Value: `, value); + return { + value: value?.id, + label: value?.name?.toUpperCase(), + }; + }); }, [averagedChartData]); - - // Watching the "timeRange" field to get its current value - const selectedTimeRange = formMethods.watch('timeRange', '24hr'); - - const onFormSubmit = useCallback( - (data) => { - onSubmit(data, 'timeRangeSelector') - .then(() => { - showSnackbar( - { - title: 'Success', - description: `Now viewing chart data for ${data?.timeRange}`, - }, - 'success' - ); - }) - .catch((error) => { - showSnackbar( - { - title: 'Error', - description: `Failed to view chart data for ${data?.timeRange}: ${error}`, - }, - 'error' - ); - }); - }, - [onSubmit, showSnackbar] + const onFormSubmit = useSubmitHandler( + onSubmit, + showSnackbar, + 'Success', + 'Now viewing chart data for {timeRange}', + 'Failed to view chart data for {timeRange}' ); + // const onFormSubmit = useCallback( + // (data) => { + // onSubmit(data, 'timeRangeSelector') + // .then(() => { + // showSnackbar( + // { + // title: 'Success', + // description: `Now viewing chart data for ${data?.timeRange}`, + // }, + // 'success' + // ); + // }) + // .catch((error) => { + // showSnackbar( + // { + // title: 'Error', + // description: `Failed to view chart data for ${data?.timeRange}: ${error}`, + // }, + // 'error' + // ); + // }); + // }, + // [onSubmit, showSnackbar] + // ); return { timeRangeOptions, diff --git a/src/context/MAIN_CONTEXT/AuthContext/authContext.js b/src/context/MAIN_CONTEXT/AuthContext/authContext.js index 46cf135..82f390c 100644 --- a/src/context/MAIN_CONTEXT/AuthContext/authContext.js +++ b/src/context/MAIN_CONTEXT/AuthContext/authContext.js @@ -8,14 +8,10 @@ import React, { useMemo, useState, } from 'react'; -import axios from 'axios'; import { useCookies } from 'react-cookie'; -import { usePageContext } from '../../UTILITIES_CONTEXT/PageContext/PageContext'; -import { processResponseData } from './helpers'; import useLogger from '../../hooks/useLogger'; import { defaultContextValue } from '../../constants'; import { Redirect, useNavigate } from 'react-router-dom'; -import { useLoading } from '../../hooks/useLoading'; import useFetchWrapper from '../../hooks/useFetchWrapper'; import jwt_decode from 'jwt-decode'; diff --git a/src/context/UTILITIES_CONTEXT/PageContext/PageContext.jsx b/src/context/UTILITIES_CONTEXT/PageContext/PageContext.jsx index ea2af24..a9748f3 100644 --- a/src/context/UTILITIES_CONTEXT/PageContext/PageContext.jsx +++ b/src/context/UTILITIES_CONTEXT/PageContext/PageContext.jsx @@ -7,10 +7,9 @@ import React, { } from 'react'; import LoadingIndicator from '../../../components/reusable/indicators/LoadingIndicator'; import ErrorIndicator from '../../../components/reusable/indicators/ErrorIndicator'; -import SplashPage2 from '../../../pages/SplashPage2'; -import useSnackBar from '../../hooks/useSnackBar'; +import SplashPage2 from '../../../layout/REUSABLE_COMPONENTS/SplashPage2'; +// import useSnackBar from '../../hooks/useSnackBar'; import { defaultContextValue } from '../../constants'; -import { DynamicSnackbar } from '../../../layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; import { useLoading } from '../../hooks/useLoading'; const PageContext = createContext(defaultContextValue.PAGE_CONTEXT); @@ -25,13 +24,13 @@ export const PageProvider = ({ children }) => { error, clearLoading, } = useLoading(); - const { snackbar, handleSnackBar, handleCloseSnackbar } = useSnackBar(); + // const { snackbar, handleSnackBar, handleCloseSnackbar } = useSnackBar(); - const handleLoadingCompletion = () => { - if (!isAnyLoading()) { - handleSnackBar('Loading completed', 'success'); - } - }; + // const handleLoadingCompletion = () => { + // if (!isAnyLoading()) { + // handleSnackBar('Loading completed', 'success'); + // } + // }; const returnDisplay = () => { if (error) { return ; diff --git a/src/context/UTILITIES_CONTEXT/SnackbarContext/SnackbarContext.jsx b/src/context/UTILITIES_CONTEXT/SnackbarContext/SnackbarContext.jsx new file mode 100644 index 0000000..3492e2a --- /dev/null +++ b/src/context/UTILITIES_CONTEXT/SnackbarContext/SnackbarContext.jsx @@ -0,0 +1,49 @@ +// // CustomSnackbarContext.js +// import React, { createContext, useContext } from 'react'; +// import { useSnackbar } from 'notistack'; +// import { Box, CircularProgress, Typography } from '@mui/material'; + +// // Create the context +// const CustomSnackbarContext = createContext(); + +// // Define a provider component +// export const SnackbarContextProvider = ({ children }) => { +// const { enqueueSnackbar } = useSnackbar(); + +// // Define the showSnackbar function +// const showSnackbar = (title, subTitle, options = {}) => { +// const content = ( +// +// {title} +// +// {subTitle} +// +// +// ); + +// enqueueSnackbar(content, { +// ...options, +// action: options.persist +// ? (key) => +// : undefined, +// }); +// }; + +// // Provide the showSnackbar function to children +// return ( +// +// {children} +// +// ); +// }; + +// // Custom hook to use the context +// export const useSnackbarContext = () => { +// const context = useContext(CustomSnackbarContext); +// if (context === undefined) { +// throw new Error( +// 'useCustomSnackbar must be used within a CustomSnackbarProvider' +// ); +// } +// return context; +// }; diff --git a/src/context/hooks/useCustomSnackbar.jsx b/src/context/hooks/useCustomSnackbar.jsx new file mode 100644 index 0000000..b29f8e9 --- /dev/null +++ b/src/context/hooks/useCustomSnackbar.jsx @@ -0,0 +1,31 @@ +// useCustomSnackbar.js +import React from 'react'; +import { useSnackbar } from 'notistack'; +import { Box, CircularProgress, Typography } from '@mui/material'; + +const useCustomSnackbar = () => { + const { enqueueSnackbar } = useSnackbar(); + + // Define the showSnackbar function + const showSnackbar = (title, subTitle, options = {}) => { + const content = ( + + {title} + + {subTitle} + + + ); + + enqueueSnackbar(content, { + ...options, + action: options.persist + ? (key) => + : undefined, + }); + }; + + return showSnackbar; +}; + +export default useCustomSnackbar; diff --git a/src/context/hooks/useDialog.jsx b/src/context/hooks/useDialog.jsx index ca69d76..41f41bb 100644 --- a/src/context/hooks/useDialog.jsx +++ b/src/context/hooks/useDialog.jsx @@ -1,9 +1,9 @@ import { useState, useCallback } from 'react'; -import useSnackBar from './useSnackBar'; +// import useSnackBar from './useSnackBar'; const useDialog = () => { const [dialogOpenStates, setDialogOpenStates] = useState({}); - const { handleSnackBar } = useSnackBar(); // Destructure handleSnackBar from useSnackBar hook + // const { handleSnackBar } = useSnackBar(); // Destructure handleSnackBar from useSnackBar hook // Toggle the state of the dialog and display snack bar message const toggleDialogState = useCallback( @@ -12,13 +12,13 @@ const useDialog = () => { ...prevStates, [dialogName]: isOpen, })); - const action = isOpen ? 'opened' : 'closed'; - handleSnackBar(`${dialogName} Dialog ${action}`, { - variant: 'info', - duration: 6000, - }); // Use enqueueSnackbar to show a snackbar + // const action = isOpen ? 'opened' : 'closed'; + // handleSnackBar(`${dialogName} Dialog ${action}`, { + // variant: 'info', + // duration: 6000, + // }); // Use enqueueSnackbar to show a snackbar }, - [handleSnackBar] + [setDialogOpenStates] ); const openDialog = useCallback( diff --git a/src/context/hooks/useFetchWrapper.jsx b/src/context/hooks/useFetchWrapper.jsx index d2b24a0..ce889f1 100644 --- a/src/context/hooks/useFetchWrapper.jsx +++ b/src/context/hooks/useFetchWrapper.jsx @@ -1,76 +1,12 @@ -// import { useState, useCallback } from 'react'; -// import useLogger from './useLogger'; -// import useLocalStorage from './useLocalStorage'; -// import { useLoading } from './useLoading'; - -// const useFetchWrapper = () => { -// const [status, setStatus] = useState('idle'); // 'idle', 'loading', 'success', 'error' -// const [data, setData] = useState(null); -// const [responseCache, setResponseCache] = useLocalStorage('apiResponses', {}); -// const [error, setError] = useState(null); -// const { logEvent } = useLogger('useFetchWrapper'); -// const { startLoading, stopLoading, isLoading } = useLoading(); - -// const fetchWrapper = useCallback( -// async (url, method = 'GET', body = null, loadingID) => { -// setStatus('loading'); -// startLoading(loadingID); -// try { -// const headers = { 'Content-Type': 'application/json' }; -// const options = { -// method, -// headers, -// ...(body && { body: JSON.stringify(body) }), -// }; -// const response = await fetch(url, options); -// const contentType = response.headers.get('content-type'); -// let responseData; - -// if (contentType && !contentType.includes('application/json')) { -// // Handle non-JSON responses first -// responseData = await response.text(); -// } else { -// // Fallback to JSON if the content type is application/json -// responseData = await response.json(); -// } -// if (!response.ok) { -// throw new Error(`An error occurred: ${response.statusText}`); -// } -// setStatus('success'); -// setData(responseData); -// setResponseCache((prevCache) => ({ -// ...prevCache, -// [loadingID]: responseData, // Use loadingID as the key -// })); - -// return responseData; -// } catch (error) { -// setError(error.toString()); -// setStatus('error'); -// logEvent('fetch error', { url, error: error.toString() }); -// } finally { -// stopLoading(loadingID); -// } -// }, -// [setResponseCache, startLoading, stopLoading, logEvent] -// ); -// return { -// status, -// data, -// responseCache, -// error, -// fetchWrapper, -// isLoading, -// }; -// }; - // export default useFetchWrapper; -import { useState, useCallback } from 'react'; +import { useState, useCallback, useContext } from 'react'; import useLogger from './useLogger'; import useLocalStorage from './useLocalStorage'; import { useLoading } from './useLoading'; -import { useSnackbar } from 'notistack'; +// import { useSnackbar } from 'notistack'; import CircularProgress from '@mui/material/CircularProgress'; +import { Box, Typography } from '@mui/material'; +import useCustomSnackbar from './useCustomSnackbar'; const useFetchWrapper = () => { const [status, setStatus] = useState('idle'); // 'idle', 'loading', 'success', 'error' @@ -79,20 +15,57 @@ const useFetchWrapper = () => { const [error, setError] = useState(null); const { logEvent } = useLogger('useFetchWrapper'); const { startLoading, stopLoading, isLoading } = useLoading(); - const { enqueueSnackbar, closeSnackbar } = useSnackbar(); + // const { enqueueSnackbar, closeSnackbar } = useSnackbar(); const fetchWrapper = useCallback( async (url, method = 'GET', body = null, loadingID) => { + // const showSnackbar = useCustomSnackbar(); + setStatus('loading'); startLoading(loadingID); - - // Show loading snackbar - const snackbarKey = enqueueSnackbar('Loading...', { - variant: 'info', - persist: true, // Keep the snackbar open - action: (key) => , - }); - + // const snackbarContent = (message, subMessage) => ( + // + // {message} + // + // {subMessage} + // + // + // ); + // // Show loading snackbar + // const snackbarKey = enqueueSnackbar( + // snackbarContent( + // 'Loading...', + // `Please wait while we fetch your ${loadingID} data.` + // ), + // { + // variant: 'info', + // persist: true, + // action: (key) => , + // } + // ); + // const snackbarSuccessOptions = { + // variant: 'success', + // persist: true, + // // action: (key) => , + // }; + // const snackbarInfoOptions = { + // variant: 'info', + // persist: true, + // }; + // CustomSnackbar.showSnackbar( + // 'Loading...', + // 'Please wait while we fetch your data.', + // snackbarInfoOptions + // ); + // showSnackbar( + // 'Loading...', + // `Please wait while we fetch your ${loadingID} data.`, + // { + // variant: 'info', + // persist: true, + // action: (key) => , + // } + // ); try { const headers = { 'Content-Type': 'application/json' }; const options = { @@ -119,14 +92,28 @@ const useFetchWrapper = () => { [loadingID]: responseData, })); + // showSnackbar( + // 'Success!', + // `Your ${loadingID} data has been fetched successfully.`, + // { + // variant: 'success', + // persist: true, + // action: (key) => , + // } + // ); return responseData; } catch (error) { setError(error.toString()); setStatus('error'); logEvent('fetch error', { url, error: error.toString() }); + + // showSnackbar('Error', error.toString(), { + // variant: 'error', + // }); } finally { stopLoading(loadingID); - closeSnackbar(snackbarKey); // Close the loading snackbar + + // closeSnackbar(snackbarKey); // Close the loading snackbar } }, [ @@ -134,8 +121,8 @@ const useFetchWrapper = () => { startLoading, stopLoading, logEvent, - enqueueSnackbar, - closeSnackbar, + // enqueueSnackbar, + // closeSnackbar, ] ); diff --git a/src/context/hooks/useSnackBar.jsx b/src/context/hooks/useSnackBar.jsx index 08d7a64..9fe2c6c 100644 --- a/src/context/hooks/useSnackBar.jsx +++ b/src/context/hooks/useSnackBar.jsx @@ -1,79 +1,79 @@ -import { IconButton } from '@mui/material'; -import { useSnackbar } from 'notistack'; -import { useState, useCallback, useRef, useEffect } from 'react'; -import CloseIcon from '@mui/icons-material/Close'; -const useSnackBar = () => { - const { enqueueSnackbar, closeSnackbar } = useSnackbar(); - const defaultOptions = { - variant: 'info', - autoHideDuration: 6000, - }; - const isMountedRef = useRef(false); +// import { IconButton } from '@mui/material'; +// import { useSnackbar } from 'notistack'; +// import { useState, useCallback, useRef, useEffect } from 'react'; +// import CloseIcon from '@mui/icons-material/Close'; +// const useSnackBar = () => { +// const { enqueueSnackbar, closeSnackbar } = useSnackbar(); +// const defaultOptions = { +// variant: 'info', +// autoHideDuration: 6000, +// }; +// const isMountedRef = useRef(false); - useEffect(() => { - isMountedRef.current = true; - return () => { - isMountedRef.current = false; - }; - }, []); - const handleSnackBar = useCallback( - (message, options = defaultOptions) => { - // Enqueue a new snackbar using notistack's enqueueSnackbar function - // `options` can include severity as `variant` and custom `duration` as `autoHideDuration` - // const { title, description } = message; - const { variant, autoHideDuration } = options; - if (open && message.title) { - enqueueSnackbar(message, { - message, - variant, - action: (key) => ( - closeSnackbar(key)}> - - - ), - }); - } - }, - [enqueueSnackbar] - ); +// useEffect(() => { +// isMountedRef.current = true; +// return () => { +// isMountedRef.current = false; +// }; +// }, []); +// const handleSnackBar = useCallback( +// (message, options = defaultOptions) => { +// // Enqueue a new snackbar using notistack's enqueueSnackbar function +// // `options` can include severity as `variant` and custom `duration` as `autoHideDuration` +// // const { title, description } = message; +// const { variant, autoHideDuration } = options; +// if (open && message.title) { +// enqueueSnackbar(message, { +// message, +// variant, +// action: (key) => ( +// closeSnackbar(key)}> +// +// +// ), +// }); +// } +// }, +// [enqueueSnackbar] +// ); - // const [snackbar, setSnackbar] = useState({ - // open: false, - // message: '', - // severity: 'info', - // duration: 6000, - // }); - // const queueRef = useRef([]); +// // const [snackbar, setSnackbar] = useState({ +// // open: false, +// // message: '', +// // severity: 'info', +// // duration: 6000, +// // }); +// // const queueRef = useRef([]); - // const showNextSnackbar = useCallback(() => { - // if (queueRef.current.length > 0 && isMountedRef.current) { - // const nextSnackbar = queueRef.current.shift(); - // setSnackbar({ ...nextSnackbar, open: true }); - // } - // }, []); +// // const showNextSnackbar = useCallback(() => { +// // if (queueRef.current.length > 0 && isMountedRef.current) { +// // const nextSnackbar = queueRef.current.shift(); +// // setSnackbar({ ...nextSnackbar, open: true }); +// // } +// // }, []); - // const handleSnackBar = useCallback( - // (message, severity = 'info', duration = 6000) => { - // queueRef.current.push({ message, severity, duration }); - // if (!snackbar.open && isMountedRef.current) { - // showNextSnackbar(); - // } - // }, - // [snackbar.open, showNextSnackbar] - // ); +// // const handleSnackBar = useCallback( +// // (message, severity = 'info', duration = 6000) => { +// // queueRef.current.push({ message, severity, duration }); +// // if (!snackbar.open && isMountedRef.current) { +// // showNextSnackbar(); +// // } +// // }, +// // [snackbar.open, showNextSnackbar] +// // ); - const handleCloseSnackbar = useCallback(() => { - if (isMountedRef.current) { - closeSnackbar(); - // setSnackbar((prevSnackbar) => ({ - // ...prevSnackbar, - // open: false, - // })); - // showNextSnackbar(); - } - }, [closeSnackbar]); +// const handleCloseSnackbar = useCallback(() => { +// if (isMountedRef.current) { +// closeSnackbar(); +// // setSnackbar((prevSnackbar) => ({ +// // ...prevSnackbar, +// // open: false, +// // })); +// // showNextSnackbar(); +// } +// }, [closeSnackbar]); - return { handleSnackBar, handleCloseSnackbar }; -}; +// return { handleSnackBar, handleCloseSnackbar }; +// }; -export default useSnackBar; +// export default useSnackBar; diff --git a/src/context/index.js b/src/context/index.js index 940c2b1..5c0c3d2 100644 --- a/src/context/index.js +++ b/src/context/index.js @@ -20,6 +20,7 @@ export { useFormContext } from './UTILITIES_CONTEXT/FormContext/FormContext'; export { useMode } from './UTILITIES_CONTEXT/ColorModeContext/useMode'; export { useConfiguratorContext } from './UTILITIES_CONTEXT/ConfiguratorContext/ConfiguratorContext'; export { useVisibilityContext } from './UTILITIES_CONTEXT/VisibilityContext'; +// export { useSnackbarContext } from './UTILITIES_CONTEXT/SnackbarContext/SnackbarContext'; // Contexts export { default as ErrorBoundary } from './ErrorBoundary'; @@ -45,3 +46,4 @@ export { PageProvider } from './UTILITIES_CONTEXT/PageContext/PageContext'; export { CardImagesProvider } from './MISC_CONTEXT/CardImagesContext/CardImagesContext'; export { ConfiguratorProvider } from './UTILITIES_CONTEXT/ConfiguratorContext/ConfiguratorContext'; export { VisibilityProvider } from './UTILITIES_CONTEXT/VisibilityContext'; +// export { SnackbarContextProvider } from './UTILITIES_CONTEXT/SnackbarContext/SnackbarContext'; diff --git a/src/tests/initialCardData.jsx b/src/data/initialCardData.jsx similarity index 100% rename from src/tests/initialCardData.jsx rename to src/data/initialCardData.jsx diff --git a/src/data/messages.json b/src/data/messages.json new file mode 100644 index 0000000..c579e71 --- /dev/null +++ b/src/data/messages.json @@ -0,0 +1,29 @@ +{ + "specific": {}, + "general": { + "loading": { + "primary": "Loading...", + "sub": "Please wait while we fetch your data." + }, + "success": { + "dataFetch": { + "primary": "Success!", + "sub": "The data was fetched successfully." + }, + "formSubmit": { + "primary": "Submitted!", + "sub": "Your information has been successfully submitted." + } + }, + "error": { + "networkError": { + "primary": "Network Error", + "sub": "Please check your internet connection and try again." + }, + "formError": { + "primary": "Submission Error", + "sub": "There was an issue submitting your form. Please try again." + } + } + } +} diff --git a/src/index.js b/src/index.js index dc4bb70..8fae952 100644 --- a/src/index.js +++ b/src/index.js @@ -2,6 +2,7 @@ import React, { StrictMode, useMemo } from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter as Router } from 'react-router-dom'; import App from './App'; +import * as serviceWorker from './serviceWorker'; // ==============================|| REACT DOM RENDER ||============================== // @@ -9,9 +10,48 @@ import { AuthProvider, ColorModeProvider, PageProvider } from './context'; import { loadStripe } from '@stripe/stripe-js'; import { Elements } from '@stripe/react-stripe-js'; import { Helmet } from 'react-helmet'; +import { SnackbarProvider } from 'notistack'; const domNode = document.getElementById('root'); +const HelmetMetadata = () => ( + + {/* Basic */} + Enhanced Cardstore + + + + + + {/* SEO */} + + + {/* Social Media */} + + + + + + + {/* Responsive and mobile */} + + + {/* Additional links and styles */} + + + +); + const AppWrapper = () => { const stripePromise = useMemo( () => loadStripe(process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY), @@ -19,56 +59,20 @@ const AppWrapper = () => { ); return ( - // - - {/* Basic */} - Enhanced Cardstore - - - - - {/* SEO */} - - {/* Social Media */} - - - - - - {/* Responsive and mobile */} - - {/* Additional links and styles */} - - - + - - - - - - - + + + + + + + + + - // ); }; diff --git a/src/tests/CardChart.jsx b/src/layout/CardChart.jsx similarity index 79% rename from src/tests/CardChart.jsx rename to src/layout/CardChart.jsx index 7612de5..4ba5ed9 100644 --- a/src/tests/CardChart.jsx +++ b/src/layout/CardChart.jsx @@ -1,46 +1,28 @@ -import React, { - useState, - useEffect, - useCallback, - useLayoutEffect, - useMemo, - useRef, -} from 'react'; +import React, { useState, useEffect, useMemo } from 'react'; import { - Avatar, Box, - Button, Card, CardActions, CardContent, CardHeader, - Container, - Grid, IconButton, List, ListItem, Paper, Typography, useMediaQuery, - useTheme, } from '@mui/material'; import MoreVertIcon from '@mui/icons-material/MoreVert'; import CardLinearChart from './CardLinearChart'; -import { - ErrorBoundary, - useCollectionStore, - useMode, - usePageContext, -} from '../context'; +import { ErrorBoundary, useMode, usePageContext } from '../context'; import useCardCronJob from './useCardCronJob'; -import initialCardData from './initialCardData'; +import initialCardData from '../data/initialCardData'; import { format } from 'date-fns'; import LoadingCardAnimation from '../assets/animations/LoadingCardAnimation'; import styled from 'styled-components'; -import MDButton from '../layout/REUSABLE_COMPONENTS/MDBUTTON'; +import MDButton from './REUSABLE_COMPONENTS/MDBUTTON'; import { useLoading } from '../context/hooks/useLoading'; -// Adjust the padding, margin, and other styles as needed const ChartArea = styled(Box)(({ theme }) => ({ width: '100%', height: '100%', @@ -51,11 +33,10 @@ const ChartArea = styled(Box)(({ theme }) => ({ border: '1px solid #000', borderRadius: '5px', })); -// A square, responsive container for the chart const SquareChartContainer = styled(Box)(({ theme }) => ({ position: 'relative', - width: '100%', // 100% of the parent width - paddingTop: '100%', // Maintain aspect ratio (1:1) + width: '100%', + paddingTop: '100%', overflow: 'hidden', '& > *': { position: 'absolute', @@ -81,7 +62,6 @@ const CardChart = ({ cardData = initialCardData }) => { }); const { returnDisplay } = usePageContext(); const { isLoading } = useLoading(); - const safeCardData = cardData || { dailyPriceHistory: [] }; useEffect(() => { if (cardData?.imageUrl) { console.log('Setting image url', cardData?.imageUrl); @@ -89,14 +69,6 @@ const CardChart = ({ cardData = initialCardData }) => { } }, [cardData?.imageUrl]); - // const chartData = useMemo( - // () => - // dailyPriceHistory?.map((priceEntry) => ({ - // x: priceEntry?.timestamp, - // y: priceEntry?.num, - // })), - // [dailyPriceHistory] // dependency array - // ); const nivoReadyData = useMemo( () => [ { @@ -116,43 +88,30 @@ const CardChart = ({ cardData = initialCardData }) => { console.log('Fetching collections'); } }, [isLoading('fetchCollections')]); - // Add responsive chart dimension handling useEffect(() => { - // Example of setting dynamic chart dimensions (could be more complex based on container size) const updateDimensions = () => { - const width = window.innerWidth < 500 ? window.innerWidth : 500; // or some other logic - const height = 300; // Fixed height or based on aspect ratio + const width = window.innerWidth < 500 ? window.innerWidth : 500; + const height = 300; setChartDimensions({ width, height }); }; window.addEventListener('resize', updateDimensions); - updateDimensions(); // Initial call + updateDimensions(); return () => { - window.removeEventListener('resize', updateDimensions); // Cleanup listener + window.removeEventListener('resize', updateDimensions); }; - }, []); // Empty array ensures this effect runs only once after initial render - // Simplified for demonstration - // const renderLoadingAnimation = () => { - // return ; - // }; + }, []); const renderHeaderWithAnimation = () => { return ( - // } action={ @@ -165,7 +124,6 @@ const CardChart = ({ cardData = initialCardData }) => { margin: theme.spacing(1), }} /> - {/* Conditionally render animation based on size or other conditions */} {isLgUp && renderLoadingAnimation()} ); @@ -176,7 +134,6 @@ const CardChart = ({ cardData = initialCardData }) => { variant="outlined" sx={{ background: theme.palette.backgroundA.lightest, - // width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', @@ -250,9 +207,6 @@ const CardChart = ({ cardData = initialCardData }) => { (text, index) => ( { if (text === 'Start Updates') startUpdates(); else if (text === 'Pause Updates') pauseUpdates(); @@ -284,7 +238,6 @@ const CardChart = ({ cardData = initialCardData }) => { ) )} - {/* */} { diff --git a/src/layout/CardLinearChart.jsx b/src/layout/CardLinearChart.jsx new file mode 100644 index 0000000..2dd03cf --- /dev/null +++ b/src/layout/CardLinearChart.jsx @@ -0,0 +1,85 @@ +import { Box, Tooltip, Typography, useMediaQuery } from '@mui/material'; + +import { ResponsiveLine } from '@nivo/line'; +import { useCallback, useMemo, useState } from 'react'; +import { useMode } from '../context'; +import styled from 'styled-components'; +const ChartContainer = styled(Box)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + width: '100%', + height: 'auto', + [theme.breakpoints.down('sm')]: { + width: '150%', // Adjust width for mobile screens + height: '300px', // Adjust height for mobile screens + transform: 'translateX(10%)', // Shift the chart to the right by 50% + }, +})); + +const parseDate = (dateString) => { + const date = new Date(dateString); + if (isNaN(date.getTime())) { + console.error(`Invalid date: ${dateString}`); + return null; // or a sensible default, or throw an error, depending on your needs + } + return date; +}; +export const useEventHandlers = () => { + const [hoveredData, setHoveredData] = useState(null); + const handleMouseMove = useCallback((point) => { + setHoveredData(point ? { x: point.data.x, y: point.data.y } : null); + }, []); + const handleMouseLeave = useCallback(() => setHoveredData(null), []); + return { hoveredData, handleMouseMove, handleMouseLeave }; +}; + +const CardLinearChart = ({ nivoReadyData, dimensions }) => { + const { theme } = useMode(); + const processedData = useMemo(() => { + return nivoReadyData?.map((series) => ({ + ...series, + data: series?.data?.map((point) => ({ + ...point, + x: parseDate(point?.x) || point?.x, + })), + })); + }, [nivoReadyData]); + + const chartProps = useMemo( + () => ({ + data: processedData, + margin: { top: 20, right: 20, bottom: 20, left: 35 }, + xScale: { + type: 'time', + format: 'time:%Y-%m-%dT%H:%M:%S.%LZ', + useUTC: false, + precision: 'second', + }, + axisBottom: { + tickRotation: 0, + legend: 'Time', + legendOffset: 36, + legendPosition: 'middle', + tickSize: 5, + tickPadding: 5, + tickValues: 'every 2 days', + format: '%b %d', + }, + enableSlices: 'x', + yScale: { type: 'linear', min: 'auto', max: 'auto' }, + }), + [nivoReadyData, processedData] + ); + + if (!processedData || !processedData?.length) { + return No data available; + } + return ( + + + + ); +}; + +export default CardLinearChart; diff --git a/src/layout/REUSABLE_COMPONENTS/BoxHeader.jsx b/src/layout/REUSABLE_COMPONENTS/BoxHeader.jsx index 04f7fb8..2406946 100644 --- a/src/layout/REUSABLE_COMPONENTS/BoxHeader.jsx +++ b/src/layout/REUSABLE_COMPONENTS/BoxHeader.jsx @@ -4,17 +4,33 @@ import FlexBetween from './FlexBetween'; import PropTypes from 'prop-types'; import { useMode } from '../../context'; -const BoxHeader = ({ icon, title, subtitle, sideText }) => { +const BoxHeader = ({ + icon, + title, + subtitle, + sideText, + sx, + useSX, + titleVariant, + colorVariant, + paddingVariant, +}) => { const { theme } = useMode(); return ( {icon} - + {title} {subtitle} @@ -24,6 +40,7 @@ const BoxHeader = ({ icon, title, subtitle, sideText }) => { variant="h5" fontWeight="700" color={theme.palette.backgroundE.dark} + sx={useSX ? sx : {}} > {sideText} diff --git a/src/layout/REUSABLE_COMPONENTS/CustomSnackbar.jsx b/src/layout/REUSABLE_COMPONENTS/CustomSnackbar.jsx new file mode 100644 index 0000000..42c508a --- /dev/null +++ b/src/layout/REUSABLE_COMPONENTS/CustomSnackbar.jsx @@ -0,0 +1,31 @@ +// // CustomSnackbar.js +// import React from 'react'; +// import { Box, Typography } from '@mui/material'; +// import CircularProgress from '@mui/material/CircularProgress'; +// import { useSnackbar } from 'notistack'; + +// const CustomSnackbar = () => { +// const { enqueueSnackbar } = useSnackbar(); + +// const showSnackbar = (title, subTitle, options = {}) => { +// const content = ( +// +// {title} +// +// {subTitle} +// +// +// ); + +// enqueueSnackbar(content, { +// ...options, +// action: options.persist +// ? (key) => +// : undefined, +// }); +// }; + +// return { showSnackbar }; +// }; + +// export default CustomSnackbar; diff --git a/src/layout/REUSABLE_COMPONENTS/Icons.jsx b/src/layout/REUSABLE_COMPONENTS/Icons.jsx index 5cc02f0..70866c1 100644 --- a/src/layout/REUSABLE_COMPONENTS/Icons.jsx +++ b/src/layout/REUSABLE_COMPONENTS/Icons.jsx @@ -1,10 +1,10 @@ -const allIconsMap = { - // Add all icons here - 'attach-money': AttachMoneyIcon, - collections: CollectionsIcon, - 'attach-money': AttachMoneyIcon, - 'format-list-numbered': FormatListNumberedIcon, - 'trending-up': TrendingUpIcon, - 'pie-chart': PieChartIcon, - 'emoji-events': EmojiEventsIcon, -}; +// const allIconsMap = { +// // Add all icons here +// 'attach-money': AttachMoneyIcon, +// collections: CollectionsIcon, +// 'attach-money': AttachMoneyIcon, +// 'format-list-numbered': FormatListNumberedIcon, +// 'trending-up': TrendingUpIcon, +// 'pie-chart': PieChartIcon, +// 'emoji-events': EmojiEventsIcon, +// }; diff --git a/src/layout/REUSABLE_COMPONENTS/SkeletonVariants.jsx b/src/layout/REUSABLE_COMPONENTS/SkeletonVariants.jsx index a4eef10..2b8a154 100644 --- a/src/layout/REUSABLE_COMPONENTS/SkeletonVariants.jsx +++ b/src/layout/REUSABLE_COMPONENTS/SkeletonVariants.jsx @@ -4,7 +4,6 @@ import { useMode } from '../../context'; import useSkeletonLoader from '../collection/collectionGrids/cards-datatable/useSkeletonLoader'; const HeroSectionSkeleton = () => { - const { theme } = useMode(); const { SkeletonLoader } = useSkeletonLoader(); return ( diff --git a/src/pages/SplashPage2.jsx b/src/layout/REUSABLE_COMPONENTS/SplashPage2.jsx similarity index 88% rename from src/pages/SplashPage2.jsx rename to src/layout/REUSABLE_COMPONENTS/SplashPage2.jsx index 2cc474b..ff25135 100644 --- a/src/pages/SplashPage2.jsx +++ b/src/layout/REUSABLE_COMPONENTS/SplashPage2.jsx @@ -1,13 +1,12 @@ import React, { useEffect, useRef } from 'react'; import * as THREE from 'three'; -import placeholder from '../assets/images/placeholder.jpeg'; +import placeholder from '../../assets/images/placeholder.jpeg'; import { Box } from '@mui/material'; const SplashPage2 = () => { const containerRef = useRef(null); useEffect(() => { - // Scene setup const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, @@ -18,8 +17,6 @@ const SplashPage2 = () => { const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); - - // Append renderer to the container ref if (containerRef.current) { containerRef.current.appendChild(renderer.domElement); } @@ -92,26 +89,20 @@ const SplashPage2 = () => { renderer.render(scene, camera); }; - // Handle window resize window.addEventListener('resize', onWindowResize, false); function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); - // Recalculate number of cards per row cardsPerRow = calculateCardsPerRow(); - // Update the rows with new card count updateRowsWithNewCardCount(); } - // Update rows with new card count when window is resized function updateRowsWithNewCardCount() { cardRows.forEach((row) => { - // Remove existing cards while (row.children.length) { row.remove(row.children[0]); } - // Add new cards based on updated count for (let j = 0; j < cardsPerRow; j++) { const card = new THREE.Mesh(geometry, material); card.position.x = (j - cardsPerRow / 2) * cardSpacing; @@ -121,15 +112,13 @@ const SplashPage2 = () => { } animate(); - - // Cleanup return () => { if (containerRef.current) { containerRef.current.removeChild(renderer.domElement); } window.removeEventListener('resize', onWindowResize, false); }; - }, []); // Empty dependency array ensures this effect runs once when the component mounts + }, []); return ( { const blue = colors.blueAccent.default; const green = colors.greenAccent.default; const greenliht = colors.greenAccent.light; - const grey = colors.grey.default; return ( - + {icon} diff --git a/src/layout/REUSABLE_COMPONENTS/unique/SimpleSectionHeader.jsx b/src/layout/REUSABLE_COMPONENTS/unique/SimpleSectionHeader.jsx index 4843798..69137e8 100644 --- a/src/layout/REUSABLE_COMPONENTS/unique/SimpleSectionHeader.jsx +++ b/src/layout/REUSABLE_COMPONENTS/unique/SimpleSectionHeader.jsx @@ -2,8 +2,9 @@ import React from 'react'; import Typography from '@mui/material/Typography'; import Box from '@mui/material/Box'; import { useMode } from '../../../context'; +import MDTypography from '../MDTYPOGRAPHY/MDTypography'; +import { useMediaQuery, useTheme } from '@mui/material'; -// Updated SimpleSectionHeader component with additional parameters const SimpleSectionHeader = ({ sectionName, userName, @@ -11,38 +12,61 @@ const SimpleSectionHeader = ({ lastUpdated, }) => { const { theme } = useMode(); + const lgDown = useMediaQuery(theme.breakpoints.down('lg')); + return ( - - {sectionName} - + + {sectionName} + + - {` ${userName}'s Portfolio`} - - - + {`${userName}'s Portfolio`} + + + + {/* Section Description */} + {sectionDescription} - - {` ${lastUpdated}`} - + + + {/* Last Updated */} + + {`Last updated: ${lastUpdated}`} ); diff --git a/src/layout/collection/collectionGrids/ChartGridLayout.jsx b/src/layout/collection/collectionGrids/ChartGridLayout.jsx index 14cfa9f..272add9 100644 --- a/src/layout/collection/collectionGrids/ChartGridLayout.jsx +++ b/src/layout/collection/collectionGrids/ChartGridLayout.jsx @@ -1,32 +1,81 @@ -import React from 'react'; -import { Grid, Card, useMediaQuery, Icon } from '@mui/material'; +import React, { Suspense, useEffect, useMemo } from 'react'; +import { Grid, Card, useMediaQuery, Icon, Container } from '@mui/material'; import MDBox from '../../REUSABLE_COMPONENTS/MDBOX'; -import CollectionPortfolioChartContainer from './cards-chart/CollectionPortfolioChartContainer'; import DataTable from './cards-datatable'; -import { useMode } from '../../../context'; +import { useMode, useStatisticsStore } from '../../../context'; import DashboardBox from '../../REUSABLE_COMPONENTS/DashboardBox'; import BoxHeader from '../../REUSABLE_COMPONENTS/BoxHeader'; import { UpdaterAndStatisticsRow } from './cards-chart/UpdaterAndStatisticsRow'; import SimpleCard from '../../REUSABLE_COMPONENTS/unique/SimpleCard'; import uniqueTheme from '../../REUSABLE_COMPONENTS/unique/uniqueTheme'; - -const ChartGridLayout = ({ selectedCards, removeCard, columns, data }) => { - const { theme } = useMode(); - const isXs = useMediaQuery(theme.breakpoints.down('sm')); - const isLg = useMediaQuery(theme.breakpoints.up('lg')); - const tableSize = isXs ? 'less' : isLg ? 'large' : 'small'; - console.log({ selectedCards, tableSize, columns, data }); // Debug log - // A function to render MDBox Card container for reusability - const renderCardContainer = (content) => ( +import { ChartArea } from '../../../pages/pageStyles/StyledComponents'; +import useSelectedCollection from '../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; +import useTimeRange from '../../../components/forms/selectors/useTimeRange'; +import useSkeletonLoader from './cards-datatable/useSkeletonLoader'; +import ChartErrorBoundary from './cards-chart/ChartErrorBoundary'; +import { ChartConfiguration } from './cards-chart/ChartConfigs'; +const renderCardContainer = (content) => { + return ( - {/* */} - {/* */} {content} - {/* */} ); +}; + +const ChartGridLayout = ({ selectedCards, removeCard, columns, data }) => { + const { theme } = useMode(); + const isXs = useMediaQuery(theme.breakpoints.down('sm')); + const isLg = useMediaQuery(theme.breakpoints.up('lg')); + const tableSize = isXs ? 'less' : isLg ? 'large' : 'small'; + const env = process.env.CHART_ENVIRONMENT; + const isSmall = useMediaQuery(theme.breakpoints.down('sm')); + const { selectedCollection } = useSelectedCollection(); + const chartDataVariants = { + averaged: selectedCollection.averagedChartData, + raw: selectedCollection.nivoChartData, + new: selectedCollection.newNivoChartData, + test: selectedCollection.nivoTestData, + }; + const selectedData = chartDataVariants.averaged; + const { selectedTimeRange } = useTimeRange(); + const { stats, markers } = useStatisticsStore(); + const { SkeletonLoader } = useSkeletonLoader(); + const selectedChartData = useMemo(() => { + const averagedData = selectedCollection.averagedChartData; + + if (!averagedData || !averagedData[selectedTimeRange]) { + console.error( + 'No averaged chart data available for the selected time range.' + ); + return null; + } + const chartData = averagedData[selectedTimeRange]; + return chartData || null; + }, [selectedCollection.averagedChartData, selectedTimeRange]); + // if (!selectedChartData) { + // return ( + // + // table_chart} + // sideText={new Date().toLocaleString()} + // /> + // + // + // + // + // ); + // } + useEffect(() => { + console.log('DEBUG LOG, ', { + selectedChartData, + markers, + selectedTimeRange, + }); + }, []); return ( @@ -53,10 +102,28 @@ const ChartGridLayout = ({ selectedCards, removeCard, columns, data }) => { /> {renderCardContainer( - + }> + + {/* */} + + + )} { -// let format, ticks; -// switch (timeRange) { -// case '24hr': -// format = '%H:%M'; -// ticks = 'every hour'; -// break; -// case '7d': -// format = '%b %d'; -// ticks = 'every day'; -// break; -// case '30d': -// format = '%b %d'; -// ticks = 'every day'; -// break; -// case '90d': -// format = '%b %d'; -// ticks = 'every 3 days'; -// break; -// case '180d': -// format = '%b %d'; -// ticks = 'every 6 days'; -// break; -// case '270d': -// format = '%b %d'; -// ticks = 'every 9 days'; -// break; -// case '365d': -// format = '%b %d'; -// ticks = 'every 12 days'; -// break; -// default: -// format = '%b %d'; -// ticks = 'every day'; -// } -// return { tickValues: ticks, xFormat: `time:${format}` }; -// }, [timeRange]); -// const normalizeData = (data, timeRange) => { -// // Determine the start and end dates based on the timeRange -// let endDate = new Date(); -// let startDate = new Date(); +import ChartErrorBoundary from './ChartErrorBoundary'; -// startDate.setDate(endDate.getDate() - parseInt(timeRange, 10)); - -// let normalizedData = []; -// let currentDate = new Date(startDate); - -// while (currentDate <= endDate) { -// let dateString = currentDate.toISOString().split('T')[0]; - -// let dataPoint = data?.find((point) => point.x === dateString); -// normalizedData.push({ -// x: dateString, -// y: dataPoint ? dataPoint.y : null, // Use null for missing data -// }); - -// currentDate.setDate(currentDate.getDate() + 1); -// } - -// return [{ id: 'data', data: normalizedData }]; -// }; -// function getTickValuesAndFormat(timeRange) { -// // Your logic to determine tick values and format based on timeRange... -// return { -// tickValues: 'every day', -// xFormat: '%Y-%m-%d', -// }; -// } -// const normalizeData = (data, timeRange) => { -// let endDate = new Date(); -// let startDate = new Date(); -// startDate.setDate(endDate.getDate() - parseInt(timeRange, 10)); - -// return [ -// { -// id: 'data', -// data: data.map(({ x, y }) => ({ -// x: x || startDate.toISOString().split('T')[0], // Provide a fallback date if necessary -// y: y != null ? y : 0, // Ensure null or undefined values are replaced with 0 -// })), -// }, -// ]; -// }; - -// function getTickValuesAndFormat(timeRange) { -// // Simplified logic for determining tick values and format based on timeRange -// const format = timeRange === '24hr' ? '%H:%M' : '%b %d'; -// const ticks = timeRange === '24hr' ? 'every hour' : 'every day'; -// return { tickValues: ticks, xFormat: `time:${format}` }; -// } export const ChartConfiguration = ({ markers, height, nivoChartData, range, - loadingId, + loadingID, }) => { const { theme } = useMode(); - const { selectedCollection, nivoTestData } = useSelectedCollection(); - // const { nivoChartData, newNivoChartData } = useCollectionManager(); const { handleMouseMove, handleMouseLeave } = useEventHandlers(); - // const chartData = useMemo(() => { - // // Access the averaged data based on the selected range - // return selectedCollection.averagedChartData.get(range) || []; - // }, [selectedCollection.averagedChartData, range]); - // const [timeRange, setTimeRange] = useState('24hr'); - // const [chartData, setChartData] = useState([]); - // useEffect(() => { - // // Assuming a function like `normalizeData` exists to format your data correctly based on the time range. - // // This should adjust the data structure to fit what Nivo expects. - // const normalizedData = normalizeData(nivoChartData, timeRange); - // setChartData(normalizedData); - // }, [nivoChartData, timeRange]); - // useEffect(() => { - // let isValidData = true; // Assume data is valid initially - - // // Checks if the data array has valid 'x' and 'y' values - // const validateChartData = (data) => { - // return data.every((series) => - // series.data.every( - // (point) => point.x && point.y !== null && point.y !== undefined - // ) - // ); - // }; - // // Check if nivoChartData or newNivoChartData has valid structure and content - // if ( - // !nivoChartData || - // !newNivoChartData || - // !validateChartData(nivoChartData) - // ) { - // isValidData = false; // Data is considered invalid if checks fail - // } - - // // Set the chart data based on the validation above - // let activeChartData; - // if (isValidData) { - // // Normalize the actual data if it's valid - // activeChartData = normalizeData(nivoChartData, timeRange); - // } else { - // // Fallback to nivoTestData for the selected time range if data is invalid - // const testData = nivoTestData.find((data) => data.id === timeRange); - // activeChartData = testData ? normalizeData(testData.data, timeRange) : []; - // } - - // setChartData(activeChartData); - // }, [nivoChartData, newNivoChartData, timeRange, nivoTestData]); - - // Filtering valid markers only to avoid any runtime errors. const validMarkers = useMemo( () => markers.filter((marker) => marker.value !== undefined), [markers] @@ -201,8 +61,7 @@ export const ChartConfiguration = ({ const chartProps = useMemo( () => ({ - // data: [nivoChartData], - data: [nivoChartData], + data: nivoChartData, onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave, colors: { datum: 'color' }, // This is the only change from the original code @@ -211,8 +70,6 @@ export const ChartConfiguration = ({ pointBorderWidth: 2, pointBorderColor: { from: 'serieColor' }, yFormat: '$.2f', - - // colors: theme.palette.backgroundE.dark, axisBottom: { tickRotation: 0, legend: 'Time', @@ -239,16 +96,11 @@ export const ChartConfiguration = ({ margin: { top: 20, right: 40, bottom: 50, left: 55 }, padding: 0.5, animate: true, - // xFormat: 'time:%Y-%m-%d %H:%M:%S7Z', - // format: '%Y-%m-%dT%H:%M:%S.%LZ', - xScale: { type: 'time', format: '%Y-%m-%dT%H:%M:%S.%LZ', precision: 'millisecond', - // format: 'time:%Y-%m-%d', useUTC: false, - // precision: 'day', }, yScale: { type: 'linear', @@ -260,7 +112,6 @@ export const ChartConfiguration = ({ curve: 'monotoneX', useMesh: true, motionConfig: 'gentle', - stiffness: 90, damping: 15, enableSlices: 'x', @@ -283,11 +134,6 @@ export const ChartConfiguration = ({ /> ), ], - // theme: { - // axis: theme.nivo.axis, - // legends: theme.nivo.legends, - // tooltip: theme.nivo.tooltip, - // }, theme: { axis: { domain: { @@ -326,51 +172,27 @@ export const ChartConfiguration = ({ ); return ( - - - + + + + + ); }; -// Define the structure of each data point -// const pointShape = PropTypes.shape({ -// x: PropTypes.oneOfType([ -// PropTypes.number, -// PropTypes.string, -// PropTypes.instanceOf(Date), -// ]).isRequired, -// y: PropTypes.number.isRequired, -// }); - -// // Define the structure for each data series -// const seriesShape = PropTypes.shape({ -// id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, -// color: PropTypes.string, -// data: PropTypes.arrayOf(pointShape).isRequired, -// }); - -// Now, apply these to ChartConfiguration propTypes ChartConfiguration.propTypes = { - // markers: PropTypes.arrayOf(PropTypes.object), - // height: PropTypes.number.isRequired, - // range: PropTypes.string.isRequired, - // loadingId: PropTypes.string, - nivoChartData: PropTypes.arrayOf( + markers: PropTypes.arrayOf( PropTypes.shape({ - id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, - color: PropTypes.string, - data: PropTypes.arrayOf( - PropTypes.shape({ - x: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - PropTypes.instanceOf(Date), - ]).isRequired, - y: PropTypes.number.isRequired, - }) - ).isRequired, + axis: PropTypes.oneOf(['x', 'y']).isRequired, + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) + .isRequired, + legend: PropTypes.string, + lineStyle: PropTypes.object, }) - ).isRequired, - // Validate chartData explicitly to match the expected structure - // nivoChartData: PropTypes.arrayOf(seriesShape).isRequired, + ), + height: PropTypes.number.isRequired, + nivoChartData: PropTypes.arrayOf(PropTypes.object).isRequired, + range: PropTypes.oneOf(['24hr', '7d', '30d', '90d', '180d', '270d', '365d']) + .isRequired, + loadingID: PropTypes.string.isRequired, }; diff --git a/src/layout/collection/collectionGrids/cards-chart/ChartErrorBoundary.jsx b/src/layout/collection/collectionGrids/cards-chart/ChartErrorBoundary.jsx index 7ec649a..761dd3d 100644 --- a/src/layout/collection/collectionGrids/cards-chart/ChartErrorBoundary.jsx +++ b/src/layout/collection/collectionGrids/cards-chart/ChartErrorBoundary.jsx @@ -1,30 +1,49 @@ -import { Typography } from '@mui/material'; -import React from 'react'; +import React, { useState, useEffect } from 'react'; +import { Box, Container, Icon, Typography, useMediaQuery } from '@mui/material'; +import useSkeletonLoader from '../cards-datatable/useSkeletonLoader'; +import BoxHeader from '../../../REUSABLE_COMPONENTS/BoxHeader'; +import { useMode } from '../../../../context'; -class ChartErrorBoundary extends React.Component { - constructor(props) { - super(props); - this.state = { hasError: false, error: null }; - } +function ChartErrorBoundary({ children }) { + const [hasError, setHasError] = useState(false); + const [error, setError] = useState(null); + const { SkeletonLoader } = useSkeletonLoader(); + const { theme } = useMode(); + const isSmall = useMediaQuery(theme.breakpoints.down('sm')); - static getDerivedStateFromError(error) { - // Update state so the next render will show the fallback UI. - return { hasError: true, error }; - } + useEffect(() => { + const errorListener = (event) => { + event.preventDefault(); + setError(event.error); + setHasError(true); + }; - componentDidCatch(error, errorInfo) { - // You can log the error to an error reporting service - console.error('Error in chart component:', error, errorInfo); - } + window.addEventListener('error', errorListener); - render() { - if (this.state.hasError) { - // You can render any custom fallback UI - return Unable to display chart; - } + return () => { + window.removeEventListener('error', errorListener); + }; + }, []); - return this.props.children; + if (hasError) { + return ( + + Unable to display chart + + table_chart} + sideText={new Date().toLocaleString()} + /> + + + + + ); } + + return children; } export default ChartErrorBoundary; diff --git a/src/layout/collection/collectionGrids/cards-chart/CollectionPortfolioChartContainer.jsx b/src/layout/collection/collectionGrids/cards-chart/CollectionPortfolioChartContainer.jsx deleted file mode 100644 index 261a730..0000000 --- a/src/layout/collection/collectionGrids/cards-chart/CollectionPortfolioChartContainer.jsx +++ /dev/null @@ -1,165 +0,0 @@ -import React, { useEffect, useMemo, useState } from 'react'; -import { Box, useMediaQuery, Grid, Container, Icon } from '@mui/material'; -import { - useChartContext, - useStatisticsStore, - useMode, - useCollectionStore, -} from '../../../../context'; -import { ChartArea } from '../../../../pages/pageStyles/StyledComponents'; -import BoxHeader from '../../../REUSABLE_COMPONENTS/BoxHeader'; -import LinearChart from './LinearChart'; -import { Suspense } from 'react'; -import useSkeletonLoader from '../cards-datatable/useSkeletonLoader'; -import useSelectedCollection from '../../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; -import useTimeRange from '../../../../components/forms/selectors/useTimeRange'; - -const CollectionPortfolioChartContainer = () => { - const { theme } = useMode(); - const env = process.env.CHART_ENVIRONMENT; - const isSmall = useMediaQuery(theme.breakpoints.down('sm')); - const { selectedCollection } = useSelectedCollection(); - const chartDataVariants = { - averaged: selectedCollection.averagedChartData, - raw: selectedCollection.nivoChartData, - new: selectedCollection.newNivoChartData, - test: selectedCollection.nivoTestData, - }; - const selectedData = chartDataVariants.averaged; - const { selectedTimeRange } = useTimeRange(); - const { stats, markers } = useStatisticsStore(); - const { SkeletonLoader } = useSkeletonLoader(); - // Directly use the averagedChartData map for selecting the data based on timeRange - const selectedChartData = useMemo(() => { - const averagedData = selectedCollection.averagedChartData; - - if (!averagedData || !averagedData[selectedTimeRange]) { - console.error( - 'No averaged chart data available for the selected time range.' - ); - return null; - } - - // Retrieve the specific dataset for the current time range directly - const chartData = averagedData[selectedTimeRange]; - return chartData || null; // Return null if the specific range data is not available - }, [selectedCollection.averagedChartData, selectedTimeRange]); - - if (!selectedChartData) { - return ( - - table_chart} - sideText={new Date().toLocaleString()} - /> - - - - - ); - } - - // const setSelectedChartData = (chartData) => { - // console.log('setSelectedChartData', chartData); - // setTimeRange(chartData); - // }; - // useEffect(() => { - // const timeRangeIdMap = nivoTestData?.reduce((acc, data) => { - // acc[data.id] = data; - // return acc; - // }, {}); - // console.log('TIME RANGE ID MAP:', timeRangeIdMap); - - // const matchedData = timeRangeIdMap[timeRange.id]; - // if (matchedData) { - // console.log('SET SELECTED DATA:', matchedData); - // setSelectedChartData(matchedData); - // // setSelectedChartData(matchedData); - // } - // }, [selectedData, timeRange]); - - // if (!selectedChartData) { - // return ( - // - // table_chart} - // sideText={new Date().toLocaleString()} - // /> - // - // - // - // - // ); - // } - return ( - }> - {/* */} - - - - {/* */} - - ); -}; - -export default CollectionPortfolioChartContainer; -// useEffect(() => { -// console.log('ADJUSTED TIME RANGE ID:', newNivoChartData[0].id); -// const oneDay = newNivoChartData[0].id; -// const sevenDays = newNivoChartData[1].id; -// const thirtyDays = newNivoChartData[2].id; -// const ninetyDays = newNivoChartData[3].id; -// const oneEightyDays = newNivoChartData[4].id; -// const twoSeventyDays = newNivoChartData[5].id; -// const threeSixtyFiveDays = newNivoChartData[6].id; - -// setTimeRangeIds([ -// oneDay, -// sevenDays, -// thirtyDays, -// ninetyDays, -// oneEightyDays, -// twoSeventyDays, -// threeSixtyFiveDays, -// ]); - -// // console.log('ALL RANES:', oneDay, sevenDays, thirtyDays, ninetyDays); -// if (timeRange.id === '24hr') { -// setSelectedChartData(oneDay); -// } -// if (timeRange.id === '7d') { -// console.log('SETTING SEVEN DAYS:', sevenDays); -// setSelectedChartData(sevenDays); -// } -// if (timeRange.id === '30d') { -// setSelectedChartData(thirtyDays); -// } -// if (timeRange.id === '90d') { -// setSelectedChartData(ninetyDays); -// } -// if (timeRange.id === '180d') { -// setSelectedChartData(oneEightyDays); -// } -// if (timeRange.id === '270d') { -// setSelectedChartData(twoSeventyDays); -// } -// if (timeRange.id === '365d') { -// setSelectedChartData(threeSixtyFiveDays); -// } -// }, [newNivoChartData, timeRange]); // Dependencies - -// if (!selectedChartData || !timeRange) { -// return ; -// } diff --git a/src/layout/collection/collectionGrids/cards-chart/LinearChart.js b/src/layout/collection/collectionGrids/cards-chart/LinearChart.js deleted file mode 100644 index edce7fe..0000000 --- a/src/layout/collection/collectionGrids/cards-chart/LinearChart.js +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import ChartWrapper from '../../../REUSABLE_COMPONENTS/unique/ChartWrapper'; -import FixedHeightCardWrapper from '../../../REUSABLE_COMPONENTS/unique/FixedHeightCardWrapper'; -import InfoStackWrapper from '../../../REUSABLE_COMPONENTS/unique/InfoStackWrapper'; -import uniqueTheme from '../../../REUSABLE_COMPONENTS/unique/uniqueTheme'; -import DynamicCollectionDestructuring from '../../data/statList'; -import { ChartConfiguration } from './ChartConfigs'; -import ChartErrorBoundary from './ChartErrorBoundary'; - -const LinearChart = ({ height, specialPoints, timeRange, nivoData }) => { - console.log('NIVODATA ', nivoData); - return ( - - - - ); -}; - -// Define prop types for LinearChart component -LinearChart.propTypes = { - height: PropTypes.number.isRequired, - specialPoints: PropTypes.arrayOf(PropTypes.object), - timeRange: PropTypes.string.isRequired, - nivoData: PropTypes.object.isRequired, -}; - -export default LinearChart; diff --git a/src/layout/collection/collectionGrids/cards-chart/UpdaterAndStatisticsRow.jsx b/src/layout/collection/collectionGrids/cards-chart/UpdaterAndStatisticsRow.jsx index d10860e..b985f05 100644 --- a/src/layout/collection/collectionGrids/cards-chart/UpdaterAndStatisticsRow.jsx +++ b/src/layout/collection/collectionGrids/cards-chart/UpdaterAndStatisticsRow.jsx @@ -14,21 +14,13 @@ import ThemeSelector from '../../../../components/forms/selectors/ThemeSelector' * @param {Object} props.timeRange Selected time range for statistics. * @param {Object} props.stats Collection statistics. */ -export const UpdaterAndStatisticsRow = ({ - isSmall, - socket, - timeRange, - stats, -}) => ( +export const UpdaterAndStatisticsRow = ({ isSmall }) => ( {/* Update Status Box */} diff --git a/src/layout/collection/collectionGrids/collections-list/SelectCollectionHeader.jsx b/src/layout/collection/collectionGrids/collections-list/SelectCollectionHeader.jsx index 3ddb427..613aae6 100644 --- a/src/layout/collection/collectionGrids/collections-list/SelectCollectionHeader.jsx +++ b/src/layout/collection/collectionGrids/collections-list/SelectCollectionHeader.jsx @@ -1,5 +1,5 @@ import React, { useEffect } from 'react'; -import { Grid, Button, Box } from '@mui/material'; +import { Grid, Button, Box, useMediaQuery } from '@mui/material'; import { useAuthContext, useFormContext, @@ -52,12 +52,12 @@ const FlexContainer = styled(Box)` padding: ${({ theme }) => theme.spacing(1, 2)}; `; -const HeaderContainer = styled.div` +const HeaderContainer = styled(Box)` flex: 1; - max-width: 25%; + max-width: 50%; `; -const ButtonContainer = styled.div` +const ButtonContainer = styled(Box)` flex: 1; display: flex; justify-content: flex-end; @@ -68,7 +68,6 @@ const SelectCollectionHeader = ({ openNewDialog }) => { const { theme } = useMode(); const { setCurrentForm } = useFormContext(); const { user } = useUserContext(); - if (!user) { return ; } diff --git a/src/layout/collection/collectionGrids/collections-list/SelectCollectionList.jsx b/src/layout/collection/collectionGrids/collections-list/SelectCollectionList.jsx index d4dc736..c38ff77 100644 --- a/src/layout/collection/collectionGrids/collections-list/SelectCollectionList.jsx +++ b/src/layout/collection/collectionGrids/collections-list/SelectCollectionList.jsx @@ -1,77 +1,4 @@ -// import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; -// import { -// Box, -// Card, -// CardActionArea, -// Collapse, -// Grid, -// List, -// Skeleton, -// } from '@mui/material'; -// import PropTypes from 'prop-types'; -// import { TransitionGroup } from 'react-transition-group'; -// import CollectionListItem from './CollectionListItem'; -// import useSelectedCollection from '../../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; -// import SimpleCard from '../../../REUSABLE_COMPONENTS/unique/SimpleCard'; -// import uniqueTheme from '../../../REUSABLE_COMPONENTS/unique/uniqueTheme'; -// import FlexBetween from '../../../REUSABLE_COMPONENTS/FlexBetween'; -// // -// // -// const CollectionListItemSkeleton = ({ count }) => { -// return ( -// -// -// -// -// -// -// -// -// -// -// -// ); -// }; - -// CollectionListItemSkeleton.propTypes = { -// count: PropTypes.number, -// }; - -// CollectionListItemSkeleton.displayName = 'CollectionListItemSkeleton'; - -// const SelectCollectionList = ({ openDialog }) => { -// const { allCollections } = useSelectedCollection(); -// const minListSize = 5; -// const collectionCount = allCollections?.length || 0; -// const skeletonsNeeded = Math.max(0, minListSize - collectionCount); - -// return ( -// -// -// -// {allCollections?.map((collection, index) => ( -// -// -// {skeletonsNeeded > 0 && ( -// -// )} -// -// ))} -// -// -// -// ); -// }; - -// SelectCollectionList.propTypes = { -// openDialog: PropTypes.func.isRequired, -// }; - -// export default SelectCollectionList; -import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; +import React, { memo, useRef, useState } from 'react'; import { Box, Card, @@ -95,26 +22,25 @@ const FlexContainer = styled(Box)` width: 100%; padding: ${({ theme }) => theme.spacing(1, 2)}; `; -const CollectionListItemSkeleton = ({ count }) => { - return [...Array(count).keys()].map((index) => ( - - - - - - - - - - - - - - )); -}; +const CollectionListItemSkeleton = ({ count, index }) => ( + + + + + + + + + + + + + +); CollectionListItemSkeleton.propTypes = { count: PropTypes.number.isRequired, + index: PropTypes.number.isRequired, }; const SelectCollectionList = ({ openDialog }) => { @@ -124,7 +50,11 @@ const SelectCollectionList = ({ openDialog }) => { const minItems = 5; const numRequired = minItems - (allCollections?.length || 0); const allSkeletonCollections = [...Array(numRequired).keys()].map((index) => ( - + )); const combinedCollections = [...allCollections, ...allSkeletonCollections]; return ( @@ -138,8 +68,15 @@ const SelectCollectionList = ({ openDialog }) => { {combinedCollections?.map((collection, index) => ( - + diff --git a/src/layout/collection/collectionGrids/collections-list/StatBoard.jsx b/src/layout/collection/collectionGrids/collections-list/StatBoard.jsx index c30585a..03b3e54 100644 --- a/src/layout/collection/collectionGrids/collections-list/StatBoard.jsx +++ b/src/layout/collection/collectionGrids/collections-list/StatBoard.jsx @@ -1,40 +1,121 @@ -import { Grid } from '@mui/material'; +/* eslint-disable react/jsx-key */ +import { Box, Grid, Typography } from '@mui/material'; // import PieChart from './statItems/PieChart'; -// import TotalPriceStatBox from './statItems/TotalPriceStatBox'; +import TotalPriceStatBox from './statItems/TotalPriceStatBox'; // import ValuDistributionCircle from './statItems/ValuDistributionCircle'; // import PricedCardList from './statItems/PricedCardList'; import SimpleCard from '../../../REUSABLE_COMPONENTS/unique/SimpleCard'; import uniqueTheme from '../../../REUSABLE_COMPONENTS/unique/uniqueTheme'; -import { ChartArea } from '../../../../pages/pageStyles/StyledComponents'; -import NivoContainer from '../cards-chart/NivoContainer'; -import { useMode } from '../../../../context'; +import { useAppContext, useMode } from '../../../../context'; import ValuDistributionCircle from './statItems/ValuDistributionCircle'; import PricedCardList from './statItems/PricedCardList'; -import ZenEnso from '../../../../assets/animations/ZenEnso'; +import PerformanceStatBox from './statItems/PerformanceStatBox'; import MDBox from '../../../REUSABLE_COMPONENTS/MDBOX'; -// import ValueDistPieChart from './statItems/ValueDistPieChart'; - +import styled from 'styled-components'; // const StatBoard = () => { +// const { theme } = useMode(); // return ( -// -// -// {item} -// -// -// {item} -// -// -// {item} +// +// +// +// {' '} +// +// + +// +// +// +// +// +// +// // -// +// // ); // }; -const StatBoard = () => { +// export default StatBoard; +const StatBoxes = () => { + const { theme } = useMode(); + return ( + + + + + ); +}; +const DistCircle = () => { + const { theme } = useMode(); + const colors = theme.palette.chartTheme; + + return ( + + + + ); +}; + +const PriceList = () => { const { theme } = useMode(); + const colors = theme.palette.chartTheme; + + return ( + + + + ); +}; +const StatBoard = () => { return ( { > - {/* - - - {' '} - */} - {/* */} - {/* */} - {/* - - */} - {/* */} - {/* - {/* - - */} - {/* - - */} - - - + {[, , ].map( + (component, index) => ( + + {component} + + ) + )} ); diff --git a/src/layout/collection/collectionGrids/collections-list/statItems/PerformanceStatBox.jsx b/src/layout/collection/collectionGrids/collections-list/statItems/PerformanceStatBox.jsx new file mode 100644 index 0000000..91cd984 --- /dev/null +++ b/src/layout/collection/collectionGrids/collections-list/statItems/PerformanceStatBox.jsx @@ -0,0 +1,86 @@ +// import MonetizationOnIcon from '@mui/icons-material/MonetizationOn'; +// import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; +// import { useMode } from '../../../../../context'; +// import { Box } from '@mui/material'; +// import StatBox from '../../../../REUSABLE_COMPONENTS/StatBox'; + +// const TotalPriceStatBox = ({ sx }) => { +// const { collectionStats, metaStats } = useCollectionStats(); +// const { theme } = useMode(); +// const colors = theme.palette.chartTheme; +// const primary = colors.primary.dark; +// const greenAccent = colors.greenAccent.light; +// return ( +// +// +// } +// /> +// +// ); +// }; + +// export default TotalPriceStatBox; +import { Box, Typography } from '@mui/material'; +import StatBox from '../../../../REUSABLE_COMPONENTS/StatBox'; +import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; +import { useMode } from '../../../../../context'; +import MonetizationOnIcon from '@mui/icons-material/MonetizationOn'; +import ProgressCircle from '../../../../REUSABLE_COMPONENTS/ProgressCircle'; +import MDBox from '../../../../REUSABLE_COMPONENTS/MDBOX'; + +const PerformanceStatBox = () => { + const { theme } = useMode(); + const colors = theme.palette.chartTheme; + const primary = colors.primary.dark; + const greenAccent = colors.greenAccent.light; + // const primary = colors.primary.default; + // const blue = colors.blueAccent.default; + const green = colors.greenAccent.default; + const greenliht = colors.greenAccent.light; + + const grey = colors.grey.default; + return ( + + + } + /> + + ); +}; + +export default PerformanceStatBox; diff --git a/src/layout/collection/collectionGrids/collections-list/statItems/PricedCardList.jsx b/src/layout/collection/collectionGrids/collections-list/statItems/PricedCardList.jsx index a255e6c..b6b6cc4 100644 --- a/src/layout/collection/collectionGrids/collections-list/statItems/PricedCardList.jsx +++ b/src/layout/collection/collectionGrids/collections-list/statItems/PricedCardList.jsx @@ -1,108 +1,164 @@ +// import MDBox from '../../../../REUSABLE_COMPONENTS/MDBOX'; +// import BoxHeader from '../../../../REUSABLE_COMPONENTS/BoxHeader'; +// import useSelectedCollection from '../../../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; +// import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; +// import { Box, Card, Paper } from '@mui/material'; +// import { useAppContext, useMode } from '../../../../../context'; +// import { DataGrid } from '@mui/x-data-grid'; +// import prepareTableData from '../../../data/topCards'; +// import { roundToNearestTenth } from '../../../../../context/Helpers'; + +// const PricedCardList = () => { +// const { theme } = useMode(); + +// const colors = theme.palette.chartTheme; +// const grey = theme.palette.chartTheme.grey.darkest; +// const lightGrey = theme.palette.chartTheme.grey.lightest; +// const greenAccent = colors.greenAccent.default; +// const primary = colors.primary.dark; + +// const greenliht = colors.greenAccent.light; +// const { collectionStats, metaStats } = useCollectionStats(); +// // const { selectedCollection } = useSelectedCollection(); +// const { cardsWithQuantities } = useAppContext(); +// // const topFiveCards = cardsWithQuantities +// // ?.sort((a, b) => b.price - a.price) +// // .slice(0, 5) +// // .map((card) => ({ +// // ...card, +// // tPrice: roundToNearestTenth(card.totalPrice), +// // action: card, +// // })); +// const topFiveCards = cardsWithQuantities +// ?.sort((a, b) => b.price - a.price) +// .slice(0, 5); +// // console.log('topFiveCards:', topFiveCards); + +// const { data, columns } = prepareTableData(topFiveCards); +// console.log('data:', data); +// console.log('columns:', columns); + +// return ( +// +// +// +// +// +// +// +// +// ); +// }; + +// export default PricedCardList; import MDBox from '../../../../REUSABLE_COMPONENTS/MDBOX'; import BoxHeader from '../../../../REUSABLE_COMPONENTS/BoxHeader'; -import useSelectedCollection from '../../../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; -import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; import { Box } from '@mui/material'; -import { useMode } from '../../../../../context'; +import { useAppContext, useMode } from '../../../../../context'; import { DataGrid } from '@mui/x-data-grid'; import prepareTableData from '../../../data/topCards'; +import styled from 'styled-components'; const PricedCardList = () => { - const { collectionStats, metaStats } = useCollectionStats(); - const { selectedCollection } = useSelectedCollection(); - const { data, columns } = prepareTableData(selectedCollection); const { theme } = useMode(); const colors = theme.palette.chartTheme; - const grey = theme.palette.chartTheme.grey.darkest; - const lightGrey = theme.palette.chartTheme.grey.lightest; - - const greenAccent = colors.greenAccent.default; - - // const renderCurrency = (params) => `$${params.value}`; - - // const productColumns = [ - // { - // field: '_id', - // headerName: 'ID', - // flex: 1, - // }, - // { - // field: 'expense', - // headerName: 'Expense', - // flex: 0.5, - // renderCell: renderCurrency, - // }, - // { - // field: 'price', - // headerName: 'Price', - // flex: 0.5, - // renderCell: renderCurrency, - // }, - // ]; - - // const countItems = (params) => params.value.length; - - // const transactionColumns = [ - // { - // field: '_id', - // headerName: 'ID', - // flex: 1, - // }, - // { - // field: 'buyer', - // headerName: 'Buyer', - // flex: 0.67, - // }, - // { - // field: 'amount', - // headerName: 'Amount', - // flex: 0.35, - // renderCell: renderCurrency, - // }, - // { - // field: 'productIds', - // headerName: 'Count', - // flex: 0.1, - // renderCell: countItems, - // }, - // ]; - - // Assuming productData is available in your context or props - // const productData = []; // Placeholder for actual data + const grey = colors.grey.darkest; + const lightGrey = colors.grey.lightest; + const primary = colors.primary.dark; + const greenAccent = colors.greenAccent.light; + const { cardsWithQuantities } = useAppContext(); + const topFiveCards = cardsWithQuantities + ?.sort((a, b) => b.price - a.price) + .slice(0, 5); + const { data, columns } = prepareTableData(topFiveCards); return ( - - + - */} + + {/* */} + + + ); diff --git a/src/layout/collection/collectionGrids/collections-list/statItems/TotalPriceStatBox.jsx b/src/layout/collection/collectionGrids/collections-list/statItems/TotalPriceStatBox.jsx index 84508fb..f97bc78 100644 --- a/src/layout/collection/collectionGrids/collections-list/statItems/TotalPriceStatBox.jsx +++ b/src/layout/collection/collectionGrids/collections-list/statItems/TotalPriceStatBox.jsx @@ -1,15 +1,62 @@ -import MonetizationOnIcon from '@mui/icons-material/MonetizationOn'; -import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; -import { useMode } from '../../../../../context'; +// import MonetizationOnIcon from '@mui/icons-material/MonetizationOn'; +// import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; +// import { useMode } from '../../../../../context'; +// import { Box } from '@mui/material'; +// import StatBox from '../../../../REUSABLE_COMPONENTS/StatBox'; + +// const TotalPriceStatBox = ({ sx }) => { +// const { collectionStats, metaStats } = useCollectionStats(); +// const { theme } = useMode(); +// const colors = theme.palette.chartTheme; +// const primary = colors.primary.dark; +// const greenAccent = colors.greenAccent.light; +// return ( +// +// +// } +// /> +// +// ); +// }; + +// export default TotalPriceStatBox; import { Box } from '@mui/material'; import StatBox from '../../../../REUSABLE_COMPONENTS/StatBox'; +import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; +import { useMode } from '../../../../../context'; +import MonetizationOnIcon from '@mui/icons-material/MonetizationOn'; +import styled from 'styled-components'; const TotalPriceStatBox = () => { - const { collectionStats, metaStats } = useCollectionStats(); const { theme } = useMode(); const colors = theme.palette.chartTheme; const primary = colors.primary.dark; const greenAccent = colors.greenAccent.light; + const StyledOuterBox = styled(Box)(({ theme }) => ({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: '100%', + backgroundColor: theme.palette.chartTheme.primary.dark, + borderRadius: theme.shape.borderRadius, + })); return ( { display: 'flex', justifyContent: 'center', alignItems: 'center', + // mb: '2rem', + borderRadius: theme.spacing(4), height: '100%', - boxSizing: 'border-box', + minHeight: '135px', + // p: '5px', }} > { +// const { theme } = useMode(); +// const colors = theme.palette.chartTheme; +// const primary = colors.primary.dark; +// const greenAccent = colors.greenAccent.default; + +// return ( +// +// +// +// Campaign +// +// +// +// +// $48,352 revenue generated +// +// Includes extra misc expenditures and costs +// +// +// +// ); +// }; + +// export default ValuDistributionCircle; import { Box, Typography } from '@mui/material'; -import { useMode } from '../../../../../context'; import ProgressCircle from '../../../../REUSABLE_COMPONENTS/ProgressCircle'; +import MDBox from '../../../../REUSABLE_COMPONENTS/MDBOX'; +import { useMode } from '../../../../../context'; const ValuDistributionCircle = () => { const { theme } = useMode(); const colors = theme.palette.chartTheme; const primary = colors.primary.dark; - const greenAccent = colors.greenAccent.default; - + const greenAccent = colors.greenAccent.light; return ( - - - Campaign - - - - - $48,352 revenue generated + + + {/* */} + + Campaign - Includes extra misc expenditures and costs + + + + $48,352 revenue generated + + Includes extra misc expenditures and costs + + {/* */} - + ); }; diff --git a/src/layout/collection/collectionGrids/cards-chart/GenerateNivoTestData.jsx b/src/layout/collection/data/GenerateNivoTestData.jsx similarity index 100% rename from src/layout/collection/collectionGrids/cards-chart/GenerateNivoTestData.jsx rename to src/layout/collection/data/GenerateNivoTestData.jsx diff --git a/src/layout/collection/data/topCards.jsx b/src/layout/collection/data/topCards.jsx index f9828d9..f388e56 100644 --- a/src/layout/collection/data/topCards.jsx +++ b/src/layout/collection/data/topCards.jsx @@ -1,95 +1,78 @@ -import Icon from '@mui/material/Icon'; -// Images -import MDTypography from '../../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; import React from 'react'; -import GenericActionButtons from '../../../components/buttons/actionButtons/GenericActionButtons'; -import { useSnackbar } from 'notistack'; +import MDTypography from '../../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; + const Name = ({ name }) => ( {name} ); + const Price = ({ price }) => ( {price} ); -const TPrice = ({ tPrice }) => ( - - {tPrice} - -); + const Quantity = ({ quantity }) => ( {quantity} ); -export default function prepareTableData(selectedCards) { - const roundToNearestTenth = (value) => Math.round(value * 10) / 10; - const columns = React.useMemo( - () => [ - { - Header: 'Name', - accessor: 'name', - id: 'name', - Cell: ({ value }) => , - }, - { - Header: 'Price', - accessor: 'price', - id: 'price', - Cell: ({ value }) => , - }, - { - Header: 'Quantity', - accessor: 'quantity', - id: 'quantity', - Cell: ({ value }) => , - }, - ], - [] - ); - const data = React.useMemo(() => { - if (!selectedCards || selectedCards.length === 0) { - return []; - } - // Sort by totalPrice in descending order and take the top 5 - const topFiveCards = selectedCards - ?.sort((a, b) => b.price - a.price) - .slice(0, 5) - .map((card) => ({ - ...card, - tPrice: roundToNearestTenth(card.totalPrice), - action: card, - })); +export default function prepareTableData(topCards) { + if (!topCards || topCards.length === 0) { + return { columns: [], data: [] }; + } + console.log('topFiveCards:', topCards); + + const columns = [ + { + field: 'name', + headerName: 'Name', + renderCell: (params) => , + width: 250, + flex: 1, + }, + { + field: 'price', + headerName: 'Price', + renderCell: (params) => , + maxWidth: 50, + flex: 1, + }, + { + field: 'quantity', + headerName: 'Quantity', + renderCell: (params) => , + maxWidth: 50, + flex: 1, + }, + ]; - return topFiveCards; - }, [selectedCards]); + const data = topCards?.map((card, index) => ({ + id: card.id, + name: card.name, + price: card.price, + quantity: card.quantity, + })); return { columns, data }; } diff --git a/src/layout/collection/index.jsx b/src/layout/collection/index.jsx index 8c12811..ad215e7 100644 --- a/src/layout/collection/index.jsx +++ b/src/layout/collection/index.jsx @@ -179,39 +179,19 @@ const CollectionPortfolio = () => { // }, [toggleShowCollections]); useEffect(() => { console.log('VIEW STATE CHANGED', viewState); - console.log('ALL COLLECTION', allCollections); - console.log('SELECTED COLLECTION', selectedCollection); - console.log('SELECTED COLLECTION ID', selectedCollectionId); - console.log('IS COLLECTION VISIBLE', isCollectionVisible); + // console.log('ALL COLLECTION', allCollections); + // console.log('SELECTED COLLECTION', selectedCollection); + // console.log('SELECTED COLLECTION ID', selectedCollectionId); + // console.log('IS COLLECTION VISIBLE', isCollectionVisible); }, [ viewState, - allCollections, - isCollectionVisible, - selectedCollection, - selectedCollectionId, + // allCollections, + // isCollectionVisible, + // selectedCollection, + // selectedCollectionId, ]); const { columns, data } = collectionPortfolioData(selectedCollection?.cards); - // if (!hasFetchedCollections) { - // return ( - // - // - // - // {/* Directly use the SkeletonLoader with 'grid' type and customize gridProps as needed */} - // - // - // - // - // ); - // } return ( { }); }, []); - // const updateCardData = useCallback(() => { - // setCardData((currentCard) => { - // console.log('Updating card data:', cardData); - // console.log('Current card data:', currentCard); - // const newPriceHistory = { - // num: (Math.random() * 10).toFixed(2), // or however you calculate new price - // timestamp: new Date().toISOString(), - // }; - - // return { - // ...currentCard, - // quantity: currentCard.quantity + 1, // Increment quantity or however you update - // dailyPriceHistory: [...currentCard.dailyPriceHistory, newPriceHistory], - // }; - // }); - // }, []); - - // Simulate a cron job with useEffect and setInterval useEffect(() => { const intervalId = setInterval(() => { - updatePriceHistory(); // Update price history every interval - }, 120000); // Update every 5 seconds for example, adjust as needed - - // Cleanup function to clear interval when component unmounts or updates + updatePriceHistory(); + }, 120000); return () => clearInterval(intervalId); }, [updatePriceHistory]); const startUpdates = useCallback(() => { console.log('Starting updates'); if (!intervalId) { - const id = setInterval(updatePriceHistory, 120000); // Update every 2 minutes, adjust as needed + const id = setInterval(updatePriceHistory, 120000); setIntervalId(id); } }, [updatePriceHistory, intervalId]); @@ -85,13 +65,6 @@ const useCardCronJob = (initialCardData) => { pauseUpdates(); }, [initialCardData, pauseUpdates]); - // useEffect(() => { - // return () => { - // // Cleanup interval on component unmount - // if (intervalId) clearInterval(intervalId); - // }; - // }, [intervalId]); - return { cardData, updatePriceHistory, diff --git a/src/pages/HomePage.js b/src/pages/HomePage.js index 7ab5a46..c75dd71 100644 --- a/src/pages/HomePage.js +++ b/src/pages/HomePage.js @@ -1,61 +1,15 @@ import React, { useContext, useEffect, useRef } from 'react'; import { CardHeader, Grid, Box, useMediaQuery } from '@mui/material'; -import { - ModalContext, - useModalContext, -} from '../context/UTILITIES_CONTEXT/ModalContext/ModalContext'; +import { useModalContext } from '../context/UTILITIES_CONTEXT/ModalContext/ModalContext'; import GenericCardDialog from '../components/dialogs/cardDialog/GenericCardDialog'; import DetailsModal from '../components/dialogs/homeDetailsModal/DetailsModal'; -import SplashPage2 from './SplashPage2'; -import pages from '../assets/data/pages.json'; -import SingleCardAnimation from '../assets/animations/SingleCardAnimation'; -import { - useAuthContext, - useCollectionStore, - useMode, - usePageContext, - useUserContext, -} from '../context'; -import useCardCronJob from '../tests/useCardCronJob'; +import SplashPage2 from '../layout/REUSABLE_COMPONENTS/SplashPage2'; import PageLayout from '../layout/Containers/PageLayout'; import HeroSection from './sections/HeroSection'; import MainContentSection from './sections/MainContentSection'; import FeatureCardsSection from './sections/FeatureCardsSection'; -import useSelectedCollection from '../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; -import useCollectionManager from '../context/MAIN_CONTEXT/CollectionContext/useCollectionManager'; -import { DEFAULT_COLLECTION } from '../context/constants'; -const getHomePageSkeletonConfigs = (tiers) => { - const { theme } = useMode(); - const { tertiaryContent, secondaryContent, mainContentFeatureCard } = - theme.skeletonLayouts; - - const homePageSkeletonConfigs = [ - { - ...tertiaryContent, - skeletons: [...tertiaryContent.baseSkeletons], - }, - { - ...secondaryContent, - skeletons: [secondaryContent.baseSkeleton], - }, - { - ...secondaryContent, - skeletons: [secondaryContent.baseSkeleton], // Assuming similar style for another secondary content - }, - ...Array.from({ length: tiers.length }, () => ({ - ...mainContentFeatureCard, - skeletons: [...mainContentFeatureCard.baseSkeletons], - })), - ]; - - return homePageSkeletonConfigs; -}; const HomePage = () => { - const { theme } = useMode(); - const { tiers, introText } = pages; - const { hasFetchedCollections } = useCollectionManager(); - const { allCollections, selectedCollection } = useSelectedCollection(); const { allFeatureData, showDetailsModal, diff --git a/src/pages/pageStyles/StyledComponents.jsx b/src/pages/pageStyles/StyledComponents.jsx index 2f1d46e..2b5cce7 100644 --- a/src/pages/pageStyles/StyledComponents.jsx +++ b/src/pages/pageStyles/StyledComponents.jsx @@ -464,7 +464,7 @@ export const CardListItem = styled(ListItem)(({ theme }) => ({ export const ChartArea = styled(Container)(({ theme }) => ({ height: '100%', width: '100%', - minHeight: '500px', + // minHeight: '500px', position: 'relative', flexGrow: 1, padding: theme.spacing(2), diff --git a/src/pages/sections/HeroSection.jsx b/src/pages/sections/HeroSection.jsx index b877815..e983398 100644 --- a/src/pages/sections/HeroSection.jsx +++ b/src/pages/sections/HeroSection.jsx @@ -19,6 +19,7 @@ import { } from 'swiper/modules'; import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; import HeroSectionSkeleton from '../../layout/REUSABLE_COMPONENTS/SkeletonVariants'; +import { useMediaQuery } from '@mui/material'; // const // return cards?.map((card, index) => ( @@ -51,6 +52,15 @@ import HeroSectionSkeleton from '../../layout/REUSABLE_COMPONENTS/SkeletonVarian const HeroSection = () => { const { theme } = useMode(); + const { breakpoints } = theme; + const isLgUp = useMediaQuery(breakpoints.up('lg')); + const isLgDown = useMediaQuery(breakpoints.down('lg')); + const isMdUp = useMediaQuery(breakpoints.up('md')); + const isBetweenLgMd = isLgDown && isMdUp; + const isMdDown = useMediaQuery(breakpoints.down('md')); + const isSmUp = useMediaQuery(breakpoints.up('sm')); + const isBetweenSmMd = isMdDown && isSmUp; + // const isXs = useMediaQuery(theme.breakpoints.down('sm')); const [activeCardIndex, setActiveCardIndex] = useState(0); const { topFiveCards } = useStatisticsStore(); @@ -61,13 +71,14 @@ const HeroSection = () => { description: `Description for Placeholder ${index + 1}`, image: placeHolder, // Use the placeholder image for all default cards })); - - // Combine topFiveCards with defaultCards const cards = [...topFiveCards, ...defaultCards]; const handleSlideChange = (swiper) => { setActiveCardIndex(swiper.realIndex); }; + // if screen is largest then show 7 slides, else show 5 slides, else show 3 slides, else show 1 slide + const slidesPerView = isLgUp ? 7 : isBetweenLgMd ? 5 : isBetweenSmMd ? 3 : 1; + if (!cards || !Array.isArray(cards) || !cards[activeCardIndex]) { return ; } @@ -115,7 +126,7 @@ const HeroSection = () => { grabCursor={true} centeredSlides={true} loop={true} - slidesPerView={7} // Ensures 7 slides are visible within the 100vw width + slidesPerView={slidesPerView} // Ensures 7 slides are visible within the 100vw width // slidesPerView={'auto'} // spaceBetween={-900} // Reduced space between slides spaceBetween={10} @@ -167,140 +178,3 @@ const HeroSection = () => { }; export default HeroSection; -// -// {return cards?.map((card, index) => ( -// -// {/* */} -// {`slide_${index}`} -// {/* */} -// -// ))} -// -// -// -// ); -// }; - -// export default HeroSection; -// import React, { useState } from 'react'; -// import { Box, Typography } from '@mui/material'; -// import { Swiper, SwiperSlide } from 'swiper/react'; -// import 'swiper/css'; -// import 'swiper/css/effect-coverflow'; -// import 'swiper/css/pagination'; -// import 'swiper/css/navigation'; -// // import { EffectCoverflow, Pagination, Navigation } from 'swiper'; -// import { EffectCoverflow, Pagination, Navigation } from 'swiper/modules'; - -// import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; -// import placeHolder from '../../assets/images/placeholder.jpeg'; -// import { useStatisticsStore } from '../../context'; - -// const HeroSection = () => { -// const [activeCardIndex, setActiveCardIndex] = useState(0); -// const { topFiveCards } = useStatisticsStore(); - -// if (!topFiveCards || !Array.isArray(topFiveCards)) { -// return null; -// } - -// // Handle the slide change event -// const handleSlideChange = (swiper) => { -// setActiveCardIndex(swiper.realIndex); -// }; - -// const createSlider = (cards) => { -// return ( -// -// {cards.map((card, index) => ( -// -// -// {`slide_${index}`} -// -// -// ))} -// -// ); -// }; - -// return ( -// -// -// {topFiveCards[activeCardIndex]?.name} -// -// {createSlider(topFiveCards)} -// {topFiveCards[activeCardIndex]?.description} -// -// ); -// }; - -// export default HeroSection; diff --git a/src/pages/sections/MainContentSection.jsx b/src/pages/sections/MainContentSection.jsx index b97c8a2..632bb98 100644 --- a/src/pages/sections/MainContentSection.jsx +++ b/src/pages/sections/MainContentSection.jsx @@ -21,9 +21,9 @@ import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; import MDAvatar from '../../layout/REUSABLE_COMPONENTS/MDAVATAR'; import MDButton from '../../layout/REUSABLE_COMPONENTS/MDBUTTON'; -import useCardCronJob from '../../tests/useCardCronJob'; import SingleCardAnimation from '../../assets/animations/SingleCardAnimation'; -import CardChart from '../../tests/CardChart'; +import CardChart from '../../layout/CardChart'; +import useCardCronJob from '../../layout/useCardCronJob'; import { StyledContainerBox, StyledPaper, @@ -37,10 +37,8 @@ const MainContentSection = () => { const { theme } = useMode(); const { authUser } = useAuthContext(); const { user } = useUserContext(); - const { hasFetchedCollections } = useCollectionManager(); const { allCollections, selectedCollection } = useSelectedCollection(); - // const isDataLoaded = allCollections && allCollections.length > 0; const isMdUp = useMediaQuery(theme.breakpoints.up('md')); const initialCardsData = hasFetchedCollections ? allCollections[0]?.cards[0] @@ -63,7 +61,6 @@ const MainContentSection = () => { {isMdUp && ( { diff --git a/src/layout/collection/collectionGrids/collections-list/statItems/ValueDistPieChart.jsx b/src/save/ValueDistPieChart.jsx similarity index 100% rename from src/layout/collection/collectionGrids/collections-list/statItems/ValueDistPieChart.jsx rename to src/save/ValueDistPieChart.jsx diff --git a/src/save/tokens.jsx b/src/save/tokens.jsx new file mode 100644 index 0000000..a8992af --- /dev/null +++ b/src/save/tokens.jsx @@ -0,0 +1,132 @@ +// export const tokens = (mode) => ({ +// ...(mode === 'dark' +// ? { +// grey: { +// 100: '#e0e0e0', +// 200: '#c2c2c2', +// 300: '#a3a3a3', +// 400: '#858585', +// 500: '#666666', +// 600: '#525252', +// 700: '#3d3d3d', +// 800: '#292929', +// 900: '#141414', +// }, +// primary: { +// 100: '#d0d1d5', +// 200: '#a1a4ab', +// 300: '#727681', +// 400: '#1F2A40', +// 500: '#141b2d', +// 600: '#101624', +// 700: '#0c101b', +// 800: '#080b12', +// 900: '#040509', +// }, +// blueGreenAccent: { +// 100: '#dbf5f2', // Lightest shade, more towards blue +// 200: '#b7ebe6', +// 300: '#93e1da', +// 400: '#6fd7ce', +// 500: '#4bcdc2', // Mid-value, a balanced blue-green +// 600: '#39a59b', +// 700: '#2b7d76', +// 800: '#1d5551', +// 900: '#0f2d28', // Darkest shade, deeper blue-green +// }, +// greenAccent: { +// 100: '#dbf5ee', +// 200: '#b7ebde', +// 300: '#94e2cd', +// 400: '#70d8bd', +// 500: '#4cceac', +// 600: '#3da58a', +// 700: '#2e7c67', +// 800: '#1e5245', +// 900: '#0f2922', +// }, +// redAccent: { +// 100: '#f8dcdb', +// 200: '#f1b9b7', +// 300: '#e99592', +// 400: '#e2726e', +// 500: '#db4f4a', +// 600: '#af3f3b', +// 700: '#832f2c', +// 800: '#58201e', +// 900: '#2c100f', +// }, +// blueAccent: { +// 100: '#e1e2fe', +// 200: '#c3c6fd', +// 300: '#a4a9fc', +// 400: '#868dfb', +// 500: '#6870fa', +// 600: '#535ac8', +// 700: '#3e4396', +// 800: '#2a2d64', +// 900: '#151632', +// }, +// } +// : { +// grey: { +// 100: '#141414', +// 200: '#292929', +// 300: '#3d3d3d', +// 400: '#525252', +// 500: '#666666', +// 600: '#858585', +// 700: '#a3a3a3', +// 800: '#c2c2c2', +// 900: '#e0e0e0', +// }, +// primary: { +// 100: '#040509', +// 200: '#080b12', +// 300: '#0c101b', +// 400: '#f2f0f0', // manually changed +// 500: '#141b2d', +// 600: '#1F2A40', +// 700: '#727681', +// 800: '#a1a4ab', +// 900: '#d0d1d5', +// }, +// // secondary: { +// // 100: '#ff7961', +// // 200: '#f44336', +// // }, +// greenAccent: { +// 100: '#0f2922', +// 200: '#1e5245', +// 300: '#2e7c67', +// 400: '#3da58a', +// 500: '#4cceac', +// 600: '#70d8bd', +// 700: '#94e2cd', +// 800: '#b7ebde', +// 900: '#dbf5ee', +// }, +// redAccent: { +// 100: '#2c100f', +// 200: '#58201e', +// 300: '#832f2c', +// 400: '#af3f3b', +// 500: '#db4f4a', +// 600: '#e2726e', +// 700: '#e99592', +// 800: '#f1b9b7', +// 900: '#f8dcdb', +// }, +// blueAccent: { +// 100: '#151632', +// 200: '#2a2d64', +// 300: '#3e4396', +// 400: '#535ac8', +// 500: '#6870fa', +// 600: '#868dfb', +// 700: '#a4a9fc', +// 800: '#c3c6fd', +// 900: '#e1e2fe', +// }, +// }), +// }); diff --git a/src/assets/serviceWorker.js b/src/serviceWorker.js similarity index 100% rename from src/assets/serviceWorker.js rename to src/serviceWorker.js diff --git a/src/tests/CardLinearChart.jsx b/src/tests/CardLinearChart.jsx deleted file mode 100644 index 435596d..0000000 --- a/src/tests/CardLinearChart.jsx +++ /dev/null @@ -1,215 +0,0 @@ -import { Box, Tooltip, Typography, useMediaQuery } from '@mui/material'; - -import { ResponsiveLine } from '@nivo/line'; -import { useCallback, useMemo, useState } from 'react'; -import { useMode } from '../context'; -import styled from 'styled-components'; -const AxisLabel = styled('div')(({ theme }) => ({ - position: 'absolute', - textAlign: 'center', - margin: theme.spacing(2), - fontSize: '1rem', - fontWeight: 'bold', - color: theme.palette.text.primary, -})); - -const ChartContainer = styled(Box)(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - width: '100%', - height: 'auto', - [theme.breakpoints.down('sm')]: { - width: '150%', // Adjust width for mobile screens - height: '300px', // Adjust height for mobile screens - transform: 'translateX(10%)', // Shift the chart to the right by 50% - }, -})); - -const CustomTooltip = ({ point }) => { - const { theme } = useMode(); - const { serieId, data: { label, xFormatted, yFormatted } = {} } = point; - return ( - - - - {`Card: ${label}`} - - - {`Time: ${new Date(xFormatted).toLocaleString()}`} - - - {`Value: $${parseFloat(yFormatted).toFixed(2)}`} - - - - ); -}; -const parseDate = (dateString) => { - const date = new Date(dateString); - if (isNaN(date.getTime())) { - console.error(`Invalid date: ${dateString}`); - return null; // or a sensible default, or throw an error, depending on your needs - } - return date; -}; -export const useEventHandlers = () => { - const [hoveredData, setHoveredData] = useState(null); - const handleMouseMove = useCallback((point) => { - setHoveredData(point ? { x: point.data.x, y: point.data.y } : null); - }, []); - const handleMouseLeave = useCallback(() => setHoveredData(null), []); - return { hoveredData, handleMouseMove, handleMouseLeave }; -}; - -const CardLinearChart = ({ nivoReadyData, dimensions }) => { - const { theme } = useMode(); - - // Ensure all data points have valid dates - const processedData = useMemo(() => { - return nivoReadyData?.map((series) => ({ - ...series, - data: series?.data?.map((point) => ({ - ...point, - x: parseDate(point?.x) || point?.x, // Use the parsed date or fallback to the original value - })), - })); - }, [nivoReadyData]); - - const chartProps = useMemo( - () => ({ - data: processedData, - margin: { top: 20, right: 20, bottom: 20, left: 35 }, - xScale: { - type: 'time', - format: 'time:%Y-%m-%dT%H:%M:%S.%LZ', - useUTC: false, - precision: 'second', - }, - axisBottom: { - tickRotation: 0, - legend: 'Time', - legendOffset: 36, - legendPosition: 'middle', - tickSize: 5, - tickPadding: 5, - tickValues: 'every 2 days', - format: '%b %d', - }, - enableSlices: 'x', - yScale: { type: 'linear', min: 'auto', max: 'auto' }, - }), - [nivoReadyData, processedData] - ); - - if (!processedData || !processedData?.length) { - return No data available; - } - return ( - - - - ); -}; - -export default CardLinearChart; -// const { theme } = useMode(); -// const isMobile = useMediaQuery(theme.breakpoints.down('sm')); -// const [isZoomed, setIsZoomed] = useState(false); -// const { handleMouseMove, handleMouseLeave } = useEventHandlers(); - -// if ( -// !nivoReadyData || -// nivoReadyData.length === 0 || -// !Array.isArray(nivoReadyData) -// ) { -// return No data available; -// } - -// // Correct the date parsing logic -// const processedData = nivoReadyData.map((series) => ({ -// ...series, -// data: series.data.map((point) => ({ -// ...point, -// x: parseDate(point.x) || point.x, // Use the parsed date or fallback to the original value -// })), -// })); - -// // Ensure all data points have valid dates -// nivoReadyData?.forEach((series) => { -// series?.data?.forEach((point) => { -// const date = parseDate(point?.x); -// if (!(date instanceof Date)) { -// // Convert to date or handle error -// console.warn('Invalid date found in chart data', date); - -// // Example of converting to date -// const date = new Date(date); -// if (date instanceof Date && !isNaN(date)) { -// point.x = date; -// } -// } -// }); -// }); - -// Calculate chart properties based on nivoReadyData and dimensions -// Minimal chart properties for testing -// animate: true, -// motionStiffness: 90, -// motionDamping: 15, -// axisLeft: { -// orient: 'left', -// legend: 'Price', -// legendOffset: -40, -// legendPosition: 'middle', -// tickSize: 5, -// tickPadding: 5, -// }, -// pointSize: 10, -// pointColor: { theme: 'background' }, -// pointBorderWidth: 2, -// pointBorderColor: { from: 'serieColor' }, -// useMesh: true, -// const chartProps = useMemo( -// () => ({ -// data: processedData, -// margin: { top: 50, right: 110, bottom: 50, left: 60 }, -// xScale: { -// type: 'time', -// format: 'time:%Y-%m-%dT%H:%M:%S.%LZ', -// useUTC: false, -// precision: 'second', -// }, -// xFormat: 'time:%Y-%m-%d %H:%M:%S', -// yScale: { type: 'linear', min: 'auto', max: 'auto' }, -// animate: true, -// motionStiffness: 90, -// motionDamping: 15, -// axisLeft: { -// orient: 'left', -// legend: 'Price', -// legendOffset: -40, -// legendPosition: 'middle', -// tickSize: 5, -// tickPadding: 5, -// }, -// pointSize: 10, -// pointColor: { theme: 'background' }, -// pointBorderWidth: 2, -// pointBorderColor: { from: 'serieColor' }, -// useMesh: true, -// enableSlices: 'x', -// }), -// [processedData, theme, isMobile] // Add other dependencies as needed -// ); // Add other dependencies as needed - -// console.log('Nivo Ready Data:', nivoReadyData); -// console.log('Processed Data:', processedData); -// console.log('Chart Dimensions:', dimensions); diff --git a/src/zcleanup/styleOverride/compStyleOverride.jsx b/src/zcleanup/styleOverride/compStyleOverride.jsx new file mode 100644 index 0000000..d19a2a6 --- /dev/null +++ b/src/zcleanup/styleOverride/compStyleOverride.jsx @@ -0,0 +1,187 @@ +// export default function componentStyleOverrides(theme) { +// const bgColor = theme.colors?.grey50; +// return { +// MuiButton: { +// styleOverrides: { +// root: { +// fontWeight: 500, +// borderRadius: '4px', +// }, +// }, +// }, +// MuiPaper: { +// defaultProps: { +// elevation: 0, +// }, +// styleOverrides: { +// root: { +// backgroundImage: 'none', +// }, +// rounded: { +// borderRadius: `${theme?.customization?.borderRadius}px`, +// }, +// }, +// }, +// MuiCardHeader: { +// styleOverrides: { +// root: { +// color: theme.colors?.textDark, +// padding: '24px', +// }, +// title: { +// fontSize: '1.125rem', +// }, +// }, +// }, +// MuiCardContent: { +// styleOverrides: { +// root: { +// padding: '24px', +// }, +// }, +// }, +// MuiCardActions: { +// styleOverrides: { +// root: { +// padding: '24px', +// }, +// }, +// }, +// MuiListItemButton: { +// styleOverrides: { +// root: { +// color: theme.darkTextPrimary, +// paddingTop: '10px', +// paddingBottom: '10px', +// '&.Mui-selected': { +// color: theme.menuSelected, +// backgroundColor: theme.menuSelectedBack, +// '&:hover': { +// backgroundColor: theme.menuSelectedBack, +// }, +// '& .MuiListItemIcon-root': { +// color: theme.menuSelected, +// }, +// }, +// '&:hover': { +// backgroundColor: theme.menuSelectedBack, +// color: theme.menuSelected, +// '& .MuiListItemIcon-root': { +// color: theme.menuSelected, +// }, +// }, +// }, +// }, +// }, +// MuiListItemIcon: { +// styleOverrides: { +// root: { +// color: theme.darkTextPrimary, +// minWidth: '36px', +// }, +// }, +// }, +// MuiListItemText: { +// styleOverrides: { +// primary: { +// color: theme.textDark, +// }, +// }, +// }, +// MuiInputBase: { +// styleOverrides: { +// input: { +// color: theme.textDark, +// '&::placeholder': { +// color: theme.darkTextSecondary, +// fontSize: '0.875rem', +// }, +// }, +// }, +// }, +// MuiOutlinedInput: { +// styleOverrides: { +// root: { +// background: bgColor, +// borderRadius: `${theme?.customization?.borderRadius}px`, +// '& .MuiOutlinedInput-notchedOutline': { +// borderColor: theme.colors?.grey400, +// }, +// '&:hover $notchedOutline': { +// borderColor: theme.colors?.primaryLight, +// }, +// '&.MuiInputBase-multiline': { +// padding: 1, +// }, +// }, +// input: { +// fontWeight: 500, +// background: bgColor, +// padding: '15.5px 14px', +// borderRadius: `${theme?.customization?.borderRadius}px`, +// '&.MuiInputBase-inputSizeSmall': { +// padding: '10px 14px', +// '&.MuiInputBase-inputAdornedStart': { +// paddingLeft: 0, +// }, +// }, +// }, +// inputAdornedStart: { +// paddingLeft: 4, +// }, +// notchedOutline: { +// borderRadius: `${theme?.customization?.borderRadius}px`, +// }, +// }, +// }, +// MuiSlider: { +// styleOverrides: { +// root: { +// '&.Mui-disabled': { +// color: theme.colors?.grey300, +// }, +// }, +// mark: { +// backgroundColor: theme.paper, +// width: '4px', +// }, +// valueLabel: { +// color: theme?.colors?.primaryLight, +// }, +// }, +// }, +// MuiDivider: { +// styleOverrides: { +// root: { +// borderColor: theme.divider, +// opacity: 1, +// }, +// }, +// }, +// MuiAvatar: { +// styleOverrides: { +// root: { +// color: theme.colors?.primaryDark, +// background: theme.colors?.primary200, +// }, +// }, +// }, +// MuiChip: { +// styleOverrides: { +// root: { +// '&.MuiChip-deletable .MuiChip-deleteIcon': { +// color: 'inherit', +// }, +// }, +// }, +// }, +// MuiTooltip: { +// styleOverrides: { +// tooltip: { +// color: theme.paper, +// background: theme.colors?.grey700, +// }, +// }, +// }, +// }; +// } From 956e8738ad6aa7eae2775b0b3d9691ade32953ee Mon Sep 17 00:00:00 2001 From: Reed Vogt Date: Thu, 14 Mar 2024 23:47:03 -0700 Subject: [PATCH 02/10] Completed styling and layout as well as mobile responsive design for hero swiper carousel. Mde additional improvemnts to various styled component such as simple button --- src/assets/css/index.css | 37 +- src/components/cards/AnimatedFeatureCard.jsx | 28 +- src/layout/CardChart.jsx | 583 ++++++++++++------ src/layout/CardLinearChart.jsx | 2 +- .../unique/SimpleButton.jsx | 43 +- src/layout/collection/index.jsx | 104 +--- src/pages/HomePage.js | 2 +- src/pages/sections/HeroSection.jsx | 221 ++++--- src/pages/sections/MainContentSection.jsx | 25 +- 9 files changed, 653 insertions(+), 392 deletions(-) diff --git a/src/assets/css/index.css b/src/assets/css/index.css index 5ff2073..25a37ea 100644 --- a/src/assets/css/index.css +++ b/src/assets/css/index.css @@ -147,7 +147,7 @@ button { /* padding: 60px; */ } -.hero-section-container { +/* .hero-section-container { background: rgba(189, 181, 181, 0.1); box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1); backdrop-filter: blur(20px); @@ -155,9 +155,32 @@ button { border: 1px solid rgba(255, 255, 255, 0.3); border-radius: 25px; /* padding: 30px 0px; */ - width: '100vw'; +/* width: '100vw'; */ +/* width: min(1200px, 100%); */ +/* } */ +.hero-section-container { + background: rgba(189, 181, 181, 0.1); + box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1); + backdrop-filter: blur(5px); + -webkit-backdrop-filter: blur(20px); + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 25px; + /* padding: 30px 0px; */ + /* width: '100vw'; */ /* width: min(1200px, 100%); */ } +.hero-section-container-left { + position: absolute; + top: 20px; /* Adjust as needed */ + left: 20px; /* Adjust as needed */ + width: 200px; /* Adjust as needed */ + height: 100px; /* Adjust as needed */ + /* background-color: rgba(255, 255, 255, 0.8); Semi-transparent white */ + display: flex; + justify-content: center; + align-items: center; + z-index: 2; /* Ensure it's above the swiper slides */ +} /* .hero-section h1 { font-size: 3.5rem; @@ -216,6 +239,14 @@ button { width: 100vw; /* Adjust based on your design needs */ overflow: hidden; /* Prevent overflow */ } + +/* .swiper-wrapper { + display: flex; /* Ensure the slides are in a row */ + /* transition: transform 0.3s; /* Smooth transition */ + /* align-items: center; + justify-content: center; +} */ + .swiper-scrollbar { --swipeer-scrollbar-bottom: 0; --swipeer-scrollbar-drag-bg-color: #dda3b6; @@ -333,7 +364,7 @@ button { } .swiper-slide-active { - transform: scale(2); /* Make the active slide larger */ + transform: scale(8); /* Make the active slide larger */ transition: transform 0.3s; /* Smooth transition */ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* Add a shadow */ } diff --git a/src/components/cards/AnimatedFeatureCard.jsx b/src/components/cards/AnimatedFeatureCard.jsx index 5a22174..9547dd1 100644 --- a/src/components/cards/AnimatedFeatureCard.jsx +++ b/src/components/cards/AnimatedFeatureCard.jsx @@ -9,6 +9,8 @@ import { } from '../../pages/pageStyles/StyledComponents'; import { useMode } from '../../context'; import MDButton from '../../layout/REUSABLE_COMPONENTS/MDBUTTON'; +import SimpleButton from '../../layout/REUSABLE_COMPONENTS/unique/SimpleButton'; +import uniqueTheme from '../../layout/REUSABLE_COMPONENTS/unique/uniqueTheme'; const AnimatedBox = animated(Box); @@ -72,7 +74,29 @@ export const AnimatedFeatureCard = ({ tier, onOpenModal }) => { flexGrow: 1, }} > - { + console.log('clicked'); + }} + sx={{ + flexGrow: 1, + justifySelf: 'bottom', + bottom: 0, + width: '100%', + mt: 'auto', + }} + > + Manage Collections + + {/* { }} > {tier.buttonText} - + */} diff --git a/src/layout/CardChart.jsx b/src/layout/CardChart.jsx index 4ba5ed9..21d9e36 100644 --- a/src/layout/CardChart.jsx +++ b/src/layout/CardChart.jsx @@ -1,8 +1,293 @@ +// import React, { useState, useEffect, useMemo } from 'react'; +// import { +// Box, +// Card, +// CardActions, +// CardContent, +// CardHeader, +// IconButton, +// List, +// ListItem, +// Paper, +// Typography, +// useMediaQuery, +// } from '@mui/material'; +// import MoreVertIcon from '@mui/icons-material/MoreVert'; +// import CardLinearChart from './CardLinearChart'; +// import { ErrorBoundary, useMode, usePageContext } from '../context'; +// import useCardCronJob from './useCardCronJob'; +// import initialCardData from '../data/initialCardData'; +// import { format } from 'date-fns'; +// import LoadingCardAnimation from '../assets/animations/LoadingCardAnimation'; +// import styled from 'styled-components'; +// import MDButton from './REUSABLE_COMPONENTS/MDBUTTON'; +// import { useLoading } from '../context/hooks/useLoading'; + +// const ChartArea = styled(Box)(({ theme }) => ({ +// width: '100%', +// height: '100%', +// padding: theme.spacing(2), +// display: 'flex', +// alignItems: 'center', +// justifyContent: 'center', +// border: '1px solid #000', +// borderRadius: '5px', +// })); +// const SquareChartContainer = styled(Box)(({ theme }) => ({ +// position: 'relative', +// width: '100%', +// paddingTop: '100%', +// overflow: 'hidden', +// '& > *': { +// position: 'absolute', +// top: 0, +// left: 0, +// right: 0, +// bottom: 0, +// }, +// })); + +// const CardChart = ({ cardData = initialCardData }) => { +// // STYLING AND MEDIA QUERY HOOKS +// const { theme } = useMode(); +// const isLgUp = useMediaQuery(theme.breakpoints.up('lg')); +// const [imageUrl, setImageUrl] = useState(null); +// const { startUpdates, pauseUpdates, resetData } = +// useCardCronJob(initialCardData); +// const formatTimestamp = (timestamp) => +// format(new Date(timestamp), "MMM do, yyyy 'at' HH:mm"); +// const [chartDimensions, setChartDimensions] = useState({ +// width: 0, +// height: 0, +// }); +// const { returnDisplay } = usePageContext(); +// const { isLoading } = useLoading(); +// useEffect(() => { +// if (cardData?.imageUrl) { +// console.log('Setting image url', cardData?.imageUrl); +// setImageUrl(cardData?.image); +// } +// }, [cardData?.imageUrl]); + +// const nivoReadyData = useMemo( +// () => [ +// { +// id: cardData?.name || 'default', +// data: cardData?.dailyPriceHistory?.map(({ timestamp, num }) => ({ +// x: timestamp, +// y: num, +// })), +// }, +// ], +// [cardData] +// ); +// const renderLoadingAnimation = () => +// isLgUp && ; +// useEffect(() => { +// if (isLoading('fetchCollections')) { +// console.log('Fetching collections'); +// } +// }, [isLoading('fetchCollections')]); +// useEffect(() => { +// const updateDimensions = () => { +// const width = window.innerWidth < 500 ? window.innerWidth : 500; +// const height = 300; +// setChartDimensions({ width, height }); +// }; + +// window.addEventListener('resize', updateDimensions); +// updateDimensions(); + +// return () => { +// window.removeEventListener('resize', updateDimensions); +// }; +// }, []); +// const renderHeaderWithAnimation = () => { +// return ( +// +// +// +// +// } +// title="Card Cron Job Simulator" +// subheader={cardData?.name || 'Card Name'} +// sx={{ +// padding: theme.spacing(1), +// margin: theme.spacing(1), +// }} +// /> +// {isLgUp && renderLoadingAnimation()} +// +// ); +// }; +// return ( +// +// +// +// +// {renderHeaderWithAnimation()} +// + +// +// +// {isLoading('fetchCollections') ? ( +// returnDisplay() +// ) : ( +// +// +// +// )} +// +// +// + +// +// +// {['Start Updates', 'Pause Updates', 'Reset Data'].map( +// (text, index) => ( +// { +// if (text === 'Start Updates') startUpdates(); +// else if (text === 'Pause Updates') pauseUpdates(); +// else if (text === 'Reset Data') resetData(); +// }} +// color="primary" +// variant="contained" +// sx={{ +// color: theme.palette.backgroundA.contrastText, +// background: theme.palette.backgroundF.darker, +// borderColor: theme.palette.backgroundB.darkest, +// borderWidth: 2, +// mt: 'auto', +// flexGrow: 1, +// justifySelf: 'bottom', +// bottom: 0, +// width: '100%', +// '&:hover': { +// color: theme.palette.backgroundA.contrastTextC, +// fontWeight: 'bold', +// background: theme.palette.backgroundF.dark, +// borderColor: theme.palette.backgroundB.darkest, +// border: `1px solid ${theme.palette.backgroundB.darkest}`, +// }, +// }} +// > +// {text} +// +// ) +// )} +// +// +// +// +// {cardData?.dailyPriceHistory?.map((entry, index) => ( +// +// +// Quantity: {cardData?.quantity} +// +// +// Price: ${entry?.num} +// +// +// {formatTimestamp(entry?.timestamp)} +// +// +// ))} +// +// +// +// +// +// +// ); +// }; + +// export default CardChart; import React, { useState, useEffect, useMemo } from 'react'; import { Box, Card, - CardActions, CardContent, CardHeader, IconButton, @@ -10,18 +295,22 @@ import { ListItem, Paper, Typography, + useTheme, useMediaQuery, + CardActions, } from '@mui/material'; import MoreVertIcon from '@mui/icons-material/MoreVert'; import CardLinearChart from './CardLinearChart'; -import { ErrorBoundary, useMode, usePageContext } from '../context'; +import { ErrorBoundary, useMode } from '../context'; import useCardCronJob from './useCardCronJob'; import initialCardData from '../data/initialCardData'; import { format } from 'date-fns'; import LoadingCardAnimation from '../assets/animations/LoadingCardAnimation'; -import styled from 'styled-components'; import MDButton from './REUSABLE_COMPONENTS/MDBUTTON'; import { useLoading } from '../context/hooks/useLoading'; +import styled from 'styled-components'; +import uniqueTheme from './REUSABLE_COMPONENTS/unique/uniqueTheme'; +import SimpleButton from './REUSABLE_COMPONENTS/unique/SimpleButton'; const ChartArea = styled(Box)(({ theme }) => ({ width: '100%', @@ -33,253 +322,171 @@ const ChartArea = styled(Box)(({ theme }) => ({ border: '1px solid #000', borderRadius: '5px', })); -const SquareChartContainer = styled(Box)(({ theme }) => ({ + +const SquareChartContainer = styled(Box)({ position: 'relative', - width: '100%', - paddingTop: '100%', + flex: 1, overflow: 'hidden', - '& > *': { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, - }, -})); +}); -const CardChart = ({ cardData = initialCardData }) => { - // STYLING AND MEDIA QUERY HOOKS +const CardChart = () => { const { theme } = useMode(); + const isMobileView = useMediaQuery(theme.breakpoints.down('sm')); const isLgUp = useMediaQuery(theme.breakpoints.up('lg')); - const [imageUrl, setImageUrl] = useState(null); const { startUpdates, pauseUpdates, resetData } = useCardCronJob(initialCardData); - const formatTimestamp = (timestamp) => - format(new Date(timestamp), "MMM do, yyyy 'at' HH:mm"); - const [chartDimensions, setChartDimensions] = useState({ - width: 0, - height: 0, - }); - const { returnDisplay } = usePageContext(); + const [cardData, setCardData] = useState(initialCardData); const { isLoading } = useLoading(); + + const getResponsiveDimensions = () => { + return isMobileView + ? { width: window.innerWidth / 2, height: window.innerHeight * 0.5 } + : { width: 500, height: 300 }; + }; + + const [chartDimensions, setChartDimensions] = useState( + getResponsiveDimensions() + ); + useEffect(() => { - if (cardData?.imageUrl) { - console.log('Setting image url', cardData?.imageUrl); - setImageUrl(cardData?.image); - } - }, [cardData?.imageUrl]); + const handleResize = () => { + setChartDimensions(getResponsiveDimensions()); + }; + + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, [isMobileView]); const nivoReadyData = useMemo( () => [ { - id: cardData?.name || 'default', - data: cardData?.dailyPriceHistory?.map(({ timestamp, num }) => ({ - x: timestamp, + id: cardData.name || 'default', + data: cardData.dailyPriceHistory.map(({ timestamp, num }) => ({ + x: format(new Date(timestamp), 'Pp'), y: num, })), }, ], [cardData] ); - const renderLoadingAnimation = () => - isLgUp && ; - useEffect(() => { - if (isLoading('fetchCollections')) { - console.log('Fetching collections'); - } - }, [isLoading('fetchCollections')]); - useEffect(() => { - const updateDimensions = () => { - const width = window.innerWidth < 500 ? window.innerWidth : 500; - const height = 300; - setChartDimensions({ width, height }); - }; - - window.addEventListener('resize', updateDimensions); - updateDimensions(); - return () => { - window.removeEventListener('resize', updateDimensions); - }; - }, []); - const renderHeaderWithAnimation = () => { - return ( - - - - - } - title="Card Cron Job Simulator" - subheader={cardData?.name || 'Card Name'} - sx={{ - padding: theme.spacing(1), - margin: theme.spacing(1), - }} - /> - {isLgUp && renderLoadingAnimation()} - - ); - }; return ( - + - - {renderHeaderWithAnimation()} - - + + + + ) + } + title="Card Cron Job Simulator" + subheader={cardData.name || 'Card Name'} + /> + {!isMobileView && isLgUp && isLoading('fetchCollections') && ( + + )} - - {isLoading('fetchCollections') ? ( - returnDisplay() - ) : ( - - - - )} + + - - - {['Start Updates', 'Pause Updates', 'Reset Data'].map( - (text, index) => ( - { - if (text === 'Start Updates') startUpdates(); - else if (text === 'Pause Updates') pauseUpdates(); - else if (text === 'Reset Data') resetData(); - }} - color="primary" - variant="contained" - sx={{ - color: theme.palette.backgroundA.contrastText, - background: theme.palette.backgroundF.darker, - borderColor: theme.palette.backgroundB.darkest, - borderWidth: 2, - mt: 'auto', - flexGrow: 1, - justifySelf: 'bottom', - bottom: 0, - width: '100%', - '&:hover': { - color: theme.palette.backgroundA.contrastTextC, - fontWeight: 'bold', - background: theme.palette.backgroundF.dark, - borderColor: theme.palette.backgroundB.darkest, - border: `1px solid ${theme.palette.backgroundB.darkest}`, - }, - }} - > - {text} - - ) - )} - - - - {cardData?.dailyPriceHistory?.map((entry, index) => ( - + + {cardData.dailyPriceHistory.map((entry, index) => ( + - Quantity: {cardData?.quantity} + Quantity: {cardData.quantity} - Price: ${entry?.num} + Price: ${entry.num} - {formatTimestamp(entry?.timestamp)} + {format( + new Date(entry.timestamp), + "MMM do, yyyy 'at' HH:mm" + )} ))} - + ) : ( + + {['Start Updates', 'Pause Updates', 'Reset Data'].map( + (action, index) => ( + { + if (action === 'Start Updates') startUpdates(); + else if (action === 'Pause Updates') pauseUpdates(); + else resetData(); + }} + > + {action} + + ) + )} + + )} - + ); }; diff --git a/src/layout/CardLinearChart.jsx b/src/layout/CardLinearChart.jsx index 2dd03cf..006513d 100644 --- a/src/layout/CardLinearChart.jsx +++ b/src/layout/CardLinearChart.jsx @@ -13,7 +13,7 @@ const ChartContainer = styled(Box)(({ theme }) => ({ [theme.breakpoints.down('sm')]: { width: '150%', // Adjust width for mobile screens height: '300px', // Adjust height for mobile screens - transform: 'translateX(10%)', // Shift the chart to the right by 50% + // transform: 'translateX(10%)', // Shift the chart to the right by 50% }, })); diff --git a/src/layout/REUSABLE_COMPONENTS/unique/SimpleButton.jsx b/src/layout/REUSABLE_COMPONENTS/unique/SimpleButton.jsx index 2891fe3..a485fc8 100644 --- a/src/layout/REUSABLE_COMPONENTS/unique/SimpleButton.jsx +++ b/src/layout/REUSABLE_COMPONENTS/unique/SimpleButton.jsx @@ -8,21 +8,52 @@ const SimpleButton = ({ isAccent, isDefault, isDisabled, + customColor, + customTextColor, + customSize, ...rest }) => { + const calculateStyles = (size) => { + switch (size) { + case 'sm': + return { + width: '75px', + // p: '1rem', + p: '0.5rem 0.75rem', + // m: '0.5rem', + fontSize: '0.875rem', + }; + case 'md': + return { + width: '100px', + padding: '0.75rem 1rem', + fontSize: '1rem', + }; + default: + return { + width: '140px', + padding: '1rem 1.25rem', + fontSize: '1.125rem', + }; + } + }; const baseStyle = { position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center', width: '100%', - minWidth: '140px', - padding: `1.035rem ${theme.lenMd1}`, + minWidth: calculateStyles(customSize).width, + padding: calculateStyles(customSize).padding, + // minWidth: customSize === 'md' ? 100 : customSize === 'sm' ? 75 : 140, + // padding: `1.035rem ${theme.lenMd1}`, borderRadius: theme.borderRadius, + fontSize: calculateStyles(customSize).fontSize, + transitionProperty: 'color, background, box-shadow', transitionDuration: '0.35s', - background: theme.colorDefaultBackground, - color: theme.colorDefaultText, + background: !customColor ? theme.colorDefaultBackground : customColor, + color: !customTextColor ? theme.colorDefaultText : customTextColor, boxShadow: isDefault ? `0 0 0 4px ${rgba(theme.colorDefaultBackground || 'white', 0.74)}` : 'none', @@ -51,7 +82,9 @@ const SimpleButton = ({ width: '100%', height: '100%', borderRadius: theme.borderRadius, - background: 'rgba(0, 0, 0, 0.075)', + background: customColor + ? rgba(customColor, 0.15) // Lighter shade of customColor if provided + : 'rgba(0, 0, 0, 0.075)', opacity: 0, pointerEvents: 'none', transition: 'opacity 0.35s', diff --git a/src/layout/collection/index.jsx b/src/layout/collection/index.jsx index ad215e7..eba97b7 100644 --- a/src/layout/collection/index.jsx +++ b/src/layout/collection/index.jsx @@ -31,79 +31,23 @@ import SelectCollectionHeader from './collectionGrids/collections-list/SelectCol import DashboardBox from '../REUSABLE_COMPONENTS/DashboardBox'; import StatBoard from './collectionGrids/collections-list/StatBoard'; -// function SelectCollectionView({ onNewDialog, onCloseDialog, dialogState }) { -// const { theme } = useMode(); -// const { allCollections, selectedCollection } = useSelectedCollection(); -// const { currentForm } = useFormContext(); -// return ( -// -// -// -// -// - -// -// -// -// -// -// {dialogState.isDialogOpen && ( -// -// )} -// {dialogState.isSelectionErrorDialogOpen && ( -// -// )} -// -// -// ); -// } - const CollectionPortfolio = () => { const { theme } = useMode(); const { fetchCollections, hasFetchedCollections } = useCollectionManager(); const { handleBackToCollections, - // showCollections, selectedCollection, selectedCollectionId, allCollections, customError, toggleShowCollections, } = useSelectedCollection(); - // Initially fetch collections if needed useEffect(() => { fetchCollections(); }, []); const { currentForm } = useFormContext(); - const { - isCollectionVisible, - toggleCollectionVisibility, - // dialogStates, - // toggleDialog, - } = useVisibilityContext(); + const { isCollectionVisible, toggleCollectionVisibility } = + useVisibilityContext(); const { dialogState, openDialog, closeDialog } = useDialogState({ isAddCollectionDialogOpen: false, @@ -130,26 +74,6 @@ const CollectionPortfolio = () => { const handleCloseSelectionErrorDialog = useCallback(() => { closeDialog('isSelectionErrorDialogOpen'); }, [closeDialog]); - // const handleDialogToggle = () => - // setDialogState((prevState) => ({ - // ...prevState, - // isDialogOpen: !prevState.isDialogOpen, - // })); - // const handleCloseDialog = () => - // setDialogState((prevState) => ({ - // ...prevState, - // isDialogOpen: false, - // })); - // const handleErrorDialog = () => - // setDialogState((prevState) => ({ - // ...prevState, - // isSelectionErrorDialogOpen: true, - // })); - // const handleCloseErrorDialog = () => - // setDialogState((prevState) => ({ - // ...prevState, - // isSelectionErrorDialogOpen: false, - // })); useEffect(() => { if (customError === 'Selection Error') { handleSelectionErrorDialogToggle(); @@ -157,15 +81,6 @@ const CollectionPortfolio = () => { handleCloseSelectionErrorDialog(); } }, [customError]); - // const handleSelectedCollectionView = useCallback(() => { - // console.log('SWITCHING TO SELECTED COLLECTION VIEW', selectedCollectionId); - // setViewState((prevState) => ({ - // ...prevState, - // showListOfAllCollections: !prevState.showListOfAllCollections, - // showSelectedCollection: !prevState.showSelectedCollection, - // currentCollection: selectedCollectionId, - // })); - // }, [selectedCollectionId]); const handleDialogToggle = useCallback( (dialogName) => { dialogState[dialogName] @@ -174,22 +89,9 @@ const CollectionPortfolio = () => { }, [dialogState, openDialog, closeDialog] ); - // const handleViewChange = useCallback(() => { - // toggleShowCollections(); - // }, [toggleShowCollections]); useEffect(() => { console.log('VIEW STATE CHANGED', viewState); - // console.log('ALL COLLECTION', allCollections); - // console.log('SELECTED COLLECTION', selectedCollection); - // console.log('SELECTED COLLECTION ID', selectedCollectionId); - // console.log('IS COLLECTION VISIBLE', isCollectionVisible); - }, [ - viewState, - // allCollections, - // isCollectionVisible, - // selectedCollection, - // selectedCollectionId, - ]); + }, [viewState]); const { columns, data } = collectionPortfolioData(selectedCollection?.cards); return ( diff --git a/src/pages/HomePage.js b/src/pages/HomePage.js index c75dd71..44c8219 100644 --- a/src/pages/HomePage.js +++ b/src/pages/HomePage.js @@ -51,7 +51,7 @@ const HomePage = () => { return ( - {renderSplashPage()} + {/* {renderSplashPage()} */} {/* INTRO SECTION */} diff --git a/src/pages/sections/HeroSection.jsx b/src/pages/sections/HeroSection.jsx index e983398..db07bb2 100644 --- a/src/pages/sections/HeroSection.jsx +++ b/src/pages/sections/HeroSection.jsx @@ -3,14 +3,10 @@ import { useMode, useStatisticsStore } from '../../context'; import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; import placeHolder from '../../assets/images/placeholder.jpeg'; import { Swiper, SwiperSlide } from 'swiper/react'; - -// Import Swiper styles import 'swiper/css'; import 'swiper/css/effect-coverflow'; import 'swiper/css/pagination'; import 'swiper/css/navigation'; - -// Corrected imports for Swiper modules import { EffectCoverflow, Pagination, @@ -19,122 +15,122 @@ import { } from 'swiper/modules'; import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; import HeroSectionSkeleton from '../../layout/REUSABLE_COMPONENTS/SkeletonVariants'; -import { useMediaQuery } from '@mui/material'; - -// const -// return cards?.map((card, index) => ( -// -// {/* */} -// {`slide_${index}`} -// {/* */} -// -// )); -// }; +import { Box, Card, useMediaQuery } from '@mui/material'; const HeroSection = () => { const { theme } = useMode(); const { breakpoints } = theme; - const isLgUp = useMediaQuery(breakpoints.up('lg')); - const isLgDown = useMediaQuery(breakpoints.down('lg')); - const isMdUp = useMediaQuery(breakpoints.up('md')); - const isBetweenLgMd = isLgDown && isMdUp; - const isMdDown = useMediaQuery(breakpoints.down('md')); - const isSmUp = useMediaQuery(breakpoints.up('sm')); - const isBetweenSmMd = isMdDown && isSmUp; - - // const isXs = useMediaQuery(theme.breakpoints.down('sm')); + const isMobileView = useMediaQuery(breakpoints.down('sm')); + const isFullView = useMediaQuery(breakpoints.up('lg')); const [activeCardIndex, setActiveCardIndex] = useState(0); const { topFiveCards } = useStatisticsStore(); - // Create 30 default card objects - const defaultCards = new Array(30).fill({}).map((_, index) => ({ + const defaultCards = new Array(45).fill({}).map((_, index) => ({ id: `default-${index}`, name: `Placeholder ${index + 1}`, description: `Description for Placeholder ${index + 1}`, - image: placeHolder, // Use the placeholder image for all default cards + image: placeHolder, })); const cards = [...topFiveCards, ...defaultCards]; - const handleSlideChange = (swiper) => { - setActiveCardIndex(swiper.realIndex); - }; - - // if screen is largest then show 7 slides, else show 5 slides, else show 3 slides, else show 1 slide - const slidesPerView = isLgUp ? 7 : isBetweenLgMd ? 5 : isBetweenSmMd ? 3 : 1; + const handleSlideChange = (swiper) => setActiveCardIndex(swiper.realIndex); if (!cards || !Array.isArray(cards) || !cards[activeCardIndex]) { return ; } return ( -
+
- {/* Ensure there's always a string value, even if it's empty */} - - {topFiveCards[activeCardIndex]?.name || ''} - - - {/* Same for the description */} - - {topFiveCards[activeCardIndex]?.description || ''} - + + {/* Content inside the card */} + + + + { delay: 2500, // Delay in milliseconds (2.5 seconds) disableOnInteraction: false, // Continues autoplay when interacted with }} + style={{ + minWidth: '150vw', + width: '100%', + // marginLeft: '60vw', + // position: 'absolute', // Position absolute to control its exact location + position: isMobileView ? 'relative' : 'absolute', + marginLeft: isMobileView ? '0' : '60vw', + }} modules={[EffectCoverflow, Pagination, Navigation, Autoplay]} // Include Autoplay module className="swiper_container" onSlideChange={handleSlideChange} > - {cards.map((card, index) => ( - + {cards?.map((card, index) => ( + + + {topFiveCards[activeCardIndex]?.name || ''} + + + {topFiveCards[activeCardIndex]?.description || ''} + {`slide_${index}`} { maxWidth: '100%', maxHeight: '100%', objectFit: 'contain', + transition: 'transform 0.9s', // Smooth transition for the image scaling }} /> diff --git a/src/pages/sections/MainContentSection.jsx b/src/pages/sections/MainContentSection.jsx index 632bb98..eec73e8 100644 --- a/src/pages/sections/MainContentSection.jsx +++ b/src/pages/sections/MainContentSection.jsx @@ -32,10 +32,12 @@ import placeHolder from '../../assets/images/placeholder.jpeg'; import { DEFAULT_COLLECTION } from '../../context/constants'; import useCollectionManager from '../../context/MAIN_CONTEXT/CollectionContext/useCollectionManager'; import useSelectedCollection from '../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; +import SimpleButton from '../../layout/REUSABLE_COMPONENTS/unique/SimpleButton'; +import uniqueTheme from '../../layout/REUSABLE_COMPONENTS/unique/uniqueTheme'; const MainContentSection = () => { const { theme } = useMode(); - const { authUser } = useAuthContext(); + const { isLoggedIn } = useAuthContext(); const { user } = useUserContext(); const { hasFetchedCollections } = useCollectionManager(); const { allCollections, selectedCollection } = useSelectedCollection(); @@ -83,7 +85,7 @@ const MainContentSection = () => { - {authUser && ( + {isLoggedIn && ( { - { + console.log('clicked'); + }} + > + Manage Collections + + {/* { }} > Manage Collections - + */} View Purchase History From 41513cdc0bb806e0050e43541a92b88be10f7d29 Mon Sep 17 00:00:00 2001 From: Reed Vogt Date: Sat, 16 Mar 2024 18:28:12 -0700 Subject: [PATCH 03/10] tried various swiper styles and worked on my styled component library --- src/Main.jsx | 47 +- src/assets/css/index.css | 22 +- src/assets/themes/base/colors.jsx | 3 + .../actionButtons/GenericActionButtons.jsx | 11 +- src/components/buttons/other/AuthSwitch.jsx | 128 ---- src/components/buttons/other/CustomButton.jsx | 43 -- .../buttons/other/OrderSubmitButton.js | 25 - .../buttons/other/ReusableLoadingButton.jsx | 170 ++++-- src/components/buttons/other/SearchButton.js | 32 - src/components/buttons/other/SignupSwitch.jsx | 36 -- .../buttons/other/ThemeToggleButton.jsx | 49 -- src/components/cards/AnimatedFeatureCard.jsx | 9 +- src/components/cards/CardCarousel.jsx | 82 +-- src/components/cards/GenericCard.jsx | 79 +-- src/components/dialogs/CollectionDialog.jsx | 3 +- src/components/dialogs/DeckEditPanel.js | 251 +++----- src/components/dialogs/LoginDialog.jsx | 36 +- .../dialogs/SelectionErrorDialog.jsx | 73 +-- .../dialogs/cardDialog/GenericCardDialog.jsx | 2 - src/components/forms/AddCollectionForm.jsx | 104 +--- src/components/forms/AddDeckForm.jsx | 151 +++-- src/components/forms/LoginForm.jsx | 177 +----- src/components/forms/SearchForm.jsx | 111 +--- src/components/forms/SignupForm.jsx | 322 +++++----- src/components/forms/UpdateCollectionForm.jsx | 141 ++--- src/components/forms/UpdateDeckForm.jsx | 224 ++++--- .../other => forms/cleanup}/CronTrigger.jsx | 0 .../forms/cleanup/ThemeToggleButton.jsx | 49 ++ .../forms/hooks/useSubmitHandler.jsx | 29 +- src/components/forms/reusable/RCSwitch.jsx | 98 +++ src/components/forms/reusable/RCZodForm.jsx | 309 ++++++++++ .../forms/search/SearchComponent.jsx | 35 +- src/components/forms/search/SearchResults.jsx | 2 +- .../forms/selectors/TimeRangeSelector.jsx | 5 +- .../forms/selectors/useTimeRange.jsx | 27 +- .../grids/deckBuilderGrids/CardsGrid.js | 84 --- .../grids/deckBuilderGrids/SelectDeckList.jsx | 2 +- .../MAIN_CONTEXT/AuthContext/authContext.js | 37 +- .../useCollectionManager.jsx | 567 ------------------ .../AppContext/AppContextProvider.jsx | 38 +- .../FormContext/FormContext.jsx | 30 +- .../UTILITIES_CONTEXT/FormContext/schemas.jsx | 26 +- .../PageContext/PageContext.jsx | 88 +-- .../SideBarContext/SideBarProvider.jsx | 2 +- .../SnackbarContext/SnackbarContext.jsx | 49 -- .../UTILITIES_CONTEXT/VisibilityContext.jsx | 2 +- src/context/hooks/index.jsx | 2 +- .../hooks/style-hooks/useResponsiveStyles.jsx | 6 +- src/context/hooks/useCardActions.jsx | 18 - src/context/hooks/useCustomSnackbar.jsx | 52 +- src/context/hooks/useFetchWrapper.jsx | 86 +-- src/context/hooks/useLocalStorage.jsx | 15 +- src/context/hooks/usePagination.jsx | 99 +-- src/context/hooks/useSnackBar.jsx | 79 --- src/context/hooks/useSnackbarManager.jsx | 59 ++ src/data/baseMenuItems.jsx | 65 ++ .../data/collectionPortfolioData.jsx | 0 src/{layout/store => }/data/searchData.jsx | 2 +- .../indicators => layout}/ErrorIndicator.js | 2 +- .../indicators => layout}/LoadingIndicator.js | 0 .../reusable => layout}/PrivateRoute.jsx | 2 +- .../REUSABLE_COMPONENTS/CustomSnackbar.jsx | 31 - .../HOC/DynamicSnackbar.jsx | 278 --------- .../HOC/withDynamicSnackbar.jsx | 76 --- .../REUSABLE_COMPONENTS}/NotFoundPage.js | 0 .../REUSABLE_COMPONENTS/RCICON/RCIcon.jsx | 48 ++ .../RCLOGOSECTION/RCLogoSection.jsx | 186 ++++++ .../RCTOOLTIP/RCToolTip.jsx | 74 +++ .../REUSABLE_COMPONENTS}/icons/CartIcon.jsx | 0 .../REUSABLE_COMPONENTS}/icons/ChartsIcon.jsx | 0 .../icons/CollectionIcon.jsx | 0 .../icons/DeckBuilderIcon.jsx | 0 .../icons/DeckOfCardsIcon.jsx | 0 .../REUSABLE_COMPONENTS}/icons/GlassyIcon.jsx | 0 .../REUSABLE_COMPONENTS}/icons/MoneyIcon.jsx | 0 .../icons/ReusableIconButton.jsx | 0 .../icons/TestingIcon.jsx | 0 .../REUSABLE_COMPONENTS}/icons/index.jsx | 0 .../REUSABLE_COMPONENTS/unique/SimpleCard.jsx | 33 +- .../unique/SimpleSectionHeader.jsx | 41 +- .../collectionGrids/ChartGridLayout.jsx | 122 +++- .../cards-chart/ChartConfigs.jsx | 3 + .../cards-chart/UpdaterAndStatisticsRow.jsx | 6 +- .../DataTableBodyComponent.jsx | 0 .../cards-datatable/DataTableHeadCell.jsx | 258 +++++--- .../DataTableHeadComponent.jsx | 54 -- .../cards-datatable/OptionsComponent.jsx | 161 +++-- .../collectionGrids/cards-datatable/index.jsx | 46 +- .../collections-list/CollectionListItem.jsx | 263 ++++---- .../SelectCollectionHeader.jsx | 5 - .../collections-list/SelectCollectionList.jsx | 142 ++++- .../statItems/PricedCardList.jsx | 109 +--- .../statItems/TotalPriceStatBox.jsx | 53 +- src/layout/collection/index.jsx | 225 +------ .../CollectionPortfolioHeader.jsx | 27 +- .../sub-components/TopCardsDisplayRow.jsx | 106 +++- src/layout/navigation/LogoSection.js | 50 -- src/layout/navigation/LongMenu.jsx | 2 - src/layout/navigation/MenuCard.jsx | 2 +- src/layout/navigation/MenuItemComponent.jsx | 19 - src/layout/navigation/Navigation.jsx | 101 ++-- src/layout/navigation/menuItemsData.jsx | 2 +- src/layout/store/StoreSearch.jsx | 1 + src/pages/HomePage.js | 4 +- src/pages/ProfilePage.js | 92 --- src/pages/index.js | 2 +- src/pages/pageStyles/StyledComponents.jsx | 2 +- src/pages/sections/HeroSection.jsx | 159 +++-- src/save/AuthSwitch.jsx | 128 ++++ .../CollectionGoalsTimeLine.jsx | 0 .../CollectionListStats.jsx | 10 +- .../ComplexStatisticsCard.jsx | 6 +- .../reusable => save}/CustomPagination.jsx | 2 +- src/{pages => save}/LoginPage.jsx | 0 .../sub-components => save}/PieChartStats.jsx | 0 src/{layout/navigation => save}/SideBar.jsx | 8 +- .../StatisticsCardsGrid.jsx | 8 +- .../StatisticsDisplaySection.jsx | 4 +- src/{layout/navigation => save}/TopBar.jsx | 8 +- .../TopFiveExpensiveCards.jsx | 0 .../TotalValueOfCollectionsDisplay.jsx | 0 .../forms => zcleanup}/CustomSelector.js | 0 .../Notifications.jsx | 14 - 123 files changed, 3120 insertions(+), 4148 deletions(-) delete mode 100644 src/components/buttons/other/AuthSwitch.jsx delete mode 100644 src/components/buttons/other/CustomButton.jsx delete mode 100644 src/components/buttons/other/OrderSubmitButton.js delete mode 100644 src/components/buttons/other/SearchButton.js delete mode 100644 src/components/buttons/other/SignupSwitch.jsx delete mode 100644 src/components/buttons/other/ThemeToggleButton.jsx rename src/components/{buttons/other => forms/cleanup}/CronTrigger.jsx (100%) create mode 100644 src/components/forms/cleanup/ThemeToggleButton.jsx create mode 100644 src/components/forms/reusable/RCSwitch.jsx create mode 100644 src/components/forms/reusable/RCZodForm.jsx delete mode 100644 src/context/UTILITIES_CONTEXT/SnackbarContext/SnackbarContext.jsx delete mode 100644 src/context/hooks/useSnackBar.jsx create mode 100644 src/context/hooks/useSnackbarManager.jsx create mode 100644 src/data/baseMenuItems.jsx rename src/{layout/store => }/data/collectionPortfolioData.jsx (100%) rename src/{layout/store => }/data/searchData.jsx (94%) rename src/{components/reusable/indicators => layout}/ErrorIndicator.js (97%) rename src/{components/reusable/indicators => layout}/LoadingIndicator.js (100%) rename src/{components/reusable => layout}/PrivateRoute.jsx (90%) delete mode 100644 src/layout/REUSABLE_COMPONENTS/CustomSnackbar.jsx delete mode 100644 src/layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar.jsx delete mode 100644 src/layout/REUSABLE_COMPONENTS/HOC/withDynamicSnackbar.jsx rename src/{pages => layout/REUSABLE_COMPONENTS}/NotFoundPage.js (100%) create mode 100644 src/layout/REUSABLE_COMPONENTS/RCICON/RCIcon.jsx create mode 100644 src/layout/REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection.jsx create mode 100644 src/layout/REUSABLE_COMPONENTS/RCTOOLTIP/RCToolTip.jsx rename src/{components/reusable => layout/REUSABLE_COMPONENTS}/icons/CartIcon.jsx (100%) rename src/{components/reusable => layout/REUSABLE_COMPONENTS}/icons/ChartsIcon.jsx (100%) rename src/{components/reusable => layout/REUSABLE_COMPONENTS}/icons/CollectionIcon.jsx (100%) rename src/{components/reusable => layout/REUSABLE_COMPONENTS}/icons/DeckBuilderIcon.jsx (100%) rename src/{components/reusable => layout/REUSABLE_COMPONENTS}/icons/DeckOfCardsIcon.jsx (100%) rename src/{components/reusable => layout/REUSABLE_COMPONENTS}/icons/GlassyIcon.jsx (100%) rename src/{components/reusable => layout/REUSABLE_COMPONENTS}/icons/MoneyIcon.jsx (100%) rename src/{components/reusable => layout/REUSABLE_COMPONENTS}/icons/ReusableIconButton.jsx (100%) rename src/{components/reusable => layout/REUSABLE_COMPONENTS}/icons/TestingIcon.jsx (100%) rename src/{components/reusable => layout/REUSABLE_COMPONENTS}/icons/index.jsx (100%) delete mode 100644 src/layout/collection/collectionGrids/cards-datatable/DataTableBodyComponent.jsx delete mode 100644 src/layout/collection/collectionGrids/cards-datatable/DataTableHeadComponent.jsx delete mode 100644 src/layout/navigation/LogoSection.js create mode 100644 src/save/AuthSwitch.jsx rename src/{layout/collection/sub-components => save}/CollectionGoalsTimeLine.jsx (100%) rename src/{layout/collection/collectionGrids => save}/CollectionListStats.jsx (76%) rename src/{layout/collection/sub-components => save}/ComplexStatisticsCard.jsx (95%) rename src/{components/reusable => save}/CustomPagination.jsx (93%) rename src/{pages => save}/LoginPage.jsx (100%) rename src/{layout/collection/sub-components => save}/PieChartStats.jsx (100%) rename src/{layout/navigation => save}/SideBar.jsx (93%) rename src/{layout/collection/collectionGrids => save}/StatisticsCardsGrid.jsx (85%) rename src/{layout/collection/sub-components => save}/StatisticsDisplaySection.jsx (97%) rename src/{layout/navigation => save}/TopBar.jsx (92%) rename src/{layout/collection/sub-components => save}/TopFiveExpensiveCards.jsx (100%) rename src/{layout/collection/sub-components => save}/TotalValueOfCollectionsDisplay.jsx (100%) rename src/{components/forms => zcleanup}/CustomSelector.js (100%) rename src/{layout/collection/sub-components => zcleanup}/Notifications.jsx (93%) diff --git a/src/Main.jsx b/src/Main.jsx index 9c15ff8..251f8d8 100644 --- a/src/Main.jsx +++ b/src/Main.jsx @@ -1,13 +1,14 @@ import React, { Suspense, lazy } from 'react'; import { Route, Routes } from 'react-router-dom'; import { useMediaQuery } from '@mui/material'; -import PrivateRoute from './components/reusable/PrivateRoute'; +import PrivateRoute from './layout/PrivateRoute.jsx'; import LoginDialog from './components/dialogs/LoginDialog'; import { useAuthContext, useConfiguratorContext, useMode } from './context'; import PageLayout from './layout/Containers/PageLayout.jsx'; import Navigation from './layout/navigation/Navigation.jsx'; -import LoadingIndicator from './components/reusable/indicators/LoadingIndicator.js'; +import LoadingIndicator from './layout/LoadingIndicator.js'; import Configurator from './layout/REUSABLE_COMPONENTS/Configurator/index.jsx'; +import { CSSTransition, TransitionGroup } from 'react-transition-group'; const ROUTE_CONFIG = [ { path: '/', componentName: 'HomePage', isPrivate: false }, @@ -47,25 +48,31 @@ const Main = () => { > {isConfiguratorOpen && } - }> - - {ROUTE_CONFIG.map(({ path, componentName, isPrivate }, index) => ( - - - - ) : ( - + + + }> + + {ROUTE_CONFIG.map( + ({ path, componentName, isPrivate }, index) => ( + + + + ) : ( + + ) + } + /> ) - } - /> - ))} - - + )} + + + + )} diff --git a/src/assets/css/index.css b/src/assets/css/index.css index 25a37ea..0cc0984 100644 --- a/src/assets/css/index.css +++ b/src/assets/css/index.css @@ -23,6 +23,24 @@ html { scroll-behavior: smooth; } +.fade-enter { + opacity: 0; +} + +.fade-enter-active { + opacity: 1; + transition: opacity 300ms ease-in; +} + +.fade-exit { + opacity: 1; +} + +.fade-exit-active { + opacity: 0; + transition: opacity 300ms ease-in; +} + /* @media (min-width: 1440px) { html { zoom: 1.5; @@ -242,8 +260,8 @@ button { /* .swiper-wrapper { display: flex; /* Ensure the slides are in a row */ - /* transition: transform 0.3s; /* Smooth transition */ - /* align-items: center; +/* transition: transform 0.3s; /* Smooth transition */ +/* align-items: center; justify-content: center; } */ diff --git a/src/assets/themes/base/colors.jsx b/src/assets/themes/base/colors.jsx index bbeecae..3bd79c6 100644 --- a/src/assets/themes/base/colors.jsx +++ b/src/assets/themes/base/colors.jsx @@ -174,6 +174,9 @@ const colors = { error: { main: '#EF5350', state: '#E53935', + dark: '#C62828', + darker: '#D32F2F', + evenDarker: '#DC143C', }, light: { diff --git a/src/components/buttons/actionButtons/GenericActionButtons.jsx b/src/components/buttons/actionButtons/GenericActionButtons.jsx index aad8ca1..fe5e2e9 100644 --- a/src/components/buttons/actionButtons/GenericActionButtons.jsx +++ b/src/components/buttons/actionButtons/GenericActionButtons.jsx @@ -5,20 +5,15 @@ import AddButton from '../../../zcleanup/AddButton'; import RemoveButton from '../../../zcleanup/RemoveButton'; import { useModalContext } from '../../../context/UTILITIES_CONTEXT/ModalContext/ModalContext'; import useSelectedContext from '../../../context/hooks/useSelectedContext'; -import { getContextIcon } from '../../../components/reusable/icons/index'; -// import { -// useCollectionManager, -// useSelectedCollection, -// } from '../../../context/MAIN_CONTEXT/CollectionContext'; +import { getContextIcon } from '../../../layout/REUSABLE_COMPONENTS/icons/index'; + import { useDeckStore } from '../../../context/MAIN_CONTEXT/DeckContext/DeckContext'; import { useCartStore } from '../../../context/MAIN_CONTEXT/CartContext/CartContext'; -import { DEFAULT_COLLECTION } from '../../../context/constants'; -import { useCardActions } from '../../../context/hooks/useCardActions'; import useCollectionManager from '../../../context/MAIN_CONTEXT/CollectionContext/useCollectionManager'; import useSelectedCollection from '../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; import ActionButton from './ActionButton'; import { useSnackbar } from 'notistack'; -import GlassyIcon from '../../../components/reusable/icons/GlassyIcon'; +import GlassyIcon from '../../../layout/REUSABLE_COMPONENTS/icons/GlassyIcon'; import MDBox from '../../../layout/REUSABLE_COMPONENTS/MDBOX'; // Utility function for mapping cardSize to buttonSize diff --git a/src/components/buttons/other/AuthSwitch.jsx b/src/components/buttons/other/AuthSwitch.jsx deleted file mode 100644 index 6f76bf7..0000000 --- a/src/components/buttons/other/AuthSwitch.jsx +++ /dev/null @@ -1,128 +0,0 @@ -import React from 'react'; -import { renderToStaticMarkup } from 'react-dom/server'; - -import { Switch, FormControlLabel, FormControl, alpha } from '@mui/material'; -import { useFormContext, useMode } from '../../../context'; // Adjust with actual path -import { AuthModeSwitch } from '../../../layout/REUSABLE_STYLED_COMPONENTS/SpecificStyledComponents'; -import LoginIcon from '@mui/icons-material/Login'; -import PersonAddIcon from '@mui/icons-material/PersonAdd'; -import styled from 'styled-components'; -import { useCookies } from 'react-cookie'; -const convertSvg = (svg) => { - const markup = renderToStaticMarkup(svg); - const encoded = encodeURIComponent(markup); - const dataUri = `url('data:image/svg+xml;utf8,${encoded}')`; - return dataUri; -}; -const AuthSwitch = () => { - // const AuthSwitch = ({ signupMode, formLabel }) => { - const { theme } = useMode(); // Ensures theme is applied correctly - // const colors = theme; - const colors = theme.palette.chartTheme; - const cookies = useCookies('colorMode'); - const mode = cookies.colorMode; - - const primary = colors.primary.default; - const blue = colors.blueAccent.default; - const green = colors.greenAccent.light; - const lihhtgreen = colors.greenAccent.default; - const greenliht = colors.greenAccent.light; - const lightgrey = colors.grey.light; - const darkgrey = colors.grey.dark; - const darkestgrey = colors.grey.darkest; - - const { currentSchemaKey, toggleForm } = useFormContext(); // Use toggleForm for toggling modes - const signupMode = currentSchemaKey === 'signupForm'; - const handleToggle = () => { - toggleForm(currentSchemaKey === 'loginForm' ? 'signupForm' : 'loginForm'); - }; - const switchBaseStyles = { - '& .MuiSwitch-switchBase': { - padding: 1, // Center the switch base padding for proper alignment - '&.Mui-checked': { - transform: 'translateX(16px)', // Ensure this aligns with your switch size - color: theme.palette.common.white, // Thumb color when checked - '& + .MuiSwitch-track': { - backgroundColor: theme.palette.primary.main, // Track color when checked - }, - }, - }, - }; - const thumbStyles = { - '& .MuiSwitch-thumb': { - width: 22, // Adjust thumb size for better visual alignment - height: 22, // Adjust thumb size for better visual alignment - backgroundColor: mode === 'dark' ? green : lihhtgreen, - // backgroundColor: theme.palette.common.white, // Default thumb color - - '&:before': { - content: '" "', - display: 'block', - backgroundImage: signupMode - ? convertSvg() - : convertSvg(), - width: '100%', - height: '100%', - backgroundSize: '50%', - backgroundPosition: 'center', - backgroundRepeat: 'no-repeat', - }, - // '&:after': { - // right: 12, // Adjust the right icon position - // backgroundImage: convertSvg(), - // }, - }, - }; - const trackStyles = { - '& .MuiSwitch-track': { - backgroundColor: theme.palette.chartTheme.grey.light, // Default track color - opacity: 1, - width: 50, // Adjust thumb size for better visual alignment - height: 14, // Adjust thumb size for better visual alignment - // '&:before, &:after': { - // content: '""', - // position: 'absolute', - // top: '50%', - // transform: 'translateY(-50%)', - // }, - // '&:before': { - // left: 12, // Adjust the left icon position - // backgroundImage: convertSvg(), - // }, - // '&:after': { - // right: 12, // Adjust the right icon position - // backgroundImage: convertSvg(), - // }, - }, - }; - const switchStyles = { - ...switchBaseStyles, - ...thumbStyles, - ...trackStyles, - // backgroundImage: convertSvg(), - // right: 2, - }; - - return ( - - - } - label={signupMode ? 'Sign Up' : 'Log In'} - style={{ margin: 'auto', justifyContent: 'center' }} // Center label and switch - /> - - ); -}; - -export default AuthSwitch; diff --git a/src/components/buttons/other/CustomButton.jsx b/src/components/buttons/other/CustomButton.jsx deleted file mode 100644 index 272b23a..0000000 --- a/src/components/buttons/other/CustomButton.jsx +++ /dev/null @@ -1,43 +0,0 @@ -// import React from 'react'; -// import { Button } from '@mui/material'; -// import { useMode } from '../../../context'; // Adjust the import path based on your project structure -// import MDButton from '../../../layout/REUSABLE_COMPONENTS/MDBUTTON'; - -// const CustomButton = ({ -// text, -// onClick, -// variant = 'contained', -// size = 'large', -// sx = {}, -// }) => { -// const { theme } = useMode(); - -// const defaultStyles = { -// background: theme.palette.backgroundE.darker, -// borderColor: theme.palette.backgroundB.darkest, -// borderWidth: 2, -// mx: 1, -// width: '70%', -// '&:hover': { -// fontWeight: 'bold', -// background: theme.palette.backgroundF.dark, -// borderColor: theme.palette.backgroundB.darkest, -// border: `1px solid ${theme.palette.backgroundB.darkest}`, -// }, -// ...sx, // Allow custom styles to override defaults -// }; - -// return ( -// -// {text} -// -// ); -// }; - -// export default CustomButton; diff --git a/src/components/buttons/other/OrderSubmitButton.js b/src/components/buttons/other/OrderSubmitButton.js deleted file mode 100644 index e990dfd..0000000 --- a/src/components/buttons/other/OrderSubmitButton.js +++ /dev/null @@ -1,25 +0,0 @@ -// import React from 'react'; -// import { Button } from '@mui/material'; -// import { useMode } from '../../../context'; - -// const OrderSubmitButton = ({ onClick }) => { -// const { theme } = useMode(); -// return ( -// -// ); -// }; - -// export default OrderSubmitButton; diff --git a/src/components/buttons/other/ReusableLoadingButton.jsx b/src/components/buttons/other/ReusableLoadingButton.jsx index 1f2b66e..45dc0e8 100644 --- a/src/components/buttons/other/ReusableLoadingButton.jsx +++ b/src/components/buttons/other/ReusableLoadingButton.jsx @@ -1,35 +1,79 @@ -// ReusableLoadingButton.js +// // ReusableLoadingButton.js +// import React from 'react'; +// import { LoadingButton } from '@mui/lab'; +// import LoginIcon from '@mui/icons-material/Login'; +// import { useMode } from '../../../context'; +// import AdjustSharpIcon from '@mui/icons-material/AdjustSharp'; +// const baseButtonStyles = { +// bgcolor: '#6a59ff', +// borderColor: '#6a59ff', +// borderWidth: 2, +// borderStyle: 'solid', +// display: 'flex', +// flexGrow: 1, +// alignItems: 'center', +// justifyContent: 'center', +// marginLeft: 'auto', +// marginRight: 'auto', +// marginBottom: '16px', +// marginTop: '16px', +// position: 'relative', +// bottom: 0, +// cursor: 'pointer', +// transition: 'background-color 0.3s, border-color 0.3s, color 0.3s', +// ':hover': { +// fontWeight: 'bold', +// bgcolor: '#4a6da7', +// borderColor: '#34597f', +// }, +// ':focus': { +// outline: '2px solid #62a4ff', +// outlineOffset: 2, +// }, +// }; + +// const ReusableLoadingButton = ({ +// loading, +// label, +// icon, +// onClick, +// style, +// fullWidth, +// sx, +// variant, +// }) => { +// const { theme } = useMode(); +// return ( +// } +// fullWidth={fullWidth} +// // sx={sx} +// onClick={onClick} +// sx={{ +// ...sx, +// mt: 2, // Adjust spacing as needed +// background: theme.palette.backgroundG.light, +// borderColor: theme.palette.backgroundG.light, +// borderWidth: 2, +// '&:hover': { background: theme.palette.backgroundG.default }, +// '&:focus': { background: theme.palette.backgroundG.default }, +// }} +// > +// {label} +// +// ); +// }; + +// export default ReusableLoadingButton; import React from 'react'; import { LoadingButton } from '@mui/lab'; -import LoginIcon from '@mui/icons-material/Login'; - -const baseButtonStyles = { - bgcolor: '#6a59ff', - borderColor: '#6a59ff', - borderWidth: 2, - borderStyle: 'solid', - display: 'flex', - flexGrow: 1, - alignItems: 'center', - justifyContent: 'center', - marginLeft: 'auto', - marginRight: 'auto', - marginBottom: '16px', - marginTop: '16px', - position: 'relative', - bottom: 0, - cursor: 'pointer', - transition: 'background-color 0.3s, border-color 0.3s, color 0.3s', - ':hover': { - fontWeight: 'bold', - bgcolor: '#4a6da7', - borderColor: '#34597f', - }, - ':focus': { - outline: '2px solid #62a4ff', - outlineOffset: 2, - }, -}; +import AdjustSharpIcon from '@mui/icons-material/AdjustSharp'; +import { useMode } from '../../../context'; const ReusableLoadingButton = ({ loading, @@ -39,20 +83,56 @@ const ReusableLoadingButton = ({ style, fullWidth, sx, -}) => ( - } - fullWidth={fullWidth} - sx={sx} - onClick={onClick} - > - {label} - -); + variant, +}) => { + const { theme } = useMode(); + + const getButtonStyles = (variant) => { + if (variant === 'warning') { + return { + bgcolor: theme.palette.error.state, + borderColor: theme.palette.error.dark, + borderWidth: 2, + '&:hover': { + fontWeight: 'bold', + bgcolor: theme.palette.error.main, + borderColor: theme.palette.error.dark, + }, + '&:focus': { + outline: `2px solid ${theme.palette.error.dark}`, + outlineOffset: 2, + }, + }; + } + // Default styles or other variants can be managed here + return { + background: theme.palette.backgroundG.light, + borderColor: theme.palette.backgroundG.light, + borderWidth: 2, + '&:hover': { background: theme.palette.backgroundG.default }, + '&:focus': { background: theme.palette.backgroundG.default }, + }; + }; + + return ( + } + fullWidth={fullWidth} + onClick={onClick} + sx={{ + ...sx, + mt: 2, // Adjust spacing as needed + ...getButtonStyles(variant), + }} + > + {label} + + ); +}; export default ReusableLoadingButton; diff --git a/src/components/buttons/other/SearchButton.js b/src/components/buttons/other/SearchButton.js deleted file mode 100644 index fcd05ae..0000000 --- a/src/components/buttons/other/SearchButton.js +++ /dev/null @@ -1,32 +0,0 @@ -// import React from 'react'; -// import { Button, Grid } from '@mui/material'; -// import { useMode } from '../../../context'; - -// const SearchButton = ({ searchParams, handleSubmit }) => { -// // const { handleRequest } = useCardStore(); -// const { theme } = useMode(); - -// return ( -// -// -// -// ); -// }; - -// export default SearchButton; diff --git a/src/components/buttons/other/SignupSwitch.jsx b/src/components/buttons/other/SignupSwitch.jsx deleted file mode 100644 index e186d06..0000000 --- a/src/components/buttons/other/SignupSwitch.jsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import { Switch, FormControlLabel, FormControl } from '@mui/material'; -import { useFormContext, useMode } from '../../../context'; // Adjust with actual path -const SignupSwitch = ({ signupMode, toggleAuthMode, formLabel }) => { - const { theme } = useMode(); // Ensures theme is applied correctly - - return ( - - - } - label={formLabel} - style={{ - margin: theme.spacing(1), // Provide some spacing - justifyContent: 'space-between', // Align items nicely - }} - /> - - ); -}; - -export default SignupSwitch; diff --git a/src/components/buttons/other/ThemeToggleButton.jsx b/src/components/buttons/other/ThemeToggleButton.jsx deleted file mode 100644 index 1576bdd..0000000 --- a/src/components/buttons/other/ThemeToggleButton.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import React, { useContext, useState } from 'react'; -import { IconButton, Menu, MenuItem } from '@mui/material'; -import Brightness4Icon from '@mui/icons-material/Brightness4'; -import Brightness7Icon from '@mui/icons-material/Brightness7'; -import { ColorModeContext } from '../../../context/UTILITIES_CONTEXT/ColorModeContext/ColorModeProvider'; - -const ThemeToggleButton = () => { - const [anchorEl, setAnchorEl] = useState(null); - const { toggleColorMode, setMode } = useContext(ColorModeContext); - - const handleClick = (event) => { - setAnchorEl(event.currentTarget); - }; - - const handleClose = () => { - setAnchorEl(null); - }; - - const handleThemeChange = (mode) => { - toggleColorMode(mode); // Updated this line - console.log('mode', mode); - handleClose(); - }; - - return ( -
- - - - - handleThemeChange('dark')}> - - Dark Mode - - handleThemeChange('light')}> - - Light Mode - - -
- ); -}; - -export default ThemeToggleButton; diff --git a/src/components/cards/AnimatedFeatureCard.jsx b/src/components/cards/AnimatedFeatureCard.jsx index 9547dd1..4f8e54b 100644 --- a/src/components/cards/AnimatedFeatureCard.jsx +++ b/src/components/cards/AnimatedFeatureCard.jsx @@ -55,7 +55,10 @@ export const AnimatedFeatureCard = ({ tier, onOpenModal }) => { subheader={tier.subheader} titleTypographyProps={{ align: 'center' }} subheaderTypographyProps={{ align: 'center' }} - sx={{ backgroundColor: theme.palette.backgroundA.dark }} + sx={{ + backgroundColor: theme.palette.backgroundA.dark, + height: '20%', + }} /> @@ -83,9 +86,7 @@ export const AnimatedFeatureCard = ({ tier, onOpenModal }) => { // isDisabled={false} // isDefault={false} theme={uniqueTheme} - onClick={() => { - console.log('clicked'); - }} + onClick={() => onOpenModal(tier.title)} sx={{ flexGrow: 1, justifySelf: 'bottom', diff --git a/src/components/cards/CardCarousel.jsx b/src/components/cards/CardCarousel.jsx index 2e9c6fa..c374f16 100644 --- a/src/components/cards/CardCarousel.jsx +++ b/src/components/cards/CardCarousel.jsx @@ -1,44 +1,44 @@ -import React from 'react'; -import styled from 'styled-components'; -import { Swiper, SwiperSlide } from 'swiper/react'; -import { EffectCoverflow, Pagination } from 'swiper'; -import 'swiper/css'; -import 'swiper/css/effect-coverflow'; -import 'swiper/css/pagination'; -import GenericCard from './GenericCard'; -import { - StyledCarousel, - StyledSwiperSlide, -} from '../../pages/pageStyles/StyledComponents'; +// import React from 'react'; +// import styled from 'styled-components'; +// import { Swiper, SwiperSlide } from 'swiper/react'; +// import { EffectCoverflow, Pagination } from 'swiper'; +// import 'swiper/css'; +// import 'swiper/css/effect-coverflow'; +// import 'swiper/css/pagination'; +// import GenericCard from './GenericCard'; +// import { +// StyledCarousel, +// StyledSwiperSlide, +// } from '../../pages/pageStyles/StyledComponents'; -const CardCarousel = ({ cards, context }) => { - const swiperSettings = { - effect: 'coverflow', - grabCursor: true, - centeredSlides: true, - slidesPerView: 'auto', - coverflowEffect: { - rotate: 50, - stretch: 0, - depth: 200, - modifier: 1, - slideShadows: true, - }, - loop: true, - pagination: { clickable: true }, - }; +// const CardCarousel = ({ cards, context }) => { +// const swiperSettings = { +// effect: 'coverflow', +// grabCursor: true, +// centeredSlides: true, +// slidesPerView: 'auto', +// coverflowEffect: { +// rotate: 50, +// stretch: 0, +// depth: 200, +// modifier: 1, +// slideShadows: true, +// }, +// loop: true, +// pagination: { clickable: true }, +// }; - return ( - - - {cards.map((card, index) => ( - - - - ))} - - - ); -}; +// return ( +// +// +// {cards.map((card, index) => ( +// +// +// +// ))} +// +// +// ); +// }; -export default CardCarousel; +// export default CardCarousel; diff --git a/src/components/cards/GenericCard.jsx b/src/components/cards/GenericCard.jsx index 6f9be82..3f1dcc6 100644 --- a/src/components/cards/GenericCard.jsx +++ b/src/components/cards/GenericCard.jsx @@ -30,7 +30,7 @@ import { enqueueSnackbar } from 'notistack'; import useSelectedContext from '../../context/hooks/useSelectedContext'; import useSelectedCollection from '../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; const GenericCard = React.forwardRef((props, ref) => { - const { card, context, page } = props; + const { card, context, page, isSwiperStyles } = props; const { theme } = useMode(); const cardRef = useRef(null); const [cardSize, setCardSize] = useState('md'); // Default to 'sm' @@ -57,19 +57,6 @@ const GenericCard = React.forwardRef((props, ref) => { const { selectedDeck, allDecks } = useDeckStore(); const { setContext, setIsContextSelected } = useSelectedContext(); const { isCardInContext } = useAppContext(); - - // const { isCardInContext } = useAppContext(); - // const isCardInContext = useCallback( - // (selectedCollection, selectedDeck, cartData, context, card) => { - // const cardsList = { - // Collection: selectedCollection?.cards, - // Deck: selectedDeck?.cards, - // Cart: cartData?.cart, - // }; - // return !!cardsList[context]?.find((c) => c?.id === card?.id); - // }, - // [context, selectedCollection, selectedDeck, cartData] - // ); const { openModalWithCard, setModalOpen, setClickedCard, isModalOpen } = useModalContext(); const { setHoveredCard, setIsPopoverOpen, hoveredCard } = @@ -115,42 +102,36 @@ const GenericCard = React.forwardRef((props, ref) => { allDecks: allDecks, }); let cardContent = null; - if (cardSize === 'sm') { - cardContent = ( - - - {name} - - - {price} - - - ); - } else if (cardSize !== 'xs') { - cardContent = ( - - - {name} - - - {price} - - {`Cart: ${isInContext ? cartQuantity : 'N/A'}`} - {`Collection: ${isInContext ? collectionQuantity : 'N/A'}`} - {`Deck: ${isInContext ? deckQuantity : 'N/A'}`} - - ); + if (!isSwiperStyles) { + if (cardSize !== 'xs') { + cardContent = ( + + + {name} + + + {price} + + {cardSize !== 'sm' && ( + <> + {`Cart: ${isInContext ? cartQuantity : 'N/A'}`} + {`Collection: ${isInContext ? collectionQuantity : 'N/A'}`} + {`Deck: ${isInContext ? deckQuantity : 'N/A'}`} + + )} + + ); + } } - return ( diff --git a/src/components/dialogs/CollectionDialog.jsx b/src/components/dialogs/CollectionDialog.jsx index b2cb527..c8f5dfc 100644 --- a/src/components/dialogs/CollectionDialog.jsx +++ b/src/components/dialogs/CollectionDialog.jsx @@ -17,7 +17,6 @@ import AddCollectionForm from '../forms/AddCollectionForm'; import UpdateCollectionForm from '../forms/UpdateCollectionForm'; import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -import { withDynamicSnackbar } from '../../layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; import { DialogPaper, StyledDialog, @@ -115,4 +114,4 @@ CollectionDialog.propTypes = { }), }; -export default withDynamicSnackbar(CollectionDialog); +export default CollectionDialog; diff --git a/src/components/dialogs/DeckEditPanel.js b/src/components/dialogs/DeckEditPanel.js index 9cbf4ed..51dfab0 100644 --- a/src/components/dialogs/DeckEditPanel.js +++ b/src/components/dialogs/DeckEditPanel.js @@ -1,189 +1,94 @@ -import React, { useState, useEffect } from 'react'; -import { - Paper, - Typography, - Button, - TextField, - Chip, - Box, - FormControl, - InputLabel, - Select, - MenuItem, -} from '@mui/material'; -import { useDeckStore, useFormContext, useMode } from '../../context'; -import useSnackBar from '../../context/hooks/useSnackBar'; -import { withDynamicSnackbar } from '../../layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; +import React, { useEffect, useState } from 'react'; import SaveIcon from '@mui/icons-material/Save'; import DeleteIcon from '@mui/icons-material/Delete'; -import { FormBox } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; -import FormField from '../forms/reusable/FormField'; -const DeckEditPanel = ({ selectedDeck, showSnackbar }) => { - const { theme } = useMode(); - const { - formMethods, - register, - handleSubmit, - setValue, - watch, - formState: { errors, isSubmitting }, - reset, - setFormSchema, - onSubmit, - } = useFormContext(); - const [newTag, setNewTag] = useState(''); - const tags = watch('tags', selectedDeck?.tags || []); - const color = watch('color'); +import { useFormContext } from '../../context'; +import { z } from 'zod'; +import RCZodForm from '../forms/reusable/RCZodForm'; - useEffect(() => { - setFormSchema('updateDeckForm'); - }, [setFormSchema]); +const deckSchema = z.object({ + name: z.string().min(1, 'Name is required'), + description: z.string().min(1, 'Description is required'), + tags: z.array(z.string()), + color: z.enum(['red', 'blue', 'green', 'yellow']), +}); + +const DeckEditPanel = ({ selectedDeck }) => { + const { formMethods, setFormSchema } = useFormContext(); + const [tags, setTags] = useState(selectedDeck?.tags || []); useEffect(() => { + setFormSchema('updateDeckForm'); if (selectedDeck) { - reset({ - name: selectedDeck.name, - description: selectedDeck.description, - tags: selectedDeck.tags || [], - color: selectedDeck.color || 'red', + formMethods.reset({ + ...selectedDeck, + tags: selectedDeck.tags.join(', '), }); } - }, [selectedDeck, reset]); + }, [selectedDeck, setFormSchema, formMethods]); - const handleAddNewTag = (newTag) => { - if (newTag && !tags.includes(newTag)) { - setValue('tags', [...tags, newTag.trim()]); + const handleAddTag = (tag) => { + if (tag && !tags.includes(tag)) { + setTags([...tags, tag]); + formMethods.setValue('tags', [...tags, tag].join(', ')); } }; - const handleTagDelete = (tagToDelete) => { - setValue( - 'tags', - tags.filter((tag) => tag !== tagToDelete) - ); - }; - const handleFormSubmit = async (data) => { - try { - await onSubmit(data); - showSnackbar({ - message: 'Deck updated successfully', - variant: 'success', - }); - } catch (error) { - showSnackbar({ - message: error.message || 'An error occurred while updating the deck.', - variant: 'error', - }); - } + + const handleDeleteTag = (tagToDelete) => { + const updatedTags = tags.filter((tag) => tag !== tagToDelete); + setTags(updatedTags); + formMethods.setValue('tags', updatedTags.join(', ')); }; - return ( - - Deck Editor - - - - - {tags && - tags?.map((tag, index) => ( - handleTagDelete(tag)} - /> - ))} - setNewTag(e.target.value)} - onBlur={handleAddNewTag} - onKeyDown={(e) => { - if (e.key === 'Enter') { - e.preventDefault(); - handleAddNewTag(); - } - }} - /> - - - Color - - - - - - - - + const fields = [ + { name: 'name', label: 'Name', type: 'text' }, + { name: 'description', label: 'Description', type: 'text' }, + { + name: 'tags', + label: 'Tags', + type: 'chips', + chipData: tags, + onAddChip: handleAddTag, + onDeleteChip: handleDeleteTag, + }, + { + name: 'color', + label: 'Color', + type: 'select', + options: [ + { value: 'red', label: 'Red' }, + { value: 'blue', label: 'Blue' }, + { value: 'green', label: 'Green' }, + { value: 'yellow', label: 'Yellow' }, + ], + }, + ]; + + return ( + formMethods.submitForm()} + startIcon={} + additionalButtons={[ + { + label: 'Delete Deck', + startIcon: , + onClick: () => { + formMethods.setValue('_id', selectedDeck._id); + formMethods.setValue('delete', true); + formMethods.submitForm(); + }, + color: 'error', + variant: 'contained', + }, + ]} + formMethods={formMethods} + formName="updateDeckForm" + /> ); }; -export default withDynamicSnackbar(DeckEditPanel); +export default DeckEditPanel; diff --git a/src/components/dialogs/LoginDialog.jsx b/src/components/dialogs/LoginDialog.jsx index a4b22a5..bd9e334 100644 --- a/src/components/dialogs/LoginDialog.jsx +++ b/src/components/dialogs/LoginDialog.jsx @@ -9,20 +9,10 @@ import { DialogContent, DialogTitle, Divider, - FormControl, FormControlLabel, - Grid, - IconButton, - Link, - Paper, - Switch, Typography, - useMediaQuery, } from '@mui/material'; -import Brightness4Icon from '@mui/icons-material/Brightness4'; -import Brightness7Icon from '@mui/icons-material/Brightness7'; import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; -import { withDynamicSnackbar } from '../../layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; // Adjust import paths as necessary import LoginForm from '../forms/LoginForm'; import SignupForm from '../forms/SignupForm'; import { useFormContext, useMode } from '../../context'; @@ -30,18 +20,14 @@ import useAuthDialog from '../../context/hooks/useAuthDialog'; // Adjust import import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; import { - DialogContentsBox, - DialogPaer, DialogPaper, - FormPaper, StyledDialog, StyledDialogContent, } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; import MDAvatar from '../../layout/REUSABLE_COMPONENTS/MDAVATAR'; -import { AuthModeSwitch } from '../../layout/REUSABLE_STYLED_COMPONENTS/SpecificStyledComponents'; -import AuthSwitch from '../buttons/other/AuthSwitch'; -import SimpleButton from '../../layout/REUSABLE_COMPONENTS/unique/SimpleButton'; - +import RCSwitch from '../forms/reusable/RCSwitch'; +import LoginIcon from '@mui/icons-material/Login'; +import PersonAddIcon from '@mui/icons-material/PersonAdd'; function LoginDialog() { const { theme, toggleColorMode, mode } = useMode(); const { toggleLoginDialog, isLoggedIn, logout } = useAuthDialog(); @@ -64,6 +50,11 @@ function LoginDialog() { logout(); toggleLoginDialog(); }; + const handleToggle = () => { + setFormSchema( + currentSchemaKey === 'loginForm' ? 'signupForm' : 'loginForm' + ); + }; const formTitle = currentSchemaKey === 'loginForm' ? 'Login' : 'Sign Up'; const signupMode = currentSchemaKey === 'signupForm'; @@ -122,7 +113,16 @@ function LoginDialog() { {formTitle}
- + {/* */} + } + iconRight={} + /> diff --git a/src/components/dialogs/SelectionErrorDialog.jsx b/src/components/dialogs/SelectionErrorDialog.jsx index 7b1e736..a25dfbd 100644 --- a/src/components/dialogs/SelectionErrorDialog.jsx +++ b/src/components/dialogs/SelectionErrorDialog.jsx @@ -13,51 +13,34 @@ import PersonIcon from '@mui/icons-material/Person'; import AddIcon from '@mui/icons-material/Add'; import Typography from '@mui/material/Typography'; import { blue } from '@mui/material/colors'; -import { withDynamicSnackbar } from '../../layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; import useSelectedCollection from '../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; import { DialogContent, Slide } from '@mui/material'; +import useSnackbarManager from '../../context/hooks/useSnackbarManager'; const Transition = React.forwardRef(function Transition(props, ref) { return ; }); function SelectionErrorDialog(props) { - const { onClose, selectedValue, open, showSnackbar } = props; - const { - handleBackToCollections, - showCollections, - allCollections, - handleSelectCollection, - } = useSelectedCollection(); + const { onClose, selectedValue, open } = props; + const { handleBackToCollections, allCollections, handleSelectCollection } = + useSelectedCollection(); + const { showSuccess, showError, showInfo } = useSnackbarManager(); // Using custom snackbar hook + const handleClose = () => { onClose(selectedValue); }; - // const handleListItemClick = (value) => { - // if (typeof value?._id === 'string') { - // showSnackbar('Not implemented yet', 'successs'); - // } else { - // showSnackbar(`${value} selected as backup account`, 'success'); - // } - // onClose(value); - // }; const handleListItemClick = React.useCallback( (collection) => { if (collection._id) { - showSnackbar('Not implemented yet', 'info'); // Assuming 'successs' was a typo, corrected to 'info' for a non-implemented feature + showInfo('Not implemented yet'); // Show an informational snackbar } else { - showSnackbar(`${collection} selected as backup account`, 'success'); + showSuccess(`${collection} selected as backup account`); // Show a success snackbar } onClose(collection); }, - [onClose, showSnackbar] - ); - const handleAction = React.useCallback( - (message, severity, error) => { - showSnackbar(message, severity); - if (error) console.error('Action failed:', error); - }, - [showSnackbar] + [onClose, showInfo, showSuccess] ); return ( @@ -87,40 +70,6 @@ function SelectionErrorDialog(props) { ))} - - handleListItemClick(collection)} - // onClick={() => handleContextSelect(mappedContext)} - onSuccess={() => - handleAction( - { - title: 'Action successful', - message: `Card added to ${selectedValue} successfully.`, - }, - 'success', - null - ) - } - onFailure={(error) => - handleAction( - { - title: 'Action failed', - message: `Failed to add card to ${selectedValue}.`, - }, - 'error', - error - ) - } - > - - - - - - - - @@ -130,7 +79,7 @@ function SelectionErrorDialog(props) { SelectionErrorDialog.propTypes = { onClose: PropTypes.func.isRequired, open: PropTypes.bool.isRequired, - selectedValue: PropTypes.string.isRequired, + selectedValue: PropTypes.string, }; -export default withDynamicSnackbar(SelectionErrorDialog); +export default SelectionErrorDialog; diff --git a/src/components/dialogs/cardDialog/GenericCardDialog.jsx b/src/components/dialogs/cardDialog/GenericCardDialog.jsx index a0a0146..86c108c 100644 --- a/src/components/dialogs/cardDialog/GenericCardDialog.jsx +++ b/src/components/dialogs/cardDialog/GenericCardDialog.jsx @@ -20,7 +20,6 @@ import { ListItem, Backdrop, } from '@mui/material'; -import useSnackbar from '../../../context/hooks/useSnackBar'; import useSelectedContext from '../../../context/hooks/useSelectedContext'; import { useModalContext, useMode } from '../../../context'; import CardMediaSection from '../../cards/media/CardMediaSection'; @@ -61,7 +60,6 @@ const GenericCardDialog = (props) => { const fullScreen = useMediaQuery(theme.breakpoints.down('md')); const { closeModal } = useModalContext(); const [imageUrl, setImageUrl] = useState(card?.card_images[0]?.image_url); - // const { handleSnackBar, handleCloseSnackbar } = useSnackbar(); const [hasLoggedCard, setHasLoggedCard] = useState(false); const { setContext, setIsContextSelected } = useSelectedContext(); const handleAction = useCallback( diff --git a/src/components/forms/AddCollectionForm.jsx b/src/components/forms/AddCollectionForm.jsx index fa91a53..33adcbd 100644 --- a/src/components/forms/AddCollectionForm.jsx +++ b/src/components/forms/AddCollectionForm.jsx @@ -1,41 +1,17 @@ -import React from 'react'; -import { Box } from '@mui/material'; -import FormField from './reusable/FormField'; -import { LoadingButton } from '@mui/lab'; -import { useFormContext, useMode } from '../../context'; -import { withDynamicSnackbar } from '../../layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; -import { useForm } from 'react-hook-form'; -import { zodResolver } from '@hookform/resolvers/zod'; -import { - formSchemas, - getDefaultValuesFromSchema, -} from '../../context/UTILITIES_CONTEXT/FormContext/schemas'; -import { - FormBox, - FormFieldBox, -} from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; -import ReusableLoadingButton from '../buttons/other/ReusableLoadingButton'; +import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline'; +import RCZodForm from './reusable/RCZodForm'; -const AddCollectionForm = ({ showSnackbar }) => { - const formId = 'addCollectionForm'; - const { onSubmit } = useFormContext(); - const { theme } = useMode(); - const { - register, - handleSubmit, - formState: { errors, isSubmitting }, - } = useForm({ - resolver: zodResolver(formSchemas.addCollectionForm), - defaultValues: getDefaultValuesFromSchema(formSchemas.addCollectionForm), - }); - - const fields = [ +const AddCollectionForm = () => { + // Assuming 'addCollectionForm' is the key/name for this form schema in your context + const schemaName = 'addCollectionForm'; + const buttonLabel = 'Create Collection'; + const startIcon = ; + const addCollectionFields = [ { name: 'name', label: 'Name', type: 'text', required: true, - multiline: false, }, { name: 'description', @@ -46,64 +22,14 @@ const AddCollectionForm = ({ showSnackbar }) => { rows: 4, }, ]; - - const onFormSubmit = async (data) => { - try { - await new Promise((resolve) => setTimeout(resolve, 2000)); // Simulated delay - onSubmit(data, formId); - showSnackbar( - { - title: 'Success', - description: "You've successfully added a new collection.", - }, - 'success' - ); // Adjust message as needed - } catch (error) { - // On error: - showSnackbar( - { - title: 'Error', - description: 'Failed to add collection. Please try again.', - }, - 'error' - ); // Adjust message as needed - } - }; return ( - - {fields.map((field, index) => ( - - - - ))} - - + ); }; -export default withDynamicSnackbar(AddCollectionForm); +export default AddCollectionForm; diff --git a/src/components/forms/AddDeckForm.jsx b/src/components/forms/AddDeckForm.jsx index fea3735..0ef423e 100644 --- a/src/components/forms/AddDeckForm.jsx +++ b/src/components/forms/AddDeckForm.jsx @@ -1,72 +1,103 @@ +// import React from 'react'; +// import { useFormContext } from '../../context'; +// import FormField from '../reusable/FormField'; +// import { Button, Paper, Typography, Box } from '@mui/material'; +// import SaveIcon from '@mui/icons-material/Save'; + +// const AddDeckForm = ({ showSnackbar }) => { +// const { formStates, onSubmit } = useFormContext(); +// const formId = 'addDeckForm'; // Assuming this is the formId for creating decks + +// const { +// register, +// handleSubmit, +// formState: { errors, isSubmitting }, +// } = formStates[formId]; + +// const onFormSubmit = async (data) => { +// try { +// await onSubmit(data, formId); +// console.log(data); +// } catch (error) { +// console.error(error); +// } +// }; + +// return ( +// +// Create Deck +//
+// +// +// +// +// +// +//
+// ); +// }; +// export default AddDeckForm; import React from 'react'; import { useFormContext } from '../../context'; -import FormField from '../reusable/FormField'; -import { Button, Paper, Typography, Box } from '@mui/material'; +import RCZodForm from './RCZodForm'; import SaveIcon from '@mui/icons-material/Save'; -import { withDynamicSnackbar } from '../../layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; -const AddDeckForm = ({ showSnackbar }) => { - const { formStates, onSubmit } = useFormContext(); +const AddDeckForm = () => { + const { setFormSchema } = useFormContext(); const formId = 'addDeckForm'; // Assuming this is the formId for creating decks - const { - register, - handleSubmit, - formState: { errors, isSubmitting }, - } = formStates[formId]; + // Fields configuration for AddDeckForm + const fields = [ + { name: 'name', label: 'Name', type: 'text', required: true }, + { + name: 'description', + label: 'Description', + type: 'text', + required: true, + multiline: true, + }, + ]; - const onFormSubmit = async (data) => { - try { - await onSubmit(data, formId); - showSnackbar( - { - title: 'Success', - description: 'Deck created successfully.', - }, - 'success' - ); - } catch (error) { - showSnackbar( - { - title: 'Error', - description: 'Failed to create deck. Please try again.', - }, - 'error' - ); - } + // This function should be context-aware or passed down as a prop + const handleSubmit = (data) => { + console.log('Add Deck Data:', data); + // Interaction with context or props for form submission }; + // Set the schema based on the form ID + React.useEffect(() => { + setFormSchema(formId); + }, [setFormSchema, formId]); + return ( - - Create Deck -
- - - - - - -
+ } + /> ); }; -export default withDynamicSnackbar(AddDeckForm); // Wrap DeckEditPanel with withDynamicSnackbar HOC + +export default AddDeckForm; diff --git a/src/components/forms/LoginForm.jsx b/src/components/forms/LoginForm.jsx index 32ae609..7b68567 100644 --- a/src/components/forms/LoginForm.jsx +++ b/src/components/forms/LoginForm.jsx @@ -1,162 +1,35 @@ -import React, { useEffect } from 'react'; -import { - Box, - Checkbox, - FormControlLabel, - Grid, - InputAdornment, - Link, -} from '@mui/material'; -import FormField from './reusable/FormField'; -import { LoadingButton } from '@mui/lab'; -import { useFormContext, useMode } from '../../context'; +import React from 'react'; import LoginIcon from '@mui/icons-material/Login'; import PersonIcon from '@mui/icons-material/Person'; import LockIcon from '@mui/icons-material/Lock'; -import { - FormBox, - FormFieldBox, -} from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; -import ReusableLoadingButton from '../buttons/other/ReusableLoadingButton'; -// import useSubmitHandler from './hooks/useSubmitHandler'; -// import useCustomSnackbar from '../../context/hooks/useCustomSnackbar'; -const baseButtonStyles = { - bgcolor: '#6a59ff', // background-color - borderColor: '#6a59ff', - borderWidth: 2, - borderStyle: 'solid', - display: 'flex', - flexGrow: 1, - alignItems: 'center', - justifyContent: 'center', - marginLeft: 'auto', - marginRight: 'auto', - marginBottom: '16px', - marginTop: '16px', - position: 'relative', - bottom: 0, - cursor: 'pointer', - transition: 'background-color 0.3s, border-color 0.3s, color 0.3s', - ':hover': { - fontWeight: 'bold', - bgcolor: '#4a6da7', - borderColor: '#34597f', +import RCZodForm from './reusable/RCZodForm'; + +const loginFields = [ + { + name: 'username', + label: 'Username', + type: 'text', + icon: , + field: 'username', }, - ':focus': { - outline: '2px solid #62a4ff', - outlineOffset: 2, + { + name: 'password', + label: 'Password', + type: 'password', + icon: , + field: 'password', }, -}; -const LoginForm = () => { - // const showSnackbar = useCustomSnackbar(); +]; - const { formMethods, onSubmit, setFormSchema } = useFormContext(); - const { theme } = useMode(); - const { - register, - handleSubmit, - formState: { errors, isSubmitting }, - } = formMethods; - - useEffect(() => { - setFormSchema('loginForm'); - }, [setFormSchema]); - const fields = [ - { - name: 'username', - label: 'Username', - type: 'text', - icon: , - }, - { - name: 'password', - label: 'Password', - type: 'password', - icon: , - }, - ]; - // const onFormSubmit = useSubmitHandler( - // onSubmit(data, 'loginForm'), // Assuming this is the function that performs the submission logic - // 'Success', // Title for the success message - // "You've successfully logged in.", // Success description - // 'Login failed. Please try again.' // Error description - // ); - const onFormSubmit = (data) => { - // showSnackbar('Loading...', 'Logging in...', { variant: 'info' }); - onSubmit(data, 'loginForm'); - // .then(() => { - // showSnackbar('Success!', "You've successfully logged in.", { - // variant: 'success', - // persist: true, - // }); - // }) - // .catch((error) => { - // showSnackbar( - // 'Error', - // 'Login failed. Please try again.' + `: ${error}`, - // { variant: 'error', persist: true } - // ); - // }); - }; +const LoginForm = () => { + const startIcon = ; return ( - - {fields.map((field, index) => ( - - {field.icon} - ), - }} - /> - {errors[field.name] && ( - {errors[field.name].message} - )} - - ))} - {/* } - fullWidth - sx={{ - background: theme.palette.backgroundG.light, - borderColor: theme.palette.backgroundG.light, - borderWidth: 2, - '&:hover': { background: theme.palette.backgroundG.default }, - '&:focus': { background: theme.palette.backgroundG.default }, - }} - > - Login - */} - } - fullWidth - sx={{ - mt: 2, // margin-top: Adjust if necessary - background: theme.palette.backgroundG.light, - '&:hover': { background: theme.palette.backgroundG.default }, - }} - /> - + ); }; diff --git a/src/components/forms/SearchForm.jsx b/src/components/forms/SearchForm.jsx index 7b583a8..445eecb 100644 --- a/src/components/forms/SearchForm.jsx +++ b/src/components/forms/SearchForm.jsx @@ -1,93 +1,32 @@ -import React, { useCallback, useEffect } from 'react'; -import { Button, Grid } from '@mui/material'; -import { useFormContext, useMode, usePageContext } from '../../context'; -import { - StyledFormBox, - StyledFormPaper, -} from '../../pages/pageStyles/StyledComponents'; -import { FormBox } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; -import { LoadingButton } from '@mui/lab'; -import FormField from './reusable/FormField'; +import React from 'react'; +import SearchIcon from '@mui/icons-material/Search'; +import RCZodForm from './reusable/RCZodForm'; +import { useFormContext } from '../../context'; const SearchForm = () => { - const { theme } = useMode(); - const formId = 'searchForm'; - const { - formMethods, - formStates: { errors, isSubmitting, ...formStates }, - onSubmit, - handleFieldChange, - handleSearchTermChange, - handleBlur, - handleFocus, - forms, - handleChange, - setFormSchema, - } = useFormContext(); - - useEffect(() => { - setFormSchema(formId); - }, [setFormSchema]); - - const handleKeyPress = (e) => { - if (e.key === 'Enter') { - e.preventDefault(); - formMethods.handleSubmit((data) => { - onSubmit(data); - }); - } - }; + const { formMethods, formStates } = useFormContext(); + const { forms } = formStates; + const { handleChange, handleFocus, handleBlur } = formMethods; + const searchFields = [ + { + name: 'searchTerm', + label: 'Search for cards', + type: 'text', + required: false, + value: forms?.searchForm?.searchTerm || '', + onChange: handleChange, + onFocus: handleFocus, + onBlur: handleBlur, + }, + ]; return ( - - - onSubmit(data, 'searchForm') - )} - > - - {errors?.searchTerm && ( - -

{errors?.searchTerm?.message}

-
- )} - - {isSubmitting ? 'Loading...' : 'Search'} - - {errors?.root &&

{errors?.root?.message}

} -
-
+ } + /> ); }; diff --git a/src/components/forms/SignupForm.jsx b/src/components/forms/SignupForm.jsx index c569194..f4d78fa 100644 --- a/src/components/forms/SignupForm.jsx +++ b/src/components/forms/SignupForm.jsx @@ -1,168 +1,172 @@ -import React, { useEffect } from 'react'; -import { Box, Button } from '@mui/material'; -import FormField from './reusable/FormField'; -import { useForm } from 'react-hook-form'; -import { zodResolver } from '@hookform/resolvers/zod'; -import { - formSchemas, - getDefaultValuesFromSchema, -} from '../../context/UTILITIES_CONTEXT/FormContext/schemas'; // Ensure this path is correct -import { LoadingButton } from '@mui/lab'; -import { useFormContext, useMode, usePageContext } from '../../context'; -import { withDynamicSnackbar } from '../../layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; -import AuthSwitch from '../buttons/other/AuthSwitch'; +// import React, { useEffect } from 'react'; +// import { Box, Button } from '@mui/material'; +// import FormField from './reusable/FormField'; +// import { useForm } from 'react-hook-form'; +// import { zodResolver } from '@hookform/resolvers/zod'; +// import { +// formSchemas, +// getDefaultValuesFromSchema, +// } from '../../context/UTILITIES_CONTEXT/FormContext/schemas'; // Ensure this path is correct +// import { LoadingButton } from '@mui/lab'; +// import { useFormContext, useMode, usePageContext } from '../../context'; +// import AuthSwitch from '../buttons/other/AuthSwitch'; +// import PersonAddIcon from '@mui/icons-material/PersonAdd'; + +// import { +// FormBox, +// FormFieldBox, +// } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; +// const baseButtonStyles = { +// bgcolor: '#6a59ff', // background-color +// borderColor: '#6a59ff', +// borderWidth: 2, +// borderStyle: 'solid', +// display: 'flex', +// flexGrow: 1, +// alignItems: 'center', +// justifyContent: 'center', +// marginLeft: 'auto', +// marginRight: 'auto', +// marginBottom: '16px', +// marginTop: '16px', +// position: 'relative', +// bottom: 0, +// cursor: 'pointer', +// transition: 'background-color 0.3s, border-color 0.3s, color 0.3s', +// ':hover': { +// fontWeight: 'bold', +// bgcolor: '#4a6da7', +// borderColor: '#34597f', +// }, +// ':focus': { +// outline: '2px solid #62a4ff', +// outlineOffset: 2, +// }, +// }; +// const SignupForm = ({ signupMode, toggleAuthMode, formLabel }) => { +// const { theme } = useMode(); +// const { formMethods, onSubmit, setFormSchema } = useFormContext(); + +// const { +// register, +// handleSubmit, +// formState: { errors, isSubmitting }, +// } = formMethods; + +// useEffect(() => { +// setFormSchema('signupForm'); +// }, [setFormSchema]); +// const fields = [ +// { name: 'firstName', label: 'First Name', type: 'text' }, +// { name: 'lastName', label: 'Last Name', type: 'text' }, +// { name: 'email', label: 'Email', type: 'email' }, +// { name: 'username', label: 'Username', type: 'text' }, +// { name: 'password', label: 'Password', type: 'password' }, +// ]; + +// // Updated onFormSubmit to directly use onSubmit from context +// const onFormSubmit = (data) => { +// onSubmit(data, 'signupForm'); +// }; +// return ( +// +// {fields.map((field, index) => ( +// +// +// +// ))} +// +// {errors.form && ( +// {errors.form.message} +// )} +// +// } +// fullWidth +// sx={{ +// background: theme.palette.backgroundG.light, +// borderColor: theme.palette.backgroundG.light, +// borderWidth: 2, +// '&:hover': { background: theme.palette.backgroundG.default }, +// '&:focus': { background: theme.palette.backgroundG.default }, +// }} +// > +// Sign Up +// +// +// ); +// }; + +// export default SignupForm; +import React from 'react'; import PersonAddIcon from '@mui/icons-material/PersonAdd'; +import PersonIcon from '@mui/icons-material/Person'; +import EmailIcon from '@mui/icons-material/Email'; +import LockIcon from '@mui/icons-material/Lock'; +import RCZodForm from './reusable/RCZodForm'; -import { - FormBox, - FormFieldBox, -} from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; -const baseButtonStyles = { - bgcolor: '#6a59ff', // background-color - borderColor: '#6a59ff', - borderWidth: 2, - borderStyle: 'solid', - display: 'flex', - flexGrow: 1, - alignItems: 'center', - justifyContent: 'center', - marginLeft: 'auto', - marginRight: 'auto', - marginBottom: '16px', - marginTop: '16px', - position: 'relative', - bottom: 0, - cursor: 'pointer', - transition: 'background-color 0.3s, border-color 0.3s, color 0.3s', - ':hover': { - fontWeight: 'bold', - bgcolor: '#4a6da7', - borderColor: '#34597f', +const signupFields = [ + { + name: 'firstName', + label: 'First Name', + type: 'text', + icon: , + field: 'firstName', }, - ':focus': { - outline: '2px solid #62a4ff', - outlineOffset: 2, + { + name: 'lastName', + label: 'Last Name', + type: 'text', + icon: , + field: 'lastName', }, -}; -const SignupForm = ({ - // showSnackbar, - signupMode, - toggleAuthMode, - formLabel, -}) => { - const { theme } = useMode(); - const { formMethods, onSubmit, setFormSchema } = useFormContext(); - - const { - register, - handleSubmit, - formState: { errors, isSubmitting }, - } = formMethods; - - useEffect(() => { - setFormSchema('signupForm'); - }, [setFormSchema]); - const fields = [ - { name: 'firstName', label: 'First Name', type: 'text' }, - { name: 'lastName', label: 'Last Name', type: 'text' }, - { name: 'email', label: 'Email', type: 'email' }, - { name: 'username', label: 'Username', type: 'text' }, - { name: 'password', label: 'Password', type: 'password' }, - ]; + { + name: 'email', + label: 'Email', + type: 'email', + icon: , + field: 'email', + }, + { + name: 'username', + label: 'Username', + type: 'text', + icon: , + field: 'username', + }, + { + name: 'password', + label: 'Password', + type: 'password', + icon: , + field: 'password', + }, +]; - // Updated onFormSubmit to directly use onSubmit from context - const onFormSubmit = (data) => { - onSubmit(data, 'signupForm'); - // .then(() => { - // showSnackbar( - // { title: 'Success', description: "You've successfully signed up." }, - // 'success' - // ); - // }) - // .catch((error) => { - // showSnackbar( - // { title: 'Error', description: 'Signup failed. Please try again.' }, - // 'error' - // ); - // }); - }; - // useEffect(() => { - // setIsFormDataLoading(isSubmitting); - // console.log('isSubmitting:', isSubmitting); - // }, [isSubmitting, setIsFormDataLoading]); +const SignupForm = () => { return ( - - {fields.map((field, index) => ( - - - - ))} - - {errors.form && ( - {errors.form.message} - )} - - } - fullWidth - sx={{ - background: theme.palette.backgroundG.light, - borderColor: theme.palette.backgroundG.light, - borderWidth: 2, - '&:hover': { background: theme.palette.backgroundG.default }, - '&:focus': { background: theme.palette.backgroundG.default }, - }} - // type="submit" - // variant="contained" - // loading={isSubmitting} - // onClick={() => handleSubmit(onFormSubmit)()} - // color="primary" - // sx={{ - // background: theme.palette.backgroundE.darker, - // borderColor: theme.palette.backgroundB.darkest, - // borderWidth: 2, - // flexGrow: 1, - // justifySelf: 'bottom', - // bottom: 0, - // mx: 'auto', - // my: 2, - // '&:hover': { - // fontWeight: 'bold', - // background: theme.palette.backgroundF.dark, - // borderColor: theme.palette.backgroundB.darkest, - // border: `1px solid ${theme.palette.backgroundB.darkest}`, - // }, - // }} - // fullWidth - > - Sign Up - - + } + /> ); }; -export default withDynamicSnackbar(SignupForm); +export default SignupForm; diff --git a/src/components/forms/UpdateCollectionForm.jsx b/src/components/forms/UpdateCollectionForm.jsx index 80cfbc8..49bb6ef 100644 --- a/src/components/forms/UpdateCollectionForm.jsx +++ b/src/components/forms/UpdateCollectionForm.jsx @@ -1,116 +1,55 @@ import React, { useEffect } from 'react'; -import { Box } from '@mui/material'; -import { LoadingButton } from '@mui/lab'; import { useFormContext, useMode } from '../../context'; -import { withDynamicSnackbar } from '../../layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; -import { useForm } from 'react-hook-form'; -import { zodResolver } from '@hookform/resolvers/zod'; -import { - formSchemas, - getDefaultValuesFromSchema, -} from '../../context/UTILITIES_CONTEXT/FormContext/schemas'; -import FormField from './reusable/FormField'; -import { - FormBox, - FormFieldBox, -} from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; - -const UpdateCollectionForm = ({ showSnackbar, collectionData }) => { - const formId = 'updateCollectionForm'; - const { onSubmit } = useFormContext(); +import useSnackbarManager from '../../context/hooks/useSnackbarManager'; +import RCZodForm from './reusable/RCZodForm'; + +const updateCollectionFields = [ + { + name: 'name', + label: 'Name', + type: 'text', + required: true, + }, + { + name: 'description', + label: 'Description', + type: 'text', + required: true, + multiline: true, + rows: 4, + }, +]; + +const UpdateCollectionForm = ({ collectionData }) => { + const { setFormSchema, onSubmit } = useFormContext(); const { theme } = useMode(); - const { - register, - handleSubmit, - reset, - formState: { errors, isSubmitting }, - } = useForm({ - resolver: zodResolver(formSchemas.updateCollectionForm), - defaultValues: - collectionData || - getDefaultValuesFromSchema(formSchemas.updateCollectionForm), - }); - - // Automatically reset form fields to the passed collection data - React.useEffect(() => { - reset(collectionData); - }, [collectionData, reset]); + const { showSuccess, showError } = useSnackbarManager(); - const fields = [ - { name: 'name', label: 'Name', type: 'text' }, - { name: 'description', label: 'Description', type: 'text' }, - ]; + useEffect(() => { + if (collectionData) { + setFormSchema('updateCollectionForm', collectionData); + } + }, [collectionData, setFormSchema]); - const onFormSubmit = async (data) => { + const handleFormSubmit = async (data) => { try { - // Simulate form submission - await new Promise((resolve) => setTimeout(resolve, 2000)); // Simulated delay - - onSubmit(data, formId, collectionData._id); // Adjust to call the actual update function - - // On success: - showSnackbar( - { - title: 'Success', - description: "You've successfully updated the collection.", - }, - 'success' - ); + await onSubmit(data, 'updateCollectionForm', collectionData?._id); + showSuccess("You've successfully updated the collection."); } catch (error) { - // On error: - showSnackbar( - { - title: 'Error', - description: 'Failed to update collection. Please try again.', - }, - 'error' - ); + showError('Failed to update collection. Please try again.'); } }; return ( - - - - - - - - - Update Collection - - + initialValues={collectionData} + /> ); }; -export default withDynamicSnackbar(UpdateCollectionForm); +export default UpdateCollectionForm; diff --git a/src/components/forms/UpdateDeckForm.jsx b/src/components/forms/UpdateDeckForm.jsx index 4c8d719..e73ba4f 100644 --- a/src/components/forms/UpdateDeckForm.jsx +++ b/src/components/forms/UpdateDeckForm.jsx @@ -1,97 +1,149 @@ -import React, { useEffect } from 'react'; -import { useFormContext, useMode } from '../../context'; -import FormField from '../reusable/FormField'; -import { Button, Paper, Typography, Box } from '@mui/material'; +// import React, { useEffect } from 'react'; +// import { useFormContext, useMode } from '../../context'; +// import FormField from '../reusable/FormField'; +// import { Button, Paper, Typography, Box } from '@mui/material'; +// import SaveIcon from '@mui/icons-material/Save'; +// import DeleteIcon from '@mui/icons-material/Delete'; +// import { FormBox } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; + +// const UpdateDeckForm = ({ selectedDeck }) => { +// const { theme } = useMode(); +// const { formStates, onSubmit } = useFormContext(); +// const formId = 'updateDeckForm'; // Assuming this is the formId for updating decks + +// const { +// register, +// handleSubmit, +// reset, +// formState: { errors, isSubmitting }, +// } = formStates[formId]; + +// useEffect(() => { +// if (selectedDeck) { +// reset(selectedDeck); +// } +// }, [selectedDeck, reset]); + +// const onFormSubmit = async (data) => { +// try { +// await onSubmit({ ...data, _id: selectedDeck._id }, formId); +// console.log(data); +// } catch (error) { +// console.error(error); +// } +// }; + +// return ( +// +// Update Deck +// +// +// +// +// +// +// +// +// +// ); +// }; +// export default UpdateDeckForm; +import React from 'react'; +import RCZodForm from './RCZodForm'; import SaveIcon from '@mui/icons-material/Save'; import DeleteIcon from '@mui/icons-material/Delete'; -import { withDynamicSnackbar } from '../../layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; -import { FormBox } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; +import { useFormContext } from '../../context'; -const UpdateDeckForm = ({ selectedDeck, showSnackbar }) => { - const { theme } = useMode(); - const { formStates, onSubmit } = useFormContext(); - const formId = 'updateDeckForm'; // Assuming this is the formId for updating decks +// Assume the schema is defined elsewhere and imported here +// import { updateDeckFormSchema } from './yourSchemaDefinitions'; - const { - register, - handleSubmit, - reset, - formState: { errors, isSubmitting }, - } = formStates[formId]; +const updateDeckFields = [ + { + name: 'name', + label: 'Name', + type: 'text', + icon: null, // No icons used for these fields + }, + { + name: 'description', + label: 'Description', + type: 'text', + multiline: true, + rows: 4, + icon: null, + }, +]; - useEffect(() => { - if (selectedDeck) { - reset(selectedDeck); - } - }, [selectedDeck, reset]); +const UpdateDeckForm = ({ selectedDeck }) => { + const { onSubmit } = useFormContext(); // Assuming useFormContext provides onSubmit - const onFormSubmit = async (data) => { - try { - await onSubmit({ ...data, _id: selectedDeck._id }, formId); - showSnackbar( - { - title: 'Success', - description: 'Deck updated successfully.', - }, - 'success' - ); - } catch (error) { - showSnackbar( - { - title: 'Error', - description: 'Failed to update deck. Please try again.', - }, - 'error' - ); - } + // Placeholder for the submission logic within the component or from props + const handleSubmit = (data) => { + console.log('Submitting update deck data:', data); + onSubmit(data, 'updateDeckForm'); // This should align with your context action + }; + + // Placeholder for the deletion logic within the component or from props + const handleDelete = () => { + console.log('Deleting deck:', selectedDeck._id); + // Here you would call a context function or similar to delete the deck + onSubmit({ _id: selectedDeck._id, delete: true }, 'updateDeckForm'); }; return ( - - Update Deck - - - - - - - - - + } + additionalButtons={[ + { + label: 'Delete Deck', + onClick: handleDelete, + startIcon: , + color: 'error', + variant: 'contained', + disabled: !selectedDeck, + }, + ]} + defaultValues={selectedDeck} // Assuming this prop is structured correctly for the form + /> ); }; -export default withDynamicSnackbar(UpdateDeckForm); // Wrap DeckEditPanel with withDynamicSnackbar HOC + +export default UpdateDeckForm; diff --git a/src/components/buttons/other/CronTrigger.jsx b/src/components/forms/cleanup/CronTrigger.jsx similarity index 100% rename from src/components/buttons/other/CronTrigger.jsx rename to src/components/forms/cleanup/CronTrigger.jsx diff --git a/src/components/forms/cleanup/ThemeToggleButton.jsx b/src/components/forms/cleanup/ThemeToggleButton.jsx new file mode 100644 index 0000000..c6f65bd --- /dev/null +++ b/src/components/forms/cleanup/ThemeToggleButton.jsx @@ -0,0 +1,49 @@ +// import React, { useContext, useState } from 'react'; +// import { IconButton, Menu, MenuItem } from '@mui/material'; +// import Brightness4Icon from '@mui/icons-material/Brightness4'; +// import Brightness7Icon from '@mui/icons-material/Brightness7'; +// import { ColorModeContext } from '../../../context/UTILITIES_CONTEXT/ColorModeContext/ColorModeProvider'; + +// const ThemeToggleButton = () => { +// const [anchorEl, setAnchorEl] = useState(null); +// const { toggleColorMode, setMode } = useContext(ColorModeContext); + +// const handleClick = (event) => { +// setAnchorEl(event.currentTarget); +// }; + +// const handleClose = () => { +// setAnchorEl(null); +// }; + +// const handleThemeChange = (mode) => { +// toggleColorMode(mode); // Updated this line +// console.log('mode', mode); +// handleClose(); +// }; + +// return ( +//
+// +// +// +// +// handleThemeChange('dark')}> +// +// Dark Mode +// +// handleThemeChange('light')}> +// +// Light Mode +// +// +//
+// ); +// }; + +// export default ThemeToggleButton; diff --git a/src/components/forms/hooks/useSubmitHandler.jsx b/src/components/forms/hooks/useSubmitHandler.jsx index 52e5725..5b3287c 100644 --- a/src/components/forms/hooks/useSubmitHandler.jsx +++ b/src/components/forms/hooks/useSubmitHandler.jsx @@ -1,5 +1,5 @@ import { useCallback } from 'react'; -import useCustomSnackbar from '../../../context/hooks/useCustomSnackbar'; +import useSnackbarManager from '../../../context/hooks/useSnackbarManager'; function useSubmitHandler( onSubmit, @@ -7,29 +7,32 @@ function useSubmitHandler( successDescription, errorDescription ) { - const showSnackbar = useCustomSnackbar(); + const { showSuccess, showError } = useSnackbarManager(); return useCallback( (data, formType) => { onSubmit(data, formType) .then(() => { - showSnackbar( - successTitle, - successDescription.replace('{timeRange}', data?.timeRange), - { variant: 'success' } + // Using showSuccess for positive feedback + showSuccess( + `${successTitle}: ${successDescription.replace('{timeRange}', data?.timeRange)}` ); }) .catch((error) => { - showSnackbar( - 'Error', - errorDescription.replace('{timeRange}', data?.timeRange) + - `: ${error}`, - { variant: 'error' } + // Using showError for negative feedback + showError( + `${errorDescription.replace('{timeRange}', data?.timeRange)}: ${error}` ); }); }, - // `showSnackbar` is now a dependency of useCallback - [onSubmit, showSnackbar, successTitle, successDescription, errorDescription] + [ + onSubmit, + showSuccess, + showError, + successTitle, + successDescription, + errorDescription, + ] ); } diff --git a/src/components/forms/reusable/RCSwitch.jsx b/src/components/forms/reusable/RCSwitch.jsx new file mode 100644 index 0000000..edaae5e --- /dev/null +++ b/src/components/forms/reusable/RCSwitch.jsx @@ -0,0 +1,98 @@ +import React from 'react'; +import { Switch, FormControlLabel, FormControl } from '@mui/material'; +import { styled } from '@mui/material/styles'; +import { useMode } from '../../../context'; +import { renderToStaticMarkup } from 'react-dom/server'; +import { useCookies } from 'react-cookie'; + +// Convert SVG icons to data URI +const convertSvg = (svg) => { + const markup = renderToStaticMarkup(svg); + const encoded = encodeURIComponent(markup); + const dataUri = `url('data:image/svg+xml;utf8,${encoded}')`; + return dataUri; +}; + +// Generic switch component +const RCSwitch = ({ + checked, + onChange, + labelLeft, + labelRight, + iconLeft, + iconRight, + size = { width: 50, height: 14, thumbWidth: 22, thumbHeight: 22 }, +}) => { + const { theme } = useMode(); + const colors = theme.palette.chartTheme; + const cookies = useCookies('colorMode'); + const mode = cookies.colorMode; + const green = colors.greenAccent.light; + const lihhtgreen = colors.greenAccent.default; + const calculateTransform = () => { + const trackPadding = 2; // Adjust based on your design + const transformDistance = size.width - size.thumbWidth - trackPadding; + return transformDistance; + }; + const SwitchBaseStyles = { + // pt: 1.5, + // pl: 1.5, + my: 1.7, + // ml: 1.5, + '&.Mui-checked': { + transform: `translateX(${calculateTransform()}px)`, + color: theme.palette.common.white, + '& + .MuiSwitch-track': { + backgroundColor: theme.palette.primary.main, + }, + }, + }; + + const ThumbStyles = (icon) => ({ + width: size.thumbWidth, + height: size.thumbHeight, + // backgroundColor: theme.palette.common.white, + backgroundColor: mode === 'dark' ? green : lihhtgreen, + + '&:before': { + content: '" "', + display: 'block', + backgroundImage: convertSvg(icon), + width: '100%', + height: '100%', + backgroundSize: '50%', + backgroundPosition: 'center', + backgroundRepeat: 'no-repeat', + }, + }); + + const TrackStyles = { + backgroundColor: theme.palette.grey.light, + opacity: 1, + // borderRadius: 20, + width: size.width, + height: size.height, + }; + + const SwitchStyles = { + ...SwitchBaseStyles, + '& .MuiSwitch-thumb': checked + ? ThumbStyles(iconRight) + : ThumbStyles(iconLeft), + '& .MuiSwitch-track': TrackStyles, + }; + + return ( + + + } + label={checked ? labelRight : labelLeft} + style={{ margin: 'auto', justifyContent: 'center' }} + /> + + ); +}; + +export default RCSwitch; diff --git a/src/components/forms/reusable/RCZodForm.jsx b/src/components/forms/reusable/RCZodForm.jsx new file mode 100644 index 0000000..d4ce7e8 --- /dev/null +++ b/src/components/forms/reusable/RCZodForm.jsx @@ -0,0 +1,309 @@ +// import React, { useEffect } from 'react'; +// import { +// Box, +// InputAdornment, +// FormControl, +// InputLabel, +// Select, +// MenuItem, +// Chip, +// } from '@mui/material'; +// import FormField from './reusable/FormField'; +// import ReusableLoadingButton from '../buttons/other/ReusableLoadingButton'; +// import { useFormContext, useMode } from '../../context'; +// import { FormFieldBox } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; + +// const RCZodForm = ({ +// fields, +// buttonLabel, +// startIcon, +// schemaName, +// additionalButtons, +// }) => { +// const { theme } = useMode(); + +// const { +// formMethods, +// register, +// onSubmit, +// handleChange, +// handleBlur, +// // getValues, +// handleFocus, +// formStates: { errors, isSubmitting, ...formStates }, +// setFormSchema, +// // formState: { errors, isSubmitting }, +// } = useFormContext(); + +// useEffect(() => { +// setFormSchema(schemaName); +// }, [setFormSchema, schemaName]); + +// const onFormSubmit = (data) => { +// onSubmit(data, schemaName); +// }; + +// const handleKeyPress = (e) => { +// if (e.key === 'Enter') { +// e.preventDefault(); +// formMethods.handleSubmit((data) => { +// onSubmit(data); +// }); +// } +// }; + +// const renderField = (field) => { +// if (field.type === 'select') { +// return ( +// +// +// {field.label} +// +// +// +// ); +// } else if (field.type === 'chips') { +// return ( +// +// +// {field?.values?.map((value, index) => ( +// field.onDelete(value)} +// /> +// ))} +// +// +// ); +// } else { +// return ( +// +// formMethods.handleChange(e, field.name)} +// // value={} +// defaultValue={formMethods.getValues(field.name)} +// onFocus={handleFocus} +// onBlur={handleBlur} +// onKeyDown={handleKeyPress} +// InputProps={ +// field.icon +// ? { +// endAdornment: ( +// +// {field.icon} +// +// ), +// } +// : null +// } +// multiline={field.multiline} +// rows={field.rows} +// /> +// +// ); +// } +// }; +// return ( +// +// {fields?.map(renderField)} +// +// {startIcon} +// +// } +// fullWidth +// /> +// {additionalButtons && +// additionalButtons?.map((button, index) => ( +// +// ))} +// +// ); +// }; + +// export default RCZodForm; +import React, { useEffect } from 'react'; +import { + Box, + InputAdornment, + FormControl, + InputLabel, + Select, + MenuItem, + Chip, +} from '@mui/material'; +import FormField from './FormField'; +import ReusableLoadingButton from '../../buttons/other/ReusableLoadingButton'; +import { useFormContext, useMode } from '../../../context'; +import { + FormBox, + FormFieldBox, +} from '../../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; + +const RCZodForm = ({ + fields, + buttonLabel, + startIcon, + schemaName, + additionalButtons, +}) => { + const { theme } = useMode(); + const { + formMethods, + onSubmit, + handleChange, + setFormSchema, + formState: { errors, isSubmitting }, + // getValues, + handleSearchTermChange, + } = useFormContext(); + + useEffect(() => { + setFormSchema(schemaName); + }, [setFormSchema, schemaName]); + + const onFormSubmit = (data) => { + onSubmit(data, schemaName); + }; + + const renderField = (field) => { + const isSearchForm = + schemaName === 'searchForm' && field.name === 'searchTerm'; + + const onChange = isSearchForm ? handleSearchTermChange : undefined; + + if (field.type === 'select') { + return ( + + + {field.label} + + + + ); + } else if (field.type === 'chips') { + return ( + + + {field?.values?.map((value, index) => ( + field.onDelete(value)} + /> + ))} + + + ); + } else { + return ( + + formMethods.handleChange(e.target.value)} + InputProps={ + field.icon + ? { + endAdornment: ( + + {field.icon} + + ), + } + : null + } + multiline={field.multiline} + rows={field.rows} + /> + + ); + } + }; + + return ( + + {fields?.map(renderField)} + + {startIcon} + + } + fullWidth + /> + {additionalButtons && + additionalButtons?.map((button, index) => ( + + ))} + + ); +}; + +export default RCZodForm; diff --git a/src/components/forms/search/SearchComponent.jsx b/src/components/forms/search/SearchComponent.jsx index 0a5e57e..2394a5a 100644 --- a/src/components/forms/search/SearchComponent.jsx +++ b/src/components/forms/search/SearchComponent.jsx @@ -1,6 +1,7 @@ // DeckSearch.js import React, { useEffect, useState } from 'react'; import { + Card, Collapse, Container, Grid, @@ -19,6 +20,8 @@ import { useCardStore, useMode } from '../../../context'; import useLocalStorage from '../../../context/hooks/useLocalStorage'; import { useCardStoreHook } from '../../../context/hooks/useCardStore'; import { useConfiguratorContext } from '../../../context'; +import SimpleCard from '../../../layout/REUSABLE_COMPONENTS/unique/SimpleCard'; +import uniqueTheme from '../../../layout/REUSABLE_COMPONENTS/unique/uniqueTheme'; const SearchComponent = (pageContext) => { const { theme } = useMode(); const itemsPerPage = 12; @@ -44,7 +47,7 @@ const SearchComponent = (pageContext) => { return ( - { boxShadow: 6, }, }} - > + > */} + { onBlur={() => setSearchBarFocused(false)} /> - + + {/* */} - + + + ); diff --git a/src/components/forms/search/SearchResults.jsx b/src/components/forms/search/SearchResults.jsx index c495304..1b10b56 100644 --- a/src/components/forms/search/SearchResults.jsx +++ b/src/components/forms/search/SearchResults.jsx @@ -3,7 +3,7 @@ import { Box, Grid } from '@mui/material'; import useGridItems from '../../../context/hooks/useGridItems'; import usePagination from '../../../context/hooks/usePagination'; import PaginationComponent from '../../../layout/collection/collectionGrids/cards-datatable/PaginationComponent'; -import LoadingIndicator from '../../reusable/indicators/LoadingIndicator'; +import LoadingIndicator from '../../../layout/LoadingIndicator'; import MDBox from '../../../layout/REUSABLE_COMPONENTS/MDBOX'; const SearchResults = ({ diff --git a/src/components/forms/selectors/TimeRangeSelector.jsx b/src/components/forms/selectors/TimeRangeSelector.jsx index 49b66f7..a8bdd34 100644 --- a/src/components/forms/selectors/TimeRangeSelector.jsx +++ b/src/components/forms/selectors/TimeRangeSelector.jsx @@ -8,10 +8,9 @@ import SelectComponent from '../reusable/Select'; import useTimeRange from './useTimeRange'; import MDTypography from '../../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -const TimeRangeSelector = ({ showSnackbar }) => { +const TimeRangeSelector = () => { const { theme } = useMode(); - const { timeRangeOptions, onFormSubmit, control, errors } = - useTimeRange(showSnackbar); + const { timeRangeOptions, onFormSubmit, control, errors } = useTimeRange(); return ( { + // Here you can integrate the logic to handle the submission data, + // for instance, to update the chart based on the selected time range. + console.log('Time Range Selected:', data.timeRange); + }; + const successTitle = 'Success'; + const successDescription = 'Now viewing chart data for {timeRange}'; + const errorDescription = 'Failed to view chart data for {timeRange}'; + + // Using the custom submit handler hook. const onFormSubmit = useSubmitHandler( - onSubmit, - showSnackbar, - 'Success', - 'Now viewing chart data for {timeRange}', - 'Failed to view chart data for {timeRange}' + handleTimeRangeSubmit, + successTitle, + successDescription, + errorDescription ); + // const onFormSubmit = useSubmitHandler( + // onSubmit, + // showSnackbar, + // 'Success', + // 'Now viewing chart data for {timeRange}', + // 'Failed to view chart data for {timeRange}' + // ); // const onFormSubmit = useCallback( // (data) => { // onSubmit(data, 'timeRangeSelector') diff --git a/src/components/grids/deckBuilderGrids/CardsGrid.js b/src/components/grids/deckBuilderGrids/CardsGrid.js index a6e58ad..05f22e8 100644 --- a/src/components/grids/deckBuilderGrids/CardsGrid.js +++ b/src/components/grids/deckBuilderGrids/CardsGrid.js @@ -1,87 +1,3 @@ -// import React, { useMemo, useState } from 'react'; -// import { Grid, Grow, Typography } from '@mui/material'; -// import { useDeckStore } from '../../../context/MAIN_CONTEXT/DeckContext/DeckContext'; -// import SkeletonDeckItem from '../gridItems/SkeletonDeckItem'; -// import GridLayout from '../searchResultsGrids/GridLayout'; -// import StoreItem from '../gridItems/StoreItem'; -// import MDBox from '../../../layout/REUSABLE_COMPONENTS/MDBOX'; - -// const CardsGrid = ({ isLoading }) => { -// const { selectedCards } = useDeckStore(); -// const [error, setError] = useState(''); - -// const flattenSelectedCards = useMemo(() => { -// if (!Array.isArray(selectedCards)) return []; - -// const cardCountMap = new Map(); - -// return selectedCards.reduce((acc, card) => { -// if (!card) return acc; -// const currentCount = cardCountMap.get(card.id) || 0; -// if (currentCount < 3) { -// cardCountMap.set(card.id, currentCount + 1); -// return [...acc, { ...card, uniqueKey: `${card.id}-${currentCount}` }]; -// } -// return acc; -// }, []); -// }, [selectedCards]); - -// if (error) { -// return {error}; -// } - -// const skeletonCount = 12; - -// return ( -// -// {(isLoading -// ? Array.from({ length: skeletonCount }) -// : flattenSelectedCards -// ).map((item, index) => ( -// -// -// -// {isLoading ? ( -// -// ) : ( -// -// )} -// -// -// -// ))} -// -// ); -// }; - -// export default React.memo(CardsGrid); import React, { useMemo } from 'react'; import { Grid, Grow, Typography } from '@mui/material'; import { useDeckStore } from '../../../context/MAIN_CONTEXT/DeckContext/DeckContext'; diff --git a/src/components/grids/deckBuilderGrids/SelectDeckList.jsx b/src/components/grids/deckBuilderGrids/SelectDeckList.jsx index 8da1a5d..90d87af 100644 --- a/src/components/grids/deckBuilderGrids/SelectDeckList.jsx +++ b/src/components/grids/deckBuilderGrids/SelectDeckList.jsx @@ -1,6 +1,6 @@ import React from 'react'; import { Grid, Chip, Typography } from '@mui/material'; -import DeckBuilderIcon from '../../reusable/icons/DeckBuilderIcon'; +import DeckBuilderIcon from '../../../layout/REUSABLE_COMPONENTS/icons/DeckBuilderIcon'; import { useDeckStore } from '../../../context/MAIN_CONTEXT/DeckContext/DeckContext'; import { useMode } from '../../../context'; diff --git a/src/context/MAIN_CONTEXT/AuthContext/authContext.js b/src/context/MAIN_CONTEXT/AuthContext/authContext.js index 82f390c..625cf63 100644 --- a/src/context/MAIN_CONTEXT/AuthContext/authContext.js +++ b/src/context/MAIN_CONTEXT/AuthContext/authContext.js @@ -14,6 +14,7 @@ import { defaultContextValue } from '../../constants'; import { Redirect, useNavigate } from 'react-router-dom'; import useFetchWrapper from '../../hooks/useFetchWrapper'; import jwt_decode from 'jwt-decode'; +import { CircularProgress, Snackbar } from '@mui/material'; export const AuthContext = createContext(defaultContextValue.AUTH_CONTEXT); @@ -28,6 +29,7 @@ export default function AuthProvider({ children }) { 'authUser', 'userId', ]); + const [openSnackbar, setOpenSnackbar] = useState(false); const [user, setUser] = useState({ isLoggedIn: false, accessToken: '', @@ -59,7 +61,7 @@ export default function AuthProvider({ children }) { const [responseMessage, setResponseMessage] = useState(''); const { fetchWrapper } = useFetchWrapper(); - const { logEvent } = useLogger('AuthContext'); + // const { logEvent } = useLogger('AuthContext'); // Helper function to set cookies const setAuthCookies = (data) => { const { accessToken, refreshToken, user } = data; @@ -101,10 +103,18 @@ export default function AuthProvider({ children }) { ); } }; + // const logout = useCallback(() => { + // clearAuthCookies(); + // }, [removeCookie, navigate]); const logout = useCallback(() => { - clearAuthCookies(); - }, [removeCookie, navigate]); - + ['accessToken', 'refreshToken', 'user'].forEach((cookieName) => + removeCookie(cookieName, { path: '/' }) + ); + setOpenSnackbar(true); // Open the snackbar with loading icon + setTimeout(() => { + navigate('/login'); // Redirect to login after the timeout + }, 3000); // Set timeout duration (e.g., 3000 ms = 3 seconds) + }, [navigate, removeCookie]); const login = useCallback( async (username, password) => { await executeAuthAction( @@ -136,7 +146,12 @@ export default function AuthProvider({ children }) { const checkTokenValidity = useCallback(() => { const accessToken = cookies.accessToken; if (!accessToken) { - logout(); + console.info('No access token found, user not logged in.'); + setOpenSnackbar(true); // Notify the user they are being redirected to login + setTimeout(() => { + setOpenSnackbar(false); // Close the notification + navigate('/login'); // Redirect to login after showing the notification + }, 3000); // Adjust the timeout duration as needed return; } @@ -144,7 +159,6 @@ export default function AuthProvider({ children }) { const { exp } = jwt_decode(accessToken); const isTokenExpired = Date.now() >= exp * 1000; if (isTokenExpired) { - console.log('Token is invalid, logging out...'); logout(); } } catch (error) { @@ -157,6 +171,13 @@ export default function AuthProvider({ children }) { useEffect(() => { checkTokenValidity(); }, [checkTokenValidity]); + const renderSnackbar = ( + } + /> + ); const contextValue = useMemo( () => ({ @@ -174,7 +195,9 @@ export default function AuthProvider({ children }) { ); return ( - {children} + + {children} {renderSnackbar} + ); } diff --git a/src/context/MAIN_CONTEXT/CollectionContext/useCollectionManager.jsx b/src/context/MAIN_CONTEXT/CollectionContext/useCollectionManager.jsx index 6dad84f..359f174 100644 --- a/src/context/MAIN_CONTEXT/CollectionContext/useCollectionManager.jsx +++ b/src/context/MAIN_CONTEXT/CollectionContext/useCollectionManager.jsx @@ -213,570 +213,3 @@ const useCollectionManager = () => { }; export default useCollectionManager; -// const validateParams = useCallback( -// (data, expectedTypes, actionName) => { -// let isValid = true; -// const errors = []; - -// expectedTypes.forEach((type, index) => { -// const actualType = Array.isArray(data[index]) -// ? 'array' -// : typeof data[index]; -// if (actualType !== type) { -// isValid = false; -// errors.push(`Param ${index + 1}: Expected ${type}, got ${actualType}`); -// } -// }); - -// if (!isValid) { -// logger.logError(`[${actionName}] Validation errors: `, errors.join('; ')); -// } -// return isValid; -// }, -// [logger] -// ); -// const createNewCollection = useCallback( -// (data) => { -// performAction( -// createApiUrl('create'), -// 'POST', -// data, -// 'createNewCollection', -// { -// paramTypes: ['object'], -// beforeAction: () => console.log('Creating new collection...'), -// afterAction: () => console.log('New collection created.'), -// } -// ); -// }, -// [performAction, createApiUrl] -// ); -// const deleteCollection = useCallback( -// (collectionId) => { -// performAction( -// createApiUrl('delete'), -// 'DELETE', -// { -// collectionId, -// }, -// 'deleteCollection', -// ['string'] -// ); -// }, -// [performAction] -// ); -// const updateCollection = useCallback( -// (collectionId, updatedData) => { -// performAction( -// createApiUrl('update'), -// 'PUT', -// updatedData, -// 'updateCollection', -// ['string', 'object'] -// ); -// }, -// [performAction] -// ); -// const updateCollection = useCallback( -// (collectionId, updatedData) => { -// performAction( -// `/update/${collectionId}`, -// 'PUT', -// updatedData, -// 'updateCollection', -// ['string', 'object'] -// ); -// }, -// [performAction] -// ); -// const updateCardInCollection = useCallback( -// (collectionId, cardId, updatedData) => { -// if ( -// !validateParams( -// [collectionId, cardId, updatedData], -// ['string', 'string', 'object'] -// ) -// ) { -// logger.logError('Invalid parameter types for updateCardInCollection.'); -// return; -// } -// performAction( -// `/updateCard/${collectionId}/${cardId}`, -// 'PUT', -// updatedData, -// 'updateCardInCollection' -// ); -// }, -// [performAction, logger] -// ); -// /** -// * Updates the chart data for a specific collection. -// * @param {string} userId - The ID of the user who owns the collection. -// * @param {string} collectionId - The ID of the collection for which chart data is being updated. -// * @param {Object} chartData - The updated chart data for the collection. The structure of this data depends on how chart data is managed in your application. -// * @returns {Promise} The response from the server. -// */ -// const updateChartDataInCollection = async (collectionId, chartData) => { -// logger.logEvent('updateChartDataInCollection start', { -// collectionId, -// chartData, -// }); -// try { -// const response = await fetchWrapper( -// createApiUrl(`/${collectionId}/updateChartData`), -// 'PUT', -// chartData -// ); -// // const data = handleApiResponse(response, 'updateChartDataInCollection'); -// // updateSelectedCollection(data); - -// // return data; -// } catch (error) { -// logger.logEvent('updateChartDataInCollection error', error); -// throw error; -// } -// }; -// const checkAndUpdateCardPrices = useCallback(async (cards, collection) => { -// const response = await fetchWrapper( -// createApiUrl('/allCollections/automatedPriceUpdate'), -// 'PUT', -// { cards, type: 'automated' } -// ); -// // const data = handleApiResponse(response, 'checkAndUpdateCardPrices'); -// // updateSelectedCollection(data); -// }); -// const createNewCollection = useCallback( -// (data) => { -// if (!validateParams([data], ['object'])) { -// logger.logError('Invalid parameter types for createNewCollection.'); -// return; -// } -// performAction('/create', 'POST', data, 'createNewCollection'); -// }, -// [performAction, logger] -// ); -// const deleteCollection = useCallback( -// (collectionId) => { -// if (!validateParams([collectionId], ['string'])) { -// logger.logError('Invalid parameter types for deleteCollection.'); -// return; -// } -// performAction( -// `/delete/${collectionId}`, -// 'DELETE', -// {}, -// 'deleteCollection' -// ); -// }, -// [performAction, logger] -// ); -// const updateAndSyncCollection = useCallback( -// (collectionId, updatedData) => { -// if (!validateParams([collectionId, updatedData], ['string', 'object'])) { -// logger.logError('Invalid parameter types for updateAndSyncCollection.'); -// return; -// } -// performAction( -// `/update/${collectionId}`, -// 'PUT', -// updatedData, -// 'updateAndSyncCollection' -// ); -// }, -// [performAction, logger] -// ); -// const addCardsToCollection = useCallback( -// (newCards, collection) => { -// console.log('addCardsToCollection', newCards, collection); -// if (!validateParams([[newCards], collection], ['object', 'object'])) { -// logger.logError( -// `Invalid parameter types for addCardsToCollection, showing: ${ -// (typeof newCards, typeof collection) -// }` -// ); -// return; -// } -// performAction( -// '/update', -// 'PUT', -// { cards: newCards }, -// 'addCardsToCollection' -// ); -// }, -// [performAction, logger] -// ); -// // Effect to fetch collections on initial load or userId change -// useEffect(() => { -// fetchCollections(); -// }, [fetchCollections]); -// const { fetchData: fetchCollections, isLoading: isLoadingCollections } = -// useGet({ -// userId, -// isLoggedIn, // This might be omitted if not relevant for the fetch -// hasFetchedFlag: hasFetchedCollections, -// path: '/allCollections', -// setLoadingFlag: setHasFetchedCollections, -// updateStates: (responseData) => { -// // Assuming your updateStates function is defined to update the relevant states -// updateStates(responseData); -// }, -// setError, // Assuming setError is a state setter for storing any fetch errors -// fetchWrapper, // Your custom fetch wrapper function -// createApiUrl, // Function to create the full API URL -// logger, // Your logging function or hook -// }); - -// // To initiate fetching: -// useEffect(() => { -// fetchCollections(); -// }, []); - -// const getAllCollectionsForUser = useCallback(async () => { -// const loadingID = 'fetchCollections'; // Define a unique loading ID -// if (!userId || isLoading(loadingID) || hasFetchedCollections) return; -// try { -// const { data, error } = await fetchWrapper( -// createApiUrl('/allCollections'), -// 'GET', -// null, -// loadingID -// ); -// if (error) { -// throw new Error(error); -// } -// const collectionData = JSON.parse(data); -// console.log('GET ALL COLLECTIONS', collectionData); -// setCollectionData({ data: collectionData }); -// setAllCollections(collectionData?.data || []); -// setSelectedCollection(collectionData?.data?.[0] || DEFAULT_COLLECTION); -// setHasFetchedCollections(true); -// } catch (error) { -// setError(error.message || 'Failed to fetch collections'); -// logger.logEvent( -// 'Error fetching collections getAllCollectionsForUser', -// error.message -// ); -// } -// }, [ -// userId, -// hasFetchedCollections, -// createApiUrl, -// fetchWrapper, -// logger, -// isLoading, -// setError, -// setCollectionData, -// setAllCollections, -// setSelectedCollection, -// setHasFetchedCollections, -// ]); -// useEffect(() => { -// // if (isLoggedIn && userId && !hasFetchedCollections) { -// if (userId && !hasFetchedCollections) { -// getAllCollectionsForUser(); -// } -// }, [selectedCollection, setSelectedCollection]); -// const getAllCollectionsForUser = useCallback(async () => { -// const loadingID = 'fetchCollections'; // Define a unique loading ID -// if (!userId || isLoading(loadingID) || hasFetchedCollections) { -// return; -// } -// try { -// // fetchWrapper should return the data directly or throw an error if unsuccessful -// const responseData = await fetchWrapper( -// createApiUrl('/allCollections'), -// 'GET', -// null, -// loadingID -// ); -// if ( -// (responseData && responseData?.status === 200) || -// responseData?.status === 201 -// ) { -// console.log('SUCCESS: fetching collections'); -// updateStates(responseData); -// } -// } catch (error) { -// console.error(error); -// setError(error.message || 'Failed to fetch collections'); -// logger.logEvent( -// 'Error fetching collections getAllCollectionsForUser', -// error.message -// ); -// } finally { -// setHasFetchedCollections(true); // Prevent re-fetching by updating state -// } -// }, [ -// userId, -// hasFetchedCollections, -// createApiUrl, -// fetchWrapper, -// logger, -// isLoading, -// setError, -// setCollectionData, -// setAllCollections, -// setSelectedCollection, -// setHasFetchedCollections, -// startLoading, // Include startLoading and stopLoading if they are not globally available -// stopLoading, -// ]); -// const createNewCollection = async (coData) => { -// const loadingID = 'createNewCollection'; -// if (!userId || isLoading(loadingID)) return; -// try { -// const { data, error } = await fetchWrapper( -// createApiUrl('/create'), -// 'POST', -// coData, -// loadingID -// ); -// if (error) { -// throw new Error(error); -// } -// updateSelectedCollection(data.data); // Assuming updateSelectedCollection updates context or state -// return data.data; -// } catch (error) { -// setError(error.message || 'Failed to create new collection'); -// logger.logEvent( -// 'Error creating new collection', -// 'createNewCollection', -// error.message -// ); -// throw error; -// } -// }; - -// /** -// * Updates and synchronizes a specific collection for a user. -// * @param {string} userId - The ID of the user who owns the collection. -// * @param {string} collectionId - The ID of the collection to be updated. -// * @param {Object} updatedData - The updated data for the collection. -// * @param {string} updatedData.name - (Optional) New name of the collection. -// * @param {string} updatedData.description - (Optional) New description of the collection. -// * @param {Array} updatedData.cards - (Optional) Array of updated cards. -// * @returns {Promise} The response from the server. -// */ -// const updateAndSyncCollection = async (collectionId, updatedData) => { -// const loadingID = 'updateAndSyncCollection'; -// if (!userId || isLoading(loadingID)) return; -// try { -// const { data, error } = await fetchWrapper( -// createApiUrl(`/${collectionId}`), -// 'PUT', -// updatedData, -// loadingID -// ); -// if (error) { -// throw new Error(error); -// } -// setAllCollections((prev) => -// prev.map((collection) => -// collection._id === collectionId ? data.data : collection -// ) -// ); -// updateSelectedCollection(data.data); // Assuming updateSelectedCollection updates context or state -// return data.data; -// } catch (error) { -// setError(error.message || 'Failed to update collection'); -// logger.logEvent('updateAndSyncCollection error', error); -// throw error; -// } -// }; - -// /** -// * Deletes a specific collection for a user. -// * @param {string} collectionId - The ID of the collection to be deleted. -// * @returns {Promise} The response from the server. -// */ -// const deleteCollection = async (collectionId) => { -// const loadingID = 'deleteCollection'; -// if (!userId || isLoading(loadingID)) return; -// setError(null); -// try { -// const response = await fetchWrapper( -// createApiUrl(`/${collectionId}`), -// 'DELETE', -// { collectionId }, -// loadingID -// ); -// // const data = handleApiResponse(response, 'addCardsToCollection'); - -// setAllCollections((prev) => -// prev.filter((collection) => collection?._id !== collectionId) -// ); -// return response; -// } catch (error) { -// setError(error); -// logger.logEvent('deleteCollection error', error); -// throw error; -// } -// }; -// /** -// * Adds new cards to a specific collection. -// * @param {string} userId - The ID of the user who owns the collection. -// * @param {string} collectionId - The ID of the target collection. -// * @param {Array} cards - Array of card objects to be added. -// * @returns {Promise} The response from the server. -// */ -// const addCardsToCollection = async (cards, collection) => { -// const loadingID = 'addCardsToCollection'; -// if (!userId || isLoading(loadingID)) return; -// setError(null); -// const newCards = []; -// const updatedCards = []; - -// for (const card of cards) { -// const existingCard = collection?.cards?.find((c) => c.id === card.id); - -// if (existingCard) { -// // await updateCardsInCollection(collection._id, [card], 'increment'); -// existingCard.tag = 'incremented'; -// updatedCards.push(existingCard); -// } else { -// card.tag = 'added'; -// newCards.push({ ...card, quantity: 1 }); -// } -// } - -// if (newCards.length > 0) { -// logger.logEvent('addCardsToCollection ADD', { -// newCards, -// collection, -// }); -// const data = await fetchWrapper( -// createApiUrl(`/${collection?._id}/add`), -// 'POST', -// { cards: newCards }, -// loadingID -// ); -// // const data = handleApiResponse(response, 'addCardsToCollection'); -// updateSelectedCollection(data.data); -// } -// if (updatedCards.length > 0) { -// logger.logEvent('addCardsToCollection UPDATE', { -// updatedCards, -// collection, -// }); -// const data = await fetchWrapper( -// createApiUrl(`/${collection._id}/update`), -// 'PUT', -// { cards: updatedCards, type: 'increment' }, -// loadingID -// ); -// // const data = handleApiResponse(response, 'addCardsToCollection'); -// updateSelectedCollection(data.data); -// } -// }; -// /** -// * Removes cards from a specific collection. -// * @param {string} userId - The ID of the user who owns the collection. -// * @param {string} collectionId - The ID of the collection from which cards are being removed. -// * @param {Array} cardIds - Array of card object IDs to be removed. -// * @returns {Promise} The response from the server. -// */ -// const removeCardsFromCollection = async (cards, cardIds, collection) => { -// const loadingID = 'removeCardsFromCollection'; -// if (!userId || isLoading(loadingID)) return; -// setError(null); -// const collectionId = collection._id; -// const cardsToRemove = []; -// const cardsToDecrement = []; -// for (const card of cards) { -// const existingCard = collection?.cards?.find((c) => c.id === card.id); -// if (existingCard) { -// if (existingCard.quantity > 1) { -// existingCard.tag = 'decremented'; -// cardsToDecrement.push(existingCard); -// } else { -// card.tag = 'removed'; -// cardsToRemove.push(card); -// } -// } -// } -// try { -// if (cardsToRemove.length > 0) { -// logger.logEvent('removeCardsFromCollection REMOVE', { -// collectionId, -// cardsToRemove, -// }); -// const response = await fetchWrapper( -// createApiUrl(`/${collectionId}/remove`), -// 'DELETE', -// { cards: cardsToRemove }, -// loadingID -// ); -// const data = handleApiResponse(response, 'removeCardsFromCollection'); -// updateSelectedCollection(data); -// } - -// if (cardsToDecrement.length > 0) { -// logger.logEvent('removeCardsFromCollection DECREMENT', { -// collectionId, -// cardsToDecrement, -// }); -// const response = await fetchWrapper( -// createApiUrl(`/${collectionId}/update`), -// 'PUT', -// { cards: cardsToDecrement, type: 'decrement' }, -// loadingID -// ); -// const data = handleApiResponse(response, 'removeCardsFromCollection'); -// updateSelectedCollection(data); -// } -// } catch (error) { -// setError(error); -// logger.logEvent('removeCardsFromCollection error', error); -// throw error; -// } -// }; -// const getAllCollectionsForUser = useCallback(async () => { -// if (!userId || hasFetchedCollections) return; - -// try { -// const response = await fetchWrapper( -// createApiUrl('/allCollections'), -// 'GET' -// ); -// const data = handleApiResponse(response, 'getAllCollectionsForUser'); -// // console.log('getAllCollectionsForUser', data); -// setCollectionData({ data: data }); -// setAllCollections(data?.data); -// setSelectedCollection(data?.data?.[0]); -// setHasFetchedCollections(true); -// } catch (error) { -// logger.logEvent( -// 'Error fetching collections', -// 'getAllCollectionsForUser', -// error.message -// ); -// } -// }, [ -// createApiUrl, -// fetchWrapper, -// handleApiResponse, -// logger, -// allCollections, -// hasFetchedCollections, -// userId, -// ]); -// Call getAllCollectionsForUser on component mount -// useEffect(() => { -// if (userId && !hasFetchedCollections) { -// getAllCollectionsForUser(); -// } -// }, [userId, hasFetchedCollections, getAllCollectionsForUser]); - -// useEffect(() => { -// if (userId && !hasFetchedCollections) { -// // console.log('getAllCollectionsForUser'); -// getAllCollectionsForUser(); -// } -// }, [userId, getAllCollectionsForUser, hasFetchedCollections]); -// useEffect(() => { -// if (hasFetchedCollections) { -// // console.log('setAllCollections', collectionData?.data?.allCollections); -// setAllCollections(collectionData?.data); -// // updateSelectedCollection(collectionData?.data?.[0]); -// } -// }, [hasFetchedCollections, collectionData]); diff --git a/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx b/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx index 4e20197..bca0246 100644 --- a/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx +++ b/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx @@ -13,13 +13,13 @@ import { CollectionContext } from '../../MAIN_CONTEXT/CollectionContext/Collecti import { defaultContextValue } from '../../constants'; import useLocalStorage from '../../hooks/useLocalStorage'; import useSelectedContext from '../../hooks/useSelectedContext'; +import useSelectedCollection from '../../MAIN_CONTEXT/CollectionContext/useSelectedCollection'; // Create the combined context export const AppContext = createContext(defaultContextValue.APP_CONTEXT); // Create a provider component that combines the contexts export const AppContextProvider = ({ children }) => { - // const [context, setContext] = useState({}); const Deck = useContext(DeckContext); const Cart = useContext(CartContext); const Collection = useContext(CollectionContext); @@ -29,10 +29,34 @@ export const AppContextProvider = ({ children }) => { 'allCardsWithQuantities', [] ); - + const [collectionMetaData, setCollectionMetaData] = useLocalStorage( + 'collectionMetaData', + [] + ); const { selectedCollection, allCollections } = Collection; + const { allIds } = useSelectedCollection(); const { selectedDeck, allDecks } = Deck; const { cartData } = Cart; + + // Function to compile metadata including totalPrice for collections + const compileCollectionMetaData = useCallback(() => { + const metaData = { + metaData: { + totalPrice: allCollections?.reduce( + (total, collection) => total + collection.totalPrice, + 0 + ), + numCollections: allIds?.length || 0, + }, + }; + + setCollectionMetaData(metaData); + }, []); + + useEffect(() => { + compileCollectionMetaData(); + }, [compileCollectionMetaData]); // Re-calculate metadata when allCollections changes + const isCardInContext = useCallback( (card) => { const cardsList = { @@ -99,8 +123,16 @@ export const AppContextProvider = ({ children }) => { getCardQuantities: compileCardsWithQuantities, isCardInContext, checkIfCardIsInContext: isCardInContext, + collectionMetaData, }), - [Deck, Cart, Collection, isCardInContext] // Include cardsWithQuantities here + [ + Deck, + Cart, + Collection, + isCardInContext, + collectionMetaData, + // cardsWithQuantities, + ] // Include cardsWithQuantities here ); return ( diff --git a/src/context/UTILITIES_CONTEXT/FormContext/FormContext.jsx b/src/context/UTILITIES_CONTEXT/FormContext/FormContext.jsx index 3a697cc..cba3d71 100644 --- a/src/context/UTILITIES_CONTEXT/FormContext/FormContext.jsx +++ b/src/context/UTILITIES_CONTEXT/FormContext/FormContext.jsx @@ -112,13 +112,20 @@ export const FormProvider = ({ children }) => { ), loginForm: (formData) => login(formData.username, formData.password), updateUserDataForm: (formData) => console.log(formData), + addCollectionForm: (formData, additionalData) => + createNewCollection(formData, additionalData), updateCollectionForm: (formData, additionalData) => updateAndSyncCollection(additionalData, formData), createCollectionForm: (formData, additionalData) => createNewCollection(additionalData, formData), - updateDeckForm: (formData, additionalData) => updateDeckDetails(formData), - addDeckForm: (formData, additionalData) => console.log(formData), - searchForm: (formData, additionalData) => setSearchSettings(formData), + updateDeckForm: (formData, additionalData) => + updateDeckDetails(formData, additionalData), + addDeckForm: (formData, additionalData) => + console.log(formData, additionalData), + searchForm: (formData, additionalData) => + setSearchSettings(formData, additionalData), + ollectionSearchForm: (formData, additionalData) => + console.log(formData, additionalData), timeRangeSelector: (formData, additionalData) => handleTimeRangeChange(formData), searchSettingsSelector: (formData, additionalData) => @@ -129,7 +136,6 @@ export const FormProvider = ({ children }) => { }, authSwitch: (formData) => { console.log('Auth Switch Form Data:', formData); - toggleAuthMode(); }, }; @@ -159,20 +165,6 @@ export const FormProvider = ({ children }) => { useEffect(() => { setFormSchema(currentSchemaKey); }, [currentSchemaKey, setFormSchema]); - // const setFormSchema = useCallback( - // (formId) => { - // const schema = formSchemas[formId]; - // const defaultValues = getDefaultValuesFromSchema(schema); - // methods.reset({ ...defaultValues }); // Reset form with new default values - // methods.clearErrors(); // Clear any existing errors - // methods.setValue('formId', formId); // Optionally set formId as a form value - // }, - // [methods] - // ); - // useEffect(() => { - // setFormSchema(initialFormKey); // Initialize form with the first schema - // }, [setFormSchema, initialFormKey]); - const onChange = (formData, currentSchemaKey) => { console.log('Form data changed:', formData, currentSchemaKey); const validation = handleZodValidation( @@ -262,7 +254,7 @@ export const FormProvider = ({ children }) => { isFormDataLoading: isFormDataLoading, currentSchemaKey, currentForm: currentSchemaKey, - + getValues: methods.getValues, handleTimeRangeChange, handleSearchTermChange, handleFieldChange, diff --git a/src/context/UTILITIES_CONTEXT/FormContext/schemas.jsx b/src/context/UTILITIES_CONTEXT/FormContext/schemas.jsx index 523500e..e7ea499 100644 --- a/src/context/UTILITIES_CONTEXT/FormContext/schemas.jsx +++ b/src/context/UTILITIES_CONTEXT/FormContext/schemas.jsx @@ -27,7 +27,6 @@ const tagConstraint = z.array(z.string()); const colorConstraint = z.enum(['red', 'blue', 'green', 'yellow'], { message: 'Invalid color', }); - const signupForm = z.object({ firstName: GenericStringConstraint, lastName: GenericStringConstraint, @@ -89,6 +88,9 @@ const searchForm = z.object({ level: z.string().optional(), }), }); +const collectionSearchForm = z.object({ + searchTerm: z.string().min(1, { message: 'Search term is required' }), +}); // Customer Info Fields Schema const customerInfoForm = z.object({ firstName: nameConstraint, @@ -122,23 +124,6 @@ const customerInfoForm = z.object({ // const timeRangeSchema = z.object({ // timeRange: z.enum(['24hr', '7d', '30d', '90d', '180d', '270d', '365d']), // }); -const timeRangeOptionSchema = z.object({ - id: z.string( - 'Invalid time range ID. Please select a valid time range from the list.' - ), - value: z.string(), - name: z.string(), - data: z.array( - z.object({ - x: z.number(), - y: z.number(), - }) - ), -}); - -// const timeRangeSchema = z.object({ -// timeRange: timeRangeOptionSchema, -// }); const timeRangeSelectorSchema = z.object({ timeRange: z.string().nonempty({ message: 'You must select a time range.', @@ -254,7 +239,7 @@ export const formSchemas = { loginForm, rememberMeForm: rememberMeFormSchema, authSwitch: authSwitchSchema, - + collectionSearchForm, updateUserDataForm, addCollectionForm, updateCollectionForm, @@ -349,6 +334,9 @@ export const defaultValues = { level: '', }, }, + collectionSearchForm: { + searchTerm: '', + }, customerInfoForm: { firstName: '', lastName: '', diff --git a/src/context/UTILITIES_CONTEXT/PageContext/PageContext.jsx b/src/context/UTILITIES_CONTEXT/PageContext/PageContext.jsx index a9748f3..25c6aba 100644 --- a/src/context/UTILITIES_CONTEXT/PageContext/PageContext.jsx +++ b/src/context/UTILITIES_CONTEXT/PageContext/PageContext.jsx @@ -5,8 +5,8 @@ import React, { useEffect, useMemo, } from 'react'; -import LoadingIndicator from '../../../components/reusable/indicators/LoadingIndicator'; -import ErrorIndicator from '../../../components/reusable/indicators/ErrorIndicator'; +import LoadingIndicator from '../../../layout/LoadingIndicator'; +import ErrorIndicator from '../../../layout/ErrorIndicator'; import SplashPage2 from '../../../layout/REUSABLE_COMPONENTS/SplashPage2'; // import useSnackBar from '../../hooks/useSnackBar'; import { defaultContextValue } from '../../constants'; @@ -24,13 +24,6 @@ export const PageProvider = ({ children }) => { error, clearLoading, } = useLoading(); - // const { snackbar, handleSnackBar, handleCloseSnackbar } = useSnackBar(); - - // const handleLoadingCompletion = () => { - // if (!isAnyLoading()) { - // handleSnackBar('Loading completed', 'success'); - // } - // }; const returnDisplay = () => { if (error) { return ; @@ -64,86 +57,9 @@ export const PageProvider = ({ children }) => { ] ); - // const { snackbar, handleSnackBar, handleCloseSnackbar } = useSnackBar(); - // // const [activelyLoading, setActivelyLoading] = useState(false); // [false, setActivelyLoading - // const [loadingStatus, setLoadingStatus] = useState({ - // isLoading: false, - // isDataLoading: false, - // isFormDataLoading: false, - // isPageLoading: false, - // loadingTimeoutExpired: false, - // error: null, - // loadingType: '', - // }); - // useEffect(() => { - // const isCompleted = Object.values(loadingStatus).every((status) => !status); - // if (isCompleted) { - // handleSnackBar( - // `Loading ${loadingStatus.loadingType} completed`, - // 'success' - // ); - // } - // }, [loadingStatus, handleSnackBar]); - // const setLoading = (type, status) => { - // setLoadingStatus((prevStatus) => ({ - // ...prevStatus, - // [type]: status, - // loadingType: status ? type : '', - // })); - // }; - // const returnDisplay = () => { - // if (loadingStatus.error) { - // return ; - // } - // switch (loadingStatus.loadingType) { - // case 'isLoading': - // case 'isDataLoading': - // case 'isFormDataLoading': - // return ; - // case 'isPageLoading': - // return ; - // default: - // return null; - // } - // }; - - // const contextValue = useMemo( - // () => ({ - // loadingStatus, - // error: loadingStatus.error, - // setActivelyLoading: (status) => setLoading('isLoading', status), - // returnDisplay, - // setError: (error) => setLoadingStatus((prev) => ({ ...prev, error })), - // setPageError: (error) => - // setLoadingStatus((prev) => ({ ...prev, error, isPageLoading: false })), - // setIsLoading: (status) => setLoading('isLoading', status), - // setIsDataLoading: (status) => setLoading('isDataLoading', status), - // setIsFormDataLoading: (status) => setLoading('isFormDataLoading', status), - // setIsPageLoading: (status) => setLoading('isPageLoading', status), - // setLoadingTimeoutExpired: (status) => - // setLoadingStatus((prev) => ({ - // ...prev, - // loadingTimeoutExpired: status, - // })), - // handleLoadingTimeout: () => - // setLoadingStatus((prev) => ({ - // ...prev, - // loadingTimeoutExpired: true, - // isPageLoading: false, - // })), - // }), - // [loadingStatus] - // ); - return ( {children}{' '} - {/* */} ); }; diff --git a/src/context/UTILITIES_CONTEXT/SideBarContext/SideBarProvider.jsx b/src/context/UTILITIES_CONTEXT/SideBarContext/SideBarProvider.jsx index a074ec5..26b91ba 100644 --- a/src/context/UTILITIES_CONTEXT/SideBarContext/SideBarProvider.jsx +++ b/src/context/UTILITIES_CONTEXT/SideBarContext/SideBarProvider.jsx @@ -5,7 +5,7 @@ import CollectionsIcon from '@mui/icons-material/Collections'; import StoreIcon from '@mui/icons-material/Store'; import ShoppingBasketIcon from '@mui/icons-material/ShoppingBasket'; import PersonIcon from '@mui/icons-material/Person'; -import DeckBuilderIcon from '../../../components/reusable/icons/DeckBuilderIcon'; +import DeckBuilderIcon from '../../../layout/REUSABLE_COMPONENTS/icons/DeckBuilderIcon'; const SidebarContext = createContext(); export const SidebarProvider = ({ children }) => { diff --git a/src/context/UTILITIES_CONTEXT/SnackbarContext/SnackbarContext.jsx b/src/context/UTILITIES_CONTEXT/SnackbarContext/SnackbarContext.jsx deleted file mode 100644 index 3492e2a..0000000 --- a/src/context/UTILITIES_CONTEXT/SnackbarContext/SnackbarContext.jsx +++ /dev/null @@ -1,49 +0,0 @@ -// // CustomSnackbarContext.js -// import React, { createContext, useContext } from 'react'; -// import { useSnackbar } from 'notistack'; -// import { Box, CircularProgress, Typography } from '@mui/material'; - -// // Create the context -// const CustomSnackbarContext = createContext(); - -// // Define a provider component -// export const SnackbarContextProvider = ({ children }) => { -// const { enqueueSnackbar } = useSnackbar(); - -// // Define the showSnackbar function -// const showSnackbar = (title, subTitle, options = {}) => { -// const content = ( -// -// {title} -// -// {subTitle} -// -// -// ); - -// enqueueSnackbar(content, { -// ...options, -// action: options.persist -// ? (key) => -// : undefined, -// }); -// }; - -// // Provide the showSnackbar function to children -// return ( -// -// {children} -// -// ); -// }; - -// // Custom hook to use the context -// export const useSnackbarContext = () => { -// const context = useContext(CustomSnackbarContext); -// if (context === undefined) { -// throw new Error( -// 'useCustomSnackbar must be used within a CustomSnackbarProvider' -// ); -// } -// return context; -// }; diff --git a/src/context/UTILITIES_CONTEXT/VisibilityContext.jsx b/src/context/UTILITIES_CONTEXT/VisibilityContext.jsx index 083acc1..ce956a9 100644 --- a/src/context/UTILITIES_CONTEXT/VisibilityContext.jsx +++ b/src/context/UTILITIES_CONTEXT/VisibilityContext.jsx @@ -6,7 +6,7 @@ const VisibilityContext = createContext(); export const useVisibilityContext = () => useContext(VisibilityContext); export const VisibilityProvider = ({ children }) => { - const [isCollectionVisible, setCollectionVisibility] = useState(true); + const [isCollectionVisible, setCollectionVisibility] = useState(false); const [dialogStates, setDialogStates] = useState({ isAddCollectionDialogOpen: false, isSelectionErrorDialogOpen: false, diff --git a/src/context/hooks/index.jsx b/src/context/hooks/index.jsx index 8eeba11..db26ec4 100644 --- a/src/context/hooks/index.jsx +++ b/src/context/hooks/index.jsx @@ -145,7 +145,7 @@ const [isToggled, toggle] = useToggle(); * Description: Manages snack bar notifications in the application. * Useful for showing temporary messages or alerts to the user. */ -const { openSnackBar, closeSnackBar } = useSnackBar(); +// const { openSnackBar, closeSnackBar } = useSnackBar(); /** * Hook: useVisible diff --git a/src/context/hooks/style-hooks/useResponsiveStyles.jsx b/src/context/hooks/style-hooks/useResponsiveStyles.jsx index 5b2e9ab..130e55a 100644 --- a/src/context/hooks/style-hooks/useResponsiveStyles.jsx +++ b/src/context/hooks/style-hooks/useResponsiveStyles.jsx @@ -1,7 +1,7 @@ import { useMediaQuery } from '@mui/material'; -import DeckOfCardsIcon from '../../../components/reusable/icons/DeckOfCardsIcon'; -import MoneyIcon from '../../../components/reusable/icons/MoneyIcon'; -import ChartsIcon from '../../../components/reusable/icons/ChartsIcon'; +import DeckOfCardsIcon from '../../../layout/REUSABLE_COMPONENTS/icons/DeckOfCardsIcon'; +import MoneyIcon from '../../../layout/REUSABLE_COMPONENTS/icons/MoneyIcon'; +import ChartsIcon from '../../../layout/REUSABLE_COMPONENTS/icons/ChartsIcon'; const useResponsiveStyles = (theme) => { const isXSmall = useMediaQuery(theme.breakpoints.down('xs')); diff --git a/src/context/hooks/useCardActions.jsx b/src/context/hooks/useCardActions.jsx index 333029f..6706f62 100644 --- a/src/context/hooks/useCardActions.jsx +++ b/src/context/hooks/useCardActions.jsx @@ -1,6 +1,5 @@ import { useCallback, useState } from 'react'; import useCounter from './useCounter'; -import useSnackBar from './useSnackBar'; import useDialog from './useDialog'; export const useCardActions = ( @@ -18,7 +17,6 @@ export const useCardActions = ( onFailure, page ) => { - const { handleSnackBar } = useSnackBar(); // Destructure handleSnackBar from useSnackBar hook const { openDialog } = useDialog(); // Destructure openDialog from useDialog hook const [isDialogOpen, setIsDialogOpen] = useState(false); @@ -36,26 +34,11 @@ export const useCardActions = ( const performAction = useCallback( (action) => { - // if (context === 'Collection' && !selectedCollection) { - // // Show alert and open dialog if no collection is selected - // handleSnackBar('Please select a collection.', 'error'); // Use handleSnackBar to show a snackbar - // openDialog('Collection'); // Open the 'Collection' dialog - // return; - // } - // if (context === 'Deck' && !selectedDeck) { - // // Show alert and open dialog if no deck is selected - // handleSnackBar('Please select a deck.', 'error'); // Use handleSnackBar to show a snackbar - // openDialog('Deck'); // Open the 'Deck' dialog - // return; - // } - // Increment or decrement based on the action const updateQuantity = (actionType) => { actionType === 'add' ? increment(card.id) : decrement(card.id); }; const array = placeObjectInArray(data); console.log('DATA =>=>=> ', data); - - // Action functions for different contexts const actionFunctions = { Collection: { add: () => { @@ -119,7 +102,6 @@ export const useCardActions = ( selectedCollection, selectedDeck, onSuccess, - handleSnackBar, ] ); diff --git a/src/context/hooks/useCustomSnackbar.jsx b/src/context/hooks/useCustomSnackbar.jsx index b29f8e9..a7329c8 100644 --- a/src/context/hooks/useCustomSnackbar.jsx +++ b/src/context/hooks/useCustomSnackbar.jsx @@ -1,31 +1,29 @@ -// useCustomSnackbar.js -import React from 'react'; -import { useSnackbar } from 'notistack'; -import { Box, CircularProgress, Typography } from '@mui/material'; +// // useCustomSnackbar.js +// import React from 'react'; +// import { useSnackbar } from 'notistack'; +// import { Box, CircularProgress, Typography } from '@mui/material'; -const useCustomSnackbar = () => { - const { enqueueSnackbar } = useSnackbar(); +// const useCustomSnackbar = () => { +// const { enqueueSnackbar } = useSnackbar(); +// const showSnackbar = (title, subTitle, options = {}) => { +// const content = ( +// +// {title} +// +// {subTitle} +// +// +// ); - // Define the showSnackbar function - const showSnackbar = (title, subTitle, options = {}) => { - const content = ( - - {title} - - {subTitle} - - - ); +// enqueueSnackbar(content, { +// ...options, +// action: options.persist +// ? (key) => +// : undefined, +// }); +// }; - enqueueSnackbar(content, { - ...options, - action: options.persist - ? (key) => - : undefined, - }); - }; +// return showSnackbar; +// }; - return showSnackbar; -}; - -export default useCustomSnackbar; +// export default useCustomSnackbar; diff --git a/src/context/hooks/useFetchWrapper.jsx b/src/context/hooks/useFetchWrapper.jsx index ce889f1..c6878e4 100644 --- a/src/context/hooks/useFetchWrapper.jsx +++ b/src/context/hooks/useFetchWrapper.jsx @@ -1,71 +1,26 @@ -// export default useFetchWrapper; -import { useState, useCallback, useContext } from 'react'; +import { useState, useCallback } from 'react'; import useLogger from './useLogger'; import useLocalStorage from './useLocalStorage'; import { useLoading } from './useLoading'; -// import { useSnackbar } from 'notistack'; -import CircularProgress from '@mui/material/CircularProgress'; -import { Box, Typography } from '@mui/material'; -import useCustomSnackbar from './useCustomSnackbar'; +import useSnackbarManager from './useSnackbarManager'; const useFetchWrapper = () => { - const [status, setStatus] = useState('idle'); // 'idle', 'loading', 'success', 'error' + const [status, setStatus] = useState('idle'); const [data, setData] = useState(null); const [responseCache, setResponseCache] = useLocalStorage('apiResponses', {}); const [error, setError] = useState(null); const { logEvent } = useLogger('useFetchWrapper'); const { startLoading, stopLoading, isLoading } = useLoading(); - // const { enqueueSnackbar, closeSnackbar } = useSnackbar(); + const { showSuccess, showInfo, showError } = useSnackbarManager(); const fetchWrapper = useCallback( async (url, method = 'GET', body = null, loadingID) => { - // const showSnackbar = useCustomSnackbar(); - setStatus('loading'); startLoading(loadingID); - // const snackbarContent = (message, subMessage) => ( - // - // {message} - // - // {subMessage} - // - // - // ); - // // Show loading snackbar - // const snackbarKey = enqueueSnackbar( - // snackbarContent( - // 'Loading...', - // `Please wait while we fetch your ${loadingID} data.` - // ), - // { - // variant: 'info', - // persist: true, - // action: (key) => , - // } - // ); - // const snackbarSuccessOptions = { - // variant: 'success', - // persist: true, - // // action: (key) => , - // }; - // const snackbarInfoOptions = { - // variant: 'info', - // persist: true, - // }; - // CustomSnackbar.showSnackbar( - // 'Loading...', - // 'Please wait while we fetch your data.', - // snackbarInfoOptions - // ); - // showSnackbar( - // 'Loading...', - // `Please wait while we fetch your ${loadingID} data.`, - // { - // variant: 'info', - // persist: true, - // action: (key) => , - // } - // ); + + // Showing loading snackbar + const loadingSnackbar = showInfo('Loading', loadingID); + try { const headers = { 'Content-Type': 'application/json' }; const options = { @@ -85,6 +40,7 @@ const useFetchWrapper = () => { if (!response.ok) { throw new Error(`An error occurred: ${response.statusText}`); } + setStatus('success'); setData(responseData); setResponseCache((prevCache) => ({ @@ -92,28 +48,22 @@ const useFetchWrapper = () => { [loadingID]: responseData, })); - // showSnackbar( - // 'Success!', - // `Your ${loadingID} data has been fetched successfully.`, - // { - // variant: 'success', - // persist: true, - // action: (key) => , - // } - // ); + // Showing success snackbar + showSuccess(`Your ${loadingID} data has been fetched successfully.`); + return responseData; } catch (error) { setError(error.toString()); setStatus('error'); logEvent('fetch error', { url, error: error.toString() }); - // showSnackbar('Error', error.toString(), { - // variant: 'error', - // }); + // Showing error snackbar + showError(`Error fetching ${loadingID}: ${error.toString()}`); } finally { stopLoading(loadingID); - // closeSnackbar(snackbarKey); // Close the loading snackbar + // Closing loading snackbar + // closeSnackbar(loadingSnackbar); } }, [ @@ -121,7 +71,9 @@ const useFetchWrapper = () => { startLoading, stopLoading, logEvent, - // enqueueSnackbar, + showSuccess, + showInfo, + showError, // closeSnackbar, ] ); diff --git a/src/context/hooks/useLocalStorage.jsx b/src/context/hooks/useLocalStorage.jsx index 621f3ca..e8a6200 100644 --- a/src/context/hooks/useLocalStorage.jsx +++ b/src/context/hooks/useLocalStorage.jsx @@ -1,5 +1,13 @@ import { useState, useEffect, useRef } from 'react'; - +// This function tries to parse JSON and provides a fallback if parsing fails +function safeJsonParse(value) { + try { + return value ? JSON.parse(value) : null; + } catch (e) { + console.error('Error reading localStorage key:', e); + return null; + } +} function useLocalStorage(key, initialValue) { const [storedValue, setStoredValue] = useState(() => { if (typeof window === 'undefined') { @@ -8,7 +16,7 @@ function useLocalStorage(key, initialValue) { try { const item = window.localStorage.getItem(key); - return item ? JSON.parse(item) : initialValue; + return item ? safeJsonParse(item) : initialValue; } catch (error) { console.error(`Error reading localStorage key "${key}":`, error); return initialValue; @@ -52,8 +60,9 @@ function useLocalStorage(key, initialValue) { const valueToStore = value instanceof Function ? value(storedValue) : value; - window.localStorage.setItem(key, JSON.stringify(valueToStore)); + // window.localStorage.setItem(key, JSON.stringify(valueToStore)); setStoredValue(valueToStore); + window.localStorage.setItem(key, JSON.stringify(valueToStore)); // Optionally, for cross-tab communication, you might want to trigger a storage event manually window.dispatchEvent( diff --git a/src/context/hooks/usePagination.jsx b/src/context/hooks/usePagination.jsx index 5102d02..5695cae 100644 --- a/src/context/hooks/usePagination.jsx +++ b/src/context/hooks/usePagination.jsx @@ -2,25 +2,15 @@ import { useMemo, useState } from 'react'; const usePagination = (items, defaultPageSize) => { const [currentPage, setCurrentPage] = useState(1); - - // Setup for react-table pagination - // Assumes items is the total dataset you want to paginate over const data = useMemo(() => items, [items]); - - // Pagination settings for react-table const initialState = useMemo( () => ({ pageIndex: 0, - pageSize: defaultPageSize || 10, // Default page size + pageSize: defaultPageSize || 10, }), [defaultPageSize] ); - // The react-table hook will manage the pageIndex and pageSize, - // so you don't need to manage these states manually. - // You would pass initialState to the useTable hook along with 'data' and 'columns' - - // Calculate the total pages const pageCount = useMemo( () => Math.ceil(items.length / initialState.pageSize), [items.length, initialState.pageSize] @@ -32,13 +22,6 @@ const usePagination = (items, defaultPageSize) => { return data.slice(start, end); }, [data, currentPage, defaultPageSize]); - // You can still create a custom pagination component if you like, - // but you would control it using the state and actions provided by react-table. - - // Note: This example does not include the implementation of fetching data based on the current page, - // as it assumes 'items' contains the full dataset. If you're fetching data from a server, - // you would need to integrate that logic here, using the pageIndex and pageSize from react-table's state. - return { data, initialState, @@ -46,87 +29,7 @@ const usePagination = (items, defaultPageSize) => { paginatedData, currentPage, setCurrentPage, - // No need to return handlers like handleChangePage or handleChangeRowsPerPage - // as react-table's usePagination hook provides these functionalities. }; }; export default usePagination; - -// import { useState, useMemo } from 'react'; -// import CustomPagination from '../../components/reusable/CustomPagination'; - -// const usePagination = (items, itemsPerPage, totalCount) => { -// const [page, setPage] = useState(0); -// const [rowsPerPageOptions] = useState([ -// 5, -// 10, -// 25, -// { label: 'All', value: -1 }, -// ]); -// const [rowsPerPage, setRowsPerPage] = useState( -// itemsPerPage || rowsPerPageOptions[0] -// ); -// const [colsPerPage, setColsPerPage] = useState(1); - -// const emptyRows = useMemo( -// () => Math.max(0, (1 + page) * rowsPerPage - (items?.length || 0)), -// [page, rowsPerPage, items] -// ); - -// const handleChangePage = (newPage) => setPage(newPage); - -// const handleChangeRowsPerPage = (event) => { -// setRowsPerPage(parseInt(event.target.value, 10)); -// setPage(0); -// }; - -// const handleChangeColsPerPage = (event) => { -// setColsPerPage(parseInt(event.target.value, 10)); -// }; - -// const paginatedItems = useMemo(() => { -// const startIndex = page * rowsPerPage; -// const endIndex = -// rowsPerPage === -1 ? items?.length : startIndex + rowsPerPage; -// return items?.slice(startIndex, endIndex); -// }, [page, rowsPerPage, items]); -// const PaginationComponent = ( -// setPage(value)} -// /> -// ); - -// // Additional pagination actions -// const goToFirstPage = () => setPage(0); -// const goToLastPage = () => -// setPage(Math.max(0, Math.ceil(items?.length / rowsPerPage) - 1)); -// const goToNextPage = () => -// setPage((current) => -// Math.min(current + 1, Math.ceil(items?.length / rowsPerPage) - 1) -// ); -// const goToPreviousPage = () => setPage((current) => Math.max(current - 1, 0)); - -// return { -// page, -// rowsPerPage, -// colsPerPage, -// rowsPerPageOptions, -// emptyRows, -// paginatedItems, -// PaginationComponent, - -// handleChangePage, -// handleChangeRowsPerPage, -// handleChangeColsPerPage, -// goToFirstPage, -// goToLastPage, -// goToNextPage, -// goToPreviousPage, -// }; -// }; - -// export default usePagination; diff --git a/src/context/hooks/useSnackBar.jsx b/src/context/hooks/useSnackBar.jsx deleted file mode 100644 index 9fe2c6c..0000000 --- a/src/context/hooks/useSnackBar.jsx +++ /dev/null @@ -1,79 +0,0 @@ -// import { IconButton } from '@mui/material'; -// import { useSnackbar } from 'notistack'; -// import { useState, useCallback, useRef, useEffect } from 'react'; -// import CloseIcon from '@mui/icons-material/Close'; -// const useSnackBar = () => { -// const { enqueueSnackbar, closeSnackbar } = useSnackbar(); -// const defaultOptions = { -// variant: 'info', -// autoHideDuration: 6000, -// }; -// const isMountedRef = useRef(false); - -// useEffect(() => { -// isMountedRef.current = true; -// return () => { -// isMountedRef.current = false; -// }; -// }, []); -// const handleSnackBar = useCallback( -// (message, options = defaultOptions) => { -// // Enqueue a new snackbar using notistack's enqueueSnackbar function -// // `options` can include severity as `variant` and custom `duration` as `autoHideDuration` -// // const { title, description } = message; -// const { variant, autoHideDuration } = options; -// if (open && message.title) { -// enqueueSnackbar(message, { -// message, -// variant, -// action: (key) => ( -// closeSnackbar(key)}> -// -// -// ), -// }); -// } -// }, -// [enqueueSnackbar] -// ); - -// // const [snackbar, setSnackbar] = useState({ -// // open: false, -// // message: '', -// // severity: 'info', -// // duration: 6000, -// // }); -// // const queueRef = useRef([]); - -// // const showNextSnackbar = useCallback(() => { -// // if (queueRef.current.length > 0 && isMountedRef.current) { -// // const nextSnackbar = queueRef.current.shift(); -// // setSnackbar({ ...nextSnackbar, open: true }); -// // } -// // }, []); - -// // const handleSnackBar = useCallback( -// // (message, severity = 'info', duration = 6000) => { -// // queueRef.current.push({ message, severity, duration }); -// // if (!snackbar.open && isMountedRef.current) { -// // showNextSnackbar(); -// // } -// // }, -// // [snackbar.open, showNextSnackbar] -// // ); - -// const handleCloseSnackbar = useCallback(() => { -// if (isMountedRef.current) { -// closeSnackbar(); -// // setSnackbar((prevSnackbar) => ({ -// // ...prevSnackbar, -// // open: false, -// // })); -// // showNextSnackbar(); -// } -// }, [closeSnackbar]); - -// return { handleSnackBar, handleCloseSnackbar }; -// }; - -// export default useSnackBar; diff --git a/src/context/hooks/useSnackbarManager.jsx b/src/context/hooks/useSnackbarManager.jsx new file mode 100644 index 0000000..01c7915 --- /dev/null +++ b/src/context/hooks/useSnackbarManager.jsx @@ -0,0 +1,59 @@ +// useSnackbarManager.js +import { useSnackbar } from 'notistack'; + +export default function useSnackbarManager() { + const { enqueueSnackbar } = useSnackbar(); + + const showSuccess = (message) => { + enqueueSnackbar(message, { + variant: 'success', + anchorOrigin: { + vertical: 'top', + horizontal: 'right', + }, + }); + }; + + const showInfo = (message) => { + enqueueSnackbar(message, { + variant: 'info', + anchorOrigin: { + vertical: 'top', + horizontal: 'right', + }, + }); + }; + + const showWarning = (message) => { + enqueueSnackbar(message, { + variant: 'warning', + anchorOrigin: { + vertical: 'top', + horizontal: 'right', + }, + }); + }; + + const showError = (message) => { + enqueueSnackbar(message, { + variant: 'error', + anchorOrigin: { + vertical: 'top', + horizontal: 'right', + }, + }); + }; + + // More examples: + const showCustom = (message, variant = 'default') => { + enqueueSnackbar(message, { + variant: variant, // could be default, error, success, warning, info, etc. + anchorOrigin: { + vertical: 'bottom', + horizontal: 'left', + }, + }); + }; + + return { showSuccess, showInfo, showWarning, showError, showCustom }; +} diff --git a/src/data/baseMenuItems.jsx b/src/data/baseMenuItems.jsx new file mode 100644 index 0000000..c9f8df2 --- /dev/null +++ b/src/data/baseMenuItems.jsx @@ -0,0 +1,65 @@ +// menuItemsData.js + +import React from 'react'; +import { + Home as HomeIcon, + Store as StoreIcon, + ShoppingCart as CartIcon, + Assessment as CollectionIcon, + Person as ProfileIcon, +} from '@mui/icons-material'; +import DeckBuilderIcon from '../layout/REUSABLE_COMPONENTS/icons/DeckBuilderIcon'; +import { Badge } from '@mui/material'; + +export const baseMenuItems = (cartCardQuantity, iconColor) => [ + { name: 'Home', icon: , to: '/home', requiresLogin: false }, + { + name: 'Deck Builder', + icon: , + to: '/deckbuilder', + requiresLogin: false, + }, + { + name: 'Collection', + icon: , + to: '/collection', + requiresLogin: true, + }, + { + name: 'Store', + icon: , + to: '/store', + requiresLogin: true, + }, + { + name: 'Cart', + icon: ( + + + + ), + to: '/cart', + requiresLogin: true, + }, + { + name: 'Profile', + icon: , + to: '/profile', + requiresLogin: false, + }, +]; diff --git a/src/layout/store/data/collectionPortfolioData.jsx b/src/data/collectionPortfolioData.jsx similarity index 100% rename from src/layout/store/data/collectionPortfolioData.jsx rename to src/data/collectionPortfolioData.jsx diff --git a/src/layout/store/data/searchData.jsx b/src/data/searchData.jsx similarity index 94% rename from src/layout/store/data/searchData.jsx rename to src/data/searchData.jsx index d7e77de..a74308b 100644 --- a/src/layout/store/data/searchData.jsx +++ b/src/data/searchData.jsx @@ -2,7 +2,7 @@ import Icon from '@mui/material/Icon'; // Images import MDTypography from '../MDTYPOGRAPHY/MDTypography'; import React from 'react'; -import StoreItem from '../../../components/grids/gridItems/StoreItem'; +import StoreItem from '../components/grids/gridItems/StoreItem'; import LoadingIndicator from '../../../components/reusable/indicators/LoadingIndicator'; export default function prepareTableData(selectedCards) { diff --git a/src/components/reusable/indicators/ErrorIndicator.js b/src/layout/ErrorIndicator.js similarity index 97% rename from src/components/reusable/indicators/ErrorIndicator.js rename to src/layout/ErrorIndicator.js index 566d59e..7592742 100644 --- a/src/components/reusable/indicators/ErrorIndicator.js +++ b/src/layout/ErrorIndicator.js @@ -5,7 +5,7 @@ import Typography from '@mui/material/Typography'; import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline'; import Container from '@mui/material/Container'; import { Alert, AlertTitle } from '@mui/material'; -import { useMode } from '../../../context'; +import { useMode } from '../context'; // Styled components with theme utilization const StyledContainer = styled(Container)(({ theme }) => ({ diff --git a/src/components/reusable/indicators/LoadingIndicator.js b/src/layout/LoadingIndicator.js similarity index 100% rename from src/components/reusable/indicators/LoadingIndicator.js rename to src/layout/LoadingIndicator.js diff --git a/src/components/reusable/PrivateRoute.jsx b/src/layout/PrivateRoute.jsx similarity index 90% rename from src/components/reusable/PrivateRoute.jsx rename to src/layout/PrivateRoute.jsx index 7953c3d..c235a9b 100644 --- a/src/components/reusable/PrivateRoute.jsx +++ b/src/layout/PrivateRoute.jsx @@ -1,6 +1,6 @@ import React, { useContext, useEffect } from 'react'; import { Navigate, useNavigate } from 'react-router-dom'; -import { useAuthContext } from '../../context'; +import { useAuthContext } from '../context'; const PrivateRoute = ({ children }) => { const { isLoggedIn, user } = useAuthContext(); diff --git a/src/layout/REUSABLE_COMPONENTS/CustomSnackbar.jsx b/src/layout/REUSABLE_COMPONENTS/CustomSnackbar.jsx deleted file mode 100644 index 42c508a..0000000 --- a/src/layout/REUSABLE_COMPONENTS/CustomSnackbar.jsx +++ /dev/null @@ -1,31 +0,0 @@ -// // CustomSnackbar.js -// import React from 'react'; -// import { Box, Typography } from '@mui/material'; -// import CircularProgress from '@mui/material/CircularProgress'; -// import { useSnackbar } from 'notistack'; - -// const CustomSnackbar = () => { -// const { enqueueSnackbar } = useSnackbar(); - -// const showSnackbar = (title, subTitle, options = {}) => { -// const content = ( -// -// {title} -// -// {subTitle} -// -// -// ); - -// enqueueSnackbar(content, { -// ...options, -// action: options.persist -// ? (key) => -// : undefined, -// }); -// }; - -// return { showSnackbar }; -// }; - -// export default CustomSnackbar; diff --git a/src/layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar.jsx b/src/layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar.jsx deleted file mode 100644 index c92cb3b..0000000 --- a/src/layout/REUSABLE_COMPONENTS/HOC/DynamicSnackbar.jsx +++ /dev/null @@ -1,278 +0,0 @@ -import * as React from 'react'; -// const withDynamicSnackbar = (WrappedComponent) => (props) => { -// const { enqueueSnackbar, closeSnackbar } = useSnackbar(); -// // const { handleSnackBar } = useSnackBar(); // Obtain enqueueSnackbar function from useSnackBar hook - -import { Snackbar, IconButton, Box, Grow } from '@mui/material'; -import { useSnackbar } from 'notistack'; -import { Close as CloseIcon } from '@mui/icons-material'; -import styled from 'styled-components'; - -// eslint-disable-next-line react/display-name -const withDynamicSnackbar = (WrappedComponent) => (props) => { - const { enqueueSnackbar, closeSnackbar } = useSnackbar(); - - const showSnackbar = (message, variant = 'success') => { - enqueueSnackbar(message, { - variant, - action: (key) => ( - closeSnackbar(key)}> - - - ), - }); - }; - - return ; -}; - -export { withDynamicSnackbar }; -// import { Transition } from 'react-transition-group'; -// import { Snackbar, IconButton, Box, Grow } from '@mui/material'; -// import { Close as CloseIcon } from '@mui/icons-material'; -// import styled from 'styled-components'; -// import CheckRoundedIcon from '@mui/icons-material/CheckRounded'; -// import { useMode } from '../../../context'; -// import { useSnackbar } from 'notistack'; - -// const DynamicSnackbar = ({ open, message, variant, onClose }) => { -// const { enqueueSnackbar, closeSnackbar } = useSnackbar(); - -// // Use enqueueSnackbar for showing messages -// React.useEffect(() => { -// if (open && message?.title) { -// enqueueSnackbar(message.title, { -// variant, -// action: (key) => ( -// closeSnackbar(key)}> -// -// -// ), -// }); -// } -// }, [open, message, variant, enqueueSnackbar, closeSnackbar]); - -// // Since snackbar management is now handled by notistack, the component itself doesn't need to render anything. -// return null; -// }; - -// export default DynamicSnackbar; -// import useSnackBar from '../../../context/hooks/useSnackBar'; - -// const DynamicSnackbar = ({ open, message, variant, onClose, loading }) => { -// const { theme } = useMode(); -// const { handleCloseSnackbar } = useSnackBar(); // Obtain handleCloseSnackbar function from useSnackBar hook - -// const handleClose = (_, reason) => { -// if (reason === 'clickaway') { -// return; -// } -// onClose(); -// }; - -// console.log('DynamicSnackbar:', open, message, variant, loading); -// return ( -// -// {/* */} -// -// {(status) => ( -// -// -//
-//

{message.title}

-//

{message.description}

-//
-// -// {' '} -// {/* Use handleCloseSnackbar instead of onClose */} -// -// -//
-// )} -//
-//
-// ); -// }; - -// DynamicSnackbar.displayName = 'DynamicSnackbar'; // Add display name - -// eslint-disable-next-line react/display-name -// HOC to provide snackbar functionality to wrapped components -// const withDynamicSnackbar = (WrappedComponent) => (props) => { -// const { enqueueSnackbar, closeSnackbar } = useSnackbar(); - -// // Function to show snackbar -// const showSnackbar = (message, variant = 'success') => { -// enqueueSnackbar(message, { -// variant, -// action: (key) => ( -// closeSnackbar(key)}> -// -// -// ), -// }); -// }; - -// return ; -// }; - -// const withDynamicSnackbar = (WrappedComponent) => (props) => { -// const { enqueueSnackbar, closeSnackbar } = useSnackbar(); -// // const { handleSnackBar } = useSnackBar(); // Obtain enqueueSnackbar function from useSnackBar hook - -// const [snackbarOpen, setSnackbarOpen] = React.useState(false); -// const [snackbarMessage, setSnackbarMessage] = React.useState({ -// title: '', -// description: '', -// }); -// const [snackbarVariant, setSnackbarVariant] = React.useState('success'); -// const [loading, setLoading] = React.useState(false); - -// const showSnackbar = (message, variant = 'success') => { -// console.log('showSnackbar:', message, variant); -// const destructuredMessage = { -// title: message.title, -// description: message.description, -// }; -// setSnackbarMessage(destructuredMessage); -// setSnackbarVariant(variant); -// setSnackbarOpen(true); -// }; - -// const hideSnackbar = () => { -// setSnackbarOpen(false); -// }; - -// return ( -// -// -// -// -// ); -// }; - -// export { withDynamicSnackbar }; - -// const positioningStyles = { -// entering: 'translateX(0)', -// entered: 'translateX(0)', -// exiting: 'translateX(500px)', -// exited: 'translateX(500px)', -// unmounted: 'translateX(500px)', -// }; - -const grey = { - 50: '#fafafa', - 100: '#f5f5f5', - 200: '#eeeeee', - 300: '#e0e0e0', - 400: '#bdbdbd', - 500: '#9e9e9e', - 600: '#757575', - 700: '#616161', - 800: '#424242', - 900: '#212121', -}; - -const StyledSnackbar = styled(Snackbar)( - ({ theme, variant }) => ` - position: fixed; - z-index: 5500; - display: flex; - bottom: 16px; - right: 16px; - max-width: 560px; - min-width: 300px; - gap: 8px; - overflow: hidden; - background-color: ${theme.palette.mode === 'dark' ? grey[900] : '#fff'}; - border-radius: 8px; - border: 1px solid ${theme.palette.mode === 'dark' ? grey[700] : grey[200]}; - box-shadow: ${ - theme.palette.mode === 'dark' - ? '0 2px 16px rgba(0,0,0, 0.5)' - : `0 2px 16px ${grey[200]}` - }; - padding: 0.75rem; - color: ${theme.palette.mode === 'dark' ? grey[50] : grey[900]}; - font-family: 'IBM Plex Sans', sans-serif; - font-weight: 500; - text-align: start; - - & .snackbar-message { - flex: 1 1 0%; - max-width: 100%; - } - - & .snackbar-title { - margin: 0; - line-height: 1.5rem; - margin-right: 0.5rem; - } - - & .snackbar-description { - margin: 0; - line-height: 1.5rem; - font-weight: 400; - color: ${theme.palette.mode === 'dark' ? grey[400] : grey[800]}; - } - - & .snackbar-close-icon { - cursor: pointer; - flex-shrink: 0; - padding: 2px; - border-radius: 4px; - color: ${theme.palette.mode === 'dark' ? grey[50] : grey[900]}; - background: transparent; - - &:hover { - background: ${theme.palette.mode === 'dark' ? grey[800] : grey[50]}; - } - } - ` -); diff --git a/src/layout/REUSABLE_COMPONENTS/HOC/withDynamicSnackbar.jsx b/src/layout/REUSABLE_COMPONENTS/HOC/withDynamicSnackbar.jsx deleted file mode 100644 index 0e7098a..0000000 --- a/src/layout/REUSABLE_COMPONENTS/HOC/withDynamicSnackbar.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import { Snackbar, IconButton, Box, Grow } from '@mui/material'; -import { useSnackbar } from 'notistack'; -import { Close as CloseIcon } from '@mui/icons-material'; - -// eslint-disable-next-line react/display-name -const withDynamicSnackbar = (WrappedComponent) => (props) => { - const { enqueueSnackbar, closeSnackbar } = useSnackbar(); - - const showSnackbar = (message, variant = 'success') => { - enqueueSnackbar(message, { - variant, - action: (key) => ( - closeSnackbar(key)}> - - - ), - }); - }; - - return ; -}; - -export { withDynamicSnackbar }; - -const positioningStyles = { - entering: 'translateX(0)', - entered: 'translateX(0)', - exiting: 'translateX(500px)', - exited: 'translateX(500px)', - unmounted: 'translateX(500px)', -}; - -// const [snackbarOpen, setSnackbarOpen] = React.useState(false); -// const [snackbarMessage, setSnackbarMessage] = React.useState({ -// title: '', -// description: '', -// }); -// const [snackbarVariant, setSnackbarVariant] = React.useState('success'); -// const [loading, setLoading] = React.useState(false); - -// const showSnackbar = (message, variant = 'success') => { -// console.log('showSnackbar:', message, variant); -// const destructuredMessage = { -// title: message.title, -// description: message.description, -// }; -// setSnackbarMessage(destructuredMessage); -// setSnackbarVariant(variant); -// setSnackbarOpen(true); -// }; - -// const hideSnackbar = () => { -// setSnackbarOpen(false); -// }; - -// return ( -// -// -// -// -// ); -// }; diff --git a/src/pages/NotFoundPage.js b/src/layout/REUSABLE_COMPONENTS/NotFoundPage.js similarity index 100% rename from src/pages/NotFoundPage.js rename to src/layout/REUSABLE_COMPONENTS/NotFoundPage.js diff --git a/src/layout/REUSABLE_COMPONENTS/RCICON/RCIcon.jsx b/src/layout/REUSABLE_COMPONENTS/RCICON/RCIcon.jsx new file mode 100644 index 0000000..783f74d --- /dev/null +++ b/src/layout/REUSABLE_COMPONENTS/RCICON/RCIcon.jsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { styled } from '@mui/material/styles'; +import * as MuiIcons from '@mui/icons-material'; +import uniqueTheme from '../unique/uniqueTheme'; +import { Box } from '@mui/material'; +import { useMode } from '../../../context'; + +const StyledIcon = styled(Box)(({ theme }) => ({ + borderRadius: '50%', + border: `1px solid ${theme.palette.chartTheme.primary.dark}`, + padding: '5px', + display: 'inline-flex', + fontSize: '30px', + alignItems: 'center', + justifyContent: 'center', + bgColor: theme.palette.chartTheme.primary.main, +})); +// function ColoredAvatars() { +// return ( +// +// G +// B +// P +// +// ); +// } + +const RCIcon = ({ + iconName, + size = '30px', + color = uniqueTheme.colorPrimary, +}) => { + const { theme } = useMode(); + // Dynamically get the icon component; ensure it's a valid icon name + const IconComponent = MuiIcons[iconName] || null; + + if (!IconComponent) { + return Icon not found; // Display error message if the icon is not found + } + + return ( + + + + ); +}; + +export default RCIcon; diff --git a/src/layout/REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection.jsx b/src/layout/REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection.jsx new file mode 100644 index 0000000..529d14a --- /dev/null +++ b/src/layout/REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection.jsx @@ -0,0 +1,186 @@ +// // import { ButtonBase, Typography } from '@mui/material'; +// // import { Link, useNavigate } from 'react-router-dom'; +// // import config from '../../../config'; +// // import DeckOfCardsIcon from '../../../components/reusable/icons/DeckOfCardsIcon'; + +// // // ==============================|| MAIN LOGO ||============================== // + +// // const RCLogoSection = () => { +// // const navigate = useNavigate(); + +// // const handleClick = () => { +// // navigate(config?.defaultPath); +// // }; + +// // return ( +// // +// // Logo +// // +// // DeckMaster +// // +// // +// // ); +// // }; + +// // export default RCLogoSection; +// import React from 'react'; +// import { ButtonBase, Typography } from '@mui/material'; +// import { Link, useNavigate } from 'react-router-dom'; +// import config from '../../../config'; +// import DeckBuilderIcon from '../../../components/reusable/icons/DeckBuilderIcon'; // Import DeckBuilderIcon + +// // ==============================|| MAIN LOGO ||============================== // + +// const RCLogoSection = () => { +// const navigate = useNavigate(); + +// const handleClick = () => { +// navigate(config?.defaultPath); +// }; + +// return ( +// +// {/* Render DeckBuilderIcon here */} +// +// +// DeckMaster +// +// +// ); +// }; + +// export default RCLogoSection; +import React from 'react'; +import { ButtonBase, Typography, Avatar } from '@mui/material'; +import { Link, useNavigate } from 'react-router-dom'; +import config from '../../../config'; +import DeckBuilderIcon from '../icons/DeckBuilderIcon'; // Import DeckBuilderIcon + +// ==============================|| MAIN LOGO ||============================== // + +const RCLogoSection = () => { + const navigate = useNavigate(); + + const handleClick = () => { + navigate(config?.defaultPath); + }; + + return ( + + {/* Encapsulate DeckBuilderIcon within an Avatar */} + + + + + DeckMaster + + + ); +}; + +export default RCLogoSection; diff --git a/src/layout/REUSABLE_COMPONENTS/RCTOOLTIP/RCToolTip.jsx b/src/layout/REUSABLE_COMPONENTS/RCTOOLTIP/RCToolTip.jsx new file mode 100644 index 0000000..5d41b1c --- /dev/null +++ b/src/layout/REUSABLE_COMPONENTS/RCTOOLTIP/RCToolTip.jsx @@ -0,0 +1,74 @@ +import React, { useState, forwardRef } from 'react'; +import Popper from '@mui/material/Popper'; +import { + useFloating, + offset, + flip, + shift, + autoUpdate, +} from '@floating-ui/react'; + +const RCToolTip = ({ tooltipContent, children }) => { + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + const id = open ? 'simple-popper' : undefined; + + // Configure Floating UI + const { x, y, strategy, refs, update } = useFloating({ + open, + onOpenChange: (isOpen) => setAnchorEl(isOpen ? anchorEl : null), + placement: 'top', + middleware: [offset(10), flip(), shift()], + whileElementsMounted: autoUpdate, + }); + + // Handle mouse enter and leave events to control the tooltip visibility + const handleMouseEnter = (event) => { + setAnchorEl(event.currentTarget); + update(); + }; + + const handleMouseLeave = () => { + setAnchorEl(null); + }; + + // Clone the child element to attach event handlers for controlling tooltip visibility + const child = React.cloneElement(children, { + 'aria-describedby': id, + onMouseEnter: handleMouseEnter, + onMouseLeave: handleMouseLeave, + ref: refs.setReference, + }); + + return ( + <> + {child} + +
{tooltipContent}
+
+ + ); +}; + +export default forwardRef(RCToolTip); diff --git a/src/components/reusable/icons/CartIcon.jsx b/src/layout/REUSABLE_COMPONENTS/icons/CartIcon.jsx similarity index 100% rename from src/components/reusable/icons/CartIcon.jsx rename to src/layout/REUSABLE_COMPONENTS/icons/CartIcon.jsx diff --git a/src/components/reusable/icons/ChartsIcon.jsx b/src/layout/REUSABLE_COMPONENTS/icons/ChartsIcon.jsx similarity index 100% rename from src/components/reusable/icons/ChartsIcon.jsx rename to src/layout/REUSABLE_COMPONENTS/icons/ChartsIcon.jsx diff --git a/src/components/reusable/icons/CollectionIcon.jsx b/src/layout/REUSABLE_COMPONENTS/icons/CollectionIcon.jsx similarity index 100% rename from src/components/reusable/icons/CollectionIcon.jsx rename to src/layout/REUSABLE_COMPONENTS/icons/CollectionIcon.jsx diff --git a/src/components/reusable/icons/DeckBuilderIcon.jsx b/src/layout/REUSABLE_COMPONENTS/icons/DeckBuilderIcon.jsx similarity index 100% rename from src/components/reusable/icons/DeckBuilderIcon.jsx rename to src/layout/REUSABLE_COMPONENTS/icons/DeckBuilderIcon.jsx diff --git a/src/components/reusable/icons/DeckOfCardsIcon.jsx b/src/layout/REUSABLE_COMPONENTS/icons/DeckOfCardsIcon.jsx similarity index 100% rename from src/components/reusable/icons/DeckOfCardsIcon.jsx rename to src/layout/REUSABLE_COMPONENTS/icons/DeckOfCardsIcon.jsx diff --git a/src/components/reusable/icons/GlassyIcon.jsx b/src/layout/REUSABLE_COMPONENTS/icons/GlassyIcon.jsx similarity index 100% rename from src/components/reusable/icons/GlassyIcon.jsx rename to src/layout/REUSABLE_COMPONENTS/icons/GlassyIcon.jsx diff --git a/src/components/reusable/icons/MoneyIcon.jsx b/src/layout/REUSABLE_COMPONENTS/icons/MoneyIcon.jsx similarity index 100% rename from src/components/reusable/icons/MoneyIcon.jsx rename to src/layout/REUSABLE_COMPONENTS/icons/MoneyIcon.jsx diff --git a/src/components/reusable/icons/ReusableIconButton.jsx b/src/layout/REUSABLE_COMPONENTS/icons/ReusableIconButton.jsx similarity index 100% rename from src/components/reusable/icons/ReusableIconButton.jsx rename to src/layout/REUSABLE_COMPONENTS/icons/ReusableIconButton.jsx diff --git a/src/components/reusable/icons/TestingIcon.jsx b/src/layout/REUSABLE_COMPONENTS/icons/TestingIcon.jsx similarity index 100% rename from src/components/reusable/icons/TestingIcon.jsx rename to src/layout/REUSABLE_COMPONENTS/icons/TestingIcon.jsx diff --git a/src/components/reusable/icons/index.jsx b/src/layout/REUSABLE_COMPONENTS/icons/index.jsx similarity index 100% rename from src/components/reusable/icons/index.jsx rename to src/layout/REUSABLE_COMPONENTS/icons/index.jsx diff --git a/src/layout/REUSABLE_COMPONENTS/unique/SimpleCard.jsx b/src/layout/REUSABLE_COMPONENTS/unique/SimpleCard.jsx index 23dc327..8db36a9 100644 --- a/src/layout/REUSABLE_COMPONENTS/unique/SimpleCard.jsx +++ b/src/layout/REUSABLE_COMPONENTS/unique/SimpleCard.jsx @@ -42,11 +42,27 @@ const getAccentStyle = (theme, isAccent) => ({ color: isAccent ? theme.colorAccentText : undefined, }); +const getTableOrChartStyle = (theme, isTableOrChart) => ({ + background: isTableOrChart ? theme.colorCardBackground : undefined, + color: isTableOrChart ? theme.colorPrimary : undefined, +}); + +const getFormHeaderStyle = (theme, isFormHeader) => ({ + background: isFormHeader ? theme.colorCardBackground : undefined, + color: isFormHeader ? theme.colorPrimary : undefined, + maxWidth: 'md', + padding: theme.lenMd3, // Updated to use theme's spacing method if available + borderRadius: '24px', + boxShadow: '0px 3px 10px 0px rgba(0, 0, 0, 0.2)', // Custom shadow with blur + margin: 'auto', + width: '80%', +}); + const CardContent = ({ theme, children }) => (
{children}
); -const CardTitle = ({ theme, children }) => ( +const CardTitle = ({ theme, children, isTableOrChart }) => (
( justifyContent: 'center', height: theme.lenXl2, padding: `0 ${theme.lenMd1}`, + // color: theme.colorLabel, color: theme.colorLabel, fontSize: theme.lenMd2, // overflow: 'hidden', }} > - + {children}
@@ -70,10 +91,12 @@ const SimpleCard = ({ hasTitle, isPrimary, isAccent, + isTableOrChart, noBottomMargin, children, cardTitle, data, + isFormHeader, ...rest }) => { const cardStyle = { @@ -84,6 +107,8 @@ const SimpleCard = ({ borderRadius: theme.borderRadius, background: theme.colorCardBackground, color: theme.colorText, + ...(isFormHeader && getFormHeaderStyle(theme, true)), + ...(isTableOrChart && getTableOrChartStyle(theme, true)), ...(isPrimary && getPrimaryStyle(theme, true)), ...(isAccent && getAccentStyle(theme, true)), }; @@ -92,7 +117,9 @@ const SimpleCard = ({
{cardTitle && ( <> - {cardTitle} + + {cardTitle} + {children} )} diff --git a/src/layout/REUSABLE_COMPONENTS/unique/SimpleSectionHeader.jsx b/src/layout/REUSABLE_COMPONENTS/unique/SimpleSectionHeader.jsx index 69137e8..a5a3317 100644 --- a/src/layout/REUSABLE_COMPONENTS/unique/SimpleSectionHeader.jsx +++ b/src/layout/REUSABLE_COMPONENTS/unique/SimpleSectionHeader.jsx @@ -4,6 +4,7 @@ import Box from '@mui/material/Box'; import { useMode } from '../../../context'; import MDTypography from '../MDTYPOGRAPHY/MDTypography'; import { useMediaQuery, useTheme } from '@mui/material'; +import MDBox from '../MDBOX'; const SimpleSectionHeader = ({ sectionName, @@ -36,12 +37,13 @@ const SimpleSectionHeader = ({ marginBottom: '8px', }} > - + {sectionName} {`${userName}'s Portfolio`} - - {/* Section Description */} - - {sectionDescription} - - - {/* Last Updated */} - - {`Last updated: ${lastUpdated}`} - + {/* Section Description */} + + {sectionDescription} + + + {/* Last Updated */} + + {`${lastUpdated}`} + + ); }; diff --git a/src/layout/collection/collectionGrids/ChartGridLayout.jsx b/src/layout/collection/collectionGrids/ChartGridLayout.jsx index 272add9..836e641 100644 --- a/src/layout/collection/collectionGrids/ChartGridLayout.jsx +++ b/src/layout/collection/collectionGrids/ChartGridLayout.jsx @@ -1,5 +1,13 @@ import React, { Suspense, useEffect, useMemo } from 'react'; -import { Grid, Card, useMediaQuery, Icon, Container } from '@mui/material'; +import { + Grid, + Card, + useMediaQuery, + Icon, + Container, + Grow, + Box, +} from '@mui/material'; import MDBox from '../../REUSABLE_COMPONENTS/MDBOX'; import DataTable from './cards-datatable'; import { useMode, useStatisticsStore } from '../../../context'; @@ -14,6 +22,8 @@ import useTimeRange from '../../../components/forms/selectors/useTimeRange'; import useSkeletonLoader from './cards-datatable/useSkeletonLoader'; import ChartErrorBoundary from './cards-chart/ChartErrorBoundary'; import { ChartConfiguration } from './cards-chart/ChartConfigs'; +import IconStatWrapper from '../../REUSABLE_COMPONENTS/unique/IconStatWrapper'; +import { TopCardsDisplayRow } from '../sub-components/TopCardsDisplayRow'; const renderCardContainer = (content) => { return ( @@ -42,15 +52,50 @@ const ChartGridLayout = ({ selectedCards, removeCard, columns, data }) => { const { selectedTimeRange } = useTimeRange(); const { stats, markers } = useStatisticsStore(); const { SkeletonLoader } = useSkeletonLoader(); + const averagedData = selectedCollection.averagedChartData; + + if (!averagedData || !averagedData[selectedTimeRange]) { + return ( + + } + sideText="Loading..." + /> + + + + + + + + + + + + + + ); + } + const selectedChartData = useMemo(() => { - const averagedData = selectedCollection.averagedChartData; + // const averagedData = selectedCollection.averagedChartData; - if (!averagedData || !averagedData[selectedTimeRange]) { - console.error( - 'No averaged chart data available for the selected time range.' - ); - return null; - } + // if (!averagedData || !averagedData[selectedTimeRange]) { + // console.error( + // 'No averaged chart data available for the selected time range.' + // ); + // return null; + // } const chartData = averagedData[selectedTimeRange]; return chartData || null; }, [selectedCollection.averagedChartData, selectedTimeRange]); @@ -77,6 +122,30 @@ const ChartGridLayout = ({ selectedCards, removeCard, columns, data }) => { }); }, []); + const IconWrapper = ({ children }) => ( + + {children} + + ); + const updatedAt = selectedCollection?.updatedAt; + const formattedTime = updatedAt + ? new Date(updatedAt).toLocaleTimeString([], { + hour: '2-digit', + minute: '2-digit', + }) + : 'Loading...'; + return ( @@ -89,15 +158,19 @@ const ChartGridLayout = ({ selectedCards, removeCard, columns, data }) => { > table_chart} + icon={ + + show_chart + + } sideText="+4%" /> @@ -134,6 +207,15 @@ const ChartGridLayout = ({ selectedCards, removeCard, columns, data }) => { > + + + { > table_chart} - sideText="+4%" + icon={ + + list + + } + // sideText="Updated recently" + sideText={`Last Updated: ${formattedTime}`} /> {renderCardContainer( diff --git a/src/layout/collection/collectionGrids/cards-chart/ChartConfigs.jsx b/src/layout/collection/collectionGrids/cards-chart/ChartConfigs.jsx index 8c2e747..5d76de6 100644 --- a/src/layout/collection/collectionGrids/cards-chart/ChartConfigs.jsx +++ b/src/layout/collection/collectionGrids/cards-chart/ChartConfigs.jsx @@ -32,6 +32,9 @@ export const ChartConfiguration = ({ ticks = 'every hour'; break; case '7d': + format = '%b %d'; + ticks = 'every day'; + break; case '30d': format = '%b %d'; ticks = 'every day'; diff --git a/src/layout/collection/collectionGrids/cards-chart/UpdaterAndStatisticsRow.jsx b/src/layout/collection/collectionGrids/cards-chart/UpdaterAndStatisticsRow.jsx index b985f05..d11a7a0 100644 --- a/src/layout/collection/collectionGrids/cards-chart/UpdaterAndStatisticsRow.jsx +++ b/src/layout/collection/collectionGrids/cards-chart/UpdaterAndStatisticsRow.jsx @@ -24,15 +24,15 @@ export const UpdaterAndStatisticsRow = ({ isSmall }) => ( }} > {/* Update Status Box */} - + {/* Time Range Selector */} - + {/* Collection Statistics Selector */} - + diff --git a/src/layout/collection/collectionGrids/cards-datatable/DataTableBodyComponent.jsx b/src/layout/collection/collectionGrids/cards-datatable/DataTableBodyComponent.jsx deleted file mode 100644 index e69de29..0000000 diff --git a/src/layout/collection/collectionGrids/cards-datatable/DataTableHeadCell.jsx b/src/layout/collection/collectionGrids/cards-datatable/DataTableHeadCell.jsx index 7ee33a1..f987f95 100644 --- a/src/layout/collection/collectionGrids/cards-datatable/DataTableHeadCell.jsx +++ b/src/layout/collection/collectionGrids/cards-datatable/DataTableHeadCell.jsx @@ -1,110 +1,200 @@ -// prop-types is a library for typechecking of props -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; +// import Icon from '@mui/material/Icon'; +// import MDBox from '../../../REUSABLE_COMPONENTS/MDBOX'; +// import { useMode } from '../../../../context'; +// import MDTypography from '../../../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; + +// function DataTableHeadCell({ width, children, sorted, align, ...rest }) { +// const { theme } = useMode(); +// return ( +// +// +// +// +// {children} +// +// {sorted && ( +// +// +// arrow_drop_up +// +// +// arrow_drop_down +// +// +// )} +// +// +// +// ); +// } -// @mui material components -import Icon from '@mui/material/Icon'; +// DataTableHeadCell.defaultProps = { +// width: 'auto', +// sorted: 'none', +// align: 'left', +// }; -// Material Dashboard 2 React components +// DataTableHeadCell.propTypes = { +// width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), +// children: PropTypes.node.isRequired, +// sorted: PropTypes.oneOf([false, 'none', 'asce', 'desc']), +// align: PropTypes.oneOf(['left', 'right', 'center']), +// }; -// Material Dashboard 2 React contexts +// export default DataTableHeadCell; +import { useMemo } from 'react'; +import PropTypes from 'prop-types'; +import { TableRow, Checkbox, Icon } from '@mui/material'; import MDBox from '../../../REUSABLE_COMPONENTS/MDBOX'; -import { useMode } from '../../../../context'; import MDTypography from '../../../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; +import { useMode } from '../../../../context'; -function DataTableHeadCell({ width, children, sorted, align, ...rest }) { +const DataTableHeadCell = ({ headerGroups, isSorted, setSortedValue }) => { const { theme } = useMode(); - return ( - + + const renderCellContent = (column, idx) => { + const sorted = setSortedValue(column, isSorted); + return ( - - {children} - {' '} - {sorted && ( - + {column.render('Header')} + + {sorted && ( - arrow_drop_up + + arrow_drop_up + + + arrow_drop_down + - - arrow_drop_down - - - )} + )} + - - ); -} + ); + }; -// Setting default values for the props of DataTableHeadCell -DataTableHeadCell.defaultProps = { - width: 'auto', - sorted: 'none', - align: 'left', + return useMemo( + () => ( + <> + {headerGroups.map((headerGroup, key) => ( + + {headerGroup.headers.map(renderCellContent)} + + ))} + + ), + [ + headerGroups, + isSorted, + setSortedValue, + theme.palette.divider, + theme.typography.fontWeightMedium, + ] + ); }; -// Typechecking props for the DataTableHeadCell DataTableHeadCell.propTypes = { - width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - children: PropTypes.node.isRequired, - sorted: PropTypes.oneOf([false, 'none', 'asce', 'desc']), - align: PropTypes.oneOf(['left', 'right', 'center']), + headerGroups: PropTypes.array.isRequired, + isSorted: PropTypes.bool.isRequired, + setSortedValue: PropTypes.func.isRequired, }; export default DataTableHeadCell; diff --git a/src/layout/collection/collectionGrids/cards-datatable/DataTableHeadComponent.jsx b/src/layout/collection/collectionGrids/cards-datatable/DataTableHeadComponent.jsx deleted file mode 100644 index e382b4d..0000000 --- a/src/layout/collection/collectionGrids/cards-datatable/DataTableHeadComponent.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import { TableRow } from '@mui/material'; -import MDBox from '../../../REUSABLE_COMPONENTS/MDBOX'; -import DataTableHeadCell from './DataTableHeadCell'; - -export const DataTableHeadComponent = (props) => { - const { - onSelectAllClick, - order, - orderBy, - numSelected, - rowCount, - onRequestSort, - headerGroups, - isSorted, - setSortedValue, - } = props; - const createSortHandler = (property) => (event) => { - onRequestSort(event, property); - }; - - return ( - - {headerGroups?.map((headerGroup, key) => ( - - {/* - 0 && numSelected < rowCount} - checked={rowCount > 0 && numSelected === rowCount} - onChange={onSelectAllClick} - /> - */} - {headerGroup.headers.map((column, idx) => ( - - {column.render('Header')} - - ))} - - ))} - - ); -}; diff --git a/src/layout/collection/collectionGrids/cards-datatable/OptionsComponent.jsx b/src/layout/collection/collectionGrids/cards-datatable/OptionsComponent.jsx index c5fdad8..96dffe9 100644 --- a/src/layout/collection/collectionGrids/cards-datatable/OptionsComponent.jsx +++ b/src/layout/collection/collectionGrids/cards-datatable/OptionsComponent.jsx @@ -1,7 +1,14 @@ // OptionsComponent.jsx -import React from 'react'; +import React, { useEffect } from 'react'; import MDBox from '../../../REUSABLE_COMPONENTS/MDBOX'; import { Autocomplete, Grid, TextField } from '@mui/material'; +import { + FormBox, + FormFieldBox, +} from '../../../REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; +import FormField from '../../../../components/forms/reusable/FormField'; +import { useFormContext, useMode } from '../../../../context'; +import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline'; const OptionsComponent = ({ canSearch, @@ -10,44 +17,124 @@ const OptionsComponent = ({ pageSize, setPageSize, pageOptions, -}) => ( - - - {canSearch && ( - - { + const { theme } = useMode(); + const schemaName = 'collectionSearchForm'; + const buttonLabel = 'Search'; + const startIcon = ; + const collectionSearchFields = [ + { + name: 'searchTerm', + label: 'Search', + type: 'text', + required: true, + value: search, + }, + ]; + const { + formMethods, + onSubmit, + handleChange, + setFormSchema, + formState: { errors, isSubmitting }, + // getValues, + handleSearchTermChange, + } = useFormContext(); + + useEffect(() => { + setFormSchema(schemaName); + }, [setFormSchema, schemaName]); + + const onFormSubmit = (data) => { + onSubmit(data, schemaName); + }; + return ( + + + {canSearch && ( + +
+ {collectionSearchFields?.map((field, index) => ( + + + + ))} +
+
+ )} + + setPageSize(parseInt(newValue, 10))} + options={pageOptions?.map((option) => option.toString())} + renderInput={(params) => ( + + )} /> - )} - - setPageSize(parseInt(newValue, 10))} - options={pageOptions?.map((option) => option?.toString())} - renderInput={(params) => ( - - )} - /> -
-
-); +
+ ); +}; export default OptionsComponent; diff --git a/src/layout/collection/collectionGrids/cards-datatable/index.jsx b/src/layout/collection/collectionGrids/cards-datatable/index.jsx index 64c80d3..dd3213d 100644 --- a/src/layout/collection/collectionGrids/cards-datatable/index.jsx +++ b/src/layout/collection/collectionGrids/cards-datatable/index.jsx @@ -13,25 +13,13 @@ import { import Table from '@mui/material/Table'; import TableContainer from '@mui/material/TableContainer'; import TableRow from '@mui/material/TableRow'; -import Icon from '@mui/material/Icon'; import DataTableBodyCell from './DataTableBodyCell'; -import useScreenWidth from '../../../../context/hooks/useScreenWidth'; -import { - Box, - Button, - Checkbox, - Grid, - Paper, - TableBody, - TextField, -} from '@mui/material'; +import { Box, Button, Checkbox, Grid, Paper, TableBody } from '@mui/material'; import PaginationComponent from './PaginationComponent'; import OptionsComponent from './OptionsComponent'; -import { DataTableHeadComponent } from './DataTableHeadComponent'; -import BoxHeader from '../../../REUSABLE_COMPONENTS/BoxHeader'; import GenericActionButtons from '../../../../components/buttons/actionButtons/GenericActionButtons'; -import { enqueueSnackbar } from 'notistack'; import { useMode } from '../../../../context'; +import DataTableHeadCell from './DataTableHeadCell'; const setSortedValue = (column, isSorted) => { let sortedValue; @@ -82,13 +70,16 @@ function DataTable({ const data = useMemo(() => table.data, [table.data]); const columns = useMemo(() => { let baseColumns = [ - // Only include the selection column if showSelection is true showSelection && { id: 'selection', Header: ({ getToggleAllRowsSelectedProps }) => ( ), Cell: ({ row }) => , + // Apply a fixed width to the checkbox column + width: 30, // Adjust the width as needed + minWidth: 30, // Ensure it doesn't get smaller than the set width + maxWidth: 30, // Ensure it doesn't get larger than the set width }, { Header: 'Name', accessor: 'name' }, // { Header: 'Price', accessor: 'price' }, @@ -101,26 +92,8 @@ function DataTable({ card={value} context={'Collection'} onClick={() => console.log('clicked')} - onSuccess={() => - enqueueSnackbar( - { - title: 'Action successful', - message: `Card added to ${value} successfully.`, - }, - 'success', - null - ) - } - onFailure={(error) => - enqueueSnackbar( - { - title: 'Action failed', - message: `Failed to add card to ${value}.`, - }, - 'error', - error - ) - } + onSuccess={() => console.log('success')} + onFailure={(error) => console.log(error)} page={'Collection'} cardSize={'small'} /> @@ -242,7 +215,7 @@ function DataTable({ /> {/* Table */} - {row.cells.map((cell, idx) => ( diff --git a/src/layout/collection/collectionGrids/collections-list/CollectionListItem.jsx b/src/layout/collection/collectionGrids/collections-list/CollectionListItem.jsx index ad57aa1..8d21fb6 100644 --- a/src/layout/collection/collectionGrids/collections-list/CollectionListItem.jsx +++ b/src/layout/collection/collectionGrids/collections-list/CollectionListItem.jsx @@ -1,175 +1,208 @@ -/* eslint-disable react/display-name */ -import React, { memo, useCallback, useRef, useState } from 'react'; -import { Card, CardActionArea, Grid, Tooltip } from '@mui/material'; +import React, { memo, useCallback, useRef } from 'react'; +import { + Box, + Card, + CardActionArea, + CardContent, + Grid, + Tooltip, +} from '@mui/material'; +import PropTypes from 'prop-types'; import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward'; import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; -import PropTypes from 'prop-types'; -import { - useAuthContext, - useMode, - useVisibilityContext, -} from '../../../../context'; -import LongMenu from '../../../../layout/navigation/LongMenu'; -import useCollectionVisibility from '../../../../context/hooks/useCollectionVisibility'; +import useCollectionManager from '../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionManager'; import MDBox from '../../../../layout/REUSABLE_COMPONENTS/MDBOX'; import MDTypography from '../../../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -import { - StyledCollectionListCard, - StyledCollectionListCardContent, -} from '../../../../pages/pageStyles/StyledComponents'; -import useCollectionManager from '../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionManager'; +import LongMenu from '../../../../layout/navigation/LongMenu'; +import useDialogState from '../../../../context/hooks/useDialogState'; import CollectionDialog from '../../../../components/dialogs/CollectionDialog'; import useSelectedCollection from '../../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; -import useDialogState from '../../../../context/hooks/useDialogState'; -import SimpleCard from '../../../REUSABLE_COMPONENTS/unique/SimpleCard'; -import uniqueTheme from '../../../REUSABLE_COMPONENTS/unique/uniqueTheme'; +import { useMode, useVisibilityContext } from '../../../../context'; -const CollectionInfoItem = ({ label, value, sx }) => ( - - - - {label}: {value} +const CollectionInfoItem = ({ label, value, theme }) => ( + + + + {label}: - - {/* - {label}: {value} - */} + + {value} + + ); const CollectionListItem = memo(({ collection }) => { const { theme } = useMode(); - const roundToNearestTenth = (number) => Math.ceil(number / 10) * 10; - const ref = useRef(null); const { deleteCollection } = useCollectionManager(); - const { - handleBackToCollections, - showCollections, - selectedCollection, - handleSelectCollection, - toggleShowCollections, - } = useSelectedCollection(); - const { - isCollectionVisible, - toggleCollectionVisibility, - // dialogStates, - // toggleDialog, - } = useVisibilityContext(); - + const { handleSelectCollection } = useSelectedCollection(); + const { toggleCollectionVisibility } = useVisibilityContext(); const { dialogState, openDialog, closeDialog } = useDialogState({ isEditCollectionDialogOpen: false, }); - const handleOpenDialog = useCallback((collection) => { + + const handleOpenDialog = useCallback(() => { openDialog('editCollectionDialog', collection); - console.log(collection); - }, []); + }, [collection, openDialog]); + const handleCloseDialog = useCallback(() => { closeDialog('editCollectionDialog'); - }, []); + }, [closeDialog]); const handleDelete = async () => { - await deleteCollection(collection?._id); - // setShowOptions(false); // Close the options menu after deletion + await deleteCollection(collection._id); }; + const renderToolTip = () => (
- - handleOpenDialog(collection)} - onDelete={handleDelete} // Pass the async delete function - onSelect={() => handleSelectCollection(collection)} - onHide={() => toggleShowCollections(false)} - onStats={() => console.log('Stats:', collection)} - onView={() => console.log('View:', collection)} - // onClose={() => setShowOptions(false)} - collectionId={collection?._id} - ref={ref} - /> - + handleSelectCollection(collection)} + collectionId={collection._id} + />
); - const renderPercentageChange = useCallback(() => { + + const renderPercentageChange = () => { const percentageChange = - collection?.collectionStatistics?.percentageChange || 0; + collection.collectionStatistics?.percentageChange || 0; return ( 0 ? 'success' : 'error'} - sx={{ display: 'flex', alignItems: 'center' }} + sx={{ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + fontSize: '1.5rem', // Triple the label size + }} > {percentageChange > 0 ? : } {percentageChange}% ); - }, [collection]); + }; + const handleSelection = useCallback(() => { handleSelectCollection(collection); toggleCollectionVisibility(); - }, [collection]); + }, [collection, handleSelectCollection, toggleCollectionVisibility]); return ( - - - - - - - - - {renderPercentageChange()} - - + + + + + + + + + {renderPercentageChange()} - + - {renderToolTip()} + + {renderToolTip()} + {dialogState.isEditCollectionDialogOpen && ( handleCloseDialog()} - isNew={false} - collectionMode="edit" - collectionData={{ - name: collection?.name, - description: collection?.description, - }} + onClose={handleCloseDialog} + collectionData={collection} /> )} - + ); }); +CollectionListItem.displayName = 'CollectionListItem'; + CollectionListItem.propTypes = { collection: PropTypes.object.isRequired, - isSelected: PropTypes.bool, -}; - -CollectionListItem.defaultProps = { - isSelected: false, }; export default CollectionListItem; diff --git a/src/layout/collection/collectionGrids/collections-list/SelectCollectionHeader.jsx b/src/layout/collection/collectionGrids/collections-list/SelectCollectionHeader.jsx index 613aae6..c2d19a8 100644 --- a/src/layout/collection/collectionGrids/collections-list/SelectCollectionHeader.jsx +++ b/src/layout/collection/collectionGrids/collections-list/SelectCollectionHeader.jsx @@ -7,17 +7,12 @@ import { useUserContext, } from '../../../../context'; import { Card, Typography } from '@mui/joy'; -import MDButton from '../../../REUSABLE_COMPONENTS/MDBUTTON'; -import CustomButton from '../../../../components/buttons/other/CustomButton'; import useSkeletonLoader from '../cards-datatable/useSkeletonLoader'; -import IconStatWrapper from '../../../REUSABLE_COMPONENTS/unique/IconStatWrapper'; import uniqueTheme from '../../../REUSABLE_COMPONENTS/unique/uniqueTheme'; import SimpleButton from '../../../REUSABLE_COMPONENTS/unique/SimpleButton'; import styled from 'styled-components'; import SimpleCard from '../../../REUSABLE_COMPONENTS/unique/SimpleCard'; -import FlexBetween from '../../../REUSABLE_COMPONENTS/FlexBetween'; import SimpleSectionHeader from '../../../REUSABLE_COMPONENTS/unique/SimpleSectionHeader'; -import MDBox from '../../../REUSABLE_COMPONENTS/MDBOX'; const StyledButtonWrapper = styled.div` margin-bottom: 1rem; `; diff --git a/src/layout/collection/collectionGrids/collections-list/SelectCollectionList.jsx b/src/layout/collection/collectionGrids/collections-list/SelectCollectionList.jsx index c38ff77..dcfd39e 100644 --- a/src/layout/collection/collectionGrids/collections-list/SelectCollectionList.jsx +++ b/src/layout/collection/collectionGrids/collections-list/SelectCollectionList.jsx @@ -1,4 +1,100 @@ -import React, { memo, useRef, useState } from 'react'; +// import React, { memo, useRef, useState } from 'react'; +// import { +// Box, +// Card, +// CardActionArea, +// Collapse, +// Grid, +// List, +// Skeleton, +// } from '@mui/material'; +// import PropTypes from 'prop-types'; +// import { TransitionGroup } from 'react-transition-group'; +// import CollectionListItem from './CollectionListItem'; +// import useSelectedCollection from '../../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; +// import styled from 'styled-components'; +// import SimpleCard from '../../../REUSABLE_COMPONENTS/unique/SimpleCard'; +// import uniqueTheme from '../../../REUSABLE_COMPONENTS/unique/uniqueTheme'; +// const FlexContainer = styled(Box)` +// display: flex; +// align-items: center; +// justify-content: space-between; +// width: 100%; +// padding: ${({ theme }) => theme.spacing(1, 2)}; +// `; +// const CollectionListItemSkeleton = ({ count, index }) => ( +// +// +// +// +// +// +// +// +// +// +// +// +// +// ); + +// CollectionListItemSkeleton.propTypes = { +// count: PropTypes.number.isRequired, +// index: PropTypes.number.isRequired, +// }; + +// const SelectCollectionList = ({ openDialog }) => { +// const { allCollections } = useSelectedCollection(); +// // const [skeletonCount, setSkeletonCount] = useState(0); +// const listRef = useRef(); +// const minItems = 5; +// const numCollections = allCollections?.length || 0; +// const numRequired = minItems - numCollections; +// const allSkeletonCollections = [...Array(numRequired).keys()].map((index) => ( +// +// )); +// const combinedCollections = [...allCollections, ...allSkeletonCollections]; +// return ( +// +// +// +// {combinedCollections?.map((collection, index) => ( +// +// +// +// ))} +// {/* */} +// +// +// +// ); +// }; + +// SelectCollectionList.propTypes = { +// openDialog: PropTypes.func.isRequired, +// }; + +// export default memo(SelectCollectionList); +import React, { memo, useEffect, useState } from 'react'; import { Box, Card, @@ -15,6 +111,7 @@ import useSelectedCollection from '../../../../context/MAIN_CONTEXT/CollectionCo import styled from 'styled-components'; import SimpleCard from '../../../REUSABLE_COMPONENTS/unique/SimpleCard'; import uniqueTheme from '../../../REUSABLE_COMPONENTS/unique/uniqueTheme'; + const FlexContainer = styled(Box)` display: flex; align-items: center; @@ -22,6 +119,7 @@ const FlexContainer = styled(Box)` width: 100%; padding: ${({ theme }) => theme.spacing(1, 2)}; `; + const CollectionListItemSkeleton = ({ count, index }) => ( @@ -44,22 +142,30 @@ CollectionListItemSkeleton.propTypes = { }; const SelectCollectionList = ({ openDialog }) => { - const { allCollections } = useSelectedCollection(); - // const [skeletonCount, setSkeletonCount] = useState(0); - const listRef = useRef(); - const minItems = 5; - const numRequired = minItems - (allCollections?.length || 0); - const allSkeletonCollections = [...Array(numRequired).keys()].map((index) => ( - - )); - const combinedCollections = [...allCollections, ...allSkeletonCollections]; + const { allCollections, allIds } = useSelectedCollection(); + const [collectionList, setCollectionList] = useState([]); + const numCollections = allIds?.length || 0; + + useEffect(() => { + const minItems = 5; + // const numCollections = allCollections?.length || 0; + const numRequired = + minItems - numCollections > 0 ? minItems - numCollections : 0; + const allSkeletonCollections = [...Array(numRequired).keys()].map( + (index) => ( + + ) + ); + const combinedCollections = [...allCollections, ...allSkeletonCollections]; + setCollectionList(combinedCollections); + }, [numCollections]); + return ( { > - {combinedCollections?.map((collection, index) => ( + {collectionList?.map((collection, index) => ( ))} - {/* */} diff --git a/src/layout/collection/collectionGrids/collections-list/statItems/PricedCardList.jsx b/src/layout/collection/collectionGrids/collections-list/statItems/PricedCardList.jsx index b6b6cc4..370aae4 100644 --- a/src/layout/collection/collectionGrids/collections-list/statItems/PricedCardList.jsx +++ b/src/layout/collection/collectionGrids/collections-list/statItems/PricedCardList.jsx @@ -1,100 +1,3 @@ -// import MDBox from '../../../../REUSABLE_COMPONENTS/MDBOX'; -// import BoxHeader from '../../../../REUSABLE_COMPONENTS/BoxHeader'; -// import useSelectedCollection from '../../../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; -// import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; -// import { Box, Card, Paper } from '@mui/material'; -// import { useAppContext, useMode } from '../../../../../context'; -// import { DataGrid } from '@mui/x-data-grid'; -// import prepareTableData from '../../../data/topCards'; -// import { roundToNearestTenth } from '../../../../../context/Helpers'; - -// const PricedCardList = () => { -// const { theme } = useMode(); - -// const colors = theme.palette.chartTheme; -// const grey = theme.palette.chartTheme.grey.darkest; -// const lightGrey = theme.palette.chartTheme.grey.lightest; -// const greenAccent = colors.greenAccent.default; -// const primary = colors.primary.dark; - -// const greenliht = colors.greenAccent.light; -// const { collectionStats, metaStats } = useCollectionStats(); -// // const { selectedCollection } = useSelectedCollection(); -// const { cardsWithQuantities } = useAppContext(); -// // const topFiveCards = cardsWithQuantities -// // ?.sort((a, b) => b.price - a.price) -// // .slice(0, 5) -// // .map((card) => ({ -// // ...card, -// // tPrice: roundToNearestTenth(card.totalPrice), -// // action: card, -// // })); -// const topFiveCards = cardsWithQuantities -// ?.sort((a, b) => b.price - a.price) -// .slice(0, 5); -// // console.log('topFiveCards:', topFiveCards); - -// const { data, columns } = prepareTableData(topFiveCards); -// console.log('data:', data); -// console.log('columns:', columns); - -// return ( -// -// -// -// -// -// -// -// -// ); -// }; - -// export default PricedCardList; import MDBox from '../../../../REUSABLE_COMPONENTS/MDBOX'; import BoxHeader from '../../../../REUSABLE_COMPONENTS/BoxHeader'; import { Box } from '@mui/material'; @@ -102,6 +5,7 @@ import { useAppContext, useMode } from '../../../../../context'; import { DataGrid } from '@mui/x-data-grid'; import prepareTableData from '../../../data/topCards'; import styled from 'styled-components'; +import { useMemo } from 'react'; const PricedCardList = () => { const { theme } = useMode(); @@ -111,10 +15,13 @@ const PricedCardList = () => { const primary = colors.primary.dark; const greenAccent = colors.greenAccent.light; const { cardsWithQuantities } = useAppContext(); - const topFiveCards = cardsWithQuantities - ?.sort((a, b) => b.price - a.price) - .slice(0, 5); - const { data, columns } = prepareTableData(topFiveCards); + const topFiveCards = useMemo(() => { + return cardsWithQuantities?.sort((a, b) => b.price - a.price).slice(0, 5); + }, [cardsWithQuantities]); + const { data, columns } = useMemo( + () => prepareTableData(topFiveCards), + [topFiveCards] + ); return ( diff --git a/src/layout/collection/collectionGrids/collections-list/statItems/TotalPriceStatBox.jsx b/src/layout/collection/collectionGrids/collections-list/statItems/TotalPriceStatBox.jsx index f97bc78..39b2d3b 100644 --- a/src/layout/collection/collectionGrids/collections-list/statItems/TotalPriceStatBox.jsx +++ b/src/layout/collection/collectionGrids/collections-list/statItems/TotalPriceStatBox.jsx @@ -1,62 +1,16 @@ -// import MonetizationOnIcon from '@mui/icons-material/MonetizationOn'; -// import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; -// import { useMode } from '../../../../../context'; -// import { Box } from '@mui/material'; -// import StatBox from '../../../../REUSABLE_COMPONENTS/StatBox'; - -// const TotalPriceStatBox = ({ sx }) => { -// const { collectionStats, metaStats } = useCollectionStats(); -// const { theme } = useMode(); -// const colors = theme.palette.chartTheme; -// const primary = colors.primary.dark; -// const greenAccent = colors.greenAccent.light; -// return ( -// -// -// } -// /> -// -// ); -// }; - -// export default TotalPriceStatBox; import { Box } from '@mui/material'; import StatBox from '../../../../REUSABLE_COMPONENTS/StatBox'; import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; import { useMode } from '../../../../../context'; import MonetizationOnIcon from '@mui/icons-material/MonetizationOn'; import styled from 'styled-components'; +import RCIcon from '../../../../REUSABLE_COMPONENTS/RCICON/RCIcon'; const TotalPriceStatBox = () => { const { theme } = useMode(); const colors = theme.palette.chartTheme; const primary = colors.primary.dark; const greenAccent = colors.greenAccent.light; - const StyledOuterBox = styled(Box)(({ theme }) => ({ - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - height: '100%', - backgroundColor: theme.palette.chartTheme.primary.dark, - borderRadius: theme.shape.borderRadius, - })); return ( { display: 'flex', justifyContent: 'center', alignItems: 'center', - // mb: '2rem', borderRadius: theme.spacing(4), height: '100%', minHeight: '135px', @@ -77,7 +30,9 @@ const TotalPriceStatBox = () => { progress="0.50" increase="+21%" icon={ - + + + // } /> diff --git a/src/layout/collection/index.jsx b/src/layout/collection/index.jsx index eba97b7..2c05168 100644 --- a/src/layout/collection/index.jsx +++ b/src/layout/collection/index.jsx @@ -8,20 +8,15 @@ import { } from '../../context'; import DashboardLayout from '../Containers/DashBoardLayout'; import MDBox from '../REUSABLE_COMPONENTS/MDBOX'; -import PageLayout from '../Containers/PageLayout'; import { PortfolioBoxA } from '../../pages/pageStyles/StyledComponents'; import { Grid, Card, Typography } from '@mui/material'; import { useFormContext } from '../../context'; import CollectionDialog from '../../components/dialogs/CollectionDialog'; import collectionPortfolioData from './data/collectionPortfolioData'; import ChartGridLayout from './collectionGrids/ChartGridLayout'; -import StatisticsCardGrid from './collectionGrids/StatisticsCardsGrid'; import CollectionPortfolioHeader from './sub-components/CollectionPortfolioHeader'; -import CollectionListStats from './collectionGrids/CollectionListStats'; import SelectCollectionList from './collectionGrids/collections-list/SelectCollectionList'; import useSelectedCollection from '../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; -import useSnackBar from '../../context/hooks/useSnackBar'; -import { withDynamicSnackbar } from '../REUSABLE_COMPONENTS/HOC/DynamicSnackbar'; import SelectionErrorDialog from '../../components/dialogs/SelectionErrorDialog'; import useCollectionManager from '../../context/MAIN_CONTEXT/CollectionContext/useCollectionManager'; import useSkeletonLoader from './collectionGrids/cards-datatable/useSkeletonLoader'; @@ -188,222 +183,4 @@ const CollectionPortfolio = () => { ); }; -export default withDynamicSnackbar(CollectionPortfolio); -// { -// viewState.showListOfAllCollections && ( -// -// -// -// -// - -// -// -// -// -// -// {dialogState.isDialogOpen && ( -// -// )} -// {dialogState.isSelectionErrorDialogOpen && ( -// -// )} -// -// -// ); -// } -// { -// viewState.showSelectedCollection && ( -// -// -// -// { -// handleBackToCollections(); -// handleSelectedCollectionView(); -// }} -// /> -// -// -// -// -// -// -// -// -// ); -// } -// const [isDialogOpen, setDialogOpen] = useState(false); -// const [isSelectionErrorDialogOpen, setSelectionErrorDialogOpen] = -// useState(false); -// const { currentForm } = useFormContext(); -// currentForm === 'addCollectionForm' -// const openNewDialog = useCallback((addOrEdit) => { -// setDialogOpen(true); // Correctly opens the dialog -// }, []); -// const handleDialogToggle = () => setDialogOpen(!isDialogOpen); -// const handleCloseDialog = () => setDialogOpen(false); -// const handleErrorDialog = () => setSelectionErrorDialogOpen(true); -// const handleCloseErrorDialog = () => setSelectionErrorDialogOpen(false); - -// if (!hasFetchedCollections) { -// return ( -// -// -// Loading... -// -// -// ); -// } - -// return ( -// -// -// {showCollections ? ( -// -// -// {/* HEADER */} -// -// -// -// {/* STATISTICS FEATURE GRID */} -// -// {/* */} -// -// {/* CHARTS */} -// -// -// -// -// -// ) : ( -// -// -// {/* HEADER */} -// -// -// -// -// -// {/* COLLECTION LIST STATS DISPLAY */} -// -// -// -// -// -// {/* COLLECTION LIST */} -// -// -// -// -// - -// {isDialogOpen && ( -// -// )} -// {isSelectionErrorDialogOpen && ( -// -// )} -// -// -// )} -// -// -// ); - -// export default withDynamicSnackbar(CollectionPortfolio); +export default CollectionPortfolio; diff --git a/src/layout/collection/sub-components/CollectionPortfolioHeader.jsx b/src/layout/collection/sub-components/CollectionPortfolioHeader.jsx index b6705e1..264382b 100644 --- a/src/layout/collection/sub-components/CollectionPortfolioHeader.jsx +++ b/src/layout/collection/sub-components/CollectionPortfolioHeader.jsx @@ -72,12 +72,13 @@ const CollectionPortfolioHeader = ({ onBack, collection, allCollections }) => { useEffect(() => { console.log('collection', collection); }, [collection]); + if ( !collection || - collection === DEFAULT_COLLECTION || - allCollections.length === 0 + collection === DEFAULT_COLLECTION + // allCollections.length === 0 ) { - return onBack(); + return ; } const headerItems = [ { @@ -126,26 +127,16 @@ const CollectionPortfolioHeader = ({ onBack, collection, allCollections }) => { width: '100%', }} > - {/* */} - + {/* */} diff --git a/src/layout/collection/sub-components/TopCardsDisplayRow.jsx b/src/layout/collection/sub-components/TopCardsDisplayRow.jsx index 825d56c..d77f98c 100644 --- a/src/layout/collection/sub-components/TopCardsDisplayRow.jsx +++ b/src/layout/collection/sub-components/TopCardsDisplayRow.jsx @@ -1,24 +1,86 @@ -import { Grid } from '@mui/material'; -import TopCardsDisplay from './TopCardsDisplay'; +import React, { useState, useMemo } from 'react'; +import { + Grid, + Card, + CardMedia, + CardContent, + Typography, + Box, +} from '@mui/material'; +import { Swiper, SwiperSlide } from 'swiper/react'; +import 'swiper/css'; +import 'swiper/css/effect-coverflow'; +import 'swiper/css/pagination'; +import 'swiper/css/navigation'; +import { Autoplay, Pagination, Navigation } from 'swiper/modules'; +import { useMode } from '../../../context'; +import useSelectedCollection from '../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; +import placeHolder from '../../../assets/images/placeholder.jpeg'; +import GenericCard from '../../../components/cards/GenericCard'; +import { StyledSwiperSlide } from '../../../pages/pageStyles/StyledComponents'; +import MDBox from '../../REUSABLE_COMPONENTS/MDBOX'; -export const TopCardsDisplayRow = ({ isSmall, theme }) => ( - - - +export const TopCardsDisplayRow = () => { + const { theme } = useMode(); + const { selectedCollection } = useSelectedCollection(); + const [activeCardIndex, setActiveCardIndex] = useState(0); + + const handleSlideChange = (swiper) => setActiveCardIndex(swiper.realIndex); + + const topFiveCards = useMemo( + () => + selectedCollection?.cards?.sort((a, b) => b.price - a.price).slice(0, 5), + [selectedCollection?.cards] + ); + + return ( + + + {topFiveCards?.map((card, index) => ( + + + + + + ))} + - -); + ); +}; diff --git a/src/layout/navigation/LogoSection.js b/src/layout/navigation/LogoSection.js deleted file mode 100644 index 92d5753..0000000 --- a/src/layout/navigation/LogoSection.js +++ /dev/null @@ -1,50 +0,0 @@ -import { ButtonBase } from '@mui/material'; -import { Link, useNavigate } from 'react-router-dom'; -import Logo from '../../assets/icons/deckIcon2.svg'; // Import SVG as a component -import config from '../../config'; - -// ==============================|| MAIN LOGO ||============================== // - -const LogoSection = () => { - const navigate = useNavigate(); - - const handleClick = () => { - navigate(config?.defaultPath); - }; - - return ( - - Logo - - ); -}; - -export default LogoSection; diff --git a/src/layout/navigation/LongMenu.jsx b/src/layout/navigation/LongMenu.jsx index 8a63783..f7992f1 100644 --- a/src/layout/navigation/LongMenu.jsx +++ b/src/layout/navigation/LongMenu.jsx @@ -46,8 +46,6 @@ const LongMenu = React.forwardRef( open={open} onClose={handleClose} sx={{ - // maxHeight: ITEM_HEIGHT * 4.5, - // width: 250, '& .MuiMenu-paper': { maxHeight: ITEM_HEIGHT * 4.5, width: 250, diff --git a/src/layout/navigation/MenuCard.jsx b/src/layout/navigation/MenuCard.jsx index c874637..b2f2605 100644 --- a/src/layout/navigation/MenuCard.jsx +++ b/src/layout/navigation/MenuCard.jsx @@ -98,7 +98,7 @@ const MenuCard = () => { sx={{ ...theme.typography.commonAvatar, ...theme.typography.largeAvatar, - color: theme.palette.primary.main, + color: theme.palette.primary.dark, border: 'none', borderColor: theme.palette.primary.main, background: '#fff', diff --git a/src/layout/navigation/MenuItemComponent.jsx b/src/layout/navigation/MenuItemComponent.jsx index af55e97..fcca2a8 100644 --- a/src/layout/navigation/MenuItemComponent.jsx +++ b/src/layout/navigation/MenuItemComponent.jsx @@ -20,25 +20,6 @@ import { } from '../../pages/pageStyles/StyledComponents'; import { useSpring, animated } from 'react-spring'; import MDTypography from '../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -const CardStyle = styled(Card)(({ theme }) => ({ - background: 'transparent', - // marginBottom: '22px', - height: '100%', - width: '100%', - overflow: 'hidden', - position: 'relative', - '&:after': { - content: '""', - position: 'absolute', - // height: '100%', - // width: '157px', - // height: '157px', - // background: theme.palette.primary[200], - borderRadius: '50%', - // top: '-105px', - // right: '-96px', - }, -})); const MenuItemComponent = ({ item, onClick, visibleItems, index }) => { const { theme } = useMode(); const navigate = useNavigate(); diff --git a/src/layout/navigation/Navigation.jsx b/src/layout/navigation/Navigation.jsx index 0ab7b22..7d8f302 100644 --- a/src/layout/navigation/Navigation.jsx +++ b/src/layout/navigation/Navigation.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { AppBar, Toolbar, @@ -6,9 +6,6 @@ import { Box, Drawer, List, - Divider, - Typography, - useTheme, Hidden, Card, CardContent, @@ -19,25 +16,13 @@ import { ListItemText, } from '@mui/material'; import MenuIcon from '@mui/icons-material/Menu'; -import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; -import ChevronRightIcon from '@mui/icons-material/ChevronRight'; -import LogoSection from './LogoSection'; -import MenuItemComponent from './MenuItemComponent'; import { useCartStore, useMode, useSidebarContext } from '../../context'; -import MenuCard from './MenuCard'; -import { - StyledAppBar, - StyledMenuItem, - StyledToolbar, - DrawerHeader, - StyledBox, - StyledSwipeableDrawer, -} from '../../pages/pageStyles/StyledComponents'; +import { StyledAppBar } from '../../pages/pageStyles/StyledComponents'; import { Navigate, useNavigate } from 'react-router-dom'; import getMenuItemsData from './menuItemsData'; -import styled from 'styled-components'; import { useSpring, animated, useSprings } from 'react-spring'; import MDTypography from '../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; +import RCLogoSection from '../REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection'; const Navigation = ({ isLoggedIn }) => { const { theme } = useMode(); const navigate = useNavigate(); @@ -47,50 +32,56 @@ const Navigation = ({ isLoggedIn }) => { /iPad|iPhone|iPod/.test(navigator.userAgent); const [isOpen, setIsOpen] = useState(false); // Manage open state locally const [isMobileView, setIsMobileView] = useState(window.innerWidth < 768); - const toggleSidebar = () => { - setIsOpen(!isOpen); - }; - const [menuItems, setMenuItems] = useState([]); - useEffect(() => { - const handleResize = () => setIsMobileView(window.innerWidth < 768); - window.addEventListener('resize', handleResize); - return () => window.removeEventListener('resize', handleResize); - }, []); const iconColor = isMobileView ? theme.palette.primary.main : 'white'; - // New state to track if component is mounted - const [isMounted, setIsMounted] = useState(false); - useEffect(() => { - setIsMounted(true); // Set to true when component mounts - - // Fetch data as before const fetchData = async () => { - const cartCardQuantity = totalQuantity; const items = await getMenuItemsData( isLoggedIn, - cartCardQuantity, + totalQuantity, iconColor - ); // Simulated fetch call - - if (isMounted) { - // Check if component is still mounted before setting state - setMenuItems(items.map((item) => ({ ...item, isVisible: true }))); // Assuming visibility logic is simplified - } + ); + setMenuItems(items.map((item) => ({ ...item, isVisible: true }))); }; + fetchData(); + }, [isLoggedIn, totalQuantity, iconColor]); + const toggleSidebar = useCallback(() => setIsOpen(!isOpen), [isOpen]); - return () => setIsMounted(false); // Set to false when component unmounts - }, [isLoggedIn, totalQuantity, iconColor, isMounted]); // Include isMounted in dependency array if it's used within the effect + const [menuItems, setMenuItems] = useState([]); + useEffect(() => { + const handleResize = () => setIsMobileView(window.innerWidth < 768); + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, []); + const [isMounted, setIsMounted] = useState(false); + // useEffect(() => { + // setIsMounted(true); // Set to true when component mounts + + // // Fetch data as before + // const fetchData = async () => { + // const cartCardQuantity = totalQuantity; + // const items = await getMenuItemsData( + // isLoggedIn, + // cartCardQuantity, + // iconColor + // ); // Simulated fetch call + + // if (isMounted) { + // // Check if component is still mounted before setting state + // setMenuItems(items.map((item) => ({ ...item, isVisible: true }))); // Assuming visibility logic is simplified + // } + // }; + // fetchData(); + + // return () => setIsMounted(false); // Set to false when component unmounts + // }, [isLoggedIn, totalQuantity, iconColor, isMounted]); // Include isMounted in dependency array if it's used within the effect const [springs, api] = useSprings(menuItems.length, (index) => ({ from: { opacity: 0, transform: 'translateY(-20px)' }, to: { opacity: 1, transform: 'translateY(0)' }, delay: index * 100, // Delay based on index })); - const handleDrawerToggle = () => { - toggleSidebar(); - }; const renderMenuItems = (type) => springs.map((style, index) => ( @@ -98,10 +89,17 @@ const Navigation = ({ isLoggedIn }) => { navigate(menuItems[index].to)} sx={{ + width: 'clamp(250px, 50%, 300px)', // Responsive width using clamp '&:hover': { backgroundColor: theme.palette.backgroundF.light, color: 'white', }, + '& .MuiListItemAvatar-root': { + justifyContent: 'flex-end', + }, + '& .MuiListItemText-root': { + mr: 1, + }, }} > @@ -135,7 +133,10 @@ const Navigation = ({ isLoggedIn }) => { )); return ( <> - + { {isMobileView ? ( - + ) : ( renderMenuItems('top') @@ -164,7 +165,7 @@ const Navigation = ({ isLoggedIn }) => { {renderMenuItems('side')} diff --git a/src/layout/navigation/menuItemsData.jsx b/src/layout/navigation/menuItemsData.jsx index d5b722d..014aeee 100644 --- a/src/layout/navigation/menuItemsData.jsx +++ b/src/layout/navigation/menuItemsData.jsx @@ -6,7 +6,7 @@ import { Assessment as CollectionIcon, Person as ProfileIcon, } from '@mui/icons-material'; -import DeckBuilderIcon from '../../components/reusable/icons/DeckBuilderIcon'; +import DeckBuilderIcon from '../REUSABLE_COMPONENTS/icons/DeckBuilderIcon'; import { Badge } from '@mui/material'; import { useCartStore } from '../../context/MAIN_CONTEXT/CartContext/CartContext'; export const getMenuItemsData = (isLoggedIn, cartCardQuantity, iconColor) => { diff --git a/src/layout/store/StoreSearch.jsx b/src/layout/store/StoreSearch.jsx index 51d2d99..19a7129 100644 --- a/src/layout/store/StoreSearch.jsx +++ b/src/layout/store/StoreSearch.jsx @@ -4,6 +4,7 @@ import MDBox from '../REUSABLE_COMPONENTS/MDBOX'; import PageLayout from '../Containers/PageLayout'; import { PortfolioBoxA } from '../../pages/pageStyles/StyledComponents'; import SearchComponent from '../../components/forms/search/SearchComponent'; +import { Card } from '@mui/material'; const StoreSearch = () => { const { theme } = useMode(); diff --git a/src/pages/HomePage.js b/src/pages/HomePage.js index 44c8219..922fda7 100644 --- a/src/pages/HomePage.js +++ b/src/pages/HomePage.js @@ -58,9 +58,9 @@ const HomePage = () => { {/* MAIN CONTENT SECTION */} - + {/* - + */} {/* FEATURE CARDS SECTION */} diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 3b5c1df..5b83180 100644 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -1,100 +1,8 @@ import React, { useState } from 'react'; -import { - Box, - Button, - Typography, - Avatar, - IconButton, - Container, - Snackbar, - Grid, - Paper, -} from '@mui/material'; -import { Edit as EditIcon } from '@mui/icons-material'; -import placeholder from '../assets/images/placeholder.jpeg'; -import { useUserContext } from '../context/MAIN_CONTEXT/UserContext/UserContext'; -import { useCookies } from 'react-cookie'; -import ThemeToggleButton from '../components/buttons/other/ThemeToggleButton'; -import ProfileForm from '../components/forms/ProfileForm'; -import useResponsiveStyles from '../context/hooks/style-hooks/useResponsiveStyles'; -import { useMode } from '../context'; -import UserStats from '../layout/profile/UserStats'; import Overview from '../layout/profile/index'; const ProfilePage = () => { - const { updateUser } = useUserContext(); - const { theme } = useMode(); - const { isLarge } = useResponsiveStyles(theme); - // const isLarge = useMediaQuery(theme.breakpoints.up('lg')); - const [cookies] = useCookies(['user']); - const user = cookies?.user; - const [snackbarData, setSnackbarData] = useState({ - open: false, - message: '', - }); - - const openSnackbar = (message) => { - setSnackbarData({ open: true, message }); - }; - - const openEdit = () => { - openSnackbar('Edit mode enabled'); - }; - - const handleSaveChanges = (data) => { - updateUser(data); - openSnackbar('Saved changes.'); - }; - return ; }; export default ProfilePage; -{ - /* */ -} - -{ - /* - - - {user?.userBasicData?.firstName || 'User Profile'} - - openEdit()}> - - - - - - - - - Personal Information - - - - - - - - Statistics - - - - - - - setSnackbarData({ ...snackbarData, open: false })} - message={snackbarData.message} - /> */ -} -{ - /* */ -} diff --git a/src/pages/index.js b/src/pages/index.js index 7160fd1..f65ccae 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -6,4 +6,4 @@ export { default as CollectionPage } from './CollectionPage'; export { default as CartPage } from './CartPage'; export { default as SplashPage } from '../assets/animations/SplashPage'; export { default as StorePage } from './StorePage'; -export { default as LoginPage } from './LoginPage'; +export { default as LoginPage } from '../save/LoginPage'; diff --git a/src/pages/pageStyles/StyledComponents.jsx b/src/pages/pageStyles/StyledComponents.jsx index 2b5cce7..bad5dac 100644 --- a/src/pages/pageStyles/StyledComponents.jsx +++ b/src/pages/pageStyles/StyledComponents.jsx @@ -567,7 +567,7 @@ export const AspectRatioBoxSkeleton = styled(Box)(({ theme }) => ({ export const StyledCollectionListCard = styled(Card)(({ theme }) => ({ // margin: theme.spacing(1), width: '100%', - // height: '100%', + height: '100%', flexGrow: 1, transition: 'transform 0.3s ease-in-out', boxShadow: '0 8px 40px -12px rgba(0,0,0,0.3)', diff --git a/src/pages/sections/HeroSection.jsx b/src/pages/sections/HeroSection.jsx index db07bb2..6200776 100644 --- a/src/pages/sections/HeroSection.jsx +++ b/src/pages/sections/HeroSection.jsx @@ -15,8 +15,45 @@ import { } from 'swiper/modules'; import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; import HeroSectionSkeleton from '../../layout/REUSABLE_COMPONENTS/SkeletonVariants'; -import { Box, Card, useMediaQuery } from '@mui/material'; +import { + Box, + Card, + Grid, + IconButton, + Typography, + useMediaQuery, +} from '@mui/material'; +import DashboardBox from '../../layout/REUSABLE_COMPONENTS/DashboardBox'; +import AttachMoneyIcon from '@mui/icons-material/AttachMoney'; +// Replace headerItems with realistic card store data +const storeInfoItems = [ + { icon: , label: 'Total Sales', value: '$152,300' }, + { icon: , label: 'Average Order', value: '$350' }, + { icon: , label: 'Total Products', value: '1250' }, +]; +const StoreInfoItem = ({ icon, label, value, delay }) => { + return ( + + {icon} + + {label} + {value} + + + ); +}; const HeroSection = () => { const { theme } = useMode(); const { breakpoints } = theme; @@ -47,26 +84,17 @@ const HeroSection = () => { }} > { }} > { height: '100%', }} > - {/* Content inside the card */} + + + + + + {storeInfoItems.map((item, index) => ( + + ))} + + + `${cards[index].name}`, // Rendering titles as bullets }} scrollbar={{ el: '.swiper-scrollbar', @@ -146,17 +192,16 @@ const HeroSection = () => { clickable: true, }} autoplay={{ - // Enable autoplay with a delay for slow rotation delay: 2500, // Delay in milliseconds (2.5 seconds) disableOnInteraction: false, // Continues autoplay when interacted with }} style={{ + // minWidth: '150vw', minWidth: '150vw', width: '100%', - // marginLeft: '60vw', - // position: 'absolute', // Position absolute to control its exact location + alignItems: isMobileView ? 'center' : 'flex-start', position: isMobileView ? 'relative' : 'absolute', - marginLeft: isMobileView ? '0' : '60vw', + ml: isMobileView ? '0' : '60vw', }} modules={[EffectCoverflow, Pagination, Navigation, Autoplay]} // Include Autoplay module className="swiper_container" @@ -170,50 +215,38 @@ const HeroSection = () => { display: 'flex', flexDirection: 'column', alignItems: 'center', - justifyContent: 'center', width: '100%', height: '100%', transform: - index === activeCardIndex ? 'scale(1.5)' : 'scale(1)', + index === activeCardIndex ? 'scale(1.7)' : 'scale(1)', transition: 'transform 0.9s', - // position: 'relative', + position: 'relative', // Ensure the slide content is positioned relatively }} > - {topFiveCards[activeCardIndex]?.name || ''} - - - {topFiveCards[activeCardIndex]?.description || ''} + {card.name} {`slide_${index}`} diff --git a/src/save/AuthSwitch.jsx b/src/save/AuthSwitch.jsx new file mode 100644 index 0000000..4ef0f4f --- /dev/null +++ b/src/save/AuthSwitch.jsx @@ -0,0 +1,128 @@ +// import React from 'react'; +// import { renderToStaticMarkup } from 'react-dom/server'; + +// import { Switch, FormControlLabel, FormControl, alpha } from '@mui/material'; +// import { useFormContext, useMode } from '../../../context'; // Adjust with actual path +// import { AuthModeSwitch } from '../../../layout/REUSABLE_STYLED_COMPONENTS/SpecificStyledComponents'; +// import LoginIcon from '@mui/icons-material/Login'; +// import PersonAddIcon from '@mui/icons-material/PersonAdd'; +// import styled from 'styled-components'; +// import { useCookies } from 'react-cookie'; +// const convertSvg = (svg) => { +// const markup = renderToStaticMarkup(svg); +// const encoded = encodeURIComponent(markup); +// const dataUri = `url('data:image/svg+xml;utf8,${encoded}')`; +// return dataUri; +// }; +// const AuthSwitch = () => { +// // const AuthSwitch = ({ signupMode, formLabel }) => { +// const { theme } = useMode(); // Ensures theme is applied correctly +// // const colors = theme; +// const colors = theme.palette.chartTheme; +// const cookies = useCookies('colorMode'); +// const mode = cookies.colorMode; + +// const primary = colors.primary.default; +// const blue = colors.blueAccent.default; +// const green = colors.greenAccent.light; +// const lihhtgreen = colors.greenAccent.default; +// const greenliht = colors.greenAccent.light; +// const lightgrey = colors.grey.light; +// const darkgrey = colors.grey.dark; +// const darkestgrey = colors.grey.darkest; + +// const { currentSchemaKey, toggleForm } = useFormContext(); // Use toggleForm for toggling modes +// const signupMode = currentSchemaKey === 'signupForm'; +// const handleToggle = () => { +// toggleForm(currentSchemaKey === 'loginForm' ? 'signupForm' : 'loginForm'); +// }; +// const switchBaseStyles = { +// '& .MuiSwitch-switchBase': { +// padding: 1, // Center the switch base padding for proper alignment +// '&.Mui-checked': { +// transform: 'translateX(16px)', // Ensure this aligns with your switch size +// color: theme.palette.common.white, // Thumb color when checked +// '& + .MuiSwitch-track': { +// backgroundColor: theme.palette.primary.main, // Track color when checked +// }, +// }, +// }, +// }; +// const thumbStyles = { +// '& .MuiSwitch-thumb': { +// width: 22, // Adjust thumb size for better visual alignment +// height: 22, // Adjust thumb size for better visual alignment +// backgroundColor: mode === 'dark' ? green : lihhtgreen, +// // backgroundColor: theme.palette.common.white, // Default thumb color + +// '&:before': { +// content: '" "', +// display: 'block', +// backgroundImage: signupMode +// ? convertSvg() +// : convertSvg(), +// width: '100%', +// height: '100%', +// backgroundSize: '50%', +// backgroundPosition: 'center', +// backgroundRepeat: 'no-repeat', +// }, +// // '&:after': { +// // right: 12, // Adjust the right icon position +// // backgroundImage: convertSvg(), +// // }, +// }, +// }; +// const trackStyles = { +// '& .MuiSwitch-track': { +// backgroundColor: theme.palette.chartTheme.grey.light, // Default track color +// opacity: 1, +// width: 50, // Adjust thumb size for better visual alignment +// height: 14, // Adjust thumb size for better visual alignment +// // '&:before, &:after': { +// // content: '""', +// // position: 'absolute', +// // top: '50%', +// // transform: 'translateY(-50%)', +// // }, +// // '&:before': { +// // left: 12, // Adjust the left icon position +// // backgroundImage: convertSvg(), +// // }, +// // '&:after': { +// // right: 12, // Adjust the right icon position +// // backgroundImage: convertSvg(), +// // }, +// }, +// }; +// const switchStyles = { +// ...switchBaseStyles, +// ...thumbStyles, +// ...trackStyles, +// // backgroundImage: convertSvg(), +// // right: 2, +// }; + +// return ( +// +// +// } +// label={signupMode ? 'Sign Up' : 'Log In'} +// style={{ margin: 'auto', justifyContent: 'center' }} // Center label and switch +// /> +// +// ); +// }; + +// export default AuthSwitch; diff --git a/src/layout/collection/sub-components/CollectionGoalsTimeLine.jsx b/src/save/CollectionGoalsTimeLine.jsx similarity index 100% rename from src/layout/collection/sub-components/CollectionGoalsTimeLine.jsx rename to src/save/CollectionGoalsTimeLine.jsx diff --git a/src/layout/collection/collectionGrids/CollectionListStats.jsx b/src/save/CollectionListStats.jsx similarity index 76% rename from src/layout/collection/collectionGrids/CollectionListStats.jsx rename to src/save/CollectionListStats.jsx index 72ef20e..87cc064 100644 --- a/src/layout/collection/collectionGrids/CollectionListStats.jsx +++ b/src/save/CollectionListStats.jsx @@ -1,9 +1,9 @@ import { Grid, Skeleton } from '@mui/material'; -import TotalValueOfCollectionsDisplay from '../sub-components/TotalValueOfCollectionsDisplay'; -import TopFiveExpensiveCards from '../sub-components/TopFiveExpensiveCards'; -import { useStatisticsStore } from '../../../context'; -import SimpleCard from '../../REUSABLE_COMPONENTS/unique/SimpleCard'; -import uniqueTheme from '../../REUSABLE_COMPONENTS/unique/uniqueTheme'; +import TotalValueOfCollectionsDisplay from './TotalValueOfCollectionsDisplay'; +import TopFiveExpensiveCards from './TopFiveExpensiveCards'; +import { useStatisticsStore } from '../context'; +import SimpleCard from '../layout/REUSABLE_COMPONENTS/unique/SimpleCard'; +import uniqueTheme from '../layout/REUSABLE_COMPONENTS/unique/uniqueTheme'; const CollectionListStats = () => { const { topFiveCards, totalValue, chartData } = useStatisticsStore(); diff --git a/src/layout/collection/sub-components/ComplexStatisticsCard.jsx b/src/save/ComplexStatisticsCard.jsx similarity index 95% rename from src/layout/collection/sub-components/ComplexStatisticsCard.jsx rename to src/save/ComplexStatisticsCard.jsx index b8062a3..4476b8a 100644 --- a/src/layout/collection/sub-components/ComplexStatisticsCard.jsx +++ b/src/save/ComplexStatisticsCard.jsx @@ -2,9 +2,9 @@ import PropTypes from 'prop-types'; import Card from '@mui/material/Card'; import Divider from '@mui/material/Divider'; import Icon from '@mui/material/Icon'; -import MDBox from '../../REUSABLE_COMPONENTS/MDBOX/index'; -import MDTypography from '../../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -import { useMode } from '../../../context'; +import MDBox from '../layout/REUSABLE_COMPONENTS/MDBOX/index'; +import MDTypography from '../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; +import { useMode } from '../context'; function ComplexStatisticsCard({ color, title, count, percentage, icon, sx }) { const { theme } = useMode(); diff --git a/src/components/reusable/CustomPagination.jsx b/src/save/CustomPagination.jsx similarity index 93% rename from src/components/reusable/CustomPagination.jsx rename to src/save/CustomPagination.jsx index 35ef3ec..4d61aff 100644 --- a/src/components/reusable/CustomPagination.jsx +++ b/src/save/CustomPagination.jsx @@ -1,6 +1,6 @@ import React from 'react'; import { Box, Pagination } from '@mui/material'; -import { useMode } from '../../context'; +import { useMode } from '../context'; const CustomPagination = ({ totalCount, diff --git a/src/pages/LoginPage.jsx b/src/save/LoginPage.jsx similarity index 100% rename from src/pages/LoginPage.jsx rename to src/save/LoginPage.jsx diff --git a/src/layout/collection/sub-components/PieChartStats.jsx b/src/save/PieChartStats.jsx similarity index 100% rename from src/layout/collection/sub-components/PieChartStats.jsx rename to src/save/PieChartStats.jsx diff --git a/src/layout/navigation/SideBar.jsx b/src/save/SideBar.jsx similarity index 93% rename from src/layout/navigation/SideBar.jsx rename to src/save/SideBar.jsx index 50f50a1..db06af6 100644 --- a/src/layout/navigation/SideBar.jsx +++ b/src/save/SideBar.jsx @@ -11,17 +11,17 @@ import { ListItemButton, Collapse, } from '@mui/material'; -import MenuItemComponent from './MenuItemComponent'; -import { useMode, useSidebarContext } from '../../context'; +import MenuItemComponent from '../layout/navigation/MenuItemComponent'; +import { useMode, useSidebarContext } from '../context'; import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import { DrawerHeader, StyledBox, StyledSwipeableDrawer, -} from '../../pages/pageStyles/StyledComponents'; +} from '../pages/pageStyles/StyledComponents'; import { ExpandLess, ExpandMore } from '@mui/icons-material'; -import MenuCard from './MenuCard'; +import MenuCard from '../layout/navigation/MenuCard'; // ==============================|| SIDEBAR DRAWER ||============================== // diff --git a/src/layout/collection/collectionGrids/StatisticsCardsGrid.jsx b/src/save/StatisticsCardsGrid.jsx similarity index 85% rename from src/layout/collection/collectionGrids/StatisticsCardsGrid.jsx rename to src/save/StatisticsCardsGrid.jsx index 2953f8a..a24a0bb 100644 --- a/src/layout/collection/collectionGrids/StatisticsCardsGrid.jsx +++ b/src/save/StatisticsCardsGrid.jsx @@ -1,9 +1,9 @@ import React, { useEffect, useState } from 'react'; import { Grid } from '@mui/material'; -import MDBox from '../../REUSABLE_COMPONENTS/MDBOX'; -import ComplexStatisticsCard from '../sub-components/ComplexStatisticsCard'; -import LoadingIndicator from '../../../components/reusable/indicators/LoadingIndicator'; -import useSelectedCollection from '../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; +import MDBox from '../layout/REUSABLE_COMPONENTS/MDBOX'; +import ComplexStatisticsCard from './ComplexStatisticsCard'; +import LoadingIndicator from '../layout/LoadingIndicator'; +import useSelectedCollection from '../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; const cardData = [ { diff --git a/src/layout/collection/sub-components/StatisticsDisplaySection.jsx b/src/save/StatisticsDisplaySection.jsx similarity index 97% rename from src/layout/collection/sub-components/StatisticsDisplaySection.jsx rename to src/save/StatisticsDisplaySection.jsx index 43bb2e9..d98cd0f 100644 --- a/src/layout/collection/sub-components/StatisticsDisplaySection.jsx +++ b/src/save/StatisticsDisplaySection.jsx @@ -2,11 +2,11 @@ import React from 'react'; import PropTypes from 'prop-types'; import { styled } from '@mui/system'; import { Card, CardContent, Typography, Box } from '@mui/material'; -import { useMode } from '../../../context'; +import { useMode } from '../context'; import PieChartIcon from '@mui/icons-material/PieChart'; import AttachMoneyIcon from '@mui/icons-material/AttachMoney'; import EmojiEventsIcon from '@mui/icons-material/EmojiEvents'; -import MDBox from '../../REUSABLE_COMPONENTS/MDBOX'; +import MDBox from '../layout/REUSABLE_COMPONENTS/MDBOX'; const StatisticCard = styled(Card)(({ theme }) => ({ height: '100%', diff --git a/src/layout/navigation/TopBar.jsx b/src/save/TopBar.jsx similarity index 92% rename from src/layout/navigation/TopBar.jsx rename to src/save/TopBar.jsx index 1ea562f..6f1ac4a 100644 --- a/src/layout/navigation/TopBar.jsx +++ b/src/save/TopBar.jsx @@ -8,16 +8,16 @@ import { Button, } from '@mui/material'; import { useNavigate } from 'react-router-dom'; -import { useMode, useSidebarContext } from '../../context'; -import LogoSection from './LogoSection'; -import MenuItemComponent from './MenuItemComponent'; +import { useMode, useSidebarContext } from '../context'; +import LogoSection from '../layout/navigation/LogoSection'; +import MenuItemComponent from '../layout/navigation/MenuItemComponent'; import MenuIcon from '@mui/icons-material/Menu'; import { StyledAppBar, StyledMenuItem, StyledToolbar, -} from '../../pages/pageStyles/StyledComponents'; +} from '../pages/pageStyles/StyledComponents'; const TopBar = ({ isMobileView, isLoggedIn, handleDrawer }) => { const { theme } = useMode(); const navigate = useNavigate(); diff --git a/src/layout/collection/sub-components/TopFiveExpensiveCards.jsx b/src/save/TopFiveExpensiveCards.jsx similarity index 100% rename from src/layout/collection/sub-components/TopFiveExpensiveCards.jsx rename to src/save/TopFiveExpensiveCards.jsx diff --git a/src/layout/collection/sub-components/TotalValueOfCollectionsDisplay.jsx b/src/save/TotalValueOfCollectionsDisplay.jsx similarity index 100% rename from src/layout/collection/sub-components/TotalValueOfCollectionsDisplay.jsx rename to src/save/TotalValueOfCollectionsDisplay.jsx diff --git a/src/components/forms/CustomSelector.js b/src/zcleanup/CustomSelector.js similarity index 100% rename from src/components/forms/CustomSelector.js rename to src/zcleanup/CustomSelector.js diff --git a/src/layout/collection/sub-components/Notifications.jsx b/src/zcleanup/Notifications.jsx similarity index 93% rename from src/layout/collection/sub-components/Notifications.jsx rename to src/zcleanup/Notifications.jsx index b987287..2284473 100644 --- a/src/layout/collection/sub-components/Notifications.jsx +++ b/src/zcleanup/Notifications.jsx @@ -1,17 +1,3 @@ -/** -========================================================= -* Material Dashboard 2 React - v2.2.0 -========================================================= - -* Product Page: https://www.creative-tim.com/product/material-dashboard-react -* Copyright 2023 Creative Tim (https://www.creative-tim.com) - -Coded by www.creative-tim.com - - ========================================================= - -* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -*/ import PriceChangeIcon from '@mui/icons-material/PriceChange'; import { useState } from 'react'; From 3d26ed38a0dd85d2bae8a31705d3ed5082bf4231 Mon Sep 17 00:00:00 2001 From: Reed Vogt Date: Sun, 17 Mar 2024 06:26:39 -0700 Subject: [PATCH 04/10] significant code base clean up --- .../actionButtons/GenericActionButtons.jsx | 12 - src/components/buttons/other/DeckSwitch.jsx | 45 ---- .../buttons/other/ReusableLoadingButton.jsx | 73 ------ src/components/cards/CardCarousel.jsx | 44 ---- src/components/cards/CardDetail.jsx | 23 -- src/components/cards/CardDetails.jsx | 72 +++--- src/components/cards/CardTextSection.jsx | 119 --------- src/components/cards/CarouselCard.jsx | 160 ------------ src/components/cards/GenericCard.jsx | 1 + .../{homeDetailsModal => }/DetailsModal.jsx | 2 +- .../{cardDialog => }/GenericCardDialog.jsx | 16 +- .../{stripeModal => }/StripeCheckoutModal.js | 2 +- src/components/forms/AddDeckForm.jsx | 64 ----- src/components/forms/UpdateDeckForm.jsx | 84 ------- src/components/forms/cleanup/CronTrigger.jsx | 27 -- .../forms/cleanup/EditUserProfileForm.jsx | 87 ------- .../forms/cleanup/EditUserSettingsForm.jsx | 124 ---------- .../forms/cleanup/ThemeToggleButton.jsx | 49 ---- src/components/forms/reusable/RCZodForm.jsx | 156 ------------ .../grids/deckBuilderGrids/CardsGrid.js | 75 ------ .../grids/gridItems/ReusableSkeletonItem.jsx | 30 --- .../grids/gridItems/SkeletonStoreItem.jsx | 35 --- src/components/grids/gridItems/StoreItem.jsx | 35 --- .../AppContext/AppContextProvider.jsx | 11 +- .../StatisticsContext/StatisticsContext.jsx | 48 +--- src/context/hooks/useGridItems.jsx | 4 +- src/data/collectionPortfolioData.jsx | 36 --- src/data/searchData.jsx | 42 +++- .../cards => layout}/AnimatedFeatureCard.jsx | 37 +-- .../ReusableSkeletonItem.jsx | 18 ++ .../REUSABLE_COMPONENTS/SkeletonCard.jsx} | 9 +- .../sub-components/TopCardsDisplayRow.jsx | 110 ++++++++- src/layout/deck/CardsDisplay.jsx | 23 -- src/layout/deck/DeckDisplay.js | 24 +- .../dialogs => layout/deck}/DeckEditPanel.js | 2 +- src/layout/deck/DeckEditor.jsx | 44 +--- src/layout/deck/DeckListToggle.jsx | 52 ---- .../deck}/SelectDeckList.jsx | 6 +- src/layout/navigation/MenuItemComponent.jsx | 77 ------ src/layout/navigation/Navigation.jsx | 64 ++--- src/pages/CollectionPage.js | 2 +- src/pages/DeckBuilderPage.js | 2 +- src/pages/HomePage.js | 4 +- src/pages/StorePage.js | 2 +- src/pages/sections/FeatureCardsSection.jsx | 2 +- src/save/CardsDisplay.jsx | 23 ++ src/save/CardsGrid.js | 75 ++++++ src/{layout/navigation => save}/MenuCard.jsx | 0 src/zcleanup/AddButton.jsx | 71 ------ src/zcleanup/CollectionPortfolioContent.jsx | 58 ----- src/zcleanup/CustomSelector.js | 93 ------- src/zcleanup/InputComponents/CardNameInput.js | 22 -- .../InputComponents/UpdateStatusBox.jsx | 100 -------- .../InputComponents/UpdateStatusBox2.jsx | 91 ------- src/zcleanup/Notifications.jsx | 230 ------------------ src/zcleanup/RemoveButton.jsx | 75 ------ src/zcleanup/SelectCollection.jsx | 84 ------- src/zcleanup/dataDisplay/CardCountDisplay.jsx | 42 ---- src/zcleanup/dataDisplay/CartTotal.jsx | 10 - src/zcleanup/dataDisplay/StatBox.jsx | 43 ---- src/zcleanup/dataDisplay/StatCard.jsx | 17 -- src/zcleanup/renderFullWidthAddButton.jsx | 185 -------------- .../styleOverride/compStyleOverride.jsx | 187 -------------- 63 files changed, 377 insertions(+), 2983 deletions(-) delete mode 100644 src/components/buttons/other/DeckSwitch.jsx delete mode 100644 src/components/cards/CardCarousel.jsx delete mode 100644 src/components/cards/CardTextSection.jsx delete mode 100644 src/components/cards/CarouselCard.jsx rename src/components/dialogs/{homeDetailsModal => }/DetailsModal.jsx (98%) rename src/components/dialogs/{cardDialog => }/GenericCardDialog.jsx (92%) rename src/components/dialogs/{stripeModal => }/StripeCheckoutModal.js (96%) delete mode 100644 src/components/forms/cleanup/CronTrigger.jsx delete mode 100644 src/components/forms/cleanup/EditUserProfileForm.jsx delete mode 100644 src/components/forms/cleanup/EditUserSettingsForm.jsx delete mode 100644 src/components/forms/cleanup/ThemeToggleButton.jsx delete mode 100644 src/components/grids/deckBuilderGrids/CardsGrid.js delete mode 100644 src/components/grids/gridItems/ReusableSkeletonItem.jsx delete mode 100644 src/components/grids/gridItems/SkeletonStoreItem.jsx delete mode 100644 src/components/grids/gridItems/StoreItem.jsx rename src/{components/cards => layout}/AnimatedFeatureCard.jsx (68%) create mode 100644 src/layout/REUSABLE_COMPONENTS/ReusableSkeletonItem.jsx rename src/{components/grids/gridItems/SkeletonDeckItem.jsx => layout/REUSABLE_COMPONENTS/SkeletonCard.jsx} (83%) delete mode 100644 src/layout/deck/CardsDisplay.jsx rename src/{components/dialogs => layout/deck}/DeckEditPanel.js (97%) delete mode 100644 src/layout/deck/DeckListToggle.jsx rename src/{components/grids/deckBuilderGrids => layout/deck}/SelectDeckList.jsx (82%) delete mode 100644 src/layout/navigation/MenuItemComponent.jsx create mode 100644 src/save/CardsDisplay.jsx create mode 100644 src/save/CardsGrid.js rename src/{layout/navigation => save}/MenuCard.jsx (100%) delete mode 100644 src/zcleanup/AddButton.jsx delete mode 100644 src/zcleanup/CollectionPortfolioContent.jsx delete mode 100644 src/zcleanup/CustomSelector.js delete mode 100644 src/zcleanup/InputComponents/CardNameInput.js delete mode 100644 src/zcleanup/InputComponents/UpdateStatusBox.jsx delete mode 100644 src/zcleanup/InputComponents/UpdateStatusBox2.jsx delete mode 100644 src/zcleanup/Notifications.jsx delete mode 100644 src/zcleanup/RemoveButton.jsx delete mode 100644 src/zcleanup/SelectCollection.jsx delete mode 100644 src/zcleanup/dataDisplay/CardCountDisplay.jsx delete mode 100644 src/zcleanup/dataDisplay/CartTotal.jsx delete mode 100644 src/zcleanup/dataDisplay/StatBox.jsx delete mode 100644 src/zcleanup/dataDisplay/StatCard.jsx delete mode 100644 src/zcleanup/renderFullWidthAddButton.jsx delete mode 100644 src/zcleanup/styleOverride/compStyleOverride.jsx diff --git a/src/components/buttons/actionButtons/GenericActionButtons.jsx b/src/components/buttons/actionButtons/GenericActionButtons.jsx index fe5e2e9..88f60e6 100644 --- a/src/components/buttons/actionButtons/GenericActionButtons.jsx +++ b/src/components/buttons/actionButtons/GenericActionButtons.jsx @@ -1,12 +1,8 @@ import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { Box } from '@mui/material'; import MDTypography from '../../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -import AddButton from '../../../zcleanup/AddButton'; -import RemoveButton from '../../../zcleanup/RemoveButton'; import { useModalContext } from '../../../context/UTILITIES_CONTEXT/ModalContext/ModalContext'; -import useSelectedContext from '../../../context/hooks/useSelectedContext'; import { getContextIcon } from '../../../layout/REUSABLE_COMPONENTS/icons/index'; - import { useDeckStore } from '../../../context/MAIN_CONTEXT/DeckContext/DeckContext'; import { useCartStore } from '../../../context/MAIN_CONTEXT/CartContext/CartContext'; import useCollectionManager from '../../../context/MAIN_CONTEXT/CollectionContext/useCollectionManager'; @@ -16,7 +12,6 @@ import { useSnackbar } from 'notistack'; import GlassyIcon from '../../../layout/REUSABLE_COMPONENTS/icons/GlassyIcon'; import MDBox from '../../../layout/REUSABLE_COMPONENTS/MDBOX'; -// Utility function for mapping cardSize to buttonSize const buttonSizeMap = { xs: 'extraSmall', sm: 'small', @@ -85,10 +80,6 @@ const GenericActionButtons = ({ } else if (action === 'remove' && removeActions[currentContext]) { removeActions[currentContext](cardData); } - - // Hook into success or failure callbacks as necessary - // onSuccess(); - // onFailure(); }, [card, context, addActions, removeActions] ); @@ -110,9 +101,6 @@ const ActionButtons = ({ page, handleCardAction, }) => { - // console.log( - // `ActionButtons: buttonSize: ${buttonSize}, card: ${card?.name}, context: ${context}` - // ); const labelValue = typeof context === 'string' ? context : context?.pageContext; const stackDirection = buttonSize === 'extraSmall' ? 'column' : 'row'; diff --git a/src/components/buttons/other/DeckSwitch.jsx b/src/components/buttons/other/DeckSwitch.jsx deleted file mode 100644 index 7288664..0000000 --- a/src/components/buttons/other/DeckSwitch.jsx +++ /dev/null @@ -1,45 +0,0 @@ -import React from 'react'; -import { - Switch, - FormControlLabel, - Typography, - FormControl, -} from '@mui/material'; -import { useFormContext, useMode } from '../../../context'; // Adjust with actual path -import MDTypography from '../../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; - -const DeckSwitch = ({ editMode, onToggle }) => { - const { theme } = useMode(); // Ensures theme is applied correctly - - return ( - - - } - label={ - - {editMode ? 'Edit Mode' : 'View Mode'} {/* Label */} - - } - style={{ - margin: theme.spacing(1), // Provide some spacing - justifyContent: 'space-between', // Align items nicely - }} - /> - - ); -}; - -export default DeckSwitch; diff --git a/src/components/buttons/other/ReusableLoadingButton.jsx b/src/components/buttons/other/ReusableLoadingButton.jsx index 45dc0e8..dc1b158 100644 --- a/src/components/buttons/other/ReusableLoadingButton.jsx +++ b/src/components/buttons/other/ReusableLoadingButton.jsx @@ -1,75 +1,3 @@ -// // ReusableLoadingButton.js -// import React from 'react'; -// import { LoadingButton } from '@mui/lab'; -// import LoginIcon from '@mui/icons-material/Login'; -// import { useMode } from '../../../context'; -// import AdjustSharpIcon from '@mui/icons-material/AdjustSharp'; -// const baseButtonStyles = { -// bgcolor: '#6a59ff', -// borderColor: '#6a59ff', -// borderWidth: 2, -// borderStyle: 'solid', -// display: 'flex', -// flexGrow: 1, -// alignItems: 'center', -// justifyContent: 'center', -// marginLeft: 'auto', -// marginRight: 'auto', -// marginBottom: '16px', -// marginTop: '16px', -// position: 'relative', -// bottom: 0, -// cursor: 'pointer', -// transition: 'background-color 0.3s, border-color 0.3s, color 0.3s', -// ':hover': { -// fontWeight: 'bold', -// bgcolor: '#4a6da7', -// borderColor: '#34597f', -// }, -// ':focus': { -// outline: '2px solid #62a4ff', -// outlineOffset: 2, -// }, -// }; - -// const ReusableLoadingButton = ({ -// loading, -// label, -// icon, -// onClick, -// style, -// fullWidth, -// sx, -// variant, -// }) => { -// const { theme } = useMode(); -// return ( -// } -// fullWidth={fullWidth} -// // sx={sx} -// onClick={onClick} -// sx={{ -// ...sx, -// mt: 2, // Adjust spacing as needed -// background: theme.palette.backgroundG.light, -// borderColor: theme.palette.backgroundG.light, -// borderWidth: 2, -// '&:hover': { background: theme.palette.backgroundG.default }, -// '&:focus': { background: theme.palette.backgroundG.default }, -// }} -// > -// {label} -// -// ); -// }; - -// export default ReusableLoadingButton; import React from 'react'; import { LoadingButton } from '@mui/lab'; import AdjustSharpIcon from '@mui/icons-material/AdjustSharp'; @@ -104,7 +32,6 @@ const ReusableLoadingButton = ({ }, }; } - // Default styles or other variants can be managed here return { background: theme.palette.backgroundG.light, borderColor: theme.palette.backgroundG.light, diff --git a/src/components/cards/CardCarousel.jsx b/src/components/cards/CardCarousel.jsx deleted file mode 100644 index c374f16..0000000 --- a/src/components/cards/CardCarousel.jsx +++ /dev/null @@ -1,44 +0,0 @@ -// import React from 'react'; -// import styled from 'styled-components'; -// import { Swiper, SwiperSlide } from 'swiper/react'; -// import { EffectCoverflow, Pagination } from 'swiper'; -// import 'swiper/css'; -// import 'swiper/css/effect-coverflow'; -// import 'swiper/css/pagination'; -// import GenericCard from './GenericCard'; -// import { -// StyledCarousel, -// StyledSwiperSlide, -// } from '../../pages/pageStyles/StyledComponents'; - -// const CardCarousel = ({ cards, context }) => { -// const swiperSettings = { -// effect: 'coverflow', -// grabCursor: true, -// centeredSlides: true, -// slidesPerView: 'auto', -// coverflowEffect: { -// rotate: 50, -// stretch: 0, -// depth: 200, -// modifier: 1, -// slideShadows: true, -// }, -// loop: true, -// pagination: { clickable: true }, -// }; - -// return ( -// -// -// {cards.map((card, index) => ( -// -// -// -// ))} -// -// -// ); -// }; - -// export default CardCarousel; diff --git a/src/components/cards/CardDetail.jsx b/src/components/cards/CardDetail.jsx index 465c53c..b49548e 100644 --- a/src/components/cards/CardDetail.jsx +++ b/src/components/cards/CardDetail.jsx @@ -30,10 +30,6 @@ const CardDetail = ({ sx={{ display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' }} > {icon && {icon}} - {/* {icon && ( - {icon} - )} */} - {title}: @@ -56,25 +52,6 @@ const CardDetail = ({ variant="outlined" /> ))} - {/* - {Array.isArray(values) && values.length > 0 - ? values.map((rarityValue, index) => ( - onRarityClick(rarityValue?.toString())} - sx={{ - borderColor: getChipColor(rarityValue?.toString()), - borderWidth: '2px', - fontWeight: 700, - color: getChipColor(rarityValue?.toString()), - margin: '5px', - }} - variant="outlined" - /> - )) - : null} - */} ); diff --git a/src/components/cards/CardDetails.jsx b/src/components/cards/CardDetails.jsx index 0ef2501..0da52dc 100644 --- a/src/components/cards/CardDetails.jsx +++ b/src/components/cards/CardDetails.jsx @@ -1,39 +1,39 @@ -import React from 'react'; -import { Box, Typography } from '@mui/material'; -import useResponsiveStyles from '../../context/hooks/style-hooks/useResponsiveStyles'; -import { useTheme } from 'styled-components'; -import { - CardDetailContainer, - CardDetailRow, - CardIconWrapper, - CardTitleStyle, - CardValueStyle, - useCardDetailStyles, -} from './styles/cardStyles'; -import { useMode } from '../../context'; -import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; +// import React from 'react'; +// import { Box, Typography } from '@mui/material'; +// import useResponsiveStyles from '../../context/hooks/style-hooks/useResponsiveStyles'; +// import { useTheme } from 'styled-components'; +// import { +// CardDetailContainer, +// CardDetailRow, +// CardIconWrapper, +// CardTitleStyle, +// CardValueStyle, +// useCardDetailStyles, +// } from './styles/cardStyles'; +// import { useMode } from '../../context'; +// import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -const CardDetails = ({ details, className }) => { - // details expected to be an array of objects with { icon, title, value } - const { theme } = useMode(); - // const theme2 = useTheme(); - // const styles = useCardDetailStyles(theme, theme2); - // const { getHeaderStyle, getButtonTypographyVariant } = - // useResponsiveStyles(theme); +// const CardDetails = ({ details, className }) => { +// // details expected to be an array of objects with { icon, title, value } +// const { theme } = useMode(); +// // const theme2 = useTheme(); +// // const styles = useCardDetailStyles(theme, theme2); +// // const { getHeaderStyle, getButtonTypographyVariant } = +// // useResponsiveStyles(theme); - return ( - - {details.map(({ icon, title, value }, index) => ( - - {icon && {icon}} - - {title}: - {value || ''} - - - ))} - - ); -}; +// return ( +// +// {details.map(({ icon, title, value }, index) => ( +// +// {icon && {icon}} +// +// {title}: +// {value || ''} +// +// +// ))} +// +// ); +// }; -export default CardDetails; +// export default CardDetails; diff --git a/src/components/cards/CardTextSection.jsx b/src/components/cards/CardTextSection.jsx deleted file mode 100644 index 2000a90..0000000 --- a/src/components/cards/CardTextSection.jsx +++ /dev/null @@ -1,119 +0,0 @@ -import React from 'react'; -import Typography from '@mui/material/Typography'; -import Box from '@mui/material/Box'; -import { useMode } from '../../../context'; -import FlexBetween from '../../layout/REUSABLE_COMPONENTS/FlexBetween'; -import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; - -// Updated SimpleSectionHeader component with additional parameters -const CardTextSection = ({ - name, - price, - cartQuantity, - collectionQuantity, - deckQuantity, - cardSet, - setCode, - cardRarity, -}) => { - const { theme } = useMode(); - return ( - - {/* CARD TITLE SECTION: name */} - - {name} - - {/* CARD TITLE SUBSECTION: set name, rarity, set code */} - - {`Set: ${cardSet}`} - - {cardRarity} - - - {setCode} - - - {/* CARD TITLE SUBSECTION B: context quantities, price, price change */} - - - - {`Cart: ${cartQuantity}`} - - - {`Collection: ${collectionQuantity}`} - - - {`Deck: ${deckQuantity}`} - - - - - {`Price: ${price}`} - - {`Price Change: ${price}`} - - - - - - ); -}; - -export default CardTextSection; diff --git a/src/components/cards/CarouselCard.jsx b/src/components/cards/CarouselCard.jsx deleted file mode 100644 index dda4859..0000000 --- a/src/components/cards/CarouselCard.jsx +++ /dev/null @@ -1,160 +0,0 @@ -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 { ModalContext } from '../../context/UTILITIES_CONTEXT/ModalContext/ModalContext'; -import GenericCard from './GenericCard'; -import { - MainContainer2, - CardMobile, - ChartContainerMobile, - CardDetails, - CardDetailsContainer, - ChartContainer, -} from '../../pages/pageStyles/StyledComponents'; -import { AspectRatio } from '@mui/joy'; -import { debounce } from 'lodash'; -import { useMode } from '../../context'; -import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -const CarouselCard = ({ card }) => { - const { theme } = useMode(); - 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 ( - - {/* */}{' '} - {/* Ensure the container doesn't overflow */} - - - - handleClick()} - context={'Collection'} - ref={cardRef} - /> - - - {/* Top section for card details */} - - - - - - {card?.name} - - - - - - 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 3f1dcc6..a20eea2 100644 --- a/src/components/cards/GenericCard.jsx +++ b/src/components/cards/GenericCard.jsx @@ -103,6 +103,7 @@ const GenericCard = React.forwardRef((props, ref) => { }); let cardContent = null; if (!isSwiperStyles) { + console.log(isSwiperStyles); if (cardSize !== 'xs') { cardContent = ( diff --git a/src/components/dialogs/homeDetailsModal/DetailsModal.jsx b/src/components/dialogs/DetailsModal.jsx similarity index 98% rename from src/components/dialogs/homeDetailsModal/DetailsModal.jsx rename to src/components/dialogs/DetailsModal.jsx index 1d210f1..0227f16 100644 --- a/src/components/dialogs/homeDetailsModal/DetailsModal.jsx +++ b/src/components/dialogs/DetailsModal.jsx @@ -13,7 +13,7 @@ import { } from '@mui/material'; import CloseIcon from '@mui/icons-material/Close'; import { FaGithub, FaExternalLinkAlt } from 'react-icons/fa'; -import { useModalContext } from '../../../context'; +import { useModalContext } from '../../context'; const DetailsModal = () => { const { featureData, detailsModalShow, closeDetailsModal } = diff --git a/src/components/dialogs/cardDialog/GenericCardDialog.jsx b/src/components/dialogs/GenericCardDialog.jsx similarity index 92% rename from src/components/dialogs/cardDialog/GenericCardDialog.jsx rename to src/components/dialogs/GenericCardDialog.jsx index 86c108c..891ac56 100644 --- a/src/components/dialogs/cardDialog/GenericCardDialog.jsx +++ b/src/components/dialogs/GenericCardDialog.jsx @@ -20,16 +20,16 @@ import { ListItem, Backdrop, } from '@mui/material'; -import useSelectedContext from '../../../context/hooks/useSelectedContext'; -import { useModalContext, useMode } from '../../../context'; -import CardMediaSection from '../../cards/media/CardMediaSection'; -import GenericActionButtons from '../../buttons/actionButtons/GenericActionButtons'; +import useSelectedContext from '../../context/hooks/useSelectedContext'; +import { useModalContext, useMode } from '../../context'; +import CardMediaSection from '../cards/media/CardMediaSection'; +import GenericActionButtons from '../buttons/actionButtons/GenericActionButtons'; import CloseIcon from '@mui/icons-material/Close'; -import CardDetail from '../../cards/CardDetail'; -import { useOverlay } from '../../../context/hooks/useOverlay'; -import CardDetailsContainer from '../../cards/CardDetailsContainer'; +import CardDetail from '../cards/CardDetail'; +import { useOverlay } from '../../context/hooks/useOverlay'; +import CardDetailsContainer from '../cards/CardDetailsContainer'; import { enqueueSnackbar } from 'notistack'; -import { DialogPaper } from '../../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; +import { DialogPaper } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; const GenericCardDialog = (props) => { const { theme } = useMode(); diff --git a/src/components/dialogs/stripeModal/StripeCheckoutModal.js b/src/components/dialogs/StripeCheckoutModal.js similarity index 96% rename from src/components/dialogs/stripeModal/StripeCheckoutModal.js rename to src/components/dialogs/StripeCheckoutModal.js index ab582fc..a6722ad 100644 --- a/src/components/dialogs/stripeModal/StripeCheckoutModal.js +++ b/src/components/dialogs/StripeCheckoutModal.js @@ -1,7 +1,7 @@ import React from 'react'; import { Modal, Fade, Box, Typography, Backdrop } from '@mui/material'; import { Elements } from '@stripe/react-stripe-js'; -import StripeForm from '../../forms/customerCheckoutForm/StripeForm'; +import StripeForm from '../forms/customerCheckoutForm/StripeForm'; import { loadStripe } from '@stripe/stripe-js'; const stripePromise = loadStripe(process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY); diff --git a/src/components/forms/AddDeckForm.jsx b/src/components/forms/AddDeckForm.jsx index 0ef423e..88ceb03 100644 --- a/src/components/forms/AddDeckForm.jsx +++ b/src/components/forms/AddDeckForm.jsx @@ -1,62 +1,3 @@ -// import React from 'react'; -// import { useFormContext } from '../../context'; -// import FormField from '../reusable/FormField'; -// import { Button, Paper, Typography, Box } from '@mui/material'; -// import SaveIcon from '@mui/icons-material/Save'; - -// const AddDeckForm = ({ showSnackbar }) => { -// const { formStates, onSubmit } = useFormContext(); -// const formId = 'addDeckForm'; // Assuming this is the formId for creating decks - -// const { -// register, -// handleSubmit, -// formState: { errors, isSubmitting }, -// } = formStates[formId]; - -// const onFormSubmit = async (data) => { -// try { -// await onSubmit(data, formId); -// console.log(data); -// } catch (error) { -// console.error(error); -// } -// }; - -// return ( -// -// Create Deck -//
-// -// -// -// -// -// -//
-// ); -// }; -// export default AddDeckForm; import React from 'react'; import { useFormContext } from '../../context'; import RCZodForm from './RCZodForm'; @@ -65,8 +6,6 @@ import SaveIcon from '@mui/icons-material/Save'; const AddDeckForm = () => { const { setFormSchema } = useFormContext(); const formId = 'addDeckForm'; // Assuming this is the formId for creating decks - - // Fields configuration for AddDeckForm const fields = [ { name: 'name', label: 'Name', type: 'text', required: true }, { @@ -78,13 +17,10 @@ const AddDeckForm = () => { }, ]; - // This function should be context-aware or passed down as a prop const handleSubmit = (data) => { console.log('Add Deck Data:', data); - // Interaction with context or props for form submission }; - // Set the schema based on the form ID React.useEffect(() => { setFormSchema(formId); }, [setFormSchema, formId]); diff --git a/src/components/forms/UpdateDeckForm.jsx b/src/components/forms/UpdateDeckForm.jsx index e73ba4f..fb5ebfa 100644 --- a/src/components/forms/UpdateDeckForm.jsx +++ b/src/components/forms/UpdateDeckForm.jsx @@ -1,87 +1,3 @@ -// import React, { useEffect } from 'react'; -// import { useFormContext, useMode } from '../../context'; -// import FormField from '../reusable/FormField'; -// import { Button, Paper, Typography, Box } from '@mui/material'; -// import SaveIcon from '@mui/icons-material/Save'; -// import DeleteIcon from '@mui/icons-material/Delete'; -// import { FormBox } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; - -// const UpdateDeckForm = ({ selectedDeck }) => { -// const { theme } = useMode(); -// const { formStates, onSubmit } = useFormContext(); -// const formId = 'updateDeckForm'; // Assuming this is the formId for updating decks - -// const { -// register, -// handleSubmit, -// reset, -// formState: { errors, isSubmitting }, -// } = formStates[formId]; - -// useEffect(() => { -// if (selectedDeck) { -// reset(selectedDeck); -// } -// }, [selectedDeck, reset]); - -// const onFormSubmit = async (data) => { -// try { -// await onSubmit({ ...data, _id: selectedDeck._id }, formId); -// console.log(data); -// } catch (error) { -// console.error(error); -// } -// }; - -// return ( -// -// Update Deck -// -// -// -// -// -// -// -// -// -// ); -// }; -// export default UpdateDeckForm; import React from 'react'; import RCZodForm from './RCZodForm'; import SaveIcon from '@mui/icons-material/Save'; diff --git a/src/components/forms/cleanup/CronTrigger.jsx b/src/components/forms/cleanup/CronTrigger.jsx deleted file mode 100644 index 9710b37..0000000 --- a/src/components/forms/cleanup/CronTrigger.jsx +++ /dev/null @@ -1,27 +0,0 @@ -// import React from 'react'; -// import { Box, Button } from '@mui/material'; -// import { useCombinedContext } from '../../../context/CombinedProvider'; -// import { useAuthContext } from '../../../context'; - -// const CronTrigger = () => { -// const { stopCronJob, handleSendAllCardsInCollections, listOfMonitoredCards } = -// useCombinedContext(); -// const { userId } = useAuthContext(); -// const handleTriggerCron = () => { -// console.log('TRIGGERING CRON JOB TO UPDATE: ' + listOfMonitoredCards); -// handleSendAllCardsInCollections(userId, listOfMonitoredCards); -// }; - -// const handleStopCron = () => { -// stopCronJob(); -// }; - -// return ( -// -// -// -// -// ); -// }; - -// export default CronTrigger; diff --git a/src/components/forms/cleanup/EditUserProfileForm.jsx b/src/components/forms/cleanup/EditUserProfileForm.jsx deleted file mode 100644 index 29fdfb0..0000000 --- a/src/components/forms/cleanup/EditUserProfileForm.jsx +++ /dev/null @@ -1,87 +0,0 @@ -import React from 'react'; -import { Typography } from '@mui/material'; -import { useUserContext } from '../../context/UserContext/UserContext'; -import { usePageContext } from '../../context/PageContext/PageContext'; -import { PageHeader, PageContent } from '../../layout'; -import { FormWrapper, StyledTextField, StyledButton } from './styled'; -import { useFormContext, useMode } from '../../../context'; - -const EditUserProfileForm = () => { - const { theme } = useMode(); - const { user, fetchUserData } = useUserContext(); - const userId = user?.id; - const { isPageLoading, setIsPageLoading, setPageError } = usePageContext(); - const { forms, handleChange, handleSubmit, formErrors } = useFormContext(); - const userDataValues = forms.updateUserDataForm; - const userDataErrors = formErrors.updateUserDataForm || {}; - - const handleFormSubmit = (event) => { - event.preventDefault(); - handleSubmit('updateUserDataForm'); - }; - return ( - <> - - - Edit User Settings - - - -
- - - - - - Save - - -
- - ); -}; - -export default EditUserProfileForm; diff --git a/src/components/forms/cleanup/EditUserSettingsForm.jsx b/src/components/forms/cleanup/EditUserSettingsForm.jsx deleted file mode 100644 index 51f7cad..0000000 --- a/src/components/forms/cleanup/EditUserSettingsForm.jsx +++ /dev/null @@ -1,124 +0,0 @@ -// Import dependencies -import React, { useState, useEffect } from 'react'; -import { useCookies } from 'react-cookie'; -import { Box, Button, TextField, Typography } from '@mui/material'; -import { useUserContext } from '../../context/UserContext/UserContext'; -import { usePageContext } from '../../context/PageContext/PageContext'; -import { PageLayout, PageHeader, PageContent } from '../../layout'; -import LoadingIndicator from '../../reusable/indicators/LoadingIndicator'; -import ErrorIndicator from '../../reusable/indicators/ErrorIndicator'; -import ThemeToggleButton from '../../components/reusable/buttons/ThemeToggleButton'; -import { useMode } from '../../../context'; - -const EditUserSettingsForm = ({ user }) => { - const [cookies] = useCookies(['user']); - const { theme } = useMode(); - const { user: currentUser } = cookies; - const userId = currentUser?.id; - - const { - userData, - updateUser, - fetchUserData, - isLoading, - setIsLoading, - pageError, - setPageError, - logPageData, - } = useUserContext(); - - const { isPageLoading, setIsPageLoading } = usePageContext(); - - const [formState, setFormState] = useState({ - email: '', - password: '', - confirmPassword: '', - }); - - const [formError, setFormError] = useState(null); - - const { email, password, confirmPassword } = formState; - - const handleChange = (e) => { - const { name, value } = e.target; - setFormState((prev) => ({ ...prev, [name]: value })); - }; - - const handleSubmit = async (e) => { - e.preventDefault(); - if (password !== confirmPassword) { - setFormError('Passwords do not match'); - return; - } - try { - setIsLoading(true); - await updateUser(userId, formState); - await fetchUserData(); - logPageData('EditUserSettingsForm', userData); - } catch (e) { - console.error('Failed to update user settings:', e); - setPageError(e); - } finally { - setIsLoading(false); - } - }; - - if (isPageLoading) return ; - if (pageError) return ; - if (isLoading) return ; - - return ( - <> - - - Edit User Settings - - - -
- - - - - - - - -
- - ); -}; - -export default EditUserSettingsForm; diff --git a/src/components/forms/cleanup/ThemeToggleButton.jsx b/src/components/forms/cleanup/ThemeToggleButton.jsx deleted file mode 100644 index c6f65bd..0000000 --- a/src/components/forms/cleanup/ThemeToggleButton.jsx +++ /dev/null @@ -1,49 +0,0 @@ -// import React, { useContext, useState } from 'react'; -// import { IconButton, Menu, MenuItem } from '@mui/material'; -// import Brightness4Icon from '@mui/icons-material/Brightness4'; -// import Brightness7Icon from '@mui/icons-material/Brightness7'; -// import { ColorModeContext } from '../../../context/UTILITIES_CONTEXT/ColorModeContext/ColorModeProvider'; - -// const ThemeToggleButton = () => { -// const [anchorEl, setAnchorEl] = useState(null); -// const { toggleColorMode, setMode } = useContext(ColorModeContext); - -// const handleClick = (event) => { -// setAnchorEl(event.currentTarget); -// }; - -// const handleClose = () => { -// setAnchorEl(null); -// }; - -// const handleThemeChange = (mode) => { -// toggleColorMode(mode); // Updated this line -// console.log('mode', mode); -// handleClose(); -// }; - -// return ( -//
-// -// -// -// -// handleThemeChange('dark')}> -// -// Dark Mode -// -// handleThemeChange('light')}> -// -// Light Mode -// -// -//
-// ); -// }; - -// export default ThemeToggleButton; diff --git a/src/components/forms/reusable/RCZodForm.jsx b/src/components/forms/reusable/RCZodForm.jsx index d4ce7e8..1117973 100644 --- a/src/components/forms/reusable/RCZodForm.jsx +++ b/src/components/forms/reusable/RCZodForm.jsx @@ -1,159 +1,3 @@ -// import React, { useEffect } from 'react'; -// import { -// Box, -// InputAdornment, -// FormControl, -// InputLabel, -// Select, -// MenuItem, -// Chip, -// } from '@mui/material'; -// import FormField from './reusable/FormField'; -// import ReusableLoadingButton from '../buttons/other/ReusableLoadingButton'; -// import { useFormContext, useMode } from '../../context'; -// import { FormFieldBox } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; - -// const RCZodForm = ({ -// fields, -// buttonLabel, -// startIcon, -// schemaName, -// additionalButtons, -// }) => { -// const { theme } = useMode(); - -// const { -// formMethods, -// register, -// onSubmit, -// handleChange, -// handleBlur, -// // getValues, -// handleFocus, -// formStates: { errors, isSubmitting, ...formStates }, -// setFormSchema, -// // formState: { errors, isSubmitting }, -// } = useFormContext(); - -// useEffect(() => { -// setFormSchema(schemaName); -// }, [setFormSchema, schemaName]); - -// const onFormSubmit = (data) => { -// onSubmit(data, schemaName); -// }; - -// const handleKeyPress = (e) => { -// if (e.key === 'Enter') { -// e.preventDefault(); -// formMethods.handleSubmit((data) => { -// onSubmit(data); -// }); -// } -// }; - -// const renderField = (field) => { -// if (field.type === 'select') { -// return ( -// -// -// {field.label} -// -// -// -// ); -// } else if (field.type === 'chips') { -// return ( -// -// -// {field?.values?.map((value, index) => ( -// field.onDelete(value)} -// /> -// ))} -// -// -// ); -// } else { -// return ( -// -// formMethods.handleChange(e, field.name)} -// // value={} -// defaultValue={formMethods.getValues(field.name)} -// onFocus={handleFocus} -// onBlur={handleBlur} -// onKeyDown={handleKeyPress} -// InputProps={ -// field.icon -// ? { -// endAdornment: ( -// -// {field.icon} -// -// ), -// } -// : null -// } -// multiline={field.multiline} -// rows={field.rows} -// /> -// -// ); -// } -// }; -// return ( -// -// {fields?.map(renderField)} -// -// {startIcon} -// -// } -// fullWidth -// /> -// {additionalButtons && -// additionalButtons?.map((button, index) => ( -// -// ))} -// -// ); -// }; - -// export default RCZodForm; import React, { useEffect } from 'react'; import { Box, diff --git a/src/components/grids/deckBuilderGrids/CardsGrid.js b/src/components/grids/deckBuilderGrids/CardsGrid.js deleted file mode 100644 index 05f22e8..0000000 --- a/src/components/grids/deckBuilderGrids/CardsGrid.js +++ /dev/null @@ -1,75 +0,0 @@ -import React, { useMemo } from 'react'; -import { Grid, Grow, Typography } from '@mui/material'; -import { useDeckStore } from '../../../context/MAIN_CONTEXT/DeckContext/DeckContext'; -import SkeletonDeckItem from '../gridItems/SkeletonDeckItem'; -import StoreItem from '../gridItems/StoreItem'; -import MDBox from '../../../layout/REUSABLE_COMPONENTS/MDBOX'; -import GridLayout from '../../../layout/Containers/GridLayout'; - -const CardsGrid = ({ isLoading }) => { - const { selectedCards } = useDeckStore(); - - // Efficiently flattening and processing selectedCards with useMemo - const flattenSelectedCards = useMemo(() => { - if (!Array.isArray(selectedCards)) return []; - - const cardCountMap = new Map(); - - return selectedCards.reduce((acc, card) => { - if (!card) return acc; - const currentCount = (cardCountMap.get(card.id) || 0) + 1; - if (currentCount <= 3) { - acc.push({ ...card, uniqueKey: `${card.id}-${currentCount - 1}` }); - cardCountMap.set(card.id, currentCount); - } - return acc; - }, []); - }, [selectedCards]); - - const gridItems = useMemo(() => { - return isLoading ? Array.from({ length: 12 }) : flattenSelectedCards; - }, [isLoading, flattenSelectedCards]); - - // Define grid item breakpoints once to reuse in the mapping - const gridItemProps = { xs: 6, sm: 4, md: 4, lg: 4 }; - - return ( - - {gridItems.map((item, index) => ( - - - - {isLoading ? ( - - ) : ( - - )} - - - - ))} - - ); -}; - -export default React.memo(CardsGrid); diff --git a/src/components/grids/gridItems/ReusableSkeletonItem.jsx b/src/components/grids/gridItems/ReusableSkeletonItem.jsx deleted file mode 100644 index 074a7b9..0000000 --- a/src/components/grids/gridItems/ReusableSkeletonItem.jsx +++ /dev/null @@ -1,30 +0,0 @@ -// ReusableSkeletonItem.jsx -import React from 'react'; -import { Grid } from '@mui/material'; -import SkeletonStoreItem from './SkeletonStoreItem'; -import SkeletonDeckItem from './SkeletonDeckItem'; - -const ReusableSkeletonItem = ({ itemType, count, gridItemProps, context }) => - context === 'Cart' ? ( - <> - {Array(count) - .fill(0) - .map((_, index) => ( - - - - ))} - - ) : ( - <> - {Array(count) - .fill(0) - .map((_, index) => ( - - - - ))} - - ); - -export default ReusableSkeletonItem; diff --git a/src/components/grids/gridItems/SkeletonStoreItem.jsx b/src/components/grids/gridItems/SkeletonStoreItem.jsx deleted file mode 100644 index 6348f9d..0000000 --- a/src/components/grids/gridItems/SkeletonStoreItem.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import { Box, CardContent, Skeleton } from '@mui/material'; -import { useMode } from '../../../context'; -import { - AspectRatioBoxSkeleton, - StyledSkeletonCard, -} from '../../../pages/pageStyles/StyledComponents'; -const SkeletonStoreItem = () => { - const { theme } = useMode(); - return ( - - - - - - - - - - - - - - ); -}; - -export default SkeletonStoreItem; diff --git a/src/components/grids/gridItems/StoreItem.jsx b/src/components/grids/gridItems/StoreItem.jsx deleted file mode 100644 index 8aa6b56..0000000 --- a/src/components/grids/gridItems/StoreItem.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { memo } from 'react'; -import { Box, Container } from '@mui/material'; -import GenericCard from '../../cards/GenericCard'; - -// eslint-disable-next-line react/display-name -const StoreItem = memo(({ card, context, page, index }) => { - return ( - - - - - - ); -}); - -export default StoreItem; diff --git a/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx b/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx index bca0246..54dc190 100644 --- a/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx +++ b/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx @@ -15,10 +15,8 @@ import useLocalStorage from '../../hooks/useLocalStorage'; import useSelectedContext from '../../hooks/useSelectedContext'; import useSelectedCollection from '../../MAIN_CONTEXT/CollectionContext/useSelectedCollection'; -// Create the combined context export const AppContext = createContext(defaultContextValue.APP_CONTEXT); -// Create a provider component that combines the contexts export const AppContextProvider = ({ children }) => { const Deck = useContext(DeckContext); const Cart = useContext(CartContext); @@ -37,8 +35,6 @@ export const AppContextProvider = ({ children }) => { const { allIds } = useSelectedCollection(); const { selectedDeck, allDecks } = Deck; const { cartData } = Cart; - - // Function to compile metadata including totalPrice for collections const compileCollectionMetaData = useCallback(() => { const metaData = { metaData: { @@ -47,6 +43,9 @@ export const AppContextProvider = ({ children }) => { 0 ), numCollections: allIds?.length || 0, + topFiveCards: cardsWithQuantities + ?.sort((a, b) => b.price - a.price) + .slice(0, 5), }, }; @@ -88,14 +87,12 @@ export const AppContextProvider = ({ children }) => { if (acc[card.id]) { acc[card.id].quantity += card?.quantity; } else { - // Otherwise, add the card with its current quantity acc[card.id] = { ...card, quantity: card.quantity }; } return acc; }, {}); const quantities = Object.values(cardQuantities); - // console.log('cardsWithQuantities:', quantities); setCardsWithQuantities(quantities); setAllCardsWithQuantities(combinedCards); @@ -105,8 +102,6 @@ export const AppContextProvider = ({ children }) => { useEffect(() => { compileCardsWithQuantities(); }, []); // Dependency array based on when you want to recalculate - - // Combine the context values into one object const appContextValues = useMemo( () => ({ Deck, diff --git a/src/context/SECONDARY_CONTEXT/StatisticsContext/StatisticsContext.jsx b/src/context/SECONDARY_CONTEXT/StatisticsContext/StatisticsContext.jsx index c7e1f3c..5520994 100644 --- a/src/context/SECONDARY_CONTEXT/StatisticsContext/StatisticsContext.jsx +++ b/src/context/SECONDARY_CONTEXT/StatisticsContext/StatisticsContext.jsx @@ -13,18 +13,17 @@ import { getTopCollection, calculateStatsForCollection, } from './helpers'; -import { useChartContext } from '../../MAIN_CONTEXT/ChartContext/ChartContext'; import { useCollectionStore } from '../../index'; import { defaultContextValue } from '../../constants'; import useSelectedCollection from '../../MAIN_CONTEXT/CollectionContext/useSelectedCollection'; +import useTimeRange from '../../../components/forms/selectors/useTimeRange'; const StatisticsContext = createContext(defaultContextValue.STATISTICS_CONTEXT); export const StatisticsProvider = ({ children }) => { const { allXYValues, hasFetchedCollections } = useCollectionStore(); const { selectedCollection, allCollections } = useSelectedCollection(); - const { timeRange } = useChartContext(); - + const { selectedTimeRange } = useTimeRange(); if (!Array.isArray(allCollections)) { return null; } @@ -39,12 +38,12 @@ export const StatisticsProvider = ({ children }) => { ? allCollections?.reduce((acc, collection) => { acc[collection?._id] = calculateStatsForCollection( collection, - timeRange + selectedTimeRange ); return acc; }, {}) : {}, - [allCollections, timeRange] + [allCollections, selectedTimeRange] ); const totalValue = useMemo(() => { @@ -68,12 +67,6 @@ export const StatisticsProvider = ({ children }) => { [allCollections] ); - // if (hasFetchedCollections) { - // console.log('SELECTED', selectedCollection); - // console.log('ALL', allCollections); - // console.log('VALID', validCollections); - // } - // Function to create markers for a given collection const createMarkers = (selectedCollection) => { if (!selectedCollection || !selectedCollection.collectionStatistics) return []; @@ -105,48 +98,28 @@ export const StatisticsProvider = ({ children }) => { ]; }; - // Example use of createMarkers within useMemo for selectedCollection const markers = useMemo(() => { - // Assuming selectedCollection is obtained from somewhere, e.g., state or context if (!selectedCollection) return []; - // console.log('SELECTED COLLECTION:', selectedCollection); - // const selectedCollection = allCollections.find( - // (collection) => collection._id === someSelectedCollectionId - // ); return createMarkers(selectedCollection); }, [allCollections]); // Add dependencies as necessary, e.g., someSelectedCollectionId - // const chartData = useMemo( - // () => - // validCollections - // ? allCollections.map((collection) => ({ - // id: collection._id, - // value: collection.totalPrice, - // label: collection.name, - // })) - // : [], - // [allCollections] - // ); - const contextValue = useMemo( () => ({ - // PRIMARY DATA stats: - calculateStatistics({ data: null }, timeRange, allCollections) || {}, + calculateStatistics( + { data: null }, + selectedTimeRange, + allCollections + ) || {}, allStats: [statsByCollectionId], statsByCollectionId: statsByCollectionId[selectedCollection?._id], selectedStat, markers, - // PRIMARY FUNCTIONS setSelectedStat, - // SECONDARY DATA totalValue, topFiveCards, - // chartData, - // SECONDARY FUNCTIONS calculateTotalPriceOfAllCollections, - // calculateStatsByCollectionId, calculatePriceChanges, getTopCard, getTopCollection, @@ -157,9 +130,8 @@ export const StatisticsProvider = ({ children }) => { markers, totalValue, topFiveCards, - // chartData, setSelectedStat, - timeRange, + selectedTimeRange, ] ); diff --git a/src/context/hooks/useGridItems.jsx b/src/context/hooks/useGridItems.jsx index fe8c851..98a14de 100644 --- a/src/context/hooks/useGridItems.jsx +++ b/src/context/hooks/useGridItems.jsx @@ -1,9 +1,9 @@ import React, { useMemo } from 'react'; import { Grid, Grow } from '@mui/material'; -import SkeletonDeckItem from '../../components/grids/gridItems/SkeletonDeckItem'; import { useCardStoreHook } from './useCardStore'; import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; import GenericCard from '../../components/cards/GenericCard'; +import SkeletonCard from '../../layout/REUSABLE_COMPONENTS/SkeletonCard'; const useGridItems = ({ itemsPerPage, cards, pageContext, isLoading }) => { const { loadingSearchResults } = useCardStoreHook(); @@ -45,7 +45,7 @@ const useGridItems = ({ itemsPerPage, cards, pageContext, isLoading }) => { > {/* Conditionally render Skeleton or Card based on loading state */} {isLoading || loadingSearchResults ? ( - + ) : ( Math.round(value * 10) / 10; -// const { -// data, -// PaginationComponent, // Assume this is your custom pagination component -// page, -// rowsPerPage, -// } = usePagination(selectedCards, 10, selectedCards?.length || 0); - -// const rows = data?.map((card, index) => ({ -// // Assuming each card has a unique 'id' for key, or use index as fallback -// key: card.id || `row-${index}`, -// name: , -// price: , -// tPrice: , -// quantity: , -// action: , -// })); - -// return { -// columns: [ -// { Header: 'name', accessor: 'name', width: '30%', align: 'left' }, -// { Header: 'price', accessor: 'price', align: 'left' }, -// { Header: 'total price', accessor: 'tPrice', align: 'center' }, -// { Header: 'quantity', accessor: 'quantity', align: 'center' }, -// { Header: 'action', accessor: 'action', align: 'center' }, -// ], -// rows, -// PaginationComponent, -// page, -// rowsPerPage, -// }; -// } diff --git a/src/data/searchData.jsx b/src/data/searchData.jsx index a74308b..3f84dde 100644 --- a/src/data/searchData.jsx +++ b/src/data/searchData.jsx @@ -1,9 +1,40 @@ import Icon from '@mui/material/Icon'; // Images import MDTypography from '../MDTYPOGRAPHY/MDTypography'; -import React from 'react'; -import StoreItem from '../components/grids/gridItems/StoreItem'; +import React, { memo } from 'react'; import LoadingIndicator from '../../../components/reusable/indicators/LoadingIndicator'; +import GenericCard from '../components/cards/GenericCard'; +import { Container } from '@mui/system'; +import { Box } from '@mui/material'; +const SearchItem = memo(({ card, context, page, index }) => { + return ( + + + + + + ); +}); + +SearchItem.displayName = 'SearchItem'; export default function prepareTableData(selectedCards) { if (!selectedCards) return ; @@ -18,14 +49,12 @@ export default function prepareTableData(selectedCards) { accessor: 'card', id: 'card', Cell: ({ card, pageContext, index }) => ( - + ), }, ], [] ); - - // Map selectedCards to rows for react-table const data = React.useMemo( () => selectedCards.map((card) => ({ @@ -35,8 +64,5 @@ export default function prepareTableData(selectedCards) { })), [selectedCards] ); - - // You don't need to return PaginationComponent, page, and rowsPerPage anymore - // since react-table handles pagination internally. You just need to provide data and columns. return { columns, data }; } diff --git a/src/components/cards/AnimatedFeatureCard.jsx b/src/layout/AnimatedFeatureCard.jsx similarity index 68% rename from src/components/cards/AnimatedFeatureCard.jsx rename to src/layout/AnimatedFeatureCard.jsx index 4f8e54b..8281daa 100644 --- a/src/components/cards/AnimatedFeatureCard.jsx +++ b/src/layout/AnimatedFeatureCard.jsx @@ -6,11 +6,11 @@ import { CardListItem, CardUnorderedList, FeatureCard, -} from '../../pages/pageStyles/StyledComponents'; -import { useMode } from '../../context'; -import MDButton from '../../layout/REUSABLE_COMPONENTS/MDBUTTON'; -import SimpleButton from '../../layout/REUSABLE_COMPONENTS/unique/SimpleButton'; -import uniqueTheme from '../../layout/REUSABLE_COMPONENTS/unique/uniqueTheme'; +} from '../pages/pageStyles/StyledComponents'; +import { useMode } from '../context'; +import MDButton from './REUSABLE_COMPONENTS/MDBUTTON'; +import SimpleButton from './REUSABLE_COMPONENTS/unique/SimpleButton'; +import uniqueTheme from './REUSABLE_COMPONENTS/unique/uniqueTheme'; const AnimatedBox = animated(Box); @@ -78,13 +78,10 @@ export const AnimatedFeatureCard = ({ tier, onOpenModal }) => { }} > onOpenModal(tier.title)} sx={{ @@ -97,30 +94,6 @@ export const AnimatedFeatureCard = ({ tier, onOpenModal }) => { > Manage Collections - {/* onOpenModal(tier.title)} - sx={{ - color: theme.palette.backgroundA.contrastText, - background: theme.palette.backgroundF.darker, - borderColor: theme.palette.backgroundB.darkest, - borderWidth: 2, - mt: 'auto', - flexGrow: 1, - justifySelf: 'bottom', - bottom: 0, - width: '100%', - '&:hover': { - color: theme.palette.backgroundA.contrastTextC, - background: theme.palette.backgroundF.default, - }, - }} - > - {tier.buttonText} - */} diff --git a/src/layout/REUSABLE_COMPONENTS/ReusableSkeletonItem.jsx b/src/layout/REUSABLE_COMPONENTS/ReusableSkeletonItem.jsx new file mode 100644 index 0000000..ebb320c --- /dev/null +++ b/src/layout/REUSABLE_COMPONENTS/ReusableSkeletonItem.jsx @@ -0,0 +1,18 @@ +// ReusableSkeletonItem.jsx +import React from 'react'; +import { Grid } from '@mui/material'; + +import SkeletonCard from './SkeletonCard'; +const ReusableSkeletonItem = ({ itemType, count, gridItemProps, context }) => ( + <> + {Array(count) + .fill(0) + .map((_, index) => ( + + + + ))} + +); + +export default ReusableSkeletonItem; diff --git a/src/components/grids/gridItems/SkeletonDeckItem.jsx b/src/layout/REUSABLE_COMPONENTS/SkeletonCard.jsx similarity index 83% rename from src/components/grids/gridItems/SkeletonDeckItem.jsx rename to src/layout/REUSABLE_COMPONENTS/SkeletonCard.jsx index 686cd89..a2ee209 100644 --- a/src/components/grids/gridItems/SkeletonDeckItem.jsx +++ b/src/layout/REUSABLE_COMPONENTS/SkeletonCard.jsx @@ -3,11 +3,12 @@ import { Box, CardContent, Skeleton } from '@mui/material'; import { AspectRatioBoxSkeleton, StyledSkeletonCard, -} from '../../../pages/pageStyles/StyledComponents'; -import { useMode } from '../../../context'; +} from '../../pages/pageStyles/StyledComponents'; +import { useMode } from '../../context'; -const SkeletonDeckItem = ({ context }) => { +const SkeletonCard = () => { const { theme } = useMode(); + return ( @@ -30,4 +31,4 @@ const SkeletonDeckItem = ({ context }) => { ); }; -export default SkeletonDeckItem; +export default SkeletonCard; diff --git a/src/layout/collection/sub-components/TopCardsDisplayRow.jsx b/src/layout/collection/sub-components/TopCardsDisplayRow.jsx index d77f98c..d3db6af 100644 --- a/src/layout/collection/sub-components/TopCardsDisplayRow.jsx +++ b/src/layout/collection/sub-components/TopCardsDisplayRow.jsx @@ -19,6 +19,9 @@ import placeHolder from '../../../assets/images/placeholder.jpeg'; import GenericCard from '../../../components/cards/GenericCard'; import { StyledSwiperSlide } from '../../../pages/pageStyles/StyledComponents'; import MDBox from '../../REUSABLE_COMPONENTS/MDBOX'; +import { AspectRatioBox } from '../../../components/cards/styles/cardStyledComponents'; +import { FormBox } from '../../REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; +import CardDetail from '../../../components/cards/CardDetail'; export const TopCardsDisplayRow = () => { const { theme } = useMode(); @@ -50,7 +53,7 @@ export const TopCardsDisplayRow = () => { centeredSlides={true} loop={true} slidesPerView={1} - autoplay={{ delay: 2500 }} + autoplay={{ delay: 5000 }} pagination={{ clickable: true }} navigation={true} onSlideChange={handleSlideChange} @@ -69,16 +72,103 @@ export const TopCardsDisplayRow = () => { }} > {topFiveCards?.map((card, index) => ( - - - + + + + + + + {/* */} + + } + title="Description" + value={card?.desc} + /> + } + title="Description" + value={card?.desc} + /> + } + title="Description" + value={card?.desc} + /> + + {/* */} + - + ))} diff --git a/src/layout/deck/CardsDisplay.jsx b/src/layout/deck/CardsDisplay.jsx deleted file mode 100644 index 1b27ab7..0000000 --- a/src/layout/deck/CardsDisplay.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react'; -import { Box, Typography } from '@mui/material'; -import CardsGrid from '../../components/grids/deckBuilderGrids/CardsGrid'; -import { useMode } from '../../context'; -import { - DeckCardsContainer, - NoCardsTypography, -} from '../../pages/pageStyles/StyledComponents'; - -const CardsDisplay = ({ selectedDeck, isLoading }) => { - const { theme } = useMode(); - return ( - - {selectedDeck?.cards?.length > 0 ? ( - - ) : ( - No cards to display - )} - - ); -}; - -export default CardsDisplay; diff --git a/src/layout/deck/DeckDisplay.js b/src/layout/deck/DeckDisplay.js index 3daed96..6c11092 100644 --- a/src/layout/deck/DeckDisplay.js +++ b/src/layout/deck/DeckDisplay.js @@ -1,10 +1,8 @@ import React, { useContext, useEffect, useState } from 'react'; import { useDeckStore } from '../../context/MAIN_CONTEXT/DeckContext/DeckContext'; import { useMode, useUserContext } from '../../context'; - -import DeckListToggle from './DeckListToggle'; import DeckEditor from './DeckEditor'; -import CardsDisplay from './CardsDisplay'; +// import CardsDisplay from './CardsDisplay'; import { DeckCardsContainer, DeckDisplayBox, @@ -17,8 +15,9 @@ import MDBox from '../REUSABLE_COMPONENTS/MDBOX'; import SettingsIcon from '@mui/icons-material/Settings'; import { Grid, IconButton } from '@mui/material'; import { StyledContainerBoxPrimary } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; -import SelectDeckList from '../../components/grids/deckBuilderGrids/SelectDeckList'; +import SelectDeckList from './SelectDeckList'; import AppsIcon from '@mui/icons-material/Apps'; +import useGridItems from '../../context/hooks/useGridItems'; const DeckDisplay = () => { const { theme } = useMode(); @@ -53,6 +52,14 @@ const DeckDisplay = () => { // // Assuming setFormType is a function that can set the form context // setFormType('addDeckForm'); // }, []); + + const cardDisplay = useGridItems({ + itemsPerPage: 8, // Define as per your requirement + cards: selectedDeck?.cards || [], + pageContext: 'DeckDisplay', // Context to pass to GenericCard + isLoading: isLoading, // Pass the actual loading state + }); + return ( {/* */} @@ -145,17 +152,12 @@ const DeckDisplay = () => { {selectedDeck && ( - + )} - + {selectedDeck && cardDisplay} {/* */} diff --git a/src/components/dialogs/DeckEditPanel.js b/src/layout/deck/DeckEditPanel.js similarity index 97% rename from src/components/dialogs/DeckEditPanel.js rename to src/layout/deck/DeckEditPanel.js index 51dfab0..82e0992 100644 --- a/src/components/dialogs/DeckEditPanel.js +++ b/src/layout/deck/DeckEditPanel.js @@ -3,7 +3,7 @@ import SaveIcon from '@mui/icons-material/Save'; import DeleteIcon from '@mui/icons-material/Delete'; import { useFormContext } from '../../context'; import { z } from 'zod'; -import RCZodForm from '../forms/reusable/RCZodForm'; +import RCZodForm from '../../components/forms/reusable/RCZodForm'; const deckSchema = z.object({ name: z.string().min(1, 'Name is required'), diff --git a/src/layout/deck/DeckEditor.jsx b/src/layout/deck/DeckEditor.jsx index 6f55246..02e1e3e 100644 --- a/src/layout/deck/DeckEditor.jsx +++ b/src/layout/deck/DeckEditor.jsx @@ -1,35 +1,15 @@ import React, { useState, useEffect } from 'react'; -import { - Paper, - Typography, - FormControlLabel, - Switch, - Box, -} from '@mui/material'; -import DeckEditPanel from '../../components/dialogs/DeckEditPanel'; +import { Paper, Typography, Box } from '@mui/material'; +import DeckEditPanel from './DeckEditPanel'; import { useDeckStore } from '../../context/MAIN_CONTEXT/DeckContext/DeckContext'; -import useDeckStyles from '../../context/hooks/style-hooks/useDeckStyles'; -import { SwitchControl } from '../../pages/pageStyles/StyledComponents'; import { useFormContext, useMode } from '../../context'; -import DeckSwitch from '../../components/buttons/other/DeckSwitch'; +import RCSwitch from '../../components/forms/reusable/RCSwitch'; +import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline'; const DeckEditor = () => { const { selectedDeck, setSelectedDeck } = useDeckStore(); const { theme } = useMode(); - const { - formStates, // Assuming this provides access to the current form state including errors - formMethods, // Assuming this provides access to register, handleSubmit, etc. - onSubmit, - currentForm, - toggleForm, - - // handleChange, - // handleBlur, - // handleFocus, - // formMethods, // Assuming formMethods provides access to register, handleSubmit, etc. - } = useFormContext(); - - // const { currentForm: currentFormType } = formStates; + const { currentForm, toggleForm, currentSchemaKey } = useFormContext(); const handleToggleEdit = () => { if (currentForm === 'updateDeckForm') { @@ -54,10 +34,6 @@ const DeckEditor = () => { {selectedDeck ? 'Edit Deck' : 'Create New Deck'} - {/* } - label={isEditing ? 'Editing' : 'Adding'} - /> */} { gap: 2, }} > - } + iconRight={} /> diff --git a/src/layout/deck/DeckListToggle.jsx b/src/layout/deck/DeckListToggle.jsx deleted file mode 100644 index ae15c53..0000000 --- a/src/layout/deck/DeckListToggle.jsx +++ /dev/null @@ -1,52 +0,0 @@ -import React from 'react'; -import { Button, Box } from '@mui/material'; -import AppsIcon from '@mui/icons-material/Apps'; -import SelectDeckList from '../../components/grids/deckBuilderGrids/SelectDeckList'; - -import { useMode } from '../../context'; -import { - DeckCardsContainer, - DeckStyledButton, -} from '../../pages/pageStyles/StyledComponents'; - -const DeckListToggle = ({ - showAllDecks, - setShowAllDecks, - handleSelectDeck, - allDecks, -}) => { - const { theme } = useMode(); - return ( - <> - setShowAllDecks(!showAllDecks)} - variant="contained" - sx={{ - width: '100%', - borderRadius: 0, - borderTopLeftRadius: 4, - borderTopRightRadius: 4, - backgroundColor: theme.palette.backgroundA.dark, - color: theme.palette.text.primary, - '&:hover': { - backgroundColor: theme.palette.backgroundA.light, - }, - }} - > - - {showAllDecks ? 'Hide Decks' : 'Show All Decks'} - - {showAllDecks && ( - - - - )} - - ); -}; - -export default DeckListToggle; diff --git a/src/components/grids/deckBuilderGrids/SelectDeckList.jsx b/src/layout/deck/SelectDeckList.jsx similarity index 82% rename from src/components/grids/deckBuilderGrids/SelectDeckList.jsx rename to src/layout/deck/SelectDeckList.jsx index 90d87af..49fb765 100644 --- a/src/components/grids/deckBuilderGrids/SelectDeckList.jsx +++ b/src/layout/deck/SelectDeckList.jsx @@ -1,8 +1,8 @@ import React from 'react'; import { Grid, Chip, Typography } from '@mui/material'; -import DeckBuilderIcon from '../../../layout/REUSABLE_COMPONENTS/icons/DeckBuilderIcon'; -import { useDeckStore } from '../../../context/MAIN_CONTEXT/DeckContext/DeckContext'; -import { useMode } from '../../../context'; +import DeckBuilderIcon from '../REUSABLE_COMPONENTS/icons/DeckBuilderIcon'; +import { useDeckStore } from '../../context/MAIN_CONTEXT/DeckContext/DeckContext'; +import { useMode } from '../../context'; const SelectDeckList = ({ handleSelectDeck }) => { const { allDecks } = useDeckStore(); diff --git a/src/layout/navigation/MenuItemComponent.jsx b/src/layout/navigation/MenuItemComponent.jsx deleted file mode 100644 index fcca2a8..0000000 --- a/src/layout/navigation/MenuItemComponent.jsx +++ /dev/null @@ -1,77 +0,0 @@ -import React from 'react'; -import { - styled, - MenuItem, - ListItemIcon, - ListItemText, - Typography, - Grow, - ListItemAvatar, - Avatar, - Card, - CardContent, - ListItem, -} from '@mui/material'; -import { useNavigate } from 'react-router-dom'; -import { useMode } from '../../context'; -import { - StyledBox, - StyledMenuItem, -} from '../../pages/pageStyles/StyledComponents'; -import { useSpring, animated } from 'react-spring'; -import MDTypography from '../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -const MenuItemComponent = ({ item, onClick, visibleItems, index }) => { - const { theme } = useMode(); - const navigate = useNavigate(); - - const itemAnimation = useSpring({ - from: { transform: 'scale(0)' }, - to: { transform: 'scale(1)' }, - delay: 200, - }); - - const handleClick = () => { - navigate(item.to); - if (onClick) onClick(); - }; - - return ( - <> - - - - {item.icon} - {' '} - - - - {item?.name} - - } - // secondary={ - // - // {item?.description} - // - // } - /> - - ); -}; - -export default MenuItemComponent; diff --git a/src/layout/navigation/Navigation.jsx b/src/layout/navigation/Navigation.jsx index 7d8f302..3f2d2e1 100644 --- a/src/layout/navigation/Navigation.jsx +++ b/src/layout/navigation/Navigation.jsx @@ -55,28 +55,6 @@ const Navigation = ({ isLoggedIn }) => { return () => window.removeEventListener('resize', handleResize); }, []); const [isMounted, setIsMounted] = useState(false); - // useEffect(() => { - // setIsMounted(true); // Set to true when component mounts - - // // Fetch data as before - // const fetchData = async () => { - // const cartCardQuantity = totalQuantity; - // const items = await getMenuItemsData( - // isLoggedIn, - // cartCardQuantity, - // iconColor - // ); // Simulated fetch call - - // if (isMounted) { - // // Check if component is still mounted before setting state - // setMenuItems(items.map((item) => ({ ...item, isVisible: true }))); // Assuming visibility logic is simplified - // } - // }; - // fetchData(); - - // return () => setIsMounted(false); // Set to false when component unmounts - // }, [isLoggedIn, totalQuantity, iconColor, isMounted]); // Include isMounted in dependency array if it's used within the effect - const [springs, api] = useSprings(menuItems.length, (index) => ({ from: { opacity: 0, transform: 'translateY(-20px)' }, to: { opacity: 1, transform: 'translateY(0)' }, @@ -87,35 +65,33 @@ const Navigation = ({ isLoggedIn }) => { springs.map((style, index) => ( navigate(menuItems[index].to)} sx={{ - width: 'clamp(250px, 50%, 300px)', // Responsive width using clamp + width: 'clamp(130px, 50%, 175px)', // Responsive width using clamp + maxHeight: 64, + mx: theme.spacing(4), '&:hover': { backgroundColor: theme.palette.backgroundF.light, color: 'white', }, - '& .MuiListItemAvatar-root': { - justifyContent: 'flex-end', - }, - '& .MuiListItemText-root': { - mr: 1, - }, }} > - - - {menuItems[index].icon} - - + + {menuItems[index].icon}{' '} + { diff --git a/src/pages/CollectionPage.js b/src/pages/CollectionPage.js index 1e4686c..7ab341a 100644 --- a/src/pages/CollectionPage.js +++ b/src/pages/CollectionPage.js @@ -1,7 +1,7 @@ import React, { useEffect } from 'react'; import { Box, Grid } from '@mui/material'; import CollectionPortfolio from '../layout/collection'; -import GenericCardDialog from '../components/dialogs/cardDialog/GenericCardDialog'; +import GenericCardDialog from '../components/dialogs/GenericCardDialog'; import { useCollectionStore, useMode } from '../context'; import useLoadingAndModal from './pageStyles/useLoadingAndModal'; import HeroBanner from './pageStyles/HeroBanner'; diff --git a/src/pages/DeckBuilderPage.js b/src/pages/DeckBuilderPage.js index 09cdca1..726a3ed 100644 --- a/src/pages/DeckBuilderPage.js +++ b/src/pages/DeckBuilderPage.js @@ -1,6 +1,6 @@ import React from 'react'; import { Grid } from '@mui/material'; -import GenericCardDialog from '../components/dialogs/cardDialog/GenericCardDialog'; +import GenericCardDialog from '../components/dialogs/GenericCardDialog'; import DeckBuilder from '../layout/deck'; import MDBox from '../layout/REUSABLE_COMPONENTS/MDBOX'; import useLoadingAndModal from './pageStyles/useLoadingAndModal'; diff --git a/src/pages/HomePage.js b/src/pages/HomePage.js index 922fda7..34daf19 100644 --- a/src/pages/HomePage.js +++ b/src/pages/HomePage.js @@ -1,8 +1,8 @@ import React, { useContext, useEffect, useRef } from 'react'; import { CardHeader, Grid, Box, useMediaQuery } from '@mui/material'; import { useModalContext } from '../context/UTILITIES_CONTEXT/ModalContext/ModalContext'; -import GenericCardDialog from '../components/dialogs/cardDialog/GenericCardDialog'; -import DetailsModal from '../components/dialogs/homeDetailsModal/DetailsModal'; +import GenericCardDialog from '../components/dialogs/GenericCardDialog'; +import DetailsModal from '../components/dialogs/DetailsModal'; import SplashPage2 from '../layout/REUSABLE_COMPONENTS/SplashPage2'; import PageLayout from '../layout/Containers/PageLayout'; import HeroSection from './sections/HeroSection'; diff --git a/src/pages/StorePage.js b/src/pages/StorePage.js index 47d93fc..8676fd5 100644 --- a/src/pages/StorePage.js +++ b/src/pages/StorePage.js @@ -1,6 +1,6 @@ import React, { useRef, useState } from 'react'; import { Grid } from '@mui/material'; -import GenericCardDialog from '../components/dialogs/cardDialog/GenericCardDialog'; +import GenericCardDialog from '../components/dialogs/GenericCardDialog'; import MDBox from '../layout/REUSABLE_COMPONENTS/MDBOX'; import StoreSearch from '../layout/store/StoreSearch'; import useLoadingAndModal from './pageStyles/useLoadingAndModal'; diff --git a/src/pages/sections/FeatureCardsSection.jsx b/src/pages/sections/FeatureCardsSection.jsx index c565459..3d78cfc 100644 --- a/src/pages/sections/FeatureCardsSection.jsx +++ b/src/pages/sections/FeatureCardsSection.jsx @@ -3,7 +3,7 @@ import { Grid } from '@mui/material'; import { useTheme } from '@mui/system'; import { useMediaQuery } from '@mui/material'; -import { AnimatedFeatureCard } from '../../components/cards/AnimatedFeatureCard'; +import { AnimatedFeatureCard } from '../../layout/AnimatedFeatureCard'; import { useModalContext } from '../../context/UTILITIES_CONTEXT/ModalContext/ModalContext'; import { useResponsiveStyles } from '../../context/hooks/style-hooks/useResponsiveStyles'; import { useMode } from '../../context'; diff --git a/src/save/CardsDisplay.jsx b/src/save/CardsDisplay.jsx new file mode 100644 index 0000000..ae70378 --- /dev/null +++ b/src/save/CardsDisplay.jsx @@ -0,0 +1,23 @@ +// import React from 'react'; +// import { Box, Typography } from '@mui/material'; +// import CardsGrid from '../../components/grids/deckBuilderGrids/CardsGrid'; +// import { useMode } from '../../context'; +// import { +// DeckCardsContainer, +// NoCardsTypography, +// } from '../../pages/pageStyles/StyledComponents'; + +// const CardsDisplay = ({ selectedDeck, isLoading }) => { +// const { theme } = useMode(); +// return ( +// +// {selectedDeck?.cards?.length > 0 ? ( +// +// ) : ( +// No cards to display +// )} +// +// ); +// }; + +// export default CardsDisplay; diff --git a/src/save/CardsGrid.js b/src/save/CardsGrid.js new file mode 100644 index 0000000..cdc4567 --- /dev/null +++ b/src/save/CardsGrid.js @@ -0,0 +1,75 @@ +// import React, { useMemo } from 'react'; +// import { Grid, Grow, Typography } from '@mui/material'; +// import { useDeckStore } from '../../../context/MAIN_CONTEXT/DeckContext/DeckContext'; +// import StoreItem from '../gridItems/StoreItem'; +// import MDBox from '../../../layout/REUSABLE_COMPONENTS/MDBOX'; +// import GridLayout from '../../../layout/Containers/GridLayout'; +// import SkeletonCard from '../gridItems/SkeletonCard'; + +// const CardsGrid = ({ isLoading }) => { +// const { selectedCards } = useDeckStore(); + +// // Efficiently flattening and processing selectedCards with useMemo +// const flattenSelectedCards = useMemo(() => { +// if (!Array.isArray(selectedCards)) return []; + +// const cardCountMap = new Map(); + +// return selectedCards.reduce((acc, card) => { +// if (!card) return acc; +// const currentCount = (cardCountMap.get(card.id) || 0) + 1; +// if (currentCount <= 3) { +// acc.push({ ...card, uniqueKey: `${card.id}-${currentCount - 1}` }); +// cardCountMap.set(card.id, currentCount); +// } +// return acc; +// }, []); +// }, [selectedCards]); + +// const gridItems = useMemo(() => { +// return isLoading ? Array.from({ length: 12 }) : flattenSelectedCards; +// }, [isLoading, flattenSelectedCards]); + +// // Define grid item breakpoints once to reuse in the mapping +// const gridItemProps = { xs: 6, sm: 4, md: 4, lg: 4 }; + +// return ( +// +// {gridItems.map((item, index) => ( +// +// +// +// {isLoading ? ( +// +// ) : ( +// +// )} +// +// +// +// ))} +// +// ); +// }; + +// export default React.memo(CardsGrid); diff --git a/src/layout/navigation/MenuCard.jsx b/src/save/MenuCard.jsx similarity index 100% rename from src/layout/navigation/MenuCard.jsx rename to src/save/MenuCard.jsx diff --git a/src/zcleanup/AddButton.jsx b/src/zcleanup/AddButton.jsx deleted file mode 100644 index 66a64d0..0000000 --- a/src/zcleanup/AddButton.jsx +++ /dev/null @@ -1,71 +0,0 @@ -// import { LoadingButton } from '@mui/lab'; -// import MDButton from '../../../layout/REUSABLE_COMPONENTS/MDBUTTON'; // Assuming MDButton is used elsewhere or can be removed if not needed -// import AddIcon from '@mui/icons-material/Add'; // Make sure this import is used if you need it elsewhere in your component or remove it if it's unused -// import { AddCircleOutlineOutlined } from '@mui/icons-material'; -// import { useMode } from '../../../context'; -// import MDTypography from '../../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -// import { getContextIcon } from '../../reusable/icons'; -// import { useLoading } from '../../../context/hooks/useLoading'; - -// const getLabelAndVariant = (buttonSize, labelValue, action) => { -// const labelTypeMap = { -// extraSmall: null, -// small: `${action}`, -// medium: `${action}`, -// // large: `${action}` + action === 'add' ? 'to ' : 'from ' + `${labelValue}`, -// large: `${labelValue}`, -// }; -// const buttonVariantMap = { -// extraSmall: 'body4', -// small: 'body3', -// medium: 'body2', -// large: 'body4', -// }; -// return { -// buttonLabel: labelTypeMap[buttonSize], -// buttonVariant: buttonVariantMap[buttonSize], -// }; -// }; -// // Styled add button -// const AddButton = ({ buttonSize, handleCardAction, labelValue, action }) => { -// const { theme } = useMode(); -// // const currentContextIcon = getContextIcon(labelValue); -// const tempLabel = action === 'add' ? 'Add' : 'Remove'; -// const { startLoading, stopLoading, isLoading } = useLoading(); -// const { buttonLabel, buttonVariant } = getLabelAndVariant( -// buttonSize, -// tempLabel, -// // labelValue, -// action -// ); - -// return ( -// handleCardAction('add')} -// startIcon={} -// sx={{ -// width: '100%', -// flexGrow: 1, -// borderRadius: theme.shape.borderRadius, -// maxWidth: '100%', -// backgroundColor: theme.palette.success.main, -// justifyContent: 'center', -// alignItems: 'center', -// display: 'flex', -// }} -// > -// -// {buttonLabel} -// -// -// ); -// }; - -// export default AddButton; diff --git a/src/zcleanup/CollectionPortfolioContent.jsx b/src/zcleanup/CollectionPortfolioContent.jsx deleted file mode 100644 index 8471e88..0000000 --- a/src/zcleanup/CollectionPortfolioContent.jsx +++ /dev/null @@ -1,58 +0,0 @@ -// // PortfolioContent.jsx -// import React, { useEffect, useState } from 'react'; -// import { Grid } from '@mui/material'; -// // eslint-disable-next-line max-len -// import { useCollectionStore } from '../../context/MAIN_CONTEXT/CollectionContext/CollectionContext'; -// import { useMode } from '../../context'; -// import DashboardLayout from '../Containers/DashBoardLayout'; -// import MDBox from '../REUSABLE_COMPONENTS/MDBOX'; -// import collectionPortfolioData from './data/collectionPortfolioData'; -// import ChartGridLayout from './collectionGrids/ChartGridLayout'; -// import StatisticsCardGrid from './collectionGrids/StatisticsCardsGrid'; -// import CollectionPortfolioHeader from './sub-components/CollectionPortfolioHeader'; - -// const CollectionPortfolioContent = ({ selectedCards, removeCard, onBack }) => { -// const { theme } = useMode(); - -// const { selectedCollection, totalQuantity } = useCollectionStore(); -// const [collectionName, setCollectionName] = useState( -// selectedCollection?.name || '' -// ); -// const { columns, data } = collectionPortfolioData( -// selectedCollection?.cards, -// null, -// null, -// null -// ); - -// return ( -// -// -// {/* HEADER */} -// -// -// -// {/* STATISTICS FEATURE GRID */} -// -// -// -// {/* CHARTS */} -// -// -// -// -// -// ); -// }; - -// export default CollectionPortfolioContent; diff --git a/src/zcleanup/CustomSelector.js b/src/zcleanup/CustomSelector.js deleted file mode 100644 index bc9e771..0000000 --- a/src/zcleanup/CustomSelector.js +++ /dev/null @@ -1,93 +0,0 @@ -// import React from 'react'; -// import { useTheme } from '@mui/material/styles'; -// import OutlinedInput from '@mui/material/OutlinedInput'; -// import MenuItem from '@mui/material/MenuItem'; -// import FormControl from '@mui/material/FormControl'; -// import Select from '@mui/material/Select'; -// import PropTypes from 'prop-types'; - -// const ITEM_HEIGHT = 48; -// const ITEM_PADDING_TOP = 8; -// const MenuProps = { -// PaperProps: { -// style: { -// maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, -// width: 250, -// }, -// }, -// }; - -// function getStyles(name, selected, theme) { -// return { -// fontWeight: -// selected.indexOf(name) === -1 -// ? theme.typography.fontWeightRegular -// : theme.typography.fontWeightMedium, -// }; -// } - -// const CustomMultipleSelect = ({ -// items, -// selectedItems, -// onChange, -// placeholder, -// label, -// }) => { -// const theme = useTheme(); - -// const handleChange = (event) => { -// const { -// target: { value }, -// } = event; -// onChange(typeof value === 'string' ? value.split(',') : value); -// }; - -// return ( -// -// -// -// ); -// }; - -// CustomMultipleSelect.propTypes = { -// items: PropTypes.arrayOf(PropTypes.string).isRequired, -// selectedItems: PropTypes.arrayOf(PropTypes.string).isRequired, -// onChange: PropTypes.func.isRequired, -// placeholder: PropTypes.string, -// label: PropTypes.string, -// }; - -// CustomMultipleSelect.defaultProps = { -// placeholder: 'Select items', -// label: 'Custom select', -// }; - -// export default CustomMultipleSelect; diff --git a/src/zcleanup/InputComponents/CardNameInput.js b/src/zcleanup/InputComponents/CardNameInput.js deleted file mode 100644 index ac66225..0000000 --- a/src/zcleanup/InputComponents/CardNameInput.js +++ /dev/null @@ -1,22 +0,0 @@ -// import React from 'react'; -// import { Input } from '@mui/material'; -// import { useCardStore } from '../../../context/CardContext/CardStore'; - -// const CardNameInput = ({ value, setValue, handleChange }) => { -// const { handleRequest } = useCardStore(); -// return ( -// { -// if (event.key === 'Enter') { -// handleRequest(value); -// } -// }} -// value={value} -// /> -// ); -// }; - -// export default CardNameInput; diff --git a/src/zcleanup/InputComponents/UpdateStatusBox.jsx b/src/zcleanup/InputComponents/UpdateStatusBox.jsx deleted file mode 100644 index ff2863e..0000000 --- a/src/zcleanup/InputComponents/UpdateStatusBox.jsx +++ /dev/null @@ -1,100 +0,0 @@ -// import React, { useState, useEffect } from 'react'; -// import { Box, Typography } from '@mui/material'; -// import { useCombinedContext } from '../../../context/CombinedProvider'; -// import { useCookies } from 'react-cookie'; - -// const UpdateStatusBox = ({ socket }) => { -// const { allCollectionData, listOfMonitoredCards, listOfSimulatedCards } = -// useCombinedContext(); -// const [currentTime, setCurrentTime] = useState(new Date()); -// const [updateStatus, setUpdateStatus] = useState('Waiting for updates...'); -// const [cookies] = useCookies(['authUser']); - -// useEffect(() => { -// const timeInterval = setInterval(() => { -// setCurrentTime(new Date()); -// }, 1000); - -// const handleStatusUpdate = (statusUpdate) => { -// setUpdateStatus(statusUpdate.message || 'Waiting for updates...'); -// }; - -// if (socket) { -// socket.on('STATUS_UPDATE', handleStatusUpdate); -// } - -// // Cleanup function -// return () => { -// clearInterval(timeInterval); -// if (socket) { -// socket.off('STATUS_UPDATE', handleStatusUpdate); -// } -// }; -// }, [socket]); - -// const sendUpdateRequest = () => { -// if (socket) { -// socket.emit('STATUS_UPDATE_REQUEST', { -// message: 'Requesting status update...', -// data: listOfMonitoredCards, -// }); -// } -// }; - -// // Styling for dark theme -// const styles = { -// container: { -// padding: '15px', -// border: '2px solid #444', -// borderRadius: '8px', -// backgroundColor: '#222', -// color: '#fff', -// // margin: '20px auto', -// boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', -// fontFamily: '"Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif', -// maxWidth: '400px', -// display: 'flex', -// flexDirection: 'column', -// justifyContent: 'space-between', -// alignItems: 'center', -// height: '100%', // Adjust height here -// width: '100%', // Adjust width here -// }, -// statusBox: { -// marginTop: '15px', -// padding: '10px', -// background: '#333', -// borderRadius: '6px', -// border: '1px solid #555', -// }, -// button: { -// padding: '10px 20px', -// marginTop: '10px', -// border: 'none', -// borderRadius: '5px', -// cursor: 'pointer', -// backgroundColor: '#5CDB95', -// color: 'white', -// fontWeight: 'bold', -// fontSize: '14px', -// letterSpacing: '1px', -// outline: 'none', -// }, -// }; - -// return ( -// -// -// Current Time: {currentTime.toLocaleTimeString()} -// -//
-// Update Status: {updateStatus} -//
-// -//
-// ); -// }; - -// export default UpdateStatusBox; diff --git a/src/zcleanup/InputComponents/UpdateStatusBox2.jsx b/src/zcleanup/InputComponents/UpdateStatusBox2.jsx deleted file mode 100644 index 33f0a74..0000000 --- a/src/zcleanup/InputComponents/UpdateStatusBox2.jsx +++ /dev/null @@ -1,91 +0,0 @@ -// import React, { useState, useEffect } from 'react'; -// import { Snackbar, Typography, Box, Button } from '@mui/material'; -// import { useCookies } from 'react-cookie'; -// import { useCombinedContext, useMode } from '../../../context'; -// import { StyledChartBox } from '../../../pages/pageStyles/StyledComponents'; - -// const UpdateStatusBox2 = ({ socket }) => { -// const { listOfMonitoredCards, handleSendAllCardsInCollections } = -// useCombinedContext(); -// const [currentTime, setCurrentTime] = useState(new Date()); -// const [updateStatus, setUpdateStatus] = useState('Waiting for cron...'); -// const [cookies] = useCookies(['authUser']); -// const [snackbarData, setSnackbarData] = useState({ -// open: false, -// message: '', -// }); - -// const userId = cookies?.authUser?.userId; -// const { theme } = useMode(); -// const openSnackbar = (message) => { -// setSnackbarData({ open: true, message }); -// }; - -// useEffect(() => { -// const timeInterval = setInterval(() => { -// setCurrentTime(new Date()); -// }, 1000); - -// const handleStatusUpdate = (statusUpdate) => { -// setUpdateStatus( -// (prevStatus) => -// statusUpdate.message || prevStatus || 'Waiting for updates...' -// ); -// }; - -// socket?.on('INITIAL_RESPONSE', handleStatusUpdate); - -// return () => { -// clearInterval(timeInterval); -// socket?.off('INITIAL_RESPONSE', handleStatusUpdate); -// }; -// }, [socket]); // Assuming `socket` is stable and doesn't change on every render - -// const handleTriggerCronJob = () => { -// if (userId && listOfMonitoredCards.length > 0) { -// handleSendAllCardsInCollections(userId, listOfMonitoredCards); -// openSnackbar('Triggered the cron job.'); -// } -// }; - -// return ( -// -// -// Current Time: {currentTime.toLocaleTimeString()} -// -// -// Update Status: {updateStatus} -// -// -// setSnackbarData({ ...snackbarData, open: false })} -// message={snackbarData.message} -// /> -// -// ); -// }; - -// export default UpdateStatusBox2; diff --git a/src/zcleanup/Notifications.jsx b/src/zcleanup/Notifications.jsx deleted file mode 100644 index 2284473..0000000 --- a/src/zcleanup/Notifications.jsx +++ /dev/null @@ -1,230 +0,0 @@ -import PriceChangeIcon from '@mui/icons-material/PriceChange'; - -import { useState } from 'react'; - -// @mui material components -import Grid from '@mui/material/Grid'; -import Card from '@mui/material/Card'; - -// Material Dashboard 2 React components -import MDBox from 'components/MDBox'; -import MDTypography from 'components/MDTypography'; -import MDAlert from 'components/MDAlert'; -import MDButton from 'components/MDButton'; -import MDSnackbar from 'components/MDSnackbar'; - -// Material Dashboard 2 React example components -import DashboardLayout from 'examples/LayoutContainers/DashboardLayout'; -import DashboardNavbar from 'examples/Navbars/DashboardNavbar'; -import Footer from 'examples/Footer'; - -function Notifications() { - const [successSB, setSuccessSB] = useState(false); - const [infoSB, setInfoSB] = useState(false); - const [warningSB, setWarningSB] = useState(false); - const [errorSB, setErrorSB] = useState(false); - - const openSuccessSB = () => setSuccessSB(true); - const closeSuccessSB = () => setSuccessSB(false); - const openInfoSB = () => setInfoSB(true); - const closeInfoSB = () => setInfoSB(false); - const openWarningSB = () => setWarningSB(true); - const closeWarningSB = () => setWarningSB(false); - const openErrorSB = () => setErrorSB(true); - const closeErrorSB = () => setErrorSB(false); - - const alertContent = (name) => ( - - A simple {name} alert with - - an example link - - . Give it a click if you like. - - ); - - const renderSuccessSB = ( - - ); - - const renderInfoSB = ( - - ); - - const renderWarningSB = ( - - ); - - const renderErrorSB = ( - - ); - - return ( - - - - - - - - Alerts - - - - {alertContent('primary')} - - - {alertContent('secondary')} - - - {alertContent('success')} - - - {alertContent('error')} - - - {alertContent('warning')} - - - {alertContent('info')} - - - {alertContent('light')} - - - {alertContent('dark')} - - - {alertContent('blueGreen')} - - - - - - - - - Notifications - - Notifications on this page use Toasts from Bootstrap. Read - more details here. - - - - - - - success notification - - {renderSuccessSB} - - - - info notification - - {renderInfoSB} - - - - warning notification - - {renderWarningSB} - - - - error notification - - {renderErrorSB} - - {/* CUSTOMIZED API NOTIFICATIONS */} - - - Price Change Notification - - {renderSuccessSB} - - - - - - - -
- - ); -} - -export default Notifications; diff --git a/src/zcleanup/RemoveButton.jsx b/src/zcleanup/RemoveButton.jsx deleted file mode 100644 index bb2c7ce..0000000 --- a/src/zcleanup/RemoveButton.jsx +++ /dev/null @@ -1,75 +0,0 @@ -// import { LoadingButton } from '@mui/lab'; -// import MDButton from '../../../layout/REUSABLE_COMPONENTS/MDBUTTON'; -// import RemoveIcon from '@mui/icons-material/Remove'; -// import { useMode } from '../../../context'; -// import { RemoveCircleOutlineOutlined } from '@mui/icons-material'; -// import MDTypography from '../../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -// import { getContextIcon } from '../../reusable/icons'; -// import { useLoading } from '../../../context/hooks/useLoading'; -// const getLabelAndVariant = (buttonSize, labelValue, action) => { -// const labelTypeMap = { -// extraSmall: null, -// small: `${action}`, -// medium: `${action}`, -// large: `${action}` + action === 'add' ? 'to' : 'from' + `${labelValue}`, -// }; -// const buttonVariantMap = { -// extraSmall: 'body4', -// small: 'body3', -// medium: 'body2', -// large: 'body4', -// }; -// return { -// buttonLabel: labelTypeMap[buttonSize], -// buttonVariant: buttonVariantMap[buttonSize], -// }; -// }; -// // Styled remove button -// const RemoveButton = ({ buttonSize, handleCardAction, labelValue, action }) => { -// const { theme } = useMode(); -// const currentContextIcon = getContextIcon(labelValue); -// const { startLoading, stopLoading, isLoading } = useLoading(); -// const { buttonLabel, buttonVariant } = getLabelAndVariant( -// buttonSize, -// labelValue, -// action -// ); - -// return ( -// handleCardAction('remove')} -// // getButtonLabel={getButtonLabel} -// startIcon={} -// sx={{ -// width: '100%', // Button grows to fill the container -// flexGrow: 1, // Grow to fill the parent container -// // minWidth: buttonSize === 'small' ? '25px' : '100px', // Ensure buttons have a minimum width -// backgroundColor: theme.palette.error.main, -// borderRadius: theme.shape.borderRadius, // Use theme values for consistent styling -// // width: '100%', // Button grows to fill the container -// // minWidth: '100px', // Ensure buttons have a minimum width -// maxWidth: '100%', // Ensure buttons have a maximum width -// justifyContent: 'center', -// alignItems: 'center', -// display: 'flex', -// // p: 1, -// '&:hover': { -// backgroundColor: theme.palette.error.dark, -// }, -// }} -// > -// -// {buttonLabel} -// -// -// ); -// }; - -// export default RemoveButton; diff --git a/src/zcleanup/SelectCollection.jsx b/src/zcleanup/SelectCollection.jsx deleted file mode 100644 index f6b68d5..0000000 --- a/src/zcleanup/SelectCollection.jsx +++ /dev/null @@ -1,84 +0,0 @@ -// import React, { useState, useCallback } from 'react'; -// import { Box, Card, Grid, Skeleton } from '@mui/material'; -// import { useCollectionStore } from '../../context/MAIN_CONTEXT/CollectionContext/CollectionContext'; -// import { useFormContext, useMode } from '../../context'; -// import SelectCollectionHeader from './sub-components/SelectCollectionHeader'; -// import CollectionDialog from '../../components/dialogs/CollectionDialog'; -// import DashboardLayout from '../Containers/DashBoardLayout'; -// import MDBox from '../REUSABLE_COMPONENTS/MDBOX'; -// import SelectCollectionList from './collectionGrids/collections-list/SelectCollectionList'; -// import CollectionListStats from './collectionGrids/CollectionListStats'; -// import LoadingIndicator from '../../components/reusable/indicators/LoadingIndicator'; - -// const SelectCollection = () => { -// const { theme } = useMode(); -// const [isDialogOpen, setDialogOpen] = useState(false); -// const { currentForm } = useFormContext(); -// const openNewDialog = useCallback((addOrEdit) => { -// setDialogOpen(true); // Correctly opens the dialog -// }, []); -// const handleDialogToggle = () => setDialogOpen(!isDialogOpen); -// const handleCloseDialog = () => setDialogOpen(false); -// const { allCollections, selectedCollection } = useCollectionStore(); - -// return ( -// -// -// -// -// -// {' '} -// -// -// -// -// -// -// -// -// -// -// - -// {isDialogOpen && ( -// -// )} -// -// -// ); -// }; - -// export default SelectCollection; diff --git a/src/zcleanup/dataDisplay/CardCountDisplay.jsx b/src/zcleanup/dataDisplay/CardCountDisplay.jsx deleted file mode 100644 index 7f85461..0000000 --- a/src/zcleanup/dataDisplay/CardCountDisplay.jsx +++ /dev/null @@ -1,42 +0,0 @@ -// import React from 'react'; -// import { Grid, Typography } from '@mui/material'; -// import { styled } from '@mui/material/styles'; -// import PropTypes from 'prop-types'; - -// // Styled components -// const StyledGrid = styled(Grid)(({ theme }) => ({ -// padding: theme.spacing(1), -// backgroundColor: theme.palette.backgroundA.lightest, -// borderRadius: theme.shape.borderRadius, -// boxShadow: theme.shadows[2], -// textAlign: 'center', -// })); - -// const CardCountDisplay = ({ quantity, label, className }) => { -// const totalItems = quantity && quantity.totalItems ? quantity.totalItems : 0; - -// return ( -// -// -// -// {label}: {totalItems} -// -// -// -// ); -// }; - -// CardCountDisplay.propTypes = { -// quantity: PropTypes.shape({ -// totalItems: PropTypes.number, -// }), -// label: PropTypes.string, -// className: PropTypes.string, -// }; - -// export default CardCountDisplay; diff --git a/src/zcleanup/dataDisplay/CartTotal.jsx b/src/zcleanup/dataDisplay/CartTotal.jsx deleted file mode 100644 index 1f65e9e..0000000 --- a/src/zcleanup/dataDisplay/CartTotal.jsx +++ /dev/null @@ -1,10 +0,0 @@ -// import React from 'react'; -// import { Typography } from '@mui/material'; - -// const CartTotal = ({ total }) => ( -// -// {`Total: $${total}`} {/* Ensure this is a string or number */} -// -// ); - -// export default CartTotal; diff --git a/src/zcleanup/dataDisplay/StatBox.jsx b/src/zcleanup/dataDisplay/StatBox.jsx deleted file mode 100644 index 34fa85d..0000000 --- a/src/zcleanup/dataDisplay/StatBox.jsx +++ /dev/null @@ -1,43 +0,0 @@ -// import { Box, Typography, useTheme } from '@mui/material'; -// import ProgressCircle from './ProgressCircle'; -// import { tokens } from '../../../assets/tokens'; - -// const StatBox = ({ title, subtitle, icon, progress, increase }) => { -// const theme = useTheme(); -// const colors = tokens(theme.palette.mode); - -// return ( -// -// -// -// {icon} -// -// {title} -// -// -// -// -// -// - -// -// -// {subtitle} -// -// -// {increase} -// -// -// -// ); -// }; - -// export default StatBox; diff --git a/src/zcleanup/dataDisplay/StatCard.jsx b/src/zcleanup/dataDisplay/StatCard.jsx deleted file mode 100644 index a2655b1..0000000 --- a/src/zcleanup/dataDisplay/StatCard.jsx +++ /dev/null @@ -1,17 +0,0 @@ -// import React from 'react'; -// import { Card, CardContent, Typography } from '@mui/material'; - -// const StatCard = ({ title, value }) => ( -// -// -// -// {title} -// -// -// {value} -// -// -// -// ); - -// export default StatCard; diff --git a/src/zcleanup/renderFullWidthAddButton.jsx b/src/zcleanup/renderFullWidthAddButton.jsx deleted file mode 100644 index 2d231aa..0000000 --- a/src/zcleanup/renderFullWidthAddButton.jsx +++ /dev/null @@ -1,185 +0,0 @@ -// import React, { useCallback, useEffect, useMemo } from 'react'; -// import { Box } from '@mui/material'; -// import { useMode } from '../../../context'; -// import { getContextIcon } from '../../../components/reusable/icons/index'; -// import AddButton from './AddButton'; -// import RemoveButton from './RemoveButton'; -// import MDTypography from '../../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -// import { useCardActions } from '../../../context/hooks/useCardActions'; -// import { useDeckStore } from '../../../context/MAIN_CONTEXT/DeckContext/DeckContext'; -// import { useCartStore } from '../../../context/MAIN_CONTEXT/CartContext/CartContext'; -// import useSelectedCollection from '../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; -// import useCollectionManager from '../../../context/MAIN_CONTEXT/CollectionContext/useCollectionManager'; -// import { DEFAULT_COLLECTION } from '../../../context/constants'; - -// // Utility function for deriving label and variant -// export const renderFullWidthAddButton = ( -// buttonSize, -// labelValue, -// context, -// card, -// page, -// onClick, -// closeModal, -// onSuccess, -// onFailure, -// cardSize -// ) => { -// const currentContextIcon = getContextIcon(labelValue); -// const stackDirection = buttonSize === 'extraSmall' ? 'column' : 'row'; -// const { addOneToCollection, removeOneFromCollection } = -// useCollectionManager(); -// const { selectedCollection, allCollections, handleSelectCollection } = -// useSelectedCollection(); -// const { -// addOneToDeck, -// removeOneFromDeck, -// selectedDeck, -// allDecks, -// setSelectedDeck, -// } = useDeckStore(); -// const { addOneToCart, removeOneFromCart, cartData } = useCartStore(); -// useEffect(() => { -// if (context === 'Deck' && !selectedDeck && allDecks?.length > 0) { -// console.warn('No deck selected. Defaulting to first deck.'); -// setSelectedDeck(allDecks[0]); -// } -// if ( -// (context === 'Collection' && !selectedCollection) || -// selectedCollection === null || -// selectedCollection === DEFAULT_COLLECTION || -// !allCollections?.length > 0 -// ) { -// console.warn('No collection selected. Defaulting to first collection.'); -// // handleSelectCollection(allCollections[0]); -// } -// }, [ -// context, -// selectedCollection, -// allCollections, -// selectedDeck, -// allDecks, -// cartData, -// ]); -// const addActions = useMemo(() => { -// Collection: addOneToCollection; -// Deck: addOneToDeck; -// Cart: addOneToCart; -// return addActions; -// }, [addOneToCollection, addOneToDeck, addOneToCart]); -// const removeActions = useMemo(() => { -// Collection: removeOneFromCollection; -// Deck: removeOneFromDeck; -// Cart: removeOneFromCart; -// return removeActions; -// }, [removeOneFromCollection, removeOneFromDeck, removeOneFromCart]); - -// const handleCardActionsAtContext = useCallback( -// (context, card) => { -// switch (context) { -// case 'Collection': -// handleSelectCollection(card); -// break; -// case 'Deck': -// setSelectedDeck(card); -// break; -// case 'Cart': -// addOneToCart(card); -// break; -// default: -// break; -// } -// }, -// [addOneToCart, handleSelectCollection, setSelectedDeck] -// ); -// const { performAction, count } = useCardActions( -// context, -// card, -// selectedCollection, -// selectedDeck, -// addOneToCollection, -// removeOneFromCollection, -// addOneToDeck, -// removeOneFromDeck, -// addOneToCart, -// removeOneFromCart, -// onSuccess, -// onFailure, -// page -// ); -// const handleCardAction = useCallback( -// async (actionType) => { -// console.log('SET LOADING FOR ', actionType); -// console.log('SET LOADING RESPONSE FOR CARD ', card); -// // onClick?.(); -// performAction(actionType); -// closeModal?.(); -// try { -// await new Promise((resolve) => setTimeout(resolve, 500)); - -// if (actionType === 'add') { -// console.log(`Adding ${card?.name} to ${labelValue}`); - -// onSuccess?.(); -// } else if (actionType === 'remove') { -// console.log(`Removing ${card?.name} from ${labelValue}`); -// performAction(actionType); - -// onSuccess?.(); -// } -// } catch (error) { -// console.error('Action failed:', error); -// onFailure?.(error); -// } finally { -// console.log('SET LOADING RESPONSE FOR CARD ', card); -// // closeModal(); -// } -// }, -// [card, labelValue, onSuccess, onFailure, closeModal] -// ); - -// return ( -// -// -// {currentContextIcon || ''} -// -// -// -// -// -// -// ); -// }; diff --git a/src/zcleanup/styleOverride/compStyleOverride.jsx b/src/zcleanup/styleOverride/compStyleOverride.jsx deleted file mode 100644 index d19a2a6..0000000 --- a/src/zcleanup/styleOverride/compStyleOverride.jsx +++ /dev/null @@ -1,187 +0,0 @@ -// export default function componentStyleOverrides(theme) { -// const bgColor = theme.colors?.grey50; -// return { -// MuiButton: { -// styleOverrides: { -// root: { -// fontWeight: 500, -// borderRadius: '4px', -// }, -// }, -// }, -// MuiPaper: { -// defaultProps: { -// elevation: 0, -// }, -// styleOverrides: { -// root: { -// backgroundImage: 'none', -// }, -// rounded: { -// borderRadius: `${theme?.customization?.borderRadius}px`, -// }, -// }, -// }, -// MuiCardHeader: { -// styleOverrides: { -// root: { -// color: theme.colors?.textDark, -// padding: '24px', -// }, -// title: { -// fontSize: '1.125rem', -// }, -// }, -// }, -// MuiCardContent: { -// styleOverrides: { -// root: { -// padding: '24px', -// }, -// }, -// }, -// MuiCardActions: { -// styleOverrides: { -// root: { -// padding: '24px', -// }, -// }, -// }, -// MuiListItemButton: { -// styleOverrides: { -// root: { -// color: theme.darkTextPrimary, -// paddingTop: '10px', -// paddingBottom: '10px', -// '&.Mui-selected': { -// color: theme.menuSelected, -// backgroundColor: theme.menuSelectedBack, -// '&:hover': { -// backgroundColor: theme.menuSelectedBack, -// }, -// '& .MuiListItemIcon-root': { -// color: theme.menuSelected, -// }, -// }, -// '&:hover': { -// backgroundColor: theme.menuSelectedBack, -// color: theme.menuSelected, -// '& .MuiListItemIcon-root': { -// color: theme.menuSelected, -// }, -// }, -// }, -// }, -// }, -// MuiListItemIcon: { -// styleOverrides: { -// root: { -// color: theme.darkTextPrimary, -// minWidth: '36px', -// }, -// }, -// }, -// MuiListItemText: { -// styleOverrides: { -// primary: { -// color: theme.textDark, -// }, -// }, -// }, -// MuiInputBase: { -// styleOverrides: { -// input: { -// color: theme.textDark, -// '&::placeholder': { -// color: theme.darkTextSecondary, -// fontSize: '0.875rem', -// }, -// }, -// }, -// }, -// MuiOutlinedInput: { -// styleOverrides: { -// root: { -// background: bgColor, -// borderRadius: `${theme?.customization?.borderRadius}px`, -// '& .MuiOutlinedInput-notchedOutline': { -// borderColor: theme.colors?.grey400, -// }, -// '&:hover $notchedOutline': { -// borderColor: theme.colors?.primaryLight, -// }, -// '&.MuiInputBase-multiline': { -// padding: 1, -// }, -// }, -// input: { -// fontWeight: 500, -// background: bgColor, -// padding: '15.5px 14px', -// borderRadius: `${theme?.customization?.borderRadius}px`, -// '&.MuiInputBase-inputSizeSmall': { -// padding: '10px 14px', -// '&.MuiInputBase-inputAdornedStart': { -// paddingLeft: 0, -// }, -// }, -// }, -// inputAdornedStart: { -// paddingLeft: 4, -// }, -// notchedOutline: { -// borderRadius: `${theme?.customization?.borderRadius}px`, -// }, -// }, -// }, -// MuiSlider: { -// styleOverrides: { -// root: { -// '&.Mui-disabled': { -// color: theme.colors?.grey300, -// }, -// }, -// mark: { -// backgroundColor: theme.paper, -// width: '4px', -// }, -// valueLabel: { -// color: theme?.colors?.primaryLight, -// }, -// }, -// }, -// MuiDivider: { -// styleOverrides: { -// root: { -// borderColor: theme.divider, -// opacity: 1, -// }, -// }, -// }, -// MuiAvatar: { -// styleOverrides: { -// root: { -// color: theme.colors?.primaryDark, -// background: theme.colors?.primary200, -// }, -// }, -// }, -// MuiChip: { -// styleOverrides: { -// root: { -// '&.MuiChip-deletable .MuiChip-deleteIcon': { -// color: 'inherit', -// }, -// }, -// }, -// }, -// MuiTooltip: { -// styleOverrides: { -// tooltip: { -// color: theme.paper, -// background: theme.colors?.grey700, -// }, -// }, -// }, -// }; -// } From 0bca1d97fc2f917429b089635bc8343ca02bb626 Mon Sep 17 00:00:00 2001 From: Reed Vogt Date: Sun, 17 Mar 2024 14:12:10 -0700 Subject: [PATCH 05/10] customizations and tweaks done to swiper in home and data display in select collection --- package.json | 1 + src/assets/themes/themeSettings.jsx | 34 +- .../buttons/other/ReusableLoadingButton.jsx | 2 +- src/components/cards/GenericCard.jsx | 3 +- .../cards/media/CardMediaSection.js | 3 +- src/components/dialogs/CollectionDialog.jsx | 178 +++++++--- src/components/forms/CollectionForm.jsx | 70 ++++ .../AppContext/AppContextProvider.jsx | 20 +- src/layout/REUSABLE_COMPONENTS/BoxHeader.jsx | 2 +- .../REUSABLE_COMPONENTS/ProgressCircle.jsx | 75 +++- .../REUSABLE_COMPONENTS/RC/RCChange.jsx | 75 ++++ src/layout/REUSABLE_COMPONENTS/StatBox.jsx | 6 +- .../cards-chart/ChartConfigs.jsx | 48 ++- .../collections-list/CollectionListItem.jsx | 332 ++++++++++++++---- .../collections-list/SelectCollectionList.jsx | 119 +------ .../collections-list/StatBoard.jsx | 109 ++---- .../statItems/PricedCardList.jsx | 39 +- .../statItems/ValuDistributionCircle.jsx | 123 +++---- src/layout/collection/index.jsx | 170 +++++---- .../sub-components/TopCardsDisplayRow.jsx | 2 +- src/pages/sections/HeroSection.jsx | 8 +- 21 files changed, 887 insertions(+), 532 deletions(-) create mode 100644 src/components/forms/CollectionForm.jsx create mode 100644 src/layout/REUSABLE_COMPONENTS/RC/RCChange.jsx diff --git a/package.json b/package.json index 1f140a9..13a5d0d 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "@babel/plugin-proposal-optional-chaining": "^7.21.0", "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", + "@floating-ui/react": "^0.26.9", "@fortawesome/fontawesome-free": "^6.4.0", "@hookform/resolvers": "^3.3.4", "@mui/icons-material": "^5.14.5", diff --git a/src/assets/themes/themeSettings.jsx b/src/assets/themes/themeSettings.jsx index 730386f..678147c 100644 --- a/src/assets/themes/themeSettings.jsx +++ b/src/assets/themes/themeSettings.jsx @@ -9,6 +9,7 @@ import linearGradient from './functions/linearGradient'; import pxToRem from './functions/pxToRem'; import rgba from './functions/rgba'; import breakpoints from './base/breakpoints'; +import Transitions from './Transitions'; export const themeSettings = (mode) => { return { @@ -25,8 +26,10 @@ export const themeSettings = (mode) => { mode: mode, }, breakpoints: breakpoints.values, - borders, - boxShadows, + Transitions: Transitions, + borders: borders, + boxShadows: boxShadows, + typography: typography, spacing: (factor) => `${0.25 * factor}rem`, shape: { borderRadius: 4, @@ -36,20 +39,19 @@ export const themeSettings = (mode) => { appBar: 1200, drawer: 1100, }, - shadows: [ - 'none', - '0px 2px 1px -1px rgba(0,0,0,0.1),0px 1px 1px 0px rgba(0,0,0,0.06),0px 1px 3px 0px rgba(0,0,0,0.04)', // example for theme.shadows[1] - '0px 3px 1px -2px rgba(0,0,0,0.1),0px 2px 2px 0px rgba(0,0,0,0.06),0px 1px 5px 0px rgba(0,0,0,0.04)', // example for theme.shadows[2] - '0px 3px 3px -2px rgba(0,0,0,0.1),0px 3px 4px 0px rgba(0,0,0,0.06),0px 1px 8px 0px rgba(0,0,0,0.04)', // example for theme.shadows[3] - '0px 2px 4px -1px rgba(0,0,0,0.1),0px 4px 5px 0px rgba(0,0,0,0.06),0px 1px 10px 0px rgba(0,0,0,0.04)', // example for theme.shadows[4] - '0px 3px 5px -1px rgba(0,0,0,0.1),0px 5px 8px 0px rgba(0,0,0,0.06),0px 1px 14px 0px rgba(0,0,0,0.04)', // example for theme.shadows[5] - '0px 3px 5px -1px rgba(0,0,0,0.1),0px 6px 10px 0px rgba(0,0,0,0.06),0px 1px 18px 0px rgba(0,0,0,0.04)', // example for theme.shadows[6] - '0px 4px 5px -2px rgba(0,0,0,0.1),0px 7px 10px 1px rgba(0,0,0,0.06),0px 2px 16px 1px rgba(0,0,0,0.04)', // example for theme.shadows[7] - '0px 5px 5px -3px rgba(0,0,0,0.1),0px 8px 10px 1px rgba(0,0,0,0.06),0px 3px 14px 2px rgba(0,0,0,0.04)', // example for theme.shadows[8] - '0px 5px 6px -3px rgba(0,0,0,0.1),0px 9px 12px 1px rgba(0,0,0,0.06),0px 3px 16px 2px rgba(0,0,0,0.04)', // example for theme.shadows[9] - '0px 5px 15px rgba(0,0,0,0.1)', // example for theme.shadows[10] - ], - typography, + // shadows: [ + // 'none', + // '0px 2px 1px -1px rgba(0,0,0,0.1),0px 1px 1px 0px rgba(0,0,0,0.06),0px 1px 3px 0px rgba(0,0,0,0.04)', // example for theme.shadows[1] + // '0px 3px 1px -2px rgba(0,0,0,0.1),0px 2px 2px 0px rgba(0,0,0,0.06),0px 1px 5px 0px rgba(0,0,0,0.04)', // example for theme.shadows[2] + // '0px 3px 3px -2px rgba(0,0,0,0.1),0px 3px 4px 0px rgba(0,0,0,0.06),0px 1px 8px 0px rgba(0,0,0,0.04)', // example for theme.shadows[3] + // '0px 2px 4px -1px rgba(0,0,0,0.1),0px 4px 5px 0px rgba(0,0,0,0.06),0px 1px 10px 0px rgba(0,0,0,0.04)', // example for theme.shadows[4] + // '0px 3px 5px -1px rgba(0,0,0,0.1),0px 5px 8px 0px rgba(0,0,0,0.06),0px 1px 14px 0px rgba(0,0,0,0.04)', // example for theme.shadows[5] + // '0px 3px 5px -1px rgba(0,0,0,0.1),0px 6px 10px 0px rgba(0,0,0,0.06),0px 1px 18px 0px rgba(0,0,0,0.04)', // example for theme.shadows[6] + // '0px 4px 5px -2px rgba(0,0,0,0.1),0px 7px 10px 1px rgba(0,0,0,0.06),0px 2px 16px 1px rgba(0,0,0,0.04)', // example for theme.shadows[7] + // '0px 5px 5px -3px rgba(0,0,0,0.1),0px 8px 10px 1px rgba(0,0,0,0.06),0px 3px 14px 2px rgba(0,0,0,0.04)', // example for theme.shadows[8] + // '0px 5px 6px -3px rgba(0,0,0,0.1),0px 9px 12px 1px rgba(0,0,0,0.06),0px 3px 16px 2px rgba(0,0,0,0.04)', // example for theme.shadows[9] + // '0px 5px 15px rgba(0,0,0,0.1)', // example for theme.shadows[10] + // ], skeletonLayouts: { tertiaryContent: { xs: 12, diff --git a/src/components/buttons/other/ReusableLoadingButton.jsx b/src/components/buttons/other/ReusableLoadingButton.jsx index dc1b158..754f390 100644 --- a/src/components/buttons/other/ReusableLoadingButton.jsx +++ b/src/components/buttons/other/ReusableLoadingButton.jsx @@ -18,7 +18,7 @@ const ReusableLoadingButton = ({ const getButtonStyles = (variant) => { if (variant === 'warning') { return { - bgcolor: theme.palette.error.state, + background: theme.palette.error.state, borderColor: theme.palette.error.dark, borderWidth: 2, '&:hover': { diff --git a/src/components/cards/GenericCard.jsx b/src/components/cards/GenericCard.jsx index a20eea2..4e89ec0 100644 --- a/src/components/cards/GenericCard.jsx +++ b/src/components/cards/GenericCard.jsx @@ -86,7 +86,8 @@ const GenericCard = React.forwardRef((props, ref) => { }, [hoveredCard, card, setIsPopoverOpen]); const isInContext = isCardInContext(card); const name = card?.name; - const imgUrl = card?.card_images?.[0]?.image_url || placeholderImage; + const imgUrl = + card?.card_images?.[0]?.image_url || 'https://placehold.co/600x400.png'; const price = `Price: ${ card?.latestPrice?.num || card?.price || diff --git a/src/components/cards/media/CardMediaSection.js b/src/components/cards/media/CardMediaSection.js index e0a70c3..e918345 100644 --- a/src/components/cards/media/CardMediaSection.js +++ b/src/components/cards/media/CardMediaSection.js @@ -10,6 +10,7 @@ import { Overlay, } from '../../../context/hooks/style-hooks/usePortfolioStyles'; import { useOverlay } from '../../../context/hooks/useOverlay'; +import placeHolder from '../../../assets/images/placeholder.jpeg'; const CardMediaSection = forwardRef( ( { @@ -62,7 +63,7 @@ const CardMediaSection = forwardRef( diff --git a/src/components/dialogs/CollectionDialog.jsx b/src/components/dialogs/CollectionDialog.jsx index c8f5dfc..352c974 100644 --- a/src/components/dialogs/CollectionDialog.jsx +++ b/src/components/dialogs/CollectionDialog.jsx @@ -1,20 +1,126 @@ -import React, { useEffect } from 'react'; +// import React, { useEffect } from 'react'; +// import PropTypes from 'prop-types'; +// import { +// Avatar, +// Box, +// CssBaseline, +// Dialog, +// DialogContent, +// DialogTitle, +// Divider, +// Grid, +// Paper, +// } from '@mui/material'; +// import { useCollectionStore, useFormContext, useMode } from '../../context'; +// import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; +// import AddCollectionForm from '../forms/AddCollectionForm'; +// import UpdateCollectionForm from '../forms/UpdateCollectionForm'; +// import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; +// import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; +// import { +// DialogPaper, +// StyledDialog, +// StyledDialogContent, +// } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; +// import MDAvatar from '../../layout/REUSABLE_COMPONENTS/MDAVATAR'; +// const CollectionDialog = ({ +// open, +// onClose, +// isNew, +// collectionData, +// collectionMode, +// }) => { +// const { +// formMethods, +// onSubmit, +// setFormSchema, +// currentSchemaKey, +// currentForm, +// setCurrentForm, +// } = useFormContext(); +// const { theme } = useMode(); + +// useEffect(() => { +// if (collectionMode === 'edit') { +// setCurrentForm('updateCollectionForm'); +// } +// }, [collectionMode, setCurrentForm]); + +// return ( +// +// +// +// +// +// +// +// +// +// {currentForm === 'addCollectionForm' +// ? 'Add a Collection' +// : 'Update a Collection'} +// +// +// {' '} +// +// + +// +// {currentForm === 'addCollectionForm' ? ( +// +// ) : ( +// +// )} +// +// +// ); +// }; + +// CollectionDialog.propTypes = { +// open: PropTypes.bool.isRequired, +// onClose: PropTypes.func.isRequired, +// isNew: PropTypes.bool, +// collectionData: PropTypes.shape({ +// name: PropTypes.string, +// description: PropTypes.string, +// }), +// }; + +// export default CollectionDialog; +import React from 'react'; import PropTypes from 'prop-types'; -import { - Avatar, - Box, - CssBaseline, - Dialog, - DialogContent, - DialogTitle, - Divider, - Grid, - Paper, -} from '@mui/material'; -import { useCollectionStore, useFormContext, useMode } from '../../context'; +import { CssBaseline, DialogTitle, Divider } from '@mui/material'; +import { useMode } from '../../context'; +import CollectionForm from '../forms/CollectionForm'; // Adjusted import import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; -import AddCollectionForm from '../forms/AddCollectionForm'; -import UpdateCollectionForm from '../forms/UpdateCollectionForm'; import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; import { @@ -23,35 +129,18 @@ import { StyledDialogContent, } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; import MDAvatar from '../../layout/REUSABLE_COMPONENTS/MDAVATAR'; -const CollectionDialog = ({ - open, - onClose, - isNew, - collectionData, - collectionMode, -}) => { - const { - formMethods, - onSubmit, - setFormSchema, - currentSchemaKey, - currentForm, - setCurrentForm, - } = useFormContext(); + +const CollectionDialog = ({ open, onClose, isNew, collectionData }) => { const { theme } = useMode(); - useEffect(() => { - if (collectionMode === 'edit') { - setCurrentForm('updateCollectionForm'); - } - }, [collectionMode, setCurrentForm]); + const actionType = isNew ? 'add' : 'update'; return ( @@ -80,25 +169,22 @@ const CollectionDialog = ({ border: 'none', }} > - + - {currentForm === 'addCollectionForm' - ? 'Add a Collection' - : 'Update a Collection'} + {isNew ? 'Add a Collection' : 'Update a Collection'} - {' '} + - {currentForm === 'addCollectionForm' ? ( - - ) : ( - - )} + ); diff --git a/src/components/forms/CollectionForm.jsx b/src/components/forms/CollectionForm.jsx new file mode 100644 index 0000000..4448ae7 --- /dev/null +++ b/src/components/forms/CollectionForm.jsx @@ -0,0 +1,70 @@ +import React, { useEffect } from 'react'; +import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline'; +import { useFormContext, useMode } from '../../context'; +import useSnackbarManager from '../../context/hooks/useSnackbarManager'; +import RCZodForm from './reusable/RCZodForm'; + +// Common fields structure used in both add and update forms +const collectionFields = [ + { + name: 'name', + label: 'Name', + type: 'text', + required: true, + }, + { + name: 'description', + label: 'Description', + type: 'text', + required: true, + multiline: true, + rows: 4, + }, +]; + +const CollectionForm = ({ collectionData, actionType }) => { + const { setFormSchema, onSubmit } = useFormContext(); + const { theme } = useMode(); + const { showSuccess, showError } = useSnackbarManager(); + + // Determine the schema name and button label based on the action type + const schemaName = + actionType === 'add' ? 'addCollectionForm' : 'updateCollectionForm'; + const buttonLabel = + actionType === 'add' ? 'Create Collection' : 'Update Collection'; + const startIcon = actionType === 'add' ? : null; + + useEffect(() => { + if (collectionData && actionType === 'update') { + setFormSchema(schemaName, collectionData); + } + }, [collectionData, setFormSchema, schemaName, actionType]); + + const handleFormSubmit = async (data) => { + const method = actionType === 'add' ? 'Add' : 'Update'; + try { + await onSubmit(data, schemaName, collectionData?._id); + showSuccess( + `You've successfully ${method.toLowerCase()}ed the collection.` + ); + } catch (error) { + showError( + `Failed to ${method.toLowerCase()} collection. Please try again.` + ); + } + }; + + return ( + + ); +}; + +export default CollectionForm; diff --git a/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx b/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx index 54dc190..a8d0b57 100644 --- a/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx +++ b/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx @@ -36,17 +36,17 @@ export const AppContextProvider = ({ children }) => { const { selectedDeck, allDecks } = Deck; const { cartData } = Cart; const compileCollectionMetaData = useCallback(() => { + if (!allCollections || allCollections.length === 0) return; + const metaData = { - metaData: { - totalPrice: allCollections?.reduce( - (total, collection) => total + collection.totalPrice, - 0 - ), - numCollections: allIds?.length || 0, - topFiveCards: cardsWithQuantities - ?.sort((a, b) => b.price - a.price) - .slice(0, 5), - }, + totalValue: allCollections?.reduce( + (total, collection) => total + collection?.totalPrice, + 0 + ), + numCollections: allIds?.length || 0, + topFiveCards: cardsWithQuantities + ?.sort((a, b) => b.price - a.price) + .slice(0, 5), }; setCollectionMetaData(metaData); diff --git a/src/layout/REUSABLE_COMPONENTS/BoxHeader.jsx b/src/layout/REUSABLE_COMPONENTS/BoxHeader.jsx index 2406946..a58193b 100644 --- a/src/layout/REUSABLE_COMPONENTS/BoxHeader.jsx +++ b/src/layout/REUSABLE_COMPONENTS/BoxHeader.jsx @@ -33,7 +33,7 @@ const BoxHeader = ({ > {title} - {subtitle} + {subtitle && {subtitle}} { +// ProgressCircle now expects an array of collections instead of a single progress value. +const ProgressCircle = ({ collections, size = 120 }) => { const { theme } = useMode(); - const colors = theme.palette.chartTheme; - const primary = colors.primary.default; - const blue = colors.blueAccent.default; - const green = colors.greenAccent.default; - const angle = progress * 360; + // Calculate the total value of all collections. + const totalValue = collections?.reduce( + (sum, { totalPrice }) => sum + totalPrice, + 0 + ); + + // Generate a conic-gradient background based on the collections' value distribution. + let cumulativePercentage = 0; + const background = collections + ?.reduce((gradient, collection) => { + const collectionPercentage = (collection.totalPrice / totalValue) * 100; + const nextCumulativePercentage = + cumulativePercentage + collectionPercentage; + const color = theme.palette.chartTheme.blueAccent.default; // Color for each segment + gradient += `${color} ${cumulativePercentage}% ${nextCumulativePercentage}%,`; + cumulativePercentage = nextCumulativePercentage; + return gradient; + }, '') + .slice(0, -1); // Remove the trailing comma + + // Prepare tooltip content displaying the name and value of each collection. + const tooltipContent = collections + ?.map( + (collection) => + `${collection.name}: $${collection.totalPrice?.toFixed(2)} (${((collection.totalPrice / totalValue) * 100)?.toFixed(2)}%)` + ) + .join('\n'); + return ( - + + + ); }; +ProgressCircle.propTypes = { + collections: PropTypes.arrayOf( + PropTypes.shape({ + name: PropTypes.string.isRequired, + totalPrice: PropTypes.number.isRequired, + }) + ).isRequired, + size: PropTypes.number, +}; + export default ProgressCircle; diff --git a/src/layout/REUSABLE_COMPONENTS/RC/RCChange.jsx b/src/layout/REUSABLE_COMPONENTS/RC/RCChange.jsx new file mode 100644 index 0000000..f529a6f --- /dev/null +++ b/src/layout/REUSABLE_COMPONENTS/RC/RCChange.jsx @@ -0,0 +1,75 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Box, Typography } from '@mui/material'; +import ProgressCircle from './../ProgressCircle'; +import ArrowDropUpIcon from '@mui/icons-material/ArrowDropUp'; +import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; +import MDTypography from '../MDTYPOGRAPHY/MDTypography'; +import MDBox from '../MDBOX'; +import { useMode } from '../../../context'; + +const useStyles = (theme) => ({ + container: { + width: '100%', + p: '20px', + borderRadius: theme.spacing(4), + }, + flexBox: { + display: 'flex', + justifyContent: 'space-between', + }, + percentageText: { + variant: 'h6', + fontWeight: 'medium', + color: theme.palette.chartTheme.grey.default, + }, + rangeText: { + variant: 'h5', + color: theme.palette.chartTheme.greenAccent.default, + mt: '2px', + }, +}); + +const RCChange = ({ progress, increase, change, rangeLevel }) => { + const { theme } = useMode(); + const styles = useStyles(theme); + + return ( + + + + Change + + {increase ? : } + {`${change}%`} + + + {/* + + */} + + + {`In ${rangeLevel}`} + + + ); +}; + +RCChange.propTypes = { + progress: PropTypes.number.isRequired, + increase: PropTypes.bool.isRequired, + change: PropTypes.number.isRequired, + rangeLevel: PropTypes.string.isRequired, +}; + +export default RCChange; diff --git a/src/layout/REUSABLE_COMPONENTS/StatBox.jsx b/src/layout/REUSABLE_COMPONENTS/StatBox.jsx index d025c73..bd1bbd7 100644 --- a/src/layout/REUSABLE_COMPONENTS/StatBox.jsx +++ b/src/layout/REUSABLE_COMPONENTS/StatBox.jsx @@ -18,12 +18,14 @@ const StatBox = ({ title, subtitle, icon, progress, increase }) => { width: '100%', p: '20px', borderRadius: theme.spacing(4), + maxHeight: '135px', }} > @@ -33,9 +35,9 @@ const StatBox = ({ title, subtitle, icon, progress, increase }) => { {title} - + {/* - + */} diff --git a/src/layout/collection/collectionGrids/cards-chart/ChartConfigs.jsx b/src/layout/collection/collectionGrids/cards-chart/ChartConfigs.jsx index 5d76de6..5f07ba5 100644 --- a/src/layout/collection/collectionGrids/cards-chart/ChartConfigs.jsx +++ b/src/layout/collection/collectionGrids/cards-chart/ChartConfigs.jsx @@ -9,6 +9,8 @@ import { useEffect, useMemo } from 'react'; import NivoContainer from './NivoContainer'; import PropTypes from 'prop-types'; import ChartErrorBoundary from './ChartErrorBoundary'; +import RCToolTip from '../../../REUSABLE_COMPONENTS/RCTOOLTIP/RCToolTip'; +import { BasicTooltip } from '@nivo/tooltip'; export const ChartConfiguration = ({ markers, @@ -24,6 +26,19 @@ export const ChartConfiguration = ({ () => markers.filter((marker) => marker.value !== undefined), [markers] ); + const TooltipLayer = ({ points }) => ( + <> + {points.map((point) => ( + + ))} + + ); const { tickValues, xFormat } = useMemo(() => { let format, ticks; switch (range) { @@ -112,9 +127,8 @@ export const ChartConfiguration = ({ stacked: true, reverse: false, }, - curve: 'monotoneX', - useMesh: true, - motionConfig: 'gentle', + curve: 'catmullRom', // This curve type can create smoother, more wavy lines + motionConfig: 'wobbly', // A more dynamic motion configuration useMesh: true, stiffness: 90, damping: 15, enableSlices: 'x', @@ -128,15 +142,27 @@ export const ChartConfiguration = ({ 'points', 'axes', 'legends', - ({ points, xScale, yScale, markers: validMarkers }) => ( - - ), + TooltipLayer, ], + + // layers: [ + // 'grid', + // 'markers', + // 'areas', + // 'lines', + // 'slices', + // 'points', + // 'axes', + // 'legends', + // ({ points, xScale, yScale, markers: validMarkers }) => ( + // + // ), + // ], theme: { axis: { domain: { diff --git a/src/layout/collection/collectionGrids/collections-list/CollectionListItem.jsx b/src/layout/collection/collectionGrids/collections-list/CollectionListItem.jsx index 8d21fb6..25de751 100644 --- a/src/layout/collection/collectionGrids/collections-list/CollectionListItem.jsx +++ b/src/layout/collection/collectionGrids/collections-list/CollectionListItem.jsx @@ -1,4 +1,214 @@ -import React, { memo, useCallback, useRef } from 'react'; +// import React, { memo, useCallback, useRef } from 'react'; +// import { +// Box, +// Card, +// CardActionArea, +// CardContent, +// Grid, +// Tooltip, +// } from '@mui/material'; +// import PropTypes from 'prop-types'; +// import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward'; +// import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; +// import useCollectionManager from '../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionManager'; +// import MDBox from '../../../../layout/REUSABLE_COMPONENTS/MDBOX'; +// import MDTypography from '../../../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; +// import LongMenu from '../../../../layout/navigation/LongMenu'; +// import useDialogState from '../../../../context/hooks/useDialogState'; +// import CollectionDialog from '../../../../components/dialogs/CollectionDialog'; +// import useSelectedCollection from '../../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; +// import { useMode, useVisibilityContext } from '../../../../context'; + +// const CollectionInfoItem = ({ label, value, theme }) => ( +// +// +// +// {label}: +// +// +// {value} +// +// +// +// ); + +// const CollectionListItem = memo(({ collection }) => { +// const { theme } = useMode(); +// const { deleteCollection } = useCollectionManager(); +// const { handleSelectCollection } = useSelectedCollection(); +// const { toggleCollectionVisibility } = useVisibilityContext(); +// const { dialogState, openDialog, closeDialog } = useDialogState({ +// isEditCollectionDialogOpen: false, +// }); + +// const handleOpenDialog = useCallback(() => { +// openDialog('editCollectionDialog', collection); +// }, [collection, openDialog]); + +// const handleCloseDialog = useCallback(() => { +// closeDialog('editCollectionDialog'); +// }, [closeDialog]); + +// const handleDelete = async () => { +// await deleteCollection(collection._id); +// }; + +// const renderToolTip = () => ( +// +//
+// handleSelectCollection(collection)} +// collectionId={collection._id} +// /> +//
+//
+// ); + +// const renderPercentageChange = () => { +// const percentageChange = +// collection.collectionStatistics?.percentageChange || 0; +// return ( +// 0 ? 'success' : 'error'} +// sx={{ +// display: 'flex', +// alignItems: 'center', +// justifyContent: 'center', +// fontSize: '1.5rem', // Triple the label size +// }} +// > +// {percentageChange > 0 ? : } +// {percentageChange}% +// +// ); +// }; + +// const handleSelection = useCallback(() => { +// handleSelectCollection(collection); +// toggleCollectionVisibility(); +// }, [collection, handleSelectCollection, toggleCollectionVisibility]); + +// return ( +// +// +// +// +// +// +// +// +// {renderPercentageChange()} +// +// +// +// +// {renderToolTip()} +// +// +// {dialogState.isEditCollectionDialogOpen && ( +// +// )} +// +// ); +// }); + +// CollectionListItem.displayName = 'CollectionListItem'; + +// CollectionListItem.propTypes = { +// collection: PropTypes.object.isRequired, +// }; + +// export default CollectionListItem; +import React, { memo, useCallback } from 'react'; import { Box, Card, @@ -8,16 +218,15 @@ import { Tooltip, } from '@mui/material'; import PropTypes from 'prop-types'; -import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward'; -import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; -import useCollectionManager from '../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionManager'; import MDBox from '../../../../layout/REUSABLE_COMPONENTS/MDBOX'; -import MDTypography from '../../../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -import LongMenu from '../../../../layout/navigation/LongMenu'; -import useDialogState from '../../../../context/hooks/useDialogState'; -import CollectionDialog from '../../../../components/dialogs/CollectionDialog'; +import useCollectionManager from '../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionManager'; import useSelectedCollection from '../../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; +import useDialogState from '../../../../context/hooks/useDialogState'; import { useMode, useVisibilityContext } from '../../../../context'; +import CollectionDialog from '../../../../components/dialogs/CollectionDialog'; +import LongMenu from '../../../../layout/navigation/LongMenu'; +import MDTypography from '../../../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; +import RCChange from '../../../REUSABLE_COMPONENTS/RC/RCChange'; const CollectionInfoItem = ({ label, value, theme }) => ( @@ -30,25 +239,15 @@ const CollectionInfoItem = ({ label, value, theme }) => ( }} > - {label}: + {`${label}:`} {value} @@ -56,6 +255,12 @@ const CollectionInfoItem = ({ label, value, theme }) => ( ); +CollectionInfoItem.propTypes = { + label: PropTypes.string.isRequired, + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + theme: PropTypes.object.isRequired, +}; + const CollectionListItem = memo(({ collection }) => { const { theme } = useMode(); const { deleteCollection } = useCollectionManager(); @@ -90,25 +295,8 @@ const CollectionListItem = memo(({ collection }) => { ); - const renderPercentageChange = () => { - const percentageChange = - collection.collectionStatistics?.percentageChange || 0; - return ( - 0 ? 'success' : 'error'} - sx={{ - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - fontSize: '1.5rem', // Triple the label size - }} - > - {percentageChange > 0 ? : } - {percentageChange}% - - ); - }; + const percentageChange = + collection.collectionStatistics?.percentageChange || 0; const handleSelection = useCallback(() => { handleSelectCollection(collection); @@ -118,36 +306,19 @@ const CollectionListItem = memo(({ collection }) => { return ( @@ -168,25 +339,32 @@ const CollectionListItem = memo(({ collection }) => { theme={theme} /> - {renderPercentageChange()} + 0} + change={percentageChange} + rangeLevel="24hr" // Default value; replace with actual data if available + /> - - {renderToolTip()} - + + + {renderToolTip()} + + {dialogState.isEditCollectionDialogOpen && ( theme.spacing(1, 2)}; -// `; -// const CollectionListItemSkeleton = ({ count, index }) => ( -// -// -// -// -// -// -// -// -// -// -// -// -// -// ); - -// CollectionListItemSkeleton.propTypes = { -// count: PropTypes.number.isRequired, -// index: PropTypes.number.isRequired, -// }; - -// const SelectCollectionList = ({ openDialog }) => { -// const { allCollections } = useSelectedCollection(); -// // const [skeletonCount, setSkeletonCount] = useState(0); -// const listRef = useRef(); -// const minItems = 5; -// const numCollections = allCollections?.length || 0; -// const numRequired = minItems - numCollections; -// const allSkeletonCollections = [...Array(numRequired).keys()].map((index) => ( -// -// )); -// const combinedCollections = [...allCollections, ...allSkeletonCollections]; -// return ( -// -// -// -// {combinedCollections?.map((collection, index) => ( -// -// -// -// ))} -// {/* */} -// -// -// -// ); -// }; - -// SelectCollectionList.propTypes = { -// openDialog: PropTypes.func.isRequired, -// }; - -// export default memo(SelectCollectionList); import React, { memo, useEffect, useState } from 'react'; import { Box, @@ -173,20 +77,15 @@ const SelectCollectionList = ({ openDialog }) => { > - {collectionList?.map((collection, index) => ( - - - - ))} + {collectionList.map((item, index) => + item.type === CollectionListItemSkeleton ? ( + item + ) : ( + + + + ) + )} diff --git a/src/layout/collection/collectionGrids/collections-list/StatBoard.jsx b/src/layout/collection/collectionGrids/collections-list/StatBoard.jsx index 03b3e54..b9709db 100644 --- a/src/layout/collection/collectionGrids/collections-list/StatBoard.jsx +++ b/src/layout/collection/collectionGrids/collections-list/StatBoard.jsx @@ -1,5 +1,5 @@ /* eslint-disable react/jsx-key */ -import { Box, Grid, Typography } from '@mui/material'; +import { Box, Grid, Typography, Skeleton } from '@mui/material'; // import PieChart from './statItems/PieChart'; import TotalPriceStatBox from './statItems/TotalPriceStatBox'; // import ValuDistributionCircle from './statItems/ValuDistributionCircle'; @@ -12,77 +12,34 @@ import PricedCardList from './statItems/PricedCardList'; import PerformanceStatBox from './statItems/PerformanceStatBox'; import MDBox from '../../../REUSABLE_COMPONENTS/MDBOX'; import styled from 'styled-components'; -// const StatBoard = () => { -// const { theme } = useMode(); -// return ( -// -// -// -// {' '} -// -// -// -// -// -// -// -// -// -// -// -// ); -// }; +const SkeletonPieChart = ({ theme }) => ( + + + Collection Value Distribution + + + +); -// export default StatBoard; const StatBoxes = () => { const { theme } = useMode(); return ( @@ -95,10 +52,17 @@ const StatBoxes = () => { const DistCircle = () => { const { theme } = useMode(); const colors = theme.palette.chartTheme; - + const { allCollections } = useAppContext(); + if (!allCollections || allCollections.length === 0) { + return ( + + {' '} + + ); + } return ( - + ); }; @@ -128,6 +92,7 @@ const StatBoard = () => { alignItems: 'flex-start', maxHeight: '270px', minHeight: '270px', + my: 2, }} > {[, , ].map( diff --git a/src/layout/collection/collectionGrids/collections-list/statItems/PricedCardList.jsx b/src/layout/collection/collectionGrids/collections-list/statItems/PricedCardList.jsx index 370aae4..149388f 100644 --- a/src/layout/collection/collectionGrids/collections-list/statItems/PricedCardList.jsx +++ b/src/layout/collection/collectionGrids/collections-list/statItems/PricedCardList.jsx @@ -1,6 +1,6 @@ import MDBox from '../../../../REUSABLE_COMPONENTS/MDBOX'; import BoxHeader from '../../../../REUSABLE_COMPONENTS/BoxHeader'; -import { Box } from '@mui/material'; +import { Box, Card, CardContent } from '@mui/material'; import { useAppContext, useMode } from '../../../../../context'; import { DataGrid } from '@mui/x-data-grid'; import prepareTableData from '../../../data/topCards'; @@ -27,24 +27,35 @@ const PricedCardList = () => { - {/* */} - - {/* */} + + + acc + card.price, 0)}`} + colorVariant={greenAccent} + useSX={true} + titleVariant="h5" + paddingVariant={theme.spacing(2)} + sx={{ + color: greenAccent, + }} + /> + + { -// const { theme } = useMode(); -// const colors = theme.palette.chartTheme; -// const primary = colors.primary.dark; -// const greenAccent = colors.greenAccent.default; - -// return ( -// -// -// -// Campaign -// -// -// -// -// $48,352 revenue generated -// -// Includes extra misc expenditures and costs -// -// -// -// ); -// }; - -// export default ValuDistributionCircle; +/* eslint-disable max-len */ +import React from 'react'; import { Box, Typography } from '@mui/material'; -import ProgressCircle from '../../../../REUSABLE_COMPONENTS/ProgressCircle'; import MDBox from '../../../../REUSABLE_COMPONENTS/MDBOX'; import { useMode } from '../../../../../context'; +import ProgressCircle from '../../../../REUSABLE_COMPONENTS/ProgressCircle'; -const ValuDistributionCircle = () => { +const ValuDistributionCircle = ({ collections }) => { const { theme } = useMode(); - const colors = theme.palette.chartTheme; - const primary = colors.primary.dark; - const greenAccent = colors.greenAccent.light; + const collectionMetaData = collections.reduce( + (meta, collection) => { + meta.totalValue += collection.totalPrice; + meta.tooltips.push( + `${collection.name}: $${collection.totalPrice.toFixed(2)}` + ); + return meta; + }, + { totalValue: 0, tooltips: [] } + ); + + let cumulativePercent = 0; + const gradientStops = collections + .map((collection) => { + const valuePercent = + (collection.totalPrice / collectionMetaData.totalValue) * 100; + const stop = `${theme.palette.chartTheme.blueAccent.default} ${cumulativePercent}%, ${theme.palette.chartTheme.blueAccent.default} ${cumulativePercent + valuePercent}%`; + cumulativePercent += valuePercent; + return stop; + }) + .join(', '); + + const tooltipContent = collectionMetaData.tooltips.join('\n'); + return ( - {/* */} - - Campaign + + Collection Value Distribution - + - - - $48,352 revenue generated - - Includes extra misc expenditures and costs - - {/* */} + Total Value: ${collectionMetaData.totalValue.toFixed(2)} +
+ + Includes extra misc expenditures and costs +
); diff --git a/src/layout/collection/index.jsx b/src/layout/collection/index.jsx index 2c05168..c5d16fb 100644 --- a/src/layout/collection/index.jsx +++ b/src/layout/collection/index.jsx @@ -28,6 +28,7 @@ import StatBoard from './collectionGrids/collections-list/StatBoard'; const CollectionPortfolio = () => { const { theme } = useMode(); + const { Transitions } = theme; const { fetchCollections, hasFetchedCollections } = useCollectionManager(); const { handleBackToCollections, @@ -99,85 +100,100 @@ const CollectionPortfolio = () => { }} > - {!isCollectionVisible ? ( - - - - - - - - - - - - - {dialogState.isAddCollectionDialogOpen && ( - + {!isCollectionVisible && ( + + + - )} - {dialogState.isSelectionErrorDialogOpen && ( - - )} - - - ) : ( - // Selected collection view - - - - - - - {/* */} - - - + > + + + + + + + + + + {dialogState.isAddCollectionDialogOpen && ( + + )} + {dialogState.isSelectionErrorDialogOpen && ( + + )} + + + )} + + + {isCollectionVisible && ( + + + + + + + {/* */} + + + + - - - )} + + )} + ); diff --git a/src/layout/collection/sub-components/TopCardsDisplayRow.jsx b/src/layout/collection/sub-components/TopCardsDisplayRow.jsx index d3db6af..ac85645 100644 --- a/src/layout/collection/sub-components/TopCardsDisplayRow.jsx +++ b/src/layout/collection/sub-components/TopCardsDisplayRow.jsx @@ -107,7 +107,7 @@ export const TopCardsDisplayRow = () => { { style={{ display: 'flex', position: 'relative', - minHeight: isMobileView ? '50vh' : '70vh', + minHeight: isMobileView ? '50vh' : 'calc(100vh - 64px)', flexDirection: isMobileView ? 'column' : 'row', }} > @@ -101,7 +101,7 @@ const HeroSection = () => { className="hero-section-container" sx={{ width: '100%', - minHeight: isMobileView ? '30vh' : '50vh', + minHeight: isMobileView ? '30vh' : '80vh', backgroundColor: 'transparent', // Make the Card background transparent }} > @@ -154,6 +154,8 @@ const HeroSection = () => { { width: '100%', height: '100%', transform: - index === activeCardIndex ? 'scale(1.7)' : 'scale(1)', + index === activeCardIndex ? 'scale(2.2)' : 'scale(1)', transition: 'transform 0.9s', position: 'relative', // Ensure the slide content is positioned relatively }} From 6fdd2e407480f6b4f0ce4a8a5ef255e59e9f8d18 Mon Sep 17 00:00:00 2001 From: Reed Vogt Date: Tue, 19 Mar 2024 13:36:28 -0700 Subject: [PATCH 06/10] committing near-perfect hero section before modifying mobile styles --- src/components/cards/CardDetail.jsx | 15 +- src/components/cards/CardDetails.jsx | 39 - src/components/cards/CardDetailsContainer.jsx | 10 +- src/components/cards/GenericCard.jsx | 66 +- .../cards/media/CardMediaSection.js | 4 +- src/components/dialogs/CollectionDialog.jsx | 117 -- src/components/dialogs/GenericCardDialog.jsx | 10 +- src/components/forms/SignupForm.jsx | 115 -- src/components/forms/formsConfig.jsx | 25 +- .../AppContext/AppContextProvider.jsx | 1 + .../hooks/style-hooks/usePortfolioStyles.jsx | 1413 +++++++++-------- src/{assets => }/data/card_info.json | 0 src/{assets => }/data/card_sample.json | 0 src/data/iconData.jsx | 220 +++ src/{assets => }/data/pages.json | 0 .../RCLOGOSECTION/RCLogoSection.jsx | 121 -- .../REUSABLE_COMPONENTS/SkeletonVariants.jsx | 53 +- src/layout/REUSABLE_COMPONENTS/StatBox.jsx | 50 +- .../REUSABLE_COMPONENTS/unique/SimpleCard.jsx | 167 +- .../collectionGrids/ChartGridLayout.jsx | 1 - .../cards-chart/ChartConfigs.jsx | 21 +- .../cards-datatable/DataTableHeadCell.jsx | 98 -- .../collections-list/CollectionListItem.jsx | 210 --- .../collections-list/StatBoard.jsx | 3 +- .../statItems/PerformanceStatBox.jsx | 52 +- .../statItems/TotalCardsCollectedStatBox.jsx | 42 + .../statItems/TotalPriceStatBox.jsx | 19 +- src/layout/navigation/Navigation.jsx | 191 ++- src/layout/navigation/menuItemsData.jsx | 8 +- src/layout/profile/ProfileSection.js | 5 - .../sub-components/DefaultInfoCard.jsx | 20 - src/pages/pageStyles/StyledComponents.jsx | 7 +- src/pages/sections/FeatureCardsSection.jsx | 5 +- src/pages/sections/HeroSection.jsx | 136 +- 34 files changed, 1557 insertions(+), 1687 deletions(-) delete mode 100644 src/components/cards/CardDetails.jsx rename src/{assets => }/data/card_info.json (100%) rename src/{assets => }/data/card_sample.json (100%) create mode 100644 src/data/iconData.jsx rename src/{assets => }/data/pages.json (100%) create mode 100644 src/layout/collection/collectionGrids/collections-list/statItems/TotalCardsCollectedStatBox.jsx diff --git a/src/components/cards/CardDetail.jsx b/src/components/cards/CardDetail.jsx index b49548e..7a2d605 100644 --- a/src/components/cards/CardDetail.jsx +++ b/src/components/cards/CardDetail.jsx @@ -27,14 +27,25 @@ const CardDetail = ({ {icon && {icon}} {title}: - {value && {value}} + {value && ( + + {value} + + )} {Array.isArray(values) && values.length > 0 && values.map((rarityValue, index) => ( diff --git a/src/components/cards/CardDetails.jsx b/src/components/cards/CardDetails.jsx deleted file mode 100644 index 0da52dc..0000000 --- a/src/components/cards/CardDetails.jsx +++ /dev/null @@ -1,39 +0,0 @@ -// import React from 'react'; -// import { Box, Typography } from '@mui/material'; -// import useResponsiveStyles from '../../context/hooks/style-hooks/useResponsiveStyles'; -// import { useTheme } from 'styled-components'; -// import { -// CardDetailContainer, -// CardDetailRow, -// CardIconWrapper, -// CardTitleStyle, -// CardValueStyle, -// useCardDetailStyles, -// } from './styles/cardStyles'; -// import { useMode } from '../../context'; -// import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; - -// const CardDetails = ({ details, className }) => { -// // details expected to be an array of objects with { icon, title, value } -// const { theme } = useMode(); -// // const theme2 = useTheme(); -// // const styles = useCardDetailStyles(theme, theme2); -// // const { getHeaderStyle, getButtonTypographyVariant } = -// // useResponsiveStyles(theme); - -// return ( -// -// {details.map(({ icon, title, value }, index) => ( -// -// {icon && {icon}} -// -// {title}: -// {value || ''} -// -// -// ))} -// -// ); -// }; - -// export default CardDetails; diff --git a/src/components/cards/CardDetailsContainer.jsx b/src/components/cards/CardDetailsContainer.jsx index bc1709b..5c5f499 100644 --- a/src/components/cards/CardDetailsContainer.jsx +++ b/src/components/cards/CardDetailsContainer.jsx @@ -31,7 +31,15 @@ const CardDetailsContainer = ({ card, className }) => { const { theme } = useMode(); return ( - + {[ { icon: FaLevelUpAlt, title: 'Level', value: card?.level }, { icon: FaVenusMars, title: 'Type', value: card?.type }, diff --git a/src/components/cards/GenericCard.jsx b/src/components/cards/GenericCard.jsx index 4e89ec0..6e7aad8 100644 --- a/src/components/cards/GenericCard.jsx +++ b/src/components/cards/GenericCard.jsx @@ -8,7 +8,7 @@ import React, { import { CardActions, Typography } from '@mui/material'; import CardMediaSection from './media/CardMediaSection'; import GenericActionButtons from '../buttons/actionButtons/GenericActionButtons'; -import placeholderImage from '../../assets/images/placeholder.jpeg'; +import placeholder from '../../assets/images/placeholder.jpeg'; import { useModalContext } from '../../context/UTILITIES_CONTEXT/ModalContext/ModalContext'; import { PopoverContext } from '../../context/UTILITIES_CONTEXT/PopoverContext/PopoverContext'; import { Box } from '@mui/system'; @@ -30,7 +30,7 @@ import { enqueueSnackbar } from 'notistack'; import useSelectedContext from '../../context/hooks/useSelectedContext'; import useSelectedCollection from '../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; const GenericCard = React.forwardRef((props, ref) => { - const { card, context, page, isSwiperStyles } = props; + const { card, context, page } = props; const { theme } = useMode(); const cardRef = useRef(null); const [cardSize, setCardSize] = useState('md'); // Default to 'sm' @@ -86,8 +86,7 @@ const GenericCard = React.forwardRef((props, ref) => { }, [hoveredCard, card, setIsPopoverOpen]); const isInContext = isCardInContext(card); const name = card?.name; - const imgUrl = - card?.card_images?.[0]?.image_url || 'https://placehold.co/600x400.png'; + const imgUrl = card?.card_images?.[0]?.image_url || placeholder; const price = `Price: ${ card?.latestPrice?.num || card?.price || @@ -103,37 +102,36 @@ const GenericCard = React.forwardRef((props, ref) => { allDecks: allDecks, }); let cardContent = null; - if (!isSwiperStyles) { - console.log(isSwiperStyles); - if (cardSize !== 'xs') { - cardContent = ( - - - {name} - - - {price} - - {cardSize !== 'sm' && ( - <> - {`Cart: ${isInContext ? cartQuantity : 'N/A'}`} - {`Collection: ${isInContext ? collectionQuantity : 'N/A'}`} - {`Deck: ${isInContext ? deckQuantity : 'N/A'}`} - - )} - - ); - } + + if (cardSize !== 'xs') { + cardContent = ( + + + {name} + + + {price} + + {cardSize !== 'sm' && ( + <> + {`Cart: ${isInContext ? cartQuantity : 'N/A'}`} + {`Collection: ${isInContext ? collectionQuantity : 'N/A'}`} + {`Deck: ${isInContext ? deckQuantity : 'N/A'}`} + + )} + + ); } + return ( diff --git a/src/components/cards/media/CardMediaSection.js b/src/components/cards/media/CardMediaSection.js index e918345..270bcef 100644 --- a/src/components/cards/media/CardMediaSection.js +++ b/src/components/cards/media/CardMediaSection.js @@ -7,7 +7,7 @@ import { MediaContainer, Media, MediaPopover, - Overlay, + // Overlay, } from '../../../context/hooks/style-hooks/usePortfolioStyles'; import { useOverlay } from '../../../context/hooks/useOverlay'; import placeHolder from '../../../assets/images/placeholder.jpeg'; @@ -63,7 +63,7 @@ const CardMediaSection = forwardRef( diff --git a/src/components/dialogs/CollectionDialog.jsx b/src/components/dialogs/CollectionDialog.jsx index 352c974..14393e3 100644 --- a/src/components/dialogs/CollectionDialog.jsx +++ b/src/components/dialogs/CollectionDialog.jsx @@ -1,120 +1,3 @@ -// import React, { useEffect } from 'react'; -// import PropTypes from 'prop-types'; -// import { -// Avatar, -// Box, -// CssBaseline, -// Dialog, -// DialogContent, -// DialogTitle, -// Divider, -// Grid, -// Paper, -// } from '@mui/material'; -// import { useCollectionStore, useFormContext, useMode } from '../../context'; -// import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; -// import AddCollectionForm from '../forms/AddCollectionForm'; -// import UpdateCollectionForm from '../forms/UpdateCollectionForm'; -// import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; -// import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -// import { -// DialogPaper, -// StyledDialog, -// StyledDialogContent, -// } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; -// import MDAvatar from '../../layout/REUSABLE_COMPONENTS/MDAVATAR'; -// const CollectionDialog = ({ -// open, -// onClose, -// isNew, -// collectionData, -// collectionMode, -// }) => { -// const { -// formMethods, -// onSubmit, -// setFormSchema, -// currentSchemaKey, -// currentForm, -// setCurrentForm, -// } = useFormContext(); -// const { theme } = useMode(); - -// useEffect(() => { -// if (collectionMode === 'edit') { -// setCurrentForm('updateCollectionForm'); -// } -// }, [collectionMode, setCurrentForm]); - -// return ( -// -// -// -// -// -// -// -// -// -// {currentForm === 'addCollectionForm' -// ? 'Add a Collection' -// : 'Update a Collection'} -// -// -// {' '} -// -// - -// -// {currentForm === 'addCollectionForm' ? ( -// -// ) : ( -// -// )} -// -// -// ); -// }; - -// CollectionDialog.propTypes = { -// open: PropTypes.bool.isRequired, -// onClose: PropTypes.func.isRequired, -// isNew: PropTypes.bool, -// collectionData: PropTypes.shape({ -// name: PropTypes.string, -// description: PropTypes.string, -// }), -// }; - -// export default CollectionDialog; import React from 'react'; import PropTypes from 'prop-types'; import { CssBaseline, DialogTitle, Divider } from '@mui/material'; diff --git a/src/components/dialogs/GenericCardDialog.jsx b/src/components/dialogs/GenericCardDialog.jsx index 891ac56..e1b03ed 100644 --- a/src/components/dialogs/GenericCardDialog.jsx +++ b/src/components/dialogs/GenericCardDialog.jsx @@ -29,7 +29,10 @@ import CardDetail from '../cards/CardDetail'; import { useOverlay } from '../../context/hooks/useOverlay'; import CardDetailsContainer from '../cards/CardDetailsContainer'; import { enqueueSnackbar } from 'notistack'; -import { DialogPaper } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; +import { + DialogPaper, + StyledDialog, +} from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; const GenericCardDialog = (props) => { const { theme } = useMode(); @@ -87,7 +90,7 @@ const GenericCardDialog = (props) => { [setContext, setIsContextSelected] ); return ( - { @@ -221,7 +225,7 @@ const GenericCardDialog = (props) => { - + ); }; diff --git a/src/components/forms/SignupForm.jsx b/src/components/forms/SignupForm.jsx index f4d78fa..9836f29 100644 --- a/src/components/forms/SignupForm.jsx +++ b/src/components/forms/SignupForm.jsx @@ -1,118 +1,3 @@ -// import React, { useEffect } from 'react'; -// import { Box, Button } from '@mui/material'; -// import FormField from './reusable/FormField'; -// import { useForm } from 'react-hook-form'; -// import { zodResolver } from '@hookform/resolvers/zod'; -// import { -// formSchemas, -// getDefaultValuesFromSchema, -// } from '../../context/UTILITIES_CONTEXT/FormContext/schemas'; // Ensure this path is correct -// import { LoadingButton } from '@mui/lab'; -// import { useFormContext, useMode, usePageContext } from '../../context'; -// import AuthSwitch from '../buttons/other/AuthSwitch'; -// import PersonAddIcon from '@mui/icons-material/PersonAdd'; - -// import { -// FormBox, -// FormFieldBox, -// } from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; -// const baseButtonStyles = { -// bgcolor: '#6a59ff', // background-color -// borderColor: '#6a59ff', -// borderWidth: 2, -// borderStyle: 'solid', -// display: 'flex', -// flexGrow: 1, -// alignItems: 'center', -// justifyContent: 'center', -// marginLeft: 'auto', -// marginRight: 'auto', -// marginBottom: '16px', -// marginTop: '16px', -// position: 'relative', -// bottom: 0, -// cursor: 'pointer', -// transition: 'background-color 0.3s, border-color 0.3s, color 0.3s', -// ':hover': { -// fontWeight: 'bold', -// bgcolor: '#4a6da7', -// borderColor: '#34597f', -// }, -// ':focus': { -// outline: '2px solid #62a4ff', -// outlineOffset: 2, -// }, -// }; -// const SignupForm = ({ signupMode, toggleAuthMode, formLabel }) => { -// const { theme } = useMode(); -// const { formMethods, onSubmit, setFormSchema } = useFormContext(); - -// const { -// register, -// handleSubmit, -// formState: { errors, isSubmitting }, -// } = formMethods; - -// useEffect(() => { -// setFormSchema('signupForm'); -// }, [setFormSchema]); -// const fields = [ -// { name: 'firstName', label: 'First Name', type: 'text' }, -// { name: 'lastName', label: 'Last Name', type: 'text' }, -// { name: 'email', label: 'Email', type: 'email' }, -// { name: 'username', label: 'Username', type: 'text' }, -// { name: 'password', label: 'Password', type: 'password' }, -// ]; - -// // Updated onFormSubmit to directly use onSubmit from context -// const onFormSubmit = (data) => { -// onSubmit(data, 'signupForm'); -// }; -// return ( -// -// {fields.map((field, index) => ( -// -// -// -// ))} -// -// {errors.form && ( -// {errors.form.message} -// )} -// -// } -// fullWidth -// sx={{ -// background: theme.palette.backgroundG.light, -// borderColor: theme.palette.backgroundG.light, -// borderWidth: 2, -// '&:hover': { background: theme.palette.backgroundG.default }, -// '&:focus': { background: theme.palette.backgroundG.default }, -// }} -// > -// Sign Up -// -// -// ); -// }; - -// export default SignupForm; import React from 'react'; import PersonAddIcon from '@mui/icons-material/PersonAdd'; import PersonIcon from '@mui/icons-material/Person'; diff --git a/src/components/forms/formsConfig.jsx b/src/components/forms/formsConfig.jsx index 9780bdd..0038a3d 100644 --- a/src/components/forms/formsConfig.jsx +++ b/src/components/forms/formsConfig.jsx @@ -1,6 +1,11 @@ import LoginIcon from '@mui/icons-material/Login'; import PersonIcon from '@mui/icons-material/Person'; import LockIcon from '@mui/icons-material/Lock'; +import EmailRoundedIcon from '@mui/icons-material/EmailRounded'; +import VerifiedUserRoundedIcon from '@mui/icons-material/VerifiedUserRounded'; +import DescriptionRoundedIcon from '@mui/icons-material/DescriptionRounded'; +import AccountCircleRoundedIcon from '@mui/icons-material/AccountCircleRounded'; +import FindInPageRoundedIcon from '@mui/icons-material/FindInPageRounded'; // TODO: ADD EMAIL ICON // TODO: ADD First ICON // TODO: ADD Last ICON @@ -8,9 +13,19 @@ import LockIcon from '@mui/icons-material/Lock'; // TODO: ADD Description ICON const auth = [ - { name: 'firstName', label: 'First Name', type: 'text', icon: <> }, - { name: 'lastName', label: 'Last Name', type: 'text', icon: <> }, - { name: 'email', label: 'Email', type: 'email', icon: <> }, + { + name: 'firstName', + label: 'First Name', + type: 'text', + icon: , + }, + { + name: 'lastName', + label: 'Last Name', + type: 'text', + icon: , + }, + { name: 'email', label: 'Email', type: 'email', icon: }, { name: 'username', label: 'Username', @@ -29,7 +44,7 @@ const collection = [ name: 'name', label: 'Name', type: 'text', - icon: <>, + icon: , required: true, multiline: false, }, @@ -37,7 +52,7 @@ const collection = [ name: 'description', label: 'Description', type: 'text', - icon: <>, + icon: , required: true, multiline: true, rows: 4, diff --git a/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx b/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx index a8d0b57..10d2c56 100644 --- a/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx +++ b/src/context/MISC_CONTEXT/AppContext/AppContextProvider.jsx @@ -47,6 +47,7 @@ export const AppContextProvider = ({ children }) => { topFiveCards: cardsWithQuantities ?.sort((a, b) => b.price - a.price) .slice(0, 5), + numCardsCollected: allCardsWithQuantities?.length || 0, }; setCollectionMetaData(metaData); diff --git a/src/context/hooks/style-hooks/usePortfolioStyles.jsx b/src/context/hooks/style-hooks/usePortfolioStyles.jsx index 998f911..9e48060 100644 --- a/src/context/hooks/style-hooks/usePortfolioStyles.jsx +++ b/src/context/hooks/style-hooks/usePortfolioStyles.jsx @@ -1,274 +1,223 @@ -import { - Box, - Button, - ButtonGroup, - CardMedia, - Container, - Grid, - Paper, - Popper, - Table, - TableBody, - TableCell, - TableFooter, - TableHead, - TableRow, - Typography, - TablePagination, -} from '@mui/material'; -// import TablePaginationActions from '@mui/material/TablePagination/TablePaginationActions'; +// import { +// Box, +// Button, +// ButtonGroup, +// CardMedia, +// Container, +// Grid, +// Paper, +// Popper, +// Table, +// TableBody, +// TableCell, +// TableFooter, +// TableHead, +// TableRow, +// Typography, +// TablePagination, +// } from '@mui/material'; +// // import TablePaginationActions from '@mui/material/TablePagination/TablePaginationActions'; +// import styled from 'styled-components'; + +import { CardMedia, Popper } from '@mui/material'; import styled from 'styled-components'; +export const MediaContainer = styled('div')({ + cursor: 'pointer', + position: 'relative', +}); -export const StatisticPaper = styled(Paper)(({ theme }) => ({ - padding: theme.spacing(2), - margin: 'auto', - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - flexGrow: 1, - justifyContent: 'center', - minHeight: '100%', - height: '100%', +export const MediaPopover = styled(Popper)({ + pointerEvents: 'none', + height: 'auto', + width: 'auto', + maxWidth: '300px', + maxHeight: 'auto', +}); + +export const Media = styled(CardMedia)(({ theme }) => ({ width: '100%', - boxShadow: theme.shadows[3], + height: 'auto', + flexGrow: 1, + alignItems: 'flex-end', + padding: theme.spacing(0.5), })); - -// export const PortfolioBox = styled(Box)(({ theme }) => ({ +// export const StatisticPaper = styled(Paper)(({ theme }) => ({ +// padding: theme.spacing(2), +// margin: 'auto', // display: 'flex', // flexDirection: 'column', -// justifyContent: 'center', // alignItems: 'center', -// maxWidth: '100vw', -// width: '100%', +// flexGrow: 1, +// justifyContent: 'center', +// minHeight: '100%', // height: '100%', -// margin: theme.spacing(0, 'auto'), -// padding: theme.spacing(1, 2, 3), -// backgroundColor: theme.palette.backgroundA.lightest, -// color: theme.palette.text.primary, +// width: '100%', +// boxShadow: theme.shadows[3], // })); -// export const PortfolioBoxA = styled(Box)(({ theme }) => ({ +// // export const PortfolioBox = styled(Box)(({ theme }) => ({ +// // display: 'flex', +// // flexDirection: 'column', +// // justifyContent: 'center', +// // alignItems: 'center', +// // maxWidth: '100vw', +// // width: '100%', +// // height: '100%', +// // margin: theme.spacing(0, 'auto'), +// // padding: theme.spacing(1, 2, 3), +// // backgroundColor: theme.palette.backgroundA.lightest, +// // color: theme.palette.text.primary, +// // })); + +// // export const PortfolioBoxA = styled(Box)(({ theme }) => ({ +// // flexDirection: 'column', +// // flexGrow: 1, +// // height: 'auto', +// // width: '100%', +// // minHeight: '100vh', // Reducing height by 128px +// // boxShadow: theme.shadows[5], +// // [theme.breakpoints.down('sm')]: { +// // padding: theme.spacing(2), +// // }, +// // })); + +// // export const PortfolioBoxB = styled(Box)(({ theme }) => ({ +// // display: 'flex', +// // flexDirection: 'column', +// // gap: theme.spacing(4), +// // borderRadius: theme.shape.borderRadius, +// // flexGrow: 1, +// // background: theme.palette.backgroundD.dark, +// // padding: theme.spacing(4), +// // width: '100%', +// // height: '100%', +// // boxShadow: theme.shadows[5], +// // [theme.breakpoints.down('sm')]: { +// // padding: theme.spacing(2), +// // }, +// // })); + +// // export const StatisticHeader = styled('div')(({ theme }) => ({ +// // marginBottom: theme.spacing(1), +// // fontWeight: 'bold', +// // color: theme.palette.backgroundA.lighter, +// // })); +// export const StatisticHeader = styled(Typography)(({ theme }) => ({ +// fontWeight: 'bold', +// color: theme.palette.backgroundA.dark, +// marginBottom: theme.spacing(1), +// })); +// export const StatisticsContent = styled('div')(({ theme }) => ({ +// display: 'flex', // flexDirection: 'column', +// alignItems: 'center', +// justifyContent: 'center', // flexGrow: 1, -// height: 'auto', +// height: '100%', // width: '100%', -// minHeight: '100vh', // Reducing height by 128px -// boxShadow: theme.shadows[5], -// [theme.breakpoints.down('sm')]: { -// padding: theme.spacing(2), -// }, // })); -// export const PortfolioBoxB = styled(Box)(({ theme }) => ({ +// export const PortfolioPaper = styled(Paper)(({ theme }) => ({ +// background: theme.palette.backgroundD.darkest, +// color: theme.palette.text.primary, // display: 'flex', +// justifyContent: 'center', // flexDirection: 'column', -// gap: theme.spacing(4), -// borderRadius: theme.shape.borderRadius, -// flexGrow: 1, -// background: theme.palette.backgroundD.dark, -// padding: theme.spacing(4), +// margin: 'auto', // width: '100%', -// height: '100%', -// boxShadow: theme.shadows[5], -// [theme.breakpoints.down('sm')]: { -// padding: theme.spacing(2), -// }, +// padding: theme.spacing(2), +// borderRadius: theme.shape.borderRadius, // })); -// export const StatisticHeader = styled('div')(({ theme }) => ({ -// marginBottom: theme.spacing(1), -// fontWeight: 'bold', -// color: theme.palette.backgroundA.lighter, +// export const ComponentGridContainer = styled('div')(({ theme }) => ({ +// width: '100%', +// alignItems: 'center', +// justifyContent: 'space-between', +// padding: theme.spacing(2), +// backgroundColor: theme.palette.backgroundB.lighter, +// borderRadius: theme.shape.borderRadius, +// border: '3px solid', +// borderColor: theme.palette.backgroundB.lightest, // })); -export const StatisticHeader = styled(Typography)(({ theme }) => ({ - fontWeight: 'bold', - color: theme.palette.backgroundA.dark, - marginBottom: theme.spacing(1), -})); -export const StatisticsContent = styled('div')(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - flexGrow: 1, - height: '100%', - width: '100%', -})); - -export const PortfolioPaper = styled(Paper)(({ theme }) => ({ - background: theme.palette.backgroundD.darkest, - color: theme.palette.text.primary, - display: 'flex', - justifyContent: 'center', - flexDirection: 'column', - margin: 'auto', - width: '100%', - padding: theme.spacing(2), - borderRadius: theme.shape.borderRadius, -})); - -export const ComponentGridContainer = styled('div')(({ theme }) => ({ - width: '100%', - alignItems: 'center', - justifyContent: 'space-between', - padding: theme.spacing(2), - backgroundColor: theme.palette.backgroundB.lighter, - borderRadius: theme.shape.borderRadius, - border: '3px solid', - borderColor: theme.palette.backgroundB.lightest, -})); - -export const ComponentGridItem = styled(Grid)(({ theme }) => ({ - display: 'flex', - justifyContent: 'flex-end', - background: theme.palette.backgroundA.main, - borderRadius: theme.shape.borderRadius, -})); - -export const DialogButton = styled(Button)({ - textTransform: 'none', -}); -export const SelectCollectionListContainer = styled(Container)(({ theme }) => ({ - // maxHeight: '60vh', - overflowY: 'auto', - padding: theme.spacing(2), - height: '100%', - width: '100%', -})); - -export const DialogContent = styled('div')(({ theme }) => ({ - padding: theme.spacing(2), - background: theme.palette.backgroundA.lightest, -})); - -export const BoxStyle = styled(Box)(({ theme }) => ({ - padding: theme.spacing(2), - justifyContent: 'center', - margin: 'auto', -})); +// export const ComponentGridItem = styled(Grid)(({ theme }) => ({ +// display: 'flex', +// justifyContent: 'flex-end', +// background: theme.palette.backgroundA.main, +// borderRadius: theme.shape.borderRadius, +// })); -export const CardStyle = styled('div')(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - margin: 'auto', - padding: theme.spacing(2), - maxWidth: '100%', - maxHeight: '100%', -})); +// export const DialogButton = styled(Button)({ +// textTransform: 'none', +// }); -export const CardContentStyle = styled('div')(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - margin: 'auto', - padding: theme.spacing(2), - maxWidth: '100%', - maxHeight: '100%', -})); +// export const SelectCollectionListContainer = styled(Container)(({ theme }) => ({ +// // maxHeight: '60vh', +// overflowY: 'auto', +// padding: theme.spacing(2), +// height: '100%', +// width: '100%', +// })); -export const CardMediaStyle = styled('div')(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - margin: 'auto', - padding: theme.spacing(2), - maxWidth: '100%', - maxHeight: '100%', -})); +// export const DialogContent = styled('div')(({ theme }) => ({ +// padding: theme.spacing(2), +// background: theme.palette.backgroundA.lightest, +// })); -export const MediaContainer = styled('div')({ - cursor: 'pointer', - position: 'relative', -}); +// export const BoxStyle = styled(Box)(({ theme }) => ({ +// padding: theme.spacing(2), +// justifyContent: 'center', +// margin: 'auto', +// })); -export const MediaPopover = styled(Popper)({ - pointerEvents: 'none', - height: 'auto', - width: 'auto', - maxWidth: '300px', - maxHeight: 'auto', -}); +// export const CardStyle = styled('div')(({ theme }) => ({ +// display: 'flex', +// flexDirection: 'column', +// justifyContent: 'center', +// margin: 'auto', +// padding: theme.spacing(2), +// maxWidth: '100%', +// maxHeight: '100%', +// })); -export const Media = styled(CardMedia)(({ theme }) => ({ - width: '100%', - height: 'auto', - flexGrow: 1, - alignItems: 'flex-end', - padding: theme.spacing(0.5), -})); +// export const CardContentStyle = styled('div')(({ theme }) => ({ +// display: 'flex', +// flexDirection: 'column', +// justifyContent: 'center', +// margin: 'auto', +// padding: theme.spacing(2), +// maxWidth: '100%', +// maxHeight: '100%', +// })); -export const CardListContainerBox = styled(Box)(({ theme }) => ({ - maxWidth: '100%', - background: theme.palette.backgroundB.dark, - borderRadius: theme.shape.borderRadius, - width: { - xs: '100%', // Full width on mobile screens - md: '100%', - }, - padding: theme.spacing(4), -})); +// export const CardMediaStyle = styled('div')(({ theme }) => ({ +// display: 'flex', +// flexDirection: 'column', +// justifyContent: 'center', +// margin: 'auto', +// padding: theme.spacing(2), +// maxWidth: '100%', +// maxHeight: '100%', +// })); -export const CardListContainerGrid = styled(Grid)(({ theme }) => ({ - // background: theme.palette.backgroundB.default, - maxHeight: '100%', - width: '100%', -})); +// export const CardListContainerBox = styled(Box)(({ theme }) => ({ +// maxWidth: '100%', +// background: theme.palette.backgroundB.dark, +// borderRadius: theme.shape.borderRadius, +// width: { +// xs: '100%', // Full width on mobile screens +// md: '100%', +// }, +// padding: theme.spacing(4), +// })); -export const TablePaper = styled(Paper)(({ theme }) => ({ - maxWidth: 'lg', - margin: 'auto', - overflowX: 'auto', // Ensures table doesn't overflow the paper - background: theme.palette.backgroundB.default, - padding: theme.spacing(2), - [theme.breakpoints.up('xs')]: { - padding: theme.spacing(1), // Smaller padding for xs - }, - [theme.breakpoints.up('sm')]: { - padding: theme.spacing(2), // Medium padding for sm - }, - [theme.breakpoints.up('md')]: { - padding: theme.spacing(2), // Larger padding for md - }, - [theme.breakpoints.up('lg')]: { - padding: theme.spacing(2), // Extra larger padding for lg - }, - [theme.breakpoints.up('xl')]: { - padding: theme.spacing(2), // Maximum padding for xl - }, -})); +// export const CardListContainerGrid = styled(Grid)(({ theme }) => ({ +// // background: theme.palette.backgroundB.default, +// maxHeight: '100%', +// width: '100%', +// })); -export const PortfolioTableContainer = styled(Container)(({ theme }) => ({ - // maxHeight: '60vh', - maxWidth: 'lg', - overflowY: 'auto', // Allows table to scroll vertically - padding: theme.spacing(2), - margin: theme.spacing(1), - background: theme.palette.backgroundB.light, - borderRadius: theme.shape.borderRadius, -})); -export const PortfolioButtonGroup = styled(ButtonGroup)(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', -})); -export const PortfolioButton = styled(Button)(({ theme }) => ({ - padding: '10px 20px', - border: 'none', - borderRadius: '5px', - cursor: 'pointer', - width: '100%', - color: theme.palette.getContrastText(theme.palette.backgroundA.dark), - backgroundColor: theme.palette.backgroundA.dark, - '&:hover': { - backgroundColor: theme.palette.backgroundA.darker, - }, -})); -// // ! PORTFOLIO TABLE STYLES -// export const PortfolioTablePaper = styled(Paper)(({ theme }) => ({ +// export const TablePaper = styled(Paper)(({ theme }) => ({ // maxWidth: 'lg', // margin: 'auto', // overflowX: 'auto', // Ensures table doesn't overflow the paper @@ -290,478 +239,530 @@ export const PortfolioButton = styled(Button)(({ theme }) => ({ // padding: theme.spacing(2), // Maximum padding for xl // }, // })); -// export const PortfolioTable = styled(Table)(({ theme }) => ({ -// minWidth: 300, -// minHeight: 300, -// width: '100%', -// height: '100%', -// background: theme.palette.backgroundA.lightest, -// })); -// // TABLE HEADER -// export const PortfolioTableHeader = styled(TableHead)(({ theme }) => ({ -// background: theme.palette.backgroundA.lighter, -// color: theme.palette.backgroundA.contrastTextA, -// [theme.breakpoints.up('md')]: { -// fontSize: '1rem', -// }, -// })); -// // TABLE BODY -// export const PortfolioTableBody = styled(TableBody)(({ theme }) => ({ -// background: theme.palette.backgroundA.lightest, -// border: '2px solid', -// borderColor: theme.palette.divider, -// })); -// export const PortfolioTableRow = styled(TableRow)(({ theme }) => ({ -// // '&:nth-of-type(odd)': { -// // background: theme.palette.backgroundA.light, -// // }, -// // '&:nth-of-type(even)': { -// // background: theme.palette.backgroundA.lighter, -// // }, + +// export const PortfolioTableContainer = styled(Container)(({ theme }) => ({ +// // maxHeight: '60vh', +// maxWidth: 'lg', +// overflowY: 'auto', // Allows table to scroll vertically +// padding: theme.spacing(2), +// margin: theme.spacing(1), +// background: theme.palette.backgroundB.light, +// borderRadius: theme.shape.borderRadius, // })); -// export const PortfolioTableCell = styled(TableCell)(({ theme }) => ({ -// border: '2px solid', -// borderColor: theme.palette.divider, -// // background: theme.palette.backgroundA.light, - -// [theme.breakpoints.down('sm')]: { -// padding: theme.spacing(1), -// fontSize: '0.7rem', -// }, -// [theme.breakpoints.up('md')]: { -// padding: theme.spacing(2), -// fontSize: '1rem', -// }, +// export const PortfolioButtonGroup = styled(ButtonGroup)(({ theme }) => ({ +// display: 'flex', +// flexDirection: 'column', +// justifyContent: 'center', +// alignItems: 'center', +// boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', // })); -// // TABLE FOOTER -// export const PortfolioTableFooter = styled(TableFooter)(({ theme }) => ({ -// backgroundColor: theme.palette.backgroundA.lighter, -// borderTop: `1px solid ${theme.palette.divider}`, -// '& .MuiTableCell-root': { -// padding: theme.spacing(2), +// export const PortfolioButton = styled(Button)(({ theme }) => ({ +// padding: '10px 20px', +// border: 'none', +// borderRadius: '5px', +// cursor: 'pointer', +// width: '100%', +// color: theme.palette.getContrastText(theme.palette.backgroundA.dark), +// backgroundColor: theme.palette.backgroundA.dark, +// '&:hover': { +// backgroundColor: theme.palette.backgroundA.darker, // }, // })); -// export const PortfolioPaginationActionsTableRow = styled(TableRow)( -// ({ theme }) => ({ -// // Example styling, you can customize as needed -// backgroundColor: theme.palette.backgroundA.lighter, -// '&:hover': { -// backgroundColor: theme.palette.action.hover, -// }, -// '& .MuiTableCell-root': { -// textAlign: 'right', -// padding: theme.spacing(1), -// }, -// }) -// ); -// export const PortfolioPaginationActionsTableCell = styled(TableCell)( -// ({ theme }) => ({ -// // Example styling, you can customize as needed -// fontSize: '0.9rem', -// fontWeight: 'bold', -// color: theme.palette.backgroundA.contrastTextA, -// backgroundColor: theme.palette.backgroundA.lighter, - -// '&:hover': { -// color: theme.palette.backgroundA.contrastTextA, -// }, -// '& .MuiTableCell-root': { -// textAlign: 'right', -// padding: theme.spacing(1), -// }, -// }) -// ); -// export const PortfolioPaginationActionsTableContentsContainer = styled(Box)( -// ({ theme }) => ({ -// // '.MuiIconButton-root': { -// // padding: theme.spacing(1), -// // margin: '0 4px', -// // '&:hover': { -// // backgroundColor: theme.palette.action.hover, -// // }, -// // }, -// display: 'flex', -// flexShrink: 0, -// justifyContent: 'flex-end', -// // ml: 2.5, -// width: '100%', -// flexDirection: 'row', -// borderRadius: '5px', -// boxShadow: '0 2px 4px rgba(0,0,0,0.1)', -// '&:hover': { -// boxShadow: '0 4px 8px rgba(0,0,0,0.2)', -// }, -// }) -// ); -// // TABLE PRICE BOX -// export const PortfolioTablePriceBox = styled(Box)(({ theme }) => ({ +// // // ! PORTFOLIO TABLE STYLES +// // export const PortfolioTablePaper = styled(Paper)(({ theme }) => ({ +// // maxWidth: 'lg', +// // margin: 'auto', +// // overflowX: 'auto', // Ensures table doesn't overflow the paper +// // background: theme.palette.backgroundB.default, +// // padding: theme.spacing(2), +// // [theme.breakpoints.up('xs')]: { +// // padding: theme.spacing(1), // Smaller padding for xs +// // }, +// // [theme.breakpoints.up('sm')]: { +// // padding: theme.spacing(2), // Medium padding for sm +// // }, +// // [theme.breakpoints.up('md')]: { +// // padding: theme.spacing(2), // Larger padding for md +// // }, +// // [theme.breakpoints.up('lg')]: { +// // padding: theme.spacing(2), // Extra larger padding for lg +// // }, +// // [theme.breakpoints.up('xl')]: { +// // padding: theme.spacing(2), // Maximum padding for xl +// // }, +// // })); +// // export const PortfolioTable = styled(Table)(({ theme }) => ({ +// // minWidth: 300, +// // minHeight: 300, +// // width: '100%', +// // height: '100%', +// // background: theme.palette.backgroundA.lightest, +// // })); +// // // TABLE HEADER +// // export const PortfolioTableHeader = styled(TableHead)(({ theme }) => ({ +// // background: theme.palette.backgroundA.lighter, +// // color: theme.palette.backgroundA.contrastTextA, +// // [theme.breakpoints.up('md')]: { +// // fontSize: '1rem', +// // }, +// // })); +// // // TABLE BODY +// // export const PortfolioTableBody = styled(TableBody)(({ theme }) => ({ +// // background: theme.palette.backgroundA.lightest, +// // border: '2px solid', +// // borderColor: theme.palette.divider, +// // })); +// // export const PortfolioTableRow = styled(TableRow)(({ theme }) => ({ +// // // '&:nth-of-type(odd)': { +// // // background: theme.palette.backgroundA.light, +// // // }, +// // // '&:nth-of-type(even)': { +// // // background: theme.palette.backgroundA.lighter, +// // // }, +// // })); +// // export const PortfolioTableCell = styled(TableCell)(({ theme }) => ({ +// // border: '2px solid', +// // borderColor: theme.palette.divider, +// // // background: theme.palette.backgroundA.light, + +// // [theme.breakpoints.down('sm')]: { +// // padding: theme.spacing(1), +// // fontSize: '0.7rem', +// // }, +// // [theme.breakpoints.up('md')]: { +// // padding: theme.spacing(2), +// // fontSize: '1rem', +// // }, +// // })); +// // // TABLE FOOTER +// // export const PortfolioTableFooter = styled(TableFooter)(({ theme }) => ({ +// // backgroundColor: theme.palette.backgroundA.lighter, +// // borderTop: `1px solid ${theme.palette.divider}`, +// // '& .MuiTableCell-root': { +// // padding: theme.spacing(2), +// // }, +// // })); +// // export const PortfolioPaginationActionsTableRow = styled(TableRow)( +// // ({ theme }) => ({ +// // // Example styling, you can customize as needed +// // backgroundColor: theme.palette.backgroundA.lighter, +// // '&:hover': { +// // backgroundColor: theme.palette.action.hover, +// // }, +// // '& .MuiTableCell-root': { +// // textAlign: 'right', +// // padding: theme.spacing(1), +// // }, +// // }) +// // ); +// // export const PortfolioPaginationActionsTableCell = styled(TableCell)( +// // ({ theme }) => ({ +// // // Example styling, you can customize as needed +// // fontSize: '0.9rem', +// // fontWeight: 'bold', +// // color: theme.palette.backgroundA.contrastTextA, +// // backgroundColor: theme.palette.backgroundA.lighter, + +// // '&:hover': { +// // color: theme.palette.backgroundA.contrastTextA, +// // }, +// // '& .MuiTableCell-root': { +// // textAlign: 'right', +// // padding: theme.spacing(1), +// // }, +// // }) +// // ); +// // export const PortfolioPaginationActionsTableContentsContainer = styled(Box)( +// // ({ theme }) => ({ +// // // '.MuiIconButton-root': { +// // // padding: theme.spacing(1), +// // // margin: '0 4px', +// // // '&:hover': { +// // // backgroundColor: theme.palette.action.hover, +// // // }, +// // // }, +// // display: 'flex', +// // flexShrink: 0, +// // justifyContent: 'flex-end', +// // // ml: 2.5, +// // width: '100%', +// // flexDirection: 'row', +// // borderRadius: '5px', +// // boxShadow: '0 2px 4px rgba(0,0,0,0.1)', +// // '&:hover': { +// // boxShadow: '0 4px 8px rgba(0,0,0,0.2)', +// // }, +// // }) +// // ); +// // // TABLE PRICE BOX +// // export const PortfolioTablePriceBox = styled(Box)(({ theme }) => ({ +// // display: 'flex', +// // justifyContent: 'flex-end', +// // alignItems: 'center', +// // width: '100%', +// // padding: theme.spacing(2), +// // background: theme.palette.backgroundB.lighter, +// // })); +// // ! OVERLAY STYLES +// export const Overlay = styled(Box)(({ theme }) => ({ +// position: 'fixed', +// top: '0', +// left: '0', +// width: '100%', +// height: '100%', +// backgroundColor: 'rgba(0,0,0,0.5)', // display: 'flex', -// justifyContent: 'flex-end', +// justifyContent: 'center', // alignItems: 'center', -// width: '100%', -// padding: theme.spacing(2), -// background: theme.palette.backgroundB.lighter, -// })); -// ! OVERLAY STYLES -export const Overlay = styled(Box)(({ theme }) => ({ - position: 'fixed', - top: '0', - left: '0', - width: '100%', - height: '100%', - backgroundColor: 'rgba(0,0,0,0.5)', - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - zIndex: 9999, -})); - -// ... more styles - -// import { makeStyles } from '@mui/material'; - -// export const usePortfolioStyles = makeStyles((theme) => ({ -// // portfolioBox: { -// // display: 'flex', -// // flexDirection: 'column', -// // justifyContent: 'center', -// // alignItems: 'center', -// // maxWidth: '100vw', -// // width: '100%', -// // height: '100%', -// // margin: theme.spacing(0, 'auto'), -// // padding: theme.spacing(1, 2, 3), -// // backgroundColor: theme.palette.backgroundA.lightest, -// // color: theme.palette.text.primary, -// // }, -// statisticPaper: { -// padding: theme.spacing(2), -// margin: 'auto', -// display: 'flex', -// flexDirection: 'column', -// alignItems: 'center', -// flexGrow: 1, -// justifyContent: 'center', -// minHeight: '100%', -// height: '100%', -// width: '100%', -// boxShadow: theme.shadows[3], -// }, -// statisticHeader: { -// marginBottom: theme.spacing(1), -// fontWeight: 'bold', -// color: theme.palette.backgroundA.lighter, -// }, -// statisticsContent: { -// display: 'flex', -// flexDirection: 'column', -// alignItems: 'center', -// justifyContent: 'center', -// flexGrow: 1, -// height: '100%', -// width: '100%', -// }, -// paper: { -// background: theme.palette.backgroundD.darkest, -// color: theme.palette.text.primary, -// display: 'flex', -// justifyContent: 'center', -// flexDirection: 'column', -// margin: 'auto', -// width: '100%', -// padding: { -// xs: theme.spacing(1), -// sm: theme.spacing(1), -// md: theme.spacing(2), -// lg: theme.spacing(2), -// }, -// borderRadius: theme.shape.borderRadius, -// }, - -// gridContainer: { -// width: '100%', -// alignItems: 'center', -// justifyContent: 'space-between', -// padding: theme.spacing(2), -// backgroundColor: theme.palette.backgroundB.lighter, -// borderRadius: theme.shape.borderRadius, -// border: '3px solid', -// borderColor: theme.palette.backgroundB.lightest, - -// // color: theme.palette.text.primary, -// // background: theme.palette.backgroundB.lighter, -// }, -// gridItem: { -// display: 'flex', -// justifyContent: 'flex-end', -// background: theme.palette.success.main, -// borderRadius: theme.shape.borderRadius, -// }, -// portfolioBoxA: { -// display: 'flex', -// flexDirection: 'column', -// gap: theme.spacing(4), -// borderRadius: theme.shape.borderRadius, -// flexGrow: 1, -// background: theme.palette.backgroundC.dark, -// padding: theme.spacing(4), -// height: 'auto', -// width: '100%', -// // Adjusting minHeight and maxHeight to take into account the header and additional space -// minHeight: 'calc(100vh - 64px)', // Reducing height by 128px -// maxHeight: 'calc(100vh - 128px)', // Adjusting maxHeight similarly -// boxShadow: theme.shadows[5], -// [theme.breakpoints.down('sm')]: { -// padding: theme.spacing(2), -// }, -// // Using margin to push the content upwards from the bottom by 64px -// // marginBottom: '64px', // Pushing upwards from the bottom -// }, - -// portfolioBoxB: { -// display: 'flex', -// flexDirection: 'column', -// gap: theme.spacing(4), -// borderRadius: theme.shape.borderRadius, -// flexGrow: 1, -// // background: theme.palette.success.main, -// background: theme.palette.backgroundD.dark, -// padding: theme.spacing(4), -// // height: 'auto', -// width: '100%', -// height: '100%', - -// // 100vh -// // minHeight: '90vh', -// boxShadow: theme.shadows[5], -// [theme.breakpoints.down('sm')]: { -// padding: theme.spacing(2), -// }, -// }, -// typography: { -// fontWeight: 700, -// color: theme.palette.backgroundC.contrastText, -// fontSize: '1.5rem', -// textAlign: 'left', -// paddingLeft: theme.spacing(2), -// [theme.breakpoints.down('sm')]: { -// fontSize: '1.25rem', -// }, -// }, - -// // Add more custom styles as needed -// // gridContainer: { -// // width: '100%', -// // alignItems: 'center', -// // justifyContent: 'space-between', -// // padding: theme.spacing(1), -// // }, -// // Additional styles -// dialogButton: { -// textTransform: 'none', // or other style adjustments for dialog buttons -// }, -// listContainer: { -// // marginTop: theme.spacing(2), -// maxHeight: '60vh', // or other appropriate height -// overflowY: 'auto', -// padding: theme.spacing(2), -// // background: theme.palette.backgroundC.lighter, -// }, -// dialogContent: { -// padding: theme.spacing(2), -// background: theme.palette.backgroundA.lightest, -// // height: '100%', -// }, -// boxStyle: { -// padding: theme.spacing(2), -// justifyContent: 'center', -// margin: 'auto', -// }, -// cardStyle: { -// display: 'flex', -// flexDirection: 'column', -// justifyContent: 'center', -// margin: 'auto', -// padding: theme.spacing(2), -// maxWidth: '100%', -// maxHeight: '100%', -// }, -// cardContentStyle: { -// display: 'flex', -// flexDirection: 'column', -// justifyContent: 'center', -// margin: 'auto', -// padding: theme.spacing(2), -// maxWidth: '100%', -// maxHeight: '100%', -// }, -// cardMediaStyle: { -// display: 'flex', -// flexDirection: 'column', -// justifyContent: 'center', -// margin: 'auto', -// padding: theme.spacing(2), -// maxWidth: '100%', -// maxHeight: '100%', -// }, - -// // CARD MEDIA SECTION -// mediaContainer: { -// cursor: 'pointer', -// position: 'relative', -// }, -// popover: { -// pointerEvents: 'none', -// height: 'auto', -// width: 'auto', -// maxWidth: '300px', -// maxHeight: 'auto', -// }, -// media: { -// width: '100%', -// height: 'auto', -// flexGrow: 1, -// alignItems: 'flex-end', -// [theme.breakpoints.down('xs')]: { -// padding: theme.spacing(1), -// }, -// [theme.breakpoints.down('sm')]: { -// padding: theme.spacing(1), -// }, -// [theme.breakpoints.down('md')]: { -// padding: theme.spacing(1), -// }, -// [theme.breakpoints.down('lg')]: { -// padding: theme.spacing(0.5), -// }, -// [theme.breakpoints.down('xl')]: { -// padding: theme.spacing(0.5), -// }, -// }, - -// // OFFICIAL UPDATED STYLES -// cardListContainerBox: { -// maxWidth: '100%', -// background: theme.palette.backgroundB.dark, -// borderRadius: theme.shape.borderRadius, -// width: { -// xs: '100%', // Full width on mobile screens -// md: '100%', -// }, -// padding: theme.spacing(4), -// }, -// cardListContainerGrid: { -// // background: theme.palette.backgroundB.default, -// maxHeight: '100%', -// width: '100%', -// }, -// tablePaper: { -// maxWidth: 'lg', -// margin: 'auto', -// overflowX: 'auto', // Ensures table doesn't overflow the paper -// background: theme.palette.backgroundB.default, -// padding: theme.spacing(2), -// [theme.breakpoints.up('xs')]: { -// padding: theme.spacing(1), // Smaller padding for xs -// }, -// [theme.breakpoints.up('sm')]: { -// padding: theme.spacing(2), // Medium padding for sm -// }, -// [theme.breakpoints.up('md')]: { -// padding: theme.spacing(2), // Larger padding for md -// }, -// [theme.breakpoints.up('lg')]: { -// padding: theme.spacing(2), // Extra larger padding for lg -// }, -// [theme.breakpoints.up('xl')]: { -// padding: theme.spacing(2), // Maximum padding for xl -// }, -// }, -// tableContainer: { -// // maxHeight: '60vh', -// maxWidth: 'lg', -// overflowY: 'auto', // Allows table to scroll vertically -// padding: theme.spacing(2), -// margin: theme.spacing(1), -// background: theme.palette.backgroundB.light, -// borderRadius: theme.shape.borderRadius, -// }, -// table: { -// minWidth: 300, -// width: '100%', -// background: theme.palette.backgroundA.lightest, -// }, -// tableRow: { -// // '&:nth-of-type(odd)': { -// // background: theme.palette.backgroundA.light, -// // }, -// // '&:nth-of-type(even)': { -// // background: theme.palette.backgroundA.lighter, -// // }, -// }, -// tableCell: { -// border: '2px solid', -// borderColor: theme.palette.divider, -// // background: theme.palette.backgroundA.light, - -// [theme.breakpoints.down('sm')]: { -// padding: theme.spacing(1), -// fontSize: '0.7rem', -// }, -// [theme.breakpoints.up('md')]: { -// padding: theme.spacing(2), -// fontSize: '1rem', -// }, -// }, -// tableHeader: { -// background: theme.palette.backgroundA.lighter, -// color: theme.palette.backgroundA.contrastTextA, -// [theme.breakpoints.up('md')]: { -// fontSize: '1rem', -// }, -// }, -// tableBody: { -// background: theme.palette.backgroundA.lightest, -// border: '2px solid', -// borderColor: theme.palette.divider, -// }, -// tableFooter: { -// background: theme.palette.backgroundA.lighter, -// }, -// tablePriceBox: { -// display: 'flex', -// justifyContent: 'flex-end', -// alignItems: 'center', -// width: '100%', -// padding: theme.spacing(2), -// background: theme.palette.backgroundB.lighter, -// }, -// buttonGroup: { -// display: 'flex', -// flexDirection: 'column', -// justifyContent: 'center', -// alignItems: 'center', -// boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', -// }, -// button: { -// padding: '10px 20px', -// border: 'none', -// borderRadius: '5px', -// cursor: 'pointer', -// width: '100%', -// color: theme.palette.getContrastText(theme.palette.backgroundA.dark), -// backgroundColor: theme.palette.backgroundA.dark, -// '&:hover': { -// backgroundColor: theme.palette.backgroundA.darker, -// }, -// [theme.breakpoints.down('sm')]: { -// fontSize: '0.8rem', -// }, -// [theme.breakpoints.up('md')]: { -// fontSize: '1rem', -// }, -// }, -// // Add any other styles from CardPortfolio, PortfolioContent, and SelectCollection components +// zIndex: 9999, // })); -// export default usePortfolioStyles; +// // ... more styles + +// // import { makeStyles } from '@mui/material'; + +// // export const usePortfolioStyles = makeStyles((theme) => ({ +// // // portfolioBox: { +// // // display: 'flex', +// // // flexDirection: 'column', +// // // justifyContent: 'center', +// // // alignItems: 'center', +// // // maxWidth: '100vw', +// // // width: '100%', +// // // height: '100%', +// // // margin: theme.spacing(0, 'auto'), +// // // padding: theme.spacing(1, 2, 3), +// // // backgroundColor: theme.palette.backgroundA.lightest, +// // // color: theme.palette.text.primary, +// // // }, +// // statisticPaper: { +// // padding: theme.spacing(2), +// // margin: 'auto', +// // display: 'flex', +// // flexDirection: 'column', +// // alignItems: 'center', +// // flexGrow: 1, +// // justifyContent: 'center', +// // minHeight: '100%', +// // height: '100%', +// // width: '100%', +// // boxShadow: theme.shadows[3], +// // }, +// // statisticHeader: { +// // marginBottom: theme.spacing(1), +// // fontWeight: 'bold', +// // color: theme.palette.backgroundA.lighter, +// // }, +// // statisticsContent: { +// // display: 'flex', +// // flexDirection: 'column', +// // alignItems: 'center', +// // justifyContent: 'center', +// // flexGrow: 1, +// // height: '100%', +// // width: '100%', +// // }, +// // paper: { +// // background: theme.palette.backgroundD.darkest, +// // color: theme.palette.text.primary, +// // display: 'flex', +// // justifyContent: 'center', +// // flexDirection: 'column', +// // margin: 'auto', +// // width: '100%', +// // padding: { +// // xs: theme.spacing(1), +// // sm: theme.spacing(1), +// // md: theme.spacing(2), +// // lg: theme.spacing(2), +// // }, +// // borderRadius: theme.shape.borderRadius, +// // }, + +// // gridContainer: { +// // width: '100%', +// // alignItems: 'center', +// // justifyContent: 'space-between', +// // padding: theme.spacing(2), +// // backgroundColor: theme.palette.backgroundB.lighter, +// // borderRadius: theme.shape.borderRadius, +// // border: '3px solid', +// // borderColor: theme.palette.backgroundB.lightest, + +// // // color: theme.palette.text.primary, +// // // background: theme.palette.backgroundB.lighter, +// // }, +// // gridItem: { +// // display: 'flex', +// // justifyContent: 'flex-end', +// // background: theme.palette.success.main, +// // borderRadius: theme.shape.borderRadius, +// // }, +// // portfolioBoxA: { +// // display: 'flex', +// // flexDirection: 'column', +// // gap: theme.spacing(4), +// // borderRadius: theme.shape.borderRadius, +// // flexGrow: 1, +// // background: theme.palette.backgroundC.dark, +// // padding: theme.spacing(4), +// // height: 'auto', +// // width: '100%', +// // // Adjusting minHeight and maxHeight to take into account the header and additional space +// // minHeight: 'calc(100vh - 64px)', // Reducing height by 128px +// // maxHeight: 'calc(100vh - 128px)', // Adjusting maxHeight similarly +// // boxShadow: theme.shadows[5], +// // [theme.breakpoints.down('sm')]: { +// // padding: theme.spacing(2), +// // }, +// // // Using margin to push the content upwards from the bottom by 64px +// // // marginBottom: '64px', // Pushing upwards from the bottom +// // }, + +// // portfolioBoxB: { +// // display: 'flex', +// // flexDirection: 'column', +// // gap: theme.spacing(4), +// // borderRadius: theme.shape.borderRadius, +// // flexGrow: 1, +// // // background: theme.palette.success.main, +// // background: theme.palette.backgroundD.dark, +// // padding: theme.spacing(4), +// // // height: 'auto', +// // width: '100%', +// // height: '100%', + +// // // 100vh +// // // minHeight: '90vh', +// // boxShadow: theme.shadows[5], +// // [theme.breakpoints.down('sm')]: { +// // padding: theme.spacing(2), +// // }, +// // }, +// // typography: { +// // fontWeight: 700, +// // color: theme.palette.backgroundC.contrastText, +// // fontSize: '1.5rem', +// // textAlign: 'left', +// // paddingLeft: theme.spacing(2), +// // [theme.breakpoints.down('sm')]: { +// // fontSize: '1.25rem', +// // }, +// // }, + +// // // Add more custom styles as needed +// // // gridContainer: { +// // // width: '100%', +// // // alignItems: 'center', +// // // justifyContent: 'space-between', +// // // padding: theme.spacing(1), +// // // }, +// // // Additional styles +// // dialogButton: { +// // textTransform: 'none', // or other style adjustments for dialog buttons +// // }, +// // listContainer: { +// // // marginTop: theme.spacing(2), +// // maxHeight: '60vh', // or other appropriate height +// // overflowY: 'auto', +// // padding: theme.spacing(2), +// // // background: theme.palette.backgroundC.lighter, +// // }, +// // dialogContent: { +// // padding: theme.spacing(2), +// // background: theme.palette.backgroundA.lightest, +// // // height: '100%', +// // }, +// // boxStyle: { +// // padding: theme.spacing(2), +// // justifyContent: 'center', +// // margin: 'auto', +// // }, +// // cardStyle: { +// // display: 'flex', +// // flexDirection: 'column', +// // justifyContent: 'center', +// // margin: 'auto', +// // padding: theme.spacing(2), +// // maxWidth: '100%', +// // maxHeight: '100%', +// // }, +// // cardContentStyle: { +// // display: 'flex', +// // flexDirection: 'column', +// // justifyContent: 'center', +// // margin: 'auto', +// // padding: theme.spacing(2), +// // maxWidth: '100%', +// // maxHeight: '100%', +// // }, +// // cardMediaStyle: { +// // display: 'flex', +// // flexDirection: 'column', +// // justifyContent: 'center', +// // margin: 'auto', +// // padding: theme.spacing(2), +// // maxWidth: '100%', +// // maxHeight: '100%', +// // }, + +// // // CARD MEDIA SECTION +// // mediaContainer: { +// // cursor: 'pointer', +// // position: 'relative', +// // }, +// // popover: { +// // pointerEvents: 'none', +// // height: 'auto', +// // width: 'auto', +// // maxWidth: '300px', +// // maxHeight: 'auto', +// // }, +// // media: { +// // width: '100%', +// // height: 'auto', +// // flexGrow: 1, +// // alignItems: 'flex-end', +// // [theme.breakpoints.down('xs')]: { +// // padding: theme.spacing(1), +// // }, +// // [theme.breakpoints.down('sm')]: { +// // padding: theme.spacing(1), +// // }, +// // [theme.breakpoints.down('md')]: { +// // padding: theme.spacing(1), +// // }, +// // [theme.breakpoints.down('lg')]: { +// // padding: theme.spacing(0.5), +// // }, +// // [theme.breakpoints.down('xl')]: { +// // padding: theme.spacing(0.5), +// // }, +// // }, + +// // // OFFICIAL UPDATED STYLES +// // cardListContainerBox: { +// // maxWidth: '100%', +// // background: theme.palette.backgroundB.dark, +// // borderRadius: theme.shape.borderRadius, +// // width: { +// // xs: '100%', // Full width on mobile screens +// // md: '100%', +// // }, +// // padding: theme.spacing(4), +// // }, +// // cardListContainerGrid: { +// // // background: theme.palette.backgroundB.default, +// // maxHeight: '100%', +// // width: '100%', +// // }, +// // tablePaper: { +// // maxWidth: 'lg', +// // margin: 'auto', +// // overflowX: 'auto', // Ensures table doesn't overflow the paper +// // background: theme.palette.backgroundB.default, +// // padding: theme.spacing(2), +// // [theme.breakpoints.up('xs')]: { +// // padding: theme.spacing(1), // Smaller padding for xs +// // }, +// // [theme.breakpoints.up('sm')]: { +// // padding: theme.spacing(2), // Medium padding for sm +// // }, +// // [theme.breakpoints.up('md')]: { +// // padding: theme.spacing(2), // Larger padding for md +// // }, +// // [theme.breakpoints.up('lg')]: { +// // padding: theme.spacing(2), // Extra larger padding for lg +// // }, +// // [theme.breakpoints.up('xl')]: { +// // padding: theme.spacing(2), // Maximum padding for xl +// // }, +// // }, +// // tableContainer: { +// // // maxHeight: '60vh', +// // maxWidth: 'lg', +// // overflowY: 'auto', // Allows table to scroll vertically +// // padding: theme.spacing(2), +// // margin: theme.spacing(1), +// // background: theme.palette.backgroundB.light, +// // borderRadius: theme.shape.borderRadius, +// // }, +// // table: { +// // minWidth: 300, +// // width: '100%', +// // background: theme.palette.backgroundA.lightest, +// // }, +// // tableRow: { +// // // '&:nth-of-type(odd)': { +// // // background: theme.palette.backgroundA.light, +// // // }, +// // // '&:nth-of-type(even)': { +// // // background: theme.palette.backgroundA.lighter, +// // // }, +// // }, +// // tableCell: { +// // border: '2px solid', +// // borderColor: theme.palette.divider, +// // // background: theme.palette.backgroundA.light, + +// // [theme.breakpoints.down('sm')]: { +// // padding: theme.spacing(1), +// // fontSize: '0.7rem', +// // }, +// // [theme.breakpoints.up('md')]: { +// // padding: theme.spacing(2), +// // fontSize: '1rem', +// // }, +// // }, +// // tableHeader: { +// // background: theme.palette.backgroundA.lighter, +// // color: theme.palette.backgroundA.contrastTextA, +// // [theme.breakpoints.up('md')]: { +// // fontSize: '1rem', +// // }, +// // }, +// // tableBody: { +// // background: theme.palette.backgroundA.lightest, +// // border: '2px solid', +// // borderColor: theme.palette.divider, +// // }, +// // tableFooter: { +// // background: theme.palette.backgroundA.lighter, +// // }, +// // tablePriceBox: { +// // display: 'flex', +// // justifyContent: 'flex-end', +// // alignItems: 'center', +// // width: '100%', +// // padding: theme.spacing(2), +// // background: theme.palette.backgroundB.lighter, +// // }, +// // buttonGroup: { +// // display: 'flex', +// // flexDirection: 'column', +// // justifyContent: 'center', +// // alignItems: 'center', +// // boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', +// // }, +// // button: { +// // padding: '10px 20px', +// // border: 'none', +// // borderRadius: '5px', +// // cursor: 'pointer', +// // width: '100%', +// // color: theme.palette.getContrastText(theme.palette.backgroundA.dark), +// // backgroundColor: theme.palette.backgroundA.dark, +// // '&:hover': { +// // backgroundColor: theme.palette.backgroundA.darker, +// // }, +// // [theme.breakpoints.down('sm')]: { +// // fontSize: '0.8rem', +// // }, +// // [theme.breakpoints.up('md')]: { +// // fontSize: '1rem', +// // }, +// // }, +// // // Add any other styles from CardPortfolio, PortfolioContent, and SelectCollection components +// // })); + +// // export default usePortfolioStyles; diff --git a/src/assets/data/card_info.json b/src/data/card_info.json similarity index 100% rename from src/assets/data/card_info.json rename to src/data/card_info.json diff --git a/src/assets/data/card_sample.json b/src/data/card_sample.json similarity index 100% rename from src/assets/data/card_sample.json rename to src/data/card_sample.json diff --git a/src/data/iconData.jsx b/src/data/iconData.jsx new file mode 100644 index 0000000..6b8d7b7 --- /dev/null +++ b/src/data/iconData.jsx @@ -0,0 +1,220 @@ +import AddCircleOutlineOutlined from '@mui/icons-material/AddCircleOutlineOutlined'; +import RemoveCircleOutlineOutlined from '@mui/icons-material/RemoveCircleOutlineOutlined'; +import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'; +import { + FaDragon, + FaLevelUpAlt, + FaRegLightbulb, + FaShieldAlt, + FaVenusMars, +} from 'react-icons/fa'; +import AdjustSharpIcon from '@mui/icons-material/AdjustSharp'; +import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; +import { FaGithub, FaExternalLinkAlt } from 'react-icons/fa'; +import CloseIcon from '@mui/icons-material/Close'; +import LoginIcon from '@mui/icons-material/Login'; +import PersonAddIcon from '@mui/icons-material/PersonAdd'; +import SettingsIcon from '@mui/icons-material/Settings'; +import SaveIcon from '@mui/icons-material/Save'; +import AddIcon from '@mui/icons-material/Add'; + +import LockIcon from '@mui/icons-material/Lock'; +import SearchIcon from '@mui/icons-material/Search'; +import DeleteIcon from '@mui/icons-material/Delete'; +import MonetizationOnIcon from '@mui/icons-material/MonetizationOn'; +import StackedLineChartRoundedIcon from '@mui/icons-material/StackedLineChartRounded'; +import FormatListNumberedRoundedIcon from '@mui/icons-material/FormatListNumberedRounded'; +import TrendingUpIcon from '@mui/icons-material/TrendingUp'; +import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import CollectionsIcon from '@mui/icons-material/Collections'; +import { KeyboardArrowLeft, KeyboardArrowRight } from '@mui/icons-material'; +import AppsIcon from '@mui/icons-material/Apps'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import EditIcon from '@mui/icons-material/Edit'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import BarChartIcon from '@mui/icons-material/BarChart'; +import SelectAllIcon from '@mui/icons-material/SelectAll'; +import MenuIcon from '@mui/icons-material/Menu'; +import ArrowDropUpIcon from '@mui/icons-material/ArrowDropUp'; +import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; + +const iconData = [ + { + id: 1, + icon: , + component: 'ReusableLoadingButton', + }, + { + id: 2, + icon: , + component: 'AddCircleOutlineOutlined', + }, + { + id: 3, + icon: , + component: 'RemoveCircleOutlineOutlined', + }, + { + id: 4, + icon: , + component: 'CheckCircleOutlineOutlinedIcon', + }, + { + id: 5, + icon: , + component: 'FaDragon', + }, + { + id: 6, + icon: , + component: 'FaLevelUpAlt', + }, + { + id: 7, + icon: , + component: 'FaRegLightbulb', + }, + { + id: 8, + icon: , + component: 'FaShieldAlt', + }, + { + id: 9, + icon: , + component: 'FaVenusMars', + }, + { + id: 10, + icon: , + component: 'LockOutlinedIcon', + }, + { + id: 11, + icon: , + component: 'FaGithub', + }, + { + id: 12, + icon: , + component: 'FaExternalLinkAlt', + }, + { + id: 13, + icon: , + component: 'CloseIcon', + }, + { + id: 14, + icon: , + component: 'LoginIcon', + }, + { + id: 15, + icon: , + component: 'PersonAddIcon', + }, + { + id: 16, + icon: , + component: 'AddIcon', + }, + { + id: 17, + icon: , + component: 'SettingsIcon', + }, + { + id: 18, + icon: , + component: 'SaveIcon', + }, + { + id: 19, + icon: , + component: 'LockIcon', + }, + { + id: 20, + icon: , + component: 'SearchIcon', + }, + { + id: 21, + icon: , + component: 'DeleteIcon', + }, + { + id: 22, + icon: , + component: 'MonetizationOnIcon', + }, + { + id: 23, + icon: , + component: 'StackedLineChartRoundedIcon', + }, + { + id: 24, + icon: , + component: 'FormatListNumberedRoundedIcon', + }, + { + id: 25, + icon: , + component: 'TrendingUpIcon', + }, + { + id: 26, + icon: , + component: 'ArrowBackIcon', + }, + { + id: 27, + icon: , + component: 'CollectionsIcon', + }, + { + id: 28, + icon: , + component: 'KeyboardArrowLeft', + }, + { + id: 29, + icon: , + component: 'KeyboardArrowRight', + }, + { + id: 30, + icon: , + component: 'AppsIcon', + }, + { + id: 31, + icon: , + component: 'MoreVertIcon', + }, + { + id: 32, + icon: , + component: 'ListItemIcon', + }, + { + id: 33, + icon: , + component: 'EditIcon', + }, + { + id: 34, + icon: , + component: 'VisibilityIcon', + }, + { + id: 35, + icon: , + component: 'BarChartIcon', + }, +]; + +export default iconData; diff --git a/src/assets/data/pages.json b/src/data/pages.json similarity index 100% rename from src/assets/data/pages.json rename to src/data/pages.json diff --git a/src/layout/REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection.jsx b/src/layout/REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection.jsx index 529d14a..29f541b 100644 --- a/src/layout/REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection.jsx +++ b/src/layout/REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection.jsx @@ -1,124 +1,3 @@ -// // import { ButtonBase, Typography } from '@mui/material'; -// // import { Link, useNavigate } from 'react-router-dom'; -// // import config from '../../../config'; -// // import DeckOfCardsIcon from '../../../components/reusable/icons/DeckOfCardsIcon'; - -// // // ==============================|| MAIN LOGO ||============================== // - -// // const RCLogoSection = () => { -// // const navigate = useNavigate(); - -// // const handleClick = () => { -// // navigate(config?.defaultPath); -// // }; - -// // return ( -// // -// // Logo -// // -// // DeckMaster -// // -// // -// // ); -// // }; - -// // export default RCLogoSection; -// import React from 'react'; -// import { ButtonBase, Typography } from '@mui/material'; -// import { Link, useNavigate } from 'react-router-dom'; -// import config from '../../../config'; -// import DeckBuilderIcon from '../../../components/reusable/icons/DeckBuilderIcon'; // Import DeckBuilderIcon - -// // ==============================|| MAIN LOGO ||============================== // - -// const RCLogoSection = () => { -// const navigate = useNavigate(); - -// const handleClick = () => { -// navigate(config?.defaultPath); -// }; - -// return ( -// -// {/* Render DeckBuilderIcon here */} -// -// -// DeckMaster -// -// -// ); -// }; - -// export default RCLogoSection; import React from 'react'; import { ButtonBase, Typography, Avatar } from '@mui/material'; import { Link, useNavigate } from 'react-router-dom'; diff --git a/src/layout/REUSABLE_COMPONENTS/SkeletonVariants.jsx b/src/layout/REUSABLE_COMPONENTS/SkeletonVariants.jsx index 2b8a154..21d9cad 100644 --- a/src/layout/REUSABLE_COMPONENTS/SkeletonVariants.jsx +++ b/src/layout/REUSABLE_COMPONENTS/SkeletonVariants.jsx @@ -1,9 +1,45 @@ import React from 'react'; -import { Box } from '@mui/material'; -import { useMode } from '../../context'; +import { + Box, + Card, + CardHeader, + CardContent, + makeStyles, + Skeleton, +} from '@mui/material'; import useSkeletonLoader from '../collection/collectionGrids/cards-datatable/useSkeletonLoader'; +function LoadingCardSkeleton() { + return ( + + } + subheader={} + avatar={} + /> + + + + + + ); +} + const HeroSectionSkeleton = () => { + // Assuming useSkeletonLoader provides a loader component that accepts type, count, and styleProps const { SkeletonLoader } = useSkeletonLoader(); return ( @@ -28,7 +64,7 @@ const HeroSectionSkeleton = () => { '-webkit-backdrop-filter': 'blur(20px)', border: '1px solid rgba(255, 255, 255, 0.3)', borderRadius: '25px', - padding: '30px 0px', + padding: '30px', width: 'min(1200px, 100%)', display: 'flex', flexDirection: 'column', @@ -36,21 +72,16 @@ const HeroSectionSkeleton = () => { justifyContent: 'center', }} > - {/* Title Skeleton */} - - {/* Subtitle Skeleton */} - - {/* Image Slider Skeleton */} { ); }; -export default HeroSectionSkeleton; +export { LoadingCardSkeleton, HeroSectionSkeleton }; diff --git a/src/layout/REUSABLE_COMPONENTS/StatBox.jsx b/src/layout/REUSABLE_COMPONENTS/StatBox.jsx index bd1bbd7..6eeb582 100644 --- a/src/layout/REUSABLE_COMPONENTS/StatBox.jsx +++ b/src/layout/REUSABLE_COMPONENTS/StatBox.jsx @@ -1,9 +1,9 @@ -import { Box, Typography, useTheme } from '@mui/material'; +import { Box, Card, CardContent, Typography, useTheme } from '@mui/material'; import ProgressCircle from './ProgressCircle'; import { useMode } from '../../context'; import MDBox from './MDBOX'; -const StatBox = ({ title, subtitle, icon, progress, increase }) => { +const StatBox = ({ title, subtitle, icon, progress, increase, wrapIcon }) => { const { theme } = useMode(); const colors = theme.palette.chartTheme; const primary = colors.primary.default; @@ -11,7 +11,21 @@ const StatBox = ({ title, subtitle, icon, progress, increase }) => { const green = colors.greenAccent.default; const greenliht = colors.greenAccent.light; const grey = colors.grey.default; - + const IconWrapper = ({ children }) => ( + + {children} + + ); return ( { borderRadius: theme.spacing(4), }} > - - {icon} + {/* */} + {/* */} + + + {icon} + + {title} - + {/* */} + + {/* */} + {/* */} {/* */} diff --git a/src/layout/REUSABLE_COMPONENTS/unique/SimpleCard.jsx b/src/layout/REUSABLE_COMPONENTS/unique/SimpleCard.jsx index 8db36a9..a6731ff 100644 --- a/src/layout/REUSABLE_COMPONENTS/unique/SimpleCard.jsx +++ b/src/layout/REUSABLE_COMPONENTS/unique/SimpleCard.jsx @@ -1,37 +1,15 @@ import React from 'react'; import MDTypography from '../MDTYPOGRAPHY/MDTypography'; import styled from 'styled-components'; -// const CardContainer = styled.div` -// padding: ${({ theme, hasTitle }) => (hasTitle ? 0 : theme.lenMd3)}; -// margin-bottom: ${({ theme, noBottomMargin }) => -// noBottomMargin ? 0 : theme.lenMd1}; -// border-radius: ${({ theme }) => theme.borderRadius}; -// background: ${({ theme, isPrimary, isAccent }) => -// isPrimary -// ? theme.colorPrimary -// : isAccent -// ? theme.colorAccent -// : theme.colorCardBackground}; -// color: ${({ theme, isPrimary, isAccent }) => -// isPrimary -// ? theme.colorPrimaryText -// : isAccent -// ? theme.colorAccentText -// : theme.colorText}; -// `; -// const Content = styled.div` -// padding: ${({ theme }) => `0 ${theme.lenMd3} ${theme.lenMd3}`}; -// `; +import { CardContent, IconButton, Typography } from '@mui/joy'; +import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'; +import { useMode } from '../../../context'; +import { Icon } from '@mui/material'; +import MDBox from '../MDBOX'; +import SaveIcon from '@mui/icons-material/Save'; +import AddIcon from '@mui/icons-material/Add'; +import CollectionsIcon from '@mui/icons-material/Collections'; -// const Title = styled.div` -// display: flex; -// align-items: center; -// justify-content: center; -// height: ${({ theme }) => theme.lenXl2}; -// padding: ${({ theme }) => `0 ${theme.lenMd1}`}; -// color: ${({ theme }) => theme.colorLabel}; -// font-size: ${({ theme }) => theme.lenMd2}; -// `; const getPrimaryStyle = (theme, isPrimary) => ({ background: isPrimary ? theme.colorPrimary : undefined, color: isPrimary ? theme.colorPrimaryText : undefined, @@ -58,9 +36,23 @@ const getFormHeaderStyle = (theme, isFormHeader) => ({ width: '80%', }); -const CardContent = ({ theme, children }) => ( -
{children}
-); +const getHeroDisplayStyles = (theme, isHeroDisplay) => ({ + background: isHeroDisplay ? theme.colorCardBackground : undefined, + color: isHeroDisplay ? theme.colorPrimary : undefined, + root: { + minWidth: 275, + backgroundColor: 'rgba(255,255,255,0.4)', + backgroundImage: + 'linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%)', + backdropFilter: 'blur(40)px', + boxShadow: '10px 10px 10px rgba(30,30,30,.1)', + borderRadius: 10, + }, +}); + +// const CardContent = ({ theme, children }) => ( +//
{children}
+// ); const CardTitle = ({ theme, children, isTableOrChart }) => (
(
); +const iconStyles = { + // Adjust icon size to be larger based on the parent size + fontSize: '8rem', // Example size, adjust as needed + color: '#000000', // Example color, adjust as needed + maxWidth: '100%', + maxHeight: '100%', +}; +const String2Icon = (icon) => { + switch (icon) { + case 'AddIcon': + return ; + case 'SaveIcon': + return ; + case 'CollectionsIcon': + return ; + default: + return null; + } +}; const SimpleCard = ({ theme, @@ -97,8 +108,12 @@ const SimpleCard = ({ cardTitle, data, isFormHeader, + isHeroDisplay, + heroText, + heroIcon, ...rest }) => { + const { theme: themeSettings } = useMode(); const cardStyle = { // display: 'flex', width: '100%', @@ -107,6 +122,8 @@ const SimpleCard = ({ borderRadius: theme.borderRadius, background: theme.colorCardBackground, color: theme.colorText, + ...(isHeroDisplay && getHeroDisplayStyles(theme, true)), + ...(isFormHeader && getFormHeaderStyle(theme, true)), ...(isTableOrChart && getTableOrChartStyle(theme, true)), ...(isPrimary && getPrimaryStyle(theme, true)), @@ -120,10 +137,92 @@ const SimpleCard = ({ {cardTitle} - {children} +
+ {children} +
)} {!cardTitle && children} + {isHeroDisplay && ( + + + + + {String2Icon(heroIcon)} + + + + + + + + + {heroText} + + + + )} ); }; diff --git a/src/layout/collection/collectionGrids/ChartGridLayout.jsx b/src/layout/collection/collectionGrids/ChartGridLayout.jsx index 836e641..8b052a1 100644 --- a/src/layout/collection/collectionGrids/ChartGridLayout.jsx +++ b/src/layout/collection/collectionGrids/ChartGridLayout.jsx @@ -132,7 +132,6 @@ const ChartGridLayout = ({ selectedCards, removeCard, columns, data }) => { alignItems: 'center', justifyContent: 'center', backgroundColor: theme.palette.success.main, - marginRight: theme.spacing(1), }} > {children} diff --git a/src/layout/collection/collectionGrids/cards-chart/ChartConfigs.jsx b/src/layout/collection/collectionGrids/cards-chart/ChartConfigs.jsx index 5f07ba5..89be8b5 100644 --- a/src/layout/collection/collectionGrids/cards-chart/ChartConfigs.jsx +++ b/src/layout/collection/collectionGrids/cards-chart/ChartConfigs.jsx @@ -122,11 +122,18 @@ export const ChartConfiguration = ({ }, yScale: { type: 'linear', - min: 'auto', - max: 'auto', - stacked: true, + min: '0', // Explicitly setting minimum to 0, adjust as needed + max: 'auto', // Consider setting an explicit max if appropriate + stacked: false, // Changed to false unless stacking is needed reverse: false, }, + // yScale: { + // type: 'linear', + // min: 'auto', + // max: 'auto', + // stacked: true, + // reverse: false, + // }, curve: 'catmullRom', // This curve type can create smoother, more wavy lines motionConfig: 'wobbly', // A more dynamic motion configuration useMesh: true, stiffness: 90, @@ -172,7 +179,10 @@ export const ChartConfiguration = ({ }, legend: { text: { - fill: theme.palette.chartTheme.grey.lightest, + fill: theme.palette.chartTheme.greenAccent.darkest, + fontSize: 12, + outlineWidth: 0.1, + outlineColor: theme.palette.chartTheme.grey.darkest, }, }, ticks: { @@ -192,7 +202,8 @@ export const ChartConfiguration = ({ }, tooltip: { container: { - color: theme.palette.chartTheme.primary.default, + color: theme.palette.chartTheme.grey.darkest, + borderColor: theme.palette.chartTheme.redAccent.darkest, }, }, }, diff --git a/src/layout/collection/collectionGrids/cards-datatable/DataTableHeadCell.jsx b/src/layout/collection/collectionGrids/cards-datatable/DataTableHeadCell.jsx index f987f95..ecec2ae 100644 --- a/src/layout/collection/collectionGrids/cards-datatable/DataTableHeadCell.jsx +++ b/src/layout/collection/collectionGrids/cards-datatable/DataTableHeadCell.jsx @@ -1,101 +1,3 @@ -// import PropTypes from 'prop-types'; -// import Icon from '@mui/material/Icon'; -// import MDBox from '../../../REUSABLE_COMPONENTS/MDBOX'; -// import { useMode } from '../../../../context'; -// import MDTypography from '../../../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; - -// function DataTableHeadCell({ width, children, sorted, align, ...rest }) { -// const { theme } = useMode(); -// return ( -// -// -// -// -// {children} -// -// {sorted && ( -// -// -// arrow_drop_up -// -// -// arrow_drop_down -// -// -// )} -// -// -// -// ); -// } - -// DataTableHeadCell.defaultProps = { -// width: 'auto', -// sorted: 'none', -// align: 'left', -// }; - -// DataTableHeadCell.propTypes = { -// width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), -// children: PropTypes.node.isRequired, -// sorted: PropTypes.oneOf([false, 'none', 'asce', 'desc']), -// align: PropTypes.oneOf(['left', 'right', 'center']), -// }; - -// export default DataTableHeadCell; import { useMemo } from 'react'; import PropTypes from 'prop-types'; import { TableRow, Checkbox, Icon } from '@mui/material'; diff --git a/src/layout/collection/collectionGrids/collections-list/CollectionListItem.jsx b/src/layout/collection/collectionGrids/collections-list/CollectionListItem.jsx index 25de751..45ec397 100644 --- a/src/layout/collection/collectionGrids/collections-list/CollectionListItem.jsx +++ b/src/layout/collection/collectionGrids/collections-list/CollectionListItem.jsx @@ -1,213 +1,3 @@ -// import React, { memo, useCallback, useRef } from 'react'; -// import { -// Box, -// Card, -// CardActionArea, -// CardContent, -// Grid, -// Tooltip, -// } from '@mui/material'; -// import PropTypes from 'prop-types'; -// import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward'; -// import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; -// import useCollectionManager from '../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionManager'; -// import MDBox from '../../../../layout/REUSABLE_COMPONENTS/MDBOX'; -// import MDTypography from '../../../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -// import LongMenu from '../../../../layout/navigation/LongMenu'; -// import useDialogState from '../../../../context/hooks/useDialogState'; -// import CollectionDialog from '../../../../components/dialogs/CollectionDialog'; -// import useSelectedCollection from '../../../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; -// import { useMode, useVisibilityContext } from '../../../../context'; - -// const CollectionInfoItem = ({ label, value, theme }) => ( -// -// -// -// {label}: -// -// -// {value} -// -// -// -// ); - -// const CollectionListItem = memo(({ collection }) => { -// const { theme } = useMode(); -// const { deleteCollection } = useCollectionManager(); -// const { handleSelectCollection } = useSelectedCollection(); -// const { toggleCollectionVisibility } = useVisibilityContext(); -// const { dialogState, openDialog, closeDialog } = useDialogState({ -// isEditCollectionDialogOpen: false, -// }); - -// const handleOpenDialog = useCallback(() => { -// openDialog('editCollectionDialog', collection); -// }, [collection, openDialog]); - -// const handleCloseDialog = useCallback(() => { -// closeDialog('editCollectionDialog'); -// }, [closeDialog]); - -// const handleDelete = async () => { -// await deleteCollection(collection._id); -// }; - -// const renderToolTip = () => ( -// -//
-// handleSelectCollection(collection)} -// collectionId={collection._id} -// /> -//
-//
-// ); - -// const renderPercentageChange = () => { -// const percentageChange = -// collection.collectionStatistics?.percentageChange || 0; -// return ( -// 0 ? 'success' : 'error'} -// sx={{ -// display: 'flex', -// alignItems: 'center', -// justifyContent: 'center', -// fontSize: '1.5rem', // Triple the label size -// }} -// > -// {percentageChange > 0 ? : } -// {percentageChange}% -// -// ); -// }; - -// const handleSelection = useCallback(() => { -// handleSelectCollection(collection); -// toggleCollectionVisibility(); -// }, [collection, handleSelectCollection, toggleCollectionVisibility]); - -// return ( -// -// -// -// -// -// -// -// -// {renderPercentageChange()} -// -// -// -// -// {renderToolTip()} -// -// -// {dialogState.isEditCollectionDialogOpen && ( -// -// )} -// -// ); -// }); - -// CollectionListItem.displayName = 'CollectionListItem'; - -// CollectionListItem.propTypes = { -// collection: PropTypes.object.isRequired, -// }; - -// export default CollectionListItem; import React, { memo, useCallback } from 'react'; import { Box, diff --git a/src/layout/collection/collectionGrids/collections-list/StatBoard.jsx b/src/layout/collection/collectionGrids/collections-list/StatBoard.jsx index b9709db..5260fd0 100644 --- a/src/layout/collection/collectionGrids/collections-list/StatBoard.jsx +++ b/src/layout/collection/collectionGrids/collections-list/StatBoard.jsx @@ -12,6 +12,7 @@ import PricedCardList from './statItems/PricedCardList'; import PerformanceStatBox from './statItems/PerformanceStatBox'; import MDBox from '../../../REUSABLE_COMPONENTS/MDBOX'; import styled from 'styled-components'; +import TotalCardsCollectedStatBox from './statItems/TotalCardsCollectedStatBox'; const SkeletonPieChart = ({ theme }) => ( { const { theme } = useMode(); return ( - + ); diff --git a/src/layout/collection/collectionGrids/collections-list/statItems/PerformanceStatBox.jsx b/src/layout/collection/collectionGrids/collections-list/statItems/PerformanceStatBox.jsx index 91cd984..d2181f0 100644 --- a/src/layout/collection/collectionGrids/collections-list/statItems/PerformanceStatBox.jsx +++ b/src/layout/collection/collectionGrids/collections-list/statItems/PerformanceStatBox.jsx @@ -1,50 +1,11 @@ -// import MonetizationOnIcon from '@mui/icons-material/MonetizationOn'; -// import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; -// import { useMode } from '../../../../../context'; -// import { Box } from '@mui/material'; -// import StatBox from '../../../../REUSABLE_COMPONENTS/StatBox'; - -// const TotalPriceStatBox = ({ sx }) => { -// const { collectionStats, metaStats } = useCollectionStats(); -// const { theme } = useMode(); -// const colors = theme.palette.chartTheme; -// const primary = colors.primary.dark; -// const greenAccent = colors.greenAccent.light; -// return ( -// -// -// } -// /> -// -// ); -// }; - -// export default TotalPriceStatBox; import { Box, Typography } from '@mui/material'; import StatBox from '../../../../REUSABLE_COMPONENTS/StatBox'; import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; -import { useMode } from '../../../../../context'; +import { useAppContext, useMode } from '../../../../../context'; import MonetizationOnIcon from '@mui/icons-material/MonetizationOn'; import ProgressCircle from '../../../../REUSABLE_COMPONENTS/ProgressCircle'; import MDBox from '../../../../REUSABLE_COMPONENTS/MDBOX'; - +import StackedLineChartRoundedIcon from '@mui/icons-material/StackedLineChartRounded'; const PerformanceStatBox = () => { const { theme } = useMode(); const colors = theme.palette.chartTheme; @@ -56,6 +17,8 @@ const PerformanceStatBox = () => { const greenliht = colors.greenAccent.light; const grey = colors.grey.default; + const { collectionMetaData } = useAppContext(); + return ( { > + } /> diff --git a/src/layout/collection/collectionGrids/collections-list/statItems/TotalCardsCollectedStatBox.jsx b/src/layout/collection/collectionGrids/collections-list/statItems/TotalCardsCollectedStatBox.jsx new file mode 100644 index 0000000..ee03550 --- /dev/null +++ b/src/layout/collection/collectionGrids/collections-list/statItems/TotalCardsCollectedStatBox.jsx @@ -0,0 +1,42 @@ +import { Box } from '@mui/material'; +import StatBox from '../../../../REUSABLE_COMPONENTS/StatBox'; +import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; +import { useAppContext, useMode } from '../../../../../context'; +import styled from 'styled-components'; +import FormatListNumberedRoundedIcon from '@mui/icons-material/FormatListNumberedRounded'; +const TotalCardsCollectedStatBox = () => { + const { theme } = useMode(); + const colors = theme.palette.chartTheme; + const primary = colors.primary.dark; + const greenAccent = colors.greenAccent.light; + const grey = colors.grey.dark; + const { collectionMetaData } = useAppContext(); + return ( + + + } + /> + + ); +}; + +export default TotalCardsCollectedStatBox; diff --git a/src/layout/collection/collectionGrids/collections-list/statItems/TotalPriceStatBox.jsx b/src/layout/collection/collectionGrids/collections-list/statItems/TotalPriceStatBox.jsx index 39b2d3b..03c486a 100644 --- a/src/layout/collection/collectionGrids/collections-list/statItems/TotalPriceStatBox.jsx +++ b/src/layout/collection/collectionGrids/collections-list/statItems/TotalPriceStatBox.jsx @@ -1,16 +1,20 @@ import { Box } from '@mui/material'; import StatBox from '../../../../REUSABLE_COMPONENTS/StatBox'; import useCollectionStats from '../../../../../context/MAIN_CONTEXT/CollectionContext/useCollectionStats'; -import { useMode } from '../../../../../context'; +import { useAppContext, useMode } from '../../../../../context'; import MonetizationOnIcon from '@mui/icons-material/MonetizationOn'; import styled from 'styled-components'; -import RCIcon from '../../../../REUSABLE_COMPONENTS/RCICON/RCIcon'; const TotalPriceStatBox = () => { const { theme } = useMode(); const colors = theme.palette.chartTheme; const primary = colors.primary.dark; const greenAccent = colors.greenAccent.light; + const grey = colors.grey.dark; + + const { collectionMetaData } = useAppContext(); + const roundToNearestTenth = (num) => Math.round(num * 10) / 10; + return ( { }} > - - // - } + wrapIcon={false} + icon={} /> ); diff --git a/src/layout/navigation/Navigation.jsx b/src/layout/navigation/Navigation.jsx index 3f2d2e1..65255e2 100644 --- a/src/layout/navigation/Navigation.jsx +++ b/src/layout/navigation/Navigation.jsx @@ -1,28 +1,39 @@ import React, { useState, useEffect, useCallback } from 'react'; import { - AppBar, Toolbar, IconButton, - Box, - Drawer, List, Hidden, - Card, - CardContent, ListItem, - ListItemIcon, - Avatar, - ListItemAvatar, ListItemText, + AppBar, } from '@mui/material'; import MenuIcon from '@mui/icons-material/Menu'; -import { useCartStore, useMode, useSidebarContext } from '../../context'; -import { StyledAppBar } from '../../pages/pageStyles/StyledComponents'; +import { + useAuthContext, + useCartStore, + useMode, + useSidebarContext, +} from '../../context'; import { Navigate, useNavigate } from 'react-router-dom'; import getMenuItemsData from './menuItemsData'; import { useSpring, animated, useSprings } from 'react-spring'; import MDTypography from '../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; import RCLogoSection from '../REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection'; +import { + Avatar, + Box, + Card, + CardContent, + DialogTitle, + Divider, + Drawer, + ModalClose, + Radio, + Sheet, + Typography, +} from '@mui/joy'; +import { useCookies } from 'react-cookie'; const Navigation = ({ isLoggedIn }) => { const { theme } = useMode(); const navigate = useNavigate(); @@ -33,6 +44,9 @@ const Navigation = ({ isLoggedIn }) => { const [isOpen, setIsOpen] = useState(false); // Manage open state locally const [isMobileView, setIsMobileView] = useState(window.innerWidth < 768); const iconColor = isMobileView ? theme.palette.primary.main : 'white'; + const [cookies] = useCookies('authUser'); + const username = cookies?.authUser?.username; + // const { authUser } = useAuthContext(); useEffect(() => { const fetchData = async () => { @@ -41,7 +55,7 @@ const Navigation = ({ isLoggedIn }) => { totalQuantity, iconColor ); - setMenuItems(items.map((item) => ({ ...item, isVisible: true }))); + setMenuItems(items?.map((item) => ({ ...item, isVisible: true }))); }; fetchData(); @@ -69,49 +83,62 @@ const Navigation = ({ isLoggedIn }) => { // disablePadding onClick={() => navigate(menuItems[index].to)} sx={{ - width: 'clamp(130px, 50%, 175px)', // Responsive width using clamp + // width: 'clamp(130px, 50%, 175px)', // Responsive width using clamp maxHeight: 64, - mx: theme.spacing(4), + maxWidth: '100%', + // mx: theme.spacing(4), '&:hover': { backgroundColor: theme.palette.backgroundF.light, color: 'white', }, }} > - - {menuItems[index].icon}{' '} - - - {menuItems[index].name} - - } - /> + + {menuItems[index].icon} + {menuItems[index].name} + + )); return ( <> - { alignItems: 'center', }} > - {isMobileView ? ( - - + + + + + + {renderMenuItems('top')} + + + - - - - - ) : ( - renderMenuItems('top') - )} + + {username} + + + - - - + {/* */} + + + Filters + + {renderMenuItems('side')} - - + + + {/* */} ); }; diff --git a/src/layout/navigation/menuItemsData.jsx b/src/layout/navigation/menuItemsData.jsx index 014aeee..243524e 100644 --- a/src/layout/navigation/menuItemsData.jsx +++ b/src/layout/navigation/menuItemsData.jsx @@ -15,7 +15,7 @@ export const getMenuItemsData = (isLoggedIn, cartCardQuantity, iconColor) => { const baseMenuItems = [ { name: 'Home', icon: , to: '/home', requiresLogin: false }, { - name: 'Deck Builder', + name: 'Deck', // icon: , icon: , to: '/deckbuilder', @@ -68,6 +68,12 @@ export const getMenuItemsData = (isLoggedIn, cartCardQuantity, iconColor) => { to: '/profile', requiresLogin: isLoggedIn, }, + // { + // name: 'Login', + // icon: , + // to: '/login', + // requiresLogin: false, + // }, ]; if (isLoggedIn) { diff --git a/src/layout/profile/ProfileSection.js b/src/layout/profile/ProfileSection.js index eac6940..1727666 100644 --- a/src/layout/profile/ProfileSection.js +++ b/src/layout/profile/ProfileSection.js @@ -1,6 +1,4 @@ import { useState, useRef, useEffect } from 'react'; - -// material-ui import { Avatar, Box, @@ -22,10 +20,7 @@ import { Switch, Typography, } from '@mui/material'; - -// third-party import PerfectScrollbar from 'react-perfect-scrollbar'; - import { useNavigate } from 'react-router-dom'; import { useAuthContext, useMode } from '../../context'; import Transitions from '../Transitions'; diff --git a/src/layout/profile/sub-components/DefaultInfoCard.jsx b/src/layout/profile/sub-components/DefaultInfoCard.jsx index 86538f0..33fb48a 100644 --- a/src/layout/profile/sub-components/DefaultInfoCard.jsx +++ b/src/layout/profile/sub-components/DefaultInfoCard.jsx @@ -1,30 +1,10 @@ -/** -========================================================= -* Material Dashboard 2 React - v2.1.0 -========================================================= - -* Product Page: https://www.creative-tim.com/product/material-dashboard-react -* Copyright 2022 Creative Tim (https://www.creative-tim.com) - -Coded by www.creative-tim.com - - ========================================================= - -* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -*/ - -// prop-types is library for typechecking of props import PropTypes from 'prop-types'; - -// @mui material components import Card from '@mui/material/Card'; import Divider from '@mui/material/Divider'; import Icon from '@mui/material/Icon'; import MDBox from '../../REUSABLE_COMPONENTS/MDBOX'; import MDTypography from '../../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -// Material Dashboard 2 React components - function DefaultInfoCard({ color, icon, title, description, value }) { return ( diff --git a/src/pages/pageStyles/StyledComponents.jsx b/src/pages/pageStyles/StyledComponents.jsx index bad5dac..4114d43 100644 --- a/src/pages/pageStyles/StyledComponents.jsx +++ b/src/pages/pageStyles/StyledComponents.jsx @@ -61,8 +61,9 @@ export const StyledAppBar = styled(AppBar)(({ theme }) => ({ border: '2px solid white', // left: -20, // borderRadius: '30px', - background: - 'linear-gradient(90deg, rgba(13, 93, 150, 1) 0%, rgba(160, 214, 186, 1) 100%);', // Subtle blue to green gradient + background: '#141414', + // background: + // 'linear-gradient(90deg, rgba(13, 93, 150, 1) 0%, rgba(160, 214, 186, 1) 100%);', // Subtle blue to green gradient })); export const StyledToolBarContainer = styled(AppBar)(({ theme }) => ({ // display: 'flex', @@ -71,7 +72,7 @@ export const StyledToolBarContainer = styled(AppBar)(({ theme }) => ({ // alignItems: 'center', // width: '100%', // Do not explicitly set the height here to allow Toolbar's default styling to take effect - backgroundColor: theme.palette.backgroundA.darker, + // backgroundColor: theme.palette.backgroundA.darker, // borderRadius: '30px', flexGrow: 1, diff --git a/src/pages/sections/FeatureCardsSection.jsx b/src/pages/sections/FeatureCardsSection.jsx index 3d78cfc..7597a0e 100644 --- a/src/pages/sections/FeatureCardsSection.jsx +++ b/src/pages/sections/FeatureCardsSection.jsx @@ -1,13 +1,10 @@ import React from 'react'; import { Grid } from '@mui/material'; -import { useTheme } from '@mui/system'; import { useMediaQuery } from '@mui/material'; - import { AnimatedFeatureCard } from '../../layout/AnimatedFeatureCard'; import { useModalContext } from '../../context/UTILITIES_CONTEXT/ModalContext/ModalContext'; -import { useResponsiveStyles } from '../../context/hooks/style-hooks/useResponsiveStyles'; import { useMode } from '../../context'; -import pages from '../../assets/data/pages.json'; +import pages from '../../data/pages.json'; import { StyledContainerBox, StyledPaper, diff --git a/src/pages/sections/HeroSection.jsx b/src/pages/sections/HeroSection.jsx index 75a0cc4..e9a1d4f 100644 --- a/src/pages/sections/HeroSection.jsx +++ b/src/pages/sections/HeroSection.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { useMode, useStatisticsStore } from '../../context'; import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; import placeHolder from '../../assets/images/placeholder.jpeg'; @@ -14,17 +14,26 @@ import { Autoplay, } from 'swiper/modules'; import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; -import HeroSectionSkeleton from '../../layout/REUSABLE_COMPONENTS/SkeletonVariants'; +import { HeroSectionSkeleton } from '../../layout/REUSABLE_COMPONENTS/SkeletonVariants'; import { Box, Card, + Container, Grid, + Icon, IconButton, Typography, + Zoom, useMediaQuery, } from '@mui/material'; import DashboardBox from '../../layout/REUSABLE_COMPONENTS/DashboardBox'; import AttachMoneyIcon from '@mui/icons-material/AttachMoney'; +import SimpleCard from '../../layout/REUSABLE_COMPONENTS/unique/SimpleCard'; +import uniqueTheme from '../../layout/REUSABLE_COMPONENTS/unique/uniqueTheme'; +import SaveIcon from '@mui/icons-material/Save'; +import AddIcon from '@mui/icons-material/Add'; +import CollectionsIcon from '@mui/icons-material/Collections'; +import pages from '../../data/pages.json'; // Replace headerItems with realistic card store data const storeInfoItems = [ @@ -57,9 +66,13 @@ const StoreInfoItem = ({ icon, label, value, delay }) => { const HeroSection = () => { const { theme } = useMode(); const { breakpoints } = theme; + const { introText } = pages; const isMobileView = useMediaQuery(breakpoints.down('sm')); const isFullView = useMediaQuery(breakpoints.up('lg')); const [activeCardIndex, setActiveCardIndex] = useState(0); + const [shouldShow, setShouldShow] = useState(false); + useEffect(() => setShouldShow(true), []); + const { topFiveCards } = useStatisticsStore(); const defaultCards = new Array(45).fill({}).map((_, index) => ({ id: `default-${index}`, @@ -69,6 +82,36 @@ const HeroSection = () => { })); const cards = [...topFiveCards, ...defaultCards]; const handleSlideChange = (swiper) => setActiveCardIndex(swiper.realIndex); + const heroCardData = [ + { + id: 'herodata-1-store-add', + name: 'Add Cards From Store', + description: 'Add cards to your collection from the store.', + heroText: 'ADD', + icon: , + heroIcon: 'AddIcon', + image: placeHolder, + }, + { + id: 'herodata-2-deck-build', + name: 'Build Decks In Deck Builder', + description: 'Build decks using the deck builder.', + heroText: 'BUILD', + icon: , + heroIcon: 'SaveIcon', + image: placeHolder, + }, + { + id: 'herodata-3-collection-view', + name: 'Track Collection Value in Portfolio', + description: + 'View and analyze your portfolio performance using the Portfolios advanced statistics settings.', + heroText: 'TRACK', + icon: , + heroIcon: 'CollectionsIcon', + image: placeHolder, + }, + ]; if (!cards || !Array.isArray(cards) || !cards[activeCardIndex]) { return ; @@ -105,15 +148,16 @@ const HeroSection = () => { backgroundColor: 'transparent', // Make the Card background transparent }} > - - { alignItems: 'center', padding: 1, width: '100%', + // borderRadius: 'none', }} > - - - - - {storeInfoItems.map((item, index) => ( - + + + A New Era of Trading Card Games + + + Discover a revolutionary way to collect, play, and compete + in your favorite trading card games. Embrace a world where + strategy and creativity transcend boundaries. + + + + + + + {heroCardData?.map((card, index) => ( + + - ))} - - - + + ))} + +
From f3eca290a74e067c79a1aab07e73c09f6a003754 Mon Sep 17 00:00:00 2001 From: Reed Vogt Date: Tue, 19 Mar 2024 17:39:51 -0700 Subject: [PATCH 07/10] hero and navigation edits completed --- src/assets/css/index.css | 10 +- .../MAIN_CONTEXT/UserContext/UserContext.js | 24 +- src/data/baseMenuItems.jsx | 13 +- .../RCLOGOSECTION/RCLogoSection.jsx | 14 +- .../REUSABLE_COMPONENTS/unique/SimpleCard.jsx | 13 +- src/layout/navigation/Navigation.jsx | 220 +++++++------ src/layout/navigation/menuItemsData.jsx | 233 +++++++------ src/pages/sections/HeroIconSection.jsx | 91 ++++++ src/pages/sections/HeroSection.jsx | 305 ++++-------------- src/pages/sections/HeroSwiper.jsx | 138 ++++++++ src/pages/sections/HeroTextSection.jsx | 68 ++++ 11 files changed, 650 insertions(+), 479 deletions(-) create mode 100644 src/pages/sections/HeroIconSection.jsx create mode 100644 src/pages/sections/HeroSwiper.jsx create mode 100644 src/pages/sections/HeroTextSection.jsx diff --git a/src/assets/css/index.css b/src/assets/css/index.css index 0cc0984..234d377 100644 --- a/src/assets/css/index.css +++ b/src/assets/css/index.css @@ -290,14 +290,14 @@ button { @media (max-width: 500px) { .swiper_container { - height: 47rem; + /* height: 47rem; */ } .swiper-slide { width: 28rem !important; - height: 36rem !important; + /* height: 36rem !important; */ } .swiper-slide img { - width: 28rem !important; + /* width: 28rem !important; */ height: 36rem !important; } } @@ -308,13 +308,13 @@ button { } .swiper-slide { width: 30rem; - height: 36rem; + /* height: 36rem; */ /* height: auto; */ /* Adjust the height as needed */ } .swiper-slide img { width: 30rem; - height: 36rem; + /* height: 36rem; */ } } diff --git a/src/context/MAIN_CONTEXT/UserContext/UserContext.js b/src/context/MAIN_CONTEXT/UserContext/UserContext.js index e26a545..cd28a19 100644 --- a/src/context/MAIN_CONTEXT/UserContext/UserContext.js +++ b/src/context/MAIN_CONTEXT/UserContext/UserContext.js @@ -19,7 +19,7 @@ export const UserContext = createContext(defaultContextValue.USER_CONTEXT); export const UserProvider = ({ children }) => { const { userId, isLoggedIn } = useAuthContext(); // Assuming useAuthContext now provides userId directly - const [user, setUser] = useLocalStorage('user', {}); + const [user, setUser] = useLocalStorage('user', null); const logger = useLogger('UserProvider'); const { isLoading } = useLoading(); const { fetchWrapper, status } = useFetchWrapper(); @@ -30,27 +30,35 @@ export const UserProvider = ({ children }) => { [userId] ); + // Fetch user data from the server and update local storage if necessary const fetchUserData = useCallback(async () => { - if (!userId || !isLoggedIn || status === 'loading') return; + if (!userId || !isLoggedIn || isLoading('fetchUserData')) return; + + // Check if user data is already fetched or present in local storage + if (user && Object.keys(user).length !== 0) { + setHasFetchedUser(true); + return; + } + try { const responseData = await fetchWrapper( - `${process.env.REACT_APP_SERVER}/api/users/${userId}/userData`, + createApiUrl('userData'), 'GET', null, - 'getUserData' + 'fetchUserData' ); - setUser(responseData?.data); + setUser(responseData?.data); // Set user data in local storage setHasFetchedUser(true); } catch (error) { console.error('Error fetching user data:', error); setError(error.message || 'Failed to fetch user data'); logger.logEvent('Failed to fetch user data', error.message); } - }, [userId, isLoggedIn, fetchWrapper, setUser, logger]); + }, [userId, isLoggedIn, fetchWrapper, setUser, logger, user]); useEffect(() => { - fetchUserData(); - }, []); + if (userId && isLoggedIn && !hasFetchedUser) fetchUserData(); + }, [userId, isLoggedIn, hasFetchedUser]); const updateUser = useCallback( async (updatedUserData) => { diff --git a/src/data/baseMenuItems.jsx b/src/data/baseMenuItems.jsx index c9f8df2..65350a0 100644 --- a/src/data/baseMenuItems.jsx +++ b/src/data/baseMenuItems.jsx @@ -10,12 +10,19 @@ import { } from '@mui/icons-material'; import DeckBuilderIcon from '../layout/REUSABLE_COMPONENTS/icons/DeckBuilderIcon'; import { Badge } from '@mui/material'; +import MenuIcon from '@mui/icons-material/Menu'; -export const baseMenuItems = (cartCardQuantity, iconColor) => [ +export const baseMenuItems = ({ cartCardQuantity }) => [ + // { + // name: 'Menu', + // icon: , + // to: '/', + // requiresLogin: false, + // }, { name: 'Home', icon: , to: '/home', requiresLogin: false }, { - name: 'Deck Builder', - icon: , + name: 'Deck', + icon: , to: '/deckbuilder', requiresLogin: false, }, diff --git a/src/layout/REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection.jsx b/src/layout/REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection.jsx index 29f541b..207b916 100644 --- a/src/layout/REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection.jsx +++ b/src/layout/REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection.jsx @@ -26,7 +26,7 @@ const RCLogoSection = () => { height: '50px', padding: '8px', marginRight: '8px', - color: 'rgba(0, 0, 0, 0.54)', + color: 'white', '&:hover': { backgroundColor: 'rgba(0, 0, 0, 0.1)', }, @@ -35,16 +35,16 @@ const RCLogoSection = () => { {/* Encapsulate DeckBuilderIcon within an Avatar */} - + { fontFamily: 'Roboto, sans-serif', fontWeight: 700, fontSize: { xs: '1rem', sm: '1.2rem', md: '1.4rem' }, - color: 'inherit', + color: 'white', }} > DeckMaster diff --git a/src/layout/REUSABLE_COMPONENTS/unique/SimpleCard.jsx b/src/layout/REUSABLE_COMPONENTS/unique/SimpleCard.jsx index a6731ff..752955e 100644 --- a/src/layout/REUSABLE_COMPONENTS/unique/SimpleCard.jsx +++ b/src/layout/REUSABLE_COMPONENTS/unique/SimpleCard.jsx @@ -4,7 +4,7 @@ import styled from 'styled-components'; import { CardContent, IconButton, Typography } from '@mui/joy'; import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'; import { useMode } from '../../../context'; -import { Icon } from '@mui/material'; +import { Icon, useMediaQuery } from '@mui/material'; import MDBox from '../MDBOX'; import SaveIcon from '@mui/icons-material/Save'; import AddIcon from '@mui/icons-material/Add'; @@ -114,6 +114,7 @@ const SimpleCard = ({ ...rest }) => { const { theme: themeSettings } = useMode(); + const isMobileView = useMediaQuery(themeSettings.breakpoints.down('sm')); const cardStyle = { // display: 'flex', width: '100%', @@ -147,6 +148,7 @@ const SimpleCard = ({ @@ -187,6 +190,7 @@ const SimpleCard = ({ justifyContent: 'center', alignItems: 'center', flexGrow: 1, + border: 'none', }} > {heroText} diff --git a/src/layout/navigation/Navigation.jsx b/src/layout/navigation/Navigation.jsx index 65255e2..1975ad5 100644 --- a/src/layout/navigation/Navigation.jsx +++ b/src/layout/navigation/Navigation.jsx @@ -7,6 +7,7 @@ import { ListItem, ListItemText, AppBar, + useMediaQuery, } from '@mui/material'; import MenuIcon from '@mui/icons-material/Menu'; import { @@ -16,7 +17,7 @@ import { useSidebarContext, } from '../../context'; import { Navigate, useNavigate } from 'react-router-dom'; -import getMenuItemsData from './menuItemsData'; +// import getMenuItemsData from './menuItemsData'; import { useSpring, animated, useSprings } from 'react-spring'; import MDTypography from '../REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; import RCLogoSection from '../REUSABLE_COMPONENTS/RCLOGOSECTION/RCLogoSection'; @@ -34,6 +35,7 @@ import { Typography, } from '@mui/joy'; import { useCookies } from 'react-cookie'; +import { baseMenuItems } from '../../data/baseMenuItems'; const Navigation = ({ isLoggedIn }) => { const { theme } = useMode(); const navigate = useNavigate(); @@ -42,151 +44,145 @@ const Navigation = ({ isLoggedIn }) => { typeof navigator !== 'undefined' && /iPad|iPhone|iPod/.test(navigator.userAgent); const [isOpen, setIsOpen] = useState(false); // Manage open state locally - const [isMobileView, setIsMobileView] = useState(window.innerWidth < 768); + const isMobileView = useMediaQuery(theme.breakpoints.down('sm')); const iconColor = isMobileView ? theme.palette.primary.main : 'white'; const [cookies] = useCookies('authUser'); const username = cookies?.authUser?.username; - // const { authUser } = useAuthContext(); - - useEffect(() => { - const fetchData = async () => { - const items = await getMenuItemsData( - isLoggedIn, - totalQuantity, - iconColor - ); - setMenuItems(items?.map((item) => ({ ...item, isVisible: true }))); - }; - - fetchData(); - }, [isLoggedIn, totalQuantity, iconColor]); + const menuItems = baseMenuItems({ cartCardQuantity: totalQuantity }); const toggleSidebar = useCallback(() => setIsOpen(!isOpen), [isOpen]); - - const [menuItems, setMenuItems] = useState([]); - useEffect(() => { - const handleResize = () => setIsMobileView(window.innerWidth < 768); - window.addEventListener('resize', handleResize); - return () => window.removeEventListener('resize', handleResize); - }, []); - const [isMounted, setIsMounted] = useState(false); - const [springs, api] = useSprings(menuItems.length, (index) => ({ + const [springs] = useSprings(menuItems.length, (index) => ({ from: { opacity: 0, transform: 'translateY(-20px)' }, to: { opacity: 1, transform: 'translateY(0)' }, - delay: index * 100, // Delay based on index + delay: index * 100, })); - const renderMenuItems = (type) => - springs.map((style, index) => ( - + const ContentContainer = ({ type, content, clickAction, itemIndex }) => { + const handleClick = () => { + if (clickAction === 'navigate' && itemIndex !== undefined) { + navigate(menuItems[itemIndex].to); + } else { + toggleSidebar(); + } + }; + return ( + + + {content} + + + ); + }; + + const renderMenuItems = (type) => { + return springs.map((style, index) => ( + navigate(menuItems[index].to)} sx={{ - // width: 'clamp(130px, 50%, 175px)', // Responsive width using clamp maxHeight: 64, maxWidth: '100%', - // mx: theme.spacing(4), - '&:hover': { - backgroundColor: theme.palette.backgroundF.light, - color: 'white', - }, + '&:hover': { backgroundColor: theme.palette.backgroundF.light }, }} > - - - {menuItems[index].icon} - {menuItems[index].name} - - + + {menuItems[index]?.icon} + + {menuItems[index]?.name} + + + } + itemIndex={index} + clickAction="navigate" + /> )); + }; return ( <> - + - - - + + + + } + clickAction={'toggle'} + index={0} + /> - {renderMenuItems('top')} - - - - - {username} - - - + {!isMobileView && renderMenuItems('top')} + + + {username} + {/* */} { }, }, }} + sx={{ + // borderRadius: 'md', + // p: 2, + display: 'flex', + flexDirection: 'column', + justifyContent: 'flex-start', + // gap: 2, + // height: '100%', + // overflow: 'auto', + }} > { > Filters - + {renderMenuItems('side')} diff --git a/src/layout/navigation/menuItemsData.jsx b/src/layout/navigation/menuItemsData.jsx index 243524e..fc5a409 100644 --- a/src/layout/navigation/menuItemsData.jsx +++ b/src/layout/navigation/menuItemsData.jsx @@ -1,104 +1,137 @@ -import React from 'react'; -import { - Home as HomeIcon, - Store as StoreIcon, - ShoppingCart as CartIcon, - Assessment as CollectionIcon, - Person as ProfileIcon, -} from '@mui/icons-material'; -import DeckBuilderIcon from '../REUSABLE_COMPONENTS/icons/DeckBuilderIcon'; -import { Badge } from '@mui/material'; -import { useCartStore } from '../../context/MAIN_CONTEXT/CartContext/CartContext'; -export const getMenuItemsData = (isLoggedIn, cartCardQuantity, iconColor) => { - // const { cartCardQuantity } = useCartStore(); - try { - const baseMenuItems = [ - { name: 'Home', icon: , to: '/home', requiresLogin: false }, - { - name: 'Deck', - // icon: , - icon: , - to: '/deckbuilder', - requiresLogin: false, - }, - { - name: 'Collection', - icon: , - to: '/collection', - requiresLogin: !isLoggedIn, - }, - { - name: 'Store', - icon: , - to: '/store', - requiresLogin: !isLoggedIn, - }, - { - name: 'Cart', - icon: ( - - - - ), - to: '/cart', - requiresLogin: !isLoggedIn, - }, - { - name: 'Profile', - icon: , - to: '/profile', - requiresLogin: isLoggedIn, - }, - // { - // name: 'Login', - // icon: , - // to: '/login', - // requiresLogin: false, - // }, - ]; +// import React, { useCallback, useState } from 'react'; +// import { +// Home as HomeIcon, +// Store as StoreIcon, +// ShoppingCart as CartIcon, +// Assessment as CollectionIcon, +// Person as ProfileIcon, +// } from '@mui/icons-material'; +// import DeckBuilderIcon from '../REUSABLE_COMPONENTS/icons/DeckBuilderIcon'; +// import { Badge } from '@mui/material'; +// import { useCartStore } from '../../context/MAIN_CONTEXT/CartContext/CartContext'; +// import { IconButton } from '@mui/joy'; +// import MenuIcon from '@mui/icons-material/Menu'; - if (isLoggedIn) { - return baseMenuItems.map((item) => ({ - ...item, - requiresLogin: false, - })); - } +// // const iconWrapper = (icon) => { +// // return ( +// // +// // {icon} +// // +// // ); +// // }; +// export const getMenuItemsData = ({ +// isLoggedIn, +// cartCardQuantity, +// // iconColor, +// // isOpen, +// // setIsOpen, +// }) => { +// // const { cartCardQuantity } = useCartStore(); +// // const [isOpen, setIsOpen] = useState(false); // Manage open state locally +// // const toggleSidebar = useCallback(() => setIsOpen(!isOpen), [isOpen]); +// // const iconColor = isMobileView ? theme.palette.primary.main : 'white'; - // Processed menu items - const processedMenuItems = isLoggedIn - ? baseMenuItems.map((item) => ({ ...item, requiresLogin: false })) - : baseMenuItems; +// try { +// const baseMenuItems = [ +// { +// name: 'Menu', +// icon: , +// to: '/', +// requiresLogin: false, +// }, +// { name: 'Home', icon: , to: '/home', requiresLogin: false }, +// { +// name: 'Deck', +// // icon: , +// icon: , +// to: '/deckbuilder', +// requiresLogin: false, +// }, +// { +// name: 'Collection', +// icon: , +// to: '/collection', +// requiresLogin: !isLoggedIn, +// }, +// { +// name: 'Store', +// icon: , +// to: '/store', +// requiresLogin: !isLoggedIn, +// }, +// { +// name: 'Cart', +// icon: ( +// +// +// +// ), +// to: '/cart', +// requiresLogin: !isLoggedIn, +// }, +// { +// name: 'Profile', +// icon: , +// to: '/profile', +// requiresLogin: isLoggedIn, +// }, +// // { +// // name: 'Login', +// // icon: , +// // to: '/login', +// // requiresLogin: false, +// // }, +// ]; - return { - baseMenuItems, - menuItems: processedMenuItems, - }; - } catch (error) { - console.error('An error occurred in getMenuItemsData:', error); - return { - baseMenuItems: [], - menuItems: [], - }; - } -}; +// if (isLoggedIn) { +// return baseMenuItems.map((item) => ({ +// ...item, +// requiresLogin: false, +// })); +// } -export default getMenuItemsData; +// // Processed menu items +// const processedMenuItems = isLoggedIn +// ? baseMenuItems.map((item) => ({ ...item, requiresLogin: false })) +// : baseMenuItems; + +// return { +// baseMenuItems, +// menuItems: processedMenuItems, +// }; +// } catch (error) { +// console.error('An error occurred in getMenuItemsData:', error); +// return { +// baseMenuItems: [], +// menuItems: [], +// }; +// } +// }; + +// export default getMenuItemsData; diff --git a/src/pages/sections/HeroIconSection.jsx b/src/pages/sections/HeroIconSection.jsx new file mode 100644 index 0000000..bca42a8 --- /dev/null +++ b/src/pages/sections/HeroIconSection.jsx @@ -0,0 +1,91 @@ +import SaveIcon from '@mui/icons-material/Save'; +import AddIcon from '@mui/icons-material/Add'; +import CollectionsIcon from '@mui/icons-material/Collections'; +import pages from '../../data/pages.json'; +import placeHolder from '../../assets/images/placeholder.jpeg'; +import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; +import { Zoom, useMediaQuery } from '@mui/material'; +import SimpleCard from '../../layout/REUSABLE_COMPONENTS/unique/SimpleCard'; +import uniqueTheme from '../../layout/REUSABLE_COMPONENTS/unique/uniqueTheme'; +import { useMode } from '../../context'; +const heroCardData = [ + { + id: 'herodata-1-store-add', + name: 'Add Cards From Store', + description: 'Add cards to your collection from the store.', + heroText: 'ADD', + icon: , + heroIcon: 'AddIcon', + image: placeHolder, + }, + { + id: 'herodata-2-deck-build', + name: 'Build Decks In Deck Builder', + description: 'Build decks using the deck builder.', + heroText: 'BUILD', + icon: , + heroIcon: 'SaveIcon', + image: placeHolder, + }, + { + id: 'herodata-3-collection-view', + name: 'Track Collection Value in Portfolio', + description: + 'View and analyze your portfolio performance using the Portfolios advanced statistics settings.', + heroText: 'TRACK', + icon: , + heroIcon: 'CollectionsIcon', + image: placeHolder, + }, +]; + +const HeroIconSection = ({ shouldShow }) => { + const { theme } = useMode(); + const isMobileView = useMediaQuery(theme.breakpoints.down('sm')); + return ( + + + + {heroCardData?.map((card, index) => ( + + + + ))} + + + + ); +}; + +export default HeroIconSection; diff --git a/src/pages/sections/HeroSection.jsx b/src/pages/sections/HeroSection.jsx index e9a1d4f..ddb24ee 100644 --- a/src/pages/sections/HeroSection.jsx +++ b/src/pages/sections/HeroSection.jsx @@ -26,43 +26,11 @@ import { Zoom, useMediaQuery, } from '@mui/material'; -import DashboardBox from '../../layout/REUSABLE_COMPONENTS/DashboardBox'; -import AttachMoneyIcon from '@mui/icons-material/AttachMoney'; -import SimpleCard from '../../layout/REUSABLE_COMPONENTS/unique/SimpleCard'; -import uniqueTheme from '../../layout/REUSABLE_COMPONENTS/unique/uniqueTheme'; -import SaveIcon from '@mui/icons-material/Save'; -import AddIcon from '@mui/icons-material/Add'; -import CollectionsIcon from '@mui/icons-material/Collections'; import pages from '../../data/pages.json'; +import HeroTextSection from './HeroTextSection'; +import HeroIconSection from './HeroIconSection'; +import HeroSwiper from './HeroSwiper'; -// Replace headerItems with realistic card store data -const storeInfoItems = [ - { icon: , label: 'Total Sales', value: '$152,300' }, - { icon: , label: 'Average Order', value: '$350' }, - { icon: , label: 'Total Products', value: '1250' }, -]; -const StoreInfoItem = ({ icon, label, value, delay }) => { - return ( - - {icon} - - {label} - {value} - - - ); -}; const HeroSection = () => { const { theme } = useMode(); const { breakpoints } = theme; @@ -71,8 +39,6 @@ const HeroSection = () => { const isFullView = useMediaQuery(breakpoints.up('lg')); const [activeCardIndex, setActiveCardIndex] = useState(0); const [shouldShow, setShouldShow] = useState(false); - useEffect(() => setShouldShow(true), []); - const { topFiveCards } = useStatisticsStore(); const defaultCards = new Array(45).fill({}).map((_, index) => ({ id: `default-${index}`, @@ -81,39 +47,41 @@ const HeroSection = () => { image: placeHolder, })); const cards = [...topFiveCards, ...defaultCards]; - const handleSlideChange = (swiper) => setActiveCardIndex(swiper.realIndex); - const heroCardData = [ - { - id: 'herodata-1-store-add', - name: 'Add Cards From Store', - description: 'Add cards to your collection from the store.', - heroText: 'ADD', - icon: , - heroIcon: 'AddIcon', - image: placeHolder, + const swiperConfig = { + effect: 'coverflow', + grabCursor: true, + centeredSlides: true, + loop: true, + resizeObserver: true, + spaceBetween: 10, + coverflowEffect: { + stretch: 0, + modifier: 1, + rotate: 0, + depth: 200, + slideShadows: false, }, - { - id: 'herodata-2-deck-build', - name: 'Build Decks In Deck Builder', - description: 'Build decks using the deck builder.', - heroText: 'BUILD', - icon: , - heroIcon: 'SaveIcon', - image: placeHolder, + autoplay: { + delay: 2500, + disableOnInteraction: false, }, - { - id: 'herodata-3-collection-view', - name: 'Track Collection Value in Portfolio', - description: - 'View and analyze your portfolio performance using the Portfolios advanced statistics settings.', - heroText: 'TRACK', - icon: , - heroIcon: 'CollectionsIcon', - image: placeHolder, + modules: [EffectCoverflow, Pagination, Navigation, Autoplay], + scrollbar: { + el: '.swiper-scrollbar', + draggable: true, }, - ]; + navigation: { + nextEl: '.swiper-button-next', + prevEl: '.swiper-button-prev', + clickable: true, + }, + className: 'swiper_container', + }; + useEffect(() => setShouldShow(true), []); - if (!cards || !Array.isArray(cards) || !cards[activeCardIndex]) { + const handleSlideChange = (swiper) => setActiveCardIndex(swiper.realIndex); + + if (!cards.length) { return ; } @@ -122,21 +90,24 @@ const HeroSection = () => { style={{ display: 'flex', position: 'relative', - minHeight: isMobileView ? '50vh' : 'calc(100vh - 64px)', + minHeight: isMobileView ? 'calc(100vh - 64px)' : 'calc(100vh - 64px)', flexDirection: isMobileView ? 'column' : 'row', }} > @@ -144,11 +115,16 @@ const HeroSection = () => { className="hero-section-container" sx={{ width: '100%', + height: isMobileView ? 'calc(100vh - 64px)' : '50vh', minHeight: isMobileView ? '30vh' : '80vh', - backgroundColor: 'transparent', // Make the Card background transparent + backgroundColor: isMobileView ? 'none' : 'transparent', + alignItems: isMobileView ? 'space-between' : 'center', + + flexDirection: 'column', + // position: isMobileView ? 'relative' : 'absolute', }} > - { justifyContent: 'center', height: '100%', }} - > - - - - - A New Era of Trading Card Games - - - Discover a revolutionary way to collect, play, and compete - in your favorite trading card games. Embrace a world where - strategy and creativity transcend boundaries. - - - - - - - {heroCardData?.map((card, index) => ( - - - - ))} - - + > */} + + + {/* */} - - - - `${cards[index].name}`, // Rendering titles as bullets - }} - scrollbar={{ - el: '.swiper-scrollbar', - draggable: true, - }} - navigation={{ - nextEl: '.swiper-button-next', - prevEl: '.swiper-button-prev', - clickable: true, - }} - autoplay={{ - delay: 2500, // Delay in milliseconds (2.5 seconds) - disableOnInteraction: false, // Continues autoplay when interacted with - }} - style={{ - // minWidth: '150vw', - minWidth: '150vw', - width: '100%', - alignItems: isMobileView ? 'center' : 'flex-start', - position: isMobileView ? 'relative' : 'absolute', - ml: isMobileView ? '0' : '60vw', - }} - modules={[EffectCoverflow, Pagination, Navigation, Autoplay]} // Include Autoplay module - className="swiper_container" - onSlideChange={handleSlideChange} - > - {cards?.map((card, index) => ( - - - {card.name} - - {`slide_${index}`} - - ))} - - + ); }; diff --git a/src/pages/sections/HeroSwiper.jsx b/src/pages/sections/HeroSwiper.jsx new file mode 100644 index 0000000..ad88239 --- /dev/null +++ b/src/pages/sections/HeroSwiper.jsx @@ -0,0 +1,138 @@ +import React from 'react'; +import { Swiper, SwiperSlide } from 'swiper/react'; +import 'swiper/css'; +import 'swiper/css/effect-coverflow'; +import 'swiper/css/pagination'; +import 'swiper/css/navigation'; +import { + EffectCoverflow, + Pagination, + Navigation, + Autoplay, +} from 'swiper/modules'; +import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; +import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; +import placeHolder from '../../assets/images/placeholder.jpeg'; + +const HeroSwiper = ({ + cards, + isMobileView, + handleSlideChange, + activeCardIndex, +}) => { + const swiperConfig = { + effect: 'coverflow', + grabCursor: true, + centeredSlides: true, + loop: true, + resizeObserver: true, + spaceBetween: 10, + coverflowEffect: { + stretch: 0, + modifier: 1, + rotate: 0, + depth: 200, + slideShadows: false, + }, + autoplay: { + delay: 2500, + disableOnInteraction: false, + }, + modules: [EffectCoverflow, Pagination, Navigation, Autoplay], + scrollbar: { + el: '.swiper-scrollbar', + draggable: true, + }, + navigation: { + nextEl: '.swiper-button-next', + prevEl: '.swiper-button-prev', + clickable: true, + }, + className: 'swiper_container', + }; + + return ( + + + `${cards[index].name}`, + }} + style={{ + minWidth: '150vw', + width: '100%', + alignItems: isMobileView ? 'center' : 'flex-start', + position: isMobileView ? 'absolute' : 'absolute', + height: isMobileView ? 'calc(100vh - 64px)' : null, + // pb: '2rem', + ml: isMobileView ? '0' : '60vw', + // position: isMobileView ? 'absolute' : 'relative', + }} + onSlideChange={handleSlideChange} + > + {cards?.map((card, index) => ( + + + {card.name} + + {`slide_${index}`} + + ))} + + + ); +}; + +export default HeroSwiper; diff --git a/src/pages/sections/HeroTextSection.jsx b/src/pages/sections/HeroTextSection.jsx new file mode 100644 index 0000000..5c9bfdf --- /dev/null +++ b/src/pages/sections/HeroTextSection.jsx @@ -0,0 +1,68 @@ +import { Typography, Zoom, useMediaQuery } from '@mui/material'; +import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; +import { useMode } from '../../context'; + +const HeroTextSection = ({ shouldShow }) => { + const { theme } = useMode(); + const isMobileView = useMediaQuery(theme.breakpoints.down('sm')); + console.log(shouldShow); + + return ( + + + + + A New Era of Trading Card Games + + + Discover a revolutionary way to collect, play, and compete in your + favorite trading card games. Embrace a world where strategy and + creativity transcend boundaries. + + + + + ); +}; + +export default HeroTextSection; From 5d9e7e2c2e8417315ac8364650ae905292343f6c Mon Sep 17 00:00:00 2001 From: Reed Vogt Date: Wed, 20 Mar 2024 08:59:37 -0700 Subject: [PATCH 08/10] updated deck context to use collection context patterns. Current issues: unable to get grid items to re render with updates --- .../themes/base/customColorPalettes.jsx | 2 + .../actionButtons/GenericActionButtons.jsx | 11 +- .../buttons/other/ReusableLoadingButton.jsx | 9 +- src/components/cards/GenericCard.jsx | 10 +- src/components/dialogs/CollectionDialog.jsx | 1 - src/components/dialogs/DeckDialog.jsx | 85 ++ src/components/forms/CollectionForm.jsx | 30 +- src/components/forms/DeckForm.jsx | 161 ++++ src/components/forms/reusable/FormField.jsx | 19 +- src/components/forms/reusable/RCZodForm.jsx | 59 +- .../forms/search/SearchComponent.jsx | 16 - src/components/forms/search/SearchResults.jsx | 1 + src/context/Helpers.jsx | 10 - .../useCollectionManager.jsx | 5 +- .../useSelectedCollection.jsx | 348 +------ .../MAIN_CONTEXT/DeckContext/DeckContext.js | 912 ++++++++---------- .../MAIN_CONTEXT/DeckContext/helpers.jsx | 235 ----- .../DeckContext/useDeckManager.jsx | 265 +++++ .../DeckContext/useSelectedDeck.jsx | 240 +++++ .../AppContext/AppContextProvider.jsx | 2 +- .../FormContext/FormContext.jsx | 53 +- .../UTILITIES_CONTEXT/FormContext/schemas.jsx | 58 +- src/context/constants.jsx | 17 +- src/context/hooks/useGridItems.jsx | 110 +-- src/context/simplified_constants.jsx | 17 + src/data/baseMenuItems.jsx | 2 +- src/data/initialCardData.jsx | 254 +++-- src/{context => data}/user.jsx | 0 src/layout/REUSABLE_COMPONENTS/BoxHeader.jsx | 4 +- .../REUSABLE_COMPONENTS/ProgressCircle.jsx | 29 +- .../REUSABLE_COMPONENTS/RC/RCChange.jsx | 2 +- .../RCLOGOSECTION/RCLogoSection.jsx | 5 +- .../ReusableSkeletonItem.jsx | 18 - .../REUSABLE_COMPONENTS/SkeletonCard.jsx | 34 - .../REUSABLE_COMPONENTS/SkeletonVariants.jsx | 116 ++- .../icons/DeckBuilderIcon.jsx | 127 +-- .../cards-datatable/useSkeletonLoader.jsx | 61 +- .../statItems/PricedCardList.jsx | 2 +- .../statItems/ValuDistributionCircle.jsx | 8 +- src/layout/collection/index.jsx | 6 +- src/layout/deck/DeckDisplay.js | 59 +- src/layout/deck/DeckEditPanel.js | 90 +- src/layout/deck/DeckEditor.jsx | 29 +- src/layout/deck/DeckListItem.jsx | 253 +++++ src/layout/deck/DeckPageHeader.jsx | 101 ++ src/layout/deck/SelectDeckList.jsx | 120 ++- src/layout/deck/index.jsx | 97 +- src/layout/navigation/Navigation.jsx | 2 +- src/pages/DeckBuilderPage.js | 14 +- src/pages/sections/HeroSection.jsx | 2 +- src/pages/sections/HeroTextSection.jsx | 15 +- src/save/helpers.jsx | 235 +++++ 52 files changed, 2488 insertions(+), 1873 deletions(-) create mode 100644 src/components/dialogs/DeckDialog.jsx create mode 100644 src/components/forms/DeckForm.jsx delete mode 100644 src/context/MAIN_CONTEXT/DeckContext/helpers.jsx create mode 100644 src/context/MAIN_CONTEXT/DeckContext/useDeckManager.jsx create mode 100644 src/context/MAIN_CONTEXT/DeckContext/useSelectedDeck.jsx create mode 100644 src/context/simplified_constants.jsx rename src/{context => data}/user.jsx (100%) delete mode 100644 src/layout/REUSABLE_COMPONENTS/ReusableSkeletonItem.jsx delete mode 100644 src/layout/REUSABLE_COMPONENTS/SkeletonCard.jsx create mode 100644 src/layout/deck/DeckListItem.jsx create mode 100644 src/layout/deck/DeckPageHeader.jsx create mode 100644 src/save/helpers.jsx diff --git a/src/assets/themes/base/customColorPalettes.jsx b/src/assets/themes/base/customColorPalettes.jsx index c590a75..21ca42f 100644 --- a/src/assets/themes/base/customColorPalettes.jsx +++ b/src/assets/themes/base/customColorPalettes.jsx @@ -1,8 +1,10 @@ import hexToRgba from '../functions/hexToRgba'; const error = { + light: '#e57373', main: '#f44336', focus: '#f44336', dark: '#d32f2f', + darkest: '#7f2e2eff', // --persian-plum-- contrastText: '#fff', hoverContrastText: '#111', }; diff --git a/src/components/buttons/actionButtons/GenericActionButtons.jsx b/src/components/buttons/actionButtons/GenericActionButtons.jsx index 88f60e6..e3f9ccc 100644 --- a/src/components/buttons/actionButtons/GenericActionButtons.jsx +++ b/src/components/buttons/actionButtons/GenericActionButtons.jsx @@ -11,6 +11,7 @@ import ActionButton from './ActionButton'; import { useSnackbar } from 'notistack'; import GlassyIcon from '../../../layout/REUSABLE_COMPONENTS/icons/GlassyIcon'; import MDBox from '../../../layout/REUSABLE_COMPONENTS/MDBOX'; +import useDeckManager from '../../../context/MAIN_CONTEXT/DeckContext/useDeckManager'; const buttonSizeMap = { xs: 'extraSmall', @@ -31,15 +32,7 @@ const GenericActionButtons = ({ const { enqueueSnackbar } = useSnackbar(); // Add this line to use Notistack const { addOneToCollection, removeOneFromCollection } = useCollectionManager(); - const { selectedCollection, allCollections, handleSelectCollection } = - useSelectedCollection(); - const { - addOneToDeck, - removeOneFromDeck, - selectedDeck, - allDecks, - setSelectedDeck, - } = useDeckStore(); + const { addOneToDeck, removeOneFromDeck } = useDeckManager(); const { addOneToCart, removeOneFromCart, cartData } = useCartStore(); const [buttonSize, setButtonSize] = useState( buttonSizeMap[cardSize] || 'medium' diff --git a/src/components/buttons/other/ReusableLoadingButton.jsx b/src/components/buttons/other/ReusableLoadingButton.jsx index 754f390..e2eac8e 100644 --- a/src/components/buttons/other/ReusableLoadingButton.jsx +++ b/src/components/buttons/other/ReusableLoadingButton.jsx @@ -18,12 +18,13 @@ const ReusableLoadingButton = ({ const getButtonStyles = (variant) => { if (variant === 'warning') { return { - background: theme.palette.error.state, - borderColor: theme.palette.error.dark, - borderWidth: 2, + background: theme.palette.error.main, + borderColor: theme.palette.error.darkest, + borderWidth: 5, + '&:hover': { fontWeight: 'bold', - bgcolor: theme.palette.error.main, + background: theme.palette.error.light, borderColor: theme.palette.error.dark, }, '&:focus': { diff --git a/src/components/cards/GenericCard.jsx b/src/components/cards/GenericCard.jsx index 6e7aad8..7c9f56b 100644 --- a/src/components/cards/GenericCard.jsx +++ b/src/components/cards/GenericCard.jsx @@ -31,6 +31,9 @@ import useSelectedContext from '../../context/hooks/useSelectedContext'; import useSelectedCollection from '../../context/MAIN_CONTEXT/CollectionContext/useSelectedCollection'; const GenericCard = React.forwardRef((props, ref) => { const { card, context, page } = props; + const effectiveContext = + typeof context === 'object' ? context.pageContext : context; + const { theme } = useMode(); const cardRef = useRef(null); const [cardSize, setCardSize] = useState('md'); // Default to 'sm' @@ -102,7 +105,6 @@ const GenericCard = React.forwardRef((props, ref) => { allDecks: allDecks, }); let cardContent = null; - if (cardSize !== 'xs') { cardContent = ( @@ -139,7 +141,7 @@ const GenericCard = React.forwardRef((props, ref) => { isRequired={true} imgUrl={imgUrl} card={card} - context={context} + context={effectiveContext} page={page} quantity={card?.quantity} isHovered={hoveredCard === card} @@ -158,8 +160,8 @@ const GenericCard = React.forwardRef((props, ref) => { > handleContextSelect(context)} + context={effectiveContext} + onClick={() => handleContextSelect(effectiveContext)} onSuccess={() => enqueueSnackbar( { diff --git a/src/components/dialogs/CollectionDialog.jsx b/src/components/dialogs/CollectionDialog.jsx index 14393e3..3df8c3b 100644 --- a/src/components/dialogs/CollectionDialog.jsx +++ b/src/components/dialogs/CollectionDialog.jsx @@ -15,7 +15,6 @@ import MDAvatar from '../../layout/REUSABLE_COMPONENTS/MDAVATAR'; const CollectionDialog = ({ open, onClose, isNew, collectionData }) => { const { theme } = useMode(); - const actionType = isNew ? 'add' : 'update'; return ( diff --git a/src/components/dialogs/DeckDialog.jsx b/src/components/dialogs/DeckDialog.jsx new file mode 100644 index 0000000..e488cd3 --- /dev/null +++ b/src/components/dialogs/DeckDialog.jsx @@ -0,0 +1,85 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { CssBaseline, DialogTitle, Divider } from '@mui/material'; +import { useMode } from '../../context'; +import DeckForm from '../forms/DeckForm'; // Adjusted import +import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; +import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; +import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; +import { + DialogPaper, + StyledDialog, + StyledDialogContent, +} from '../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; +import MDAvatar from '../../layout/REUSABLE_COMPONENTS/MDAVATAR'; + +const DeckDialog = ({ open, onClose, isNew, deckData }) => { + const { theme } = useMode(); + const actionType = isNew ? 'add' : 'update'; + + return ( + + + + + + + + + + {isNew ? 'Add a Deck' : 'Update a Deck'} + + + + + + + + + + + ); +}; + +DeckDialog.propTypes = { + open: PropTypes.bool.isRequired, + onClose: PropTypes.func.isRequired, + isNew: PropTypes.bool, + deckData: PropTypes.shape({ + name: PropTypes.string, + description: PropTypes.string, + }), +}; + +export default DeckDialog; diff --git a/src/components/forms/CollectionForm.jsx b/src/components/forms/CollectionForm.jsx index 4448ae7..904c8e0 100644 --- a/src/components/forms/CollectionForm.jsx +++ b/src/components/forms/CollectionForm.jsx @@ -25,7 +25,7 @@ const collectionFields = [ const CollectionForm = ({ collectionData, actionType }) => { const { setFormSchema, onSubmit } = useFormContext(); const { theme } = useMode(); - const { showSuccess, showError } = useSnackbarManager(); + // const { showSuccess, showError } = useSnackbarManager(); // Determine the schema name and button label based on the action type const schemaName = @@ -40,19 +40,19 @@ const CollectionForm = ({ collectionData, actionType }) => { } }, [collectionData, setFormSchema, schemaName, actionType]); - const handleFormSubmit = async (data) => { - const method = actionType === 'add' ? 'Add' : 'Update'; - try { - await onSubmit(data, schemaName, collectionData?._id); - showSuccess( - `You've successfully ${method.toLowerCase()}ed the collection.` - ); - } catch (error) { - showError( - `Failed to ${method.toLowerCase()} collection. Please try again.` - ); - } - }; + // const handleFormSubmit = async (data) => { + // const method = actionType === 'add' ? 'Add' : 'Update'; + // try { + // await onSubmit(data, schemaName, collectionData?._id); + // showSuccess( + // `You've successfully ${method.toLowerCase()}ed the collection.` + // ); + // } catch (error) { + // showError( + // `Failed to ${method.toLowerCase()} collection. Please try again.` + // ); + // } + // }; return ( { buttonLabel={buttonLabel} startIcon={startIcon} fields={collectionFields} - onSubmit={handleFormSubmit} + // onSubmit={handleFormSubmit} theme={theme} initialValues={actionType === 'update' ? collectionData : {}} /> diff --git a/src/components/forms/DeckForm.jsx b/src/components/forms/DeckForm.jsx new file mode 100644 index 0000000..412b337 --- /dev/null +++ b/src/components/forms/DeckForm.jsx @@ -0,0 +1,161 @@ +import React, { useEffect, useState } from 'react'; +import SaveIcon from '@mui/icons-material/Save'; +import DeleteIcon from '@mui/icons-material/Delete'; +import { useFormContext } from '../../context'; +import RCZodForm from './reusable/RCZodForm'; + +// You should have your schema definitions imported here + +const DeckForm = ({ actionType, deckData }) => { + const { onSubmit, setFormSchema, formMethods } = useFormContext(); + const isUpdateMode = actionType === 'update'; + const [tags, setTags] = useState(deckData?.tags || []); + + useEffect(() => { + setFormSchema('updateDeckForm'); + if (deckData) { + console.log('deckData:', deckData); + formMethods.reset({ + ...deckData, + tags: deckData?.tags?.join(', '), + color: deckData?.color || 'red', + }); + } + }, [deckData, setFormSchema, formMethods]); + + const handleAddTag = (tag) => { + if (tag && !tags.includes(tag)) { + setTags([...tags, tag]); + formMethods.setValue('tags', [...tags, tag].join(', ')); + } + }; + + const handleDeleteTag = (tagToDelete) => { + const updatedTags = tags.filter((tag) => tag !== tagToDelete); + setTags(updatedTags); + formMethods.setValue('tags', updatedTags.join(', ')); + }; + const updateDeckFields = [ + { name: 'name', label: 'Name', type: 'text', icon: null, required: true }, + { + name: 'description', + label: 'Description', + type: 'text', + multiline: true, + rows: 4, + icon: null, + required: false, + }, + { + name: 'tags', + label: 'Tags', + type: 'chips', + chipData: tags, + icon: null, + onAddChip: handleAddTag, + onDeleteChip: handleDeleteTag, + required: false, + }, + { + name: 'color', + label: 'Color', + type: 'select', + icon: null, + required: false, + options: [ + { value: 'red', label: 'Red' }, + { value: 'blue', label: 'Blue' }, + { value: 'green', label: 'Green' }, + { value: 'yellow', label: 'Yellow' }, + { value: 'purple', label: 'Purple' }, + { value: 'pink', label: 'Pink' }, + { value: 'orange', label: 'Orange' }, + { value: 'teal', label: 'Teal' }, + ], + }, + ]; + + const addDeckFields = [ + { name: 'name', label: 'Name', type: 'text', icon: null, required: true }, + { + name: 'description', + label: 'Description', + type: 'text', + multiline: true, + rows: 4, + icon: null, + required: false, + }, + ]; + + const formId = isUpdateMode ? 'updateDeckForm' : 'addDeckForm'; + const fields = isUpdateMode ? updateDeckFields : addDeckFields; + + React.useEffect(() => { + if (!isUpdateMode) { + setFormSchema(formId); + } + }, [setFormSchema, formId, isUpdateMode]); + + const handleSubmit = (data) => { + if (isUpdateMode) { + console.log('Submitting update deck data:', data); + onSubmit(data); + } else { + console.log('Add Deck Data:', data); + onSubmit(data); + } + }; + + const handleDelete = () => { + if (isUpdateMode) { + console.log('Deleting deck:', deckData._id); + onSubmit({ _id: deckData._id, delete: true }, formId); + } + }; + + return ( + } + initialValues={deckData} + additionalData={{ + deckId: deckData ? deckData?._id : null, + }} + // additionalButtons={[ + // { + // label: 'Delete Deck', + // startIcon: , + // onClick: () => { + // formMethods.setValue('_id', deck?._id); + // formMethods.setValue('delete', true); + // formMethods.submitForm(); + // }, + // color: 'error', + // variant: 'contained', + // }, + // ]} + additionalButtons={ + isUpdateMode + ? [ + { + label: 'Delete Deck', + onClick: handleDelete, + startIcon: , + color: 'error', + variant: 'contained', + disabled: !deckData, + }, + ] + : [] + } + defaultValues={isUpdateMode ? deckData : {}} + /> + ); +}; + +export default DeckForm; diff --git a/src/components/forms/reusable/FormField.jsx b/src/components/forms/reusable/FormField.jsx index 776600d..edce8e4 100644 --- a/src/components/forms/reusable/FormField.jsx +++ b/src/components/forms/reusable/FormField.jsx @@ -3,8 +3,17 @@ import PropTypes from 'prop-types'; // Import PropTypes import { useMode } from '../../../context'; import { StyledTextField } from '../../../layout/REUSABLE_STYLED_COMPONENTS/ReusableStyledComponents'; -const FormField = ({ name, register, errors, ...props }) => { +const FormField = ({ + name, + register, + initialValue, + value, + errors, + ...props +}) => { const { theme } = useMode(); + const showLabel = !initialValue; + return ( { fullWidth variant="outlined" theme={theme} + InputLabelProps={{ + shrink: showLabel ? undefined : true, + }} {...props} + sx={{}} /> ); }; @@ -24,10 +37,8 @@ FormField.propTypes = { name: PropTypes.string.isRequired, // Name is a required string register: PropTypes.func.isRequired, // Register is a required function errors: PropTypes.object, // Errors is an object, not necessarily required - theme: PropTypes.object, // Theme is an object, not necessarily required - // CONTROLLED FIELDS - value: PropTypes.string, // Value is a string, not necessarily required + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), // Value can be string or number }; // Define default props if there are any optional props diff --git a/src/components/forms/reusable/RCZodForm.jsx b/src/components/forms/reusable/RCZodForm.jsx index 1117973..a9a1ebd 100644 --- a/src/components/forms/reusable/RCZodForm.jsx +++ b/src/components/forms/reusable/RCZodForm.jsx @@ -22,6 +22,8 @@ const RCZodForm = ({ startIcon, schemaName, additionalButtons, + initialValues, + additionalData, }) => { const { theme } = useMode(); const { @@ -29,24 +31,36 @@ const RCZodForm = ({ onSubmit, handleChange, setFormSchema, + currentForm, formState: { errors, isSubmitting }, // getValues, handleSearchTermChange, } = useFormContext(); + // useEffect(() => { + // setFormSchema(schemaName); + // }, [setFormSchema, schemaName]); + // useEffect(() => { + // setFormSchema(schemaName); + // if (initialValues) { + // console.log('initialValues:', initialValues); + // formMethods.reset(initialValues); + // } + // }, [setFormSchema, schemaName, formMethods, initialValues]); useEffect(() => { setFormSchema(schemaName); - }, [setFormSchema, schemaName]); - + // When currentForm or schemaName changes, reset form with new initialValues or empty values + formMethods.reset(initialValues || {}); + }, [setFormSchema, schemaName, formMethods, initialValues, currentForm]); const onFormSubmit = (data) => { - onSubmit(data, schemaName); + onSubmit(data, additionalData); }; const renderField = (field) => { const isSearchForm = schemaName === 'searchForm' && field.name === 'searchTerm'; - const onChange = isSearchForm ? handleSearchTermChange : undefined; + const onChange = isSearchForm ? handleChange : undefined; if (field.type === 'select') { return ( @@ -56,7 +70,24 @@ const RCZodForm = ({
- {}} - headerGroups={headerGroups} - isSorted={isSorted} - setSortedValue={setSortedValue} - /> - {/* Table Body */} - - {page.map((row, key) => { - prepareRow(row); - return ( - - {row.cells.map((cell, idx) => ( - - {cell.render('Cell')} - - ))} - - ); - })} - -
+ + + + {}} + headerGroups={headerGroups} + isSorted={isSorted} + setSortedValue={setSortedValue} + /> + + {/* Table Body */} + + {page.map((row, key) => { + prepareRow(row); + return ( + + {' '} + + {row.cells.map((cell, idx) => ( + + {cell.render('Cell')} + + ))} + + + ); + })} + +
+
{/* Pagination */} - + + + ); diff --git a/src/layout/collection/data/collectionPortfolioData.jsx b/src/layout/collection/data/collectionPortfolioData.jsx index e77ddca..ae256ca 100644 --- a/src/layout/collection/data/collectionPortfolioData.jsx +++ b/src/layout/collection/data/collectionPortfolioData.jsx @@ -84,6 +84,7 @@ export default function prepareTableData(selectedCards) { Cell: ({ value }) => ( console.log('clicked')} onSuccess={() => diff --git a/src/layout/sections/HeroIconSection.jsx b/src/layout/sections/HeroIconSection.jsx index bca42a8..15a0d4d 100644 --- a/src/layout/sections/HeroIconSection.jsx +++ b/src/layout/sections/HeroIconSection.jsx @@ -8,6 +8,7 @@ import { Zoom, useMediaQuery } from '@mui/material'; import SimpleCard from '../../layout/REUSABLE_COMPONENTS/unique/SimpleCard'; import uniqueTheme from '../../layout/REUSABLE_COMPONENTS/unique/uniqueTheme'; import { useMode } from '../../context'; +import { AspectRatio } from '@mui/joy'; const heroCardData = [ { id: 'herodata-1-store-add', @@ -50,11 +51,18 @@ const HeroIconSection = ({ shouldShow }) => { flexDirection: 'row', padding: 1, width: '100%', - height: isMobileView ? 'calc(100vh - 64px)' : '20%', + zIndex: 5, + height: isMobileView ? 'calc(100vh - 64px)' : null, + maxHeight: isMobileView ? 'calc(100vh - 64px)' : 200, + overFlow: 'hidden', // Hide overflow to maintain the card's dimensions + background: 'transparent', + my: isMobileView ? null : 1, + // minHeight: isMobileView ? 'calc(100vh - 64px)' : '30vh', alignItems: isMobileView ? 'flex-end' : 'center', position: isMobileView ? 'absolute' : 'relative', // borderRadius: 'none', - mt: isMobileView ? null : '2rem', + // mt: isMobileView ? null : '2rem', + borderColor: 'transparent', }} > @@ -63,24 +71,64 @@ const HeroIconSection = ({ shouldShow }) => { textAlign: 'center', width: '100%', maxWidth: '100%', + maxHeight: 200, + overFlow: 'hidden', // Hide overflow to maintain the card's dimensions + // height: isMobileView ? 'calc(100vh - 64px)' : '20%', flexDirection: 'row', display: 'flex', + borderColor: 'transparent', justifyContent: 'space-between', - // border: 'none', - // margin: 'auto', - // display: 'flex', - // flexDirectinon: 'row', + alignItems: 'center', + mx: isMobileView ? null : 'auto', + pt: isMobileView ? '1rem' : 'auto', + // my: isMobileView ? null : 'auto', + // py: '1.5rem', + background: 'transparent', + // minHeight: '30vh', + // position: isMobileView ? 'absolute' : 'relative', }} > {heroCardData?.map((card, index) => ( - - - + + + + + ))} diff --git a/src/layout/sections/HeroSection.jsx b/src/layout/sections/HeroSection.jsx index c8b1202..e8b0aec 100644 --- a/src/layout/sections/HeroSection.jsx +++ b/src/layout/sections/HeroSection.jsx @@ -1,5 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { useMode, useStatisticsStore } from '../../context'; +import React, { useEffect, useMemo, useState } from 'react'; +import { ErrorBoundary, useMode, useStatisticsStore } from '../../context'; import MDBox from '../../layout/REUSABLE_COMPONENTS/MDBOX'; import placeHolder from '../../assets/images/placeholder.jpeg'; import { Swiper, SwiperSlide } from 'swiper/react'; @@ -15,62 +15,103 @@ import { } from 'swiper/modules'; import MDTypography from '../../layout/REUSABLE_COMPONENTS/MDTYPOGRAPHY/MDTypography'; import { HeroSectionSkeleton } from '../../layout/REUSABLE_COMPONENTS/SkeletonVariants'; -import { Card, useMediaQuery } from '@mui/material'; +import { + Box, + Card, + CardContent, + CardMedia, + Zoom, + useMediaQuery, +} from '@mui/material'; import pages from '../../data/pages.json'; import HeroTextSection from './HeroTextSection'; import HeroIconSection from './HeroIconSection'; import HeroSwiper from './HeroSwiper'; import FlexBetween from '../REUSABLE_COMPONENTS/FlexBetween'; +import RCHeader from '../REUSABLE_COMPONENTS/RCHeader'; +import styled from 'styled-components'; +import { ChartArea } from '../../pages/pageStyles/StyledComponents'; +import { useCardStoreHook } from '../../context/hooks/useCardStore'; +import useLocalStorage from '../../context/hooks/useLocalStorage'; +import { AspectRatio } from '@mui/joy'; +import { useLoading } from '../../context/hooks/useLoading'; +import useSkeletonLoader from '../collection/collectionGrids/cards-datatable/useSkeletonLoader'; +import { + ResponsiveContainer, + CartesianGrid, + AreaChart, + BarChart, + Bar, + LineChart, + XAxis, + YAxis, + Legend, + Line, + Tooltip, + Area, +} from 'recharts'; +import DashboardBox from '../REUSABLE_COMPONENTS/DashboardBox'; +import BoxHeader from '../REUSABLE_COMPONENTS/BoxHeader'; const HeroSection = () => { const { theme } = useMode(); const { breakpoints } = theme; const { introText } = pages; + const { fetchRandomCardsAndSet } = useCardStoreHook(); + const [randomCards, setRandomCards] = useLocalStorage('randomCards', []); const isMobileView = useMediaQuery(breakpoints.down('sm')); + const isMidView = useMediaQuery(breakpoints.down('md')); const isFullView = useMediaQuery(breakpoints.up('lg')); + const { isLoading } = useLoading(); + const { SkeletonLoader } = useSkeletonLoader(); const [activeCardIndex, setActiveCardIndex] = useState(0); const [shouldShow, setShouldShow] = useState(false); - const { topFiveCards } = useStatisticsStore(); const defaultCards = new Array(45).fill({}).map((_, index) => ({ id: `default-${index}`, name: `Placeholder ${index + 1}`, description: `Description for Placeholder ${index + 1}`, image: placeHolder, })); - const cards = [...topFiveCards, ...defaultCards]; - const swiperConfig = { - effect: 'coverflow', - grabCursor: true, - centeredSlides: true, - loop: true, - resizeObserver: true, - spaceBetween: 10, - coverflowEffect: { - stretch: 0, - modifier: 1, - rotate: 0, - depth: 200, - slideShadows: false, - }, - autoplay: { - delay: 2500, - disableOnInteraction: false, - }, - modules: [EffectCoverflow, Pagination, Navigation, Autoplay], - scrollbar: { - el: '.swiper-scrollbar', - draggable: true, - }, - navigation: { - nextEl: '.swiper-button-next', - prevEl: '.swiper-button-prev', - clickable: true, - }, - className: 'swiper_container', - }; + const cards = [...randomCards, ...defaultCards]; + // const swiperConfig = { + // effect: 'coverflow', + // grabCursor: true, + // centeredSlides: true, + // loop: true, + // resizeObserver: true, + // spaceBetween: 10, + // coverflowEffect: { + // stretch: 0, + // modifier: 1, + // rotate: 0, + // depth: 200, + // slideShadows: false, + // }, + // autoplay: { + // delay: 2500, + // disableOnInteraction: false, + // }, + // modules: [EffectCoverflow, Pagination, Navigation, Autoplay], + // scrollbar: { + // el: '.swiper-scrollbar', + // draggable: true, + // }, + // navigation: { + // nextEl: '.swiper-button-next', + // prevEl: '.swiper-button-prev', + // clickable: true, + // }, + // className: 'swiper_container', + // }; useEffect(() => setShouldShow(true), []); + useEffect(() => fetchRandomCardsAndSet(), []); const handleSlideChange = (swiper) => setActiveCardIndex(swiper.realIndex); + if (!randomCards.length) return ; + + const chartData = useMemo(() => { + return randomCards[activeCardIndex]?.averagedChartData?.['30d']?.data || []; + }, [randomCards, activeCardIndex]); if (!cards.length) { return ; @@ -83,41 +124,158 @@ const HeroSection = () => { position: 'relative', minHeight: isMobileView ? 'calc(100vh - 64px)' : 'calc(100vh - 64px)', flexDirection: isMobileView ? 'column' : 'row', + // flexDirection: 'column', }} > + {!isMidView && ( + + + + + + {/* */} + {/* */} + + + {/* */} + + + + + + + + + + + + + + {' '} + + + + + + + + + + + + )} - {/* */} { + const swiperRef = useRef(null); + const swiperConfig = { effect: 'coverflow', grabCursor: true, @@ -51,6 +53,26 @@ const HeroSwiper = ({ className: 'swiper_container', }; + useEffect(() => { + // Ensuring the swiper instance is available + const swiperInstance = swiperRef.current?.swiper; + if (swiperInstance) { + // Listen to slideChange event + swiperInstance.on('slideChange', () => { + const { activeIndex } = swiperInstance; + handleSlideChange(activeIndex); // Assuming this function you pass handles updating activeCardIndex + + // Check if the slide is every 4th slide (0-indexed, so we check for 3, 7, 11, ...) + if ((activeIndex + 1) % 4 === 0) { + swiperInstance.autoplay.stop(); + setTimeout(() => { + swiperInstance?.autoplay?.start(); + }, 10000); // Pause for 30 seconds + } + }); + } + }, []); + return ( { background: 'transparent', alignItems: isMobileView ? 'flex-start' : 'center', padding: 1, + my: isMobileView ? null : 1, width: isMobileView ? '100%' : '100%', - height: isMobileView ? 'calc(100vh - 64px)' : '30%', position: isMobileView ? 'absolute' : 'relative', - mt: isMobileView ? null : '25%', - // borderRadius: 'none', - // my: isMobileView ? null : '30%', }} > @@ -28,10 +25,12 @@ const HeroTextSection = ({ shouldShow }) => { textAlign: 'center', background: 'transparent', maxWidth: '100%', - height: isMobileView ? '20vh' : '100%', + height: isMobileView ? null : '100%', alignItems: isMobileView ? 'center' : 'center', // mt: isMobileView ? '0.5rem' : 'auto', mx: 'auto', + my: 'auto', + borderColor: 'transparent', }} > { sx={{ fontWeight: 'bold', color: theme.palette.primary.main, - // marginBottom: 2, - mt: isMobileView ? '5%' : '10%', + my: isMobileView ? '1rem' : 'auto', }} > A New Era of Trading Card Games diff --git a/src/pages/CartPage.js b/src/pages/CartPage.js index d7477f5..b9e0458 100644 --- a/src/pages/CartPage.js +++ b/src/pages/CartPage.js @@ -6,8 +6,7 @@ import { useCartStore, useMode } from '../context'; import Checkout from '../layout/cart/cartPageContainers/Checkout'; import PageLayout from '../layout/REUSABLE_COMPONENTS/PageLayout'; import { useLoading } from '../context/hooks/useLoading'; -import { CartSummary } from '../layout/cart/CartSummary'; - +import CartSummary from '../layout/cart/CartSummary'; const CartPage = () => { const { theme } = useMode(); const { @@ -34,8 +33,6 @@ const CartPage = () => { stopLoading('isPageLoading'); } }; - - // Fetch cart data if not already loaded if (!cartData) { fetchData(); } @@ -48,16 +45,6 @@ const CartPage = () => { console.error('Failed to adjust quantity in cart:', e); } }; - // Function to render the cart content grid - const renderCartContent = () => ( - - - - ); // Function to render the checkout and summary section const renderCheckoutAndSummary = () => ( @@ -94,7 +81,13 @@ const CartPage = () => { }} > - {renderCartContent()} + + + {' '} {renderCheckoutAndSummary()}