From d689e22dd81312f1eb28c38f70a2e99ae133076d Mon Sep 17 00:00:00 2001 From: Andy Chan Date: Sat, 13 Apr 2024 12:56:00 -0400 Subject: [PATCH] Add editing of table fields, significant refactoring This makes RowOpenAction obsolete with PrimaryTableCell. Dropdowns to be implemented at a later point. Lots of typing and further styling needed. --- compass/components/Table/Index.tsx | 56 +++++++++++-------- compass/components/Table/PrimaryTableCell.tsx | 22 ++++++++ compass/components/Table/RowOptionMenu.tsx | 2 +- compass/components/Table/TableCell.tsx | 17 ++++++ compass/components/page/Drawer.tsx | 2 +- 5 files changed, 73 insertions(+), 26 deletions(-) create mode 100644 compass/components/Table/PrimaryTableCell.tsx create mode 100644 compass/components/Table/TableCell.tsx diff --git a/compass/components/Table/Index.tsx b/compass/components/Table/Index.tsx index d498ed8..9c7329b 100644 --- a/compass/components/Table/Index.tsx +++ b/compass/components/Table/Index.tsx @@ -12,12 +12,14 @@ import { sortingFns, useReactTable, } from "@tanstack/react-table"; -import { ChangeEvent, useState, useEffect, FunctionComponent } from "react"; +import { ChangeEvent, useState, useEffect, FunctionComponent, useRef, ChangeEventHandler, Key } from "react"; import { RowOptionMenu } from "./RowOptionMenu"; import { RowOpenAction } from "./RowOpenAction"; import { TableAction } from "./TableAction"; import { Bars2Icon, AtSymbolIcon, HashtagIcon, ArrowDownCircleIcon } from "@heroicons/react/24/solid"; import { rankItem } from "@tanstack/match-sorter-utils"; +import { TableCell } from "./TableCell"; +import { PrimaryTableCell } from "./PrimaryTableCell"; const usersExample = usersImport as unknown as User[]; @@ -80,19 +82,19 @@ export const Table = () => { }), columnHelper.accessor("username", { header: () => <> Username, - cell: (info) => , + cell: PrimaryTableCell, }), columnHelper.accessor("role", { header: () => <> Role, - cell: (info) => info.renderValue(), + cell: TableCell, }), columnHelper.accessor("email", { header: () => <> Email, - cell: (info) => info.renderValue(), + cell: TableCell, }), columnHelper.accessor("program", { header: () => <> Program, - cell: (info) => info.renderValue(), + cell: TableCell, }), ]; @@ -105,6 +107,11 @@ export const Table = () => { setQuery(String(target.value)); } + const handleCellChange = (e: ChangeEvent, key: Key) => { + const target = e.target as HTMLInputElement; + console.log(key); + } + // TODO: Filtering // TODO: Sorting @@ -121,6 +128,21 @@ export const Table = () => { globalFilterFn: fuzzyFilter, getCoreRowModel: getCoreRowModel(), getFilteredRowModel: getFilteredRowModel(), + meta: { + updateData: (rowIndex: number, columnId: string, value: string) => { + setData(old => + old.map((row, index) => { + if (index === rowIndex) { + return { + ...old[rowIndex], + [columnId]: value, + }; + } + return row; + }) + ); + } + } }); return ( @@ -163,7 +185,11 @@ export const Table = () => { key={row.id} > {row.getVisibleCells().map((cell, i) => ( - + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + ))} ); @@ -173,21 +199,3 @@ export const Table = () => { ) } - -type TableCellProps = { - cell: Cell; - //i: number; -} - -const TableCell: FunctionComponent = ({ cell }) => { - return ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - ) -} diff --git a/compass/components/Table/PrimaryTableCell.tsx b/compass/components/Table/PrimaryTableCell.tsx new file mode 100644 index 0000000..47e87e0 --- /dev/null +++ b/compass/components/Table/PrimaryTableCell.tsx @@ -0,0 +1,22 @@ +/* An extension of TableCell.tsx that includes an "open" button and the drawer. +For cells in the "primary" (or first) column of the table. */ +import Drawer from "@/components/page/Drawer"; +import { TableCell } from "./TableCell"; +import { SetStateAction, useState } from "react"; + +export const PrimaryTableCell = ({ getValue, row, column, table }) => { + const [pageContent, setPageContent] = useState("") + + const handleDrawerContentChange = (newContent: SetStateAction) => { + setPageContent(newContent); + }; + + return ( +
+ + + {pageContent} + +
+ ); +}; diff --git a/compass/components/Table/RowOptionMenu.tsx b/compass/components/Table/RowOptionMenu.tsx index 58c5284..d383b20 100644 --- a/compass/components/Table/RowOptionMenu.tsx +++ b/compass/components/Table/RowOptionMenu.tsx @@ -16,7 +16,7 @@ export const RowOptionMenu = ( { onDelete, onHide } ) => { <>
*]:rounded" + (!menuOpen ? " invisible" : "")} + className={"justify-start border border-gray-200 shadow-lg flex flex-col absolute bg-white w-auto p-2 rounded [&>*]:rounded z-10" + (!menuOpen ? " invisible" : "")} > { /* handle open */ }} /> diff --git a/compass/components/Table/TableCell.tsx b/compass/components/Table/TableCell.tsx new file mode 100644 index 0000000..a84e40f --- /dev/null +++ b/compass/components/Table/TableCell.tsx @@ -0,0 +1,17 @@ +/* A lone table cell. Passed in for "cell" for a TanStack Table. */ +import { useState, useEffect } from "react"; + +export const TableCell = ({ getValue, row, column, table }) => { + const initialValue = getValue(); + const [value, setValue] = useState(initialValue); + + useEffect(() => { + setValue(initialValue); + }, [initialValue]); + + const onBlur = () => { + table.options.meta?.updateData(row.index, column.id, value); + }; + + return setValue(e.target.value)} onBlur={onBlur} />; +}; diff --git a/compass/components/page/Drawer.tsx b/compass/components/page/Drawer.tsx index 91118f3..a60c447 100644 --- a/compass/components/page/Drawer.tsx +++ b/compass/components/page/Drawer.tsx @@ -26,7 +26,7 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita setEditContent(event.target.value); }; - const drawerClassName = `fixed top-0 right-0 w-1/2 h-full bg-white transform ease-in-out duration-300 ${ + const drawerClassName = `fixed top-0 right-0 w-1/2 h-full bg-white transform ease-in-out duration-300 z-20 ${ isOpen ? "translate-x-0 shadow-xl" : "translate-x-full" }`;