diff --git a/hooks/useGetProject.tsx b/hooks/useGetProject.tsx new file mode 100644 index 0000000..2ce07ea --- /dev/null +++ b/hooks/useGetProject.tsx @@ -0,0 +1,19 @@ +import { Project } from "@/types/mongo"; +import { useQuery } from "wagmi"; + +async function getProject(id: string): Promise { + try { + return fetch(`${process.env.BACKEND_URL}/projects/${id}`).then((res) => + res.json() + ); + } catch (e) { + console.error(e); + return undefined; + } +} + +export function useGetProject(id?: string) { + return useQuery(["project", id], () => getProject(id!), { + enabled: Boolean(id) + }); +} diff --git a/hooks/useGetUser.tsx b/hooks/useGetUser.tsx new file mode 100644 index 0000000..2196740 --- /dev/null +++ b/hooks/useGetUser.tsx @@ -0,0 +1,21 @@ +import { AuthContext } from "@/components/AuthProvider"; +import { User } from "@/types/mongo"; +import { useContext } from "react"; +import { useQuery } from "wagmi"; + +async function getCurrentUser(userId: string): Promise { + try { + return fetch(`${process.env.BACKEND_URL}/users/${userId}`).then((res) => + res.json() + ); + } catch (e) { + console.error(e); + return; + } +} + +export function useGetUser(userId?: string) { + const { idToken } = useContext(AuthContext); + + return useQuery(["users"], () => getCurrentUser(userId!), { enabled: Boolean(userId) }); +} diff --git a/pages/admin/index.tsx b/pages/admin/index.tsx index 91decf4..15b5573 100644 --- a/pages/admin/index.tsx +++ b/pages/admin/index.tsx @@ -86,7 +86,6 @@ export default function AdminPage() { const { address, status } = useAccount(); const { chain } = useNetwork(); const { data: onChainProjects } = useRadarEditionsGetEditions({ - account: address, address: isTestnet() ? GOERLI_CONTRACT_ADDRESS : MAINNET_CONTRACT_ADDRESS, chainId: chain?.id, enabled: Boolean(chain), diff --git a/pages/api/get-checkout-link.ts b/pages/api/get-checkout-link.ts index 477a757..9e5b24e 100644 --- a/pages/api/get-checkout-link.ts +++ b/pages/api/get-checkout-link.ts @@ -30,12 +30,10 @@ export default async function handler( title: "RADAR Editions - Create Project", // description: "Describe your project *with Markdown!*", // imageUrl: "https://unsplash.it/240/240", - // successCallbackUrl: "string", - // cancelCallbackUrl: "string", - // walletAddress: "string", - // email: "string", + successCallbackUrl: "https://radarlaunch.app", + cancelCallbackUrl: "https://radarlaunch.app", sendEmailOnCreation: true, - quantity: 1, + // quantity: 1, metadata: {}, mintMethod: { name: "createEdition", diff --git a/pages/api/get-mint-checkout-link.ts b/pages/api/get-mint-checkout-link.ts new file mode 100644 index 0000000..2d4732a --- /dev/null +++ b/pages/api/get-mint-checkout-link.ts @@ -0,0 +1,63 @@ +import { GOERLI_CONTRACT_ID, MAINNET_CONTRACT_ID } from "@/constants/paper"; +import isTestnet from "@/lib/utils/isTestnet"; +import { NextApiRequest, NextApiResponse } from "next"; + +interface Response { + checkoutLinkIntentUrl: string; + transactionId: string; + estimatedPrice: { value: string; currency: string }; +} + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + if (req.method !== "POST") { + return res.status(404).send("Not found"); + } + try { + const { editionId, value } = req.body; + console.log({ editionId, value }); + const options = { + method: "POST", + headers: { + accept: "application/json", + "content-type": "application/json", + Authorization: "Bearer " + process.env.PAPER_API_KEY, + }, + body: JSON.stringify({ + contractId: isTestnet() ? GOERLI_CONTRACT_ID : MAINNET_CONTRACT_ID, + title: "RADAR Editions - Mint Project", + // description: "Describe your project *with Markdown!*", + // imageUrl: "https://unsplash.it/240/240", + successCallbackUrl: "https://radarlaunch.app", + cancelCallbackUrl: "https://radarlaunch.app", + sendEmailOnCreation: true, + quantity: 1, + metadata: {}, + mintMethod: { + name: "mintEdition", + args: { + editionId, + buyer: "$WALLET", + amount: "$QUANTITY", + data: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + payment: { currency: "ETH", value }, + }, + // contractArgs: "string", + feeBearer: "BUYER", + sendEmailOnTransferSucceeded: true, + }), + }; + + const response = await fetch( + "https://withpaper.com/api/2022-08-12/checkout-link-intent", + options + ).then((response) => response.json()); + return res.status(200).send(response); + } catch (e) { + console.log(e); + return res.status(400).send("Error has occured"); + } +} diff --git a/pages/project/[id]/index.tsx b/pages/project/[id]/index.tsx index 7b88708..a785a35 100644 --- a/pages/project/[id]/index.tsx +++ b/pages/project/[id]/index.tsx @@ -1,91 +1,108 @@ +import { chains } from "@/components/Web3Provider"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; -import { Card, CardHeader, CardTitle } from "@/components/ui/card"; import { Table, TableBody, TableCell, TableRow } from "@/components/ui/table"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { useToast } from "@/components/ui/use-toast"; +import { GOERLI_CONTRACT_ADDRESS, MAINNET_CONTRACT_ADDRESS } from "@/constants/address"; +import { useGetProject } from "@/hooks/useGetProject"; +import { useGetUser } from "@/hooks/useGetUser"; +import { useRadarEditionsGetEditions } from "@/lib/generated"; +import { cn } from "@/lib/utils"; +import isTestnet from "@/lib/utils/isTestnet"; import { MoveDown } from "lucide-react"; +import Link from "next/link"; +import { useRouter } from "next/router"; +import { useQuery } from "wagmi"; enum Tab { ONE = "ONE", TWO = "TWO", } -const milestones = [ - { - name: "Milestone 1", - amount: 0, - }, - { - name: "Milestone 2", - amount: 0, - }, - { - name: "Milestone 3", - amount: 0, - }, - { - name: "Milestone 4", - amount: 0, - }, - { - name: "Milestone 5", - amount: 0, - }, - { - name: "Milestone 6", - amount: 0, - }, -]; +function transformYouTubeUrl(url: string) { + if (!url.includes("youtube")) { + return "" + } + if (!url.includes("embed")) { + return url.replace("watch?v=", "embed/"); + } + return url; +} + +async function getMintCheckoutLink( + editionId: number, + value: string // project's mint fee +): Promise { + try { + const result = await fetch(`/api/get-mint-checkout-link`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + editionId, value, + }), + }).then((res) => res.json()); -const benefits = [ - { - amountRequired: 0, - benefitTitle: "Benefit 1", - }, - { - amountRequired: 0, - benefitTitle: "Benefit 2", - }, - { - amountRequired: 0, - benefitTitle: "Benefit 3", - }, - { - amountRequired: 0, - benefitTitle: "Benefit 4", - }, - { - amountRequired: 0, - benefitTitle: "Benefit 5", - }, - { - amountRequired: 0, - benefitTitle: "Benefit 6", - }, - { - amountRequired: 0, - benefitTitle: "Benefit 7", - }, -]; + if ("checkoutLinkIntentUrl" in result) { + return result.checkoutLinkIntentUrl; + } + } catch (e) { + console.error(e); + } + return ""; +} export default function IndividualProjectPage() { + const router = useRouter() + const { id } = router.query; + + const { data } = useGetProject(id?.toString()) + const { data: userData } = useGetUser(data?.founder) + const { data: onChainProjects } = useRadarEditionsGetEditions({ + address: isTestnet() ? GOERLI_CONTRACT_ADDRESS : MAINNET_CONTRACT_ADDRESS, + chainId: chains[0]?.id, + enabled: Boolean(chains[0]?.id), + }); + const { toast } = useToast() + + const editionId = onChainProjects?.findIndex(project => project.id === id) + const value = editionId !== undefined && onChainProjects?.[editionId]?.fee + const { data: checkoutLink, isLoading: isCheckoutLinkLoading } = useQuery( + ["checkout-mint-link", editionId, value], + () => getMintCheckoutLink(editionId!, value!.toString()), + { enabled: editionId !== undefined && value !== undefined } + ); + + console.log({ onChainProjects, editionId, value }) + + + if (!data) { + return
No project found
+ } + console.log("Video URL", data.video_url) + return ( -
-
+ +
+
-