Skip to content
Closed
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,6 +1,7 @@
"use client";
import { VirtualTable } from "@/components/virtual-table/index";
import type { Column } from "@/components/virtual-table/types";
import { formatNumberFull } from "@/lib/fmt";
import { shortenId } from "@/lib/shorten-id";
import { trpc } from "@/lib/trpc/client";
import { cn } from "@/lib/utils";
Expand Down Expand Up @@ -449,9 +450,10 @@ export const KeyDetailsLogsTable = ({ keyspaceId, keyId, selectedLog, onLogSelec
hide: isLoading,
countInfoText: (
<div className="flex gap-2">
<span>Showing</span> <span className="text-accent-12">{historicalLogs.length}</span>
<span>Showing</span>{" "}
<span className="text-accent-12">{formatNumberFull(historicalLogs.length)}</span>
<span>of</span>
{totalCount}
{formatNumberFull(totalCount)}
<span>requests</span>
</div>
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";
import { VirtualTable } from "@/components/virtual-table/index";
import type { Column } from "@/components/virtual-table/types";
import { formatNumberFull } from "@/lib/fmt";
import { shortenId } from "@/lib/shorten-id";
import type { KeyDetails } from "@/lib/trpc/routers/api/keys/query-api-keys/schema";
import { BookBookmark, Dots, Focus, Key } from "@unkey/icons";
Expand All @@ -25,10 +26,20 @@ import { StatusDisplay } from "./components/status-cell";
import { useKeysListQuery } from "./hooks/use-keys-list-query";
import { getRowClassName } from "./utils/get-row-class";

const SKELETON_COLUMN_KEYS = [
"select",
"key",
"value",
"usage",
"last_used",
"status",
"action",
] as const;

const KeysTableActionPopover = dynamic(
() =>
import("./components/actions/keys-table-action.popover.constants").then(
(mod) => mod.KeysTableActions,
(mod) => mod.KeysTableActions
),
{
ssr: false,
Expand All @@ -37,13 +48,16 @@ const KeysTableActionPopover = dynamic(
type="button"
className={cn(
"group-data-[state=open]:bg-gray-6 group-hover:bg-gray-6 group size-5 p-0 rounded m-0 items-center flex justify-center",
"border border-gray-6 group-hover:border-gray-8 ring-2 ring-transparent focus-visible:ring-gray-7 focus-visible:border-gray-7",
"border border-gray-6 group-hover:border-gray-8 ring-2 ring-transparent focus-visible:ring-gray-7 focus-visible:border-gray-7"
)}
>
<Dots className="group-hover:text-gray-12 text-gray-11" size="sm-regular" />
<Dots
className="group-hover:text-gray-12 text-gray-11"
size="sm-regular"
/>
</button>
),
},
}
);

export const KeysList = ({
Expand All @@ -53,9 +67,10 @@ export const KeysList = ({
keyspaceId: string;
apiId: string;
}) => {
const { keys, isLoading, isLoadingMore, loadMore, totalCount, hasMore } = useKeysListQuery({
keyAuthId: keyspaceId,
});
const { keys, isLoading, isLoadingMore, loadMore, totalCount, hasMore } =
useKeysListQuery({
keyAuthId: keyspaceId,
});
const [selectedKey, setSelectedKey] = useState<KeyDetails | null>(null);
const [navigatingKeyId, setNavigatingKeyId] = useState<string | null>(null);
// Add state for selected keys
Expand Down Expand Up @@ -98,13 +113,17 @@ export const KeysList = ({
className={cn(
"size-5 rounded flex items-center justify-center cursor-pointer",
identity ? "bg-successA-3" : "bg-grayA-3",
isSelected && "bg-brand-5",
isSelected && "bg-brand-5"
)}
onMouseEnter={() => setHoveredKeyId(key.id)}
onMouseLeave={() => setHoveredKeyId(null)}
>
{isNavigating ? (
<div className={cn(identity ? "text-successA-11" : "text-grayA-11")}>
<div
className={cn(
identity ? "text-successA-11" : "text-grayA-11"
)}
>
<Loading size={18} />
</div>
) : (
Expand Down Expand Up @@ -155,17 +174,24 @@ export const KeysList = ({
rel="noopener noreferrer"
aria-disabled={isNavigating}
>
<span className="font-mono bg-gray-4 p-1 rounded">{identity}</span>
<span className="font-mono bg-gray-4 p-1 rounded">
{identity}
</span>
</Link>
) : (
<span className="font-mono bg-gray-4 p-1 rounded">{identity}</span>
<span className="font-mono bg-gray-4 p-1 rounded">
{identity}
</span>
)}
Comment on lines +177 to 185
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Make the tooltip trigger focusable for keyboard users

iconContainer is a div; with asChild, the trigger won’t be focusable. Add tabIndex and an aria-label for a11y.

-                    {React.cloneElement(iconContainer, {
-                      className: cn(
-                        iconContainer.props.className,
-                        "cursor-pointer"
-                      ),
-                    })}
+                    {React.cloneElement(iconContainer, {
+                      className: cn(iconContainer.props.className, "cursor-pointer"),
+                      tabIndex: 0,
+                      role: "button",
+                      "aria-label": "Key identity info",
+                    })}

Also applies to: 179-184

🤖 Prompt for AI Agents
In
apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/_components/components/table/keys-list.tsx
around lines 166-174 (and likewise 179-184), the tooltip trigger is using a div
asChild which is not keyboard-focusable; make the trigger accessible by either
replacing the div with a semantic focusable element (e.g., a button) or adding
tabIndex={0} and a descriptive aria-label to the existing element so it can
receive keyboard focus and convey its purpose to assistive tech; apply the same
change to the second occurrence at lines 179-184.

</>
}
asChild
>
{React.cloneElement(iconContainer, {
className: cn(iconContainer.props.className, "cursor-pointer"),
className: cn(
iconContainer.props.className,
"cursor-pointer"
),
})}
</InfoTooltip>
) : (
Expand Down Expand Up @@ -205,7 +231,11 @@ export const KeysList = ({
header: "Value",
width: "15%",
render: (key) => (
<HiddenValueCell value={key.start} title="Value" selected={selectedKey?.id === key.id} />
<HiddenValueCell
value={key.start}
title="Value"
selected={selectedKey?.id === key.id}
/>
),
},
{
Expand Down Expand Up @@ -266,7 +296,7 @@ export const KeysList = ({
selectedKeys,
toggleSelection,
hoveredKeyId,
],
]
);

const getSelectedKeysState = useCallback(() => {
Expand All @@ -291,17 +321,15 @@ export const KeysList = ({

// Early exit if we already found a mix
if (!allEnabled && !allDisabled) {
break;
return "mixed";
}
}

if (allEnabled) {
return "all-enabled";
}
if (allDisabled) {
return "all-disabled";
}
return "mixed";

return "all-disabled";
}, [selectedKeys, keys]);

return (
Expand Down Expand Up @@ -330,9 +358,12 @@ export const KeysList = ({
),
countInfoText: (
<div className="flex gap-2">
<span>Showing</span> <span className="text-accent-12">{keys.length}</span>
<span>Showing</span>{" "}
<span className="text-accent-12">
{formatNumberFull(keys.length)}
</span>
<span>of</span>
{totalCount}
{formatNumberFull(totalCount)}
<span>keys</span>
</div>
),
Expand All @@ -343,8 +374,8 @@ export const KeysList = ({
<Empty.Icon className="w-auto" />
<Empty.Title>No API Keys Found</Empty.Title>
<Empty.Description className="text-left">
There are no API keys associated with this service yet. Create your first API key to
get started.
There are no API keys associated with this service yet. Create
your first API key to get started.
</Empty.Description>
<Empty.Actions className="mt-4 justify-start">
<a
Expand Down Expand Up @@ -374,7 +405,7 @@ export const KeysList = ({
className={cn(
"text-xs align-middle whitespace-nowrap pr-4",
idx === 0 ? "pl-[18px]" : "",
column.key === "key" ? "py-[6px]" : "py-1",
column.key === "key" ? "py-[6px]" : "py-1"
)}
style={{ height: `${rowHeight}px` }}
>
Expand All @@ -384,9 +415,11 @@ export const KeysList = ({
{column.key === "last_used" && <LastUsedColumnSkeleton />}
{column.key === "status" && <StatusColumnSkeleton />}
{column.key === "action" && <ActionColumnSkeleton />}
{!["select", "key", "value", "usage", "last_used", "status", "action"].includes(
column.key,
) && <div className="h-4 w-full bg-grayA-3 rounded animate-pulse" />}
{!SKELETON_COLUMN_KEYS.includes(
column.key as (typeof SKELETON_COLUMN_KEYS)[number]
) && (
<div className="h-4 w-full bg-grayA-3 rounded animate-pulse" />
)}
</td>
))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import { EmptyComponentSpacer } from "@/components/empty-component-spacer";
import { formatNumberFull } from "@/lib/fmt";
import { trpc } from "@/lib/trpc/client";
import { BookBookmark } from "@unkey/icons";
import { Button, Empty } from "@unkey/ui";
Expand Down Expand Up @@ -81,7 +82,8 @@ export const ApiListClient = () => {

<div className="flex flex-col items-center justify-center mt-8 space-y-4 pb-8">
<div className="text-center text-sm text-accent-11">
Showing {apiList.length} of {apisData?.pages[0]?.total || 0} APIs
Showing {formatNumberFull(apiList.length)} of{" "}
{formatNumberFull(apisData?.pages[0]?.total || 0)} APIs
</div>

{!isSearching && hasNextPage && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { EmptyComponentSpacer } from "@/components/empty-component-spacer";
import { formatNumberFull } from "@/lib/fmt";
import type { ApiOverview } from "@/lib/trpc/routers/api/overview/query-overview/schemas";
import { ChevronDown } from "@unkey/icons";
import { Button, Empty } from "@unkey/ui";
Expand Down Expand Up @@ -43,7 +44,7 @@ export const ApiListGrid = ({

<div className="flex flex-col items-center justify-center mt-8 space-y-4 pb-8">
<div className="text-center text-sm text-accent-11">
Showing {apiList.length} of {total} APIs
Showing {formatNumberFull(apiList.length)} of {formatNumberFull(total)} APIs
</div>

{!isSearching && hasMore && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";
import { VirtualTable } from "@/components/virtual-table/index";
import type { Column } from "@/components/virtual-table/types";
import { formatNumberFull } from "@/lib/fmt";
import type { Permission } from "@/lib/trpc/routers/authorization/permissions/query";
import { BookBookmark, Page2 } from "@unkey/icons";
import { Button, Checkbox, Empty } from "@unkey/ui";
Expand Down Expand Up @@ -182,9 +183,10 @@ export const PermissionsList = () => {
),
countInfoText: (
<div className="flex gap-2">
<span>Showing</span> <span className="text-accent-12">{permissions.length}</span>
<span>Showing</span>{" "}
<span className="text-accent-12">{formatNumberFull(permissions.length)}</span>
<span>of</span>
{totalCount}
{formatNumberFull(totalCount)}
<span>permissions</span>
</div>
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";
import { VirtualTable } from "@/components/virtual-table/index";
import type { Column } from "@/components/virtual-table/types";
import { formatNumberFull } from "@/lib/fmt";
import type { RoleBasic } from "@/lib/trpc/routers/authorization/roles/query";
import { BookBookmark, Tag } from "@unkey/icons";
import { Button, Checkbox, Empty } from "@unkey/ui";
Expand Down Expand Up @@ -166,9 +167,10 @@ export const RolesList = () => {
),
countInfoText: (
<div className="flex gap-2">
<span>Showing</span> <span className="text-accent-12">{roles.length}</span>
<span>Showing</span>{" "}
<span className="text-accent-12">{formatNumberFull(roles.length)}</span>
<span>of</span>
{totalCount}
{formatNumberFull(totalCount)}
<span>roles</span>
</div>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { VirtualTable } from "@/components/virtual-table/index";
import type { Column } from "@/components/virtual-table/types";
import { formatNumberFull } from "@/lib/fmt";
import { cn } from "@/lib/utils";
import type { Log } from "@unkey/clickhouse/src/logs";
import { BookBookmark, TriangleWarning2 } from "@unkey/icons";
Expand Down Expand Up @@ -250,9 +251,10 @@ export const LogsTable = () => {
hasMore,
countInfoText: (
<div className="flex gap-2">
<span>Showing</span> <span className="text-accent-12">{historicalLogs.length}</span>
<span>Showing</span>{" "}
<span className="text-accent-12">{formatNumberFull(historicalLogs.length)}</span>
<span>of</span>
{total}
{formatNumberFull(total)}
<span>requests</span>
</div>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { VirtualTable } from "@/components/virtual-table/index";
import type { Column } from "@/components/virtual-table/types";
import { useIsMobile } from "@/hooks/use-mobile";
import type { Deployment, Environment } from "@/lib/collections";

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing type imports cause compilation error: Deployment and Environment types are used but their import statement was removed.

View Details
📝 Patch Details
diff --git a/apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/deployments-list.tsx b/apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/deployments-list.tsx
index afe222b25..9876d5843 100644
--- a/apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/deployments-list.tsx
+++ b/apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/deployments-list.tsx
@@ -2,6 +2,7 @@
 import { VirtualTable } from "@/components/virtual-table/index";
 import type { Column } from "@/components/virtual-table/types";
 import { useIsMobile } from "@/hooks/use-mobile";
+import type { Deployment, Environment } from "@/lib/collections";
 
 import { shortenId } from "@/lib/shorten-id";
 import { BookBookmark, Cloud, CodeBranch, Cube } from "@unkey/icons";

Analysis

Missing type imports cause TypeScript compilation errors in deployments-list.tsx

What fails: TypeScript compilation fails with "Cannot find name 'Deployment'" and "Cannot find name 'Environment'" errors in deployments-list.tsx on lines 44-45 and throughout the component

How to reproduce:

cd apps/dashboard
pnpm exec tsc --noEmit --isolatedModules --jsx react-jsx app/\(app\)/projects/\[projectId\]/deployments/components/table/deployments-list.tsx

Result: TypeScript errors:

error TS2304: Cannot find name 'Deployment'.
error TS2304: Cannot find name 'Environment'.

Expected: Code should compile without type errors since the types are defined and exported from @/lib/collections

Fix: Added import type { Deployment, Environment } from "@/lib/collections"; to resolve the missing type definitions used in component state and prop declarations.

import { shortenId } from "@/lib/shorten-id";
import { BookBookmark, Cloud, CodeBranch, Cube } from "@unkey/icons";
import { Button, Empty, TimestampInfo } from "@unkey/ui";
Expand Down Expand Up @@ -307,7 +307,7 @@ export const DeploymentsList = () => {
onRowClick={setSelectedDeployment}
selectedItem={selectedDeployment}
keyExtractor={(deployment) => deployment.id}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix keyExtractor to use row.deployment.id

VirtualTable rows appear to be shaped as { deployment, environment }. The current extractor uses the row itself as a Deployment, which likely produces undefined/duplicate keys.

-      keyExtractor={(deployment) => deployment.id}
+      keyExtractor={(row) => row.deployment.id}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
keyExtractor={(deployment) => deployment.id}
keyExtractor={(row) => row.deployment.id}
🤖 Prompt for AI Agents
In
apps/dashboard/app/(app)/projects/[projectId]/deployments/components/table/deployments-list.tsx
around line 292, the keyExtractor currently treats the row as a Deployment and
returns deployment.id from the row itself, but rows are shaped as { deployment,
environment } so this yields undefined/duplicate keys; update the keyExtractor
to return row.deployment.id (or otherwise access the nested deployment object)
to ensure a stable, unique key for each VirtualTable row.

rowClassName={(deployment) => getRowClassName(deployment, selectedDeployment?.deployment.id)}

emptyState={
<div className="w-full flex justify-center items-center h-full">
<Empty className="w-[400px] flex items-start">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { collection } from "@/lib/collections";
import { ilike, useLiveQuery } from "@tanstack/react-db";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing imports cause compilation error: collection, useLiveQuery, and ilike are used but not imported after the import statements were accidentally removed.

View Details
📝 Patch Details
diff --git a/apps/dashboard/app/(app)/projects/_components/list/index.tsx b/apps/dashboard/app/(app)/projects/_components/list/index.tsx
index b0d569ece..e2d6fe4ea 100644
--- a/apps/dashboard/app/(app)/projects/_components/list/index.tsx
+++ b/apps/dashboard/app/(app)/projects/_components/list/index.tsx
@@ -1,6 +1,8 @@
 
 import { BookBookmark, Dots } from "@unkey/icons";
 import { Button, Empty } from "@unkey/ui";
+import { ilike, useLiveQuery } from "@tanstack/react-db";
+import { collection } from "@/lib/collections";
 import { useProjectsFilters } from "../hooks/use-projects-filters";
 import { ProjectActions } from "./project-actions";
 import { ProjectCard } from "./projects-card";
@@ -101,6 +103,6 @@ export const ProjectsList = () => {
           />
         ))}
       </div>
-
+    </div>
   );
 };

Analysis

Missing imports cause TypeScript compilation errors in ProjectsList component

What fails: ProjectsList component in apps/dashboard/app/(app)/projects/_components/list/index.tsx uses useLiveQuery, collection.projects, and ilike on lines 15-19 without importing them, causing TypeScript compilation errors.

How to reproduce:

cd apps/dashboard && pnpm run typecheck

Result: TypeScript compiler reports:

app/(app)/projects/_components/list/index.tsx(15,20): error TS2304: Cannot find name 'useLiveQuery'.
app/(app)/projects/_components/list/index.tsx(18,26): error TS2304: Cannot find name 'collection'.
app/(app)/projects/_components/list/index.tsx(19,33): error TS2304: Cannot find name 'ilike'.

Expected: Clean compilation with proper imports from @tanstack/react-db and @/lib/collections per TanStack DB React documentation


Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical syntax errors: Missing required imports for collection, ilike, and useLiveQuery, and malformed JSX with missing closing </div> tag.

View Details
📝 Patch Details
diff --git a/apps/dashboard/app/(app)/projects/_components/list/index.tsx b/apps/dashboard/app/(app)/projects/_components/list/index.tsx
index b0d569ece..e2d6fe4ea 100644
--- a/apps/dashboard/app/(app)/projects/_components/list/index.tsx
+++ b/apps/dashboard/app/(app)/projects/_components/list/index.tsx
@@ -1,6 +1,8 @@
 
 import { BookBookmark, Dots } from "@unkey/icons";
 import { Button, Empty } from "@unkey/ui";
+import { ilike, useLiveQuery } from "@tanstack/react-db";
+import { collection } from "@/lib/collections";
 import { useProjectsFilters } from "../hooks/use-projects-filters";
 import { ProjectActions } from "./project-actions";
 import { ProjectCard } from "./projects-card";
@@ -101,6 +103,6 @@ export const ProjectsList = () => {
           />
         ))}
       </div>
-
+    </div>
   );
 };

Analysis

Critical syntax errors in ProjectsList component: Missing imports and unclosed JSX tag

What fails: File apps/dashboard/app/(app)/projects/_components/list/index.tsx has compilation-blocking errors preventing TypeScript compilation

How to reproduce:

cd apps/dashboard && pnpm run typecheck

Result: TypeScript compiler fails with errors:

  • Line 15: Cannot find name 'useLiveQuery'
  • Line 18: Cannot find name 'collection'
  • Line 19: Cannot find name 'ilike'
  • Line 70: JSX element 'div' has no corresponding closing tag

Expected: File should compile without TypeScript errors

Fix applied:

  • Added missing imports: import { ilike, useLiveQuery } from "@tanstack/react-db"; and import { collection } from "@/lib/collections";
  • Added missing closing </div> tag to complete JSX structure

import { BookBookmark, Dots } from "@unkey/icons";
import { Button, Empty } from "@unkey/ui";
import { useProjectsFilters } from "../hooks/use-projects-filters";
Expand Down Expand Up @@ -102,6 +101,6 @@ export const ProjectsList = () => {
/>
))}
</div>
</div>

);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useSort } from "@/components/logs/hooks/use-sort";
import { VirtualTable } from "@/components/virtual-table/index";
import type { Column } from "@/components/virtual-table/types";
import { formatNumber } from "@/lib/fmt";
import { formatNumber, formatNumberFull } from "@/lib/fmt";
import { cn } from "@/lib/utils";
import type { RatelimitOverviewLog } from "@unkey/clickhouse/src/ratelimits";
import { Ban, BookBookmark } from "@unkey/icons";
Expand Down Expand Up @@ -218,8 +218,9 @@ export const RatelimitOverviewLogsTable = ({
hide: isLoading,
countInfoText: (
<div className="flex gap-2">
<span>Showing</span> <span className="text-accent-12">{historicalLogs.length}</span>
<span>of {totalCount}</span>
<span>Showing</span>{" "}
<span className="text-accent-12">{formatNumberFull(historicalLogs.length)}</span>
<span>of {formatNumberFull(totalCount)}</span>
<span>rate limit identifiers</span>
</div>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { safeParseJson } from "@/app/(app)/logs/utils";
import { VirtualTable } from "@/components/virtual-table/index";
import type { Column } from "@/components/virtual-table/types";
import { formatNumberFull } from "@/lib/fmt";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Don't force en-US; honor user locale and cache formatter

Import looks good, but current formatNumberFull uses Intl.NumberFormat("en-US"), which conflicts with the PR goal of “locale-appropriate” formatting and allocates a formatter per call. Switch the helper to default-locale (or param) and cache per locale.

Support (outside selected lines, apps/dashboard/lib/fmt.ts):

-export function formatNumberFull(n: number): string {
-  return Intl.NumberFormat("en-US").format(n);
-}
+const nfCache = new Map<string | undefined, Intl.NumberFormat>();
+function getNF(locale?: string) {
+  if (!nfCache.has(locale)) nfCache.set(locale, new Intl.NumberFormat(locale));
+  return nfCache.get(locale)!;
+}
+export function formatNumberFull(n: number, locale?: string): string {
+  return getNF(locale).format(n);
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { formatNumberFull } from "@/lib/fmt";
// apps/dashboard/lib/fmt.ts
const nfCache = new Map<string | undefined, Intl.NumberFormat>();
function getNF(locale?: string) {
if (!nfCache.has(locale)) nfCache.set(locale, new Intl.NumberFormat(locale));
return nfCache.get(locale)!;
}
export function formatNumberFull(n: number, locale?: string): string {
return getNF(locale).format(n);
}

import { cn } from "@/lib/utils";
import type { RatelimitLog } from "@unkey/clickhouse/src/ratelimits";
import { BookBookmark } from "@unkey/icons";
Expand Down Expand Up @@ -220,9 +221,10 @@ export const RatelimitLogsTable = () => {
hide: isLoading,
countInfoText: (
<div className="flex gap-2">
<span>Showing</span> <span className="text-accent-12">{historicalLogs.length}</span>
<span>Showing</span>{" "}
<span className="text-accent-12">{formatNumberFull(historicalLogs.length)}</span>
<span>of</span>
{totalCount}
{formatNumberFull(totalCount)}
<span>ratelimit requests</span>
</div>
),
Expand Down
Loading