Skip to content

Commit

Permalink
feat: post festival page
Browse files Browse the repository at this point in the history
  • Loading branch information
lauchness committed Aug 31, 2023
1 parent 4dbcdd0 commit 17d1345
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 52 deletions.
48 changes: 13 additions & 35 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,27 @@ import { getNow } from '@/utils/getNow'
import { getArweaveById } from '@/utils/getArweaveById'
import { getDropDate } from '@/utils/getDropDate'
import { siteDataSuffix } from '@/components/MintDialog/types'
import { Drop } from '@/config/partners/types'
import { Drop, Partner } from '@/config/partners/types'
import { Gift } from '@/components/icons/Gift'
import { DropCardList } from '@/components/DropCard/DropCardList'
import { getCollections } from '@/utils/getCollections'
import { ArrowRight } from '@/components/icons/ArrowRight'
import { CBSubscribeDialog } from '@/components/CBSubscribeDialog'
import { PostFestivalPage } from '@/components/PostFestivalPage/PostFestivalPage'
import { BasedChallenge } from '@/components/BasedChallenge/BasedChallenge'

type Props = {
searchParams: { [key: string]: string | string[] | undefined }
}

const CHALLENGE_IMAGES = [
{ url: '/challenge/1.png', alt: 'Based NFT Drop' },
{ url: '/challenge/2.png', alt: '' },
{ url: '/challenge/3.png', alt: '' },
{ url: '/challenge/4.png', alt: '' },
]

