diff --git a/dapp/src/DApp.tsx b/dapp/src/DApp.tsx index aa67ce180..31255b53d 100644 --- a/dapp/src/DApp.tsx +++ b/dapp/src/DApp.tsx @@ -20,13 +20,21 @@ import queryClient from "./queryClient" import { delay, logPromiseFailure } from "./utils" import { AcreLogo } from "./assets/icons" +function SplashPage() { + return ( +
+ +
+ ) +} + function DApp() { useInitApp() return ( <> - + } /> ) @@ -48,9 +56,7 @@ function DAppProviders() { if (!config) return ( -
- -
+
) diff --git a/dapp/src/components/Layout.tsx b/dapp/src/components/Layout.tsx index 88e533cbe..64d4a99be 100644 --- a/dapp/src/components/Layout.tsx +++ b/dapp/src/components/Layout.tsx @@ -1,8 +1,7 @@ -import React, { useEffect } from "react" +import React from "react" import { Outlet } from "react-router-dom" import { Flex, VStack } from "@chakra-ui/react" -import { useIsEmbed, useMobileMode, useModal } from "#/hooks" -import { MODAL_TYPES } from "#/types" +import { useIsEmbed, useMobileMode } from "#/hooks" import DocsDrawer from "./DocsDrawer" import Header from "./Header" import ModalRoot from "./ModalRoot" @@ -19,12 +18,6 @@ const PAGE_MAX_WIDTH = { function Layout() { const isMobileMode = useMobileMode() const { embeddedApp } = useIsEmbed() - const { openModal } = useModal() - - // TODO: Temporary solution to test Welcome modal. - useEffect(() => { - openModal(MODAL_TYPES.WELCOME, { navigateToOnClose: "/" }) - }, [openModal]) if (isMobileMode) return diff --git a/dapp/src/hooks/useAccessCode.ts b/dapp/src/hooks/useAccessCode.ts index 691f16cb7..428ae9fa6 100644 --- a/dapp/src/hooks/useAccessCode.ts +++ b/dapp/src/hooks/useAccessCode.ts @@ -1,9 +1,14 @@ import { useCallback } from "react" -import useLocalStorage from "./useLocalStorage" +import useLocalStorage, { getLocalStorageItem } from "./useLocalStorage" +const LOCAL_STORAGE_KEY = "acre.accessCode" + +export function getAccessCodeFromLocalStorage() { + return getLocalStorageItem(LOCAL_STORAGE_KEY) +} export default function useAccessCode() { const [encodedCode, setAccessCode] = useLocalStorage( - "acre.accessCode", + LOCAL_STORAGE_KEY, undefined, ) diff --git a/dapp/src/hooks/useInitApp.ts b/dapp/src/hooks/useInitApp.ts index 3f462d8db..e87e8955a 100644 --- a/dapp/src/hooks/useInitApp.ts +++ b/dapp/src/hooks/useInitApp.ts @@ -7,7 +7,6 @@ import useDetectEmbed from "./useDetectEmbed" import useDetectReferral from "./useDetectReferral" import { useDisconnectWallet } from "./useDisconnectWallet" import { useFetchBTCPriceUSD } from "./useFetchBTCPriceUSD" -import useGatingDApp from "./useGatingDApp" export function useInitApp() { // TODO: Let's uncomment when dark mode is ready @@ -15,7 +14,6 @@ export function useInitApp() { useSentry() useDetectEmbed() useDetectReferral() - useGatingDApp() useInitializeAcreSdk() useInitDataFromSdk() useFetchBTCPriceUSD() diff --git a/dapp/src/pages/AccessPage/index.tsx b/dapp/src/pages/AccessPage/index.tsx new file mode 100644 index 000000000..41acf7020 --- /dev/null +++ b/dapp/src/pages/AccessPage/index.tsx @@ -0,0 +1,15 @@ +import React from "react" +import { useAppNavigate } from "#/hooks" +import GateModal from "#/components/GateModal" + +export default function AccessPage() { + const navigate = useAppNavigate() + + return ( + { + navigate("/dashboard") + }} + /> + ) +} diff --git a/dapp/src/pages/AccessPage/loader.ts b/dapp/src/pages/AccessPage/loader.ts new file mode 100644 index 000000000..956c07065 --- /dev/null +++ b/dapp/src/pages/AccessPage/loader.ts @@ -0,0 +1,40 @@ +import { getAccessCodeFromLocalStorage } from "#/hooks/useAccessCode" +import redirectWithSearchParams from "#/router/utils" +import { acreApi, shouldDisplayWelcomeModal } from "#/utils" +import { LoaderFunction } from "react-router-dom" + +export const redirectToAccessPageLoader = async ( + url: string, + redirectToOnSuccess: null | string = null, + redirectToOnFail: null | string = null, +) => { + try { + const isValid = await acreApi.verifyAccessCode( + getAccessCodeFromLocalStorage() ?? "", + ) + + if (isValid) { + const shouldRedirectToWelcomeModal = shouldDisplayWelcomeModal() + + return shouldRedirectToWelcomeModal + ? redirectWithSearchParams(url, "/welcome") + : !redirectToOnSuccess || + redirectWithSearchParams(url, redirectToOnSuccess) + } + + return redirectToOnFail + ? redirectWithSearchParams(url, redirectToOnFail) + : null + } catch (error) { + console.error("Failed to verify access code") + + return redirectToOnFail + ? redirectWithSearchParams(url, redirectToOnFail) + : null + } +} + +const accessPageLoader: LoaderFunction = async ({ request }) => + redirectToAccessPageLoader(request.url, "/dashboard") + +export default accessPageLoader diff --git a/dapp/src/pages/DashboardPage/loader.ts b/dapp/src/pages/DashboardPage/loader.ts new file mode 100644 index 000000000..f04804b98 --- /dev/null +++ b/dapp/src/pages/DashboardPage/loader.ts @@ -0,0 +1,17 @@ +import { referralProgram, shouldDisplayWelcomeModal } from "#/utils" +import { LoaderFunction } from "react-router-dom" +import redirectWithSearchParams from "#/router/utils" +import { redirectToAccessPageLoader } from "../AccessPage/loader" + +const dashboardPageLoader: LoaderFunction = async (args) => { + const { request } = args + + if (referralProgram.isEmbedApp(referralProgram.getEmbeddedApp(request.url))) + return shouldDisplayWelcomeModal() + ? redirectWithSearchParams(request.url, "/welcome") + : null + + return redirectToAccessPageLoader(request.url, null, "/access") +} + +export default dashboardPageLoader diff --git a/dapp/src/pages/WelcomePage/index.tsx b/dapp/src/pages/WelcomePage/index.tsx new file mode 100644 index 000000000..f1ef5dd23 --- /dev/null +++ b/dapp/src/pages/WelcomePage/index.tsx @@ -0,0 +1,23 @@ +import React from "react" +import WelcomeModal from "#/components/WelcomeModal" +import { useAppNavigate, useLocalStorage } from "#/hooks" +import { LOCAL_STORAGE_KEY } from "#/utils/shouldDisplayWelcomeModal" + +function WelcomePage() { + const navigate = useAppNavigate() + const [_, setShouldDisplayWelcomeModal] = useLocalStorage( + LOCAL_STORAGE_KEY, + true, + ) + + return ( + { + setShouldDisplayWelcomeModal(false) + navigate("/dashboard") + }} + /> + ) +} + +export default WelcomePage diff --git a/dapp/src/pages/WelcomePage/loader.ts b/dapp/src/pages/WelcomePage/loader.ts new file mode 100644 index 000000000..180104869 --- /dev/null +++ b/dapp/src/pages/WelcomePage/loader.ts @@ -0,0 +1,10 @@ +import redirectWithSearchParams from "#/router/utils" +import { shouldDisplayWelcomeModal } from "#/utils" +import { LoaderFunction } from "react-router-dom" + +const welcomePageLoader: LoaderFunction = ({ request }) => + shouldDisplayWelcomeModal() + ? null + : redirectWithSearchParams(request.url, "/dashboard") + +export default welcomePageLoader diff --git a/dapp/src/router/index.tsx b/dapp/src/router/index.tsx index 5943ddd6f..869551f0c 100644 --- a/dapp/src/router/index.tsx +++ b/dapp/src/router/index.tsx @@ -1,28 +1,53 @@ import React from "react" import Layout from "#/components/Layout" import DashboardPage from "#/pages/DashboardPage" -import { createBrowserRouter, redirectDocument } from "react-router-dom" -import { referralProgram } from "#/utils" +import { createBrowserRouter, LoaderFunction } from "react-router-dom" +import { shouldDisplayWelcomeModal, referralProgram } from "#/utils" +import dashboardPageLoader from "#/pages/DashboardPage/loader" +import AccessPage from "#/pages/AccessPage" +import WelcomePage from "#/pages/WelcomePage" +import welcomePageLoader from "#/pages/WelcomePage/loader" +import accessPageLoader from "#/pages/AccessPage/loader" +import redirectWithSearchParams from "./utils" import { routerPath } from "./path" +const mainLayoutLoader: LoaderFunction = ({ request }) => { + const embedApp = referralProgram.getEmbeddedApp(request.url) + + if (referralProgram.isEmbedApp(embedApp)) { + const shouldRedirectToWelcomeModal = !shouldDisplayWelcomeModal() + + return shouldRedirectToWelcomeModal + ? redirectWithSearchParams(request.url, "/welcome") + : redirectWithSearchParams(request.url, "/dashboard") + } + + return redirectWithSearchParams(request.url, "/access") +} + export const router = createBrowserRouter([ { path: "/", element: , - loader: ({ request }) => { - const embedApp = referralProgram.getEmbeddedApp(request.url) - - if (!!embedApp && !referralProgram.isEmbedApp(embedApp)) { - return redirectDocument("/") - } - - return null - }, children: [ { index: true, + loader: mainLayoutLoader, + }, + { path: routerPath.home, element: , + loader: dashboardPageLoader, + }, + { + path: "/access", + element: , + loader: accessPageLoader, + }, + { + path: "/welcome", + element: , + loader: welcomePageLoader, }, ], }, diff --git a/dapp/src/router/path.ts b/dapp/src/router/path.ts index ce48928bf..ea138162a 100644 --- a/dapp/src/router/path.ts +++ b/dapp/src/router/path.ts @@ -5,7 +5,7 @@ export const SEARCH_PARAMS_NAMES = { } export const routerPath = { - home: "/", + home: "/dashboard", } as const export type Pathname = (typeof routerPath)[keyof typeof routerPath] diff --git a/dapp/src/router/utils.ts b/dapp/src/router/utils.ts new file mode 100644 index 000000000..76fad6c5f --- /dev/null +++ b/dapp/src/router/utils.ts @@ -0,0 +1,9 @@ +import { redirect } from "react-router-dom" + +const redirectWithSearchParams = (url: string, to: string) => { + const requestUrl = new URL(url) + + return redirect(`${to}${requestUrl.search}`) +} + +export default redirectWithSearchParams diff --git a/dapp/src/utils/index.ts b/dapp/src/utils/index.ts index 2deea8e9e..c79d332b7 100644 --- a/dapp/src/utils/index.ts +++ b/dapp/src/utils/index.ts @@ -17,3 +17,4 @@ export { default as referralProgram } from "./referralProgram" export { default as acreApi } from "./acreApi" export { default as router } from "./router" export { default as delay } from "./delay" +export { default as shouldDisplayWelcomeModal } from "./shouldDisplayWelcomeModal" diff --git a/dapp/src/utils/shouldDisplayWelcomeModal.ts b/dapp/src/utils/shouldDisplayWelcomeModal.ts new file mode 100644 index 000000000..19cc1da8d --- /dev/null +++ b/dapp/src/utils/shouldDisplayWelcomeModal.ts @@ -0,0 +1,7 @@ +import { getLocalStorageItem } from "#/hooks/useLocalStorage" + +export const LOCAL_STORAGE_KEY = "acre.shouldDisplayWelcomeModal" + +export default function shouldDisplayWelcomeModal() { + return getLocalStorageItem(LOCAL_STORAGE_KEY) !== "false" +}