create reusable query render wrapper that handles loading and error states

This commit is contained in:
Brandon Egger 2023-08-29 08:14:07 -05:00
parent 9074f79dee
commit 1566be88f6
2 changed files with 44 additions and 22 deletions

View File

@ -0,0 +1,34 @@
import { type UseTRPCQueryResult } from "@trpc/react-query/shared";
import { LoadingBarChart } from "./LoadingBarChart";
import { ErrorNotice } from "./notice";
/**
* Generic query wrapper which handles the states of a query
* (loading, error, etc.). Will hydrate child with query.data
*
*/
export function QueryWaitWrapper<TData, TError>({
query,
Render,
}: {
query: UseTRPCQueryResult<TData, TError>;
Render: (data: TData) => JSX.Element;
}) {
if (query.isLoading) {
return <LoadingBarChart width={200} height={200} />;
}
if (!query.data || query.isError) {
return (
<div className="my-10 sm:my-16 md:my-28">
<ErrorNotice
icon
header="Unable to retrieve page data. Please try again."
body="If this issue persists, please contact a site administrator"
/>
</div>
);
}
return <Render {...query.data} />;
}

View File

@ -5,9 +5,9 @@ import { useRouter } from "next/router";
import ResourceTable from "~/components/ResourceTable"; import ResourceTable from "~/components/ResourceTable";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { parseQueryData } from "~/utils/parseSearchForm"; import { parseQueryData } from "~/utils/parseSearchForm";
import { LoadingBarChart } from "~/components/LoadingBarChart";
import { ErrorNotice } from "~/components/notice";
import { HeaderFooterLayout } from "~/layouts/HeaderFooterLayout"; import { HeaderFooterLayout } from "~/layouts/HeaderFooterLayout";
import { type AuditoryResource } from "@prisma/client";
import { QueryWaitWrapper } from "~/components/LoadingWrapper";
const Resources = () => { const Resources = () => {
const router = useRouter(); const router = useRouter();
@ -30,29 +30,16 @@ const Resources = () => {
: ""; : "";
const printLink = `${router.route}/print?${printQueryStr}`; const printLink = `${router.route}/print?${printQueryStr}`;
const ConditionalTable = () => { const ConditionalTable = (data: {
if (resourceQuery.isLoading) { count: number;
return <LoadingBarChart width={200} height={200} />; resources: AuditoryResource[];
} }) => {
const totalPages = Math.ceil(data.count / queryData.perPage);
if (!resourceQuery.data || resourceQuery.isError) {
return (
<div className="my-10 sm:my-16 md:my-28">
<ErrorNotice
icon
header="Unable to pull available resources. Please try again."
body="If this issue persists, please contact a site administrator"
/>
</div>
);
}
const totalPages = Math.ceil(resourceQuery.data.count / queryData.perPage);
return ( return (
<ResourceTable <ResourceTable
resourcesPerPage={queryData.perPage} resourcesPerPage={queryData.perPage}
resources={resourceQuery.data.resources} resources={data.resources}
totalPages={totalPages} totalPages={totalPages}
query={router.query} query={router.query}
currentPage={currentPage} currentPage={currentPage}
@ -92,7 +79,8 @@ const Resources = () => {
</Link> </Link>
</section> </section>
</div> </div>
<ConditionalTable />
<QueryWaitWrapper query={resourceQuery} Render={ConditionalTable} />
</div> </div>
</HeaderFooterLayout> </HeaderFooterLayout>
); );