Skip to content

Commit a549dea

Browse files
committed
feat: enhance AppsPreviewTable and appsQuery with ordering options and recent usage filter
1 parent f1ed9c2 commit a549dea

File tree

3 files changed

+100
-17
lines changed

3 files changed

+100
-17
lines changed

src/modules/apps/AppsPreviewTable.tsx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { PREVIEW_TABLE_LENGTH, PREVIEW_TABLE_REFETCH_INTERVAL } from '@/config';
22
import { execute } from '@/graphql/poco/execute';
3+
import { App_OrderBy, OrderDirection } from '@/graphql/poco/graphql';
34
import { cn } from '@/lib/utils';
45
import { useQuery } from '@tanstack/react-query';
56
import { LoaderCircle } from 'lucide-react';
@@ -8,25 +9,38 @@ import { DataTable } from '@/components/DataTable';
89
import AppIcon from '@/components/icons/AppIcon';
910
import { Button } from '@/components/ui/button';
1011
import useUserStore from '@/stores/useUser.store';
11-
import { createPlaceholderDataFnForQueryKey } from '@/utils/createPlaceholderDataFnForQueryKey';
12+
import { createPlaceholderDataFn } from '@/utils/createPlaceholderDataFnForQueryKey';
1213
import { ErrorAlert } from '../ErrorAlert';
1314
import { appsQuery } from './appsQuery';
1415
import { columns } from './appsTable/columns';
1516

