Merge branch 'mel-admin-GEN-102-tag' into varun-admin-GEN-59-page

This commit is contained in:
Varun Murlidhar 2024-04-20 12:00:44 -04:00
commit cd276935ef
3 changed files with 59 additions and 9 deletions

View File

@ -8,8 +8,7 @@ import {
getCoreRowModel, getCoreRowModel,
useReactTable, useReactTable,
} from "@tanstack/react-table"; } from "@tanstack/react-table";
import { useState, useEffect } from "react";
import { useState } 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";
@ -33,6 +32,18 @@ type User = {
export const Table = () => { export const Table = () => {
const columnHelper = createColumnHelper<User>(); const columnHelper = createColumnHelper<User>();
const [presetOptions, setPresetOptions] = useState(["administrator", "volunteer", "employee"]);
const [tagColors, setTagColors] = useState(new Map());
const getTagColor = (tag: string) => {
if (!tagColors.has(tag)) {
const colors = ["bg-cyan-100", "bg-blue-100", "bg-green-100", "bg-yellow-100", "bg-purple-100"];
const randomColor = colors[Math.floor(Math.random() * colors.length)];
setTagColors(new Map(tagColors).set(tag, randomColor));
}
return tagColors.get(tag);
};
const columns = [ const columns = [
columnHelper.display({ columnHelper.display({
id: "options", id: "options",
@ -43,7 +54,12 @@ export const Table = () => {
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", {
cell: (info) => <TagsInput presetValue={info.getValue() }presetOptions={["administrator","volunteer","employee"]} />, cell: (info) => <TagsInput presetValue={info.getValue() }
presetOptions={presetOptions}
setPresetOptions={setPresetOptions}
getTagColor={getTagColor}
setTagColors={setTagColors}
/>,
}), }),
columnHelper.accessor("email", { columnHelper.accessor("email", {
header: () => <><AtSymbolIcon className="inline align-top h-4" /> Email</>, header: () => <><AtSymbolIcon className="inline align-top h-4" /> Email</>,

View File

@ -1,4 +1,4 @@
import React, { useState } from "react"; import React, { useState, useRef } from "react";
import "tailwindcss/tailwind.css"; import "tailwindcss/tailwind.css";
import { TagsArray } from "./TagsArray"; import { TagsArray } from "./TagsArray";
import { TagDropdown } from "./TagDropdown"; import { TagDropdown } from "./TagDropdown";
@ -11,6 +11,8 @@ interface TagsInputProps {
const TagsInput: React.FC<TagsInputProps> = ({ const TagsInput: React.FC<TagsInputProps> = ({
presetValue, presetValue,
presetOptions, presetOptions,
setPresetOptions,
getTagColor
}) => { }) => {
const [inputValue, setInputValue] = useState(""); const [inputValue, setInputValue] = useState("");
const [cellSelected, setCellSelected] = useState(false); const [cellSelected, setCellSelected] = useState(false);
@ -18,13 +20,41 @@ const TagsInput: React.FC<TagsInputProps> = ({
new Set(presetValue ? [presetValue] : []) new Set(presetValue ? [presetValue] : [])
); );
const [options, setOptions] = useState<Set<string>>(new Set(presetOptions)); const [options, setOptions] = useState<Set<string>>(new Set(presetOptions));
const dropdown = useRef<HTMLDivElement>(null);
const handleClick = () => {
if (!cellSelected) {
setCellSelected(true);
// Add event listener only after setting cellSelected to true
setTimeout(() => {
window.addEventListener("click", handleOutsideClick);
}, 100);
}
}
const handleOutsideClick = (event) => {
if (dropdown.current && !dropdown.current.contains(event.target)) {
setCellSelected(false);
// Remove event listener after handling outside click
window.removeEventListener("click", handleOutsideClick);
}
};
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value); setOptions(() => {
const newOptions = presetOptions.filter(item => item.includes(e.target.value.toLowerCase()));
return new Set(newOptions);
})
setInputValue(e.target.value); // Update input value state
}; };
const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => { const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter" && inputValue.trim()) { if (e.key === "Enter" && inputValue.trim()) {
// setPresetOptions((prevPreset) => {
// const uniqueSet = new Set(presetOptions);
// uniqueSet.add(inputValue);
// return Array.from(uniqueSet);
// });
setTags((prevTags) => new Set(prevTags).add(inputValue)); setTags((prevTags) => new Set(prevTags).add(inputValue));
setOptions((prevOptions) => new Set(prevOptions).add(inputValue)); setOptions((prevOptions) => new Set(prevOptions).add(inputValue));
setInputValue(""); setInputValue("");
@ -47,6 +77,7 @@ const TagsInput: React.FC<TagsInputProps> = ({
}; };
const handleDeleteTagOption = (tagToDelete: string) => { const handleDeleteTagOption = (tagToDelete: string) => {
// setPresetOptions(presetOptions.filter(tag => tag !== tagToDelete));
setOptions((prevOptions) => { setOptions((prevOptions) => {
const updatedOptions = new Set(prevOptions); const updatedOptions = new Set(prevOptions);
updatedOptions.delete(tagToDelete); updatedOptions.delete(tagToDelete);
@ -78,14 +109,13 @@ const TagsInput: React.FC<TagsInputProps> = ({
}); });
} }
}; };
return ( return (
<div className="cursor-pointer" onClick={() => setCellSelected(true)}> <div className="cursor-pointer" onClick={handleClick}>
{!cellSelected ? ( {!cellSelected ? (
<TagsArray handleDelete={handleDeleteTag} tags={tags} /> <TagsArray handleDelete={handleDeleteTag} tags={tags} />
) : ( ) : (
<div ref={dropdown}>
<div className="absolute w-64 z-50 -ml-3 -mt-7"> <div className="absolute w-64 z-50 -ml-3 -mt-7">
<div className="rounded-md border border-gray-200 shadow"> <div className="rounded-md border border-gray-200 shadow">
<div className="flex flex-wrap rounded-t-md items-center gap-2 bg-gray-50 p-2"> <div className="flex flex-wrap rounded-t-md items-center gap-2 bg-gray-50 p-2">
@ -114,6 +144,7 @@ const TagsInput: React.FC<TagsInputProps> = ({
</div> </div>
</div> </div>
</div> </div>
</div>
)} )}
</div> </div>
); );

View File

@ -1,7 +1,10 @@
import { XMarkIcon } from "@heroicons/react/24/solid"; import { XMarkIcon } from "@heroicons/react/24/solid";
import React, { useState, useEffect } from "react";
export const Tag = ({ children, handleDelete, active = false }) => { export const Tag = ({ children, handleDelete, active = false }) => {
const [tagColor, setTagColor] = useState('');
return ( return (
<span className={`font-normal bg-cyan-100 text-gray-800 flex flex-row p-1 px-2 rounded-lg`}> <span className={`font-normal bg-cyan-100 text-gray-800 flex flex-row p-1 px-2 rounded-lg`}>
{children} {children}
@ -12,4 +15,4 @@ export const Tag = ({ children, handleDelete, active = false }) => {
)} )}
</span> </span>
); );
}; };