Skip to content

Commit

Permalink
banking applications pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
ap-justin committed Nov 10, 2024
1 parent 1e38c1f commit 58dca6e
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 58 deletions.
90 changes: 47 additions & 43 deletions src/pages/BankingApplications/BankingApplications.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
import QueryLoader from "components/QueryLoader";
import Seo from "components/Seo";
import withAuth from "contexts/Auth";
import { Info } from "components/Status";
import { useEffect, useState } from "react";
import { useFetcher, useLoaderData, useSearchParams } from "react-router-dom";
import type { BankingApplicationsPage } from "types/aws";
import Filter from "./Filter";
import Table from "./Table";
import usePagination from "./usePagination";

function BankingApplications() {
const {
data,
hasMore,
isError,
isLoading,
isLoadingNextPage,
loadNextPage,
setParams,
isFetching,
} = usePagination();
export function BankingApplications() {
const [params, setParams] = useSearchParams();
const firstPage = useLoaderData() as BankingApplicationsPage;
const { load, data, state } = useFetcher<BankingApplicationsPage>({
key: params.toString(),
});
const [items, setItems] = useState(firstPage.items);

const isLoadingOrError = isLoading || isLoadingNextPage || isError;
useEffect(() => {
if (state === "loading" || !data) return;
setItems((prev) => [...prev, ...data.items]);
}, [data, state]);

const nextPage = data ? data.nextPageKey : firstPage.nextPageKey;

function loadNextPage(key: string) {
const copy = new URLSearchParams(params);
copy.set("nextPageKey", key);
load(`?index&${copy.toString()}`);
}

return (
<div className="grid content-start gap-y-4 lg:gap-y-8 lg:gap-x-3 relative padded-container py-20 lg:pt-10">
Expand All @@ -27,37 +35,33 @@ function BankingApplications() {
</h1>

<Filter
isDisabled={isLoadingOrError || isFetching}
setParams={setParams}
params={params}
isDisabled={state === "loading"}
setParams={(p) => {
const copy = new URLSearchParams();
for (const [key, value] of Object.entries(p)) {
copy.set(key, value.toString());
}
setParams(copy);
}}
classes="justify-self-end"
/>
<QueryLoader
queryState={{
data: data?.items,
isLoading,
isFetching,
isError: isError,
}}
messages={{
loading: "Loading applications...",
error: "Failed to get applications",
empty: "No applications found.",
}}
>
{(applications) => (
<div className="grid col-span-full overflow-x-auto">
<Table
applications={applications}
hasMore={hasMore}
onLoadMore={loadNextPage}
disabled={isLoadingOrError}
isLoading={isLoadingNextPage}
/>
</div>

<div className="grid col-span-full overflow-x-auto">
{items.length > 0 ? (
<Table
applications={items}
nextPageKey={nextPage}
onLoadMore={loadNextPage}
disabled={state === "loading"}
isLoading={state === "loading"}
/>
) : (
<Info classes="pt-4 border-t border-gray-l4">
No applications found
</Info>
)}
</QueryLoader>
</div>
</div>
);
}

export const Component = withAuth(BankingApplications, ["ap-admin"]);
19 changes: 12 additions & 7 deletions src/pages/BankingApplications/Filter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,22 @@ import { FormProvider, useForm } from "react-hook-form";
import { optionType, schema, stringNumber } from "schemas/shape";
import type { BankingApplicationsQueryParams } from "types/aws";
import Form from "./Form";
import { statuses } from "./constants";
import type { FormValues as FV } from "./types";

type Props = {
classes?: string;
setParams: React.Dispatch<
React.SetStateAction<BankingApplicationsQueryParams>
>;
params: URLSearchParams;
setParams: (params: BankingApplicationsQueryParams) => void;
isDisabled: boolean;
};

export default function Filter({ setParams, classes = "", isDisabled }: Props) {
export default function Filter({
setParams,
classes = "",
isDisabled,
params,
}: Props) {
const buttonRef = useRef<HTMLButtonElement | null>(null);

const methods = useForm<FV>({
Expand All @@ -34,8 +39,9 @@ export default function Filter({ setParams, classes = "", isDisabled }: Props) {
})
),
defaultValues: {
endowmentID: "",
status: { label: "Under Review", value: "under-review" },
endowmentID: params.get("endowmentID") || "",
status:
statuses.find((s) => s.value === params.get("status")) || statuses[0],
},
});

Expand All @@ -46,7 +52,6 @@ export default function Filter({ setParams, classes = "", isDisabled }: Props) {
cleanObject({
status: data.status.value,
endowmentID: data.endowmentID ? +data.endowmentID : undefined,
requestor: "bg-admin",
})
);
buttonRef.current?.click();
Expand Down
8 changes: 4 additions & 4 deletions src/pages/BankingApplications/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function Table({
classes = "",
disabled,
isLoading,
hasMore,
nextPageKey,
onLoadMore,
}: TableProps) {
return (
Expand Down Expand Up @@ -44,7 +44,7 @@ export default function Table({
key={row.wiseRecipientID}
type="td"
cellClass={`p-3 border-t border-blue-l2 max-w-[256px] truncate ${
hasMore ? "" : "first:rounded-bl last:rounded-br"
nextPageKey ? "" : "first:rounded-bl last:rounded-br"
}`}
>
<>{new Date(row.dateCreated).toLocaleDateString()}</>
Expand All @@ -66,14 +66,14 @@ export default function Table({
</Cells>
))
.concat(
hasMore ? (
nextPageKey ? (
<td
colSpan={9}
key="load-more-btn"
className="border-t border-blue-l2 rounded-b"
>
<LoadMoreBtn
onLoadMore={onLoadMore}
onLoadMore={() => onLoadMore(nextPageKey)}
disabled={disabled}
isLoading={isLoading}
/>
Expand Down
35 changes: 33 additions & 2 deletions src/pages/BankingApplications/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,33 @@
export { Component } from "./BankingApplications";
export { authLocLoader as loader } from "helpers/state-params";
import { loadAuth, redirectToAuth } from "auth";
import { APIs } from "constants/urls";
import { cacheGet } from "helpers/cache-get";
import type { LoaderFunction } from "react-router-dom";
import { version as v } from "services/helpers";
import type { UserV2 } from "types/auth";

export { BankingApplications as Component } from "./BankingApplications";

export const loader: LoaderFunction = async ({ request }) => {
console.log({ request });
const auth = await loadAuth();
if (auth) return getApplications(new URL(request.url), auth);
return redirectToAuth(request);
};

async function getApplications(source: URL, user: UserV2) {
const url = new URL(APIs.aws);
url.pathname = `${v(1)}/banking-applications`;
url.searchParams.set("requestor", "bg-admin");

const status = source.searchParams.get("status");
const nextPageKey = source.searchParams.get("nextPageKey");
const endowId = source.searchParams.get("endowmentID");

if (status) url.searchParams.set("status", status);
if (nextPageKey) url.searchParams.set("nextPageKey", nextPageKey);
if (endowId) url.searchParams.set("endowmentID", endowId);

const req = new Request(url);
req.headers.set("authorization", user.idToken);
return cacheGet(req).then((res) => res.json());
}
4 changes: 2 additions & 2 deletions src/pages/BankingApplications/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import type { BankingApplication } from "types/aws";
export type TableProps = {
applications: BankingApplication[];
classes?: string;
onLoadMore(): void;
hasMore: boolean;
onLoadMore(key: string): void;
nextPageKey?: string;
disabled: boolean;
isLoading: boolean;
};

0 comments on commit 58dca6e

Please sign in to comment.