From 85d99a0a96c37fb588e11425eab7d2a77a3fe4b2 Mon Sep 17 00:00:00 2001 From: anikaahmed114 Date: Sat, 30 Mar 2024 04:07:40 -0400 Subject: [PATCH 01/19] added multiple input functionality --- compass/app/pages/page/page.tsx | 24 ++++- compass/components/page/Card.tsx | 29 ++++++ compass/components/page/Drawer.tsx | 146 ++++++++++++++++++++------- compass/components/page/DropDown.tsx | 30 ++++++ compass/components/page/Field.tsx | 4 - 5 files changed, 188 insertions(+), 45 deletions(-) create mode 100644 compass/components/page/Card.tsx create mode 100644 compass/components/page/DropDown.tsx delete mode 100644 compass/components/page/Field.tsx diff --git a/compass/app/pages/page/page.tsx b/compass/app/pages/page/page.tsx index dce1122..391c81c 100644 --- a/compass/app/pages/page/page.tsx +++ b/compass/app/pages/page/page.tsx @@ -1,5 +1,7 @@ // pages/index.tsx "use client"; +import Image from 'next/image'; + import Drawer from '@/components/page/Drawer'; @@ -18,9 +20,21 @@ export default function Page() { }; return ( - <> -

Resources

- {pageContent} - +
+
+
+ Compass Center logo +

Untitled Page

