Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Stat } from "components/analytics/stat";
import { StatCard } from "components/analytics/stat";
import { ActivityIcon, UserIcon } from "lucide-react";
import type { EcosystemWalletStats } from "types/analytics";

Expand Down Expand Up @@ -28,15 +28,17 @@ export function EcosystemWalletsSummary(props: {

return (
<div className="grid grid-cols-2 gap-4 lg:gap-6">
<Stat
<StatCard
label="Total Users"
value={allTimeStats?.uniqueWalletsConnected || 0}
icon={ActivityIcon}
isPending={false}
/>
<Stat
<StatCard
label="Monthly Active Users"
value={monthlyStats?.uniqueWalletsConnected || 0}
icon={UserIcon}
isPending={false}
/>
</div>
);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getAggregateUserOpUsage, getUserOpUsage } from "@/api/analytics";
import { getUserOpUsage } from "@/api/analytics";
import { getProject } from "@/api/projects";
import { getTeamBySlug } from "@/api/team";
import { getThirdwebClient } from "@/constants/thirdweb.server";
Expand All @@ -9,6 +9,7 @@ import {
import { AccountAbstractionAnalytics } from "components/smart-wallets/AccountAbstractionAnalytics";
import { notFound, redirect } from "next/navigation";
import type { SearchParams } from "nuqs/server";
import { AccountAbstractionSummary } from "../../../../../../components/smart-wallets/AccountAbstractionAnalytics/AccountAbstractionSummary";
import { getAuthToken } from "../../../../../api/lib/getAuthToken";
import { searchParamLoader } from "./search-params";

Expand Down Expand Up @@ -60,32 +61,29 @@ export default async function Page(props: {
type: rangeType,
};

const userOpStatsPromise = getUserOpUsage({
const userOpStats = await getUserOpUsage({
teamId: project.teamId,
projectId: project.id,
from: range.from,
to: range.to,
period: interval,
});

const aggregateUserOpStatsPromise = getAggregateUserOpUsage({
teamId: team.id,
projectId: project.id,
});

const [userOpStats, aggregateUserOpStats] = await Promise.all([
userOpStatsPromise,
aggregateUserOpStatsPromise,
]);

return (
<AccountAbstractionAnalytics
userOpStats={userOpStats}
client={getThirdwebClient(authToken)}
teamId={project.teamId}
projectId={project.id}
teamSlug={params.team_slug}
aggregateUserOpStats={aggregateUserOpStats}
/>
<div>
<AccountAbstractionSummary
teamId={project.teamId}
projectId={project.id}
/>

<div className="h-10" />
<AccountAbstractionAnalytics
userOpStats={userOpStats}
client={getThirdwebClient(authToken)}
teamId={project.teamId}
projectId={project.id}
teamSlug={params.team_slug}
/>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,7 @@
import { getInAppWalletUsage } from "@/api/analytics";
import { TrackedUnderlineLink } from "@/components/ui/tracked-link";
import { InAppWalletsSummary } from "components/embedded-wallets/Analytics/Summary";
import { subDays } from "date-fns";
import { TRACKING_CATEGORY } from "../_constants";

export async function InAppWalletsHeader({
teamId,
projectId,
}: { teamId: string; projectId: string }) {
const allTimeStatsPromise = getInAppWalletUsage({
teamId,
projectId,
from: new Date(2022, 0, 1),
to: new Date(),
period: "all",
});

const monthlyStatsPromise = getInAppWalletUsage({
teamId,
projectId,
from: subDays(new Date(), 30),
to: new Date(),
period: "month",
});

const [allTimeStats, monthlyStats] = await Promise.all([
allTimeStatsPromise,
monthlyStatsPromise,
]).catch(() => [null, null]);

export async function InAppWalletsHeader() {
return (
<div>
<h1 className="mb-1 font-semibold text-2xl tracking-tight lg:mb-2 lg:text-3xl">
Expand All @@ -47,10 +20,6 @@ export async function InAppWalletsHeader({
Learn more
</TrackedUnderlineLink>
</p>
<InAppWalletsSummary
allTimeStats={allTimeStats || []}
monthlyStats={monthlyStats || []}
/>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ export default async function Layout(props: {

return (
<div>
<InAppWalletsHeader teamId={project.teamId} projectId={project.id} />
<div className="h-8" />

<InAppWalletsHeader />
<TabPathLinks
links={[
{
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { getProject } from "@/api/projects";
import type { Range } from "components/analytics/date-range-selector";
import { InAppWalletAnalytics } from "components/embedded-wallets/Analytics";
import { redirect } from "next/navigation";
import { getProject } from "../../../../../../@/api/projects";
import { InAppWalletsSummary } from "../../../../../../components/embedded-wallets/Analytics/Summary";

export default async function Page(props: {
params: Promise<{ team_slug: string; project_slug: string }>;
Expand Down Expand Up @@ -39,11 +40,15 @@ export default async function Page(props: {
}

return (
<InAppWalletAnalytics
teamId={project.teamId}
projectId={project.id}
interval={interval}
range={range as Range}
/>
<div>
<InAppWalletsSummary teamId={project.teamId} projectId={project.id} />
<div className="h-10" />
<InAppWalletAnalytics
teamId={project.teamId}
projectId={project.id}
interval={interval}
range={range as Range}
/>
</div>
);
}
17 changes: 12 additions & 5 deletions apps/dashboard/src/components/analytics/stat.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
export const Stat: React.FC<{
import { Skeleton } from "../../@/components/ui/skeleton";

export const StatCard: React.FC<{
label: string;
value?: number;
icon: React.FC<{ className?: string }>;
formatter?: (value: number) => string;
}> = ({ label, value, formatter, icon: Icon }) => {
isPending: boolean;
}> = ({ label, value, formatter, icon: Icon, isPending }) => {
return (
<dl className="flex items-center justify-between gap-4 rounded-lg border border-border bg-card p-4 pr-6">
<div>
<dd className="mb-0.5 font-semibold text-2xl tracking-tight">
{value !== undefined && formatter
? formatter(value)
: value?.toLocaleString()}
{isPending ? (
<Skeleton className="h-8 w-20" />
) : value !== undefined && formatter ? (
formatter(value)
) : (
value?.toLocaleString()
)}
</dd>
<dt className="text-muted-foreground text-sm">{label}</dt>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { Stat } from "components/analytics/stat";
import { getInAppWalletUsage } from "@/api/analytics";
import { StatCard } from "components/analytics/stat";
import { subDays } from "date-fns";
import { ActivityIcon, UserIcon } from "lucide-react";
import { Suspense } from "react";
import type { InAppWalletStats } from "types/analytics";

export function InAppWalletsSummary(props: {
function InAppWalletsSummaryInner(props: {
allTimeStats: InAppWalletStats[] | undefined;
monthlyStats: InAppWalletStats[] | undefined;
isPending: boolean;
}) {
const allTimeStats = props.allTimeStats?.reduce(
(acc, curr) => {
Expand All @@ -28,16 +32,75 @@ export function InAppWalletsSummary(props: {

return (
<div className="grid grid-cols-2 gap-4">
<Stat
<StatCard
label="Total Users"
value={allTimeStats?.uniqueWalletsConnected || 0}
icon={ActivityIcon}
isPending={props.isPending}
/>
<Stat
<StatCard
label="Monthly Active Users"
value={monthlyStats?.uniqueWalletsConnected || 0}
icon={UserIcon}
isPending={props.isPending}
/>
</div>
);
}

async function AsyncInAppWalletsSummary(props: {
teamId: string;
projectId: string;
}) {
const { teamId, projectId } = props;
const allTimeStatsPromise = getInAppWalletUsage({
teamId,
projectId,
from: new Date(2022, 0, 1),
to: new Date(),
period: "all",
});

const monthlyStatsPromise = getInAppWalletUsage({
teamId,
projectId,
from: subDays(new Date(), 30),
to: new Date(),
period: "month",
});

const [allTimeStats, monthlyStats] = await Promise.all([
allTimeStatsPromise,
monthlyStatsPromise,
]).catch(() => [null, null]);

return (
<InAppWalletsSummaryInner
allTimeStats={allTimeStats || undefined}
monthlyStats={monthlyStats || undefined}
isPending={false}
/>
);
}

export function InAppWalletsSummary(props: {
teamId: string;
projectId: string;
}) {
return (
<Suspense
fallback={
<InAppWalletsSummaryInner
allTimeStats={undefined}
monthlyStats={undefined}
isPending={true}
/>
}
>
<AsyncInAppWalletsSummary
teamId={props.teamId}
projectId={props.projectId}
/>
</Suspense>
);
}
Loading
Loading