diff --git a/ui/src/components/General/Search/index.tsx b/ui/src/components/General/Search/index.tsx index 6ec53f59..c48ab619 100644 --- a/ui/src/components/General/Search/index.tsx +++ b/ui/src/components/General/Search/index.tsx @@ -1,46 +1,24 @@ import { Input } from "antd"; import style from "./search.module.scss"; -import { QUERY_KEY_NEWS } from "pages/Newsfeed"; -import { useSearchParams } from "react-router-dom"; import CategoryTags from "./CategoryTags"; -import { useState, useEffect, ChangeEvent } from "react"; +import { ChangeEvent } from "react"; interface SearchProps { categories: string[]; resourceName: string; isLoading: boolean; + searchQuery: string; + categoryQuery: string; + onSearchCriteriaChange: (queryType: "q" | "cat", value: string) => void; } const Search: React.FC = ({ - resourceName, categories, isLoading, + searchQuery, + categoryQuery, + onSearchCriteriaChange, }) => { - const [searchParams, setSearchParams] = useSearchParams(); - const [queryParams, setQueryParams] = useState({ - q: searchParams.get("q") || "", - cat: searchParams.get("cat") || "", - }); - - const { q: searchQuery, cat: categoryQuery } = queryParams; - - useEffect(() => { - if (resourceName === QUERY_KEY_NEWS) { - setSearchParams(`?q=${searchQuery}`); - } else { - setSearchParams(`?q=${searchQuery}&cat=${categoryQuery}`); - } - }, [searchQuery, categoryQuery, setSearchParams, resourceName]); - - const handleSearchChange = (e: ChangeEvent) => { - const value = e.target.value; - setQueryParams((prevParams) => ({ ...prevParams, q: value })); - }; - - const handleCategoryChange = (value: string) => { - setQueryParams((prevParams) => ({ ...prevParams, cat: value })); - }; - return (
= ({ type="text" placeholder="Search by title..." value={searchQuery} - onChange={handleSearchChange} + onChange={(e: ChangeEvent) => { + onSearchCriteriaChange("q", e.target.value); + }} disabled={isLoading} /> { + onSearchCriteriaChange("cat", value); + }} className={style.search__category} />
diff --git a/ui/src/components/Layouts/Menu/utils/constants.ts b/ui/src/components/Layouts/Menu/utils/constants.ts index 1f76648e..f743422e 100644 --- a/ui/src/components/Layouts/Menu/utils/constants.ts +++ b/ui/src/components/Layouts/Menu/utils/constants.ts @@ -1,9 +1,16 @@ import { MenuProps } from "antd"; import { IconName } from "components/General/Icon/utils/types"; import { getItem } from "components/Layouts/Menu/utils/helper"; +import { routes } from "pages/Routes/utils/constant"; +import { Route, RouteId } from "pages/Routes/utils/types"; const IN_DEVELOPMENT = import.meta.env.DEV; +const routesById = routes.reduce((acc, route) => { + acc[route.id] = route; + return acc; +}, {} as Record); + export const MENU_ITEMS = [ { name: "Newsfeed", @@ -11,8 +18,8 @@ export const MENU_ITEMS = [ show: true, children: [ { - name: "News", - url: "/newsfeed", + name: routesById.newsfeed.title, + url: routesById.newsfeed.path, icon: "Mailbox", show: true, }, @@ -24,14 +31,14 @@ export const MENU_ITEMS = [ show: true, children: [ { - name: "Color Picker", - url: "/colors/cp", + name: routesById.colorpicker.title, + url: routesById.colorpicker.path, icon: "Baseline", show: true, }, { - name: "Shades & Tints", - url: "/colors/shades-tints", + name: routesById.shadesandtints.title, + url: routesById.shadesandtints.path, icon: "Layers", show: true, }, @@ -43,20 +50,20 @@ export const MENU_ITEMS = [ show: true, children: [ { - name: "Border Radius", - url: "/css/br", + name: routesById.borderradius.title, + url: routesById.borderradius.path, icon: "Square", show: true, }, { - name: "Box Shadow", - url: "/css/bs", + name: routesById.boxshadow.title, + url: routesById.boxshadow.path, icon: "Box", show: IN_DEVELOPMENT, }, { - name: "Svg Formatter", - url: "/css/svg-formatter", + name: routesById.svgformatter.title, + url: routesById.svgformatter.path, icon: "Command", show: true, }, @@ -68,20 +75,20 @@ export const MENU_ITEMS = [ show: true, children: [ { - name: "Base64", - url: "/converter/base-64", + name: routesById.base64.title, + url: routesById.base64.path, icon: "Replace", show: true, }, { - name: "Pixel", - url: "/converter/pixel", + name: routesById.pixelconverter.title, + url: routesById.pixelconverter.path, icon: "FileOutput", show: true, }, { - name: "JSON To TypeScript", - url: "/converter/jtt", + name: routesById.jsontotypescript.title, + url: routesById.jsontotypescript.path, icon: "FileOutput", show: true, }, @@ -93,32 +100,32 @@ export const MENU_ITEMS = [ show: true, children: [ { - name: "Data", - url: "/generator/data", + name: routesById.data.title, + url: routesById.data.path, icon: "DatabaseBackup", show: true, }, { - name: "Image", - url: "/generator/igfc", + name: routesById.image.title, + url: routesById.image.path, icon: "Image", show: true, }, { - name: "Avatar", - url: "/generator/avatar", + name: routesById.avatar.title, + url: routesById.avatar.path, icon: "BadgeHelp", show: true, }, { - name: "QR Code", - url: "/generator/qrcode", + name: routesById.qrcode.title, + url: routesById.qrcode.path, icon: "QrCode", show: true, }, { - name: "Sorting", - url: "/generator/sorting", + name: routesById.sorting.title, + url: routesById.sorting.path, icon: "ArrowUpNarrowWide", show: true, }, @@ -130,20 +137,20 @@ export const MENU_ITEMS = [ show: true, children: [ { - name: "Editor", - url: "/markdown/me", + name: routesById.editor.title, + url: routesById.editor.path, icon: "FileEdit", show: true, }, { - name: "Table", - url: "/markdown/md-table-generator", + name: routesById.table.title, + url: routesById.table.path, icon: "Dice5", show: true, }, { - name: "Table Of Content", - url: "/markdown/toc", + name: routesById.tableofcontent.title, + url: routesById.tableofcontent.path, icon: "Table", show: true, }, @@ -155,8 +162,8 @@ export const MENU_ITEMS = [ show: true, children: [ { - name: "Text Editor", - url: "/text/te", + name: routesById.texteditor.title, + url: routesById.texteditor.path, icon: "ClipboardEdit", show: true, }, @@ -168,8 +175,8 @@ export const MENU_ITEMS = [ show: true, children: [ { - name: "Mimetype", - url: "/information/mimetype", + name: routesById.mimetype.title, + url: routesById.mimetype.path, icon: "ArrowLeftRight", show: true, }, @@ -181,80 +188,80 @@ export const MENU_ITEMS = [ show: true, children: [ { - name: "Blog", - url: "/resource/blog", + name: routesById.blog.title, + url: routesById.blog.path, icon: "Keyboard", show: true, }, { - name: "Book", - url: "/resource/book", + name: routesById.book.title, + url: routesById.book.path, icon: "BookOpen", show: true, }, { - name: "Course", - url: "/resource/course", + name: routesById.course.title, + url: routesById.course.path, icon: "GraduationCap", show: true, }, { - name: "Design System", - url: "/resource/design-system", + name: routesById.designsystem.title, + url: routesById.designsystem.path, icon: "LayoutDashboard", show: true, }, { - name: "Github", - url: "/resource/github", + name: routesById.github.title, + url: routesById.github.path, icon: "Github", show: true, }, { - name: "Icon", - url: "/resource/icon", + name: routesById.icon.title, + url: routesById.icon.path, icon: "Square", show: true, }, { - name: "Movie", - url: "/resource/movie", + name: routesById.movie.title, + url: routesById.movie.path, icon: "Clapperboard", show: true, }, { - name: "Platform", - url: "/resource/platform", + name: routesById.platform.title, + url: routesById.platform.path, icon: "Server", show: true, }, { - name: "Plugin", - url: "/resource/plugin", + name: routesById.plugin.title, + url: routesById.plugin.path, icon: "Plug", show: true, }, { - name: "Tool", - url: "/resource/tool", + name: routesById.tool.title, + url: routesById.tool.path, icon: "Wrench", show: true, }, { - name: "TV Series", - url: "/resource/tv-series", + name: routesById.tvseries.title, + url: routesById.tvseries.path, icon: "Tv", show: true, }, { - name: "UI/UX", - url: "/resource/ui-ux", + name: routesById.uiux.title, + url: routesById.uiux.path, icon: "Brush", show: true, }, { - name: "Youtube", - url: "/resource/youtube", + name: routesById.youtube.title, + url: routesById.youtube.path, icon: "Youtube", show: true, }, diff --git a/ui/src/components/RenderProps/ListSearchResults/index.tsx b/ui/src/components/RenderProps/ListSearchResults/index.tsx index f29bfe34..b420ede0 100644 --- a/ui/src/components/RenderProps/ListSearchResults/index.tsx +++ b/ui/src/components/RenderProps/ListSearchResults/index.tsx @@ -22,7 +22,7 @@ const ListSearchResults = ({ isError, source = "", }: ListSearchResultsProps): ReactElement => { - const [searchParams] = useSearchParams(); + const [searchParams, setSearchParams] = useSearchParams(); if (isError) { return ; @@ -46,12 +46,20 @@ const ListSearchResults = ({ const categories = getCategories(items as ResourceType[], resourceName); + const onSearchCriteriaChange = (queryType: "q" | "cat", value: string) => { + searchParams.set(queryType, value); + setSearchParams(searchParams); + }; + return (
{ - const [params, updateParams, searchParams] = useUrlParams({ - color: INITIAL_COLOR, - }); - - const [color, setColor] = useState( - searchParams.get("color") || (params.color as string) - ); + const [searchParams, setSearchParams] = useSearchParams(); + const color = String(searchParams.get("color") || INITIAL_COLOR); const [format, setFormat] = useState( determineFormat(color) || INITIAL_FORMAT @@ -29,15 +23,24 @@ const ColorPicker: React.FC = () => { const colors = useMemo(() => calculateColors(color), [color]); + const setColor = (color: string) => { + searchParams.set("color", color); + setSearchParams(searchParams); + }; + const onInputChange = (e: ChangeEvent) => { const input = e.target.value.trim(); - setColor(input); + searchParams.set("color", input); + setSearchParams(searchParams); setFormat(determineFormat(input)); }; useEffect(() => { - updateParams("color", color); - }, [color]); + if (!searchParams.get("color")) { + searchParams.set("color", INITIAL_COLOR); + setSearchParams(searchParams); + } + }, []); return (
diff --git a/ui/src/pages/Routes/utils/constant.tsx b/ui/src/pages/Routes/utils/constant.tsx index 63780e89..c8432dac 100644 --- a/ui/src/pages/Routes/utils/constant.tsx +++ b/ui/src/pages/Routes/utils/constant.tsx @@ -38,182 +38,212 @@ import { YouTube, } from "pages/pages"; -const routes: Route[] = [ +export const routes: Route[] = [ { + id: "newsfeed", path: "/newsfeed", title: "Newsfeed", description: "Get the scoop! Fresh news served daily.", component: News, }, { + id: "colorpicker", path: "/colors/cp", title: "Color Picker", description: "Unleash your inner Picasso & pick the perfect hue.", component: ColorPicker, }, { + id: "shadesandtints", path: "/colors/shades-tints", title: "Shades & Tints", description: "50 shades of any color you fancy!", component: ShadesAndTints, }, { + id: "borderradius", path: "/css/br", title: "Border Radius", description: "Shape up your CSS with some smooth curves.", component: BorderRadius, }, { + id: "boxshadow", path: "/css/bs", title: "Box Shadow", description: "Add drama to your box! Shadows included.", component: BoxShadow, }, { + id: "svgformatter", path: "/css/svg-formatter", title: "SVG Formatter", description: "Get your SVGs in shipshape.", component: SvgFormatter, }, { + id: "base64", path: "/converter/base-64", title: "Base64", description: "Encode, decode, and party in Base64 style.", component: Base64, }, { + id: "pixelconverter", path: "/converter/pixel", title: "Pixel Converter", description: "Pixels to units - like magic, but real!", component: Pixel, }, { + id: "jsontotypescript", path: "/converter/jtt", title: "Json To Typescript", description: "Turn your JSON into TypeScript's next top model.", component: JsonToTypescript, }, { + id: "data", path: "/generator/data", title: "Data", description: "Make it rain with random data.", component: DataGenerator, }, { + id: "avatar", path: "/generator/avatar", title: "Avatar", description: "Create funky avatars. No airbending skills required.", component: Avatar, }, { + id: "image", path: "/generator/igfc", title: "Image", description: "Craft beautiful images from a simple palette of colors.", component: ImageGeneratorFromColors, }, { + id: "qrcode", path: "/generator/qrcode", title: "QR Code", description: "Generate QR codes - like barcodes, but squarer!", component: QRcode, }, { + id: "sorting", path: "/generator/sorting", title: "Sorting", description: "Sort arrays like a boss.", component: Sorting, }, { + id: "blog", path: "/resource/blog", title: "Blog", description: "Feast your eyes on our riveting reads.", component: Blog, }, { + id: "book", path: "/resource/book", title: "Book", description: "Dive into our library of literary treasures.", component: Book, }, { + id: "course", path: "/resource/course", title: "Course", description: "Learn new tricks without any Hogwarts tuition fees.", component: Course, }, { + id: "designsystem", path: "/resource/design-system", title: "Design System", description: "Marvel at the methods behind our design madness.", component: DesignSystem, }, { + id: "github", path: "/resource/github", title: "Github", description: "Peek at our code in its natural habitat.", component: Github, }, { + id: "icon", path: "/resource/icon", title: "Icon", description: "Icons galore! Pick 'em, use 'em, love 'em.", component: Icon, }, { + id: "movie", path: "/resource/movie", title: "Movie", description: "Roll out the red carpet for our movie collection.", component: Movie, }, { + id: "platform", path: "/resource/platform", title: "Platform", description: "Step up to our platform of choice resources.", component: Platform, }, { + id: "plugin", path: "/resource/plugin", title: "Plugin", description: "Plugins to power up your projects.", component: Plugin, }, { + id: "tool", path: "/resource/tool", title: "Tool", description: "Tools of the trade to make your work a breeze.", component: Tool, }, { + id: "tvseries", path: "/resource/tv-series", title: "TV Series", description: "Get comfy with our collection of binge-worthy TV series.", component: TvSeries, }, { + id: "uiux", path: "/resource/ui-ux", title: "UI/UX", description: "Feast your eyes on the finest UI/UX resources.", component: UiUx, }, { + id: "youtube", path: "/resource/youtube", title: "Youtube", description: "Dive into our YouTube video vault.", component: YouTube, }, { + id: "editor", path: "/markdown/me", title: "Editor", description: "Markdown Editor - for words that mark the spot.", component: MarkdownEditor, }, { + id: "table", path: "/markdown/md-table-generator", title: "Table", description: "Create tables that would make any spreadsheet jealous.", component: TableGenerator, }, { + id: "tableofcontent", path: "/markdown/toc", title: "Table Of Content", description: @@ -221,41 +251,45 @@ const routes: Route[] = [ component: TableOfContent, }, { + id: "texteditor", path: "/text/te", title: "Text Editor", description: "For those who love to play with words.", component: TextEditor, }, { + id: "mimetype", path: "/information/mimetype", title: "Mimetype", description: "Find out what type your file fancies itself as.", component: Mimetype, }, { + id: "/", path: "/", title: "", description: "", component: Home, }, { + id: "about", path: "/about", title: "About", description: "All the juicy details about us.", component: About, }, { + id: "feedback", path: "/feedback", title: "Feedback", description: "We're all ears for your cheers or jeers.", component: Feedback, }, { + id: "pagenotfound", path: "*", title: "Page Not Found", description: "", component: PageNotFound, }, ]; - -export { routes }; diff --git a/ui/src/pages/Routes/utils/types.ts b/ui/src/pages/Routes/utils/types.ts index e204999e..1624883f 100644 --- a/ui/src/pages/Routes/utils/types.ts +++ b/ui/src/pages/Routes/utils/types.ts @@ -1,8 +1,47 @@ +type RouteId = + | "newsfeed" + | "colorpicker" + | "shadesandtints" + | "borderradius" + | "boxshadow" + | "svgformatter" + | "base64" + | "pixelconverter" + | "jsontotypescript" + | "data" + | "avatar" + | "image" + | "qrcode" + | "sorting" + | "blog" + | "book" + | "course" + | "designsystem" + | "github" + | "icon" + | "movie" + | "platform" + | "plugin" + | "tool" + | "tvseries" + | "uiux" + | "youtube" + | "editor" + | "table" + | "tableofcontent" + | "texteditor" + | "mimetype" + | "/" + | "about" + | "feedback" + | "pagenotfound"; + interface Route { path: string; title: string; description: string; component: React.FC; + id: RouteId; } -export type { Route }; +export type { Route, RouteId };