|
1 | 1 | import ErrorComponent from '@/app/server-components/shared/ErrorComponent'; |
2 | | -import { getAllLicenseTokenIds } from '@/lib/api/blockchain'; |
3 | | -import { LicenseItem } from '@/typedefs/general'; |
| 2 | +import { PAGE_SIZE } from '@/config'; |
| 3 | +import { getLicensesPage } from '@/lib/api/blockchain'; |
| 4 | +import { LicenseListItem } from '@/typedefs/general'; |
4 | 5 | import { unstable_cache } from 'next/cache'; |
5 | 6 | import List from '../server-components/Licenses/List'; |
6 | 7 | import { BorderedCard } from '../server-components/shared/cards/BorderedCard'; |
7 | 8 | import { CardHorizontal } from '../server-components/shared/cards/CardHorizontal'; |
8 | | - |
9 | | -export async function generateMetadata({ searchParams }: { searchParams?: Promise<{ page?: string }> }) { |
10 | | - const resolvedSearchParams = await searchParams; |
11 | | - const pageParam = Number.parseInt(resolvedSearchParams?.page ?? '', 10); |
12 | | - const canonical = Number.isFinite(pageParam) && pageParam > 1 ? `/licenses?page=${pageParam}` : '/licenses'; |
13 | | - |
14 | | - return { |
15 | | - title: 'Licenses', |
16 | | - openGraph: { |
17 | | - title: 'Licenses', |
18 | | - }, |
19 | | - alternates: { |
20 | | - canonical, |
21 | | - }, |
22 | | - }; |
23 | | -} |
24 | | - |
25 | | -const getCachedLicenseTokenIds = unstable_cache(getAllLicenseTokenIds, ['licenses-token-ids'], { revalidate: 300 }); |
26 | | - |
27 | | -export default async function LicensesPage(props: { |
28 | | - searchParams?: Promise<{ |
29 | | - page?: string; |
30 | | - }>; |
31 | | -}) { |
32 | | - const searchParams = await props.searchParams; |
33 | | - const currentPage = Number(searchParams?.page) || 1; |
34 | | - |
35 | | - let ndTotalSupply: number, mndTotalSupply: number; |
36 | | - let licenses: LicenseItem[]; |
| 9 | + |
| 10 | +export async function generateMetadata({ searchParams }: { searchParams?: Promise<{ page?: string }> }) { |
| 11 | + const resolvedSearchParams = await searchParams; |
| 12 | + const pageParam = Number.parseInt(resolvedSearchParams?.page ?? '', 10); |
| 13 | + const canonical = Number.isFinite(pageParam) && pageParam > 1 ? `/licenses?page=${pageParam}` : '/licenses'; |
| 14 | + |
| 15 | + return { |
| 16 | + title: 'Licenses', |
| 17 | + openGraph: { |
| 18 | + title: 'Licenses', |
| 19 | + }, |
| 20 | + alternates: { |
| 21 | + canonical, |
| 22 | + }, |
| 23 | + }; |
| 24 | +} |
| 25 | + |
| 26 | +const getCachedLicensesPage = unstable_cache( |
| 27 | + async (currentPage: number) => { |
| 28 | + const page = currentPage > 0 ? currentPage : 1; |
| 29 | + const offset = (page - 1) * PAGE_SIZE; |
| 30 | + const data = await getLicensesPage(offset, PAGE_SIZE); |
| 31 | + |
| 32 | + return { |
| 33 | + ...data, |
| 34 | + ndTotalSupply: data.ndTotalSupply.toString(), |
| 35 | + mndTotalSupply: data.mndTotalSupply.toString(), |
| 36 | + }; |
| 37 | + }, |
| 38 | + ['licenses-page'], |
| 39 | + { revalidate: 300 }, |
| 40 | +); |
| 41 | + |
| 42 | +export default async function LicensesPage(props: { |
| 43 | + searchParams?: Promise<{ |
| 44 | + page?: string; |
| 45 | + }>; |
| 46 | +}) { |
| 47 | + const searchParams = await props.searchParams; |
| 48 | + const currentPage = Number(searchParams?.page) || 1; |
| 49 | + |
| 50 | + let ndTotalSupply: bigint, mndTotalSupply: bigint; |
| 51 | + let licensesCount: number; |
| 52 | + let licenses: LicenseListItem[]; |
37 | 53 |
|
38 | 54 | try { |
39 | | - const { ndLicenseIds, mndLicenseIds } = await getCachedLicenseTokenIds(); |
40 | | - ndTotalSupply = ndLicenseIds.length; |
41 | | - mndTotalSupply = mndLicenseIds.length; |
| 55 | + const { |
| 56 | + ndTotalSupply: ndSupply, |
| 57 | + mndTotalSupply: mndSupply, |
| 58 | + licenses: pageLicenses, |
| 59 | + } = await getCachedLicensesPage(currentPage); |
| 60 | + |
| 61 | + ndTotalSupply = BigInt(ndSupply); |
| 62 | + mndTotalSupply = BigInt(mndSupply); |
| 63 | + licenses = pageLicenses; |
| 64 | + licensesCount = Number(ndTotalSupply + mndTotalSupply); |
| 65 | + } catch (error) { |
| 66 | + console.error(error); |
| 67 | + console.log('[Licenses Page] Failed to fetch license data'); |
| 68 | + return <NotFound />; |
| 69 | + } |
| 70 | + |
| 71 | + return ( |
| 72 | + <> |
| 73 | + <div className="w-full"> |
| 74 | + <BorderedCard> |
| 75 | + <div className="card-title-big font-bold">Licenses</div> |
| 76 | + |
| 77 | + <div className="flexible-row"> |
| 78 | + <CardHorizontal |
| 79 | + label="Total" |
| 80 | + value={licensesCount.toString()} |
| 81 | + isFlexible |
| 82 | + widthClasses="min-w-[192px]" |
| 83 | + /> |
| 84 | + <CardHorizontal label="ND" value={ndTotalSupply.toString()} isFlexible widthClasses="min-w-[192px]" /> |
| 85 | + <CardHorizontal label="MND" value={mndTotalSupply.toString()} isFlexible widthClasses="min-w-[192px]" /> |
| 86 | + </div> |
| 87 | + </BorderedCard> |
| 88 | + </div> |
| 89 | + |
| 90 | + <List licenses={licenses} currentPage={currentPage} totalLicenses={licensesCount} /> |
| 91 | + </> |
| 92 | + ); |
| 93 | +} |
42 | 94 |
|
43 | | - licenses = [ |
44 | | - ...mndLicenseIds.map((licenseId) => ({ |
45 | | - licenseId, |
46 | | - licenseType: licenseId === 1 ? ('GND' as const) : ('MND' as const), |
47 | | - })), |
48 | | - ...ndLicenseIds.map((licenseId) => ({ |
49 | | - licenseId, |
50 | | - licenseType: 'ND' as const, |
51 | | - })), |
52 | | - ]; |
53 | | - } catch (error) { |
54 | | - console.error(error); |
55 | | - console.log('[Licenses Page] Failed to fetch license data'); |
56 | | - return <NotFound />; |
57 | | - } |
58 | | - |
59 | | - return ( |
60 | | - <> |
61 | | - <div className="w-full"> |
62 | | - <BorderedCard> |
63 | | - <div className="card-title-big font-bold">Licenses</div> |
64 | | - |
65 | | - <div className="flexible-row"> |
66 | | - <CardHorizontal |
67 | | - label="Total" |
68 | | - value={ndTotalSupply + mndTotalSupply} |
69 | | - isFlexible |
70 | | - widthClasses="min-w-[192px]" |
71 | | - /> |
72 | | - <CardHorizontal label="ND" value={ndTotalSupply} isFlexible widthClasses="min-w-[192px]" /> |
73 | | - <CardHorizontal label="MND" value={mndTotalSupply} isFlexible widthClasses="min-w-[192px]" /> |
74 | | - </div> |
75 | | - </BorderedCard> |
76 | | - </div> |
77 | | - |
78 | | - <List licenses={licenses} currentPage={currentPage} /> |
79 | | - </> |
80 | | - ); |
81 | | -} |
82 | | - |
83 | | -function NotFound() { |
84 | | - return <ErrorComponent title="Error" description="The licenses data could not be loaded. Please try again later." />; |
85 | | -} |
| 95 | +function NotFound() { |
| 96 | + return <ErrorComponent title="Error" description="The licenses data could not be loaded. Please try again later." />; |
| 97 | +} |
0 commit comments