Skip to content

Commit ff75479

Browse files
committed
Lazy load plan customer counts
1 parent da2902f commit ff75479

3 files changed

Lines changed: 53 additions & 6 deletions

File tree

vite/src/views/products/products/components/product-list/ProductListColumns.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ProductV2 } from "@autumn/shared";
2-
import { MiniCopyButton } from "@autumn/ui";
2+
import { MiniCopyButton, Skeleton } from "@autumn/ui";
33
import type { Row } from "@tanstack/react-table";
44
import type { SandboxSummary } from "@/hooks/queries/useSandboxesQuery";
55
import { formatUnixToDateTime } from "@/utils/formatUtils/formatDateUtils";
@@ -9,10 +9,12 @@ import { ProductNameCell } from "./ProductNameCell";
99

1010
export const createProductListColumns = ({
1111
showGroup = false,
12+
isCountsLoading = false,
1213
onDeleteClick,
1314
sandboxes = [],
1415
}: {
1516
showGroup?: boolean;
17+
isCountsLoading?: boolean;
1618
onDeleteClick?: (product: ProductV2) => void;
1719
sandboxes?: SandboxSummary[];
1820
} = {}) => [
@@ -63,7 +65,14 @@ export const createProductListColumns = ({
6365
cell: ({ row }: { row: Row<ProductV2 & { active_count?: number }> }) => {
6466
return (
6567
<div className="text-muted-foreground">
66-
<ProductCountsTooltip product={row.original} />
68+
{isCountsLoading ? (
69+
<Skeleton
70+
aria-label="Loading customer count"
71+
className="h-4 w-14"
72+
/>
73+
) : (
74+
<ProductCountsTooltip product={row.original} />
75+
)}
6776
</div>
6877
);
6978
},

vite/src/views/products/products/components/product-list/ProductListTable.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,11 @@ export function ProductListTable() {
139139
() =>
140140
createProductListColumns({
141141
showGroup: hasAnyGroup,
142+
isCountsLoading,
142143
onDeleteClick: handleDeleteClick,
143144
sandboxes,
144145
}),
145-
[hasAnyGroup, handleDeleteClick, sandboxes],
146+
[hasAnyGroup, isCountsLoading, handleDeleteClick, sandboxes],
146147
);
147148

148149
const recurringBaseTable = useProductTable({
@@ -213,7 +214,6 @@ export function ProductListTable() {
213214
table: recurringBaseTable,
214215
numberOfColumns: columns.length,
215216
enableSorting,
216-
isLoading: isCountsLoading,
217217
getRowHref,
218218
getRowClassName: (product: ProductWithCounts) =>
219219
product.base_id
@@ -241,7 +241,6 @@ export function ProductListTable() {
241241
table: recurringAddOnTable,
242242
numberOfColumns: columns.length,
243243
enableSorting,
244-
isLoading: isCountsLoading,
245244
getRowHref,
246245
rowClassName: "h-10",
247246
}}
@@ -261,7 +260,6 @@ export function ProductListTable() {
261260
table: oneTimeTable,
262261
numberOfColumns: columns.length,
263262
enableSorting,
264-
isLoading: isCountsLoading,
265263
getRowHref,
266264
emptyStateText:
267265
"One-time prices for top-ups or lifetime purchases",
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { describe, expect, test } from "bun:test";
2+
import type { ProductV2 } from "@autumn/shared";
3+
import { Skeleton } from "@autumn/ui";
4+
import type { ReactElement } from "react";
5+
import { createProductListColumns } from "@/views/products/products/components/product-list/ProductListColumns";
6+
import { ProductCountsTooltip } from "@/views/products/products/product-row-toolbar/ProductCountsTooltip";
7+
8+
const product = { id: "pro" } as ProductV2;
9+
10+
const renderCustomerCell = ({
11+
isCountsLoading,
12+
}: {
13+
isCountsLoading: boolean;
14+
}) => {
15+
const customerColumn = createProductListColumns({ isCountsLoading }).find(
16+
(column) => column.header === "Customers",
17+
);
18+
19+
if (typeof customerColumn?.cell !== "function") {
20+
throw new Error("Customers column cell is not renderable");
21+
}
22+
23+
return customerColumn.cell({
24+
row: { original: product },
25+
} as never) as ReactElement<{ children: ReactElement }>;
26+
};
27+
28+
describe("product list customer count loading", () => {
29+
test("shows a skeleton in the Customers cell while counts load", () => {
30+
const cell = renderCustomerCell({ isCountsLoading: true });
31+
32+
expect(cell.props.children.type).toBe(Skeleton);
33+
});
34+
35+
test("shows the customer count tooltip after counts load", () => {
36+
const cell = renderCustomerCell({ isCountsLoading: false });
37+
38+
expect(cell.props.children.type).toBe(ProductCountsTooltip);
39+
});
40+
});

0 commit comments

Comments
 (0)