Skip to content

Commit

Permalink
Merge pull request #57 from ubc-biztech/sort-reg-tables
Browse files Browse the repository at this point in the history
  • Loading branch information
liuisaac authored Nov 13, 2024
2 parents 884d708 + 3ae999d commit 6754852
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 34 deletions.
45 changes: 45 additions & 0 deletions src/components/RegistrationTable/SortableHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React, { useState } from "react";
import { Column } from "@tanstack/react-table";
import { CircleChevronDown, CircleChevronUp } from "lucide-react";

interface SortableHeaderProps<T> {
column: Column<T, unknown>;
title: string;
}

export const SortableHeader = <T,>({
column,
title,
}: SortableHeaderProps<T>) => {
const [hover, setHover] = useState(false);
return (
<div
className={`group cursor-pointer select-none ${
column.getIsSorted() === "asc" ||
column.getIsSorted() === "desc"
? "text-black"
: "hover:text-black text-white"
} transition-colors duration-200 ease-in-out inline-flex gap-1`}
onClick={column.getToggleSortingHandler()}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
>
{title}
<div
className={`${
column.getIsSorted() === "asc"
? "text-biztech-green" // Color for ascending sort
: column.getIsSorted() === "desc"
? "text-light-red" // Color for descending sort
: "text-black" // Default color for unsorted
}`}
>
{(column.getIsSorted() === "asc" ||
(hover && column.getIsSorted() != "desc")) && (
<CircleChevronUp />
)}
{column.getIsSorted() === "desc" && <CircleChevronDown />}
</div>
</div>
);
};
88 changes: 56 additions & 32 deletions src/components/RegistrationTable/columns.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
"use client"
"use client";

import { ColumnDef } from "@tanstack/react-table"
import { Checkbox } from "@/components/ui/checkbox"
import { TableCell } from "./TableCell"
import { EditCell } from "./EditCell"
import { ColumnDef } from "@tanstack/react-table";
import { Checkbox } from "@/components/ui/checkbox";
import { TableCell } from "./TableCell";
import { EditCell } from "./EditCell";
import { SortableHeader } from "./SortableHeader";

export type Attendee = {
id: string
regStatus: string
appStatus: string
firstName: string
lastName: string
email: string
points: number
studentNumber: string
faculty: string
[key: string]: any // This allows for dynamic properties
}
id: string;
regStatus: string;
appStatus: string;
firstName: string;
lastName: string;
email: string;
points: number;
studentNumber: string;
faculty: string;
[key: string]: any; // This allows for dynamic properties
};

export type ColumnMeta = {
type?: "select" | "number";
options?: { value: string; label: string }[];
}
};

export const columns: ColumnDef<Attendee>[] = [
{
id: 'edit',
id: "edit",
size: 30,
cell: ({ row, table }) => <EditCell row={row} table={table} />,
},
Expand All @@ -35,7 +36,9 @@ export const columns: ColumnDef<Attendee>[] = [
<div className="flex items-center">
<Checkbox
checked={table.getIsAllPageRowsSelected()}
onCheckedChange={(value: any) => table.toggleAllPageRowsSelected(!!value)}
onCheckedChange={(value: any) =>
table.toggleAllPageRowsSelected(!!value)
}
aria-label="Select all"
/>
</div>
Expand All @@ -45,17 +48,21 @@ export const columns: ColumnDef<Attendee>[] = [
<div className="flex items-center">
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value: any) => row.toggleSelected(!!value)}
onCheckedChange={(value: any) =>
row.toggleSelected(!!value)
}
aria-label="Select row"
/>
</div>
),
enableSorting: false,
enableSorting: true,
enableHiding: false,
},
{
accessorKey: "regStatus",
header: "Reg. Status",
header: ({ column }) => (
<SortableHeader title="Reg. Status" column={column} />
),
cell: TableCell,
meta: {
type: "select",
Expand All @@ -67,53 +74,70 @@ export const columns: ColumnDef<Attendee>[] = [
],
} as ColumnMeta,
size: 200,
enableSorting: true,
sortingFn: (rowA, rowB) => {
const order = ["Checked-In", "Registered", "Incomplete", "Cancelled"];
return (
order.indexOf(rowA.getValue("regStatus")) -
order.indexOf(rowB.getValue("regStatus"))
);
},
},
{
accessorKey: "appStatus",
header: "App. Status",
header: ({ column }) => (<SortableHeader title="App. Status" column={column} />),
cell: TableCell,
meta: {
type: "select",
options: [ // These values were inferred from the database
options: [
// These values were inferred from the database
{ value: "Accepted", label: "Accepted" },
{ value: "Reviewing", label: "Reviewing" },
{ value: "Waitlist", label: "Waitlist" },
{ value: "Rejected", label: "Rejected" },
],
} as ColumnMeta,
size: 200,
enableSorting: true,
sortingFn: (rowA, rowB) => {
const order = ["Accepted", "Reviewing", "Waitlist", "Rejected"];
return (
order.indexOf(rowA.getValue("appStatus")) -
order.indexOf(rowB.getValue("appStatus"))
);
},
},
{
accessorKey: "firstName",
header: "First Name",
header: ({ column }) => (<SortableHeader title="First Name" column={column} />),
cell: TableCell,
},
{
accessorKey: "lastName",
header: "Last Name",
header: ({ column }) => (<SortableHeader title="Last Name" column={column} />),
cell: TableCell,
},
{
accessorKey: "email",
header: "Email",
header: ({ column }) => (<SortableHeader title="Email" column={column} />),
cell: TableCell,
},
{
accessorKey: "points",
header: "Points",
header: ({ column }) => (<SortableHeader title="Points" column={column} />),
cell: TableCell,
meta: {
type: "number",
} as ColumnMeta,
},
{
accessorKey: "studentNumber",
header: "Student Number",
header: ({ column }) => (<SortableHeader title="Student Number" column={column} />),
cell: TableCell,
},
{
accessorKey: "faculty",
header: "Faculty",
header: ({ column }) => (<SortableHeader title="Faculty" column={column} />),
cell: TableCell,
}
]
},
];
5 changes: 3 additions & 2 deletions src/pages/admin/event/[eventId]/[year]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ import { ColumnDef } from "@tanstack/react-table";
import { GetServerSideProps } from "next";
import { fetchRegistrationData } from "@/lib/dbUtils";
import { Button } from "@/components/ui/button";
import { SortableHeader } from "@/components/RegistrationTable/SortableHeader";

// Dynamic columns
const dynamicColumns: ColumnDef<Attendee>[] = [
{
accessorKey: "dynamicField1",
header: "Dynamic Field 1",
header: ({ column }) => (<SortableHeader title="Dynamic Field 1" column={column} />),
},
{
accessorKey: "dynamicField2",
header: "Dynamic Field 2",
header: ({ column }) => (<SortableHeader title="Dynamic Field 2" column={column} />),
},
// Fetch dynamic columns from events DB - backend to do.
];
Expand Down

0 comments on commit 6754852

Please sign in to comment.