const Home = async ({ searchParams }: Props) => {
const spoofDateParam = searchParams.spoofDate
const spoofDate = Array.isArray(spoofDateParam)
? spoofDateParam[0]
: spoofDateParam
const { partner, tabs, article, tweets, activeDrops } =
await getPageData(spoofDate)
const { drops, name, icon } = partner
const { drops, name, icon } = partner || { drops: [], name: '', icon: '' }

const dropAddressParam = searchParams.drop

Expand All @@ -55,6 +50,10 @@ const Home = async ({ searchParams }: Props) => {
const { featuredDrop, remainingDrops } = getDrops(drops, dropAddress)
const collections = await getCollections(drops)

if (!partner) {
return <PostFestivalPage activeDrops={activeDrops} tabs={tabs} />
}

return (
<PageContainer subNavOverlap>
<div className="flex h-full flex-col items-center justify-between relative pb-36 gap-10 md:gap-[54px]">
Expand All @@ -64,29 +63,8 @@ const Home = async ({ searchParams }: Props) => {
staticHeadline={!!dropAddress}
floorAsk={collections[featuredDrop.address.toLowerCase()]?.floorAsk}
/>
<section className="bg-ocs-light-gray w-full shadow-large rounded-3xl p-6 flex flex-col gap-6 lg:flex-row">
<div className="flex flex-col gap-4 max-w-[520px]">
<h2 className="desktop-h2">Join the Based Challenge</h2>
<p className="desktop-body">
Claim your free onchain art, then watch it evolve as you mint more
on Base during Onchain Summer. Scan the QR code to get started.
</p>
<CBSubscribeDialog>
<Button>
<span>Claim now</span>{' '}
<span className="hidden md:inline">on Coinbase Wallet</span>
<ArrowRight className="ml-auto" />
</Button>
</CBSubscribeDialog>
</div>
<div className="grid gap-6 grid-cols-2 sm:grid-cols-4 lg:grid-cols-2 xl:grid-cols-4 w-full items-center max-w-[624px] lg:ml-auto">
{CHALLENGE_IMAGES.map(({ url, alt }) => (
<div key={url} className="relative z-20 w-full aspect-square">
<Image fill src={url} alt={alt} className="object-cover" />
</div>
))}
</div>
</section>

<BasedChallenge />
{remainingDrops?.length > 0 || article?.content ? (
<section className="bg-ocs-light-gray w-full shadow-large rounded-3xl">
<div className="p-[20px] lg:p-4 rounded-3xl">
Expand Down Expand Up @@ -243,7 +221,7 @@ const INITIAL_TABS: TabsComponentProps = {
pastDrops: [],
}

interface DropWithPartnerData extends Drop {
export interface DropWithPartnerData extends Drop {
partner: string
partnerIcon: string
}
Expand All @@ -252,7 +230,7 @@ async function getPageData(spoofDate?: string) {
const now = getNow(spoofDate)
const today = getDropDate(spoofDate)

const featuredPartner = schedule[today] || schedule[Object.keys(schedule)[0]]
const featuredPartner = (schedule[today] || null) as Partner | null

const tabs: TabsComponentProps = Object.keys(schedule).reduce((acc, date) => {
const scheduleDate = new Date(date)
Expand Down Expand Up @@ -314,7 +292,7 @@ async function getPageData(spoofDate?: string) {
.sort((a, b) => (a?.sequence ?? 0) - (b?.sequence ?? 0))

const [article, tweets] = await Promise.all([
getArweaveById(featuredPartner.aarweaveDigest),
getArweaveById(featuredPartner?.aarweaveDigest ?? ''),
getTweets(),
])

Expand Down
40 changes: 40 additions & 0 deletions src/components/BasedChallenge/BasedChallenge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { FC } from 'react'
import { CBSubscribeDialog } from '../CBSubscribeDialog'
import { Button } from '../Button'
import { ArrowRight } from '../icons/ArrowRight'
import Image from 'next/image'

const CHALLENGE_IMAGES = [
{ url: '/challenge/1.png', alt: 'Based NFT Drop' },
{ url: '/challenge/2.png', alt: '' },
{ url: '/challenge/3.png', alt: '' },
{ url: '/challenge/4.png', alt: '' },
]

export const BasedChallenge: FC = ({}) => {
return (
<section className="bg-ocs-light-gray w-full shadow-large rounded-3xl p-6 flex flex-col gap-6 lg:flex-row">
<div className="flex flex-col gap-4 max-w-[520px]">
<h2 className="desktop-h2">Join the Based Challenge</h2>
<p className="desktop-body">
Claim your free onchain art, then watch it evolve as you mint more on
Base during Onchain Summer. Scan the QR code to get started.
</p>
<CBSubscribeDialog>
<Button>
<span>Claim now</span>{' '}
<span className="hidden md:inline">on Coinbase Wallet</span>
<ArrowRight className="ml-auto" />
</Button>
</CBSubscribeDialog>
</div>
<div className="grid gap-6 grid-cols-2 sm:grid-cols-4 lg:grid-cols-2 xl:grid-cols-4 w-full items-center max-w-[624px] lg:ml-auto">
{CHALLENGE_IMAGES.map(({ url, alt }) => (
<div key={url} className="relative z-20 w-full aspect-square">
<Image fill src={url} alt={alt} className="object-cover" />
</div>
))}
</div>
</section>
)
}
10 changes: 10 additions & 0 deletions src/components/PageContainer/PageContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ interface PageContainerProps {
children: ReactNode
subNavBgColor?: string
subNavOverlap?: boolean
postFestival?: boolean
}

export const PageContainer: React.FC<PageContainerProps> = ({
children,
subNavBgColor,
subNavOverlap = false,
postFestival = false,
}) => {
const isMismatched = useIsMisMatched()

Expand All @@ -26,6 +28,14 @@ export const PageContainer: React.FC<PageContainerProps> = ({
return (
<>
<SubNav subNavBgColor={subNavBgColor} />
{postFestival ? (
<div className="flex flex-col gap-6 bg-ocs-blue items-center justify-center py-24 w-full">
<div className="w-14 h-14 bg-ocs-yellow rounded-full" />
<h1 className="text-white text-center font-display text-[64px] font-bold leading-[120%] uppercase">
Summer Never Ends
</h1>
</div>
) : null}
<div className={clsx('px-6 md:px-20', mt)}>
<main className="w-full max-w-7xl mx-auto">{children}</main>
</div>
Expand Down
87 changes: 87 additions & 0 deletions src/components/PostFestivalPage/PostFestivalPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
'use client'

import { FC } from 'react'
import { PageContainer } from '../PageContainer'
import { Gift } from '../icons/Gift'
import { DropCardList } from '../DropCard/DropCardList'
import { DropWithPartnerData } from '@/app/page'
import { DropCard } from '../DropCard'
import { siteDataSuffix } from '@/components/MintDialog/types'
import { Trending, TrendingQueryResult } from '../Trending'
import { Tabs, TabsComponentProps } from '../Tabs'
import { BasedChallenge } from '../BasedChallenge/BasedChallenge'
import { useAccount } from 'wagmi'
import { l2 } from '@/config/chain'
import { useQuery } from 'react-query'
import { getTrendingData } from '@/utils/getTrendingData'

interface PostFestivalPageProps {
activeDrops: DropWithPartnerData[]
tabs: TabsComponentProps
}

export const PostFestivalPage: FC<PostFestivalPageProps> = ({
activeDrops,
tabs,
}) => {
const { address: connectedWallet } = useAccount()
const chainId = l2.id

const { data, error, isLoading } = useQuery<TrendingQueryResult>({
queryKey: [connectedWallet, chainId],
queryFn: ({ queryKey }) => {
const [connectedWallet, chainId] = queryKey

return getTrendingData(connectedWallet as string, chainId as number)
},
})

const hasActiveSection =
activeDrops.length > 0 ||
(!isLoading && (data?.collections.length ?? 0) > 0)

return (
<PageContainer postFestival>
<div className="flex h-full flex-col items-center justify-between relative pb-36 gap-10 md:gap-[54px]">
{hasActiveSection ? (
<section className="w-full shadow-large rounded-3xl bg-[#EFEFEF] p-[20px]">
<div className="mb-4 flex gap-2 items-center">
<div className="flex justify-center items-center h-[64px] w-[64px] rounded-2xl bg-ocs-turquoise">
<Gift />
</div>
<div className="">
<h2 className="text-[32px] text-display">Active Mints</h2>
</div>
</div>

<div className="-mr-4 mb-4">
<DropCardList>
{activeDrops.map((drop) => (
<DropCard
{...drop}
key={drop.name}
partner={drop.partner}
partnerIcon={drop.partnerIcon}
openSeaLink={drop.openSeaLink}
interactWithNFTLink={drop.interactWithNFTLink}
dataSuffix={siteDataSuffix}
dropDataSuffix={drop.dataSuffix}
buttonText={drop.buttonText}
description={drop.description}
/>
))}
</DropCardList>
</div>

<Trending />
</section>
) : null}

<section className="w-full" id="drops">
<Tabs {...tabs} />
</section>
<BasedChallenge />
</div>
</PageContainer>
)
}
8 changes: 5 additions & 3 deletions src/components/Tabs/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ export interface TabsComponentProps {
}

export const Tabs: FC<TabsComponentProps> = ({ upcomingDrops, pastDrops }) => {
const hasUpcomingDrops = upcomingDrops.length > 0

return (
<section className="p-4 bg-ocs-light-gray rounded-3xl shadow-large">
<TabsComponent.Root defaultValue="tab1">
<TabsComponent.Root defaultValue={hasUpcomingDrops ? 'upcoming' : 'past'}>
<TabsComponent.List
className="flex [@media(max-width:374px)]:flex-wrap gap-2"
aria-label="Manage your account"
Expand All @@ -25,7 +27,7 @@ export const Tabs: FC<TabsComponentProps> = ({ upcomingDrops, pastDrops }) => {
pastLength={pastDrops.length}
/>
</TabsComponent.List>
<TabsComponent.Content value="tab1">
<TabsComponent.Content value="upcoming">
{upcomingDrops.map(
({ name, drops, banner, description, slug, brandColor }) => (
<div key={name} className="my-8 first:mt-6 last:mb-0">
Expand All @@ -43,7 +45,7 @@ export const Tabs: FC<TabsComponentProps> = ({ upcomingDrops, pastDrops }) => {
)
)}
</TabsComponent.Content>
<TabsComponent.Content className="" value="tab2">
<TabsComponent.Content className="" value="past">
{pastDrops.map(
({ name, drops, banner, description, slug, brandColor }) => (
<div key={name} className="my-8 first:mt-6 last:mb-0">
Expand Down
27 changes: 15 additions & 12 deletions src/components/Tabs/TabsListItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,28 @@ export const TabsListItems: FC<TabsListItemsProps> = ({
upcomingLength,
pastLength,
}) => {
const hasUpcomingDrops = upcomingLength > 0
return (
<>
<Tabs.Trigger
className="md:min-w-[200px] border-2 border-solid border-[#858585] radix-state-active:border-ocs-yellow radix-state-active:bg-ocs-yellow px-3 pt-10 pb-2 md:px-4 rounded-2xl relative"
value="tab1"
>
<div className="flex items-center desktop-h3 md:desktop-h2">
upcoming{' '}
<div className="h-[24px] w-[24px] py-[1px] text-[12px] bg-neutral-950 text-white rounded-full flex items-center justify-center mx-2 relative bottom-3">
<span className="text-center text-lg">{upcomingLength}</span>
{hasUpcomingDrops ? (
<Tabs.Trigger
className="md:min-w-[200px] border-2 border-solid border-[#858585] radix-state-active:border-ocs-yellow radix-state-active:bg-ocs-yellow px-3 pt-10 pb-2 md:px-4 rounded-2xl relative"
value="upcoming"
>
<div className="flex items-center desktop-h3 md:desktop-h2">
upcoming{' '}
<div className="h-[24px] w-[24px] py-[1px] text-[12px] bg-neutral-950 text-white rounded-full flex items-center justify-center mx-2 relative bottom-3">
<span className="text-center text-lg">{upcomingLength}</span>
</div>
</div>
</div>
</Tabs.Trigger>
</Tabs.Trigger>
) : null}
<Tabs.Trigger
className="md:min-w-[200px] border-2 border-solid border-[#858585] radix-state-active:border-none radix-state-active:bg-ocs-yellow px-3 pt-10 pb-2 md:px-4 rounded-2xl relative"
value="tab2"
value="past"
>
<div className="flex items-center desktop-h3 md:desktop-h2">
active{' '}
{hasUpcomingDrops ? 'active' : 'mints'}{' '}
<div className="h-[24px] w-[24px] py-[1px] text-[12px] bg-neutral-950 text-white rounded-full flex items-center justify-center mx-2 relative bottom-3">
<span className="text-center text-lg">{pastLength}</span>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/components/Trending/Trending.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ import { MintType, siteDataSuffix } from '@/components/MintDialog/types'

export interface TrendingComponentProps {}

interface QueryResult {
export interface TrendingQueryResult {
collections: Collection[]
}

export const Trending: FC<TrendingComponentProps> = () => {
const { address: connectedWallet } = useAccount()
const chainId = l2.id

const { data, error, isLoading } = useQuery<QueryResult>({
const { data, error, isLoading } = useQuery<TrendingQueryResult>({
queryKey: [connectedWallet, chainId],
queryFn: ({ queryKey }) => {
const [connectedWallet, chainId] = queryKey
Expand Down

0 comments on commit 17d1345

Please sign in to comment.