diff --git a/app/(pages)/explore/categories/page.tsx b/app/(pages)/explore/categories/page.tsx index 79e833f4..de4b74a9 100644 --- a/app/(pages)/explore/categories/page.tsx +++ b/app/(pages)/explore/categories/page.tsx @@ -5,6 +5,7 @@ import { MAX_CONTENT_WIDTH } from '../../../utils/constants' import { fetchTokenCategoryPages } from '../../../../contentful/tokenCategoryPage' import DataDisclaimer from '../../../components/explore/DataDisclaimer' import ExploreCategories from '../../../components/explore/ExploreCategories' +import { fetchContentfulTokenPages } from '../../../../contentful/tokenPage' export const metadata: Metadata = { title: 'Explore Listed Token Categories on Mango Markets', @@ -17,12 +18,19 @@ function ExploreCategoriesFallback() { } async function ExploreCategoriesPage() { - const categoryPages = await fetchTokenCategoryPages({ + const categoryPagesPromise = fetchTokenCategoryPages({ preview: draftMode().isEnabled, }) + const tokensPromise = fetchContentfulTokenPages({ + preview: draftMode().isEnabled, + }) + const [categoryPages, tokens] = await Promise.all([ + categoryPagesPromise, + tokensPromise, + ]) return categoryPages && categoryPages?.length ? ( }> - +
diff --git a/app/components/explore/CategoryTokenParticles.tsx b/app/components/explore/CategoryTokenParticles.tsx new file mode 100644 index 00000000..cde5acb6 --- /dev/null +++ b/app/components/explore/CategoryTokenParticles.tsx @@ -0,0 +1,115 @@ +import React, { useEffect, useState } from 'react' +import Particles from 'react-tsparticles' +import { Engine } from 'tsparticles-engine' + +const createEmitters = (tokenSymbols: string[]) => { + return [ + { + autoPlay: true, + fill: true, + life: { + wait: true, + duration: 1, + }, + rate: { + quantity: 1, + delay: { min: 6, max: 12 }, + }, + startCount: 0, + particles: { + shape: { + type: 'images', + options: { + images: tokenSymbols.map((sym) => ({ + src: `/icons/tokens/${sym.toLowerCase()}.svg`, + width: 48, + height: 48, + })), + }, + }, + rotate: { + value: 0, + random: true, + direction: 'clockwise', + animation: { + enable: true, + speed: 15, + sync: false, + }, + }, + lineLinked: { + enable: false, + }, + opacity: { + value: 0.4, + }, + size: { + value: 16, + random: false, + }, + move: { + speed: 1, + random: false, + outMode: 'destroy', + }, + }, + position: { + y: 0, + }, + }, + ] +} + +const CategoryTokenParticles = ({ + tokenSymbols, + id, +}: { + tokenSymbols: string[] + id: string +}) => { + const [mounted, setMounted] = useState(false) + const [emitters, setEmitters] = useState() + + useEffect(() => { + setMounted(true) + setEmitters(createEmitters(tokenSymbols)) + }, []) + + // Delay rendering until the library is fully initialized + if (!mounted) return null + + // const emitters = createEmitters(tokenSymbols) + + return ( + { + // On library initialization + console.log('Particles library initialized:', engine) + }} + options={{ + fullScreen: false, + particles: { + move: { + angle: 10, + attract: { + rotate: { + x: 600, + y: 1200, + }, + }, + direction: 'bottom', + enable: true, + speed: 0.1, + }, + opacity: { + value: 0, + }, + }, + emitters: emitters, + }} + /> + ) +} + +export default CategoryTokenParticles diff --git a/app/components/explore/ExploreCategories.tsx b/app/components/explore/ExploreCategories.tsx index a5618226..ced17917 100644 --- a/app/components/explore/ExploreCategories.tsx +++ b/app/components/explore/ExploreCategories.tsx @@ -1,14 +1,17 @@ 'use client' import { MagnifyingGlassIcon } from '@heroicons/react/20/solid' -import { ChangeEvent, useMemo, useState } from 'react' +import { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react' import Input from '../forms/Input' import { TokenCategoryPage } from '../../../contentful/tokenCategoryPage' import { MAX_CONTENT_WIDTH } from '../../utils/constants' import Link from 'next/link' import NoResults from './NoResults' import PageHeader from './PageHeader' -import CardImage from '../shared/CardImage' +import { TokenPage } from '../../../contentful/tokenPage' +import CategoryTokenParticles from './CategoryTokenParticles' +import { tsParticles } from 'tsparticles-engine' +import { loadFull } from 'tsparticles' const generateSearchTerm = (item: TokenCategoryPage, searchValue: string) => { const normalizedSearchValue = searchValue.toLowerCase() @@ -39,8 +42,10 @@ const startSearch = (items: TokenCategoryPage[], searchValue: string) => { const ExploreCategories = ({ categoryPages, + tokens, }: { categoryPages: TokenCategoryPage[] + tokens: TokenPage[] }) => { const [searchString, setSearchString] = useState('') @@ -54,6 +59,14 @@ const ExploreCategories = ({ setSearchString(e.target.value) } + const particlesInit = useCallback(async () => { + await loadFull(tsParticles) + }, []) + + useEffect(() => { + particlesInit() + }, [particlesInit]) + return ( <> @@ -76,19 +89,28 @@ const ExploreCategories = ({
{filteredCategories.map((cat) => { const { category, slug } = cat + const categoryTokenSymbols = tokens + ?.filter((token) => token.tags.includes(category)) + .map((t) => t.symbol) return (
-
- +
-
+

{category}

+ {categoryTokenSymbols?.length ? ( +

+ {categoryTokenSymbols.length} +

+ ) : null}
diff --git a/app/components/shared/CardImage.tsx b/app/components/shared/CardImage.tsx index a54d4d99..c595cdb6 100644 --- a/app/components/shared/CardImage.tsx +++ b/app/components/shared/CardImage.tsx @@ -17,7 +17,7 @@ const CardImage = ({ customImagePath }: { customImagePath?: string }) => { ? '/images/new/cube-bg.png' : '/images/new/cube-bg-light.png' - if (!mounted) return
+ if (!mounted) return
return (