Skip to content

Commit

Permalink
add categories page
Browse files Browse the repository at this point in the history
  • Loading branch information
saml33 committed Dec 22, 2023
1 parent c94f50a commit 0516668
Show file tree
Hide file tree
Showing 25 changed files with 263 additions and 101 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { Metadata } from 'next'
import { draftMode } from 'next/headers'
import { notFound } from 'next/navigation'
import { fetchTokenPagesForCategory } from '../../../../contentful/tokenPage'
import { fetchTokenPagesForCategory } from '../../../../../contentful/tokenPage'
import {
fetchTokenCategoryPage,
fetchTokenCategoryPages,
} from '../../../../contentful/tokenCategoryPage'
import { fetchMangoTokenData } from '../../../utils/mango'
import Category from '../../../components/explore/Category'
import { MAX_CONTENT_WIDTH } from '../../../utils/constants'
import RichTextDisplay from '../../../components/rich-text/RichTextDisplay'
import DataDisclaimer from '../../../components/explore/DataDisclaimer'
} from '../../../../../contentful/tokenCategoryPage'
import { fetchMangoTokenData } from '../../../../utils/mango'
import Category from '../../../../components/explore/Category'
import { MAX_CONTENT_WIDTH } from '../../../../utils/constants'
import RichTextDisplay from '../../../../components/rich-text/RichTextDisplay'
import DataDisclaimer from '../../../../components/explore/DataDisclaimer'

