Merge branch 'admin-GEN-57-all-together-now' into varun-admin-GEN-59-page

i hope

Co-Authored-By: Varun Murlidhar <vmurlidhar@unc.edu>
This commit is contained in:
Andy Chan 2024-04-20 14:49:50 -04:00
commit 9ba65213a9
10 changed files with 229 additions and 39 deletions

View File

@ -2,18 +2,25 @@
import usersImport from "./users.json"; import usersImport from "./users.json";
import { import {
Cell,
ColumnDef, ColumnDef,
Row,
createColumnHelper, createColumnHelper,
flexRender, flexRender,
getCoreRowModel, getCoreRowModel,
getFilteredRowModel,
sortingFns,
useReactTable, useReactTable,
} from "@tanstack/react-table"; } from "@tanstack/react-table";
import { useState, useEffect } from "react"; import { ChangeEvent, useState, useEffect, FunctionComponent, useRef, ChangeEventHandler, Key } from "react";
import { RowOptionMenu } from "./RowOptionMenu"; import { RowOptionMenu } from "./RowOptionMenu";
import { RowOpenAction } from "./RowOpenAction"; import { RowOpenAction } from "./RowOpenAction";
import { TableAction } from "./TableAction"; import { TableAction } from "./TableAction";
import { AtSymbolIcon, Bars2Icon } from "@heroicons/react/24/solid"; import { AtSymbolIcon, Bars2Icon, ArrowDownCircleIcon, PlusIcon } from "@heroicons/react/24/solid";
import TagsInput from "../TagsInput/Index"; import TagsInput from "../TagsInput/Index";
import { rankItem } from "@tanstack/match-sorter-utils";
import { TableCell } from "./TableCell";
import { PrimaryTableCell } from "./PrimaryTableCell";
const usersExample = usersImport as unknown as User[]; const usersExample = usersImport as unknown as User[];
@ -26,12 +33,49 @@ type User = {
program: "domestic" | "economic" | "community"; program: "domestic" | "economic" | "community";
experience: number; experience: number;
group?: string; group?: string;
visible: boolean;
}; };
// For search
const fuzzyFilter = (row: Row<any>, columnId: string, value: any, addMeta: (meta: any) => void) => {
// Rank the item
const itemRank = rankItem(row.getValue(columnId), value)
// Store the ranking info
addMeta(itemRank)
// Return if the item should be filtered in/out
return itemRank.passed
}
export const Table = () => { export const Table = () => {
const columnHelper = createColumnHelper<User>(); const columnHelper = createColumnHelper<User>();
useEffect(() => {
const sortedUsers = [...usersExample].sort((a, b) => (a.visible === b.visible ? 0 : a.visible ? -1 : 1));
setData(sortedUsers);
}, []);
const deleteUser = (userId) => {
console.log(data);
setData(currentData => currentData.filter(user => user.id !== userId));
};
const hideUser = (userId: number) => {
console.log(`Toggling visibility for user with ID: ${userId}`);
setData(currentData => {
const newData = currentData.map(user => {
if (user.id === userId) {
return { ...user, visible: !user.visible };
}
return user;
}).sort((a, b) => a.visible === b.visible ? 0 : a.visible ? -1 : 1);
console.log(newData);
return newData;
});
};
const [presetOptions, setPresetOptions] = useState(["administrator", "volunteer", "employee"]); const [presetOptions, setPresetOptions] = useState(["administrator", "volunteer", "employee"]);
const [tagColors, setTagColors] = useState(new Map()); const [tagColors, setTagColors] = useState(new Map());
@ -47,13 +91,14 @@ export const Table = () => {
const columns = [ const columns = [
columnHelper.display({ columnHelper.display({
id: "options", id: "options",
cell: props => <RowOptionMenu /> cell: props => <RowOptionMenu onDelete={() => deleteUser(props.row.original.id)} onHide={() => hideUser(props.row.original.id)} />
}), }),
columnHelper.accessor("username", { columnHelper.accessor("username", {
header: () => <><Bars2Icon className="inline align-top h-4" /> Username</>, header: () => <><Bars2Icon className="inline align-top h-4" /> Username</>,
cell: (info) => <RowOpenAction title={info.getValue()} rowData={info.row.original} onRowUpdate={handleRowUpdate} />, cell: (info) => <RowOpenAction title={info.getValue()} rowData={info.row.original} onRowUpdate={handleRowUpdate} />,
}), }),
columnHelper.accessor("role", { columnHelper.accessor("role", {
header: () => <><ArrowDownCircleIcon className="inline align-top h-4" /> Role</>,
cell: (info) => <TagsInput presetValue={info.getValue() } cell: (info) => <TagsInput presetValue={info.getValue() }
presetOptions={presetOptions} presetOptions={presetOptions}
setPresetOptions={setPresetOptions} setPresetOptions={setPresetOptions}
@ -63,15 +108,35 @@ export const Table = () => {
}), }),
columnHelper.accessor("email", { columnHelper.accessor("email", {
header: () => <><AtSymbolIcon className="inline align-top h-4" /> Email</>, header: () => <><AtSymbolIcon className="inline align-top h-4" /> Email</>,
cell: (info) => info.renderValue(), cell: TableCell,
}), }),
columnHelper.accessor("program", { columnHelper.accessor("program", {
header: () => <><ArrowDownCircleIcon className="inline align-top h-4" /> Program</>,
cell: (info) => info.renderValue(), cell: (info) => info.renderValue(),
}), }),
]; ];
const [data, setData] = useState<User[]>([...usersExample]); const [data, setData] = useState<User[]>([...usersExample]);
const addUser = () => {
setData([...data, {}]);
}
// Searching
const [query, setQuery] = useState("");
const handleSearchChange = (e: ChangeEvent) => {
const target = e.target as HTMLInputElement;
setQuery(String(target.value));
}
const handleCellChange = (e: ChangeEvent, key: Key) => {
const target = e.target as HTMLInputElement;
console.log(key);
}
// TODO: Filtering
// TODO: Sorting
// added this fn for editing rows // added this fn for editing rows
const handleRowUpdate = (updatedRow: User) => { const handleRowUpdate = (updatedRow: User) => {
const dataIndex = data.findIndex((row) => row.id === updatedRow.id); const dataIndex = data.findIndex((row) => row.id === updatedRow.id);
@ -85,7 +150,31 @@ export const Table = () => {
const table = useReactTable({ const table = useReactTable({
columns, columns,
data, data,
filterFns: {
fuzzy: fuzzyFilter
},
state: {
globalFilter: query,
},
onGlobalFilterChange: setQuery,
globalFilterFn: fuzzyFilter,
getCoreRowModel: getCoreRowModel(), 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;
})
);
}
}
}); });
const handleRowData = (row: any) => { const handleRowData = (row: any) => {
@ -101,7 +190,7 @@ export const Table = () => {
return ( return (
<div className="flex flex-col"> <div className="flex flex-col">
<div className="flex flex-row justify-end"> <div className="flex flex-row justify-end">
<TableAction /> <TableAction query={query} handleChange={handleSearchChange} />
</div> </div>
<table className="w-full text-xs text-left rtl:text-right"> <table className="w-full text-xs text-left rtl:text-right">
<thead className="text-xs text-gray-500 capitalize"> <thead className="text-xs text-gray-500 capitalize">
@ -127,24 +216,40 @@ export const Table = () => {
</tr> </tr>
))} ))}
</thead> </thead>
<tbody className=""> <tbody>
{table.getRowModel().rows.map((row) => ( {table.getRowModel().rows.map((row) => {
<tr className="text-gray-800 border-y lowercase hover:bg-gray-50" key={row.id}> // Individual row
{row.getVisibleCells().map((cell, i) => ( const isUserVisible = row.original.visible;
<td const rowClassNames = `text-gray-800 border-y lowercase hover:bg-gray-50 ${!isUserVisible ? "bg-gray-200 text-gray-500" : ""}`;
className={ return (
"p-2 " <tr
+ ((1 < i && i < columns.length - 1) ? "border-x" : "") className={rowClassNames}
+ ((i === 0) ? "text-center px-0" : "") key={row.id}
} >
key={cell.id}> {row.getVisibleCells().map((cell, i) => (
{flexRender(cell.column.columnDef.cell, cell.getContext())} <td key={cell.id}
</td> className={"[&:nth-child(n+3)]:border-x relative first:text-left first:px-0 last:border-none"}
))} >
</tr> {flexRender(cell.column.columnDef.cell, cell.getContext())}
))} </td>
))}
</tr>
);
})}
</tbody> </tbody>
<tfoot>
<tr>
<td className="p-3 border-y border-gray-200 text-gray-600 hover:bg-gray-50" colSpan={100} onClick={addUser}>
<span className="flex ml-1 text-gray-500">
<PlusIcon className="inline h-4 mr-1" />
New
</span>
</td>
</tr>
</tfoot>
</table> </table>
</div> </div>
) )
} }

