diff --git a/package.json b/package.json index 022d33d..eeabcb7 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "react-scripts": "5.0.1", "react-slick": "^0.29.0", "react-spinners": "^0.13.8", + "react-spring": "^9.7.3", "react-stripe-checkout": "^2.6.3", "react-swipeable-views": "^0.14.0", "slick-carousel": "^1.8.1", diff --git a/src/assets/animations/CardRowsAnimation.jsx b/src/assets/animations/CardRowsAnimation.jsx new file mode 100644 index 0000000..fc6f40b --- /dev/null +++ b/src/assets/animations/CardRowsAnimation.jsx @@ -0,0 +1,108 @@ +import React, { useEffect, useRef } from 'react'; +import * as THREE from 'three'; +import placeholder from '../images/placeholder.jpeg'; + +const CardRowsAnimation = () => { + const containerRef = useRef(null); + + useEffect(() => { + // Scene setup + const scene = new THREE.Scene(); + const camera = new THREE.PerspectiveCamera( + 75, + window.innerWidth / window.innerHeight, + 0.1, + 1000 + ); + const renderer = new THREE.WebGLRenderer(); + renderer.setSize(window.innerWidth, window.innerHeight); + + // Append renderer to the container ref + if (containerRef.current) { + containerRef.current.appendChild(renderer.domElement); + } + + // Camera position + camera.position.z = 5; + + // Texture loader + const textureLoader = new THREE.TextureLoader(); + const cardTexture = textureLoader.load(placeholder); + + // Define card geometry and material + const geometry = new THREE.PlaneGeometry(1, 1.4); + const material = new THREE.MeshBasicMaterial({ map: cardTexture }); + + // Rows and columns configuration + const rows = 4; + const cardSpacing = 1.8; + let cardsPerRow = Math.floor( + window.innerWidth / (geometry.parameters.width * cardSpacing) + ); + + // Create card meshes and add to scene + const cardRows = []; + for (let i = 0; i < rows; i++) { + const row = new THREE.Group(); + for (let j = 0; j < cardsPerRow; j++) { + const card = new THREE.Mesh(geometry, material); + card.position.x = (j - cardsPerRow / 2) * cardSpacing; + card.position.y = (i - rows / 2) * cardSpacing; + row.add(card); + } + // Alternate direction for each row + row.userData = { direction: i % 2 === 0 ? 0.005 : -0.005 }; + cardRows.push(row); + scene.add(row); + } + + // Animation loop + const animate = () => { + requestAnimationFrame(animate); + + // Update card positions + cardRows.forEach((row) => { + row.children.forEach((card) => { + card.position.x += row.userData.direction; + // Reset position if it's off-screen + if ( + card.position.x > window.innerWidth / 2 || + card.position.x < -window.innerWidth / 2 + ) { + card.position.x = -card.position.x; + } + }); + }); + + 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 = Math.floor( + window.innerWidth / (geometry.parameters.width * cardSpacing) + ); + } + + animate(); + + // Cleanup + return () => { + if (containerRef.current) { + containerRef.current.removeChild(renderer.domElement); + } + window.removeEventListener('resize', onWindowResize, false); + }; + }, []); + + return ( +
+ ); +}; + +export default CardRowsAnimation; diff --git a/src/assets/animations/CardStormAnimation.jsx b/src/assets/animations/CardStormAnimation.jsx new file mode 100644 index 0000000..344f72a --- /dev/null +++ b/src/assets/animations/CardStormAnimation.jsx @@ -0,0 +1,140 @@ +import React, { useRef, useEffect } from 'react'; +import * as THREE from 'three'; +import placeholder from '../images/placeholder.jpeg'; + +const CardStormAnimation = () => { + const mountRef = useRef(null); + const cards = []; + const textureLoader = new THREE.TextureLoader(); + // Configuration + const initialPullRange = 1; + const orderlinessThreshold = 300; + const gravitationalPull = 0.01; + const rotationSpeed = 0.005; // Uniform rotation speed for all cards + + useEffect(() => { + const scene = new THREE.Scene(); + const camera = new THREE.PerspectiveCamera( + 75, + window.innerWidth / window.innerHeight, + 0.1, + 1000 + ); + const renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize(window.innerWidth, window.innerHeight); + renderer.shadowMap.enabled = true; + mountRef.current.appendChild(renderer.domElement); + + // Lighting + const ambientLight = new THREE.AmbientLight(0x999999); + scene.add(ambientLight); + const pointLight = new THREE.PointLight(0xffffff, 1, 100); + pointLight.position.set(10, 10, 10); + pointLight.castShadow = true; + scene.add(pointLight); + + // Card creation + for (let i = 0; i < 100; i++) { + const geometry = new THREE.BoxGeometry(0.5, 0.7, 0.01); + const material = new THREE.MeshStandardMaterial({ + map: textureLoader.load(placeholder), + }); + const card = new THREE.Mesh(geometry, material); + card.position.set( + (Math.random() - 0.5) * 10, + (Math.random() - 0.5) * 10, + (Math.random() - 0.5) * 10 + ); + card.castShadow = true; + card.receiveShadow = true; + cards.push(card); + scene.add(card); + } + + camera.position.z = 5; + + // Mouse position + let mouseX = 0, + mouseY = 0; + const onDocumentMouseMove = (event) => { + const vector = new THREE.Vector3( + (event.clientX / window.innerWidth) * 2 - 1, + -(event.clientY / window.innerHeight) * 2 + 1, + 0.5 + ); + vector.unproject(camera); + const dir = vector.sub(camera.position).normalize(); + const distance = -camera.position.z / dir.z; + const pos = camera.position.clone().add(dir.multiplyScalar(distance)); + mouseX = pos.x; + mouseY = pos.y; + }; + document.addEventListener('mousemove', onDocumentMouseMove, false); + + const animate = () => { + requestAnimationFrame(animate); + + cards.forEach((card) => { + const dx = card.position.x - mouseX; + const dy = card.position.y - mouseY; + const distance = Math.sqrt(dx * dx + dy * dy); + const angle = Math.atan2(dy, dx); + + if (distance < initialPullRange || card.isInfluenced) { + card.isInfluenced = true; + card.timeInfluenced = card.timeInfluenced || 0; + card.timeInfluenced++; + + if (card.timeInfluenced > orderlinessThreshold) { + const targetRotation = Math.atan2( + mouseY - card.position.y, + mouseX - card.position.x + ); + card.rotation.z = THREE.MathUtils.lerp( + card.rotation.z, + targetRotation, + 0.01 + ); + } + + // Velocity for orbital movement + card.velocityX = card.velocityX || 0.01 * (Math.random() - 0.5); + card.velocityY = card.velocityY || 0.01 * (Math.random() - 0.5); + + card.velocityX -= gravitationalPull * Math.cos(angle); + card.velocityY -= gravitationalPull * Math.sin(angle); + + card.position.x += card.velocityX; + card.position.y += card.velocityY; + + // Reducing gravitational pull gradually + if (card.timeInfluenced > orderlinessThreshold) { + const pullReductionFactor = + 1 - + (card.timeInfluenced - orderlinessThreshold) / + orderlinessThreshold; + card.velocityX *= pullReductionFactor; + card.velocityY *= pullReductionFactor; + } + } + + // Applying continuous rotation for a smooth effect + card.rotation.x += rotationSpeed; + card.rotation.y += rotationSpeed; + }); + + renderer.render(scene, camera); + }; + animate(); + + // Clean up + return () => { + mountRef?.current?.removeChild(renderer.domElement); + document?.removeEventListener('mousemove', onDocumentMouseMove, false); + }; + }, []); // Only re-run the effect if mountRef changes + + return
; +}; + +export default CardStormAnimation; diff --git a/src/assets/animations/SingleCardAnimation.jsx b/src/assets/animations/SingleCardAnimation.jsx new file mode 100644 index 0000000..7bc8923 --- /dev/null +++ b/src/assets/animations/SingleCardAnimation.jsx @@ -0,0 +1,120 @@ +import React, { useRef } from 'react'; +import { useSpring, animated } from 'react-spring'; +import placeholder from '../../assets/images/placeholder.jpeg'; + +const SingleCardAnimation = ({ cardImage }) => { + const containerRef = useRef(null); + + // Default the card image to placeholder if it's null/undefined + const frontImage = cardImage || placeholder; + + const [tilt, setTilt] = useSpring(() => ({ + xys: [0, 0, 1], // Initial values for tilt [rotateX, rotateY, scale] + config: { mass: 5, tension: 350, friction: 40 }, + })); + + const calcTilt = (x, y) => { + const rect = containerRef.current.getBoundingClientRect(); + const relX = x - rect.left - rect.width / 2; + const relY = y - rect.top - rect.height / 2; + // Update tilt based on mouse position over the card + return [relY / 10, relX / 10, 1.1]; // Adjust sensitivity and scale here + }; + + const handleMouseMove = (event) => { + setTilt({ xys: calcTilt(event.clientX, event.clientY) }); + }; + + const handleMouseLeave = () => { + setTilt({ xys: [0, 0, 1] }); + }; + + return ( + + `perspective(1000px) rotateX(${x}deg) rotateY(${y}deg) scale(${s})` + ), + position: 'relative', + }} + /> + ); +}; + +export default SingleCardAnimation; + +// import React, { useRef } from 'react'; +// import { useSpring, animated } from 'react-spring'; +// import placeholder from '../../assets/images/placeholder.jpeg'; + +// const SingleCardAnimation = ({ cardImage }) => { +// const containerRef = useRef(null); + +// // Default the card image to placeholder if it's null/undefined +// const frontImage = cardImage || placeholder; + +// const [props, set] = useSpring(() => ({ +// to: { opacity: 1, transform: 'rotateY(0deg)' }, +// from: { opacity: 0.5, transform: 'rotateY(180deg)' }, +// config: { mass: 5, tension: 500, friction: 80 }, +// })); + +// // Handle mouse enter and leave for tilt effect +// const handleMouseEnter = () => set({ transform: 'rotateY(0deg)' }); +// const handleMouseLeave = () => set({ transform: 'rotateY(180deg)' }); + +// return ( +//
+// +// {/* Front Side */} +// + +// {/* Back Side */} +// +// +//
+// ); +// }; + +// export default SingleCardAnimation; diff --git a/src/assets/animations/SingleCardRowAnimation.jsx b/src/assets/animations/SingleCardRowAnimation.jsx new file mode 100644 index 0000000..a150ab0 --- /dev/null +++ b/src/assets/animations/SingleCardRowAnimation.jsx @@ -0,0 +1,122 @@ +import React, { useEffect, useRef } from 'react'; +import * as THREE from 'three'; +import placeholder from '../../assets/images/placeholder.jpeg'; + +const SingleCardRowAnimation = () => { + const containerRef = useRef(null); + + useEffect(() => { + let camera, scene, renderer, cardRow, cardTexture; + + const textureLoader = new THREE.TextureLoader(); + cardTexture = textureLoader.load(placeholder); // Load the texture once and reuse it + + const calculateCardsPerRow = () => { + const cardWidth = 1 * 1.8; // assuming geometry and spacing are constant + return Math.floor(containerRef.current.clientWidth / cardWidth); + }; + + const updateRowWithNewCardCount = (cardsPerRow) => { + const geometry = new THREE.PlaneGeometry(1, 1.4); + const material = new THREE.MeshBasicMaterial({ map: cardTexture }); + while (cardRow.children.length) { + cardRow.remove(cardRow.children[0]); + } + for (let j = 0; j < cardsPerRow; j++) { + const card = new THREE.Mesh(geometry, material); + card.position.x = (j - cardsPerRow / 2) * 1.8; + card.position.y = -containerRef.current.clientHeight / 2 + 1.4 / 2; // Top position + cardRow.add(card); + } + }; + + const onWindowResize = () => { + camera.aspect = + containerRef.current.clientWidth / containerRef.current.clientHeight; + camera.updateProjectionMatrix(); + renderer.setSize( + containerRef.current.clientWidth, + containerRef.current.clientHeight + ); + const newCardsPerRow = calculateCardsPerRow(); + updateRowWithNewCardCount(newCardsPerRow); + }; + + const onSetup = () => { + scene = new THREE.Scene(); + camera = new THREE.PerspectiveCamera( + 75, + containerRef.current.clientWidth / containerRef.current.clientHeight, + 0.1, + 1000 + ); + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( + containerRef.current.clientWidth, + containerRef.current.clientHeight + ); + containerRef.current.appendChild(renderer.domElement); + camera.position.z = 5; + + const geometry = new THREE.PlaneGeometry(1, 1.4); + const material = new THREE.MeshBasicMaterial({ map: cardTexture }); + + let cardsPerRow = calculateCardsPerRow(); + const topPosition = -containerRef.current.clientHeight / 2 + 1.4 / 2; + + cardRow = new THREE.Group(); + for (let j = 0; j < cardsPerRow; j++) { + const card = new THREE.Mesh(geometry, material); + card.position.x = (j - cardsPerRow / 2) * 1.8; + card.position.y = topPosition; + cardRow.add(card); + } + cardRow.userData = { direction: 0.005 }; + scene.add(cardRow); + + const animate = () => { + requestAnimationFrame(animate); + cardRow.children.forEach((card) => { + card.position.x += cardRow.userData.direction; + wrapPosition(card); + }); + renderer.render(scene, camera); + }; + + const wrapPosition = (card) => { + if ( + card.position.x > + containerRef.current.clientWidth / 2 + 1 / 2 // considering the width of the card is 1 unit + ) { + card.position.x = -containerRef.current.clientWidth / 2 - 1 / 2; + } else if ( + card.position.x < + -containerRef.current.clientWidth / 2 - 1 / 2 + ) { + card.position.x = containerRef.current.clientWidth / 2 + 1 / 2; + } + }; + + animate(); + }; + + if (containerRef.current) { + onSetup(); + } + + window.addEventListener('resize', onWindowResize); + + return () => { + if (containerRef.current) { + containerRef.current.removeChild(renderer.domElement); + } + window.removeEventListener('resize', onWindowResize); + }; + }, []); + + return ( +
+ ); +}; + +export default SingleCardRowAnimation; diff --git a/src/assets/themeSettings.jsx b/src/assets/themeSettings.jsx index 6a8283f..f75a57f 100644 --- a/src/assets/themeSettings.jsx +++ b/src/assets/themeSettings.jsx @@ -1,8 +1,42 @@ import { tokens } from './tokens'; +// Utility function to convert Hex to RGBA +function hexToRgba(hex, alpha = 1) { + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + let shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, function (m, r, g, b) { + return 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; +} export const themeSettings = (mode) => { const colors = tokens(mode); + const backgroundA = { + darkest: '#70d8bd', // '#70d8bd', + darker: '#70d8bd', + dark: '#70d8bd', + default: '#4cceac', // '#4cceac', + light: '#4cceac', + lighter: '#4cceac', + lightest: '#4cceac', + }; + const backgroundB = { + darkest: '#111', + darker: '#222', + dark: '#333', + default: '#444', + light: '#555', + lighter: '#666', + lightest: '#777', + }; + return { width: '100vw', palette: { @@ -61,6 +95,45 @@ export const themeSettings = (mode) => { disabled: colors.grey[200], // paper: mode === 'dark' ? colors.grey[300] : '#ffffff', }, + backgroundA: { + darkest: '#70d8bd', // '#70d8bd', + darker: '#70d8bd', + dark: '#70d8bd', + default: '#4cceac', // '#4cceac', + light: '#4cceac', + lighter: '#4cceac', + lightest: '#4cceac', + }, + backgroundB: { + darkest: '#111', + darker: '#222', + dark: '#333', + default: '#444', + light: '#555', + lighter: '#666', + lightest: '#777', + contrastText: '#FBFAF2', + }, + backgroundC: { + darkest: hexToRgba(backgroundB.darkest, 0.9), + darker: hexToRgba(backgroundB.darker, 0.8), + dark: hexToRgba(backgroundB.dark, 0.7), + default: hexToRgba(backgroundB.default, 0.6), + light: hexToRgba(backgroundB.light, 0.5), + lighter: hexToRgba(backgroundB.lighter, 0.4), + lightest: hexToRgba(backgroundB.lightest, 0.3), + contrastText: '#FBFAF2', + }, + backgroundD: { + darkest: hexToRgba(backgroundA.darkest, 0.9), + darker: hexToRgba(backgroundA.darker, 0.7), + dark: hexToRgba(backgroundA.dark, 0.6), + default: hexToRgba(backgroundA.default, 0.5), + light: hexToRgba(backgroundA.light, 0.4), + lighter: hexToRgba(backgroundA.lighter, 0.3), + lightest: hexToRgba(backgroundA.lightest, 0.2), + contrastText: '#FBFAF2', + }, error: { main: colors.redAccent[500], dark: colors.redAccent[700], diff --git a/src/components/collection/CardPortfolio.jsx b/src/components/collection/CardPortfolio.jsx index 1ab3a96..8a9aa79 100644 --- a/src/components/collection/CardPortfolio.jsx +++ b/src/components/collection/CardPortfolio.jsx @@ -5,56 +5,62 @@ import { Box, Typography, useTheme } from '@mui/material'; import { useCollectionStore } from '../../context/CollectionContext/CollectionContext'; import { useMode } from '../../context'; import { makeStyles } from '@mui/styles'; -const useCardPortfolioStyles = makeStyles((theme) => ({ - boxStyle: { - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - borderRadius: theme.shape.borderRadius, - flexGrow: 1, - background: '#333', - padding: { - xs: theme.spacing(1), - sm: theme.spacing(1), - md: theme.spacing(2.5), - lg: theme.spacing(2.5), - }, - height: '100%', - width: '100%', - }, -})); +import { usePortfolioStyles } from '../../context/hooks/usePortfolioStyles'; +// const useCardPortfolioStyles = makeStyles((theme) => ({ +// boxStyle: { +// display: 'flex', +// flexDirection: 'column', +// alignItems: 'center', +// justifyContent: 'center', +// borderRadius: theme.shape.borderRadius, +// flexGrow: 1, +// background: '#333', +// padding: { +// xs: theme.spacing(1), +// sm: theme.spacing(1), +// md: theme.spacing(2.5), +// lg: theme.spacing(2.5), +// }, +// height: '100%', +// width: '100%', +// }, +// })); const CardPortfolio = ({ allCollections, onCollectionSelect }) => { const { theme } = useMode(); - const classes = useCardPortfolioStyles(theme); - + const classes = usePortfolioStyles(theme); const [showCollections, setShowCollections] = useState(true); - const [showPortfolio, setShowPortfolio] = useState(false); const [selectedCards, setSelectedCards] = useState([]); const { selectedCollection } = useCollectionStore(); - useEffect(() => { setSelectedCards(selectedCollection?.cards?.slice(0, 30)); }, [selectedCollection]); + useEffect(() => { + if (selectedCollection && !showCollections) { + onCollectionSelect(true); + } + }, [selectedCollection, showCollections, onCollectionSelect]); const handleSelectCollection = (collectionId) => { - const foundCollection = allCollections.find( - (collection) => collection._id === collectionId + const foundCollection = allCollections?.find( + (collection) => collection?._id === collectionId ); if (foundCollection) { setShowCollections(false); - setShowPortfolio(true); - onCollectionSelect(true); } }; + return ( - + {showCollections ? ( - - ) : showPortfolio ? ( - + ) : ( - No Collection Selected + )} ); diff --git a/src/components/collection/PortfolioContent.jsx b/src/components/collection/PortfolioContent.jsx index 750aaf5..2aff7a3 100644 --- a/src/components/collection/PortfolioContent.jsx +++ b/src/components/collection/PortfolioContent.jsx @@ -1,88 +1,41 @@ +// PortfolioContent.jsx import React, { useEffect, useState } from 'react'; -import { Box, Container, Grid, Paper, useTheme } from '@mui/material'; +import { Box, Grid, Paper } from '@mui/material'; import HeaderTitle from '../reusable/HeaderTitle'; -import { useCollectionStore } from '../../context/CollectionContext/CollectionContext'; -import { useMode } from '../../context/hooks/colormode'; // eslint-disable-next-line max-len import CollectionPortfolioChartContainer from '../../containers/collectionPageContainers/CollectionPortfolioChartContainer'; // eslint-disable-next-line max-len import CollectionPortfolioListContainer from '../../containers/collectionPageContainers/CollectionPortfolioListContainer'; -import { makeStyles } from '@mui/styles'; -const useStyles = makeStyles((theme) => ({ - portfolioBox: { - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - maxWidth: '100vw', - width: '100%', - height: '100%', - margin: { xs: 0, sm: 'auto', md: 'auto', lg: 'auto' }, - padding: { - xs: theme.spacing(1), - sm: theme.spacing(2), - md: theme.spacing(3), - lg: theme.spacing(3), - }, - backgroundColor: theme.palette.background.paper, - color: theme.palette.text.primary, - }, - portfolioPaper: { - background: theme.palette.background.main, - 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%', - maxWidth: '100vw', - justifyContent: 'center', - }, - gridItem: { - justifyContent: 'center', - }, -})); +import { useCollectionStore } from '../../context/CollectionContext/CollectionContext'; +import usePortfolioStyles from '../../context/hooks/usePortfolioStyles'; +import { useMode } from '../../context'; const PortfolioContent = ({ selectedCards, removeCard }) => { + const { theme } = useMode(); + const { selectedCollection } = useCollectionStore(); - const [collectionName, setCollectionName] = useState( - selectedCollection?.name - ); - const classes = useStyles(useMode().theme); + const [collectionName, setCollectionName] = useState(''); + const classes = usePortfolioStyles(theme); useEffect(() => { if (selectedCollection?.name) { setCollectionName(selectedCollection.name); } }, [selectedCollection]); + return ( - - - + + + - - + + - + ({ - boxStyle: { - p: 2, - justifyContent: 'center', - margin: 'auto', - }, - typographyStyle: { - fontWeight: 'bold', - color: 'black', - m: 'auto', - }, - button: { - variant: 'outlined', - '& .MuiTypography-root': { - variant: 'button', - [theme.breakpoints.down('sm')]: { - variant: 'caption', - }, - }, - }, -})); +import usePortfolioStyles from '../../context/hooks/usePortfolioStyles'; +import { useMode } from '../../context'; const SelectCollection = ({ handleSelectCollection }) => { const { theme } = useMode(); - const classes = useSelectCollectionStyles(theme); + const classes = usePortfolioStyles(theme); const [isDialogOpen, setDialogOpen] = useState(false); const [isNew, setIsNew] = useState(false); const { setSelectedCollection, selectedCollection } = useCollectionStore(); - const handleOpenCollectionModal = useCallback(() => { - setDialogOpen(true); - setIsNew(true); - }, []); - + const handleDialogToggle = useCallback(() => { + setDialogOpen(!isDialogOpen); + }, [isDialogOpen]); const closeDialog = useCallback(() => setDialogOpen(false), []); + const handleSave = useCallback( (collection) => { setSelectedCollection(collection); @@ -54,57 +26,42 @@ const SelectCollection = ({ handleSelectCollection }) => { }, [setSelectedCollection, closeDialog] ); - - const openDialog = useCallback((isNewCollection) => { - setDialogOpen(true); - setIsNew(isNewCollection); - }, []); + const openNewDialog = () => { + setIsNew(true); + handleDialogToggle(); + }; return ( - - - - - - - Choose a Collection - - - - - - - - + + + + + Choose a Collection + + + + - - openDialog(false)} - /> - - + + - - + + + ); }; -SelectCollection.propTypes = { - handleSelectCollection: PropTypes.func.isRequired, -}; - export default SelectCollection; diff --git a/src/components/dialogs/cardDialog/CardDetailsContainer.jsx b/src/components/dialogs/cardDialog/CardDetailsContainer.jsx index 18413f8..d476662 100644 --- a/src/components/dialogs/cardDialog/CardDetailsContainer.jsx +++ b/src/components/dialogs/cardDialog/CardDetailsContainer.jsx @@ -1,28 +1,34 @@ import React from 'react'; -import { Grid, Typography, useTheme } from '@mui/material'; +import { Grid } from '@mui/material'; import { FaDragon, FaLevelUpAlt, - FaRegCopy, FaRegLightbulb, FaShieldAlt, FaVenusMars, } from 'react-icons/fa'; +import { GiAxeSword } from 'react-icons/gi'; import CardDetail from './CardDetail'; import { styled } from '@mui/system'; +import { useMode } from '../../../context'; -// Styled wrapper for icon for consistent styling const IconWrapper = styled('div')(({ theme }) => ({ display: 'flex', alignItems: 'center', justifyContent: 'center', marginRight: theme.spacing(1), fontSize: '1.5rem', - color: theme.palette.text.secondary, + [theme.breakpoints.down('sm')]: { + fontSize: '1.2rem', + }, + [theme.breakpoints.down('xs')]: { + fontSize: '1rem', + }, + color: theme.palette.text.primary, })); const CardDetailsContainer = ({ card, className }) => { - const theme = useTheme(); + const { theme } = useMode(); return ( @@ -31,15 +37,19 @@ const CardDetailsContainer = ({ card, className }) => { { icon: FaVenusMars, title: 'Type', value: card?.type }, { icon: FaDragon, title: 'Race', value: card?.race }, { icon: FaRegLightbulb, title: 'Attribute', value: card?.attribute }, - { title: 'ATK', value: card?.atk }, + { icon: GiAxeSword, title: 'ATK', value: card?.atk }, { icon: FaShieldAlt, title: 'DEF', value: card?.def }, ].map((detail, index) => ( - + // Adjust Grid item sizing based on breakpoints + // At xs and sm sizes, each detail takes full width making it a single column + // At md size, each detail takes 6 spaces (out of 12), creating 2 equal columns + // For lg and xl, you might want to adjust accordingly or keep the same as md + + ) diff --git a/src/components/dialogs/cardDialog/GenericCardDialog.jsx b/src/components/dialogs/cardDialog/GenericCardDialog.jsx index bb1be0b..9ed87df 100644 --- a/src/components/dialogs/cardDialog/GenericCardDialog.jsx +++ b/src/components/dialogs/cardDialog/GenericCardDialog.jsx @@ -13,7 +13,6 @@ import { IconButton, } from '@mui/material'; import { useTheme } from '@mui/styles'; -import axios from 'axios'; import useSnackbar from '../../../context/hooks/useSnackBar'; import useSelectedContext from '../../../context/hooks/useSelectedContext'; import { @@ -22,13 +21,12 @@ import { useUserContext, } from '../../../context'; import CardMediaSection from '../../cards/media/CardMediaSection'; -import CardCarousel from './CardCarousel'; import GenericActionButtons from '../../buttons/actionButtons/GenericActionButtons'; -import CardDetailsContainer from '../../../containers/CardDetailsContainer'; import CloseIcon from '@mui/icons-material/Close'; import useResponsiveStyles from '../../../context/hooks/useResponsiveStyles'; import CardDetail from './CardDetail'; import { FaRegCopy } from 'react-icons/fa'; +import CardDetailsContainer from './CardDetailsContainer'; const GenericCardDialog = (props) => { const theme = useTheme(); @@ -134,8 +132,12 @@ const GenericCardDialog = (props) => { )} {' '} - - + + {/* these two grid items are for the card media and card details */} @@ -148,7 +150,7 @@ const GenericCardDialog = (props) => { } + // icon={} title="Description" value={card?.desc} /> @@ -158,7 +160,6 @@ const GenericCardDialog = (props) => { {/* these two grid items are for the card carousel and action buttons */} - {['Deck', 'Collection', 'Cart'].map((mappedContext) => ( { const { featureData, detailsModalShow, closeDetailsModal } = useModalContext(); + console.log('featureData', featureData); return ( { > {featureData?.description} - + {featureData?.images?.map((imgSrc, idx) => ( - + {`Image { style={{ borderRadius: '8px', boxShadow: '0 4px 8px rgba(0,0,0,0.1)', + maxWidth: '100%', + maxHeight: '100%', + objectFit: 'contain', // ensures the aspect ratio is preserved + margin: 'auto', }} /> diff --git a/src/containers/CardDetailsContainer.jsx b/src/containers/CardDetailsContainer.jsx index 066717a..452ea69 100644 --- a/src/containers/CardDetailsContainer.jsx +++ b/src/containers/CardDetailsContainer.jsx @@ -1,22 +1,22 @@ -// Import necessary modules from MUI or other libraries -import React from 'react'; -import { Typography, Grid } from '@mui/material'; -import { useStyles } from '../components/cards/cardStyles'; +// // Import necessary modules from MUI or other libraries +// import React from 'react'; +// import { Typography, Grid } from '@mui/material'; +// import { useStyles } from '../components/cards/cardStyles'; -const CardDetailsContainer = ({ card }) => { - const classes = useStyles(); - return ( - - - - {card?.name} - - - {card?.desc || 'No description available.'} - - - - ); -}; +// const CardDetailsContainer = ({ card }) => { +// const classes = useStyles(); +// return ( +// +// +// +// {card?.name} +// +// +// {card?.desc || 'No description available.'} +// +// +// +// ); +// }; -export default CardDetailsContainer; +// export default CardDetailsContainer; diff --git a/src/context/CollectionContext/CollectionContext.jsx b/src/context/CollectionContext/CollectionContext.jsx index 5f9c437..7d2f2dd 100644 --- a/src/context/CollectionContext/CollectionContext.jsx +++ b/src/context/CollectionContext/CollectionContext.jsx @@ -129,9 +129,6 @@ export const CollectionProvider = ({ children }) => { setAllCollections(newData); } if (newData && typeof newData === 'object') { - console.log( - 'SETTING SELECTED CO IN UPDATEDCOLLECTIONDATA --------->' - ); if (newData.cards && !isEqual(newData, selectedCollection)) { setSelectedCollection(newData); setTotalPrice(calculateCollectionValue(newData)); diff --git a/src/context/ModalContext/ModalContext.jsx b/src/context/ModalContext/ModalContext.jsx index bec2e03..9229e53 100644 --- a/src/context/ModalContext/ModalContext.jsx +++ b/src/context/ModalContext/ModalContext.jsx @@ -27,10 +27,7 @@ export const ModalProvider = ({ children }) => { url: 'https://github.com/reedoooo/enhanced-card-store', readmeurl: 'deck-builder-frontend/README.md', images: [ - 'public/images/pages/deckBuilder.png', - - // eslint-disable-next-line max-len - // 'https://github.com/reedoooo/enhanced-card-store/blob/6af330ab4f553bb3279dfa8ed7d30bce098e770f/public/images/pages/deckBuilder.png', + 'https://github.com/reedoooo/enhanced-card-store/blob/main/public/images/pages/deckBuilder.png?raw=true', ], startDate: 'August 2021', endDate: 'September 2021', @@ -44,9 +41,7 @@ export const ModalProvider = ({ children }) => { url: 'https://github.com/reedoooo/enhanced-card-store', readmeurl: 'collection-tracker-frontend/README.md', images: [ - 'public/images/pages/portfolio.png', - // eslint-disable-next-line max-len - // 'https://github.com/reedoooo/enhanced-card-store/blob/6af330ab4f553bb3279dfa8ed7d30bce098e770f/public/images/pages/portfolio.png', + 'https://github.com/reedoooo/enhanced-card-store/blob/main/public/images/pages/portfolio.png?raw=true,', ], startDate: 'August 2021', endDate: 'September 2021', @@ -60,11 +55,7 @@ export const ModalProvider = ({ children }) => { url: 'https://github.com/reedoooo/enhanced-card-store', readmeurl: 'store-frontend/README.md', images: [ - 'public/images/pages/cart.png', - // eslint-disable-next-line max-len - // 'https://github.com/reedoooo/enhanced-card-store/blob/6af330ab4f553bb3279dfa8ed7d30bce098e770f/public/images/pages/cart.png', - // eslint-disable-next-line max-len - // '../assets/images/pages/cart.png', + 'https://github.com/reedoooo/enhanced-card-store/blob/main/public/images/pages/cart.png?raw=true', // eslint-disable-next-line max-len ], startDate: 'August 2021', endDate: 'September 2021', diff --git a/src/context/PageContext/PageContext.jsx b/src/context/PageContext/PageContext.jsx index dfdc638..49ab08f 100644 --- a/src/context/PageContext/PageContext.jsx +++ b/src/context/PageContext/PageContext.jsx @@ -2,6 +2,7 @@ import React, { createContext, useState, useContext } from 'react'; import { SplashPage } from '../../pages'; import LoadingIndicator from '../../components/reusable/indicators/LoadingIndicator'; import ErrorIndicator from '../../components/reusable/indicators/ErrorIndicator'; +import SplashPage2 from '../../pages/otherPages/SplashPage2'; // Creating the context const PageContext = createContext(); @@ -48,7 +49,8 @@ export const PageProvider = ({ children }) => { }; const displaySplashPage = () => { - if (isPageLoading) return ; + // if (isPageLoading) return ; + if (isPageLoading) return ; }; // const setLoader = (isLoading) => { diff --git a/src/context/hooks/usePortfolioStyles.jsx b/src/context/hooks/usePortfolioStyles.jsx new file mode 100644 index 0000000..e4bfacd --- /dev/null +++ b/src/context/hooks/usePortfolioStyles.jsx @@ -0,0 +1,195 @@ +import { makeStyles } from '@mui/styles'; + +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.background.paper, + // color: theme.palette.text.primary, + // }, + + 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, + }, + // paper: { + // background: theme.palette.background.main, + // color: theme.palette.text.primary, + // display: 'flex', + // justifyContent: 'center', + // flexDirection: 'column', + // margin: 'auto', + // width: '100%', + // padding: theme.spacing(1, 2), + // borderRadius: theme.shape.borderRadius, + // }, + // portfolioBox: { + // display: 'flex', + // flexDirection: 'column', + // justifyContent: 'center', + // alignItems: 'center', + // maxWidth: '100vw', + // width: '100%', + // height: '100%', + // margin: { xs: 0, sm: 'auto', md: 'auto', lg: 'auto' }, + // padding: { xs: 1, sm: 2, md: 3, lg: 3 }, + // backgroundColor: theme.palette.background.paper, + // color: theme.palette.text.primary, + // }, + // paper: { + // background: theme.palette.background.main, + // color: theme.palette.text.primary, + // display: 'flex', + // justifyContent: 'center', + // flexDirection: 'column', + // margin: 'auto', + // width: '100%', + // padding: { xs: 1, sm: 1, md: 2, lg: 2 }, + // borderRadius: theme.shape.borderRadius, + // }, + gridContainer: { + width: '100%', + alignItems: 'center', + justifyContent: 'space-between', + padding: theme.spacing(1), + // backgroundColor: theme.palette.background.quinternary, + background: theme.palette.backgroundB.lighter, + }, + gridItem: { + display: 'flex', + justifyContent: 'flex-end', + background: theme.palette.success.main, + }, + portfolioBox: { + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(4), + borderRadius: theme.shape.borderRadius, + flexGrow: 1, + // background: theme.palette.success.main, + background: theme.palette.backgroundC.dark, + padding: theme.spacing(4), + height: 'auto', + width: '100%', + // height: '100%', + boxShadow: theme.shadows[5], + [theme.breakpoints.down('sm')]: { + padding: theme.spacing(2), + }, + }, + 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%', + 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', + }, + }, + button: { + margin: theme.spacing(1), + padding: theme.spacing(1), + backgroundColor: theme.palette.primary.main, + color: theme.palette.getContrastText(theme.palette.primary.main), + transition: 'background-color 0.3s', + '&:hover': { + backgroundColor: theme.palette.primary.dark, + // Elevate button on hover + boxShadow: theme.shadows[2], + }, + }, + // 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.background.paper, + // 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%', + }, + // Add any other styles from CardPortfolio, PortfolioContent, and SelectCollection components +})); + +export default usePortfolioStyles; diff --git a/src/pages/CollectionPage.js b/src/pages/CollectionPage.js index f192040..47a4ce9 100644 --- a/src/pages/CollectionPage.js +++ b/src/pages/CollectionPage.js @@ -41,7 +41,6 @@ const CollectionPage = () => { if (pageError) displayErrorIndicator(); const handleCollectionSelected = (selected) => { - console.log('selected', selected); setIsCollectionSelected(!!selected); }; return ( diff --git a/src/pages/HomePage.js b/src/pages/HomePage.js index 6963d07..102bceb 100644 --- a/src/pages/HomePage.js +++ b/src/pages/HomePage.js @@ -1,15 +1,13 @@ -import React, { useContext } from 'react'; -import { Carousel } from 'react-responsive-carousel'; -import 'react-responsive-carousel/lib/styles/carousel.min.css'; +import React, { useContext, useEffect, useRef } from 'react'; import { Typography, - Stack, CssBaseline, CardActions, CardContent, CardHeader, Grid, Box, + useMediaQuery, } from '@mui/material'; import { useMode } from '../context/hooks/colormode'; import { @@ -17,30 +15,41 @@ import { useModalContext, } from '../context/ModalContext/ModalContext'; import GenericCardDialog from '../components/dialogs/cardDialog/GenericCardDialog'; -import pages from '../assets/pages.json'; -import { CarouselImage } from './pageStyles/CarouselImage'; import DetailsModal from '../components/dialogs/homeDetailsModal/DetailsModal'; import useResponsiveStyles from '../context/hooks/useResponsiveStyles'; import { HomePageBox, - CarouselContainer, - ActionButton, FeatureCard, MainContentContainer, TertiaryContentContainer, SecondaryContentContainer, - CardListItem, CardUnorderedList, + CardListItem, + ActionButton, } from './pageStyles/StyledComponents'; +import { useSpring, animated } from 'react-spring'; + +import SplashPage2 from './otherPages/SplashPage2'; +import pages from '../assets/pages.json'; +import { useTheme } from '@emotion/react'; +import SplashPage3 from './otherPages/SplashPage3'; +import SingleCardRowAnimation from '../assets/animations/SingleCardRowAnimation'; +import SingleCardAnimation from '../assets/animations/SingleCardAnimation'; +import { useCollectionStore } from '../context'; + +const AnimatedBox = animated(Box); const HomePage = () => { const { theme } = useMode(); + const theme2 = useTheme(); + const isSmUp = useMediaQuery(theme.breakpoints.up('sm')); + const { isModalOpen, modalContent } = useContext(ModalContext); + const { selectedCollection } = useCollectionStore(); const { allFeatureData, showDetailsModal, detailsModalShow } = useModalContext(); - const { carouselImages, tiers, introText } = pages; + const { tiers, introText } = pages; const { getTypographyVariant, getIconForTitle } = useResponsiveStyles(theme); - const handleOpenModal = (itemTitle) => { const selectedItem = allFeatureData.find( (item) => item.title === itemTitle @@ -49,10 +58,34 @@ const HomePage = () => { showDetailsModal(selectedItem); } }; + const splashRef = useRef(null); + useEffect(() => { + if (splashRef.current) { + splashRef.current.style.position = 'fixed'; + splashRef.current.style.top = '0'; + splashRef.current.style.left = '0'; + splashRef.current.style.width = '100%'; + splashRef.current.style.height = '100%'; + splashRef.current.style.zIndex = '-1'; + } + }, []); + const titleStyles = { + padding: theme.spacing(2), // consistent padding with the theme + textAlign: 'center', + color: theme.palette.backgroundD.contrastText, + background: theme.palette.background.dark, + borderRadius: theme.shape.borderRadius, + margin: theme.spacing(2), + // Add more styles as per the theme or design requirements + }; return ( +
+ {/* */} + +
{ - - - {carouselImages?.map(({ image, caption }, index) => ( - - ))} - - + + Top Performing Cards + + + {/* This is your animation component */} + + + {tiers.map((tier, index) => { + const [tiltAnimation, setTiltAnimation] = useSpring(() => ({ + transform: + 'perspective(600px) rotateX(0deg) rotateY(0deg) scale(1)', + })); + const handleMouseEnter = () => + setTiltAnimation({ + transform: + 'perspective(600px) rotateX(5deg) rotateY(5deg) scale(1.05)', + }); - - - - {tiers.map((tier) => ( + const handleMouseLeave = () => + setTiltAnimation({ + transform: + 'perspective(600px) rotateX(0deg) rotateY(0deg) scale(1)', + }); + return ( - - + - - - {tier.description.map((line, index) => ( - - {line} {/* Directly using line as content */} - - ))} - - - - handleOpenModal(tier.title)} - > - {tier.buttonText} - - - + style={{ + display: 'flex', + flexDirection: 'column', + height: '100%', + }} + > + + + + {tier.description.map((line, index) => ( + + {line} + + ))} + + + + handleOpenModal(tier.title)} + > + {tier.buttonText} + + + + - ))} - - - + ); + })} + + {isModalOpen && ( { + const containerRef = useRef(null); + + useEffect(() => { + // Scene setup + const scene = new THREE.Scene(); + const camera = new THREE.PerspectiveCamera( + 75, + window.innerWidth / window.innerHeight, + 0.1, + 1000 + ); + 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); + } + + // Camera position + camera.position.z = 5; + + // Texture loader + const textureLoader = new THREE.TextureLoader(); + const cardTexture = textureLoader.load(placeholder); + + // Define card geometry and material + const geometry = new THREE.PlaneGeometry(1, 1.4); + const material = new THREE.MeshBasicMaterial({ map: cardTexture }); + + // Rows and columns configuration + const rows = 4; + const cardSpacing = 1.8; // Spacing between cards + + // Function to calculate the number of cards per row based on current viewport width + const calculateCardsPerRow = () => { + return Math.floor( + window.innerWidth / (geometry.parameters.width * cardSpacing) + ); + }; + + let cardsPerRow = calculateCardsPerRow(); // Initial number of cards per row + + // Create card meshes and add to scene + const cardRows = []; + for (let i = 0; i < rows; i++) { + const row = new THREE.Group(); + for (let j = 0; j < cardsPerRow; j++) { + const card = new THREE.Mesh(geometry, material); + card.position.x = (j - cardsPerRow / 2) * cardSpacing; + card.position.y = (i - rows / 2) * cardSpacing; + row.add(card); + } + // Alternate direction for each row + row.userData = { direction: i % 2 === 0 ? 0.005 : -0.005 }; + cardRows.push(row); + scene.add(row); + } + + // Animation loop + const animate = () => { + requestAnimationFrame(animate); + + // Update card positions + cardRows.forEach((row) => { + row.children.forEach((card) => { + card.position.x += row.userData.direction; + // Wrap position if it's off-screen + if ( + card.position.x > + window.innerWidth / 2 + geometry.parameters.width / 2 + ) { + card.position.x = + -window.innerWidth / 2 - geometry.parameters.width / 2; + } else if ( + card.position.x < + -window.innerWidth / 2 - geometry.parameters.width / 2 + ) { + card.position.x = + window.innerWidth / 2 + geometry.parameters.width / 2; + } + }); + }); + + 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; + row.add(card); + } + }); + } + + 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 ( +
+ ); +}; + +export default SplashPage2; diff --git a/src/pages/otherPages/SplashPage3.jsx b/src/pages/otherPages/SplashPage3.jsx new file mode 100644 index 0000000..2b8ac84 --- /dev/null +++ b/src/pages/otherPages/SplashPage3.jsx @@ -0,0 +1,28 @@ +// SplashPage.js +import React from 'react'; +import { Box, Typography } from '@mui/material'; +import CardStormAnimation from '../../assets/animations/CardStormAnimation'; + +const SplashPage3 = () => { + return ( + + + Welcome to the Card Storm + + + {/* Include the Card Animation */} + + + ); +}; + +export default SplashPage3; diff --git a/src/pages/pageStyles/StyledComponents.jsx b/src/pages/pageStyles/StyledComponents.jsx index 9187c3a..c0d630f 100644 --- a/src/pages/pageStyles/StyledComponents.jsx +++ b/src/pages/pageStyles/StyledComponents.jsx @@ -413,6 +413,10 @@ export const HomePageBox = styled(Box)(({ theme }) => ({ padding: theme.spacing(2, 4, 8), margin: theme.spacing(1, 2, 4), borderRadius: theme.shape.borderRadius, + elevation: 3, + boxShadow: theme.shadows[7], + display: 'flex', + flexDirection: 'column', })); export const CarouselContainer = styled(Paper)(({ theme }) => ({ @@ -445,24 +449,28 @@ export const ActionButton = styled(Button)(({ theme }) => ({ export const MainContentContainer = styled(Container)(({ theme }) => ({ padding: theme.spacing(2, 4, 6), borderRadius: theme.shape.borderRadius, - backgroundColor: theme.palette.background.paper, + backgroundColor: theme.palette.backgroundD.dark, boxShadow: theme.shadows[10], margin: theme.spacing(2, 0), // added vertical spacing })); export const SecondaryContentContainer = styled('div')(({ theme }) => ({ - background: theme.palette.secondary.light, - padding: theme.spacing(2), + background: theme.palette.backgroundD.dark, marginBottom: theme.spacing(2), width: '100%', - display: 'flex', flexDirection: 'column', - alignItems: 'center', boxShadow: theme.shadows[3], borderRadius: theme.shape.borderRadius, - transition: 'background-color 0.3s', // smooth background color transition + transition: 'background-color 0.3s', + position: 'relative', + paddingTop: '0', // Remove top padding to align the animation at the top + paddingBottom: '0', // Remove bottom padding + minHeight: '70vh', // Adjust the height as needed to fit the animation + display: 'flex', + justifyContent: 'center', // Center the animation horizontally + alignItems: 'center', // Center the animation vertically + overflow: 'hidden', // Prevent overflow })); - export const TertiaryContentContainer = styled('div')(({ theme }) => ({ padding: theme.spacing(3), borderRadius: theme.shape.borderRadius,