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
Expand Up @@ -11,6 +11,7 @@ import {
} from "@/components/ui/select";
import { SkeletonContainer } from "@/components/ui/skeleton";
import { useState } from "react";
import { toUSD } from "../../../../utils/number";
import {
type PayTopCustomersData,
usePayCustomers,
Expand Down Expand Up @@ -249,7 +250,7 @@ function getCSVData(data: PayTopCustomersData["customers"]) {
const header = ["Wallet Address", "Total spend"];
const rows = data.map((customer) => [
customer.walletAddress,
`$${(customer.totalSpendUSDCents / 100).toLocaleString()}`,
toUSD(customer.totalSpendUSDCents / 100),
]);

return { header, rows };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { SkeletonContainer } from "@/components/ui/skeleton";
import { ToolTipLabel } from "@/components/ui/tooltip";
import { cn } from "@/lib/utils";
import { useState } from "react";
import { toUSD } from "../../../../utils/number";
import { usePayVolume } from "../hooks/usePayVolume";
import { CardHeading, FailedToLoad } from "./common";

Expand Down Expand Up @@ -229,7 +230,7 @@ function InfoRow(props: {
props.isEmpty
? "$-"
: props.amount !== undefined
? `$${props.amount.toLocaleString()}`
? toUSD(props.amount)
: undefined
}
skeletonData="$50"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { SkeletonContainer } from "@/components/ui/skeleton";
import { format } from "date-fns";
import { useEffect, useState } from "react";
import { Bar, BarChart, ResponsiveContainer, Tooltip, XAxis } from "recharts";
import { toUSD } from "../../../../utils/number";
import { AreaChartLoadingState } from "../../../analytics/area-chart";
import { usePayVolume } from "../hooks/usePayVolume";
import {
Expand Down Expand Up @@ -144,7 +145,7 @@ function RenderData(props: {
props.query.isEmpty
? "$-"
: props.query.data
? `$${props.query.data?.totalPayoutsUSD}`
? toUSD(props.query.data.totalPayoutsUSD)
: undefined
}
skeletonData="$20"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { SkeletonContainer } from "@/components/ui/skeleton";
import { cn } from "@/lib/utils";
import { Cell, Pie, PieChart } from "recharts";
import { toUSD } from "../../../../utils/number";
import { usePayVolume } from "../hooks/usePayVolume";
import { FailedToLoad, chartHeight } from "./common";

Expand Down Expand Up @@ -155,7 +156,7 @@ function RenderData(props: { query: ProcessedQuery }) {
<SkeletonContainer
loadedData={
queryData
? `$${queryData?.totalAmount.toLocaleString()}`
? toUSD(queryData.totalAmount)
: props.query.isEmpty
? "NA"
: undefined
Expand Down Expand Up @@ -187,7 +188,7 @@ function RenderData(props: { query: ProcessedQuery }) {
label={v.name}
amount={
queryData
? `$${v.amount.toLocaleString()}`
? toUSD(v.amount)
: props.query.isEmpty
? "$-"
: undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { useMemo } from "react";
import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts";
import type { UserOpStats } from "types/analytics";
import { useAllChainsData } from "../../../hooks/chains/allChains";
import { formatTickerNumber } from "../../../lib/format-utils";
import { toUSD } from "../../../utils/number";

type ChartData = Record<string, number> & {
time: string; // human readable date
Expand Down Expand Up @@ -210,13 +210,22 @@ export function TotalSponsoredChartCard(props: {
}}
tickLine={false}
axisLine={false}
tickFormatter={(value) => `$${formatTickerNumber(value)}`}
tickFormatter={(value) => toUSD(value)}
/>

<ChartTooltip
cursor={true}
content={
<ChartTooltipContent valueFormatter={(value) => `$${value}`} />
<ChartTooltipContent
valueFormatter={(value) => {
// typeguard
if (typeof value !== "number") {
return "";
}

return toUSD(value);
}}
/>
}
/>
<ChartLegend content={<ChartLegendContent />} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ export function createUserOpStatsStub(days: number): UserOpStats[] {

let d = days;
while (d !== 0) {
const successful = Math.floor(Math.random() * 100);
const failed = Math.floor(Math.random() * 100);
const sponsoredUsd = Math.floor(Math.random() * 100);
// don't use Math.floor because real data doesn't not have integer values
const successful = Math.random() * 100;
const failed = Math.random() * 100;
const sponsoredUsd = Math.random() * 100;

stubbedData.push({
date: new Date(2024, 1, d).toLocaleString(),
successful,
Expand Down
16 changes: 5 additions & 11 deletions apps/dashboard/src/lib/format-utils.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
const compactNumberFormatter = new Intl.NumberFormat("en-US", {
notation: "compact",
});

export const formatTickerNumber = (value: number) => {
if (value >= 1000000) {
const millions = value / 1000000;
// Only show decimal if not a whole number, up to 2 decimals with no trailing zeros
return `${millions % 1 === 0 ? millions.toFixed(0) : Number(millions.toFixed(2)).toString()}M`;
}
if (value >= 1000) {
const thousands = value / 1000;
// Only show decimal if not a whole number
return `${thousands % 1 === 0 ? thousands.toFixed(0) : thousands.toFixed(1)}k`;
}
return value.toString();
return compactNumberFormatter.format(value);
};

export const formatWalletType = (walletType: string) => {
Expand Down
14 changes: 10 additions & 4 deletions apps/dashboard/src/utils/number.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
const usdCurrencyFormatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD", // prefix with $
minimumFractionDigits: 0, // don't show decimal places if value is a whole number
maximumFractionDigits: 2, // at max 2 decimal places
roundingMode: "halfEven", // round to nearest even number, standard practice for financial calculations
notation: "compact", // shows 1.2M instead of 1,200,000, 1.2B instead of 1,200,000,000
});

export const toUSD = (value: number) => {
return new Intl.NumberFormat(undefined, {
style: "currency",
currency: "USD",
}).format(value);
return usdCurrencyFormatter.format(value);
};

export const toSize = (value: number | bigint, defaultUnit?: string) => {
Expand Down
Loading