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
18 changes: 16 additions & 2 deletions app/network/metrics/components/CumulativeMetricCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
formatNumberWithCommas,
formatPercent,
} from "../utils/formatNumbers";
import MetricSparkline from "./MetricSparkline";

interface CumulativeMetricCardProps {
readonly title: string;
Expand All @@ -19,6 +20,9 @@ interface CumulativeMetricCardProps {
readonly accentColor: string;
readonly unit?: string;
readonly href?: string;
readonly sparklineData?: number[] | undefined;
readonly sparklineColor?: string | undefined;
readonly sparklineDates?: number[] | undefined;
}

function ChangeRow({
Expand Down Expand Up @@ -69,6 +73,9 @@ export default function CumulativeMetricCard({
accentColor,
unit = "",
href,
sparklineData,
sparklineColor,
sparklineDates,
}: CumulativeMetricCardProps) {
const total = dailyData.current.valueCount;
const daily24hChange =
Expand All @@ -78,7 +85,7 @@ export default function CumulativeMetricCard({

const content = (
<div
className={`tw-block tw-h-full tw-rounded-xl tw-border tw-border-neutral-800 tw-bg-[#0f1318] tw-p-5 tw-transition-all tw-duration-300 ${href ? "hover:-tw-translate-y-1 hover:tw-border-neutral-700 hover:tw-shadow-xl hover:tw-shadow-neutral-900/50" : ""}`}
className={`tw-group tw-flex tw-h-full tw-flex-col tw-overflow-hidden tw-rounded-xl tw-border tw-border-neutral-800 tw-bg-[#0f1318] tw-p-5 tw-transition-all tw-duration-300 ${sparklineData && sparklineColor ? "tw-pb-0" : ""} ${href ? "hover:-tw-translate-y-1 hover:tw-border-neutral-700 hover:tw-shadow-xl hover:tw-shadow-neutral-900/50" : ""}`}
>
<div className="tw-mb-5 tw-flex tw-items-start tw-justify-between">
<h3 className="tw-flex tw-items-center tw-gap-2 tw-text-base tw-font-semibold tw-text-white">
Expand Down Expand Up @@ -143,14 +150,21 @@ export default function CumulativeMetricCard({
/>
</div>
</div>
{sparklineData && sparklineColor && (
<MetricSparkline
data={sparklineData}
color={sparklineColor}
dates={sparklineDates}
/>
)}
</div>
);

if (href) {
return (
<Link
href={href}
className="tw-block tw-no-underline hover:tw-no-underline"
className="tw-group tw-block tw-no-underline hover:tw-no-underline"
>
{content}
</Link>
Expand Down
18 changes: 16 additions & 2 deletions app/network/metrics/components/MetricCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
formatNumberWithCommas,
formatPercent,
} from "../utils/formatNumbers";
import MetricSparkline from "./MetricSparkline";

interface MetricCardProps {
readonly title: string;
Expand All @@ -19,6 +20,9 @@ interface MetricCardProps {
readonly useValueCount?: boolean;
readonly suffix?: string | undefined;
readonly href?: string;
readonly sparklineData?: number[] | undefined;
readonly sparklineColor?: string | undefined;
readonly sparklineDates?: number[] | undefined;
}

function StatBlock({
Expand Down Expand Up @@ -97,6 +101,9 @@ export default function MetricCard({
useValueCount = false,
suffix,
href,
sparklineData,
sparklineColor,
sparklineDates,
}: MetricCardProps) {
const getCount = (data: MetricData, period: "current" | "previous") =>
useValueCount ? data[period].valueCount : data[period].eventCount;
Expand All @@ -106,7 +113,7 @@ export default function MetricCard({

const content = (
<div
className={`tw-block tw-h-full tw-rounded-xl tw-border tw-border-neutral-800 tw-bg-[#0f1318] tw-p-5 tw-transition-all tw-duration-300 ${href ? "hover:-tw-translate-y-1 hover:tw-border-neutral-700 hover:tw-shadow-xl hover:tw-shadow-neutral-900/50" : ""}`}
className={`tw-group tw-flex tw-h-full tw-flex-col tw-overflow-hidden tw-rounded-xl tw-border tw-border-neutral-800 tw-bg-[#0f1318] tw-p-5 tw-transition-all tw-duration-300 ${sparklineData && sparklineColor ? "tw-pb-0" : ""} ${href ? "hover:-tw-translate-y-1 hover:tw-border-neutral-700 hover:tw-shadow-xl hover:tw-shadow-neutral-900/50" : ""}`}
>
<div className="tw-mb-5 tw-flex tw-items-start tw-justify-between">
<h3 className="tw-flex tw-items-center tw-gap-2 tw-text-base tw-font-semibold tw-text-white">
Expand Down Expand Up @@ -144,14 +151,21 @@ export default function MetricCard({
suffix={suffix}
/>
</div>
{sparklineData && sparklineColor && (
<MetricSparkline
data={sparklineData}
color={sparklineColor}
dates={sparklineDates}
/>
)}
</div>
);

if (href) {
return (
<Link
href={href}
className="tw-block tw-no-underline hover:tw-no-underline"
className="tw-group tw-block tw-no-underline hover:tw-no-underline"
>
{content}
</Link>
Expand Down
49 changes: 49 additions & 0 deletions app/network/metrics/components/MetricSparkline.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import CustomTooltip from "@/components/utils/tooltip/CustomTooltip";
import { formatCompactNumber } from "../utils/formatNumbers";

interface MetricSparklineProps {
readonly data: number[];
readonly color: string;
readonly dates?: number[];
}

function formatDate(timestamp: number): string {
return new Date(timestamp).toLocaleDateString("en-US", {
month: "short",
day: "numeric",
});
}

export default function MetricSparkline({
data,
color,
dates,
}: MetricSparklineProps) {
if (data.length === 0) return null;

const maxValue = Math.max(...data);
const reversed = [...data].reverse();
const reversedDates = dates ? [...dates].reverse() : undefined;

return (
<div className="tw-mt-auto tw-flex tw-h-12 tw-items-end tw-gap-px tw-pt-4">
{reversed.map((value, index) => {
const height = maxValue > 0 ? (value / maxValue) * 100 : 0;
const date = reversedDates?.[index];
const tooltipContent =
typeof date === "number"
? `${formatDate(date)}: ${formatCompactNumber(value)}`
: formatCompactNumber(value);

return (
<CustomTooltip key={index} content={tooltipContent} placement="top">
<div
className={`tw-max-w-1.5 tw-flex-1 tw-rounded-t tw-grayscale tw-transition-all tw-duration-300 group-hover:tw-grayscale-0 hover:tw-opacity-80 ${color}`}
style={{ height: `${Math.max(height, 3)}%` }}
/>
</CustomTooltip>
);
})}
</div>
);
}
39 changes: 39 additions & 0 deletions app/network/metrics/page.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { useSetTitle } from "@/contexts/TitleContext";
import { useCommunityMetrics } from "@/hooks/useCommunityMetrics";
import { useCommunityMetricsSeries } from "@/hooks/useCommunityMetricsSeries";
import { useMintMetrics } from "@/hooks/useMintMetrics";
import CumulativeMetricCard from "./components/CumulativeMetricCard";
import MetricCard from "./components/MetricCard";
Expand Down Expand Up @@ -30,10 +31,12 @@ export default function MetricsPageClient() {
const dailyQuery = useCommunityMetrics("DAY");
const weeklyQuery = useCommunityMetrics("WEEK");
const mintQuery = useMintMetrics(50);
const seriesQuery = useCommunityMetricsSeries();

const isLoading =
dailyQuery.isLoading || weeklyQuery.isLoading || mintQuery.isLoading;
const error = dailyQuery.error ?? weeklyQuery.error ?? mintQuery.error;
const series = seriesQuery.data;

return (
<div className="tailwind-scope tw-min-h-screen tw-bg-black">
Expand Down Expand Up @@ -68,6 +71,9 @@ export default function MetricsPageClient() {
icon={<DroppersIcon />}
iconBgColor="tw-bg-purple-500"
accentColor="tw-text-purple-400"
sparklineData={series?.distinctDroppers}
sparklineColor="tw-bg-purple-500"
sparklineDates={series?.stepsStartTimes}
/>
<MetricCard
title="Drops Created"
Expand All @@ -76,6 +82,9 @@ export default function MetricsPageClient() {
icon={<DropsIcon />}
iconBgColor="tw-bg-blue-500"
accentColor="tw-text-blue-400"
sparklineData={series?.dropsCreated}
sparklineColor="tw-bg-blue-500"
sparklineDates={series?.stepsStartTimes}
/>
<MetricCard
title="Submissions"
Expand All @@ -84,6 +93,9 @@ export default function MetricsPageClient() {
icon={<SubmissionsIcon />}
iconBgColor="tw-bg-orange-500"
accentColor="tw-text-orange-400"
sparklineData={series?.mainStageSubmissions}
sparklineColor="tw-bg-orange-500"
sparklineDates={series?.stepsStartTimes}
/>
<MetricCard
title="Distinct Voters"
Expand All @@ -92,6 +104,9 @@ export default function MetricsPageClient() {
icon={<VotersIcon />}
iconBgColor="tw-bg-emerald-500"
accentColor="tw-text-emerald-400"
sparklineData={series?.mainStageDistinctVoters}
sparklineColor="tw-bg-emerald-500"
sparklineDates={series?.stepsStartTimes}
/>
<MetricCard
title="Vote Volume"
Expand All @@ -101,6 +116,9 @@ export default function MetricsPageClient() {
iconBgColor="tw-bg-cyan-500"
accentColor="tw-text-cyan-400"
useValueCount
sparklineData={series?.mainStageVotes}
sparklineColor="tw-bg-cyan-500"
sparklineDates={series?.stepsStartTimes}
/>
<CumulativeMetricCard
title="Voting Power"
Expand All @@ -110,6 +128,9 @@ export default function MetricsPageClient() {
iconBgColor="tw-bg-amber-500"
accentColor="tw-text-amber-400"
unit="TDH"
sparklineData={series?.tdhOnMainStageSubmissions}
sparklineColor="tw-bg-amber-500"
sparklineDates={series?.stepsStartTimes}
/>
<CumulativeMetricCard
title="Network TDH"
Expand All @@ -120,6 +141,9 @@ export default function MetricsPageClient() {
accentColor="tw-text-teal-400"
unit="TDH"
href="/network/metrics/network-tdh"
sparklineData={series?.networkTdh}
sparklineColor="tw-bg-teal-500"
sparklineDates={series?.stepsStartTimes}
/>
<CumulativeMetricCard
title="TDH Utilization %"
Expand All @@ -129,6 +153,9 @@ export default function MetricsPageClient() {
iconBgColor="tw-bg-rose-500"
accentColor="tw-text-rose-400"
unit="%"
sparklineData={series?.tdhUtilizationPercentage}
sparklineColor="tw-bg-rose-500"
sparklineDates={series?.stepsStartTimes}
/>
<CumulativeMetricCard
title="xTDH Granted"
Expand All @@ -138,6 +165,9 @@ export default function MetricsPageClient() {
iconBgColor="tw-bg-lime-500"
accentColor="tw-text-lime-400"
unit="xTDH"
sparklineData={series?.xtdhGranted}
sparklineColor="tw-bg-lime-500"
sparklineDates={series?.stepsStartTimes}
/>
<CumulativeMetricCard
title="Profile Count"
Expand All @@ -146,6 +176,9 @@ export default function MetricsPageClient() {
icon={<ProfileIcon />}
iconBgColor="tw-bg-violet-500"
accentColor="tw-text-violet-400"
sparklineData={series?.profileCount}
sparklineColor="tw-bg-violet-500"
sparklineDates={series?.stepsStartTimes}
/>
<MetricCard
title="Active Identities"
Expand All @@ -154,6 +187,9 @@ export default function MetricsPageClient() {
icon={<ActiveIdentitiesIcon />}
iconBgColor="tw-bg-pink-500"
accentColor="tw-text-pink-400"
sparklineData={series?.activeIdentities}
sparklineColor="tw-bg-pink-500"
sparklineDates={series?.stepsStartTimes}
/>
<MetricCard
title="Consolidations Formed"
Expand All @@ -162,6 +198,9 @@ export default function MetricsPageClient() {
icon={<ConsolidationsIcon />}
iconBgColor="tw-bg-indigo-500"
accentColor="tw-text-indigo-400"
sparklineData={series?.consolidationsFormed}
sparklineColor="tw-bg-indigo-500"
sparklineDates={series?.stepsStartTimes}
/>
</div>
)}
Expand Down
25 changes: 11 additions & 14 deletions components/react-query-wrapper/ReactQueryWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export enum QueryKey {
WAVE_OUTCOME_DISTRIBUTION = "WAVE_OUTCOME_DISTRIBUTION",
WAVE_OUTCOME_DISTRIBUTION_PAGE = "WAVE_OUTCOME_DISTRIBUTION_PAGE",
COMMUNITY_METRICS = "COMMUNITY_METRICS",
COMMUNITY_METRICS_SERIES = "COMMUNITY_METRICS_SERIES",
MINT_METRICS = "MINT_METRICS",
}

Expand Down Expand Up @@ -301,13 +302,11 @@ const createReactQueryContextValue = (
const existingData = queryClient.getQueryData(queryKey);
if (existingData) {
return;
} else {
// If there's no existing data, set the initial data
queryClient.setQueryData<InfiniteData<ApiWave[]>>(queryKey, {
}
queryClient.setQueryData<InfiniteData<ApiWave[]>>(queryKey, {
pages: [wavesOverview],
pageParams: [undefined],
});
}
};

const setWaveDrops = ({
Expand All @@ -330,13 +329,11 @@ const createReactQueryContextValue = (
const existingData = queryClient.getQueryData(queryKey);
if (existingData) {
return;
} else {
// If there's no existing data, set the initial data
queryClient.setQueryData<InfiniteData<ApiWaveDropsFeed>>(queryKey, {
pages: [waveDrops],
pageParams: [undefined],
});
}
queryClient.setQueryData<InfiniteData<ApiWaveDropsFeed>>(queryKey, {
pages: [waveDrops],
pageParams: [undefined],
});
};

const setProfileProxy = (profileProxy: ApiProfileProxy) => {
Expand Down Expand Up @@ -559,7 +556,7 @@ const createReactQueryContextValue = (
rater: rater.toLowerCase(),
});
}
if (profileProxy?.created_by?.handle && profileProxy.granted_to?.handle) {
if (profileProxy?.created_by.handle && profileProxy.granted_to.handle) {
invalidateQueries({
key: QueryKey.PROFILE,
values: [
Expand All @@ -571,12 +568,12 @@ const createReactQueryContextValue = (
key: QueryKey.PROFILE_RATERS,
values: [
{
handleOrWallet: profileProxy.created_by?.handle,
handleOrWallet: profileProxy.created_by.handle,
matter: RateMatter.NIC,
given: false,
},
{
handleOrWallet: profileProxy.granted_to?.handle,
handleOrWallet: profileProxy.granted_to.handle,
matter: RateMatter.NIC,
given: false,
},
Expand Down Expand Up @@ -643,7 +640,7 @@ const createReactQueryContextValue = (
});
}

if (profileProxy?.created_by?.handle && profileProxy.granted_to?.handle) {
if (profileProxy?.created_by.handle && profileProxy.granted_to.handle) {
invalidateQueries({
key: QueryKey.PROFILE,
values: [
Expand Down
Loading