feat: criteria table

This commit is contained in:
mehedi-hasan 2024-04-17 21:27:31 +06:00
parent 9ab2cacfea
commit 86d73de22a
14 changed files with 930 additions and 72 deletions

View File

@ -0,0 +1,20 @@
import Breadcrumb from "@/components/breadcrumb";
import ToolsTable from "@/components/criteria-table/tools-table";
import { dummyCriteria } from "@/constants/data";
import { Criteria } from "@/types/criteria";
import React from "react";
const breadcrumbItems = [
{ title: "Dashboard", link: "#" },
{ title: "Criteria" },
];
const Page = () => {
return (
<div className="flex-1 space-y-4 p-4 md:p-8 pt-6">
<Breadcrumb items={breadcrumbItems} />
<ToolsTable criteriaData={dummyCriteria as Criteria[]} />
</div>
);
};
export default Page;

View File

@ -2,7 +2,7 @@ import Breadcrumb from "@/components/breadcrumb";
import ToolsTable from "@/components/evaluation-start-table/tools-table"; import ToolsTable from "@/components/evaluation-start-table/tools-table";
import { dummyCourseAdmin, dummyEvaluation } from "@/constants/data"; import { dummyCourseAdmin, dummyEvaluation } from "@/constants/data";
import { CourseAdmin } from "@/types/course-admin"; import { CourseAdmin } from "@/types/course-admin";
import { Evaluation } from "@/types/evaluation-start"; import { EvaluationStart } from "@/types/evaluation-start";
import React from "react"; import React from "react";
const breadcrumbItems = [ const breadcrumbItems = [
@ -13,7 +13,7 @@ const Page = () => {
return ( return (
<div className="flex-1 space-y-4 p-4 md:p-8 pt-6"> <div className="flex-1 space-y-4 p-4 md:p-8 pt-6">
<Breadcrumb items={breadcrumbItems} /> <Breadcrumb items={breadcrumbItems} />
<ToolsTable evaluationData={dummyEvaluation as Evaluation[]} /> <ToolsTable evaluationData={dummyEvaluation as EvaluationStart[]} />
</div> </div>
); );
}; };

View File

@ -0,0 +1,69 @@
"use client";
import { AlertModal } from "@/components/alert-modal";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { useToast } from "@/components/ui/use-toast";
import { Criteria } from "@/types/criteria";
import { EvaluationStart } from "@/types/evaluation-start";
import { Edit, GitCommit, MoreHorizontal, Trash } from "lucide-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
interface CellActionProps {
data: Criteria;
}
export const CellAction: React.FC<CellActionProps> = ({ data }) => {
const [loading, setLoading] = useState(false);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const router = useRouter();
const { toast } = useToast();
const onDeleteConfirm = async () => {};
const handleUpdateStatus = async () => {};
return (
<>
<AlertModal
isOpen={isDeleteModalOpen}
onClose={() => setIsDeleteModalOpen(false)}
onConfirm={onDeleteConfirm}
loading={loading}
/>
<DropdownMenu modal={false}>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open menu</span>
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem
className="cursor-pointer"
// onClick={() =>
// router.push(`#`)
// }
>
<Edit className="mr-2 h-4 w-4" /> Edit
</DropdownMenuItem>
<DropdownMenuItem
className="cursor-pointer"
onClick={() => setIsDeleteModalOpen(true)}
>
<Trash className="mr-2 h-4 w-4" /> Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</>
);
};

View File

@ -0,0 +1,122 @@
"use client";
import { DataTableColumnHeader } from "./data-table-column-header";
import { CellAction } from "./cell-action";
import { ColumnDef } from "@tanstack/react-table";
import { Checkbox } from "@/components/ui/checkbox";
import { Criteria } from "@/types/criteria";
import { formatDate } from "@/lib/format-date";
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "../ui/hover-card";
import { ScrollArea, ScrollBar } from "../ui/scroll-area";
export const columns: ColumnDef<Criteria>[] = [
{
id: "select",
header: ({ table }) => (
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && "indeterminate")
}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
aria-label="Select all"
className="translate-y-[2px]"
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
aria-label="Select row"
className="translate-y-[2px]"
/>
),
enableSorting: false,
enableHiding: false,
},
{
accessorKey: "name",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="NAME" />
),
cell: ({ row }) => {
return <p>{row.getValue("name")}</p>;
},
},
{
accessorKey: "description",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="DESCRIPTION" />
),
cell: ({ row }) => {
return (
<div className="w-fit">
<HoverCard>
<HoverCardTrigger>
<p className="max-w-[250px] truncate font-medium">
{row.getValue("description")}
</p>
</HoverCardTrigger>
<HoverCardContent>
<p className="whitespace-pre-wrap">
{row.getValue("description")}
</p>
</HoverCardContent>
</HoverCard>
</div>
);
},
},
{
accessorKey: "prompt",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="PROMPT" />
),
cell: ({ row }) => {
return (
<div className="w-fit">
<HoverCard>
<HoverCardTrigger>
<p className="max-w-[250px] truncate font-medium">
{row.getValue("prompt")}
</p>
</HoverCardTrigger>
<HoverCardContent className="p-0 h-72 w-72 lg:h-96 lg:w-96">
<ScrollArea className="h-72 w-72 p-4 lg:h-96 lg:w-96">
<p className="whitespace-pre-wrap">{row.getValue("prompt")}</p>
<ScrollBar orientation="vertical" />
</ScrollArea>
</HoverCardContent>
</HoverCard>
</div>
);
},
},
{
accessorKey: "created_at",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="CREATED AT" />
),
cell: ({ row }) => {
return <p className="w-fit">{formatDate(row.getValue("created_at"))}</p>;
},
filterFn: (row, id, value) => {
return value.includes(row.getValue(id));
},
},
{
id: "actions",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="ACTIONS" />
),
cell: ({ row }) => <CellAction data={row.original} />,
},
];

