From 514c1a848032eb49834950b1556c4905f2f16461 Mon Sep 17 00:00:00 2001 From: MananTank Date: Sat, 22 Feb 2025 01:38:35 +0000 Subject: [PATCH] [TOOL-3496] Dashboard: Ecosystem pages UI improvements (#6311) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/yNOf1svJ8o3zjO7zQouZ/f1d0c79f-f711-42e3-9c5e-2b57bfacc05b.png) ![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/yNOf1svJ8o3zjO7zQouZ/39702f47-477c-4177-bf3b-ac41c05b5093.png) ![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/yNOf1svJ8o3zjO7zQouZ/ce5cc358-a16a-4a06-90a1-a11ff47f67e4.png) --- ## PR-Codex overview This PR focuses on refactoring and enhancing the loading components and ecosystem management pages in the `dashboard` application. It introduces improvements in code structure, UI components, and error handling. ### Detailed summary - Removed unused files from `utils`, `data`, and `ecosystem` directories. - Updated `GenericLoadingPage` to accept a `className` prop for styling. - Refactored loading components to use the new `GenericLoadingPage` structure. - Enhanced `EcosystemCreatePage` layout and styling. - Improved `EcosystemAnalyticsPage` to fetch and display wallet usage statistics. - Replaced direct API calls with token-based authentication in ecosystem pages. - Updated `EcosystemHeader` to utilize new UI components and improve layout. - Refactored ecosystem creation form for better user experience and error handling. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` --- .../blocks/skeletons/GenericLoadingPage.tsx | 14 +- .../components/EcosystemAnalyticsPage.tsx | 36 ++- .../[slug]/(active)/analytics/page.tsx | 36 ++- .../components/EcosystemSlugLayout.tsx | 58 ++-- .../components/ecosystem-header.client.tsx | 149 ++++------ .../[slug]/(active)/configuration/page.tsx | 18 -- .../~/ecosystem/[slug]/(active)/loading.tsx | 6 +- .../ecosystem/create/EcosystemCreatePage.tsx | 20 +- .../client/create-ecosystem-form.client.tsx | 272 ++++++++++-------- .../create/components/pricing-card.tsx | 24 +- .../[team_slug]/(team)/~/ecosystem/layout.tsx | 7 - .../(team)/~/ecosystem/loading.tsx | 6 +- .../[team_slug]/(team)/~/ecosystem/page.tsx | 144 ++++------ .../src/data/analytics/fetch-api-server.ts | 42 --- apps/dashboard/src/utils/error.ts | 8 - 15 files changed, 383 insertions(+), 457 deletions(-) delete mode 100644 apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/page.tsx delete mode 100644 apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/layout.tsx delete mode 100644 apps/dashboard/src/data/analytics/fetch-api-server.ts delete mode 100644 apps/dashboard/src/utils/error.ts diff --git a/apps/dashboard/src/@/components/blocks/skeletons/GenericLoadingPage.tsx b/apps/dashboard/src/@/components/blocks/skeletons/GenericLoadingPage.tsx index f52f0a8b76b..23a492985fd 100644 --- a/apps/dashboard/src/@/components/blocks/skeletons/GenericLoadingPage.tsx +++ b/apps/dashboard/src/@/components/blocks/skeletons/GenericLoadingPage.tsx @@ -1,10 +1,20 @@ "use client"; import { Spinner } from "@/components/ui/Spinner/Spinner"; +import { cn } from "../../../lib/utils"; -export function GenericLoadingPage() { +export function GenericLoadingPage({ + className, +}: { + className?: string; +}) { return ( -
+
); diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemAnalyticsPage.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemAnalyticsPage.tsx index 0433316c8c2..32c20c6c96c 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemAnalyticsPage.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemAnalyticsPage.tsx @@ -5,25 +5,57 @@ import { import { RangeSelector } from "components/analytics/range-selector"; import { getEcosystemWalletUsage } from "data/analytics/wallets/ecosystem"; import { EcosystemWalletUsersChartCard } from "./EcosystemWalletUsersChartCard"; +import { EcosystemWalletsSummary } from "./Summary"; export async function EcosystemAnalyticsPage({ ecosystemSlug, interval, range, -}: { ecosystemSlug: string; interval: "day" | "week"; range?: Range }) { +}: { + ecosystemSlug: string; + interval: "day" | "week"; + range?: Range; +}) { if (!range) { range = getLastNDaysRange("last-120"); } - const stats = await getEcosystemWalletUsage({ + const allTimeStatsPromise = getEcosystemWalletUsage({ + ecosystemSlug, + from: new Date(2022, 0, 1), + to: new Date(), + period: "all", + }); + + const monthlyStatsPromise = getEcosystemWalletUsage({ + ecosystemSlug, + from: new Date(new Date().getFullYear(), new Date().getMonth(), 1), + to: new Date(), + period: "month", + }); + + const statsPromise = getEcosystemWalletUsage({ ecosystemSlug, from: range.from, to: range.to, period: interval, }).catch(() => null); + const [allTimeStats, monthlyStats, stats] = await Promise.all([ + allTimeStatsPromise, + monthlyStatsPromise, + statsPromise, + ]); + return (
+ + +
+
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/page.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/page.tsx index 0b3f809d281..dc18b1becc9 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/page.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/page.tsx @@ -1,7 +1,7 @@ import type { Range } from "components/analytics/date-range-selector"; -import { fetchApiServer } from "data/analytics/fetch-api-server"; -import { FetchError } from "utils/error"; -import type { Ecosystem } from "../../../types"; +import { redirect } from "next/navigation"; +import { getAuthToken } from "../../../../../../../../api/lib/getAuthToken"; +import { fetchEcosystem } from "../../../utils/fetchEcosystem"; import { EcosystemAnalyticsPage } from "./components/EcosystemAnalyticsPage"; export default async function Page(props: { @@ -19,7 +19,19 @@ export default async function Page(props: { props.searchParams, ]); - const ecosystem = await getEcosystem(params.slug); + const ecosystemLayoutPath = `/team/${params.team_slug}/~/ecosystem`; + const authToken = await getAuthToken(); + + if (!authToken) { + redirect(ecosystemLayoutPath); + } + + const ecosystem = await fetchEcosystem(params.slug, authToken); + + if (!ecosystem) { + redirect(ecosystemLayoutPath); + } + return ( ); } - -async function getEcosystem(ecosystemSlug: string) { - const res = await fetchApiServer(`/v1/ecosystem-wallet/${ecosystemSlug}`); - - if (!res.ok) { - const data = await res.json(); - console.error(data); - throw new FetchError( - res, - data?.message ?? data?.error?.message ?? "Failed to fetch ecosystems", - ); - } - - const data = (await res.json()) as { result: Ecosystem }; - return data.result; -} diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/EcosystemSlugLayout.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/EcosystemSlugLayout.tsx index 90149874100..b53977e5974 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/EcosystemSlugLayout.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/EcosystemSlugLayout.tsx @@ -1,8 +1,7 @@ -import { COOKIE_ACTIVE_ACCOUNT, COOKIE_PREFIX_TOKEN } from "@/constants/cookie"; -import { getEcosystemWalletUsage } from "data/analytics/wallets/ecosystem"; -import { cookies } from "next/headers"; +import { SidebarLayout } from "@/components/blocks/SidebarLayout"; +import {} from "@/constants/cookie"; import { redirect } from "next/navigation"; -import { getAddress } from "thirdweb"; +import { getAuthToken } from "../../../../../../../../api/lib/getAuthToken"; import { fetchEcosystem } from "../../../utils/fetchEcosystem"; import { EcosystemHeader } from "./ecosystem-header.client"; @@ -15,12 +14,7 @@ export async function EcosystemLayoutSlug({ params: { slug: string }; ecosystemLayoutPath: string; }) { - const cookiesManager = await cookies(); - const activeAccount = cookiesManager.get(COOKIE_ACTIVE_ACCOUNT)?.value; - const authToken = activeAccount - ? (await cookies()).get(COOKIE_PREFIX_TOKEN + getAddress(activeAccount)) - ?.value - : null; + const authToken = await getAuthToken(); if (!authToken) { redirect(ecosystemLayoutPath); @@ -32,34 +26,32 @@ export async function EcosystemLayoutSlug({ redirect(ecosystemLayoutPath); } - const allTimeStatsPromise = getEcosystemWalletUsage({ - ecosystemSlug: ecosystem.slug, - from: new Date(2022, 0, 1), - to: new Date(), - period: "all", - }); - - const monthlyStatsPromise = getEcosystemWalletUsage({ - ecosystemSlug: ecosystem.slug, - from: new Date(new Date().getFullYear(), new Date().getMonth(), 1), - to: new Date(), - period: "month", - }); - - const [allTimeStats, monthlyStats] = await Promise.all([ - allTimeStatsPromise, - monthlyStatsPromise, - ]); - return ( -
+
- {children} + + + {children} +
); } diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/ecosystem-header.client.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/ecosystem-header.client.tsx index 75e9c0054f0..d71bdb600f3 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/ecosystem-header.client.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/ecosystem-header.client.tsx @@ -1,5 +1,6 @@ "use client"; -import { CopyButton } from "@/components/ui/CopyButton"; +import { Img } from "@/components/blocks/Img"; +import { CopyTextButton } from "@/components/ui/CopyTextButton"; import { Spinner } from "@/components/ui/Spinner/Spinner"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { Button } from "@/components/ui/button"; @@ -12,21 +13,18 @@ import { DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Skeleton } from "@/components/ui/skeleton"; -import { TabPathLinks } from "@/components/ui/tabs"; import { useThirdwebClient } from "@/constants/thirdweb.client"; import { resolveSchemeWithErrorHandler } from "@/lib/resolveSchemeWithErrorHandler"; import { AlertTriangleIcon, CheckIcon, ChevronsUpDown, + ExternalLinkIcon, PlusCircleIcon, } from "lucide-react"; -import Image from "next/image"; import Link from "next/link"; -import type { EcosystemWalletStats } from "types/analytics"; import { useEcosystemList } from "../../../hooks/use-ecosystem-list"; import type { Ecosystem } from "../../../types"; -import { EcosystemWalletsSummary } from "../analytics/components/Summary"; import { useEcosystem } from "../hooks/use-ecosystem"; function EcosystemAlertBanner({ ecosystem }: { ecosystem: Ecosystem }) { @@ -111,8 +109,6 @@ function EcosystemSelect(props: { export function EcosystemHeader(props: { ecosystem: Ecosystem; ecosystemLayoutPath: string; - allTimeStats: EcosystemWalletStats[]; - monthlyStats: EcosystemWalletStats[]; }) { const { data: fetchedEcosystem } = useEcosystem({ slug: props.ecosystem.slug, @@ -135,95 +131,72 @@ export function EcosystemHeader(props: { }); return ( -
- -
-
-
- {!ecosystem.imageUrl ? ( - - ) : ( - ecosystemImageLink && ( -
- +
+ +
+
+
+ {!ecosystem.imageUrl ? ( + + ) : ( + ecosystemImageLink && ( + {ecosystem.name} -
- ) - )} -
- {!ecosystem.name ? ( - - ) : ( -

- {ecosystem.name} -

+ ) )} - {!ecosystem.slug ? ( - - ) : ( -
-
-

- ecosystem.{ecosystem.slug} -

- -
- - )} + )} +
+
+
+
-
- -
-
- - -
+ +
); } diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/page.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/page.tsx deleted file mode 100644 index b62af1259e2..00000000000 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { getAuthToken } from "../../../../../../../../api/lib/getAuthToken"; -import { loginRedirect } from "../../../../../../../../login/loginRedirect"; -import { EcosystemPermissionsPage } from "./components/client/EcosystemPermissionsPage"; - -export default async function Page(props: { - params: Promise<{ team_slug: string; slug: string }>; -}) { - const params = await props.params; - const authToken = await getAuthToken(); - - if (!authToken) { - loginRedirect( - `/team/${params.team_slug}/~/ecosystem/${params.slug}/configuration`, - ); - } - - return ; -} diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/loading.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/loading.tsx index 6c54ef15def..0528bd15ae9 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/loading.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/loading.tsx @@ -1,3 +1,7 @@ "use client"; -export { GenericLoadingPage as default } from "@/components/blocks/skeletons/GenericLoadingPage"; +import { GenericLoadingPage } from "@/components/blocks/skeletons/GenericLoadingPage"; + +export default function Loading() { + return ; +} diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/EcosystemCreatePage.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/EcosystemCreatePage.tsx index ba3fcdfbadb..d4813ff4820 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/EcosystemCreatePage.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/EcosystemCreatePage.tsx @@ -3,22 +3,12 @@ import { EcosystemWalletPricingCard } from "./components/pricing-card"; export async function EcosystemCreatePage(props: { teamSlug: string }) { return ( -
-
-

- Create an Ecosystem -

-

- Create wallets that work across every chain and every app. -

-
-
-
- -
-
+
+
+
-
+ +
); diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/components/client/create-ecosystem-form.client.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/components/client/create-ecosystem-form.client.tsx index 65a5fb4a19a..11ee2de0a1c 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/components/client/create-ecosystem-form.client.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/components/client/create-ecosystem-form.client.tsx @@ -1,4 +1,5 @@ "use client"; +import { Spinner } from "@/components/ui/Spinner/Spinner"; import { Button } from "@/components/ui/button"; import { Form, @@ -14,7 +15,7 @@ import { ImageUpload } from "@/components/ui/image-upload"; import { Input } from "@/components/ui/input"; import { RadioGroup, RadioGroupItemButton } from "@/components/ui/radio-group"; import { zodResolver } from "@hookform/resolvers/zod"; -import { Loader2 } from "lucide-react"; +import { ArrowRightIcon } from "lucide-react"; import Link from "next/link"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; @@ -45,138 +46,159 @@ export function CreateEcosystemForm(props: { teamSlug: string }) { }); return ( - <> -
- { - const res = await createEcosystem({ - teamSlug: props.teamSlug, - ...values, - }); - switch (res.status) { - case 401: { - toast.error("Please login to create an ecosystem"); - break; - } - case 403: - { - toast.error( - "You are not authorized to create an ecosystem, please ask your team owner to create it.", - ); - } - break; - case 409: { - toast.error("An ecosystem with that name already exists."); - break; - } - // any other status code treat as a random failure - default: { - toast.error( - "Failed to create ecosystem, please try again later.", - ); - } + + { + const res = await createEcosystem({ + teamSlug: props.teamSlug, + ...values, + }); + switch (res.status) { + case 401: { + toast.error("Please login to create an ecosystem"); + break; } - })} - className="flex flex-col items-stretch gap-8" - > -
- ( - - Ecosystem Name - - - - - - - )} - /> - ( - - Ecosystem Logo - - { - if (files[0]) { - form.setValue("logo", files[0]); - form.clearErrors("logo"); - } - }} - /> - - - The logo will be displayed as the ecosystem's wallet icon. - - - - )} - /> - ( - - Integration permissions - - - - - - Allowlist - - - - - - - Public - - - - - - - - Learn more about ecosystem permissions - - - - - )} - /> + case 403: { + toast.error( + "You are not authorized to create an ecosystem, please ask your team owner to create it.", + ); + break; + } + case 409: { + toast.error("An ecosystem with that name already exists."); + break; + } + // any other status code treat as a random failure + default: { + toast.error( + "Failed to create ecosystem, please try again later.", + ); + } + } + })} + > +
+
+

+ Create Ecosystem +

+

+ Create wallets that work across every chain and every app +

+ ( + + Ecosystem Name + + + + + + + )} + /> + ( + + Ecosystem Logo + + { + if (files[0]) { + form.setValue("logo", files[0]); + form.clearErrors("logo"); + } + }} + /> + + + The logo will be displayed as the ecosystem's wallet icon. + + + + )} + /> + ( + + Integration permissions + + + + + + Allowlist + + + + + + + Public + + + + + + + + Learn more about ecosystem permissions + + + + + )} + /> +
+ +
+ +
- - - +
+ + ); } diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/components/pricing-card.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/components/pricing-card.tsx index 1146146b9d8..2bd6115198d 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/components/pricing-card.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/create/components/pricing-card.tsx @@ -7,42 +7,44 @@ export function EcosystemWalletPricingCard(props: { className?: string }) { return (
-
-

+ +
+

$250{" "} per month

-
    + +
    • - Share + Share assets across apps within your ecosystem
    • - Connect + Connect with social, phone, email, or passkey
    • - A + A standalone wallet UI for all your users
    • - Custom + Custom permissions and billing across your ecosystem
    • - 30,000 + 30,000 active wallets included*
    -

    - $0.02 per additional wallet +

    + * $0.02 per additional wallet

diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/layout.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/layout.tsx deleted file mode 100644 index 8e3185bcc9c..00000000000 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/layout.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function Layout(props: { - children: React.ReactNode; -}) { - return ( -
{props.children}
- ); -} diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/loading.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/loading.tsx index 6c54ef15def..0528bd15ae9 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/loading.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/loading.tsx @@ -1,3 +1,7 @@ "use client"; -export { GenericLoadingPage as default } from "@/components/blocks/skeletons/GenericLoadingPage"; +import { GenericLoadingPage } from "@/components/blocks/skeletons/GenericLoadingPage"; + +export default function Loading() { + return ; +} diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/page.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/page.tsx index 35a4b86ad4e..880786776af 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/page.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/ecosystem/page.tsx @@ -1,12 +1,11 @@ import { Button } from "@/components/ui/button"; -import { Card } from "@/components/ui/card"; -import { ToolTipLabel } from "@/components/ui/tooltip"; -import { COOKIE_ACTIVE_ACCOUNT, COOKIE_PREFIX_TOKEN } from "@/constants/cookie"; -import { BookMarkedIcon, ExternalLinkIcon, MoveRightIcon } from "lucide-react"; -import { cookies } from "next/headers"; +import {} from "@/constants/cookie"; +import { ArrowRightIcon, ExternalLinkIcon } from "lucide-react"; import Image from "next/image"; import Link from "next/link"; import { redirect } from "next/navigation"; +import { getAuthToken } from "../../../../../api/lib/getAuthToken"; +import { loginRedirect } from "../../../../../login/loginRedirect"; import headerImage from "./assets/header.png"; import { fetchEcosystemList } from "./utils/fetchEcosystemList"; @@ -14,97 +13,74 @@ export default async function Page(props: { params: Promise<{ team_slug: string }>; }) { const { team_slug } = await props.params; - return ( - - ); + const ecosystemLayoutPath = `/team/${team_slug}/~/ecosystem`; + + const authToken = await getAuthToken(); + + if (!authToken) { + loginRedirect(ecosystemLayoutPath); + } + + const ecosystems = await fetchEcosystemList(authToken).catch((err) => { + console.error("failed to fetch ecosystems", err); + return []; + }); + if (ecosystems[0]) { + redirect(`${ecosystemLayoutPath}/${ecosystems[0].slug}`); + } + + return ; } async function EcosystemLandingPage(props: { ecosystemLayoutPath: string; }) { - const cookiesManager = await cookies(); - const activeAccount = cookiesManager.get(COOKIE_ACTIVE_ACCOUNT)?.value; - const authToken = activeAccount - ? cookiesManager.get(`${COOKIE_PREFIX_TOKEN}${activeAccount}`)?.value - : null; + return ( +
+ {/* Card */} +
+ Ecosystems - // if user is logged in and has an ecosystem, redirect to the first ecosystem - if (authToken) { - const ecosystems = await fetchEcosystemList(authToken).catch((err) => { - console.error("failed to fetch ecosystems", err); - return []; - }); - if (ecosystems[0]) { - redirect(`${props.ecosystemLayoutPath}/${ecosystems[0].slug}`); - } - } + {/* body */} +
+

+ One wallet, a whole ecosystem of apps and games +

- // otherwise we fall through to the page +

+ With Ecosystem Wallets, your users can access their assets across + hundreds of apps and games within your ecosystem. You can control + which apps join your ecosystem and how their users interact with + your wallet. +

+
- return ( -
- Ecosystems -
-

- One wallet, a whole ecosystem of apps and games -

-

- With Ecosystem Wallets, your users can access their assets across - hundreds of apps and games within your ecosystem. You can control - which apps join your ecosystem and how their users interact with your - wallet. -

-
-
- {!authToken ? ( - - - - ) : ( - + + - )} - +
-
- - -
- -

Learn more

-
-

- Learn how to create and manage Ecosystem Wallets in our docs. -

-
- View Docs -
-
- - +
); } diff --git a/apps/dashboard/src/data/analytics/fetch-api-server.ts b/apps/dashboard/src/data/analytics/fetch-api-server.ts deleted file mode 100644 index 82baaf9b93e..00000000000 --- a/apps/dashboard/src/data/analytics/fetch-api-server.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { COOKIE_ACTIVE_ACCOUNT, COOKIE_PREFIX_TOKEN } from "@/constants/cookie"; -import { API_SERVER_URL } from "@/constants/env"; -import { cookies } from "next/headers"; -import { getAddress } from "thirdweb"; -import "server-only"; - -export async function fetchApiServer( - input: string | URL, - init?: RequestInit, -): Promise { - const cookieManager = await cookies(); - const activeAccount = cookieManager.get(COOKIE_ACTIVE_ACCOUNT)?.value; - const authToken = activeAccount - ? cookieManager.get(COOKIE_PREFIX_TOKEN + getAddress(activeAccount))?.value - : null; - - const [pathname, searchParams] = input.toString().split("?"); - if (!pathname) { - throw new Error("Invalid input, no pathname provided"); - } - - // create a new URL object for the analytics server - const url = new URL(API_SERVER_URL); - - url.pathname = pathname; - for (const param of searchParams?.split("&") || []) { - const [key, value] = param.split("="); - if (!key || !value) { - throw new Error("Invalid input, no key or value provided"); - } - url.searchParams.append(decodeURIComponent(key), decodeURIComponent(value)); - } - - return fetch(url, { - ...init, - headers: { - "content-type": "application/json", - ...(authToken ? { authorization: `Bearer ${authToken}` } : {}), - ...init?.headers, - }, - }); -} diff --git a/apps/dashboard/src/utils/error.ts b/apps/dashboard/src/utils/error.ts deleted file mode 100644 index 2604ec2aeb9..00000000000 --- a/apps/dashboard/src/utils/error.ts +++ /dev/null @@ -1,8 +0,0 @@ -export class FetchError extends Error { - constructor( - public res?: Response, - message?: string, - ) { - super(message); - } -}