From 264f384db62063c1b2228ce056f8b3e8cf39da97 Mon Sep 17 00:00:00 2001 From: Mark Paul Date: Sat, 10 Feb 2024 18:09:40 +1100 Subject: [PATCH] feat: WIP #279 timecapsule componenets --- src/App.tsx | 2 + src/appsConfig.tsx | 5 +- src/libs/utils/constant.ts | 7 + .../components/TrailBlazerModal.tsx | 15 +- .../TimeCapsule/TimeCapsule.tsx | 131 ++++++++++++++++++ src/pages/index.tsx | 1 + src/routes.ts | 8 ++ 7 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 src/pages/AppMarketplace/TimeCapsule/TimeCapsule.tsx diff --git a/src/App.tsx b/src/App.tsx index a11de28..ce0b224 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -9,6 +9,7 @@ import { TransactionsToastList, NotificationModal, SignTransactionsModals } from import { apiTimeout, walletConnectV2ProjectId, sampleAuthenticatedDomains, ELROND_NETWORK } from "config"; import { MultiversxBubbles, MultiversxInfographics, MyWallet, PageNotFound, Unlock } from "pages"; import { ItheumTrailblazer } from "pages/AppMarketplace/ItheumTrailblazer/ItheumTrailblazer"; +import { TimeCapsule } from "pages/AppMarketplace/TimeCapsule/TimeCapsule"; import { NFTunes } from "pages/AppMarketplace/NFTunes"; import { routes, routeNames } from "routes"; import { ThemeProvider } from "./libComponents/ThemeProvider"; @@ -44,6 +45,7 @@ export const App = () => { } /> } /> } /> + } /> } /> } /> diff --git a/src/appsConfig.tsx b/src/appsConfig.tsx index 56c1db3..b75a7b5 100644 --- a/src/appsConfig.tsx +++ b/src/appsConfig.tsx @@ -46,7 +46,10 @@ export const PLAYSTATION_GAMER_PASSPORT_TOKENS: app_token[] = [ export const ESDT_BUBBLE_TOKENS: app_token[] = [ // { tokenIdentifier: "DATANFTFT-e0b917", nonce: 417 } ]; +export const TIMECAPSULE_TOKENS: app_token[] = IS_DEVNET + ? [{ tokenIdentifier: "DATANFTFT-e0b917", nonce: 57 }] + : [{ tokenIdentifier: "DATANFTFT-e936d4", nonce: 5 }]; export const SUPPORTED_APPS = IS_DEVNET - ? ["itheumtrailblazer", "multiversxbubbles", "esdtBubble", "playstationgamerpassport", "multiversxinfographics", "nftunes"] + ? ["itheumtrailblazer", "multiversxbubbles", "esdtBubble", "playstationgamerpassport", "multiversxinfographics", "nftunes", "timecapsule"] : ["itheumtrailblazer", "multiversxbubbles", "multiversxinfographics", "nftunes"]; diff --git a/src/libs/utils/constant.ts b/src/libs/utils/constant.ts index 25919b5..634450f 100644 --- a/src/libs/utils/constant.ts +++ b/src/libs/utils/constant.ts @@ -50,6 +50,13 @@ export const APP_MAPPINGS = [ desc: "Explore a multisensory journey with this app, extending art beyond visuals. Through vibrations, it unveils the creative potentials of Data NFTs, offering a unique and immersive experience.", img: iconNFTunes, }, + { + appName: "Time Capsule", + appDescription: "Time Capsule", + routeKey: "timecapsule", + desc: "Capture, archive, and relive historic social media events through photos and videos, preserving memories for future generations. Join the nostalgia journey!", + img: "https://itheum-static.s3.ap-southeast-2.amazonaws.com/expl-app-esdt-bubbles-icon.png", + }, ]; export const ITHEUM_EXPLORER_PROD_URL = "https://explorer.itheum.io"; diff --git a/src/pages/AppMarketplace/ItheumTrailblazer/components/TrailBlazerModal.tsx b/src/pages/AppMarketplace/ItheumTrailblazer/components/TrailBlazerModal.tsx index 3b93e95..a258f96 100644 --- a/src/pages/AppMarketplace/ItheumTrailblazer/components/TrailBlazerModal.tsx +++ b/src/pages/AppMarketplace/ItheumTrailblazer/components/TrailBlazerModal.tsx @@ -165,7 +165,20 @@ export const TrailBlazerModal = ({ owned, isFetchingDataMarshal, data }: { owned ); break; - default: + case "Meme": + tileCode = ( +
+ +

{dataItem.title}

+

{new Date(dataItem.date).toDateString()}