View File

@ -0,0 +1,72 @@
import {
ArrowDownIcon,
ArrowUpIcon,
CaretSortIcon,
EyeNoneIcon,
} from "@radix-ui/react-icons"
import { Column } from "@tanstack/react-table"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
interface DataTableColumnHeaderProps<TData, TValue>
extends React.HTMLAttributes<HTMLDivElement> {
column: Column<TData, TValue>
title: string
}
export function DataTableColumnHeader<TData, TValue>({
column,
title,
className,
}: DataTableColumnHeaderProps<TData, TValue>) {
if (!column.getCanSort()) {
return <div className={cn(className)}>{title}</div>
}
return (
<div className={cn("flex items-center space-x-2", className)}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="sm"
className="-ml-3 h-8 data-[state=open]:bg-accent"
>
<span>{title}</span>
{column.getIsSorted() === "desc" ? (
<ArrowDownIcon className="ml-2 h-4 w-4" />
) : column.getIsSorted() === "asc" ? (
<ArrowUpIcon className="ml-2 h-4 w-4" />
) : (
<CaretSortIcon className="ml-2 h-4 w-4" />
)}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem onClick={() => column.toggleSorting(false)}>
<ArrowUpIcon className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
Asc
</DropdownMenuItem>
<DropdownMenuItem onClick={() => column.toggleSorting(true)}>
<ArrowDownIcon className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
Desc
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => column.toggleVisibility(false)}>
<EyeNoneIcon className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
Hide
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
)
}

View File

