Files
probo/apps/console/src/components/SortableTable.tsx
Jonathan eaf54f9836 Fix types
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-06-17 13:24:18 -07:00

109 lines
2.4 KiB
TypeScript

import { useTranslate } from "@probo/i18n";
import {
Button,
IconChevronDown,
IconChevronTriangleDownSmall,
Spinner,
Table,
Th,
} from "@probo/ui";
import clsx from "clsx";
import {
createContext,
startTransition,
useContext,
useState,
type ComponentProps,
} from "react";
type Order = {
direction: string;
field: string;
};
const SortableContext = createContext({
order: {
direction: "DESC",
field: "CREATED_AT",
},
onOrderChange: (() => {}) as (order: Order) => void,
});
const defaultOrder = {
direction: "DESC",
field: "CREATED_AT",
} as Order;
export function SortableTable({
refetch,
hasNext,
loadNext,
isLoadingNext,
...props
}: ComponentProps<typeof Table> & {
refetch: (o: { order: Order }) => void;
hasNext?: boolean;
loadNext?: (...args: any[]) => void;
isLoadingNext?: boolean;
}) {
const { __ } = useTranslate();
const [order, setOrder] = useState(defaultOrder);
const onOrderChange = (o: Order) => {
startTransition(() => {
setOrder(o);
refetch({ order: o });
});
};
return (
<SortableContext value={{ order, onOrderChange }}>
<div className="space-y-4">
<Table {...props} />
{hasNext && loadNext && (
<Button
variant="tertiary"
onClick={() => loadNext()}
className="mt-3 mx-auto"
disabled={isLoadingNext}
icon={isLoadingNext ? Spinner : IconChevronDown}
>
{__("Show more")}
</Button>
)}
</div>
</SortableContext>
);
}
export function SortableTh({
children,
field,
...props
}: ComponentProps<typeof Th> & { field: string }) {
const { order, onOrderChange } = useContext(SortableContext);
const isCurrentField = order.field === field;
const isDesc = order.direction === "DESC";
const changeOrder = () => {
onOrderChange({
direction: isDesc && isCurrentField ? "ASC" : "DESC",
field,
});
};
return (
<Th {...props}>
<button
className="flex items-center cursor-pointer hover:text-txt-primary"
onClick={changeOrder}
>
{children}
<IconChevronTriangleDownSmall
size={16}
className={clsx(
isCurrentField && "text-txt-primary",
isCurrentField && !isDesc && "rotate-180"
)}
/>
</button>
</Th>
);
}