interface TokenCategoryPageParams {
category: string
Expand Down
47 changes: 47 additions & 0 deletions app/(pages)/explore/categories/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { fetchTokenPages } from '../../../../contentful/tokenPage'
import { draftMode } from 'next/headers'
import { Metadata } from 'next'
import { Suspense } from 'react'
import { MAX_CONTENT_WIDTH } from '../../../utils/constants'
import { fetchTokenCategoryPages } from '../../../../contentful/tokenCategoryPage'
import DataDisclaimer from '../../../components/explore/DataDisclaimer'
import ExploreCategories from '../../../components/explore/ExploreCategories'

export const metadata: Metadata = {
title: 'Explore Listed Token Categories on Mango Markets',
description:
'Discover and learn about the different types of tokens listed on Mango',
}

function ExploreCategoriesFallback() {
return <></>
}

async function ExploreCategoriesPage() {
const tokens = await fetchTokenPages({
preview: draftMode().isEnabled,
})
const categoryPages = await fetchTokenCategoryPages({
preview: draftMode().isEnabled,
})
return tokens && tokens?.length ? (
<Suspense fallback={<ExploreCategoriesFallback />}>
<ExploreCategories categoryPages={categoryPages} />
<div className={`px-6 lg:px-20 ${MAX_CONTENT_WIDTH} mx-auto pb-10`}>
<DataDisclaimer />
</div>
</Suspense>
) : (
<div
className={`px-6 lg:px-20 py-10 md:py-16 ${MAX_CONTENT_WIDTH} mx-auto min-h-screen`}
>
<div className="p-6 rounded-xl border border-th-bkg-3">
<p className="text-center">
Something went wrong. Try refreshing the page.
</p>
</div>
</div>
)
}

export default ExploreCategoriesPage
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import BackButton from '../../../components/shared/BackButton'
import BackButton from '../../../../components/shared/BackButton'

export default function TokenPageLayout({
children,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import { notFound } from 'next/navigation'
import {
fetchTokenPage,
fetchTokenPages,
} from '../../../../contentful/tokenPage'
import RichTextDisplay from '../../../components/rich-text/RichTextDisplay'
import { fetchMangoMarketData, fetchMangoTokenData } from '../../../utils/mango'
import { MangoMarketsData, MangoTokenData } from '../../../types/mango'
import TokenMangoStats from '../../../components/explore/token-page/TokenMangoStats'
import DataDisclaimer from '../../../components/explore/DataDisclaimer'
import InfoAndStats from '../../../components/explore/token-page/InfoAndStats'
} from '../../../../../contentful/tokenPage'
import RichTextDisplay from '../../../../components/rich-text/RichTextDisplay'
import {
fetchMangoMarketData,
fetchMangoTokenData,
} from '../../../../utils/mango'
import { MangoMarketsData, MangoTokenData } from '../../../../types/mango'
import TokenMangoStats from '../../../../components/explore/token-page/TokenMangoStats'
import DataDisclaimer from '../../../../components/explore/DataDisclaimer'
import InfoAndStats from '../../../../components/explore/token-page/InfoAndStats'

const SECTION_WRAPPER_CLASSES = 'border-t border-th-bkg-3 pt-6 mt-12'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,30 @@
import { fetchTokenPages } from '../../../contentful/tokenPage'
import Explore from '../../components/explore/Explore'
import { fetchTokenPages } from '../../../../contentful/tokenPage'
import ExploreTokens from '../../../components/explore/ExploreTokens'
import { draftMode } from 'next/headers'
import { fetchMangoTokensData } from '../../utils/mango'
import { fetchMangoTokensData } from '../../../utils/mango'
import { Metadata } from 'next'
import { Suspense } from 'react'
import { MAX_CONTENT_WIDTH } from '../../utils/constants'
import { fetchTokenCategoryPages } from '../../../contentful/tokenCategoryPage'
import DataDisclaimer from '../../components/explore/DataDisclaimer'
import { MAX_CONTENT_WIDTH } from '../../../utils/constants'
import DataDisclaimer from '../../../components/explore/DataDisclaimer'

export const metadata: Metadata = {
title: 'Explore Listed Tokens on Mango Markets',
description:
'Live prices, charts, stats and alpha on every token listed on Mango Markets.',
}

function ExploreFallback() {
function ExploreTokensFallback() {
return <></>
}

async function ExplorePage() {
async function ExploreTokensPage() {
const tokens = await fetchTokenPages({
preview: draftMode().isEnabled,
})
const mangoTokensData = await fetchMangoTokensData()
const categoryPages = await fetchTokenCategoryPages({
preview: draftMode().isEnabled,
})
return tokens && tokens?.length ? (
<Suspense fallback={<ExploreFallback />}>
<Explore
categoryPages={categoryPages}
tokens={tokens}
mangoTokensData={mangoTokensData}
/>
<Suspense fallback={<ExploreTokensFallback />}>
<ExploreTokens tokens={tokens} mangoTokensData={mangoTokensData} />
<div className={`px-6 lg:px-20 ${MAX_CONTENT_WIDTH} mx-auto pb-10`}>
<DataDisclaimer />
</div>
Expand All @@ -50,4 +42,4 @@ async function ExplorePage() {
)
}

export default ExplorePage
export default ExploreTokensPage
10 changes: 7 additions & 3 deletions app/components/explore/Category.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import CategorySwitcher from './CategorySwitcher'
import TableViewToggle from './TableViewToggle'
import TokenTable from './TokenTable'
import { TokenCategoryPage } from '../../../contentful/tokenCategoryPage'
import { sortTokens } from './Explore'
import { sortTokens } from './ExploreTokens'
import { MAX_CONTENT_WIDTH } from '../../utils/constants'
import BackButton from '../shared/BackButton'

const Category = ({
categoryPages,
Expand All @@ -35,13 +36,16 @@ const Category = ({
return (
<>
<div
className={`flex flex-col items-start justify-end h-[264px] ${
className={`flex flex-col items-start justify-between h-[264px] py-6 ${
description ? 'bg-cover bg-center' : 'bg-repeat'
}`}
style={{ backgroundImage: `url('${backgroundImageUrl}')` }}
>
<div className={`${MAX_CONTENT_WIDTH} w-full mx-auto px-6 lg:px-20`}>
<BackButton />
</div>
<div className={`${MAX_CONTENT_WIDTH} mx-auto`}>
<div className="bg-[rgba(0,0,0,0.8)] px-3 py-1 mb-6">
<div className="bg-[rgba(21,19,27,0.8)] px-3 py-1">
<h1 className="text-4xl">{`Explore ${category}`}</h1>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions app/components/explore/CategorySwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useParams, useRouter } from 'next/navigation'
import { TokenCategoryPage } from '../../../contentful/tokenCategoryPage'

const goToCategoryPage = (categorySlug: string, router: AppRouterInstance) => {
router.push(`/explore/${categorySlug}`)
router.push(`/explore/categories/${categorySlug}`)
}

const CategorySwitcher = ({
Expand Down Expand Up @@ -40,7 +40,7 @@ const CategorySwitcher = ({
const handleSetCategory = (cat: string) => {
setSelectedCategory(cat)
if (cat === 'All') {
router.push('/explore', { shallow: true })
router.push('/explore/categories', { shallow: true })
} else {
const slug = categories.find((category) => category.category === cat)
?.slug
Expand Down
120 changes: 120 additions & 0 deletions app/components/explore/ExploreCategories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
'use client'

import { MagnifyingGlassIcon } from '@heroicons/react/20/solid'
import { ChangeEvent, 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'

const generateSearchTerm = (item: TokenCategoryPage, searchValue: string) => {
const normalizedSearchValue = searchValue.toLowerCase()
const value = item.category.toLowerCase()

const isMatching = value.includes(normalizedSearchValue)
const matchingPercent = isMatching
? normalizedSearchValue.length / item.category.length
: 0

const matchingIdx = value.indexOf(normalizedSearchValue)

return {
category: item,
matchingIdx,
matchingPercent,
}
}

const startSearch = (items: TokenCategoryPage[], searchValue: string) => {
return items
.map((item) => generateSearchTerm(item, searchValue))
.filter((item) => item.matchingIdx >= 0)
.sort((i1, i2) => i1.matchingIdx - i2.matchingIdx)
.sort((i1, i2) => i2.matchingPercent - i1.matchingPercent)
.map((item) => item.category)
}

const ExploreCategories = ({
categoryPages,
}: {
categoryPages: TokenCategoryPage[]
}) => {
const [searchString, setSearchString] = useState('')

const filteredCategories = useMemo(() => {
return searchString
? startSearch(categoryPages, searchString)
: categoryPages
}, [searchString, categoryPages])

const handleUpdateSearch = (e: ChangeEvent<HTMLInputElement>) => {
setSearchString(e.target.value)
}

return (
<>
<div
className={`flex flex-col items-start justify-end h-[264px] bg-[url('/images/new/cube-bg.png')] bg-repeat`}
>
<div className={`${MAX_CONTENT_WIDTH} mx-auto`}>
<div className="bg-[rgba(0,0,0,0.8)] px-3 py-1 mb-6 mx-6 sm:mx-0">
<h1 className="text-4xl text-center">
Explore listed token categories
</h1>
</div>
</div>
</div>
<div
className={`px-6 lg:px-20 ${MAX_CONTENT_WIDTH} mx-auto py-10 md:py-16`}
>
<div className="mb-6 flex flex-col sm:flex-row sm:items-center sm:justify-between">
<p className="mb-3 sm:mb-0">{`${categoryPages?.length} token categories`}</p>
<div className="relative w-full lg:mb-0 sm:w-44">
<Input
heightClass="h-10 pl-8"
type="text"
value={searchString}
onChange={handleUpdateSearch}
/>
<MagnifyingGlassIcon className="absolute left-2 top-3 h-4 w-4 text-th-fgd-3" />
</div>
</div>
{filteredCategories?.length ? (
<div className="grid grid-cols-4 gap-6">
{filteredCategories.map((cat) => {
const { category, description, slug } = cat
const imgSrc = description
? `/images/categories/${slug}-small.png`
: '/images/new/cube-bg.png'
return (
<div
className="col-span-4 sm:col-span-2 lg:col-span-1 border border-th-bkg-3 rounded-xl group relative"
key={slug}
>
<Link href={`/explore/categories/${slug}`}>
<div className="overflow-hidden rounded-t-xl">
<div
className={`h-[200px] lg:h-[140px] ${
description ? 'bg-center bg-cover bg-no-repeat' : ''
} transition-transform transform md:group-hover:scale-105 duration-300`}
style={{ backgroundImage: `url('${imgSrc}')` }}
/>
</div>
<div className="px-4 py-3">
<p className="text-th-fgd-2 font-display">{category}</p>
</div>
</Link>
</div>
)
})}
</div>
) : (
<NoResults message="No categories found..." />
)}
</div>
</>
)
}

export default ExploreCategories
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import { MagnifyingGlassIcon } from '@heroicons/react/20/solid'
import { ChangeEvent, useMemo, useState } from 'react'
import Input from '../forms/Input'
import TokenTable from './TokenTable'
import CategorySwitcher from './CategorySwitcher'
import TableViewToggle from './TableViewToggle'
import { TokenCategoryPage } from '../../../contentful/tokenCategoryPage'
import { MAX_CONTENT_WIDTH } from '../../utils/constants'

const generateSearchTerm = (item: TokenPageWithData, searchValue: string) => {
Expand Down Expand Up @@ -65,12 +63,10 @@ export const sortTokens = (tokens: TokenPageWithData[]) => {
})
}

const Explore = ({
categoryPages,
const ExploreTokens = ({
tokens,
mangoTokensData,
}: {
categoryPages: TokenCategoryPage[]
tokens: TokenPageWithData[]
mangoTokensData: MangoTokenData[]
}) => {
Expand All @@ -91,19 +87,19 @@ const Explore = ({
className={`flex flex-col items-start justify-end h-[264px] bg-[url('/images/new/cube-bg.png')] bg-repeat`}
>
<div className={`${MAX_CONTENT_WIDTH} mx-auto`}>
<div className="bg-[rgba(0,0,0,0.8)] px-3 py-1 mb-6">
<div className="bg-[rgba(0,0,0,0.8)] px-3 py-1 mb-6 mx-6 sm:mx-0">
<h1 className="text-4xl">Explore listed tokens</h1>
</div>
</div>
</div>
<div
className={`px-6 lg:px-20 ${MAX_CONTENT_WIDTH} mx-auto py-10 md:py-16`}
>
<div className="mb-6 flex flex-col lg:flex-row lg:items-center lg:justify-between">
<div className="mb-6 flex flex-col sm:flex-row sm:items-center sm:justify-between">
<p className="mb-3 sm:mb-0">{`${tokens?.length} tokens listed on Mango`}</p>
<div className="flex space-x-2">
<CategorySwitcher categories={categoryPages} />
<div className="relative w-1/2 lg:mb-0 lg:w-44">
{/* <CategorySwitcher categories={categoryPages} /> */}
<div className="relative w-full lg:mb-0 sm:w-44">
<Input
heightClass="h-10 pl-8"
type="text"
Expand All @@ -128,4 +124,4 @@ const Explore = ({
)
}

export default Explore
export default ExploreTokens
9 changes: 9 additions & 0 deletions app/components/explore/NoResults.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const NoResults = ({ message }: { message: string }) => {
return (
<div className="border border-th-bkg-3 p-6 rounded-xl flex items-center justify-center">
<p>{message}</p>
</div>
)
}

export default NoResults
Loading

1 comment on commit 0516668

@vercel
Copy link

@vercel vercel bot commented on 0516668 Dec 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.