1617
export function AppsPreviewTable({ className }: { className?: string }) {
1718
const { chainId } = useUserStore();
1819

19-
const queryKey = [chainId, 'apps_preview'];
20+
// Pertinent ordering: usageCount desc + recent usage constraint (last 14 days)
21+
const recentFrom = Math.floor(Date.now() / 1000) - 14 * 24 * 60 * 60;
22+
const orderBy: App_OrderBy = App_OrderBy.UsageCount;
23+
const orderDirection: OrderDirection = OrderDirection.Desc;
24+
const queryKey = [
25+
chainId,
26+
'apps_preview',
27+
orderBy,
28+
orderDirection,
29+
recentFrom,
30+
];
2031
const apps = useQuery({
2132
queryKey,
2233
queryFn: () =>
2334
execute(appsQuery, chainId, {
2435
length: PREVIEW_TABLE_LENGTH,
2536
skip: 0,
37+
orderBy,
38+
orderDirection,
39+
recentFrom,
2640
}),
2741
refetchInterval: PREVIEW_TABLE_REFETCH_INTERVAL,
2842
enabled: !!chainId,
29-
placeholderData: createPlaceholderDataFnForQueryKey(queryKey),
43+
placeholderData: createPlaceholderDataFn(),
3044
});
3145

3246
const formattedData =
@@ -40,7 +54,7 @@ export function AppsPreviewTable({ className }: { className?: string }) {
4054
<div className="flex items-center justify-between">
4155
<h2 className="flex items-center gap-2 font-sans">
4256
<AppIcon size={20} className="text-foreground" />
43-
Latest apps deployed
57+
Most pertinent apps
4458
{apps.data && apps.isError && (
4559
<span className="text-muted-foreground text-sm font-light">
4660
(outdated)

src/modules/apps/appsQuery.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
import { graphql } from '@/graphql/poco/gql';
22

3+
// @ts-expect-error Updated query signature; regenerate codegen after change.
34
export const appsQuery = graphql(`
45
query Apps(
56
$length: Int = 20
67
$skip: Int = 0
78
$nextSkip: Int = 20
89
$nextNextSkip: Int = 40
10+
$orderBy: App_orderBy = timestamp
11+
$orderDirection: OrderDirection = desc
12+
$recentFrom: BigInt = 0
913
) {
1014
apps(
1115
first: $length
1216
skip: $skip
13-
orderBy: timestamp
14-
orderDirection: desc
17+
where: { lastUsageTimestamp_gte: $recentFrom }
18+
orderBy: $orderBy
19+
orderDirection: $orderDirection
1520
) {
1621
address: id
1722
owner {
@@ -23,6 +28,7 @@ export const appsQuery = graphql(`
2328
multiaddr
2429
checksum
2530
mrenclave
31+
lastUsageTimestamp
2632
transfers(orderBy: timestamp, orderDirection: desc) {
2733
transaction {
2834
txHash: id
@@ -34,16 +40,18 @@ export const appsQuery = graphql(`
3440
appsHasNext: apps(
3541
first: 1
3642
skip: $nextSkip
37-
orderBy: timestamp
38-
orderDirection: desc
43+
orderBy: $orderBy
44+
orderDirection: $orderDirection
45+
where: { lastUsageTimestamp_gte: $recentFrom }
3946
) {
4047
address: id
4148
}
4249
appsHasNextNext: apps(
4350
first: 1
4451
skip: $nextNextSkip
45-
orderBy: timestamp
46-
orderDirection: desc
52+
orderBy: $orderBy
53+
orderDirection: $orderDirection
54+
where: { lastUsageTimestamp_gte: $recentFrom }
4755
) {
4856
address: id
4957
}

src/routes/$chainSlug/_layout/apps.tsx

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,55 @@
11
import { TABLE_LENGTH, TABLE_REFETCH_INTERVAL } from '@/config';
22
import { execute } from '@/graphql/poco/execute';
3+
import { App_OrderBy, OrderDirection } from '@/graphql/poco/graphql';
34
import { useQuery } from '@tanstack/react-query';
45
import { createFileRoute } from '@tanstack/react-router';
5-
import { LoaderCircle } from 'lucide-react';
6+
import { LoaderCircle, SlidersHorizontal } from 'lucide-react';
67
import { DataTable } from '@/components/DataTable';
78
import { PaginatedNavigation } from '@/components/PaginatedNavigation';
89
import AppIcon from '@/components/icons/AppIcon';
910
import { BackButton } from '@/components/ui/BackButton';
11+
import {
12+
Select,
13+
SelectContent,
14+
SelectItem,
15+
SelectTrigger,
16+
} from '@/components/ui/select';
17+
import { useFilterParam } from '@/hooks/useFilterParam';
1018
import { usePageParam } from '@/hooks/usePageParam';
1119
import { ErrorAlert } from '@/modules/ErrorAlert';
1220
import { AppBreadcrumbsList } from '@/modules/apps/AppBreadcrumbs';
1321
import { appsQuery } from '@/modules/apps/appsQuery';
1422
import { columns } from '@/modules/apps/appsTable/columns';
1523
import { SearcherBar } from '@/modules/search/SearcherBar';
1624
import useUserStore from '@/stores/useUser.store';
17-
import { createPlaceholderDataFnForQueryKey } from '@/utils/createPlaceholderDataFnForQueryKey';
25+
import { createPlaceholderDataFn } from '@/utils/createPlaceholderDataFnForQueryKey';
1826
import { getAdditionalPages } from '@/utils/format';
1927

2028
export const Route = createFileRoute('/$chainSlug/_layout/apps')({
2129
component: AppsRoute,
2230
});
2331

24-
function useAppsData(currentPage: number) {
32+
function useAppsData(currentPage: number, orderFilter: string) {
2533
const { chainId } = useUserStore();
2634
const skip = currentPage * TABLE_LENGTH;
2735
const nextSkip = skip + TABLE_LENGTH;
2836
const nextNextSkip = skip + 2 * TABLE_LENGTH;
2937

30-
const queryKey = [chainId, 'apps', currentPage];
38+
const orderBy = orderFilter === 'pertinent' ? 'usageCount' : 'timestamp';
39+
const orderDirection = orderFilter === 'oldest' ? 'asc' : 'desc';
40+
const recentFrom =
41+
orderFilter === 'pertinent'
42+
? Math.floor(Date.now() / 1000) - 14 * 24 * 60 * 60
43+
: 0;
44+
45+
const queryKey = [
46+
chainId,
47+
'apps',
48+
currentPage,
49+
orderBy,
50+
orderDirection,
51+
recentFrom,
52+
];
3153
const { data, isLoading, isRefetching, isError, errorUpdateCount } = useQuery(
3254
{
3355
queryKey,
@@ -37,10 +59,13 @@ function useAppsData(currentPage: number) {
3759
skip,
3860
nextSkip,
3961
nextNextSkip,
62+
orderBy: orderBy as App_OrderBy,
63+
orderDirection: orderDirection as OrderDirection,
64+
recentFrom: recentFrom,
4065
}),
4166
refetchInterval: TABLE_REFETCH_INTERVAL,
4267
enabled: !!chainId,
43-
placeholderData: createPlaceholderDataFnForQueryKey(queryKey),
68+
placeholderData: createPlaceholderDataFn(),
4469
}
4570
);
4671

@@ -68,20 +93,55 @@ function useAppsData(currentPage: number) {
6893
}
6994

7095
function AppsRoute() {
96+
const orders = [
97+
{ id: 1, value: 'recent', name: 'Recently deployed' },
98+
{ id: 2, value: 'oldest', name: 'Oldest deployed' },
99+
{ id: 3, value: 'pertinent', name: 'Most pertinent' },
100+
];
101+
const allowedOrderValues = orders.map((o) => o.value);
71102
const [currentPage, setCurrentPage] = usePageParam('appsPage');
103+
const [orderBy, setOrderBy] = useFilterParam(
104+
'appsOrderBy',
105+
allowedOrderValues,
106+
'pertinent'
107+
);
72108
const {
73109
data,
74110
isLoading,
75111
isRefetching,
76112
isError,
77113
hasPastError,
78114
additionalPages,
79-
} = useAppsData(currentPage - 1);
115+
} = useAppsData(currentPage - 1, orderBy);
116+
117+
function handleOrderChange(value: string) {
118+
setOrderBy(value);
119+
setCurrentPage(1);
120+
}
80121

81122
return (
82123
<div className="mt-8 grid gap-6">
83124
<div className="mt-6 flex flex-col justify-between lg:flex-row">
84-
<SearcherBar className="py-6 lg:order-last lg:mr-0 lg:max-w-md lg:py-0 xl:max-w-xl" />
125+
<div className="flex flex-col items-stretch gap-4 py-6 sm:flex-row lg:order-last lg:mr-0 lg:py-0">
126+
<SearcherBar className="lg:max-w-md xl:max-w-xl" />
127+
<Select
128+
value={orderBy?.toString()}
129+
onValueChange={handleOrderChange}
130+
defaultValue="pertinent"
131+
>
132+
<SelectTrigger className="m-auto box-content h-9! rounded-2xl">
133+
<SlidersHorizontal />
134+
Order by
135+
</SelectTrigger>
136+
<SelectContent>
137+
{orders.map((order) => (
138+
<SelectItem key={order.id} value={order.value}>
139+
{order.name}
140+
</SelectItem>
141+
))}
142+
</SelectContent>
143+
</Select>
144+
</div>
85145
<div className="space-y-2">
86146
<h1 className="flex items-center gap-2 font-sans text-2xl font-extrabold">
87147
<AppIcon size={24} />
@@ -116,6 +176,7 @@ function AppsRoute() {
116176
currentPage={currentPage}
117177
totalPages={currentPage + additionalPages}
118178
onPageChange={setCurrentPage}
179+
filterKey={orderBy}
119180
/>
120181
</div>
121182
);

0 commit comments

Comments
 (0)