Skip to content

Commit

Permalink
Update POAP Testing
Browse files Browse the repository at this point in the history
  • Loading branch information
lucemans committed Oct 6, 2023
1 parent afd9c10 commit c05ad5b
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 63 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules/
.next
.dockerignore
.env.local
132 changes: 69 additions & 63 deletions app/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
/* eslint-disable unicorn/prevent-abbreviations */
import { ens_normalize } from '@adraffy/ens-normalize';
import { formatRecord } from '@ens-tools/format';
import { Metadata } from 'next';
import { FC, PropsWithChildren, ReactNode } from 'react';
import { FaTelegram } from 'react-icons/fa';
import { FiGithub, FiLink, FiTwitter } from 'react-icons/fi';
import shortNumber from 'short-number';

import { SPOAPModal } from '../../components/SPOAPModal';
import { useEnstate } from '../../hooks/useEnstate';
import { useIYKRef } from '../../hooks/useIYKRef';
import { useWarpcast } from '../../hooks/useWarpcast';

const Button: FC<PropsWithChildren<{ href: string }>> = ({
children,
href,
}) => {
return (
<a
href={href}
target="_blank"
className="bg-[#7116EB] relative rounded-lg px-4 py-3 flex items-center justify-center gap-2"
>
<a href={href} target="_blank" className="btn px-4 py-3">
{children}
</a>
);
Expand Down Expand Up @@ -76,8 +76,10 @@ const buttonControls = (key: string, value: string): ReactNode | undefined => {

export default async function ({
params: { slug },
searchParams: { event, iykRef },
}: {
params: { slug: string };
searchParams: { event?: string; iykRef?: string };
}) {
const raw_name = slug;
const name = ens_normalize(raw_name.toLowerCase());
Expand All @@ -86,82 +88,86 @@ export default async function ({
throw new Error('Invalid ENS name');
}

const [enstate, farcaster] = await Promise.all([
const [enstate, farcaster, iykData] = await Promise.all([
useEnstate(name),
useWarpcast(name),
useIYKRef(iykRef),
]);

return (
<div className="mx-auto w-full max-w-md flex flex-col gap-8 mt-4 lg:mt-10 px-6 py-8">
<div className="text-center px-4">
<img
src="/frensday_2.png"
alt="frensday"
className="w-full h-auto mx-auto"
/>
<div>November 13 2023, Istanbul Türkiye</div>
</div>
<div className="w-full flex flex-col gap-2 items-center justify-center">
<div className="flex items-center relative w-full pt-8">
<div className="mx-auto w-40 h-40 aspect-square border bg-white rounded-full overflow-hidden">
<img
src={enstate.avatar}
alt="profile"
className="w-full h-full"
/>
<div className="w-full flex flex-col gap-8 mt-4 lg:mt-10 px-6 py-8">
<div className="w-full max-w-md mx-auto">
<div className="text-center px-4">
<img
src="/frensday_2.png"
alt="frensday"
className="w-full h-auto mx-auto"
/>
<div>November 13 2023, Istanbul Türkiye</div>
</div>
<div className="w-full flex flex-col gap-2 items-center justify-center">
<div className="flex items-center relative w-full pt-8">
<div className="mx-auto w-40 h-40 aspect-square border bg-white rounded-full overflow-hidden">
<img
src={enstate.avatar}
alt="profile"
className="w-full h-full"
/>
</div>
<div className="absolute inset-0">
<img
src="/frensday_1.svg"
alt="frensday"
className="w-full h-full object-contain"
/>
</div>
</div>
<div className="absolute inset-0">
<img
src="/frensday_1.svg"
alt="frensday"
className="w-full h-full object-contain"
/>
<div className="text-center px-2 py-2 space-y-2">
<div className="text-3xl font-extrabold text-center">
{enstate.name}
</div>
{enstate.records.description && (
<div>{enstate.records.description}</div>
)}
</div>
</div>
<div className="text-center px-2 py-2 space-y-2">
<div className="text-3xl font-extrabold text-center">
{enstate.name}
</div>
{enstate.records.description && (
<div>{enstate.records.description}</div>
<div className="flex flex-col gap-4">
{Object.keys(enstate.records)
.map((key) => buttonControls(key, enstate.records[key]))
.filter(Boolean)}
{farcaster && farcaster.result && (
<Button
href={`https://warpcast.com/${farcaster.result.user.username}`}
>
<img
src="/warpcaster.svg"
alt="warpcaster"
style={{ height: '1em', width: '1em' }}
></img>
{farcaster.result.user.username}
<div className="bg-white/20 text-white px-2 py-1 rounded-md absolute right-2">
{shortNumber(
farcaster.result.user.followerCount
)}
</div>
</Button>
)}
</div>
</div>
<div className="flex flex-col gap-4">
{Object.keys(enstate.records)
.map((key) => buttonControls(key, enstate.records[key]))
.filter(Boolean)}
{farcaster && farcaster.result && (
<Button
href={`https://warpcast.com/${farcaster.result.user.username}`}
>
<img
src="/warpcaster.svg"
alt="warpcaster"
<Button href={'https://ens.app/' + name}>
<div
className="bg-white"
style={{ height: '1em', width: '1em' }}
></img>
{farcaster.result.user.username}
<div className="bg-white/20 text-white px-2 py-1 rounded-md absolute right-2">
{shortNumber(farcaster.result.user.followerCount)}
</div>
></div>
View on ENS App
</Button>
)}
<Button href={'https://ens.app/' + name}>
<div
className="bg-white"
style={{ height: '1em', width: '1em' }}
></div>
View on ENS App
</Button>
{iykData && <SPOAPModal data={iykData} name={name} />}
</div>
</div>
</div>
);
}

// Metadata
import { Metadata } from 'next';

// or Dynamic metadata
export async function generateMetadata({
params: { slug },
}: {
Expand Down
4 changes: 4 additions & 0 deletions app/global.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

.btn {
@apply bg-[#7116EB] relative rounded-lg flex items-center justify-center gap-2;
}
35 changes: 35 additions & 0 deletions components/POAPModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use client';

import { FC } from 'react';

import { IYKRefResponse as IYKReferenceResponse } from '../hooks/useIYKRef';
import { POAPMetadata } from '../hooks/usePOAPData';

export const POAPModal: FC<{
data: IYKReferenceResponse;
name: string;
metadata: POAPMetadata;
}> = ({ data, name, metadata }) => {
return (
<div className="fixed bottom-0 inset-x-0 px-3 pb-4">
<div className="w-full max-w-md mx-auto">
<div className="p-4 text-center relative">
<div className="absolute inset-x-0 bottom-0 top-12 bg-[#14032C] rounded-3xl -z-10"></div>
<div className="w-24 h-24 bg-slate-100 rounded-full mx-auto">
<img
src={metadata.image_url}
alt=""
className="w-full h-full object-cover"
/>
</div>
<div className="">
<div className="px-4 py-2 btn w-fit mx-auto -translate-y-3 font-bold">
Mint POAP
</div>
</div>
Claim your POAP to show you met {name} at frENSday!
</div>
</div>
</div>
);
};
20 changes: 20 additions & 0 deletions components/SPOAPModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { FC } from 'react';

import { IYKRefResponse as IYKReferenceResponse } from '../hooks/useIYKRef';
import { usePOAPData } from '../hooks/usePOAPData';
import { POAPModal } from './POAPModal';

export const SPOAPModal: FC<{
data: IYKReferenceResponse;
name: string;
}> = async ({ data, name }) => {
if (data.poapEvents.length === 0) return;

const [iyk_poap_event_data] = data.poapEvents;

const metadata = await usePOAPData(iyk_poap_event_data.poapEventId);

if (!metadata) return;

return <POAPModal data={data} name={name} metadata={metadata} />;
};
33 changes: 33 additions & 0 deletions hooks/useIYKRef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* eslint-disable unicorn/prevent-abbreviations */

type IYKPOAPEvent = {
id: number;
poapEventId: number;
otp: string;
status: 'expired';
};

type IYKLinkedToken = {
contractAddress: string;
chainId: number;
tokenId: string;
};

export type IYKRefResponse = {
uid: string;
isValidRef: boolean;
poapEvents: IYKPOAPEvent[];
linkedToken: IYKLinkedToken;
};

export const useIYKRef = async (reference?: string) => {
if (!reference) return;

const response = await fetch('https://api.iyk.app/refs/' + reference, {
headers: { 'x-api-key': process.env.IYK_API_KEY },
});

if (!response.ok) return;

return (await response.json()) as IYKRefResponse;
};
25 changes: 25 additions & 0 deletions hooks/usePOAPData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const POAP_API_HOST = 'https://api.poap.tech';

export type POAPMetadata = {
description: string;
external_url: string;
home_url: string;
image_url: string;
name: string;
year: number;
tags: string[];
attributes: {
trait_type: string;
value: string;
}[];
};

export const usePOAPData = async (
poapEventId: number
): Promise<POAPMetadata | undefined> => {
const request = await fetch(`${POAP_API_HOST}/metadata/${poapEventId}/1`);

if (!request.ok) return;

return await request.json();
};

0 comments on commit c05ad5b

Please sign in to comment.