chore: add sorting to provider's table

This commit is contained in:
Pablo Lara
2024-09-03 16:31:05 +02:00
parent 81743c9c29
commit 45f398bf30
7 changed files with 120 additions and 33 deletions
+20 -8
View File
@@ -3,22 +3,33 @@
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { auth } from "@/auth.config";
import { parseStringify } from "@/lib";
export const getProvider = async ({ page = 1 }) => {
export const getProvider = async ({
page = 1,
query = "",
sort = "",
filter = "",
}) => {
const session = await auth();
const tenantId = session?.user.tenantId;
if (isNaN(Number(page)) || page < 1) redirect("/providers");
const keyServer = process.env.LOCAL_SERVER_URL;
const url = new URL(`${keyServer}/providers`);
if (page) url.searchParams.append("page[number]", page.toString());
if (query) url.searchParams.append("filter[query]", query);
if (sort) url.searchParams.append("sort", sort);
if (filter) url.searchParams.append("filter[provider]", filter);
try {
const providers = await fetch(
`${keyServer}/providers?page%5Bnumber%5D=${page}`,
{
headers: {
"X-Tenant-ID": `${process.env.HEADER_TENANT_ID}`,
},
const providers = await fetch(`${url.toString()}`, {
headers: {
"X-Tenant-ID": `${tenantId}`,
},
);
});
const data = await providers.json();
const parsedData = parseStringify(data);
revalidatePath("/providers");
@@ -28,6 +39,7 @@ export const getProvider = async ({ page = 1 }) => {
return undefined;
}
};
export const addProvider = async (formData: FormData) => {
const keyServer = process.env.LOCAL_SERVER_URL;
+25 -6
View File
@@ -10,9 +10,15 @@ import {
SkeletonTableProvider,
} from "@/components/providers";
import { Header } from "@/components/ui";
import { searchParamsProps } from "@/types";
export default async function Providers({ searchParams }: searchParamsProps) {
export default async function Providers({
searchParams,
}: {
searchParams?: {
query?: string;
page: string;
};
}) {
return (
<>
<Header title="Providers" icon="fluent:cloud-sync-24-regular" />
@@ -22,7 +28,7 @@ export default async function Providers({ searchParams }: searchParamsProps) {
<AddProviderModal />
</div>
<Spacer y={6} />
<Suspense key={searchParams.page} fallback={<SkeletonTableProvider />}>
<Suspense key={searchParams?.page} fallback={<SkeletonTableProvider />}>
<SSRDataTable searchParams={searchParams} />
</Suspense>
</div>
@@ -30,9 +36,22 @@ export default async function Providers({ searchParams }: searchParamsProps) {
);
}
const SSRDataTable = async ({ searchParams }: searchParamsProps) => {
const page = searchParams.page ? parseInt(searchParams.page) : 1;
const providersData = await getProvider({ page });
const SSRDataTable = async ({
searchParams,
}: {
searchParams?: {
query?: string;
page?: string;
sort?: string;
filter?: string;
};
}) => {
const query = searchParams?.query || "";
const page = searchParams?.page ? parseInt(searchParams.page) : 1;
const sort = searchParams?.sort || "";
const filter = searchParams?.filter || "";
const providersData = await getProvider({ query, page, sort, filter });
const [providers] = await Promise.all([providersData]);
if (providers?.errors) redirect("/providers");
+1
View File
@@ -14,6 +14,7 @@ async function getUser(email: string, password: string): Promise<any | null> {
return {
id: user.id,
tenantId: user.tenantId,
name: user.name,
companyName: user.companyName,
email: user.email,
+18 -3
View File
@@ -18,6 +18,7 @@ import { CheckConnectionProvider } from "../CheckConnectionProvider";
import { DateWithTime } from "../DateWithTime";
import { DeleteProvider } from "../DeleteProvider";
import { ProviderInfo } from "../ProviderInfo";
import { DataTableColumnHeader } from "./DataTableColumnHeader";
const getProviderData = (row: { original: ProviderProps }) => {
return row.original;
@@ -30,7 +31,9 @@ export const ColumnsProvider: ColumnDef<ProviderProps>[] = [
},
{
accessorKey: "account",
header: "Account",
header: ({ column }) => (
<DataTableColumnHeader column={column} title={"Account"} param="alias" />
),
cell: ({ row }) => {
const {
attributes: { connection, provider, alias, provider_id },
@@ -55,7 +58,13 @@ export const ColumnsProvider: ColumnDef<ProviderProps>[] = [
},
{
accessorKey: "lastScan",
header: "Last Scan",
header: ({ column }) => (
<DataTableColumnHeader
column={column}
title={"Last Scan"}
param="updated_at"
/>
),
cell: ({ row }) => {
const {
attributes: { updated_at },
@@ -86,7 +95,13 @@ export const ColumnsProvider: ColumnDef<ProviderProps>[] = [
},
{
accessorKey: "added",
header: "Added",
header: ({ column }) => (
<DataTableColumnHeader
column={column}
title={"Added"}
param="inserted_at"
/>
),
cell: ({ row }) => {
const {
attributes: { inserted_at },
@@ -1,3 +1,5 @@
"use client";
import { Button } from "@nextui-org/react";
import { Column } from "@tanstack/react-table";
import {
@@ -5,25 +7,61 @@ import {
ArrowUpIcon,
ChevronsLeftRightIcon,
} from "lucide-react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { HTMLAttributes } from "react";
interface DataTableColumnHeaderProps<TData, TValue>
extends HTMLAttributes<HTMLDivElement> {
column: Column<TData, TValue>;
title: string;
param?: string;
}
export const DataTableColumnHeader = <TData, TValue>({
column,
title,
className,
param,
}: DataTableColumnHeaderProps<TData, TValue>) => {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const getToggleSortingHandler = () => {
const currentSortParam = searchParams.get("sort");
let newSortParam = "";
if (
!currentSortParam ||
currentSortParam === "" ||
currentSortParam !== param
) {
// Sort ascending for the first time or switch to a different column
newSortParam = `${param}`;
} else if (currentSortParam === param) {
// If already sorting ascending, switch to descending
newSortParam = `-${param}`;
} else if (currentSortParam === `-${param}`) {
// If already sorting descending, remove sorting
newSortParam = "";
}
// Construct the new URL with the sorting parameter
const newUrl = newSortParam ? `${pathname}?sort=${newSortParam}` : pathname;
router.push(newUrl, {
scroll: false,
});
};
const renderSortIcon = () => {
const sort = column.getIsSorted();
if (!sort) {
const currentSortParam = searchParams.get("sort");
if (
!currentSortParam ||
currentSortParam === "" ||
(currentSortParam !== param && currentSortParam !== `-${param}`)
) {
return <ChevronsLeftRightIcon className="ml-2 h-4 w-4 rotate-90" />;
}
return sort === "desc" ? (
return currentSortParam === `-${param}` ? (
<ArrowDownIcon className="ml-2 h-4 w-4" />
) : (
<ArrowUpIcon className="ml-2 h-4 w-4" />
@@ -31,19 +69,18 @@ export const DataTableColumnHeader = <TData, TValue>({
};
if (!column.getCanSort()) {
return <div className={className}>{title}</div>;
return <div>{title}</div>;
}
return (
<div className={className}>
<Button
variant="ghost"
size="sm"
className="h-8"
onClick={column.getToggleSortingHandler()}
>
<span>{title}</span>
{renderSortIcon()}
</Button>
</div>
<Button
variant="light"
size="md"
className="h-8"
onClick={getToggleSortingHandler}
>
<span>{title}</span>
{renderSortIcon()}
</Button>
);
};
+2
View File
@@ -4,6 +4,7 @@ import { v4 as uuidv4 } from "uuid";
export const userMockData = [
{
id: uuidv4(), // Generate a unique UUID.
tenantId: "12646005-9067-4d2a-a098-8bb378604362",
email: "admin@prowler.com",
name: "Admin Prowler",
companyName: "Prowler",
@@ -13,6 +14,7 @@ export const userMockData = [
},
{
id: uuidv4(), // Generate a unique UUID.
tenantId: "12646005-9067-4d2a-a098-8bb378604362",
email: "user@prowler.com",
name: "User Prowler",
companyName: "Prowler",
+1
View File
@@ -4,6 +4,7 @@ declare module "next-auth" {
interface Session {
user: {
id: string;
tenantId: string;
firstName: string;
companyName: string;
email: string;