From 0a0c9ac27bcae36c7b11cc08da5a764b3e3b6738 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Sat, 18 Nov 2023 22:44:30 -0300 Subject: [PATCH] Modularized Tags Selection and created share modal --- .../tagsSelectorComponent/index.tsx | 105 +++++++++++++++--- src/frontend/src/modals/shareModal/index.tsx | 91 ++++++--------- src/frontend/src/pages/StorePage/index.tsx | 101 ++--------------- 3 files changed, 133 insertions(+), 164 deletions(-) diff --git a/src/frontend/src/components/tagsSelectorComponent/index.tsx b/src/frontend/src/components/tagsSelectorComponent/index.tsx index c371816be..50be6b87e 100644 --- a/src/frontend/src/components/tagsSelectorComponent/index.tsx +++ b/src/frontend/src/components/tagsSelectorComponent/index.tsx @@ -1,26 +1,101 @@ -import TagComponent from "./tagComponent"; +import { useEffect, useRef, useState } from "react"; +import { cn } from "../../utils/utils"; +import { Badge } from "../ui/badge"; export function TagsSelector({ tags, + disabled = false, + loadingTags, selectedTags, setSelectedTags, }: { - tags: string[]; - selectedTags: Set; - setSelectedTags: (tag: string) => void; + tags: { id: string; name: string }[]; + disabled?: boolean; + loadingTags: boolean; + selectedTags: any[]; + setSelectedTags: (tags: any[]) => void; }) { + const updateTags = (tagName: string) => { + const index = selectedTags.indexOf(tagName); + let newArray = + index === -1 + ? [...selectedTags, tagName] + : selectedTags.filter((_, i) => i !== index); + setSelectedTags(newArray); + }; + + const scrollContainerRef = useRef(null); + const fadeContainerRef = useRef(null); + const [divWidth, setDivWidth] = useState(0); + + useEffect(() => { + const handleResize = () => { + if (scrollContainerRef.current) { + setDivWidth(scrollContainerRef.current.clientWidth); + } + }; + + window.addEventListener("resize", handleResize); + handleResize(); // call the function at start to get the initial width + return () => window.removeEventListener("resize", handleResize); + }, []); + + useEffect(() => { + const handleScroll = () => { + if (!scrollContainerRef.current || !fadeContainerRef.current) return; + + const { scrollLeft, scrollWidth, clientWidth } = + scrollContainerRef.current; + const atStart = scrollLeft === 0; + const atEnd = scrollLeft === scrollWidth - clientWidth; + const isScrollable = scrollWidth > clientWidth; + + fadeContainerRef.current.classList.toggle( + "fade-left", + isScrollable && !atStart + ); + fadeContainerRef.current.classList.toggle( + "fade-right", + isScrollable && !atEnd + ); + }; + + const scrollContainer = scrollContainerRef.current; + if (scrollContainer) { + scrollContainer.addEventListener("scroll", handleScroll); + // Delay the initial scroll event dispatch to ensure correct calculation + scrollContainer.dispatchEvent(new Event("scroll")); + return () => scrollContainer.removeEventListener("scroll", handleScroll); + } + }, [divWidth, loadingTags]); // Depend on divWidth + return ( -
- {tags.map((tag, index) => { - return ( - - ); - })} +
+
+ {!loadingTags && + tags.map((tag, idx) => ( + + ))} +
); } diff --git a/src/frontend/src/modals/shareModal/index.tsx b/src/frontend/src/modals/shareModal/index.tsx index 312ce4be6..e754984ff 100644 --- a/src/frontend/src/modals/shareModal/index.tsx +++ b/src/frontend/src/modals/shareModal/index.tsx @@ -9,7 +9,6 @@ import { import EditFlowSettings from "../../components/EditFlowSettingsComponent"; import IconComponent from "../../components/genericIconComponent"; import { TagsSelector } from "../../components/tagsSelectorComponent"; -import ToggleShadComponent from "../../components/toggleShadComponent"; import { Button } from "../../components/ui/button"; import { Checkbox } from "../../components/ui/checkbox"; import { alertContext } from "../../contexts/alertContext"; @@ -42,36 +41,29 @@ const ShareModal = forwardRef( const nameComponent = props.is_component ? "Component" : "Flow"; - const [tags, setTags] = useState([]); + const [tags, setTags] = useState<{ id: string; name: string }[]>([]); + const [loadingTags, setLoadingTags] = useState(false); const [sharePublic, setSharePublic] = useState(true); - const [selectedTags, setSelectedTags] = useState>(new Set()); + const [selectedTags, setSelectedTags] = useState([]); const tagListId = useRef<{ id: string; name: string }[]>([]); useEffect(() => { - getStoreTags().then((res) => { - tagListId.current = res; - let tags = res.map((tag) => tag.name); - setTags(tags); - }); + handleGetTags(); }, []); + function handleGetTags() { + setLoadingTags(true); + getStoreTags().then((res) => { + setTags(res); + setLoadingTags(false); + }); + } + useEffect(() => { setName(props.component?.name ?? ""); setDescription(props.component?.description ?? ""); }, [props.component]); - function handleTagSelection(tag: string) { - setSelectedTags((prev) => { - const newSet = new Set(prev); - if (newSet.has(tag)) { - newSet.delete(tag); - } else { - newSet.add(tag); - } - return newSet; - }); - } - const handleShareComponent = () => { const saveFlow: FlowType = checked ? { @@ -92,7 +84,7 @@ const ShareModal = forwardRef( }); saveFlowStore( saveFlow, - getTagsIds(Array.from(selectedTags), tagListId), + getTagsIds(selectedTags, tagListId), sharePublic ).then( () => { @@ -138,6 +130,27 @@ const ShareModal = forwardRef( setName={setName} setDescription={setDescription} /> +
+ +
+
+ { + setSharePublic(event); + }} + /> + +
-
-
- -
{ - setSharePublic(!sharePublic); - }} - > - {sharePublic ? ( - - This flow will be avaliable for everyone - - ) : ( - - This flow will be avaliable just for you - - )} -
-
-
- - Add some tags to your {nameComponent} - - -
-
diff --git a/src/frontend/src/pages/StorePage/index.tsx b/src/frontend/src/pages/StorePage/index.tsx index 8931b7276..31e834dfe 100644 --- a/src/frontend/src/pages/StorePage/index.tsx +++ b/src/frontend/src/pages/StorePage/index.tsx @@ -1,15 +1,15 @@ import { uniqueId } from "lodash"; -import { useContext, useEffect, useRef, useState } from "react"; +import { useContext, useEffect, useState } from "react"; import PaginatorComponent from "../../components/PaginatorComponent"; import ShadTooltip from "../../components/ShadTooltipComponent"; import CollectionCardComponent from "../../components/cardComponent"; import IconComponent from "../../components/genericIconComponent"; import PageLayout from "../../components/pageLayout"; import { SkeletonCardComponent } from "../../components/skeletonCardComponent"; -import { Badge } from "../../components/ui/badge"; import { Button } from "../../components/ui/button"; import { Input } from "../../components/ui/input"; +import { TagsSelector } from "../../components/tagsSelectorComponent"; import { Select, SelectContent, @@ -44,51 +44,6 @@ export default function StorePage(): JSX.Element { const [searchNow, setSearchNow] = useState(""); const [selectFilter, setSelectFilter] = useState("all"); - const scrollContainerRef = useRef(null); - const fadeContainerRef = useRef(null); - const [divWidth, setDivWidth] = useState(0); - - useEffect(() => { - const handleResize = () => { - if (scrollContainerRef.current) { - setDivWidth(scrollContainerRef.current.clientWidth); - } - }; - - window.addEventListener("resize", handleResize); - handleResize(); // call the function at start to get the initial width - return () => window.removeEventListener("resize", handleResize); - }, []); - - useEffect(() => { - const handleScroll = () => { - if (!scrollContainerRef.current || !fadeContainerRef.current) return; - - const { scrollLeft, scrollWidth, clientWidth } = - scrollContainerRef.current; - const atStart = scrollLeft === 0; - const atEnd = scrollLeft === scrollWidth - clientWidth; - const isScrollable = scrollWidth > clientWidth; - - fadeContainerRef.current.classList.toggle( - "fade-left", - isScrollable && !atStart - ); - fadeContainerRef.current.classList.toggle( - "fade-right", - isScrollable && !atEnd - ); - }; - - const scrollContainer = scrollContainerRef.current; - if (scrollContainer) { - scrollContainer.addEventListener("scroll", handleScroll); - // Delay the initial scroll event dispatch to ensure correct calculation - scrollContainer.dispatchEvent(new Event("scroll")); - return () => scrollContainer.removeEventListener("scroll", handleScroll); - } - }, [divWidth, loadingTags]); // Depend on divWidth - useEffect(() => { handleGetTags(); }, []); @@ -184,19 +139,6 @@ export default function StorePage(): JSX.Element { }); } - const updateTags = (tagName: string) => { - setFilterCategories((prevArray) => { - const index = prevArray.indexOf(tagName); - if (index === -1) { - // Item does not exist in array, add it - return [...prevArray, tagName]; - } else { - // Item exists in array, remove it - return prevArray.filter((_, i) => i !== index); - } - }); - }; - return ( -
-
- {!loadingTags && - tags.map((tag, idx) => ( - - ))} -
-
+