+
+ {pageContent} +
+
); -}; \ No newline at end of file +}; + diff --git a/compass/components/page/Card.tsx b/compass/components/page/Card.tsx new file mode 100644 index 0000000..39894cb --- /dev/null +++ b/compass/components/page/Card.tsx @@ -0,0 +1,29 @@ +import React, { ReactNode, useState } from "react"; + + +interface TagProps { + text: string; + icon: React.ReactNode; + onClick?: (event: React.MouseEvent) => void; + children?: React.ReactNode; +} + + +const Card: React.FC = ({children, text, icon, onClick }) => { + return ( + + ); +}; + +export default Card; diff --git a/compass/components/page/Drawer.tsx b/compass/components/page/Drawer.tsx index 217fbd2..624c92f 100644 --- a/compass/components/page/Drawer.tsx +++ b/compass/components/page/Drawer.tsx @@ -1,8 +1,10 @@ -import { FunctionComponent, ReactNode } from 'react'; +import { FunctionComponent, ReactElement, ReactNode } from 'react'; import Button from '@/components/Button' import React, { useState } from 'react'; -import {DATATYPE} from '@/utils/constants' -import InlineLink from '@/components/InlineLink' +import { ChevronDoubleLeftIcon } from '@heroicons/react/24/solid'; +import { BookmarkIcon, XMarkIcon } from "@heroicons/react/24/solid"; +import Card from '@/components/page/Card' + type DrawerProps = { @@ -15,62 +17,134 @@ type DrawerProps = { onSave?: (content: any) => void; }; +interface EditContent { + content: string; + isEditing: boolean; + } + + const Drawer: FunctionComponent = ({ title, children, onSave, editableContent }) => { const [isOpen, setIsOpen] = useState(false); const [isEditing, setIsEditing] = useState(false); - const [editContent, setEditContent] = useState(editableContent || ''); + const [editContents, setEditContents] = useState(editableContent || [{ content: '', isEditing: true }]); + const [currentCardText, setCurrentCardText] = useState(""); + const [currentCardIcon, setCurrentCardIcon] = useState(''); + const [error, setError] = useState(null); + const toggleDrawer = () => setIsOpen(!isOpen); - const toggleEditing = () => setIsEditing(!isEditing); - const handleContentChange = (event: React.ChangeEvent) => { - setEditContent(event.target.value); - }; + + const handleCardClick = (text: string, icon: ReactElement) => { + console.log('click') + toggleDrawer(); + setCurrentCardText(text); + setCurrentCardIcon(icon)}; + const toggleEditing = () => setIsEditing(!isEditing); + const handleInputChange = (index: number) => (event: React.ChangeEvent) => { + const newContents = editContents.map((item, idx) => idx === index ? { ...item, content: event.target.value } : item); + setEditContents(newContents); + }; const drawerClassName = `fixed top-0 right-0 w-1/2 h-full bg-white shadow-xl transform ease-in-out duration-300 ${ isOpen ? "translate-x-0" : "translate-x-full" }`; + + const addInput = () => { + setEditContents([...editContents, { content: '', isEditing: true }]); + }; - const saveChanges = () => { - console.log(editContent); - if (onSave) { - onSave(editContent); + const saveIndividualChange = (index: number) => { + const content = editContents[index].content.trim(); + if (!content) { + setError("Input cannot be empty."); + return; } - setIsEditing(false); + + setError(null); // Clear error state if input passes validation + + const updatedContents = editContents.map((item, idx) => idx === index ? { ...item, isEditing: false } : item); + setEditContents(updatedContents); + + if (onSave) { + onSave(updatedContents); + } + }; + + const toggleEdit = (index: number) => { + const newContents = editContents.map((item, idx) => idx === index ? { ...item, isEditing: !item.isEditing } : item); + setEditContents(newContents); + }; + + const deleteInput = (index: number) => { + // Filter out the input at the given index + const filteredContents = editContents.filter((_, idx) => idx !== index); + setEditContents(filteredContents); }; - const addRow = () => { - - } return (
- + } text="Resources" onClick={() => handleCardClick("Resources", )}/>
-
-

{title}

+
+ + {currentCardIcon} + +

{currentCardText}

- - +
- {isEditing ? ( - <> - - Save - - ) : ( - children - )} -
+ { + editContents.map((item, index) => ( +
+ {item.isEditing ? ( + <> + + + + ) : ( + <> + {item.content} + + + )} + {/* Delete button moved here, outside of the editing conditional */} + +
+ )) +} + +
); }; -export default Drawer; \ No newline at end of file +export default Drawer; + diff --git a/compass/components/page/DropDown.tsx b/compass/components/page/DropDown.tsx new file mode 100644 index 0000000..dfda408 --- /dev/null +++ b/compass/components/page/DropDown.tsx @@ -0,0 +1,30 @@ +import React, { ChangeEvent, FunctionComponent } from 'react'; + +// Define the shape of a single option +interface DropdownOption { + label: string; + value: string | number; +} + +// Define the props for the Dropdown component +interface DropdownProps { + options: DropdownOption[]; + onChange: (event: ChangeEvent) => void; // Type for change event on + {options.map((option, index) => ( + + ))} + + ); +}; + +export default Dropdown; \ No newline at end of file diff --git a/compass/components/page/Field.tsx b/compass/components/page/Field.tsx deleted file mode 100644 index 9ee44b1..0000000 --- a/compass/components/page/Field.tsx +++ /dev/null @@ -1,4 +0,0 @@ -// components/Field.tsx -import { FunctionComponent, ReactNode } from 'react'; -import Button from '@/components/Button' -import React, { useState } from 'react'; From 034906cfc152e57b51838f2aa1cab6cd5c0c2450 Mon Sep 17 00:00:00 2001 From: anikaahmed114 Date: Sat, 30 Mar 2024 04:17:03 -0400 Subject: [PATCH 02/19] update UI --- compass/components/page/Drawer.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compass/components/page/Drawer.tsx b/compass/components/page/Drawer.tsx index 624c92f..d9c6a04 100644 --- a/compass/components/page/Drawer.tsx +++ b/compass/components/page/Drawer.tsx @@ -1,5 +1,4 @@ import { FunctionComponent, ReactElement, ReactNode } from 'react'; -import Button from '@/components/Button' import React, { useState } from 'react'; import { ChevronDoubleLeftIcon } from '@heroicons/react/24/solid'; import { BookmarkIcon, XMarkIcon } from "@heroicons/react/24/solid"; @@ -87,10 +86,12 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita } text="Resources" onClick={() => handleCardClick("Resources", )}/>
+
{currentCardIcon} -

{currentCardText}

+

{currentCardText}

+
) : ( = ({ presetValue, presetOptions }) => { const [inputValue, setInputValue] = useState(''); const [cellSelected, setCellSelected] = useState(false); - const [tags, setTags] = useState([presetValue]); - const [options, setOptions] = useState(presetOptions); + const [tags, setTags] = useState>(new Set(presetValue ? [presetValue] : [])); + const [options, setOptions] = useState>(new Set(presetOptions)); const handleInputChange = (e: React.ChangeEvent) => { setInputValue(e.target.value); @@ -19,43 +19,52 @@ const TagsInput: React.FC = ({ presetValue, presetOptions }) => const handleAddTag = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && inputValue.trim()) { - setTags(prevTags => [...prevTags, inputValue]); - setOptions(prevOptions => [...prevOptions, inputValue]); + // To add to a Set, you need to create a new Set for immutability in React state updates. + setTags(prevTags => new Set(prevTags).add(inputValue)); + setOptions(prevOptions => new Set(prevOptions).add(inputValue)); setInputValue(''); } }; - const handleDeleteTag = (tagToDelete: string) => { - setTags(tags.filter(tag => tag !== tagToDelete)); - }; + const handleSelectTag = (tagToAdd: string) => { + if (!tags.has(tagToAdd)){ // Corrected syntax for checking if a Set contains an item + setTags(prevTags => new Set(prevTags).add(tagToAdd)); + } + } + const handleDeleteTag = (tagToDelete: string) => { + setTags(prevTags => { + const updatedTags = new Set(prevTags); + updatedTags.delete(tagToDelete); + return updatedTags; + }); + }; const handleBlur = () => { setCellSelected(false); }; return ( -
setCellSelected(true)}> +
setCellSelected(true)}> {!cellSelected ? ( - + ) : ( -
+
-
- +
+
Select an option or create one - +
diff --git a/compass/components/TagsInput/Tag.tsx b/compass/components/TagsInput/Tag.tsx index 59ede37..e7093fd 100644 --- a/compass/components/TagsInput/Tag.tsx +++ b/compass/components/TagsInput/Tag.tsx @@ -1,12 +1,10 @@ import { XMarkIcon } from "@heroicons/react/24/solid" -export const Tag = ({children, active = false}) => { - const handleClick = () => { - - } +export const Tag = ({children, handleDelete, active = false}) => { + return ( {children} - {active && } + {active && } ) } \ No newline at end of file diff --git a/compass/components/TagsInput/TagDropdown.tsx b/compass/components/TagsInput/TagDropdown.tsx index b1b5f9b..535bf7f 100644 --- a/compass/components/TagsInput/TagDropdown.tsx +++ b/compass/components/TagsInput/TagDropdown.tsx @@ -2,11 +2,11 @@ import { Tag } from "./Tag"; import { DropdownAction } from "./DropdownAction"; -export const TagDropdown = ({ tags }) => { +export const TagDropdown = ({ tags, handleAdd }) => { return (
- {tags.map((tag, index) => ( -
+ {Array.from(tags).map((tag, index) => ( +
handleAdd(tag)} key={index} className="items-center rounded-md p-1 flex flex-row justify-between hover:bg-gray-100"> {tag}
diff --git a/compass/components/TagsInput/TagsArray.tsx b/compass/components/TagsInput/TagsArray.tsx index 98769c7..486a8a4 100644 --- a/compass/components/TagsInput/TagsArray.tsx +++ b/compass/components/TagsInput/TagsArray.tsx @@ -1,12 +1,12 @@ import { Tag } from "./Tag" -export const TagsArray = ({ tags, active = false }) => { +export const TagsArray = ({ tags, handleDelete, active = false }) => { return( -
+
{ - tags.map((tag) => { + Array.from(tags).map((tag) => { return ( - {tag} + {tag} ) }) } From 167fa009ae62f7edb3a67af12009caf0dc18bfa9 Mon Sep 17 00:00:00 2001 From: Meliora Ho Date: Thu, 4 Apr 2024 20:28:41 +0000 Subject: [PATCH 07/19] Edited the dropdown action --- compass/components/Table/Index.tsx | 6 +- .../TagsInput/CreateNewTagAction.tsx | 10 +++ .../components/TagsInput/DropdownAction.tsx | 35 ++++---- compass/components/TagsInput/Index.tsx | 88 ++++++++++++++----- compass/components/TagsInput/Tag.tsx | 21 +++-- compass/components/TagsInput/TagDropdown.tsx | 10 +-- compass/components/TagsInput/TagsArray.tsx | 1 + 7 files changed, 115 insertions(+), 56 deletions(-) create mode 100644 compass/components/TagsInput/CreateNewTagAction.tsx diff --git a/compass/components/Table/Index.tsx b/compass/components/Table/Index.tsx index 625dca3..7b5ee92 100644 --- a/compass/components/Table/Index.tsx +++ b/compass/components/Table/Index.tsx @@ -21,17 +21,17 @@ type User = { id: number; created_at: any; username: string; - role: "ADMIN" | "EMPLOYEE" | "VOLUNTEER"; + role: "administrator" | "employee" | "volunteer"; email: string; - program: "DOMESTIC" | "ECONOMIC" | "COMMUNITY"; + program: "domestic" | "economic" | "community"; experience: number; group?: string; }; + export const Table = () => { const columnHelper = createColumnHelper(); - const columns = [ columnHelper.display({ id: "options", diff --git a/compass/components/TagsInput/CreateNewTagAction.tsx b/compass/components/TagsInput/CreateNewTagAction.tsx new file mode 100644 index 0000000..f906270 --- /dev/null +++ b/compass/components/TagsInput/CreateNewTagAction.tsx @@ -0,0 +1,10 @@ +import { Tag } from "./Tag" + +export const CreateNewTagAction = ({ input }) => { + return ( +
+

Create

+ {input} +
+ ) +} \ No newline at end of file diff --git a/compass/components/TagsInput/DropdownAction.tsx b/compass/components/TagsInput/DropdownAction.tsx index 737ec69..7c9b7d1 100644 --- a/compass/components/TagsInput/DropdownAction.tsx +++ b/compass/components/TagsInput/DropdownAction.tsx @@ -1,51 +1,48 @@ import { EllipsisHorizontalIcon, TrashIcon } from "@heroicons/react/24/solid"; import { useState } from "react"; -export const DropdownAction = ({ tag, handleDeleteTag, handleAddTag }) => { +export const DropdownAction = ({ tag, handleDeleteTag, handleEditTag }) => { const [isVisible, setVisible] = useState(false); const [inputValue, setInputValue] = useState(tag); - const handleBlur = () => { - setVisible(false); + + const editTagOption = (e) => { + if (e.key === 'Enter') { + handleEditTag(tag, inputValue) + setVisible(false); + } }; - const editTagOption = () => { - handleDeleteTag(tag) - handleAddTag(inputValue) - } const handleInputChange = (e: React.ChangeEvent) => { setInputValue(e.target.value); }; - const handleClick = (event: React.MouseEvent) => { - event.stopPropagation(); // This stops the click event from propagating - setVisible(!isVisible); // Toggle visibility - }; return (
- {isVisible ? ( + setVisible(!isVisible)} + /> + {isVisible && (
-
- ) : ( - )}
); diff --git a/compass/components/TagsInput/Index.tsx b/compass/components/TagsInput/Index.tsx index 3c8d43a..ca0c947 100644 --- a/compass/components/TagsInput/Index.tsx +++ b/compass/components/TagsInput/Index.tsx @@ -1,16 +1,22 @@ -import React, { useState } from 'react'; -import 'tailwindcss/tailwind.css'; -import { TagsArray } from './TagsArray'; // Corrected path assumption -import { TagDropdown } from './TagDropdown'; +import React, { useState } from "react"; +import "tailwindcss/tailwind.css"; +import { TagsArray } from "./TagsArray"; +import { TagDropdown } from "./TagDropdown"; +import { CreateNewTagAction } from "./CreateNewTagAction"; interface TagsInputProps { presetOptions: string[]; } -const TagsInput: React.FC = ({ presetValue, presetOptions }) => { - const [inputValue, setInputValue] = useState(''); +const TagsInput: React.FC = ({ + presetValue, + presetOptions, +}) => { + const [inputValue, setInputValue] = useState(""); const [cellSelected, setCellSelected] = useState(false); - const [tags, setTags] = useState>(new Set(presetValue ? [presetValue] : [])); + const [tags, setTags] = useState>( + new Set(presetValue ? [presetValue] : []) + ); const [options, setOptions] = useState>(new Set(presetOptions)); const handleInputChange = (e: React.ChangeEvent) => { @@ -18,31 +24,63 @@ const TagsInput: React.FC = ({ presetValue, presetOptions }) => }; const handleAddTag = (e: React.KeyboardEvent) => { - if (e.key === 'Enter' && inputValue.trim()) { - // To add to a Set, you need to create a new Set for immutability in React state updates. - setTags(prevTags => new Set(prevTags).add(inputValue)); - setOptions(prevOptions => new Set(prevOptions).add(inputValue)); - setInputValue(''); + if (e.key === "Enter" && inputValue.trim()) { + setTags((prevTags) => new Set(prevTags).add(inputValue)); + setOptions((prevOptions) => new Set(prevOptions).add(inputValue)); + setInputValue(""); } }; const handleSelectTag = (tagToAdd: string) => { - if (!tags.has(tagToAdd)){ // Corrected syntax for checking if a Set contains an item - setTags(prevTags => new Set(prevTags).add(tagToAdd)); + if (!tags.has(tagToAdd)) { + // Corrected syntax for checking if a Set contains an item + setTags((prevTags) => new Set(prevTags).add(tagToAdd)); } - } + }; const handleDeleteTag = (tagToDelete: string) => { - setTags(prevTags => { + setTags((prevTags) => { const updatedTags = new Set(prevTags); updatedTags.delete(tagToDelete); return updatedTags; }); }; - const handleBlur = () => { - setCellSelected(false); + + const handleDeleteTagOption = (tagToDelete: string) => { + setOptions((prevOptions) => { + const updatedOptions = new Set(prevOptions); + updatedOptions.delete(tagToDelete); + return updatedOptions; + }); + if (tags.has(tagToDelete)) { + handleDeleteTag(tagToDelete); + } }; + const handleEditTag = (oldTag: string, newTag: string) => { + if (oldTag !== newTag) { + setTags((prevTags) => { + const tagsArray = Array.from(prevTags); + const oldTagIndex = tagsArray.indexOf(oldTag); + if (oldTagIndex !== -1) { + tagsArray.splice(oldTagIndex, 1, newTag); + } + return new Set(tagsArray); + }); + + setOptions((prevOptions) => { + const optionsArray = Array.from(prevOptions); + const oldTagIndex = optionsArray.indexOf(oldTag); + if (oldTagIndex !== -1) { + optionsArray.splice(oldTagIndex, 1, newTag); + } + return new Set(optionsArray); + }); + } + }; + + + return (
setCellSelected(true)}> {!cellSelected ? ( @@ -50,7 +88,7 @@ const TagsInput: React.FC = ({ presetValue, presetOptions }) => ) : (
-
+
= ({ presetValue, presetOptions }) => />
- Select an option or create one - +

Select an option or create one

+ + {inputValue.length > 0 && ( + + )}
diff --git a/compass/components/TagsInput/Tag.tsx b/compass/components/TagsInput/Tag.tsx index e7093fd..1d5999c 100644 --- a/compass/components/TagsInput/Tag.tsx +++ b/compass/components/TagsInput/Tag.tsx @@ -1,10 +1,15 @@ -import { XMarkIcon } from "@heroicons/react/24/solid" +import { XMarkIcon } from "@heroicons/react/24/solid"; -export const Tag = ({children, handleDelete, active = false}) => { +export const Tag = ({ children, handleDelete, active = false }) => { - return ( - {children} - {active && } - - ) -} \ No newline at end of file + return ( + + {children} + {active && handleDelete && ( + + )} + + ); +}; diff --git a/compass/components/TagsInput/TagDropdown.tsx b/compass/components/TagsInput/TagDropdown.tsx index 535bf7f..6f4558a 100644 --- a/compass/components/TagsInput/TagDropdown.tsx +++ b/compass/components/TagsInput/TagDropdown.tsx @@ -2,13 +2,13 @@ import { Tag } from "./Tag"; import { DropdownAction } from "./DropdownAction"; -export const TagDropdown = ({ tags, handleAdd }) => { +export const TagDropdown = ({ tags, handleEditTag,handleDeleteTag,handleAdd }) => { return ( -
+
{Array.from(tags).map((tag, index) => ( -
handleAdd(tag)} key={index} className="items-center rounded-md p-1 flex flex-row justify-between hover:bg-gray-100"> - {tag} - +
+ +
))}
diff --git a/compass/components/TagsInput/TagsArray.tsx b/compass/components/TagsInput/TagsArray.tsx index 486a8a4..59d8aa1 100644 --- a/compass/components/TagsInput/TagsArray.tsx +++ b/compass/components/TagsInput/TagsArray.tsx @@ -1,6 +1,7 @@ import { Tag } from "./Tag" export const TagsArray = ({ tags, handleDelete, active = false }) => { + return(
{ From 71833c629cfe226c4e87a3bb4b9675cc0b6a53c9 Mon Sep 17 00:00:00 2001 From: Varun Murlidhar Date: Fri, 5 Apr 2024 11:21:52 -0400 Subject: [PATCH 08/19] Add togglable favorite icon to drawer --- compass/components/page/Drawer.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/compass/components/page/Drawer.tsx b/compass/components/page/Drawer.tsx index 6387def..90c02a5 100644 --- a/compass/components/page/Drawer.tsx +++ b/compass/components/page/Drawer.tsx @@ -1,8 +1,8 @@ import { FunctionComponent, ReactElement, ReactNode } from 'react'; import React, { useState } from 'react'; import { ChevronDoubleLeftIcon } from '@heroicons/react/24/solid'; -import { BookmarkIcon, XMarkIcon } from "@heroicons/react/24/solid"; -import { ArrowsPointingOutIcon, ArrowsPointingInIcon } from '@heroicons/react/24/outline'; +import { BookmarkIcon, XMarkIcon, StarIcon as SolidStarIcon } from "@heroicons/react/24/solid"; +import { ArrowsPointingOutIcon, ArrowsPointingInIcon, StarIcon as OutlineStarIcon } from '@heroicons/react/24/outline'; import Card from '@/components/page/Card' @@ -31,6 +31,7 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita const [currentCardText, setCurrentCardText] = useState(""); const [currentCardIcon, setCurrentCardIcon] = useState(''); const [error, setError] = useState(null); + const [isFavorite, setIsFavorite] = useState(false); const toggleDrawer = () => { @@ -41,6 +42,8 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita } const toggleDrawerFullScreen = () => setIsFull(!isFull); + + const toggleFavorite = () => setIsFavorite(!isFavorite); const handleCardClick = (text: string, icon: ReactElement) => { console.log('click') @@ -92,6 +95,8 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita const iconComponent = isFull ? : ; + const favoriteIcon = isFavorite ? : + return (
@@ -105,6 +110,9 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita

{currentCardText}

+ From 5c8a612df11b88f4f496be93beceaa6ecb9ebab0 Mon Sep 17 00:00:00 2001 From: Varun Murlidhar Date: Fri, 5 Apr 2024 11:27:23 -0400 Subject: [PATCH 09/19] Add margin for icons --- compass/components/page/Drawer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compass/components/page/Drawer.tsx b/compass/components/page/Drawer.tsx index 90c02a5..d848923 100644 --- a/compass/components/page/Drawer.tsx +++ b/compass/components/page/Drawer.tsx @@ -110,10 +110,10 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita

{currentCardText}

- - +
-
+
{currentCardIcon} -

{currentCardText}

+

{rowContent.username}

+
+ Username: { rowContent.username } +
+
+ Role: { rowContent.role } +
+
+ Email: { rowContent.email } +
+
+ Program: { rowContent.program } +
+
{ editContents.map((item, index) => (
From e3b31b086192fa958eefa9f8bba4cc1071c78e71 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Sat, 13 Apr 2024 10:36:40 -0400 Subject: [PATCH 13/19] progress on handling clicks. --- compass/components/TagsInput/Index.tsx | 28 ++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/compass/components/TagsInput/Index.tsx b/compass/components/TagsInput/Index.tsx index 7ae393e..7e3b26f 100644 --- a/compass/components/TagsInput/Index.tsx +++ b/compass/components/TagsInput/Index.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useEffect, useRef } from "react"; import "tailwindcss/tailwind.css"; import { TagsArray } from "./TagsArray"; import { TagDropdown } from "./TagDropdown"; @@ -18,6 +18,25 @@ const TagsInput: React.FC = ({ new Set(presetValue ? [presetValue] : []) ); const [options, setOptions] = useState>(new Set(presetOptions)); + const dropdown = useRef(null); + + useEffect(() => { + console.log(cellSelected); + if (!cellSelected) { + return; + } + function handleClick(event: MouseEvent) { + if (dropdown.current && !dropdown.current.contains(event.target as Node)) { + setCellSelected(false); + } + } + + if (cellSelected){ + window.addEventListener("click", handleClick); + } + + return () => window.removeEventListener("click", handleClick); + }, [cellSelected]) const handleInputChange = (e: React.ChangeEvent) => { setOptions(() => { @@ -85,10 +104,14 @@ const TagsInput: React.FC = ({ return ( -
setCellSelected(true)}> +
{ + e.stopPropagation(); + setCellSelected(true) + }}> {!cellSelected ? ( ) : ( +
@@ -117,6 +140,7 @@ const TagsInput: React.FC = ({
+
)}
); From 316a986f33a17ff4644d9f03df8eefe2e9f5dc60 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Mon, 15 Apr 2024 00:43:35 -0400 Subject: [PATCH 14/19] fixed problem where multiple tag dropdowns could be open at once. --- compass/components/Table/Index.tsx | 7 +++- compass/components/TagsInput/Index.tsx | 51 ++++++++++++++++---------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/compass/components/Table/Index.tsx b/compass/components/Table/Index.tsx index 7b5ee92..5e1f49b 100644 --- a/compass/components/Table/Index.tsx +++ b/compass/components/Table/Index.tsx @@ -8,7 +8,7 @@ import { getCoreRowModel, useReactTable, } from "@tanstack/react-table"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import { RowOptionMenu } from "./RowOptionMenu"; import { RowOpenAction } from "./RowOpenAction"; import { TableAction } from "./TableAction"; @@ -32,6 +32,8 @@ type User = { export const Table = () => { const columnHelper = createColumnHelper(); + + const columns = [ columnHelper.display({ id: "options", @@ -42,7 +44,8 @@ export const Table = () => { cell: (info) => , }), columnHelper.accessor("role", { - cell: (info) => , + cell: (info) => , }), columnHelper.accessor("email", { header: () => <> Email, diff --git a/compass/components/TagsInput/Index.tsx b/compass/components/TagsInput/Index.tsx index 7e3b26f..6590a88 100644 --- a/compass/components/TagsInput/Index.tsx +++ b/compass/components/TagsInput/Index.tsx @@ -20,23 +20,41 @@ const TagsInput: React.FC = ({ const [options, setOptions] = useState>(new Set(presetOptions)); const dropdown = useRef(null); - useEffect(() => { - console.log(cellSelected); + // useEffect(() => { + // if (!cellSelected) { + // return; + // } + // function handleOutsideClick(event: MouseEvent) { + // if (dropdown.current && !dropdown.current.contains(event.target as Node)) { + // console.log("here2") + // setCellSelected(false); + // } + // } + + // if (cellSelected){ + // window.addEventListener("click", handleOutsideClick); + // } + + // return () => window.removeEventListener("click", handleOutsideClick); + // }, [cellSelected]) + + const handleClick = () => { if (!cellSelected) { - return; - } - function handleClick(event: MouseEvent) { - if (dropdown.current && !dropdown.current.contains(event.target as Node)) { - setCellSelected(false); - } + setCellSelected(true); + // Add event listener only after setting cellSelected to true + setTimeout(() => { + window.addEventListener("click", handleOutsideClick); + }, 100); } + } - if (cellSelected){ - window.addEventListener("click", handleClick); + const handleOutsideClick = (event) => { + if (dropdown.current && !dropdown.current.contains(event.target)) { + setCellSelected(false); + // Remove event listener after handling outside click + window.removeEventListener("click", handleOutsideClick); } - - return () => window.removeEventListener("click", handleClick); - }, [cellSelected]) + }; const handleInputChange = (e: React.ChangeEvent) => { setOptions(() => { @@ -100,14 +118,9 @@ const TagsInput: React.FC = ({ }); } }; - - return ( -
{ - e.stopPropagation(); - setCellSelected(true) - }}> +
{!cellSelected ? ( ) : ( From b1b3313de0c50b21166170e5c33825cc584e7299 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Mon, 15 Apr 2024 00:54:50 -0400 Subject: [PATCH 15/19] New options now display on all rows --- compass/components/Table/Index.tsx | 8 +++++++- compass/components/TagsInput/Index.tsx | 23 ++++------------------- compass/components/TagsInput/Tag.tsx | 3 ++- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/compass/components/Table/Index.tsx b/compass/components/Table/Index.tsx index 5e1f49b..fdc11bd 100644 --- a/compass/components/Table/Index.tsx +++ b/compass/components/Table/Index.tsx @@ -32,7 +32,11 @@ type User = { export const Table = () => { const columnHelper = createColumnHelper(); + const [presetOptions, setPresetOptions] = useState(["administrator", "volunteer", "employee"]); + const handleAddTag = (newTag) => { + setPresetOptions((prevOptions) => [...prevOptions, newTag]); + } const columns = [ columnHelper.display({ @@ -45,7 +49,9 @@ export const Table = () => { }), columnHelper.accessor("role", { cell: (info) => , + presetOptions={presetOptions} + addOption={handleAddTag} + />, }), columnHelper.accessor("email", { header: () => <> Email, diff --git a/compass/components/TagsInput/Index.tsx b/compass/components/TagsInput/Index.tsx index 6590a88..ab9a98f 100644 --- a/compass/components/TagsInput/Index.tsx +++ b/compass/components/TagsInput/Index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useRef } from "react"; +import React, { useState, useRef } from "react"; import "tailwindcss/tailwind.css"; import { TagsArray } from "./TagsArray"; import { TagDropdown } from "./TagDropdown"; @@ -11,6 +11,7 @@ interface TagsInputProps { const TagsInput: React.FC = ({ presetValue, presetOptions, + addOption, }) => { const [inputValue, setInputValue] = useState(""); const [cellSelected, setCellSelected] = useState(false); @@ -20,24 +21,6 @@ const TagsInput: React.FC = ({ const [options, setOptions] = useState>(new Set(presetOptions)); const dropdown = useRef(null); - // useEffect(() => { - // if (!cellSelected) { - // return; - // } - // function handleOutsideClick(event: MouseEvent) { - // if (dropdown.current && !dropdown.current.contains(event.target as Node)) { - // console.log("here2") - // setCellSelected(false); - // } - // } - - // if (cellSelected){ - // window.addEventListener("click", handleOutsideClick); - // } - - // return () => window.removeEventListener("click", handleOutsideClick); - // }, [cellSelected]) - const handleClick = () => { if (!cellSelected) { setCellSelected(true); @@ -63,8 +46,10 @@ const TagsInput: React.FC = ({ }) setInputValue(e.target.value); // Update input value state }; + const handleAddTag = (e: React.KeyboardEvent) => { if (e.key === "Enter" && inputValue.trim()) { + addOption(inputValue); setTags((prevTags) => new Set(prevTags).add(inputValue)); setOptions((prevOptions) => new Set(prevOptions).add(inputValue)); setInputValue(""); diff --git a/compass/components/TagsInput/Tag.tsx b/compass/components/TagsInput/Tag.tsx index 1d5999c..f44ba9c 100644 --- a/compass/components/TagsInput/Tag.tsx +++ b/compass/components/TagsInput/Tag.tsx @@ -1,4 +1,5 @@ import { XMarkIcon } from "@heroicons/react/24/solid"; +import React, { useState } from "react"; export const Tag = ({ children, handleDelete, active = false }) => { @@ -12,4 +13,4 @@ export const Tag = ({ children, handleDelete, active = false }) => { )} ); -}; +}; \ No newline at end of file From 8667ef64314289602e908bfd80216a913bcffb5e Mon Sep 17 00:00:00 2001 From: Nicholas Date: Mon, 15 Apr 2024 01:32:26 -0400 Subject: [PATCH 16/19] cleanup and checkpoint --- compass/components/Table/Index.tsx | 16 ++++++++++++---- compass/components/TagsInput/Index.tsx | 10 ++++++++-- compass/components/TagsInput/Tag.tsx | 4 +++- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/compass/components/Table/Index.tsx b/compass/components/Table/Index.tsx index fdc11bd..0cc773b 100644 --- a/compass/components/Table/Index.tsx +++ b/compass/components/Table/Index.tsx @@ -33,10 +33,16 @@ type User = { export const Table = () => { const columnHelper = createColumnHelper(); const [presetOptions, setPresetOptions] = useState(["administrator", "volunteer", "employee"]); + const [tagColors, setTagColors] = useState(new Map()); - const handleAddTag = (newTag) => { - setPresetOptions((prevOptions) => [...prevOptions, newTag]); - } + 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 = [ columnHelper.display({ @@ -50,7 +56,9 @@ export const Table = () => { columnHelper.accessor("role", { cell: (info) => , }), columnHelper.accessor("email", { diff --git a/compass/components/TagsInput/Index.tsx b/compass/components/TagsInput/Index.tsx index ab9a98f..60f695c 100644 --- a/compass/components/TagsInput/Index.tsx +++ b/compass/components/TagsInput/Index.tsx @@ -11,7 +11,8 @@ interface TagsInputProps { const TagsInput: React.FC = ({ presetValue, presetOptions, - addOption, + setPresetOptions, + getTagColor }) => { const [inputValue, setInputValue] = useState(""); const [cellSelected, setCellSelected] = useState(false); @@ -49,7 +50,11 @@ const TagsInput: React.FC = ({ const handleAddTag = (e: React.KeyboardEvent) => { if (e.key === "Enter" && inputValue.trim()) { - addOption(inputValue); + // setPresetOptions((prevPreset) => { + // const uniqueSet = new Set(presetOptions); + // uniqueSet.add(inputValue); + // return Array.from(uniqueSet); + // }); setTags((prevTags) => new Set(prevTags).add(inputValue)); setOptions((prevOptions) => new Set(prevOptions).add(inputValue)); setInputValue(""); @@ -72,6 +77,7 @@ const TagsInput: React.FC = ({ }; const handleDeleteTagOption = (tagToDelete: string) => { + // setPresetOptions(presetOptions.filter(tag => tag !== tagToDelete)); setOptions((prevOptions) => { const updatedOptions = new Set(prevOptions); updatedOptions.delete(tagToDelete); diff --git a/compass/components/TagsInput/Tag.tsx b/compass/components/TagsInput/Tag.tsx index f44ba9c..c31950f 100644 --- a/compass/components/TagsInput/Tag.tsx +++ b/compass/components/TagsInput/Tag.tsx @@ -1,8 +1,10 @@ import { XMarkIcon } from "@heroicons/react/24/solid"; -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; export const Tag = ({ children, handleDelete, active = false }) => { + const [tagColor, setTagColor] = useState(''); + return ( {children} From b42080deae33478cbb11389277fe9a9e1e2df909 Mon Sep 17 00:00:00 2001 From: Varun Murlidhar Date: Fri, 19 Apr 2024 15:18:23 -0400 Subject: [PATCH 17/19] Make email field editable and remove input --- compass/components/Table/Index.tsx | 12 +- compass/components/Table/RowOpenAction.tsx | 5 +- compass/components/page/Drawer.tsx | 155 ++++++++++++--------- 3 files changed, 101 insertions(+), 71 deletions(-) diff --git a/compass/components/Table/Index.tsx b/compass/components/Table/Index.tsx index 7beaff7..77b597f 100644 --- a/compass/components/Table/Index.tsx +++ b/compass/components/Table/Index.tsx @@ -40,7 +40,7 @@ export const Table = () => { }), columnHelper.accessor("username", { header: () => <> Username, - cell: (info) => , + cell: (info) => , }), columnHelper.accessor("role", { cell: (info) => , @@ -56,6 +56,16 @@ export const Table = () => { const [data, setData] = useState([...usersExample]); + // added this fn for editing rows + const handleRowUpdate = (updatedRow: User) => { + const dataIndex = data.findIndex((row) => row.id === updatedRow.id); + if (dataIndex !== -1) { + const updatedData = [...data]; + updatedData[dataIndex] = updatedRow; + setData(updatedData); + } + }; + const table = useReactTable({ columns, data, diff --git a/compass/components/Table/RowOpenAction.tsx b/compass/components/Table/RowOpenAction.tsx index 0543dfc..a38ff51 100644 --- a/compass/components/Table/RowOpenAction.tsx +++ b/compass/components/Table/RowOpenAction.tsx @@ -1,7 +1,7 @@ import Drawer from "@/components/page/Drawer"; import {ChangeEvent, useState} from "react"; -export const RowOpenAction = ({ title, rowData }) => { +export const RowOpenAction = ({ title, rowData, onRowUpdate }) => { const [pageContent, setPageContent] = useState("") const handleDrawerContentChange = (newContent) => { @@ -14,7 +14,8 @@ export const RowOpenAction = ({ title, rowData }) => {
{title} - {pageContent} + {/* Added OnRowUpdate to drawer */} + {pageContent}
); diff --git a/compass/components/page/Drawer.tsx b/compass/components/page/Drawer.tsx index d8e46c7..b22ac8a 100644 --- a/compass/components/page/Drawer.tsx +++ b/compass/components/page/Drawer.tsx @@ -1,8 +1,8 @@ import { FunctionComponent, ReactElement, ReactNode } from 'react'; import React, { useState } from 'react'; import { ChevronDoubleLeftIcon } from '@heroicons/react/24/solid'; -import { BookmarkIcon, XMarkIcon, StarIcon as SolidStarIcon } from "@heroicons/react/24/solid"; -import { ArrowsPointingOutIcon, ArrowsPointingInIcon, StarIcon as OutlineStarIcon } from '@heroicons/react/24/outline'; +import { BookmarkIcon, XMarkIcon, StarIcon as SolidStarIcon, EnvelopeIcon, UserIcon } from "@heroicons/react/24/solid"; +import { ArrowsPointingOutIcon, ArrowsPointingInIcon, StarIcon as OutlineStarIcon, ListBulletIcon } from '@heroicons/react/24/outline'; import Card from '@/components/page/Card' @@ -16,15 +16,16 @@ type DrawerProps = { editableContent?: any; onSave?: (content: any) => void; rowContent?: any; + onRowUpdate?: (content: any) => void; }; interface EditContent { content: string; isEditing: boolean; - } +} -const Drawer: FunctionComponent = ({ title, children, onSave, editableContent, rowContent }) => { +const Drawer: FunctionComponent = ({ title, children, onSave, editableContent, rowContent, onRowUpdate }) => { const [isOpen, setIsOpen] = useState(false); const [isFull, setIsFull] = useState(false); const [isEditing, setIsEditing] = useState(false); @@ -33,7 +34,27 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita const [currentCardIcon, setCurrentCardIcon] = useState(''); const [error, setError] = useState(null); const [isFavorite, setIsFavorite] = useState(false); + const [tempRowContent, setTempRowContent] = useState(rowContent); + const handleTempRowContentChange = (e) => { + const { name, value } = e.target; + console.log(name); + console.log(value); + setTempRowContent((prevContent) => ({ + ...prevContent, + [name]: value, + })); + }; + + const handleEnterPress = (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + // Update the rowContent with the temporaryRowContent + if(onRowUpdate) { + onRowUpdate(tempRowContent); + } + } + }; const toggleDrawer = () => { setIsOpen(!isOpen); @@ -81,7 +102,7 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita if (onSave) { onSave(updatedContents); } - }; + }; const toggleEdit = (index: number) => { const newContents = editContents.map((item, idx) => idx === index ? { ...item, isEditing: !item.isEditing } : item); @@ -107,12 +128,10 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita
-
-
- - {currentCardIcon} - -

{rowContent.username}

+
+
+ {currentCardIcon} +

{rowContent.username}

-
-
- Username: { rowContent.username } -
-
- Role: { rowContent.role } -
-
- Email: { rowContent.email } -
-
- Program: { rowContent.program } -
+ + + + + + + + + + + + + + + + + + + + + + + +
Username{rowContent.username}
Role{rowContent.role}
Email +
Type of Program{rowContent.program}

- { - editContents.map((item, index) => ( -
- {item.isEditing ? ( - <> - - - - ) : ( - <> - {item.content} - - - )} - {/* Delete button moved here, outside of the editing conditional */} - -
- )) -} - -
+ {/* {editContents.map((item, index) => ( +
+ {item.isEditing ? ( + <> + + + + ) : ( + <> + {item.content} + + + )} + +
+ ))} + */} +
); From c53e12d7760b488e8728141d7ae2978f08f6dcea Mon Sep 17 00:00:00 2001 From: Varun Murlidhar Date: Sat, 20 Apr 2024 11:58:18 -0400 Subject: [PATCH 18/19] Drawer changes --- compass/components/page/Drawer.tsx | 49 +++++++++--------------------- 1 file changed, 15 insertions(+), 34 deletions(-) diff --git a/compass/components/page/Drawer.tsx b/compass/components/page/Drawer.tsx index b22ac8a..5697235 100644 --- a/compass/components/page/Drawer.tsx +++ b/compass/components/page/Drawer.tsx @@ -119,12 +119,9 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita const favoriteIcon = isFavorite ? : - // const buttonStyle = `ml-2 uppercase opacity-0 group-hover:opacity-100 text-gray-500 font-medium border bg-white ${isOpen ? `border-gray-200` : ``} shadow hover:bg-gray-50 p-2 rounded-md` - return (
- {/* } text="Open" onClick={() => handleCardClick("Resources", )}/> */}
@@ -150,18 +147,25 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita - Username - {rowContent.username} + Username + + - Role - {rowContent.role} + Role + {rowContent.role} - Email - + Email + = ({ title, children, onSave, edita - Type of Program - {rowContent.program} + Type of Program + {rowContent.program}
- {/* {editContents.map((item, index) => ( -
- {item.isEditing ? ( - <> - - - - ) : ( - <> - {item.content} - - - )} - -
- ))} - */}
From 7e36404757d2f114fe2b0b6ef78e4224c6c73502 Mon Sep 17 00:00:00 2001 From: Varun Murlidhar Date: Sat, 20 Apr 2024 14:38:17 -0400 Subject: [PATCH 19/19] Table styling --- compass/components/page/Drawer.tsx | 107 ++++++++++------------------- 1 file changed, 37 insertions(+), 70 deletions(-) diff --git a/compass/components/page/Drawer.tsx b/compass/components/page/Drawer.tsx index 5697235..ffa4304 100644 --- a/compass/components/page/Drawer.tsx +++ b/compass/components/page/Drawer.tsx @@ -28,11 +28,7 @@ interface EditContent { const Drawer: FunctionComponent = ({ title, children, onSave, editableContent, rowContent, onRowUpdate }) => { const [isOpen, setIsOpen] = useState(false); const [isFull, setIsFull] = useState(false); - const [isEditing, setIsEditing] = useState(false); - const [editContents, setEditContents] = useState(editableContent || [{ content: '', isEditing: true }]); - const [currentCardText, setCurrentCardText] = useState(""); const [currentCardIcon, setCurrentCardIcon] = useState(''); - const [error, setError] = useState(null); const [isFavorite, setIsFavorite] = useState(false); const [tempRowContent, setTempRowContent] = useState(rowContent); @@ -66,55 +62,12 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita const toggleDrawerFullScreen = () => setIsFull(!isFull); const toggleFavorite = () => setIsFavorite(!isFavorite); - - const handleCardClick = (text: string, icon: ReactElement) => { - console.log('click') - toggleDrawer(); - setCurrentCardText(text); - setCurrentCardIcon(icon)}; - const toggleEditing = () => setIsEditing(!isEditing); - const handleInputChange = (index: number) => (event: React.ChangeEvent) => { - const newContents = editContents.map((item, idx) => idx === index ? { ...item, content: event.target.value } : item); - setEditContents(newContents); - }; const drawerClassName = `fixed top-0 right-0 h-full bg-white transform ease-in-out duration-300 ${ isOpen ? "translate-x-0 shadow-xl" : "translate-x-full" } ${isFull ? "w-full" : "w-1/2"}`; - const addInput = () => { - setEditContents([...editContents, { content: '', isEditing: true }]); - }; - - const saveIndividualChange = (index: number) => { - const content = editContents[index].content.trim(); - if (!content) { - setError("Input cannot be empty."); - return; - } - - setError(null); // Clear error state if input passes validation - - const updatedContents = editContents.map((item, idx) => idx === index ? { ...item, isEditing: false } : item); - setEditContents(updatedContents); - - if (onSave) { - onSave(updatedContents); - } - }; - - const toggleEdit = (index: number) => { - const newContents = editContents.map((item, idx) => idx === index ? { ...item, isEditing: !item.isEditing } : item); - setEditContents(newContents); - }; - - const deleteInput = (index: number) => { - // Filter out the input at the given index - const filteredContents = editContents.filter((_, idx) => idx !== index); - setEditContents(filteredContents); - }; - const iconComponent = isFull ? : ; const favoriteIcon = isFavorite ? : @@ -128,7 +81,7 @@ const Drawer: FunctionComponent = ({ title, children, onSave, edita
{currentCardIcon} -

{rowContent.username}

+

{rowContent.username}

- - - - - + +
+
+ + + - - - - + +
+
+ + + - - - - +
+
+ + + - - - - + +
+
+ + +
Username +
Username
Role{rowContent.role}
Role + {rowContent.role} +
Email +
Email
Type of Program{rowContent.program}
Type of Program + {rowContent.program} +