diff --git a/src/_temp_types/projects.ts b/src/_temp_types/projects.ts index e5619bd..a10dfb3 100644 --- a/src/_temp_types/projects.ts +++ b/src/_temp_types/projects.ts @@ -5,7 +5,7 @@ export type ProjectRequirement = { attribute: number; operator: RequirementOperator; // The number of students with this attribute required as described by the RequirementOperator - value: number; + subject: number; }; export enum RequirementOperator { @@ -25,8 +25,7 @@ export enum RequirementOperator { export type Project = { id: number; name: string; - // Specifies the number of teams that can work on this project - numberOfTeams: number; + number_of_teams: number; // Specifies the number of teams that can work on this project requirements?: ProjectRequirement[]; }; diff --git a/src/app/(app)/course/[courseId]/project-sets/[projectSetId]/(components)/ProjectRequirementsTable.tsx b/src/app/(app)/course/[courseId]/project-sets/[projectSetId]/(components)/ProjectRequirementsTable.tsx new file mode 100644 index 0000000..cca0bb7 --- /dev/null +++ b/src/app/(app)/course/[courseId]/project-sets/[projectSetId]/(components)/ProjectRequirementsTable.tsx @@ -0,0 +1,106 @@ +'use client' + +import {DataTable} from "@/components/ui/data-table" +import {Text} from "@/components/ui/text" +import {ProjectRequirement, RequirementOperator} from "@/_temp_types/projects" +import {ColumnDef} from "@tanstack/react-table" +import {DataTableColumnHeader} from "@/components/ui/data-table-column-header" +import { + useProjectsContext, +} from "@/app/(app)/course/[courseId]/project-sets/[projectSetId]/(hooks)" +import {toast} from "@/hooks/use-toast" +import {Button} from "@/components/ui/button" +import {useState} from "react" +import {Pencil1Icon, ExitIcon} from "@radix-ui/react-icons" + +const persistedColumnDefs: ColumnDef[] = [ + { + accessorKey: "attribute", + header: ({column}) => ( + + ), + }, + { + accessorKey: "operator", + header: "Operator", + cell: ({row}) => { + const operator = row.original.operator + // Check if operator is a valid RequirementOperator + if (!Object.keys(RequirementOperator).includes(operator as RequirementOperator)) { + toast({ + title: `Invalid operator "${operator}" in Project Requirement.`, + variant: "destructive", + }) + return null + } + return RequirementOperator[operator as string as keyof typeof RequirementOperator] + }, + }, + { + accessorKey: "subject", + header: "Value", + }, +] + +export const ProjectRequirementsTable = () => { + const columns = persistedColumnDefs + + const {currentProject} = useProjectsContext() + // TODO: Implement edit mode + const [isEditing, setIsEditing] = useState(false) + + + // TODO: Implement conversion of Attribute and Attribute Value. + return ( +
+ {currentProject ? <> +
+
+ + {currentProject.name} + +
+ {/* TODO: Implement edit mode */} + +
+
+
+ {/* TODO: Implement edit mode */} + + This project can be completed + by {currentProject.number_of_teams} team{currentProject.number_of_teams > 1 && 's'}. + +
+
+
+
+ + Requirements + + {isEditing && } +
+
+ + columns={columns} + data={currentProject?.requirements ?? []} + /> +
+
+ : ( +
+ No project found. +
+ )} +
) +} diff --git a/src/app/(app)/course/[courseId]/project-sets/[projectSetId]/(components)/index.tsx b/src/app/(app)/course/[courseId]/project-sets/[projectSetId]/(components)/index.tsx index 876473e..2c687cd 100644 --- a/src/app/(app)/course/[courseId]/project-sets/[projectSetId]/(components)/index.tsx +++ b/src/app/(app)/course/[courseId]/project-sets/[projectSetId]/(components)/index.tsx @@ -1,3 +1,4 @@ export {ProjectSetSelect, type ProjectSetSelectProps} from './ProjectSetSelect' export {SidebarProjectList} from './SidebarProjectList' +export {ProjectRequirementsTable} from './ProjectRequirementsTable' export {ProjectSetSidebar} from './ProjectSetSidebar' diff --git a/src/app/(app)/course/[courseId]/project-sets/[projectSetId]/page.tsx b/src/app/(app)/course/[courseId]/project-sets/[projectSetId]/page.tsx index c6e177d..9fc6cd8 100644 --- a/src/app/(app)/course/[courseId]/project-sets/[projectSetId]/page.tsx +++ b/src/app/(app)/course/[courseId]/project-sets/[projectSetId]/page.tsx @@ -2,6 +2,7 @@ import {toast} from "@/hooks/use-toast" import {type ApiTeamSetTemplate} from "@/_temp_types/api/teams" import PageView from "@/components/views/Page" import { + ProjectRequirementsTable, ProjectSetSidebar, } from "./(components)" import {ProjectsProvider, ProjectSearchProvider} from "./(hooks)" @@ -38,7 +39,13 @@ const ProjectSetPage = async ({params: {courseId, projectSetId}}: ProjectPageTyp > - +
+
+ +
+ +
+
diff --git a/src/app/(app)/course/[courseId]/students/(table)/columns.tsx b/src/app/(app)/course/[courseId]/students/(table)/columns.tsx index 7f12853..c2bc01d 100644 --- a/src/app/(app)/course/[courseId]/students/(table)/columns.tsx +++ b/src/app/(app)/course/[courseId]/students/(table)/columns.tsx @@ -4,7 +4,7 @@ import { Student } from "@/_temp_types/student" import { ColumnDef } from "@tanstack/react-table" import { Text } from "@/components/ui/text" import { Badge } from "@/components/ui/badge" -import { DataTableColumnHeader } from "@/components/ui/table-column-header" +import { DataTableColumnHeader } from "@/components/ui/data-table-column-header" type SectionFilterValue = string[]; diff --git a/src/components/ui/table-column-header.tsx b/src/components/ui/table-column-header.tsx deleted file mode 100644 index 364a55a..0000000 --- a/src/components/ui/table-column-header.tsx +++ /dev/null @@ -1,95 +0,0 @@ -"use client" - -import { - ArrowDownIcon, - ArrowUpIcon, - CaretSortIcon, - ResetIcon, -} from "@radix-ui/react-icons" -import { Column } from "@tanstack/react-table" - -import { Button } from "@/components/ui/button" -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu" - -import { cn } from "@/lib/utils" -import React from "react" - -interface DataTableColumnHeaderProps - extends React.HTMLAttributes { - column: Column; - title: string; - hasDropDownMenu?: boolean; -} - -export function DataTableColumnHeader({ - column, - title, - className, - hasDropDownMenu = true, -}: DataTableColumnHeaderProps) { - if (!column.getCanSort()) { - return
{title}
- } - - return ( -
- {hasDropDownMenu ? ( - - - - - - column.toggleSorting(false)}> - - Asc - - column.toggleSorting(true)}> - - Desc - - - column.clearSorting()}> - - Reset - - - - ) : ( - - )} -
- ) -} diff --git a/src/components/ui/table-pagination.tsx b/src/components/ui/table-pagination.tsx deleted file mode 100644 index 006787b..0000000 --- a/src/components/ui/table-pagination.tsx +++ /dev/null @@ -1,102 +0,0 @@ -"use client" - -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" -import { Text } from "./text" - -interface DataTablePaginationProps { - table: Table; -} - -export function DataTablePagination({ - table, -}: DataTablePaginationProps) { - return ( -
-
- {table.getFilteredSelectedRowModel().rows.length} of{" "} - {table.getFilteredRowModel().rows.length} row(s) selected. -
-
-
- - Row per page - - -
- - Page {table.getState().pagination.pageIndex + 1} of{" "} - {table.getPageCount()} - -
- - - - -
-
-
- ) -}