@ -0,0 +1,147 @@
import * as React from "react"
import { CheckIcon, PlusCircledIcon } from "@radix-ui/react-icons"
import { Column } from "@tanstack/react-table"
import { cn } from "@/lib/utils"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
} from "@/components/ui/command"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import { Separator } from "@/components/ui/separator"
interface DataTableFacetedFilterProps<TData, TValue> {
column?: Column<TData, TValue>
title?: string
options: {
label: string
value: string
icon?: React.ComponentType<{ className?: string }>
}[]
}
export function DataTableFacetedFilter<TData, TValue>({
column,
title,
options,
}: DataTableFacetedFilterProps<TData, TValue>) {
const facets = column?.getFacetedUniqueValues()
const selectedValues = new Set(column?.getFilterValue() as string[])
return (
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" size="sm" className="h-8 border-dashed">
<PlusCircledIcon className="mr-2 h-4 w-4" />
{title}
{selectedValues?.size > 0 && (
<>
<Separator orientation="vertical" className="mx-2 h-4" />
<Badge
variant="secondary"
className="rounded-sm px-1 font-normal lg:hidden"
>
{selectedValues.size}
</Badge>
<div className="hidden space-x-1 lg:flex">
{selectedValues.size > 2 ? (
<Badge
variant="secondary"
className="rounded-sm px-1 font-normal"
>
{selectedValues.size} selected
</Badge>
) : (
options
.filter((option) => selectedValues.has(option.value))
.map((option) => (
<Badge
variant="secondary"
key={option.value}
className="rounded-sm px-1 font-normal"
>
{option.label}
</Badge>
))
)}
</div>
</>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0" align="start">
<Command>
<CommandInput placeholder={title} />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup>
{options.map((option) => {
const isSelected = selectedValues.has(option.value)
return (
<CommandItem
key={option.value}
onSelect={() => {
if (isSelected) {
selectedValues.delete(option.value)
} else {
selectedValues.add(option.value)
}
const filterValues = Array.from(selectedValues)
column?.setFilterValue(
filterValues.length ? filterValues : undefined
)
}}
>
<div
className={cn(
"mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary",
isSelected
? "bg-primary text-primary-foreground"
: "opacity-50 [&_svg]:invisible"
)}
>
<CheckIcon className={cn("h-4 w-4")} />
</div>
{option.icon && (
<option.icon className="mr-2 h-4 w-4 text-muted-foreground" />
)}
<span>{option.label}</span>
{facets?.get(option.value) && (
<span className="ml-auto flex h-4 w-4 items-center justify-center font-mono text-xs">
{facets.get(option.value)}
</span>
)}
</CommandItem>
)
})}
</CommandGroup>
{selectedValues.size > 0 && (
<>
<CommandSeparator />
<CommandGroup>
<CommandItem
onSelect={() => column?.setFilterValue(undefined)}
className="justify-center text-center"
>
Clear filters
</CommandItem>
</CommandGroup>
</>
)}
</CommandList>
</Command>
</PopoverContent>
</Popover>
)
}

View File

@ -0,0 +1,97 @@
import {
ChevronLeftIcon,
ChevronRightIcon,
DoubleArrowLeftIcon,
DoubleArrowRightIcon,
} from "@radix-ui/react-icons";
import { Table } from "@tanstack/react-table";
import { Button } from "@/components/ui/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
interface DataTablePaginationProps<TData> {
table: Table<TData>;
}
export function DataTablePagination<TData>({
table,
}: DataTablePaginationProps<TData>) {
return (
<div className="grid grid-cols-2 md:grid-cols-[1fr_auto_auto] gap-x-6 gap-y-2">
<div className="text-sm text-muted-foreground">
{table.getFilteredSelectedRowModel().rows.length} of{" "}
{table.getFilteredRowModel().rows.length} row(s) selected.
</div>
<div className="flex items-center space-x-2">
<p className="text-sm font-medium">Rows per page</p>
<Select
value={`${table.getState().pagination.pageSize}`}
onValueChange={(value) => {
table.setPageSize(Number(value));
}}
>
<SelectTrigger className="h-8 w-[70px]">
<SelectValue placeholder={table.getState().pagination.pageSize} />
</SelectTrigger>
<SelectContent side="top">
{[10, 20, 30, 40, 50].map((pageSize) => (
<SelectItem key={pageSize} value={`${pageSize}`}>
{pageSize}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="flex items-center gap-2">
<div className="text-sm font-medium">
Page {table.getState().pagination.pageIndex + 1} of{" "}
{table.getPageCount()}
</div>
<div className="flex items-center space-x-2">
<Button
variant="outline"
className="h-8 w-8 p-0 flex"
onClick={() => table.setPageIndex(0)}
disabled={!table.getCanPreviousPage()}
>
<span className="sr-only">Go to first page</span>
<DoubleArrowLeftIcon className="h-4 w-4" />
</Button>
<Button
variant="outline"
className="h-8 w-8 p-0"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
<span className="sr-only">Go to previous page</span>
<ChevronLeftIcon className="h-4 w-4" />
</Button>
<Button
variant="outline"
className="h-8 w-8 p-0"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
<span className="sr-only">Go to next page</span>
<ChevronRightIcon className="h-4 w-4" />
</Button>
<Button
variant="outline"
className="h-8 w-8 p-0 flex"
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
disabled={!table.getCanNextPage()}
>
<span className="sr-only">Go to last page</span>
<DoubleArrowRightIcon className="h-4 w-4" />
</Button>
</div>
</div>
</div>
);
}

View File

@ -0,0 +1,84 @@
"use client";
import { Cross2Icon } from "@radix-ui/react-icons";
import { Table } from "@tanstack/react-table";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { DataTableFacetedFilter } from "./data-table-faceted-filter";
import { DataTableViewOptions } from "./data-table-view-options";
import { userFilterLabels } from "@/constants/data";
import { Criteria } from "@/types/criteria";
interface DataTableToolbarProps<TData> {
table: Table<TData>;
data: Criteria[];
}
export function DataTableToolbar<TData>({
table,
data,
}: DataTableToolbarProps<TData>) {
const isFiltered = table.getState().columnFilters.length > 0;
// const statusFilterOptions = Array.from(
// new Set(data.map((d) => d.status))
// ).map((v) => ({
// label: v,
// value: v,
// }));
return (
<div className="flex items-center justify-between">
<div className="flex flex-1 items-center gap-2 flex-wrap">
<Input
placeholder="Search name..."
value={(table.getColumn("name")?.getFilterValue() as string) ?? ""}
onChange={(event: any) =>
table.getColumn("name")?.setFilterValue(event.target.value)
}
className="h-8 w-[150px] lg:w-[250px]"
/>
<Input
placeholder="Search description..."
value={
(table.getColumn("description")?.getFilterValue() as string) ?? ""
}
onChange={(event: any) =>
table.getColumn("description")?.setFilterValue(event.target.value)
}
className="h-8 w-[150px] lg:w-[250px]"
/>
<Input
placeholder="Search prompt..."
value={
(table.getColumn("prompt")?.getFilterValue() as string) ?? ""
}
onChange={(event: any) =>
table.getColumn("prompt")?.setFilterValue(event.target.value)
}
className="h-8 w-[150px] lg:w-[250px]"
/>
{/* {table.getColumn("status") && (
<DataTableFacetedFilter
column={table.getColumn("status")}
title="STATUS"
options={statusFilterOptions}
/>
)}
{isFiltered && (
<Button
variant="ghost"
onClick={() => table.resetColumnFilters()}
className="h-8 px-2 lg:px-3"
>
Reset
<Cross2Icon className="ml-2 h-4 w-4" />
</Button>
)} */}
</div>
<DataTableViewOptions table={table} />
</div>
);
}

View File

@ -0,0 +1,59 @@
"use client"
import { DropdownMenuTrigger } from "@radix-ui/react-dropdown-menu"
import { MixerHorizontalIcon } from "@radix-ui/react-icons"
import { Table } from "@tanstack/react-table"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuLabel,
DropdownMenuSeparator,
} from "@/components/ui/dropdown-menu"
interface DataTableViewOptionsProps<TData> {
table: Table<TData>
}
export function DataTableViewOptions<TData>({
table,
}: DataTableViewOptionsProps<TData>) {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
size="sm"
className="ml-auto hidden h-8 lg:flex"
>
<MixerHorizontalIcon className="mr-2 h-4 w-4" />
View
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-[150px]">
<DropdownMenuLabel>Toggle columns</DropdownMenuLabel>
<DropdownMenuSeparator />
{table
.getAllColumns()
.filter(
(column) =>
typeof column.accessorFn !== "undefined" && column.getCanHide()
)
.map((column) => {
return (
<DropdownMenuCheckboxItem
key={column.id}
className="capitalize"
checked={column.getIsVisible()}
onCheckedChange={(value) => column.toggleVisibility(!!value)}
>
{column.id}
</DropdownMenuCheckboxItem>
)
})}
</DropdownMenuContent>
</DropdownMenu>
)
}

View File

@ -0,0 +1,131 @@
"use client";
import * as React from "react";
import {
ColumnDef,
ColumnFiltersState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFacetedRowModel,
getFacetedUniqueValues,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { DataTablePagination } from "./data-table-pagination";
import { DataTableToolbar } from "./data-table-toolbar";
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
import { Criteria } from "@/types/criteria";
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
}
export function DataTable<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const [rowSelection, setRowSelection] = React.useState({});
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const [sorting, setSorting] = React.useState<SortingState>([]);
const table = useReactTable({
data,
columns,
state: {
sorting,
columnVisibility,
rowSelection,
columnFilters,
},
enableRowSelection: true,
onRowSelectionChange: setRowSelection,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
onColumnVisibilityChange: setColumnVisibility,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFacetedRowModel: getFacetedRowModel(),
getFacetedUniqueValues: getFacetedUniqueValues(),
});
return (
<div className="space-y-4">
<DataTableToolbar table={table} data={data as Criteria[]} />
{/* <div className="rounded-md border"> */}
<ScrollArea className="rounded-md border h-[66vh]">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id} colSpan={header.colSpan}>
{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>
<ScrollBar orientation="horizontal" />
</ScrollArea>
{/* </div> */}
<DataTablePagination table={table} />
</div>
);
}

View File

@ -0,0 +1,39 @@
"use client";
import { Heading } from "@/components/ui/heading";
import { Separator } from "@/components/ui/separator";
import React from "react";
import { DataTable } from "./data-table";
import { columns } from "./columns";
import Link from "next/link";
import { Plus } from "lucide-react";
import { buttonVariants } from "@/components/ui/button";
import { Criteria } from "@/types/criteria";
const ToolsTable = ({ criteriaData }: { criteriaData: Criteria[] }) => {
return (
<>
<div className="flex items-start justify-between">
<Heading
title={`Criteria (${criteriaData.length})`}
description="Manage Criteria"
/>
<Link
href="#"
className={buttonVariants({
variant: "default",
// size: "sm",
})}
// className="text-xs md:text-sm"
// onClick={() => router.push(`/admin-dashboard/tools/add`)}
>
<Plus className="mr-2 h-4 w-4" /> Add Criteria
</Link>
</div>
<Separator />
<DataTable data={criteriaData} columns={columns} />
</>
);
};
export default ToolsTable;

View File

@ -1,13 +1,7 @@
"use client"; "use client";
import { DataTableColumnHeader } from "./data-table-column-header"; import { DataTableColumnHeader } from "./data-table-column-header";
import { CellAction } from "./cell-action"; import { CellAction } from "./cell-action";
import { ColumnDef } from "@tanstack/react-table"; import { ColumnDef } from "@tanstack/react-table";
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/components/ui/hover-card";
import { User } from "@/types/user"; import { User } from "@/types/user";
import { Checkbox } from "@/components/ui/checkbox"; import { Checkbox } from "@/components/ui/checkbox";
import { formatDate } from "@/lib/format-date"; import { formatDate } from "@/lib/format-date";
@ -44,28 +38,8 @@ export const columns: ColumnDef<User>[] = [
<DataTableColumnHeader column={column} title="EMAIL" /> <DataTableColumnHeader column={column} title="EMAIL" />
), ),
cell: ({ row }) => { cell: ({ row }) => {
return ( return <p>{row.getValue("email")}</p>;
<div className="w-fit">
<HoverCard>
<HoverCardTrigger>
{/* <p className="max-w-[100px] truncate font-medium">
{row.getValue("email")}
</p> */}
<p>{row.getValue("email")}</p>
</HoverCardTrigger>
<HoverCardContent>
{/* <ScrollArea className="w-64 p-4"> */}
{row.getValue("email")}
{/* <ScrollBar orientation="horizontal" /> */}
{/* </ScrollArea> */}
</HoverCardContent>
</HoverCard>
</div>
);
}, },
// filterFn: (row, id, value) => {
// return value.includes(row.getValue(id));
// },
}, },
{ {
accessorKey: "fullName", accessorKey: "fullName",
@ -73,29 +47,8 @@ export const columns: ColumnDef<User>[] = [
<DataTableColumnHeader column={column} title="FULL NAME" /> <DataTableColumnHeader column={column} title="FULL NAME" />
), ),
cell: ({ row }) => { cell: ({ row }) => {
return ( return <p>{row.getValue("fullName")}</p>;
<div className="w-fit">
<HoverCard>
<HoverCardTrigger>
<p className="max-w-[100px] truncate font-medium">
{row.getValue("fullName")}
</p>
</HoverCardTrigger>
<HoverCardContent
// className="p-0"
>
{/* <ScrollArea className="w-64 p-4"> */}
{row.getValue("fullName")}
{/* <ScrollBar orientation="horizontal" /> */}
{/* </ScrollArea> */}
</HoverCardContent>
</HoverCard>
</div>
);
}, },
// filterFn: (row, id, value) => {
// return value.includes(row.getValue(id));
// },
}, },
{ {
accessorKey: "role", accessorKey: "role",
@ -103,25 +56,7 @@ export const columns: ColumnDef<User>[] = [
<DataTableColumnHeader column={column} title="ROLE" /> <DataTableColumnHeader column={column} title="ROLE" />
), ),
cell: ({ row }) => { cell: ({ row }) => {
return ( return <p>{row.getValue("role")}</p>;
<div className="w-fit">
<HoverCard>
<HoverCardTrigger>
<p className="max-w-[100px] truncate font-medium">
{row.getValue("role")}
</p>
</HoverCardTrigger>
<HoverCardContent
// className="p-0"
>
{/* <ScrollArea className="w-64 p-4"> */}
{row.getValue("role")}
{/* <ScrollBar orientation="horizontal" /> */}
{/* </ScrollArea> */}
</HoverCardContent>
</HoverCard>
</div>
);
}, },
filterFn: (row, id, value) => { filterFn: (row, id, value) => {
return value.includes(row.getValue(id)); return value.includes(row.getValue(id));

View File

@ -1,7 +1,8 @@
import { Account } from "@/types/account"; import { Account } from "@/types/account";
import { ApiCommunication } from "@/types/api-communication"; import { ApiCommunication } from "@/types/api-communication";
import { Configuration } from "@/types/configuration"; import { Configuration } from "@/types/configuration";
import { Evaluation } from "@/types/evaluation-start"; import { Criteria } from "@/types/criteria";
import { EvaluationStart } from "@/types/evaluation-start";
import { Organization } from "@/types/organization"; import { Organization } from "@/types/organization";
import { User } from "@/types/user"; import { User } from "@/types/user";
import { UserRound, UserRoundCheck } from "lucide-react"; import { UserRound, UserRoundCheck } from "lucide-react";
@ -180,7 +181,7 @@ export const dummyCourseAdmin = [
}, },
]; ];
export const dummyEvaluation: Evaluation[] = [ export const dummyEvaluation: EvaluationStart[] = [
{ {
id: 1, id: 1,
fullName: "John Doe", fullName: "John Doe",
@ -194,3 +195,78 @@ export const dummyEvaluation: Evaluation[] = [
status: "unfinished", status: "unfinished",
}, },
]; ];
export const dummyCriteria: Criteria[] = [
{
id: 1,
name: "readability",
description: "assesses the clarity and understandability of the code",
prompt: `You are a professional git reviewing assistant with focus on --name--.
You are given a commit message or a commit diff.
You know sometimes developers do simple stuff like fixing a typo.
In that case you can evaluate the criterias with a score of 0 which means it is not applicable.
If there is no code at all, you can evaluate the criterias with a score of 0 which means it is not applicable.
Otherwise if you think the code is good enough to make a review,
You have to rate the code from 1-10, where 1 is poor and 10 is excellent based on the following criterias:
--subcriteria--
If you always rate the coe above 5, you are too nice.
You have to ignore comments and strings in variables.
Always answer in the following json format where "cn" is the name of criterion and "s" is the score:
{[
{"cn": criterion_name_1, "s": score_1},
{"cn": criterion_name_2, "s": score_2},
...
]}
----------------------------------------
ONLY JSON IS ALLOWED as an answer. No explanation or other text is allowed.
`,
created_at: new Date().toISOString(),
},
{
id: 2,
name: "refinement",
description: "assesses the process and stages of code development",
prompt: `You are a professional git reviewing assistant with focus on --name--.
You are given a commit message or a commit diff.
You know sometimes developers do simple stuff like fixing a typo.
In that case you can evaluate the criterias with a score of 0 which means it is not applicable.
If there is no code at all, you can evaluate the criterias with a score of 0 which means it is not applicable.
Otherwise if you think the code is good enough to make a review,
You have to rate the code from 1-10, where 1 is poor and 10 is excellent based on the following criterias:
--subcriteria--
If you always rate the coe above 5, you are too nice.
You have to ignore comments and strings in variables.
Always answer in the following json format where "cn" is the name of criterion and "s" is the score:
{[
{"cn": criterion_name_1, "s": score_1},
{"cn": criterion_name_2, "s": score_2},
...
]}
----------------------------------------
ONLY JSON IS ALLOWED as an answer. No explanation or other text is allowed.
`,
created_at: new Date().toISOString(),
},
];

7
src/types/criteria.ts Normal file
View File

@ -0,0 +1,7 @@
export interface Criteria {
id: number;
name: string;
description: string;
prompt: string;
created_at: string;
}