View File

@ -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<string>) => {
setPageContent(newContent);
};
return (
<div className="font-semibold group">
<TableCell getValue={getValue} row={row} column={column} table={table} />
<span className="absolute right-1 top-1">
<Drawer title={getValue()} editableContent={pageContent} onSave={handleDrawerContentChange}>{pageContent}</Drawer>
</span>
</div>
);
};

View File

@ -0,0 +1,10 @@
import React from 'react';
import { TrashIcon, DocumentDuplicateIcon, ArrowUpRightIcon, EyeSlashIcon } from "@heroicons/react/24/solid";
export const RowOption = ({ icon: Icon, label, onClick }) => {
return (
<button onClick={onClick} className="hover:bg-gray-100 flex items-center gap-2 p-2 w-full">
<Icon className="inline h-4" /> {label}
</button>
);
};

View File

@ -1,9 +1,10 @@
//delete, duplicate, open //delete, duplicate, open
import { TrashIcon, DocumentDuplicateIcon, ArrowUpRightIcon, EllipsisVerticalIcon } from "@heroicons/react/24/solid"; import { TrashIcon, DocumentDuplicateIcon, ArrowUpRightIcon, EllipsisVerticalIcon, EyeSlashIcon } from "@heroicons/react/24/solid";
import Button from "../Button";
import { useState, useEffect, useRef } from "react"; import { useState, useEffect, useRef } from "react";
import { RowOption } from "./RowOption";
export const RowOptionMenu = ( { onDelete, onHide } ) => {
export const RowOptionMenu = () => {
const [menuOpen, setMenuOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false);
const openMenu = () => setMenuOpen(true); const openMenu = () => setMenuOpen(true);
const closeMenu = () => setMenuOpen(false); const closeMenu = () => setMenuOpen(false);
@ -15,12 +16,12 @@ export const RowOptionMenu = () => {
<> <>
<button className="align-center" onClick={() => setMenuOpen(!menuOpen)}><EllipsisVerticalIcon className="h-4"/></button> <button className="align-center" onClick={() => setMenuOpen(!menuOpen)}><EllipsisVerticalIcon className="h-4"/></button>
<div <div
className={"absolute text-left bg-white w-auto p-1 rounded [&>*]:p-1 [&>*]:px-5 [&>*]: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" : "")}
> >
<div className="hover:bg-gray-100"><TrashIcon className="inline h-4"/> Delete</div> <RowOption icon={TrashIcon} label="Delete" onClick={onDelete} />
<div className="hover:bg-gray-100"><DocumentDuplicateIcon className="inline h-4"/> Duplicate</div> <RowOption icon={ArrowUpRightIcon} label="Open" onClick={() => { /* handle open */ }} />
<div className="hover:bg-gray-100"><ArrowUpRightIcon className="inline h-4"/> Open</div> <RowOption icon={EyeSlashIcon} label="Hide" onClick={ onHide } />
</div> </div>
</> </>
); );
} }

