Skip to content

Commit

Permalink
Migrate PaginatedList to useQuery
Browse files Browse the repository at this point in the history
  • Loading branch information
rajku-dev committed Feb 1, 2025
1 parent 66104a8 commit 52a3fae
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 36 deletions.
81 changes: 47 additions & 34 deletions src/CAREUI/misc/PaginatedList.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { UseQueryResult, useQuery } from "@tanstack/react-query";
import { createContext, useContext, useEffect, useState } from "react";

import CareIcon from "@/CAREUI/icons/CareIcon";
Expand All @@ -6,21 +7,22 @@ import { Button, ButtonProps } from "@/components/ui/button";

import Pagination from "@/components/Common/Pagination";

import { ApiRoute, PaginatedResponse } from "@/Utils/request/types";
import useTanStackQueryInstead, {
QueryOptions,
} from "@/Utils/request/useQuery";
import apiQuery from "@/Utils/request/query";
import {
ApiRoute,
PaginatedResponse,
QueryParams,
} from "@/Utils/request/types";
import { classNames } from "@/Utils/utils";

const DEFAULT_PER_PAGE_LIMIT = 14;

interface PaginatedListContext<TItem>
extends ReturnType<typeof useTanStackQueryInstead<PaginatedResponse<TItem>>> {
type PaginatedListContext<TItem> = UseQueryResult<PaginatedResponse<TItem>> & {
items: TItem[];
perPage: number;
currentPage: number;
setPage: (page: number) => void;
}
};

const context = createContext<PaginatedListContext<object> | null>(null);

Expand All @@ -34,41 +36,52 @@ function useContextualized<TItem>() {
return ctx as PaginatedListContext<TItem>;
}

interface Props<TItem> extends QueryOptions<PaginatedResponse<TItem>> {
interface Props<TItem> {
route: ApiRoute<PaginatedResponse<TItem>>;
perPage?: number;
initialPage?: number;
onPageChange?: (page: number) => void;
queryCB?: (
query: ReturnType<typeof useTanStackQueryInstead<PaginatedResponse<TItem>>>,
) => void;
queryCB?: (query: UseQueryResult<PaginatedResponse<TItem>>) => void;
pathParams?: Record<string, string>;
queryParams?: QueryParams;
silent?: boolean | ((response: Response) => boolean);
signal?: AbortSignal;
headers?: HeadersInit;
children: (
ctx: PaginatedListContext<TItem>,
query: ReturnType<typeof useTanStackQueryInstead<PaginatedResponse<TItem>>>,
query: UseQueryResult<PaginatedResponse<TItem>>,
) => JSX.Element | JSX.Element[];
}

export default function PaginatedList<TItem extends object>({
children,
route,
perPage = DEFAULT_PER_PAGE_LIMIT,
onPageChange,
initialPage,
pathParams,
queryParams,
queryCB,
...queryOptions
...apiCallOptions
}: Props<TItem>) {
const [currentPage, _setPage] = useState(queryOptions.initialPage ?? 1);
const [currentPage, _setPage] = useState(initialPage ?? 1);

const setPage = (page: number) => {
_setPage(page);
queryOptions.onPageChange?.(page);
onPageChange?.(page);
};

const query = useTanStackQueryInstead(route, {
...queryOptions,
query: {
...queryOptions.query,
limit: perPage,
offset: (currentPage - 1) * perPage,
},
const query = useQuery({
queryKey: [route.path, currentPage, perPage, queryParams],
queryFn: apiQuery(route, {
queryParams: {
limit: perPage,
offset: (currentPage - 1) * perPage,
...queryParams,
},
pathParams,
...apiCallOptions,
}),
});

const items = query.data?.results ?? [];
Expand Down Expand Up @@ -96,9 +109,9 @@ interface WhenEmptyProps {
}

const WhenEmpty = <TItem extends object>(props: WhenEmptyProps) => {
const { items, loading } = useContextualized<TItem>();
const { items, isLoading } = useContextualized<TItem>();

if (loading || items.length > 0) {
if (isLoading || items.length > 0) {
return null;
}

Expand All @@ -108,9 +121,9 @@ const WhenEmpty = <TItem extends object>(props: WhenEmptyProps) => {
PaginatedList.WhenEmpty = WhenEmpty;

const WhenLoading = <TItem extends object>(props: WhenEmptyProps) => {
const { loading } = useContextualized<TItem>();
const { isLoading } = useContextualized<TItem>();

if (!loading) {
if (!isLoading) {
return null;
}

Expand All @@ -124,18 +137,18 @@ interface CommonButtonProps extends ButtonProps {
}

const Refresh = ({ label = "Refresh", ...props }: CommonButtonProps) => {
const { loading, refetch } = useContextualized<object>();
const { isLoading, refetch } = useContextualized<object>();

return (
<Button
variant="secondary"
{...props}
onClick={() => refetch()}
disabled={loading}
disabled={isLoading}
>
<CareIcon
icon="l-sync"
className={classNames("text-lg", loading && "animate-spin")}
className={classNames("text-lg", isLoading && "animate-spin")}
/>
<span>{label}</span>
</Button>
Expand All @@ -152,15 +165,15 @@ interface ItemsProps<TItem> {
}

const Items = <TItem extends object>(props: ItemsProps<TItem>) => {
const { loading, items } = useContextualized<TItem>();
const { isLoading, items } = useContextualized<TItem>();

if (loading || items.length === 0) {
if (isLoading || items.length === 0) {
return null;
}

return (
<ul className={props.className}>
{loading && props.shimmer
{isLoading && props.shimmer
? Array.from({ length: props.shimmerCount ?? 8 }).map((_, i) => (
<li key={i} className="w-full">
{props.shimmer}
Expand All @@ -187,9 +200,9 @@ const Paginator = <TItem extends object>({
hideIfSinglePage,
}: PaginatorProps) => {
const { data, perPage, currentPage, setPage } = useContextualized<object>();
const { loading } = useContextualized<TItem>();
const { isLoading } = useContextualized<TItem>();

if (loading) {
if (isLoading) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ export default function QuestionnaireResponsesList({
pathParams={{
patientId: patientId,
}}
query={{
queryParams={{
...(encounter && { encounter: encounter.id }),
}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const EncounterHistory = (props: PatientProps) => {
return (
<PaginatedList
route={routes.encounter.list}
query={{ patient: patientId }}
queryParams={{ patient: patientId }}
perPage={5}
>
{() => (
Expand Down

0 comments on commit 52a3fae

Please sign in to comment.