diff --git a/components/ftc-board.tsx b/components/ftc-board.tsx index 9fa73f1..a479f45 100644 --- a/components/ftc-board.tsx +++ b/components/ftc-board.tsx @@ -7,6 +7,7 @@ import { import { Center, Flex, Spinner } from "@chakra-ui/react"; import { Hyperboard } from "@/components/hyperboard"; import * as React from "react"; +import Head from "next/head"; export const FtcBoard = ({ registryId }: { registryId: string }) => { const containerRef = useRef(null); @@ -16,9 +17,11 @@ export const FtcBoard = ({ registryId }: { registryId: string }) => { "sponsors" | "speakers" | "all" >("all"); - const { data, isLoading } = useRegistryContents(registryId); + const { data: results, isLoading } = useRegistryContents(registryId); - const sponsors = Object.values(data || {}).filter( + const data = results?.content || {}; + + const sponsors = Object.values(data).filter( (x) => x.displayData?.type === "person" || x.displayData?.type === "company", ); @@ -49,61 +52,66 @@ export const FtcBoard = ({ registryId }: { registryId: string }) => { }, [displayBoards]); return ( -
- - {isLoading ? ( -
- -
- ) : ( - <> - - - setDisplayBoards((val) => - val === "all" ? "sponsors" : "all", - ) - } - label="Sponsors" - height={height} - data={sponsors.map((x) => - registryContentItemToHyperboardEntry(x), - )} - /> - - - - setDisplayBoards((val) => - val === "all" ? "speakers" : "all", - ) - } - label="Speakers" - height={height} - data={speakers.map((x) => - registryContentItemToHyperboardEntry(x), - )} - /> - - - )} -
-
+ <> + + Hyperboards - {results?.registry.name || "Loading"} + +
+ + {isLoading ? ( +
+ +
+ ) : ( + <> + + + setDisplayBoards((val) => + val === "all" ? "sponsors" : "all", + ) + } + label="Sponsors" + height={height} + data={sponsors.map((x) => + registryContentItemToHyperboardEntry(x), + )} + /> + + + + setDisplayBoards((val) => + val === "all" ? "speakers" : "all", + ) + } + label="Speakers" + height={height} + data={speakers.map((x) => + registryContentItemToHyperboardEntry(x), + )} + /> + + + )} +
+
+ ); }; diff --git a/components/store/buy-hypercert-tile.tsx b/components/store/buy-hypercert-tile.tsx index 1bf8ecf..3510f6d 100644 --- a/components/store/buy-hypercert-tile.tsx +++ b/components/store/buy-hypercert-tile.tsx @@ -2,7 +2,11 @@ import { Box, Button, Flex, + Heading, Image, + Input, + InputGroup, + InputRightAddon, Slider, SliderFilledTrack, SliderThumb, @@ -10,20 +14,24 @@ import { Text, Tooltip, useToast, + VStack, } from "@chakra-ui/react"; import { useState } from "react"; import { HypercertMetadata } from "@hypercerts-org/sdk"; import { Offer, OfferFromContract } from "@/hooks/store"; import { useBuyFraction } from "@/hooks/useBuyFraction"; +import { formatEther } from "viem"; export const BuyHypercertTile = ({ metaData, offer, offerFromContract, + totalUnits, }: { metaData: HypercertMetadata; offer?: Offer; offerFromContract?: OfferFromContract; + totalUnits: number; }) => { const toast = useToast(); const buyFraction = useBuyFraction(); @@ -56,42 +64,87 @@ export const BuyHypercertTile = ({ ); const [showTooltip, setShowTooltip] = useState(false); - return ( - - {"Hypercert - {metaData.name} - {!offer ? ( + const percentageAvailable = + (Number(offerFromContract?.unitsAvailable.toString()) / totalUnits) * 100; + + const totalPrice = offerFromContract + ? formatEther( + sliderValue * offerFromContract?.acceptedTokens[0].minimumAmountPerUnit, + ) + : "unknown"; + + if (!offer || !offerFromContract) { + return ( + + {"Hypercert + {metaData.name}
Offer unknown
- ) : ( - <> - - setShowTooltip(true)} - onMouseLeave={() => setShowTooltip(false)} - min={Number(offer.minUnitsPerTrade.toString())} - max={Number(offer.unitsAvailable.toString())} - value={Number(sliderValue.toString())} - aria-label="buy fractions slider" - onChange={(v) => setSliderValue(BigInt(v))} - > - - - - - - - - - - - )} -
+
+ ); + } + + const minValue = Number(offer.minUnitsPerTrade.toString()); + const maxValue = Number(offerFromContract.unitsAvailable.toString()); + + const currentPercentageValue = + (Number(sliderValue.toString()) / totalUnits) * 100; + + return ( + + {"Hypercert + + {metaData.name} + + + + % + + + setShowTooltip(true)} + onMouseLeave={() => setShowTooltip(false)} + min={minValue} + max={maxValue} + value={Number(sliderValue.toString())} + aria-label="buy fractions slider" + onChange={(v) => { + setSliderValue(BigInt(v)); + }} + > + + + + + + + + + Price: {totalPrice} ETH + + ); }; diff --git a/components/store/index.tsx b/components/store/index.tsx index 28640c0..604e993 100644 --- a/components/store/index.tsx +++ b/components/store/index.tsx @@ -1,6 +1,7 @@ import { GridItem, SimpleGrid } from "@chakra-ui/react"; import { BuyHypercertTile } from "@/components/store/buy-hypercert-tile"; import { useStoreHypercerts } from "@/hooks/store"; +import _ from "lodash"; export const Store = () => { const { data } = useStoreHypercerts(); @@ -15,6 +16,9 @@ export const Store = () => { metaData={x.metadata} offer={x.offer} offerFromContract={x.offerFromContract} + totalUnits={_.sum( + x.fractions.map((fraction) => parseInt(fraction.units)), + )} /> ))} diff --git a/hooks/registry.ts b/hooks/registry.ts index c2dd46b..8885f93 100644 --- a/hooks/registry.ts +++ b/hooks/registry.ts @@ -8,6 +8,7 @@ import { client } from "@/lib/hypercert-client"; interface RegistryWithClaims { id: string; + name: string; "hyperboard-claims": { id: string; hypercert_id: string; @@ -66,7 +67,7 @@ export const useRegistryContents = (registryId: string) => { ); // Group by owner, merge with display data and calculate total value of all fractions per owner - return _.chain(fractions) + const content = _.chain(fractions) .groupBy((fraction) => fraction.owner) .mapValues((fractionsPerOwner, owner) => { return { @@ -78,6 +79,11 @@ export const useRegistryContents = (registryId: string) => { }; }) .value(); + + return { + registry: registry.data, + content, + }; }); }); }; diff --git a/hooks/store.ts b/hooks/store.ts index aae84b0..70b3c25 100644 --- a/hooks/store.ts +++ b/hooks/store.ts @@ -94,6 +94,7 @@ export const useStoreHypercerts = () => { return supabase .from("hypercerts-store") .select("*") + .neq("hidden", true) .then(async (res) => { if (!res.data) { return; diff --git a/pages/events.tsx b/pages/events.tsx index acd3886..f10aa55 100644 --- a/pages/events.tsx +++ b/pages/events.tsx @@ -1,15 +1,21 @@ import { useListRegistries } from "@/hooks/registry"; import Link from "next/link"; import { Center, Heading, Spinner, VStack } from "@chakra-ui/react"; +import Head from "next/head"; const EventsPage = () => { const { data, isLoading } = useListRegistries(); if (isLoading) { return ( -
- -
+ <> + + Hyperboards - Events + +
+ +
+ ); } @@ -18,25 +24,30 @@ const EventsPage = () => { } return ( - - - Archive - - - {data.data.map((registry) => ( - - - {registry.name} - - - ))} + <> + + Hyperboards - Events + + + + Archive + + + {data.data.map((registry) => ( + + + {registry.name} + + + ))} + - + ); }; diff --git a/pages/index.tsx b/pages/index.tsx index 66f5457..46ced66 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,8 +1,16 @@ import React from "react"; import { FtcBoard } from "@/components/ftc-board"; +import Head from "next/head"; function Index() { - return ; + return ( + <> + + Hyperboards - FTC + + + + ); } export default Index; diff --git a/pages/store.tsx b/pages/store.tsx index 391936f..8779182 100644 --- a/pages/store.tsx +++ b/pages/store.tsx @@ -1,11 +1,52 @@ import { Store } from "@/components/store"; -import { Center } from "@chakra-ui/react"; +import { + Button, + Center, + Heading, + HStack, + Image, + Text, + VStack, +} from "@chakra-ui/react"; +import { RightOutlined } from "@ant-design/icons"; +import Head from "next/head"; const StorePage = () => { return ( -
- -
+ <> + + Hyperboards - Store + +
+ + + + Funding the Commons + + The Funding the Commons Conference and Hackathon Series brings + together communities in web2, web3, academia, and philanthropy, to + address challenges in public goods funding, to explore innovative + solutions, and to foster collaboration between industry leaders, + academia, and developers. + + + + + + + +
+ ); };