View File

@ -1,9 +1,16 @@
/** The actions (Filter, Sort, Search) at the top of the table. */
import { MagnifyingGlassIcon } from "@heroicons/react/24/solid"; import { MagnifyingGlassIcon } from "@heroicons/react/24/solid";
import { useRef, useState } from "react"; import { ChangeEventHandler, Dispatch, FunctionComponent, SetStateAction, useRef, useState } from "react";
export const TableAction = () => { type TableActionProps = {
query: string
handleChange: ChangeEventHandler<HTMLInputElement>
}
export const TableAction: FunctionComponent<TableActionProps> = ({query, handleChange}) => {
const searchInput = useRef<HTMLInputElement>(null); const searchInput = useRef<HTMLInputElement>(null);
const [searchActive, setSearchActive] = useState(false); const [searchActive, setSearchActive] = useState(false);
const activateSearch = () => { const activateSearch = () => {
setSearchActive(true); setSearchActive(true);
if (searchInput.current === null) { return; } if (searchInput.current === null) { return; }
@ -30,7 +37,10 @@ export const TableAction = () => {
className={"outline-none transition-all duration-300 " + (searchActive ? "w-48" : "w-0")} className={"outline-none transition-all duration-300 " + (searchActive ? "w-48" : "w-0")}
type="text" type="text"
name="search" name="search"
placeholder="Type to search..." /> placeholder="Type to search..."
value={query ?? ""}
onChange={handleChange}
/>
</div> </div>
); );
}; };

View File

@ -0,0 +1,21 @@
/* 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);
};
// focus:border focus:border-gray-200
const className = "w-full p-3 bg-inherit rounded-md outline-none border border-transparent relative "
+ "focus:shadow-md focus:border-gray-200 focus:bg-white focus:z-20 focus:p-4 focus:-m-1 "
+ "focus:w-[calc(100%+0.5rem)]";
return <input className={className} value={value} onChange={e => setValue(e.target.value)} onBlur={onBlur} />;
};

View File

@ -1 +1 @@
[{"id":0,"created_at":1711482132230,"username":"Bo_Pfeffer","role":"ADMIN","email":"Bo.Pfeffer@gmail.com","program":"DOMESTIC","experience":2,"group":""},{"id":1,"created_at":1711482132231,"username":"Marianna_Heathcote76","role":"ADMIN","email":"Marianna_Heathcote14@yahoo.com","program":"DOMESTIC","experience":1,"group":""},{"id":2,"created_at":1711482132231,"username":"Queenie_Schroeder","role":"VOLUNTEER","email":"Queenie_Schroeder@yahoo.com","program":"COMMUNITY","experience":5,"group":""},{"id":3,"created_at":1711482132231,"username":"Arne.Bode","role":"VOLUNTEER","email":"Arne.Bode@hotmail.com","program":"DOMESTIC","experience":3,"group":""},{"id":4,"created_at":1711482132231,"username":"Maia.Zulauf9","role":"ADMIN","email":"Maia_Zulauf@gmail.com","program":"DOMESTIC","experience":5,"group":""},{"id":5,"created_at":1711482132231,"username":"River_Bauch","role":"EMPLOYEE","email":"River.Bauch@yahoo.com","program":"ECONOMIC","experience":2,"group":""},{"id":6,"created_at":1711482132231,"username":"Virgil.Hilll","role":"VOLUNTEER","email":"Virgil.Hilll@yahoo.com","program":"ECONOMIC","experience":3,"group":""},{"id":7,"created_at":1711482132231,"username":"Bridget_Cartwright","role":"ADMIN","email":"Bridget_Cartwright@yahoo.com","program":"ECONOMIC","experience":3,"group":""},{"id":8,"created_at":1711482132231,"username":"Glennie_Keebler64","role":"EMPLOYEE","email":"Glennie_Keebler60@yahoo.com","program":"DOMESTIC","experience":2,"group":""},{"id":9,"created_at":1711482132232,"username":"Orin.Jenkins53","role":"EMPLOYEE","email":"Orin.Jenkins@gmail.com","program":"ECONOMIC","experience":1,"group":""},{"id":10,"created_at":1711482132232,"username":"Zachery.Rosenbaum","role":"ADMIN","email":"Zachery.Rosenbaum@hotmail.com","program":"COMMUNITY","experience":3,"group":""},{"id":11,"created_at":1711482132232,"username":"Phoebe.Ziemann","role":"EMPLOYEE","email":"Phoebe_Ziemann92@gmail.com","program":"COMMUNITY","experience":2,"group":""},{"id":12,"created_at":1711482132232,"username":"Bradford_Conroy53","role":"VOLUNTEER","email":"Bradford_Conroy94@hotmail.com","program":"COMMUNITY","experience":2,"group":""},{"id":13,"created_at":1711482132232,"username":"Florine_Strosin55","role":"VOLUNTEER","email":"Florine.Strosin29@hotmail.com","program":"ECONOMIC","experience":1,"group":""},{"id":14,"created_at":1711482132232,"username":"Constance.Doyle59","role":"EMPLOYEE","email":"Constance_Doyle@hotmail.com","program":"DOMESTIC","experience":3,"group":""},{"id":15,"created_at":1711482132232,"username":"Chauncey_Lockman","role":"ADMIN","email":"Chauncey_Lockman@yahoo.com","program":"DOMESTIC","experience":5,"group":""},{"id":16,"created_at":1711482132232,"username":"Esther_Wuckert-Larson26","role":"EMPLOYEE","email":"Esther_Wuckert-Larson@gmail.com","program":"ECONOMIC","experience":0,"group":""},{"id":17,"created_at":1711482132232,"username":"Jewel.Kunde","role":"VOLUNTEER","email":"Jewel_Kunde29@gmail.com","program":"ECONOMIC","experience":5,"group":""},{"id":18,"created_at":1711482132232,"username":"Hildegard_Parker92","role":"ADMIN","email":"Hildegard_Parker74@yahoo.com","program":"ECONOMIC","experience":2,"group":""},{"id":19,"created_at":1711482132232,"username":"Jordane.Lakin2","role":"ADMIN","email":"Jordane_Lakin@hotmail.com","program":"COMMUNITY","experience":1,"group":""}] [{"id":0,"created_at":1711482132230,"username":"Bo_Pfeffer","role":"ADMIN","email":"Bo.Pfeffer@gmail.com","program":"DOMESTIC","experience":2,"group":"", "visible": true},{"id":1,"created_at":1711482132231,"username":"Marianna_Heathcote76","role":"ADMIN","email":"Marianna_Heathcote14@yahoo.com","program":"DOMESTIC","experience":1,"group":"", "visible": true},{"id":2,"created_at":1711482132231,"username":"Queenie_Schroeder","role":"VOLUNTEER","email":"Queenie_Schroeder@yahoo.com","program":"COMMUNITY","experience":5,"group":"", "visible": true},{"id":3,"created_at":1711482132231,"username":"Arne.Bode","role":"VOLUNTEER","email":"Arne.Bode@hotmail.com","program":"DOMESTIC","experience":3,"group":"", "visible": true},{"id":4,"created_at":1711482132231,"username":"Maia.Zulauf9","role":"ADMIN","email":"Maia_Zulauf@gmail.com","program":"DOMESTIC","experience":5,"group":"", "visible": true},{"id":5,"created_at":1711482132231,"username":"River_Bauch","role":"EMPLOYEE","email":"River.Bauch@yahoo.com","program":"ECONOMIC","experience":2,"group":"", "visible": true},{"id":6,"created_at":1711482132231,"username":"Virgil.Hilll","role":"VOLUNTEER","email":"Virgil.Hilll@yahoo.com","program":"ECONOMIC","experience":3,"group":"", "visible": true},{"id":7,"created_at":1711482132231,"username":"Bridget_Cartwright","role":"ADMIN","email":"Bridget_Cartwright@yahoo.com","program":"ECONOMIC","experience":3,"group":"", "visible": true},{"id":8,"created_at":1711482132231,"username":"Glennie_Keebler64","role":"EMPLOYEE","email":"Glennie_Keebler60@yahoo.com","program":"DOMESTIC","experience":2,"group":"", "visible": true},{"id":9,"created_at":1711482132232,"username":"Orin.Jenkins53","role":"EMPLOYEE","email":"Orin.Jenkins@gmail.com","program":"ECONOMIC","experience":1,"group":"", "visible": true},{"id":10,"created_at":1711482132232,"username":"Zachery.Rosenbaum","role":"ADMIN","email":"Zachery.Rosenbaum@hotmail.com","program":"COMMUNITY","experience":3,"group":"", "visible": true},{"id":11,"created_at":1711482132232,"username":"Phoebe.Ziemann","role":"EMPLOYEE","email":"Phoebe_Ziemann92@gmail.com","program":"COMMUNITY","experience":2,"group":"", "visible": true},{"id":12,"created_at":1711482132232,"username":"Bradford_Conroy53","role":"VOLUNTEER","email":"Bradford_Conroy94@hotmail.com","program":"COMMUNITY","experience":2,"group":"", "visible": true},{"id":13,"created_at":1711482132232,"username":"Florine_Strosin55","role":"VOLUNTEER","email":"Florine.Strosin29@hotmail.com","program":"ECONOMIC","experience":1,"group":"", "visible": true},{"id":14,"created_at":1711482132232,"username":"Constance.Doyle59","role":"EMPLOYEE","email":"Constance_Doyle@hotmail.com","program":"DOMESTIC","experience":3,"group":"", "visible": true},{"id":15,"created_at":1711482132232,"username":"Chauncey_Lockman","role":"ADMIN","email":"Chauncey_Lockman@yahoo.com","program":"DOMESTIC","experience":5,"group":"", "visible": true},{"id":16,"created_at":1711482132232,"username":"Esther_Wuckert-Larson26","role":"EMPLOYEE","email":"Esther_Wuckert-Larson@gmail.com","program":"ECONOMIC","experience":0,"group":"", "visible": true},{"id":17,"created_at":1711482132232,"username":"Jewel.Kunde","role":"VOLUNTEER","email":"Jewel_Kunde29@gmail.com","program":"ECONOMIC","experience":5,"group":"", "visible": true},{"id":18,"created_at":1711482132232,"username":"Hildegard_Parker92","role":"ADMIN","email":"Hildegard_Parker74@yahoo.com","program":"ECONOMIC","experience":2,"group":"", "visible": true},{"id":19,"created_at":1711482132232,"username":"Jordane.Lakin2","role":"ADMIN","email":"Jordane_Lakin@hotmail.com","program":"COMMUNITY","experience":1,"group":"", "visible": true}]

View File

@ -58,14 +58,14 @@ const Drawer: FunctionComponent<DrawerProps> = ({ title, children, onSave, edita
setIsFull(!isFull); setIsFull(!isFull);
} }
} }
const toggleDrawerFullScreen = () => setIsFull(!isFull); const toggleDrawerFullScreen = () => setIsFull(!isFull);
const toggleFavorite = () => setIsFavorite(!isFavorite); const toggleFavorite = () => setIsFavorite(!isFavorite);
const drawerClassName = `fixed top-0 right-0 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" isOpen ? "translate-x-0 shadow-xl" : "translate-x-full"
} ${isFull ? "w-full" : "w-1/2"}`; } ${isFull ? "w-full" : "w-1/2"}`;
const iconComponent = isFull ? <ArrowsPointingInIcon className="h-5 w-5" /> : <ArrowsPointingOutIcon className="h-5 w-5" />; const iconComponent = isFull ? <ArrowsPointingInIcon className="h-5 w-5" /> : <ArrowsPointingOutIcon className="h-5 w-5" />;
@ -80,7 +80,7 @@ const Drawer: FunctionComponent<DrawerProps> = ({ title, children, onSave, edita
<div className={drawerClassName}> <div className={drawerClassName}>
<div className="flex items-center justify-between p-4 border-b"> <div className="flex items-center justify-between p-4 border-b">
<div className="flex flex-row items-center justify-between space-x-2"> <div className="flex flex-row items-center justify-between space-x-2">
<span className="h-5 text-purple-700 w-5">{currentCardIcon}</span> <span className="h-5 text-purple-700 w-5">{currentCardIcon}</span>
<h2 style={{ fontSize: '20px' }} className = "text-sm text-gray-800 font-semibold">{rowContent.username}</h2> <h2 style={{ fontSize: '20px' }} className = "text-sm text-gray-800 font-semibold">{rowContent.username}</h2>
</div> </div>
<div> <div>

View File

@ -9,6 +9,7 @@
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@heroicons/react": "^2.1.1", "@heroicons/react": "^2.1.1",
"@tanstack/match-sorter-utils": "^8.15.1",
"@tanstack/react-table": "^8.15.0", "@tanstack/react-table": "^8.15.0",
"next": "13.5.6", "next": "13.5.6",
"react": "^18", "react": "^18",
@ -402,6 +403,21 @@
"tslib": "^2.4.0" "tslib": "^2.4.0"
} }
}, },
"node_modules/@tanstack/match-sorter-utils": {
"version": "8.15.1",
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.15.1.tgz",
"integrity": "sha512-PnVV3d2poenUM31ZbZi/yXkBu3J7kd5k2u51CGwwNojag451AjTH9N6n41yjXz2fpLeewleyLBmNS6+HcGDlXw==",
"dependencies": {
"remove-accents": "0.5.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/react-table": { "node_modules/@tanstack/react-table": {
"version": "8.15.0", "version": "8.15.0",
"resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.15.0.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.15.0.tgz",
@ -3556,6 +3572,11 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/remove-accents": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz",
"integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A=="
},
"node_modules/resolve": { "node_modules/resolve": {
"version": "1.22.8", "version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",

View File

@ -1,4 +1,3 @@
{ {
"name": "compass", "name": "compass",
"version": "0.1.0", "version": "0.1.0",
@ -11,6 +10,7 @@
}, },
"dependencies": { "dependencies": {
"@heroicons/react": "^2.1.1", "@heroicons/react": "^2.1.1",
"@tanstack/match-sorter-utils": "^8.15.1",
"@tanstack/react-table": "^8.15.0", "@tanstack/react-table": "^8.15.0",
"next": "13.5.6", "next": "13.5.6",
"react": "^18", "react": "^18",