Merge branch 'main' into PRWLR-4393-Setup-NextAuth-client-session

This commit is contained in:
Pablo Lara committed 2024-08-26 15:46:03 +02:00
commit 06d05ec860
19 files changed
+643 -17

No files matched your search

+23 -11
View File
@@ -126,12 +126,6 @@ export const sectionItems: SidebarItem[] = [
// />
// ),
// },
{
key: "services",
href: "/services",
icon: "material-symbols:linked-services-outline",
title: "Services",
},
{
key: "compliance",
href: "/compliance",
@@ -143,6 +137,24 @@ export const sectionItems: SidebarItem[] = [
</Chip>
),
},
{
key: "services",
href: "/services",
icon: "material-symbols:linked-services-outline",
title: "Services",
},
{
key: "categories",
href: "/categories",
icon: "material-symbols:folder-open-outline",
title: "Categories",
},
{
key: "workloads",
href: "/workloads",
icon: "lucide:tags",
title: "Workloads",
},
],
},
{
@@ -190,10 +202,10 @@ export const sectionItems: SidebarItem[] = [
),
},
{
key: "integration",
href: "/integration",
key: "integrations",
href: "/integrations",
icon: "tabler:puzzle",
title: "Integration",
title: "Integrations",
},
{
key: "settings",
@@ -213,9 +225,9 @@ export const sectionItemsWithTeams: SidebarItem[] = [
items: [
{
key: "users",
href: "#",
href: "/users",
title: "Users",
startContent: <TeamAvatar name="Users page" />,
icon: "ci:users",
},
{
key: "roles",
+5 -1
View File
@@ -7,7 +7,9 @@ type Status =
| "cancelled"
| "fail"
| "success"
| "muted";
| "muted"
| "active"
| "inactive";
const statusColorMap: Record<
Status,
@@ -19,6 +21,8 @@ const statusColorMap: Record<
fail: "danger",
success: "success",
muted: "default",
active: "success",
inactive: "default",
};
export const StatusBadge = ({ status }: { status: Status }) => {
+5
View File
@@ -0,0 +1,5 @@
export * from "./table/ColumnsUser";
export * from "./table/DataTableColumnHeader";
export * from "./table/DataTablePagination";
export * from "./table/DataTableUser";
export * from "./table/SkeletonTableUser";
+83
View File
@@ -0,0 +1,83 @@
"use client";
import {
Button,
Dropdown,
DropdownItem,
DropdownMenu,
DropdownTrigger,
} from "@nextui-org/react";
import { ColumnDef } from "@tanstack/react-table";
import { VerticalDotsIcon } from "@/components/icons";
import { DateWithTime } from "@/components/providers";
import { StatusBadge } from "@/components/ui";
import { UserProps } from "@/types";
const getUserData = (row: { original: UserProps }) => {
return row.original;
};
export const ColumnsUser: ColumnDef<UserProps>[] = [
{
accessorKey: "email",
header: "Email",
cell: ({ row }) => {
const { email } = getUserData(row);
return <p className="font-semibold">{email}</p>;
},
},
{
accessorKey: "name",
header: "Name",
cell: ({ row }) => {
const { name } = getUserData(row);
return <p className="font-semibold">{name}</p>;
},
},
{
accessorKey: "role",
header: "Role",
cell: ({ row }) => {
const { role } = getUserData(row);
return <p className="font-semibold">{role}</p>;
},
},
{
accessorKey: "added",
header: "Added",
cell: ({ row }) => {
const { dateAdded } = getUserData(row);
return <DateWithTime dateTime={dateAdded} showTime={false} />;
},
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const { status } = getUserData(row);
return <StatusBadge status={status} />;
},
},
{
accessorKey: "actions",
header: () => <div className="text-right">Actions</div>,
id: "actions",
cell: () => {
return (
<div className="relative flex justify-end items-center gap-2">
<Dropdown className="bg-background border-1 border-default-200">
<DropdownTrigger>
<Button isIconOnly radius="full" size="sm" variant="light">
<VerticalDotsIcon className="text-default-400" />
</Button>
</DropdownTrigger>
<DropdownMenu>
<DropdownItem>Edit</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
);
},
},
];
@@ -0,0 +1,49 @@
import { Button } from "@nextui-org/react";
import { Column } from "@tanstack/react-table";
import {
ArrowDownIcon,
ArrowUpIcon,
ChevronsLeftRightIcon,
} from "lucide-react";
import { HTMLAttributes } from "react";
interface DataTableColumnHeaderProps<TData, TValue>
extends HTMLAttributes<HTMLDivElement> {
column: Column<TData, TValue>;
title: string;
}
export const DataTableColumnHeader = <TData, TValue>({
column,
title,
className,
}: DataTableColumnHeaderProps<TData, TValue>) => {
const renderSortIcon = () => {
const sort = column.getIsSorted();
if (!sort) {
return <ChevronsLeftRightIcon className="ml-2 h-4 w-4 rotate-90" />;
}
return sort === "desc" ? (
<ArrowDownIcon className="ml-2 h-4 w-4" />
) : (
<ArrowUpIcon className="ml-2 h-4 w-4" />
);
};
if (!column.getCanSort()) {
return <div className={className}>{title}</div>;
}
return (
<div className={className}>
<Button
variant="ghost"
size="sm"
className="h-8"
onClick={column.getToggleSortingHandler()}
>
<span>{title}</span>
{renderSortIcon()}
</Button>
</div>
);
};
@@ -0,0 +1,85 @@
"use client";
import {
ChevronLeftIcon,
ChevronRightIcon,
DoubleArrowLeftIcon,
DoubleArrowRightIcon,
} from "@radix-ui/react-icons";
import Link from "next/link";
import { usePathname, useSearchParams } from "next/navigation";
import { extractPaginationInfo } from "@/lib";
import { MetaDataProps } from "@/types";
interface DataTablePaginationProps {
pageSizeOptions?: number[];
metadata?: MetaDataProps;
}
export function DataTablePagination({ metadata }: DataTablePaginationProps) {
if (!metadata) return null;
const pathname = usePathname();
const searchParams = useSearchParams();
const { currentPage, totalPages, totalEntries } =
extractPaginationInfo(metadata);
const createPageUrl = (pageNumber: number | string) => {
const params = new URLSearchParams(searchParams);
if (pageNumber === "...") return `${pathname}?${params.toString()}`;
if (+pageNumber > totalPages) {
return `${pathname}?${params.toString()}`;
}
params.set("page", pageNumber.toString());
return `${pathname}?${params.toString()}`;
};
return (
<div className="flex w-full flex-col-reverse items-center justify-between gap-4 overflow-auto p-1 sm:flex-row sm:gap-8">
<div className="whitespace-nowrap text-sm font-medium">
{totalEntries} entries in Total.
</div>
<div className="flex flex-col-reverse items-center gap-4 sm:flex-row sm:gap-6 lg:gap-8">
<div className="flex items-center justify-center text-sm font-medium">
Page {currentPage} of {totalPages}
</div>
<div className="flex items-center space-x-2">
<Link
aria-label="Go to first page"
className="page-link relative block py-1.5 px-3 border-0 bg-transparent outline-none transition-all duration-300 rounded text-gray-800 hover:text-gray-800 hover:bg-gray-200 focus:shadow-none"
href={createPageUrl(1)}
aria-disabled="true"
>
<DoubleArrowLeftIcon className="size-4" aria-hidden="true" />
</Link>
<Link
aria-label="Go to previous page"
className="page-link relative block py-1.5 px-3 border-0 bg-transparent outline-none transition-all duration-300 rounded text-gray-800 hover:text-gray-800 hover:bg-gray-200 focus:shadow-none"
href={createPageUrl(currentPage - 1)}
aria-disabled="true"
>
<ChevronLeftIcon className="size-4" aria-hidden="true" />
</Link>
<Link
aria-label="Go to next page"
className="page-link relative block py-1.5 px-3 border-0 bg-transparent outline-none transition-all duration-300 rounded text-gray-800 hover:text-gray-800 hover:bg-gray-200 focus:shadow-none"
href={createPageUrl(currentPage + 1)}
>
<ChevronRightIcon className="size-4" aria-hidden="true" />
</Link>
<Link
aria-label="Go to last page"
className="page-link relative block py-1.5 px-3 border-0 bg-transparent outline-none transition-all duration-300 rounded text-gray-800 hover:text-gray-800 hover:bg-gray-200 focus:shadow-none"
href={createPageUrl(totalPages)}
>
<DoubleArrowRightIcon className="size-4" aria-hidden="true" />
</Link>
</div>
</div>
</div>
);
}
+106
View File
@@ -0,0 +1,106 @@
"use client";
import {
ColumnDef,
flexRender,
getCoreRowModel,
getPaginationRowModel,
getSortedRowModel,
SortingState,
useReactTable,
} from "@tanstack/react-table";
import { useState } from "react";
import { DataTablePagination } from "@/components/providers";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui";
import { MetaDataProps } from "@/types";
interface DataTableUserProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
metadata?: MetaDataProps;
}
export function DataTableUser<TData, TValue>({
columns,
data,
metadata,
}: DataTableUserProps<TData, TValue>) {
const [sorting, setSorting] = useState<SortingState>([]);
const table = useReactTable({
data,
columns,
enableSorting: true,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onSortingChange: setSorting,
getSortedRowModel: getSortedRowModel(),
state: {
sorting,
},
});
return (
<>
<div className="rounded-md border w-full">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
<div className="flex items-center w-full space-x-2 py-4">
<DataTablePagination metadata={metadata} />
</div>
</>
);
}
@@ -0,0 +1,59 @@
import { Card, Skeleton } from "@nextui-org/react";
import React from "react";
export const SkeletonTableUser = () => {
return (
<Card className="w-full h-full space-y-5 p-4" radius="sm">
{/* Table headers */}
<div className="hidden md:flex justify-between">
<Skeleton className="w-2/12 rounded-lg">
<div className="h-8 bg-default-200"></div>
</Skeleton>
<Skeleton className="w-2/12 rounded-lg">
<div className="h-8 bg-default-200"></div>
</Skeleton>
<Skeleton className="w-2/12 rounded-lg">
<div className="h-8 bg-default-200"></div>
</Skeleton>
<Skeleton className="w-2/12 rounded-lg">
<div className="h-8 bg-default-200"></div>
</Skeleton>
<Skeleton className="w-2/12 rounded-lg">
<div className="h-8 bg-default-200"></div>
</Skeleton>
<Skeleton className="w-1/12 rounded-lg">
<div className="h-8 bg-default-200"></div>
</Skeleton>
</div>
{/* Table body */}
<div className="space-y-3">
{[...Array(10)].map((_, index) => (
<div
key={index}
className="flex flex-col md:flex-row justify-between items-center space-x-0 md:space-x-4"
>
<Skeleton className="w-full md:w-2/12 rounded-lg mb-2 md:mb-0">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="w-full md:w-2/12 rounded-lg mb-2 md:mb-0">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-2/12 rounded-lg mb-2 md:mb-0">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-2/12 rounded-lg mb-2 md:mb-0">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-2/12 rounded-lg mb-2 md:mb-0">
<div className="h-12 bg-default-300"></div>
</Skeleton>
<Skeleton className="hidden sm:flex md:w-1/12 rounded-lg mb-2 md:mb-0">
<div className="h-12 bg-default-300"></div>
</Skeleton>
</div>
))}
</div>
</Card>
);
};