Skip to content

Instantly share code, notes, and snippets.

@JWPapi
Created October 26, 2022 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JWPapi/9f0a4c0f677e2712e6949e336174603d to your computer and use it in GitHub Desktop.
Save JWPapi/9f0a4c0f677e2712e6949e336174603d to your computer and use it in GitHub Desktop.
import Image from "next/image";
import useSWR from "swr";
import {useInView} from "react-intersection-observer";
const fetcher = (url) => fetch(url).then((res) => res.json())
export default function Collection({name, items, slug}) {
const {ref, inView} = useInView({
rootMargin: '500px',
triggerOnce: true,
});
const {data} = useSWR(() => inView && slug ? `https://api.opensea.io/api/v1/collection/${slug}/stats` : null, fetcher)
return (
<div className="mb-8 card bg-base-300 p-4 shadow-xl" ref={ref}>
<a href={'https://opensea.io/collection/' + slug} target="_blank" rel="noreferrer" className="cursor-pointer">
<h2 className="text-xl text-left text-primary mb-4"> {name}</h2>
</a>
<div className={"md:grid grid-cols-2"}>
<div className="flex flex-col">
{items?.map((item) => <Item key={item.id} {...item} collectionSlug={slug}/>)}
</div>
{data && slug && <Stats stats={data.stats}/>}
</div>
</div>)
}
const Item = ({name, imageUrl, series, mintCount,collectionSlug}) => {
return (
<a href={openSeaSearchUrl(name,collectionSlug )} target="_blank" id={name} rel="noreferrer"
className="cursor-pointer block m-2">
<div className="bg-transparent flex flex-row">
<Image src={imageUrl} alt={name} layout="fixed" width={64} height={85}/>
<div className="p-2 items-center text-left rounded-xl mt-1 ">
<h2 className="card-title text-md">{name} </h2>
{mintCount && <div className="mx-auto">{mintCount} / {series}</div>}
{!mintCount && <p>Series of {series}</p>}
</div>
</div>
</a>
)
}
const Stat = ({title, value, description}) => {
return (<div className="stat border-none text-center">
<div className="stat-title">{title}</div>
<div className="stat-value text-lg text-primary ">{value}</div>
<div className="stat-description text-sm">{description}</div>
</div>)
}
const Stats = ({stats}) => {
const format = {
eth: (value) => Math.round(value * 100) / 100 + ' ETH',
pc: (value, trend) => (trend ? (value > 0 ? '📈' : '📉') : '') + Math.round(value * 100) + '%',
volume: (title, value, description) => ({
title,
value: format.eth(value),
description: format.pc(description, true)
})
}
return (
<div className="grid grid-cols-2 gap-2 ">
<div className="stats stats-vertical bg-transparent">
<Stat {...format.volume('1d Volume', stats.one_day_volume, stats.one_day_change)} />
<Stat {...format.volume('7d Volume', stats.seven_day_volume, stats.seven_day_change)}/>
</div>
<div className="stats stats-vertical bg-transparent">
<Stat
title='Unique Owners'
value={format.pc(stats.num_owners / stats.total_supply)}
description={stats.total_supply + ' Supply'}
/>
<Stat title="Floor Price" value={format.eth(stats.floor_price)}
description={format.eth(stats.market_cap)}/>
</div>
</div>)
}
const openSeaSearchUrl = (name, collectionSlug) => {
return 'https://opensea.io/assets?search[collections][0]='
+ collectionSlug
+ '&search[query]='
+ name
+ '&search[resultModel]=ASSETS&search[sortAscending]=true&search[sortBy]=UNIT_PRICE'
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment