Skip to content

Commit

Permalink
use query manager
Browse files Browse the repository at this point in the history
  • Loading branch information
SKairinos committed Aug 8, 2024
1 parent f90ad0f commit 999993a
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 23 deletions.
14 changes: 14 additions & 0 deletions src/components/SyncError.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { SyncProblem as SyncProblemIcon } from "@mui/icons-material"
import { Stack, Typography } from "@mui/material"
import { type FC } from "react"

export interface SyncErrorProps {}

const SyncError: FC<SyncErrorProps> = () => (
<Stack alignItems="center" alignContent="center">
<SyncProblemIcon color="error" />
<Typography color="error.main">Failed to sync data</Typography>
</Stack>
)

export default SyncError
8 changes: 2 additions & 6 deletions src/components/TablePagination.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { SyncProblem as SyncProblemIcon } from "@mui/icons-material"
import {
CircularProgress,
TablePagination as MuiTablePagination,
type TablePaginationProps as MuiTablePaginationProps,
Stack,
type StackProps,
type TablePaginationBaseProps,
Typography,
} from "@mui/material"
import type { TypedUseLazyQuery } from "@reduxjs/toolkit/query/react"
import {
Expand All @@ -18,6 +16,7 @@ import {

import { type Pagination, usePagination } from "../hooks/api"
import type { ListArg, ListResult } from "../utils/api"
import SyncError from "./SyncError"

export type TablePaginationProps<
QueryArg extends ListArg,
Expand Down Expand Up @@ -95,10 +94,7 @@ const TablePagination = <
{isLoading ? (
<CircularProgress />
) : error || !data ? (
<>
<SyncProblemIcon color="error" />
<Typography color="error.main">Failed to load data</Typography>
</>
<SyncError />
) : (
children(data, { limit, page, offset, count, maxLimit: max_limit })
)}
Expand Down
19 changes: 3 additions & 16 deletions src/components/form/ApiAutocompleteField.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import { SyncProblem as SyncProblemIcon } from "@mui/icons-material"
import {
Button,
CircularProgress,
Stack,
Typography,
type ChipTypeMap,
} from "@mui/material"
import { Button, CircularProgress, type ChipTypeMap } from "@mui/material"
import type { TypedUseLazyQuery } from "@reduxjs/toolkit/query/react"
import {
Children,
Expand All @@ -21,6 +14,7 @@ import {
} from "../../components/form"
import { usePagination } from "../../hooks/api"
import type { ListArg, ListResult, TagId } from "../../utils/api"
import SyncError from "../SyncError"

export interface ApiAutocompleteFieldProps<
SearchKey extends keyof Omit<QueryArg, "limit" | "offset">,
Expand Down Expand Up @@ -135,14 +129,7 @@ const ApiAutocompleteField = <
const listItems = Children.toArray(children)
if (isLoading) listItems.push(<CircularProgress key="is-loading" />)
else {
if (isError) {
listItems.push(
<Stack direction="row" key="is-error">
<SyncProblemIcon color="error" />
<Typography color="error.main">Failed to load data</Typography>
</Stack>,
)
}
if (isError) listItems.push(<SyncError key="is-error" />)
if (hasMore) {
listItems.push(
<Button key="load-more" onClick={loadNextPage}>
Expand Down
3 changes: 3 additions & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Image, { type ImageProps } from "./Image"
import ItemizedList, { type ItemizedListProps } from "./ItemizedList"
import OrderedGrid, { type OrderedGridProps } from "./OrderedGrid"
import ScrollRoutes, { type ScrollRoutesProps } from "./ScrollRoutes"
import SyncError, { type SyncErrorProps } from "./SyncError"
import TablePagination, { type TablePaginationProps } from "./TablePagination"
import YouTubeVideo, { type YouTubeVideoProps } from "./YouTubeVideo"

Expand All @@ -22,6 +23,7 @@ export {
ItemizedList,
OrderedGrid,
ScrollRoutes,
SyncError,
TablePagination,
YouTubeVideo,
type AppProps,
Expand All @@ -33,6 +35,7 @@ export {
type ItemizedListProps,
type OrderedGridProps,
type ScrollRoutesProps,
type SyncErrorProps,
type TablePaginationProps,
type YouTubeVideoProps,
}
46 changes: 45 additions & 1 deletion src/utils/api.ts → src/utils/api.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import type { FetchBaseQueryError } from "@reduxjs/toolkit/query/react"
import { CircularProgress } from "@mui/material"
import type {
FetchBaseQueryError,
TypedUseQuery,
} from "@reduxjs/toolkit/query/react"
import type { ReactNode } from "react"

import { SyncError } from "../components"
import type { Optional, Required } from "./general"

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -240,3 +247,40 @@ export function tagData<Type extends string, M extends Model<any>>(
return []
}
}

export type UseQueryManagerOptions = Partial<{
loading: ReactNode
error: ReactNode
}>

export function useQueryManager<QueryArg, ResultType>(
useQuery: TypedUseQuery<ResultType, QueryArg, any>,
arg: QueryArg,
children: (data: ResultType) => ReactNode,
options?: UseQueryManagerOptions,
): ReactNode {
const { data, isLoading, isSuccess, error } = useQuery(arg)

const {
loading: loadingNode = <CircularProgress />,
error: errorNode = <SyncError />,
} = options || {}

// An error occurred.
if (error) {
console.error(error)
return errorNode
}

// Busy calling the API.
if (isLoading) return loadingNode

// Called the API and got data.
if (data) return children(data)

// Called the API and did not get data.
if (isSuccess) throw Error("Expected to get data from API but got nothing.")

// Have yet to call the API.
return loadingNode
}

0 comments on commit 999993a

Please sign in to comment.