Skip to content

Commit

Permalink
feat: improve performance of search page by suspension of search resu…
Browse files Browse the repository at this point in the history
…lts table
  • Loading branch information
RyukTheCoder committed Dec 23, 2024
1 parent 65f30b5 commit 914e71c
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 22 deletions.
4 changes: 0 additions & 4 deletions src/app/search/_components/Result/Result.type.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import { SwapType } from 'src/types';

export interface PropsType {
data: SwapType[];
query: string;
total: number;
page: number;
}
21 changes: 18 additions & 3 deletions src/app/search/_components/Result/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
import { PropsType } from './Result.type';
import Pagination from '../Pagination';
import Table from 'src/components/common/Table';
import { getWalletSwaps } from 'src/services';
import { notFound } from 'next/navigation';

async function Result(props: PropsType) {
const { query, page } = props;

await new Promise((res) =>
setTimeout(() => {
res(5);
}, 5000),
);
const data = await getWalletSwaps(query, page);
const { transactions, total } = data || {};

if (!data || !transactions?.length) {
notFound();
}

function Result(props: PropsType) {
const { data, query, total, page } = props;
return (
<div className="w-[calc(100%-3.125rem)] md:container mt-30 md:mt-[3.125rem] rounded-normal bg-baseForeground px-15 py-20 md:p-35 overflow-hidden">
<div className="flex flex-col">
Expand All @@ -16,7 +31,7 @@ function Result(props: PropsType) {
</p>
</div>
<div className="md:mt-25">
<Table data={data} />
<Table data={transactions} />
</div>
<div className="mt-15 md:mt-25">
<Pagination page={page} total={total} query={query} />
Expand Down
20 changes: 6 additions & 14 deletions src/app/search/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { MATCH_TYPE } from 'src/constant';
import { notFound, redirect } from 'next/navigation';
import { getSearchResult, getWalletSwaps } from 'src/services';
import { getSearchResult } from 'src/services';
import Result from './_components/Result';
import TableLoading from 'src/components/common/Table/TableLoading';
import { Suspense } from 'react';

export async function generateMetadata({
searchParams,
Expand Down Expand Up @@ -38,21 +40,11 @@ const Page = async ({
if (requestId) redirect(`/swap/${requestId}`);
}

const data = await getWalletSwaps(query, page);
const { transactions, total } = data || {};

if (!data || !transactions?.length) {
notFound();
}

return (
<div className="w-full flex justify-center">
<Result
total={total}
page={Number(page || 0)}
data={transactions}
query={query as string}
/>
<Suspense fallback={<TableLoading />}>
<Result page={Number(page || 0)} query={query as string} />
</Suspense>
</div>
);
};
Expand Down
6 changes: 6 additions & 0 deletions src/components/common/Skeleton/Skeleton.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type PropTypes = {
width?: number;
height?: number;
variant?: 'circular' | 'rectangular';
className?: string;
};
18 changes: 18 additions & 0 deletions src/components/common/Skeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { PropTypes } from './Skeleton.types';

export function Skeleton(props: PropTypes) {
const { height, width, variant = 'rectangular', className = '' } = props;
return (
<div
style={{
background:
'linear-gradient(90deg, #C8E2FF 0%, rgba(200, 226, 255, 0.20) 70%, #C8E2FF 100%)',
backgroundSize: '800px 100px',
...(width && { width: `${width}px` }),
...(height && { height: `${height}px` }),
}}
className={`animate-wave ${
variant === 'rectangular' ? 'rounded-soft' : 'rounded-full'
} ${className} `}></div>
);
}
135 changes: 135 additions & 0 deletions src/components/common/Table/TableLoading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { useId } from 'react';
import TableHead from './TableHead';
import { Skeleton } from '../Skeleton';
import Link from 'next/link';

function TableLoading() {
const id = useId();
return (
<div className="w-[calc(100%-3.125rem)] md:container mt-30 md:mt-[3.125rem] rounded-normal bg-baseForeground px-15 py-20 md:p-35 overflow-hidden">
<div className="flex flex-col">
<div className="flex flex-col justify-center">
<h2 className="text-14 md:text-28 font-semibold text-primary-500">
Search Results
</h2>
<div className="text-12 md:text-16 text-neutral-800">
<Skeleton width={300} height={10} />
</div>
</div>
<div className="md:mt-25">
<div className="w-full">
<TableHead />
<div className="w-full">
{Array.from({ length: 14 }, () => {
return (
<div
key={id}
className={`flex flex-col p-15 mt-15 md:mt-0 md:p-0 rounded-micro md:-rounded-none md:grid bg-surfacesBackground md:bg-transparent md:hover:bg-hoverBackground md:border-b md:border-neutral-300 md:even:bg-surfacesBackground md:grid-cols-11 w-full`}>
<div
className={`flex flex-col md:py-[27px] md:px-15 lg:px-20 col-span-3`}>
<div className="text-12 md:hidden text-primary-500">
Request ID
</div>
<Skeleton
className="mt-5 md:mt-0 w-[220px] md:w-[178px]"
height={15}
/>
<Skeleton className="mt-5" width={169} height={10} />
</div>
<div className="flex items-center mt-15 md:mt-0 md:py-[27px] md:px-15 lg:px-20 col-span-2">
<div className="relative">
<Skeleton
className="w-[27px] md:w-[30px] h-[27px] md:h-[30px]"
variant="circular"
/>
<Skeleton
className="absolute w-[12px] md:w-[15px] h-[12px] md:h-[15px] right-[-2px] bottom-[-2px] md:right-[-3px] md:bottom-[-3px]"
variant="circular"
/>
</div>
<div className="flex flex-col ml-5 justify-center">
<Skeleton width={92} height={15} />
<Skeleton
className="mt-[2px] md:mt-5"
width={60}
height={10}
/>
</div>
</div>
<div className="md:hidden ml-[0.875rem] h-[15px] border-l border-neutral-400"></div>
<div className="flex items-center md:py-[27px] md:px-15 lg:px-20 col-span-2">
<div className="relative">
<Skeleton
className="w-[27px] md:w-[30px] h-[27px] md:h-[30px]"
variant="circular"
/>
<Skeleton
className="absolute w-[12px] md:w-[15px] h-[12px] md:h-[15px] right-[-2px] bottom-[-2px] md:right-[-3px] md:bottom-[-3px]"
variant="circular"
/>
</div>
<div className="flex flex-col ml-5 justify-center">
<Skeleton width={92} height={15} />
<Skeleton
className="mt-[2px] md:mt-5"
width={60}
height={10}
/>
</div>
</div>
<div
className={`flex flex-col md:py-[27px] mt-15 md:mt-0 md:px-15 lg:px-20 col-span-2`}>
<div className="text-12 md:hidden text-primary-500">
Amount
</div>
<Skeleton
className="mt-5 md:mt-0 w-[114px] md:w-[145px]"
height={15}
/>
<Skeleton
className="mt-5 w-[86px] md:w-[108px]"
height={10}
/>
</div>
<div
className={`flex flex-col mt-25 md:mt-0 md:py-[27px] md:px-15 lg:px-20 col-span-2`}>
<div className="text-12 md:hidden text-primary-500">
Status
</div>
<Skeleton
className="mt-5 md:mt-0 w-[114px] md:w-[108px]"
height={15}
/>
<Skeleton
className="mt-5 w-[86px] md:w-[70px]"
height={10}
/>
</div>
<Link
href="#"
className={`w-full md:hidden text-center rounded-micro mt-30 border border-primary-600 py-10 text-primary-600 text-16 font-semibold`}>
Detail
</Link>
</div>
);
})}
</div>
</div>
</div>
<div className="mt-15 md:mt-25">
<div className="flex items-center justify-center">
<Skeleton className="rounded-micro w-[2.25rem] md:w-[2.5rem] h-[2.25rem] md:h-[2.5rem]" />
<Skeleton className="mx-5 md:mx-10 rounded-micro w-[2.25rem] md:w-[2.5rem] h-[2.25rem] md:h-[2.5rem]" />

<Skeleton className="w-[5.375rem] h-[2.25rem] md:w-[7.125rem] md:h-[2.5rem] rounded-micro" />

<Skeleton className="mx-5 md:mx-10 rounded-micro w-[2.25rem] md:w-[2.5rem] h-[2.25rem] md:h-[2.5rem]" />
<Skeleton className="rounded-micro w-[2.25rem] md:w-[2.5rem] h-[2.25rem] md:h-[2.5rem]" />
</div>
</div>
</div>
</div>
);
}

export default TableLoading;
2 changes: 1 addition & 1 deletion src/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const getSearchResult = async (query: string) =>
.then(async (res) => await res.json())
.then((data) => data?.searchResult || data);

export const getWalletSwaps = async (address: string, page?: string) =>
export const getWalletSwaps = async (address: string, page?: number) =>
await fetch(
`${API_URL}/scanner/tx/wallet?walletAddress=${address}&offset=${SEARCH_RESULT_OFFSET}&page=${
page || 0
Expand Down

0 comments on commit 914e71c

Please sign in to comment.