+ + See more... + +
+
+ ); + break; + case "Leaderboard": tileCode = (
diff --git a/src/pages/AppMarketplace/TimeCapsule/TimeCapsule.tsx b/src/pages/AppMarketplace/TimeCapsule/TimeCapsule.tsx new file mode 100644 index 0000000..dd1f8d5 --- /dev/null +++ b/src/pages/AppMarketplace/TimeCapsule/TimeCapsule.tsx @@ -0,0 +1,131 @@ +import React, { useEffect, useState } from "react"; +import { DataNft } from "@itheum/sdk-mx-data-nft"; +import { useGetLoginInfo } from "@multiversx/sdk-dapp/hooks"; +import { TIMECAPSULE_TOKENS } from "appsConfig"; +import headerHero from "assets/img/custom-app-header-trailblazer.png"; +import { DataNftCard, Loader } from "components"; +import { HeaderComponent } from "components/Layout/HeaderComponent"; +import { useGetAccount, useGetPendingTransactions } from "hooks"; +import { decodeNativeAuthToken, toastError } from "libs/utils"; +import "react-vertical-timeline-component/style.min.css"; +import { TrailBlazerModal } from "../ItheumTrailblazer/components/TrailBlazerModal"; + +export const TimeCapsule = () => { + const { address } = useGetAccount(); + const { hasPendingTransactions } = useGetPendingTransactions(); + const { tokenLogin } = useGetLoginInfo(); + + const [itDataNfts, setItDataNfts] = useState([]); + const [flags, setFlags] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [isFetchingDataMarshal, setIsFetchingDataMarshal] = useState(true); + const [owned, setOwned] = useState(false); + const [data, setData] = useState(); + + useEffect(() => { + if (!hasPendingTransactions) { + fetchAppNfts(); + } + }, [hasPendingTransactions]); + + useEffect(() => { + if (!isLoading && address) { + fetchMyNfts(); + } + }, [isLoading, address]); + + async function fetchAppNfts() { + setIsLoading(true); + + const _nfts: DataNft[] = await DataNft.createManyFromApi(TIMECAPSULE_TOKENS.map((v) => ({ nonce: v.nonce, tokenIdentifier: v.tokenIdentifier }))); + + setItDataNfts(_nfts); + setIsLoading(false); + } + + async function fetchMyNfts() { + const _dataNfts = await DataNft.ownedByAddress(address); + const _flags = []; + + for (const cnft of itDataNfts) { + const matches = _dataNfts.filter((mnft) => cnft.nonce === mnft.nonce); + _flags.push(matches.length > 0); + } + + setFlags(_flags); + } + + async function viewData(index: number) { + try { + if (!(index >= 0 && index < itDataNfts.length)) { + toastError("Data is not loaded"); + return; + } + + const dataNft = itDataNfts[index]; + const _owned = flags[index]; + setOwned(_owned); + + if (_owned) { + setIsFetchingDataMarshal(true); + + let res: any; + if (!(tokenLogin && tokenLogin.nativeAuthToken)) { + throw Error("No nativeAuth token"); + } + + const arg = { + mvxNativeAuthOrigins: [decodeNativeAuthToken(tokenLogin.nativeAuthToken).origin], + mvxNativeAuthMaxExpirySeconds: 3600, + fwdHeaderMapLookup: { + "authorization": `Bearer ${tokenLogin.nativeAuthToken}`, + }, + }; + + res = await dataNft.viewDataViaMVXNativeAuth(arg); + res.data = await (res.data as Blob).text(); + res.data = JSON.parse(res.data); + + setData(res.data.data.reverse()); + setIsFetchingDataMarshal(false); + } + } catch (err) { + console.error(err); + toastError((err as Error).message); + setIsFetchingDataMarshal(false); + } + } + + if (isLoading) { + return ; + } + + return ( + + {itDataNfts.length > 0 ? ( + itDataNfts.map((dataNft, index) => ( + } + modalTitle={"TimeCapsule"} + modalTitleStyle="md:p-5 pt-5 pb-5 px-2" + hasFilter={false} + /> + )) + ) : ( +

No Data NFTs

+ )} +
+ ); +}; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 736f1ed..24a609b 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -4,6 +4,7 @@ export * from "./AppMarketplace/MultiversxBubbles/MultiversxBubbles"; export * from "./AppMarketplace/MultiversxInfographics"; export * from "./AppMarketplace/ItheumTrailblazer/components/TrailBlazerModal"; export * from "./AppMarketplace/NFTunes"; +export * from "./AppMarketplace/TimeCapsule/TimeCapsule"; export * from "./Home"; export * from "./MyListed"; export * from "./MyWallet"; diff --git a/src/routes.ts b/src/routes.ts index d2aac5b..2662b5f 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -1,6 +1,7 @@ import { dAppName } from "config"; import { RouteType } from "libs/types"; import { ItheumTrailblazer } from "pages/AppMarketplace/ItheumTrailblazer/ItheumTrailblazer"; +import { TimeCapsule } from "pages/AppMarketplace/TimeCapsule/TimeCapsule"; import { NFTunes } from "pages/AppMarketplace/NFTunes"; import { withPageTitle } from "./components/PageTitle"; import { PlayStationGamer, Home, MyListed, MyWallet, MultiversxBubbles, MultiversxInfographics } from "./pages"; @@ -16,6 +17,7 @@ export const routeNames = { multiversxbubbles: "/multiversx-bubbles", multiversxinfographics: "/multiversx-infographics", nftunes: "/nftunes", + timecapsule: "/timecapsule", }; interface RouteWithTitleType extends RouteType { @@ -70,6 +72,12 @@ export const routes: RouteWithTitleType[] = [ component: NFTunes, authenticatedRoute: false, }, + { + path: routeNames.timecapsule, + title: "Time Capsule", + component: TimeCapsule, + authenticatedRoute: false, + }, ]; export const mappedRoutes = routes.map((route) => {