From cbaa1e822b5e540633530e7161f382017439e851 Mon Sep 17 00:00:00 2001 From: Rajgupta36 Date: Fri, 24 Jan 2025 02:22:29 +0530 Subject: [PATCH 1/9] fix --- frontend/package-lock.json | 2 +- frontend/package.json | 2 +- frontend/src/components/SortBy.tsx | 66 ++++----- frontend/src/components/ui/close-button.tsx | 17 +++ frontend/src/components/ui/select.tsx | 143 ++++++++++++++++++++ frontend/src/utils/sortingOptions.ts | 26 ++-- 6 files changed, 207 insertions(+), 49 deletions(-) create mode 100644 frontend/src/components/ui/close-button.tsx create mode 100644 frontend/src/components/ui/select.tsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index dbdd3ef0f..8ac23190e 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -43,7 +43,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "react-gtm-module": "^2.0.11", - "react-icons": "^5.3.0", + "react-icons": "^5.4.0", "react-leaflet": "^5.0.0", "react-router-dom": "^7.0.2", "react-tooltip": "^5.28.0", diff --git a/frontend/package.json b/frontend/package.json index 6a166372d..dd661946c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -53,7 +53,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "react-gtm-module": "^2.0.11", - "react-icons": "^5.3.0", + "react-icons": "^5.4.0", "react-leaflet": "^5.0.0", "react-router-dom": "^7.0.2", "react-tooltip": "^5.28.0", diff --git a/frontend/src/components/SortBy.tsx b/frontend/src/components/SortBy.tsx index 19974db81..35fef50dc 100644 --- a/frontend/src/components/SortBy.tsx +++ b/frontend/src/components/SortBy.tsx @@ -1,12 +1,11 @@ -import { faCaretDown, faCaretUp, faCheck } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { useState } from 'react' import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from 'components/ui/dropdownMenu' + SelectContent, + SelectItem, + SelectLabel, + SelectRoot, + SelectTrigger, + SelectValueText, +} from 'components/ui/select' interface SortOption { value: string @@ -14,43 +13,38 @@ interface SortOption { } interface SortByProps { - options: SortOption[] + options: any selectedOption: string onSortChange: (value: string) => void } const SortBy = ({ options, selectedOption, onSortChange }: SortByProps) => { - const [open, setOpen] = useState(false) - const handleOpenChange = (isOpen: boolean) => { - setOpen(isOpen) - } - + console.log(selectedOption) if (!options || options.length === 0) return null - return ( - - - - - - {options.map((option) => ( - onSortChange(option.value)} - className="justify-between" + { + onSortChange(e.value[0]) + }} + > + + + + + {options.items.map((sortAttribute) => ( + - {option.label} - {option.value === selectedOption && } - + {sortAttribute.label} + ))} - - + + ) } diff --git a/frontend/src/components/ui/close-button.tsx b/frontend/src/components/ui/close-button.tsx new file mode 100644 index 000000000..94af48859 --- /dev/null +++ b/frontend/src/components/ui/close-button.tsx @@ -0,0 +1,17 @@ +import type { ButtonProps } from "@chakra-ui/react" +import { IconButton as ChakraIconButton } from "@chakra-ui/react" +import * as React from "react" +import { LuX } from "react-icons/lu" + +export type CloseButtonProps = ButtonProps + +export const CloseButton = React.forwardRef< + HTMLButtonElement, + CloseButtonProps +>(function CloseButton(props, ref) { + return ( + + {props.children ?? } + + ) +}) diff --git a/frontend/src/components/ui/select.tsx b/frontend/src/components/ui/select.tsx new file mode 100644 index 000000000..99d84e6c5 --- /dev/null +++ b/frontend/src/components/ui/select.tsx @@ -0,0 +1,143 @@ +"use client" + +import type { CollectionItem } from "@chakra-ui/react" +import { Select as ChakraSelect, Portal } from "@chakra-ui/react" +import { CloseButton } from "./close-button" +import * as React from "react" + +interface SelectTriggerProps extends ChakraSelect.ControlProps { + clearable?: boolean +} + +export const SelectTrigger = React.forwardRef< + HTMLButtonElement, + SelectTriggerProps +>(function SelectTrigger(props, ref) { + const { children, clearable, ...rest } = props + return ( + + {children} + + {clearable && } + + + + ) +}) + +const SelectClearTrigger = React.forwardRef< + HTMLButtonElement, + ChakraSelect.ClearTriggerProps +>(function SelectClearTrigger(props, ref) { + return ( + + + + ) +}) + +interface SelectContentProps extends ChakraSelect.ContentProps { + portalled?: boolean + portalRef?: React.RefObject +} + +export const SelectContent = React.forwardRef< + HTMLDivElement, + SelectContentProps +>(function SelectContent(props, ref) { + const { portalled = true, portalRef, ...rest } = props + return ( + + + + + + ) +}) + +export const SelectItem = React.forwardRef< + HTMLDivElement, + ChakraSelect.ItemProps +>(function SelectItem(props, ref) { + const { item, children, ...rest } = props + return ( + + {children} + + + ) +}) + +interface SelectValueTextProps + extends Omit { + children?(items: CollectionItem[]): React.ReactNode +} + +export const SelectValueText = React.forwardRef< + HTMLSpanElement, + SelectValueTextProps +>(function SelectValueText(props, ref) { + const { children, ...rest } = props + return ( + + + {(select) => { + const items = select.selectedItems + if (items.length === 0) return props.placeholder + if (children) return children(items) + if (items.length === 1) + return select.collection.stringifyItem(items[0]) + return `${items.length} selected` + }} + + + ) +}) + +export const SelectRoot = React.forwardRef< + HTMLDivElement, + ChakraSelect.RootProps +>(function SelectRoot(props, ref) { + return ( + + {props.asChild ? ( + props.children + ) : ( + <> + + {props.children} + + )} + + ) +}) as ChakraSelect.RootComponent + +interface SelectItemGroupProps extends ChakraSelect.ItemGroupProps { + label: React.ReactNode +} + +export const SelectItemGroup = React.forwardRef< + HTMLDivElement, + SelectItemGroupProps +>(function SelectItemGroup(props, ref) { + const { children, label, ...rest } = props + return ( + + {label} + {children} + + ) +}) + +export const SelectLabel = ChakraSelect.Label +export const SelectItemText = ChakraSelect.ItemText diff --git a/frontend/src/utils/sortingOptions.ts b/frontend/src/utils/sortingOptions.ts index 15f63b0e9..331d636e4 100644 --- a/frontend/src/utils/sortingOptions.ts +++ b/frontend/src/utils/sortingOptions.ts @@ -1,11 +1,15 @@ -export const sortOptionsProject = [ - { label: 'Default', value: '' }, - { label: 'Name (A-Z)', value: 'name_asc' }, - { label: 'Name (Z-A)', value: 'name_desc' }, - { label: 'Stars (Low to High)', value: 'stars_count_asc' }, - { label: 'Stars (High to Low)', value: 'stars_count_desc' }, - { label: 'Contributors (Low to High)', value: 'contributors_count_asc' }, - { label: 'Contributors (High to Low)', value: 'contributors_count_desc' }, - { label: 'Forks (Low to High)', value: 'forks_count_asc' }, - { label: 'Forks (High to Low)', value: 'forks_count_desc' }, -] +import { createListCollection } from "@chakra-ui/react"; + +export const sortOptionsProject = createListCollection({ + items: [ + { label: 'Default', value: '' }, + { label: 'Name (A-Z)', value: 'name_asc' }, + { label: 'Name (Z-A)', value: 'name_desc' }, + { label: 'Stars (Low to High)', value: 'stars_count_asc' }, + { label: 'Stars (High to Low)', value: 'stars_count_desc' }, + { label: 'Contributors (Low to High)', value: 'contributors_count_asc' }, + { label: 'Contributors (High to Low)', value: 'contributors_count_desc' }, + { label: 'Forks (Low to High)', value: 'forks_count_asc' }, + { label: 'Forks (High to Low)', value: 'forks_count_desc' }, + ], +}) From 2e2804ede11cb73d1790c05bfe149bcad8adc5ea Mon Sep 17 00:00:00 2001 From: Rajgupta36 Date: Sat, 25 Jan 2025 00:59:41 +0530 Subject: [PATCH 2/9] updated_logic --- frontend/src/components/SearchPageLayout.tsx | 2 +- frontend/src/components/SortBy.tsx | 108 ++++++--- frontend/src/components/ui/close-button.tsx | 27 ++- frontend/src/components/ui/select.tsx | 223 +++++++++---------- frontend/src/hooks/useSearchPage.ts | 21 +- frontend/src/pages/Projects.tsx | 15 +- frontend/src/utils/sortingOptions.ts | 23 +- 7 files changed, 234 insertions(+), 185 deletions(-) diff --git a/frontend/src/components/SearchPageLayout.tsx b/frontend/src/components/SearchPageLayout.tsx index c91f54fdc..f223023f3 100644 --- a/frontend/src/components/SearchPageLayout.tsx +++ b/frontend/src/components/SearchPageLayout.tsx @@ -50,7 +50,6 @@ const SearchPageLayout = ({ initialValue={searchQuery} onReady={handleSearchBarReady} /> -
{sortChildren}
{!isSearchBarReady || !isLoaded ? (
@@ -59,6 +58,7 @@ const SearchPageLayout = ({ ) : ( <>
+
{sortChildren}
{totalPages === 0 &&
{empty}
} {children}
diff --git a/frontend/src/components/SortBy.tsx b/frontend/src/components/SortBy.tsx index 35fef50dc..cbade725c 100644 --- a/frontend/src/components/SortBy.tsx +++ b/frontend/src/components/SortBy.tsx @@ -7,44 +7,82 @@ import { SelectValueText, } from 'components/ui/select' -interface SortOption { - value: string - label: string -} - -interface SortByProps { - options: any - selectedOption: string - onSortChange: (value: string) => void -} +const SortBy = ({ + sortOptions, + selectedSortOption, + selectedOrder, + onSortChange, + onOrderChange, + sortOrderOptions, +}: any) => { + if (!sortOptions || sortOptions.length === 0) return null -const SortBy = ({ options, selectedOption, onSortChange }: SortByProps) => { - console.log(selectedOption) - if (!options || options.length === 0) return null return ( - { - onSortChange(e.value[0]) - }} - > - - - - - {options.items.map((sortAttribute) => ( - + {/* Sort Attribute Dropdown */} +
+ { + onSortChange(e.value) + }} + > +
+ + Sort By: + + + + +
+ + {sortOptions.items.map((attribute) => ( + + {attribute.label} + + ))} + +
+
+ + {/* Sort Order Dropdown */} + {selectedSortOption !== 'default' && ( +
+ { + onOrderChange(e.value) + }} > - {sortAttribute.label} - - ))} - - +
+ + Order: + + + + +
+ + {sortOrderOptions.items.map((order) => ( + + {order.label} + + ))} + + +
+ )} +
) } diff --git a/frontend/src/components/ui/close-button.tsx b/frontend/src/components/ui/close-button.tsx index 94af48859..f834ed996 100644 --- a/frontend/src/components/ui/close-button.tsx +++ b/frontend/src/components/ui/close-button.tsx @@ -1,17 +1,16 @@ -import type { ButtonProps } from "@chakra-ui/react" -import { IconButton as ChakraIconButton } from "@chakra-ui/react" -import * as React from "react" -import { LuX } from "react-icons/lu" +import type { ButtonProps } from '@chakra-ui/react' +import { IconButton as ChakraIconButton } from '@chakra-ui/react' +import * as React from 'react' +import { LuX } from 'react-icons/lu' export type CloseButtonProps = ButtonProps -export const CloseButton = React.forwardRef< - HTMLButtonElement, - CloseButtonProps ->(function CloseButton(props, ref) { - return ( - - {props.children ?? } - - ) -}) +export const CloseButton = React.forwardRef( + function CloseButton(props, ref) { + return ( + + {props.children ?? } + + ) + } +) diff --git a/frontend/src/components/ui/select.tsx b/frontend/src/components/ui/select.tsx index 99d84e6c5..80efdd986 100644 --- a/frontend/src/components/ui/select.tsx +++ b/frontend/src/components/ui/select.tsx @@ -1,143 +1,134 @@ -"use client" +'use client' -import type { CollectionItem } from "@chakra-ui/react" -import { Select as ChakraSelect, Portal } from "@chakra-ui/react" -import { CloseButton } from "./close-button" -import * as React from "react" +import type { CollectionItem } from '@chakra-ui/react' +import { Select as ChakraSelect, Portal } from '@chakra-ui/react' +import * as React from 'react' +import { CloseButton } from './close-button' interface SelectTriggerProps extends ChakraSelect.ControlProps { clearable?: boolean } -export const SelectTrigger = React.forwardRef< - HTMLButtonElement, - SelectTriggerProps ->(function SelectTrigger(props, ref) { - const { children, clearable, ...rest } = props - return ( - - {children} - - {clearable && } - - - - ) -}) +export const SelectTrigger = React.forwardRef( + function SelectTrigger(props, ref) { + const { children, clearable, ...rest } = props + return ( + + {children} + + {clearable && } + + + + ) + } +) -const SelectClearTrigger = React.forwardRef< - HTMLButtonElement, - ChakraSelect.ClearTriggerProps ->(function SelectClearTrigger(props, ref) { - return ( - - - - ) -}) +const SelectClearTrigger = React.forwardRef( + function SelectClearTrigger(props, ref) { + return ( + + + + ) + } +) interface SelectContentProps extends ChakraSelect.ContentProps { portalled?: boolean portalRef?: React.RefObject } -export const SelectContent = React.forwardRef< - HTMLDivElement, - SelectContentProps ->(function SelectContent(props, ref) { - const { portalled = true, portalRef, ...rest } = props - return ( - - - - - - ) -}) +export const SelectContent = React.forwardRef( + function SelectContent(props, ref) { + const { portalled = true, portalRef, ...rest } = props + return ( + + + + + + ) + } +) -export const SelectItem = React.forwardRef< - HTMLDivElement, - ChakraSelect.ItemProps ->(function SelectItem(props, ref) { - const { item, children, ...rest } = props - return ( - - {children} - - - ) -}) +export const SelectItem = React.forwardRef( + function SelectItem(props, ref) { + const { item, children, ...rest } = props + return ( + + {children} + + + ) + } +) -interface SelectValueTextProps - extends Omit { +interface SelectValueTextProps extends Omit { children?(items: CollectionItem[]): React.ReactNode } -export const SelectValueText = React.forwardRef< - HTMLSpanElement, - SelectValueTextProps ->(function SelectValueText(props, ref) { - const { children, ...rest } = props - return ( - - - {(select) => { - const items = select.selectedItems - if (items.length === 0) return props.placeholder - if (children) return children(items) - if (items.length === 1) - return select.collection.stringifyItem(items[0]) - return `${items.length} selected` - }} - - - ) -}) +export const SelectValueText = React.forwardRef( + function SelectValueText(props, ref) { + const { children, ...rest } = props + return ( + + + {(select) => { + const items = select.selectedItems + if (items.length === 0) return props.placeholder + if (children) return children(items) + if (items.length === 1) return select.collection.stringifyItem(items[0]) + return `${items.length} selected` + }} + + + ) + } +) -export const SelectRoot = React.forwardRef< - HTMLDivElement, - ChakraSelect.RootProps ->(function SelectRoot(props, ref) { - return ( - - {props.asChild ? ( - props.children - ) : ( - <> - - {props.children} - - )} - - ) -}) as ChakraSelect.RootComponent +export const SelectRoot = React.forwardRef( + function SelectRoot(props, ref) { + return ( + + {props.asChild ? ( + props.children + ) : ( + <> + + {props.children} + + )} + + ) + } +) as ChakraSelect.RootComponent interface SelectItemGroupProps extends ChakraSelect.ItemGroupProps { label: React.ReactNode } -export const SelectItemGroup = React.forwardRef< - HTMLDivElement, - SelectItemGroupProps ->(function SelectItemGroup(props, ref) { - const { children, label, ...rest } = props - return ( - - {label} - {children} - - ) -}) +export const SelectItemGroup = React.forwardRef( + function SelectItemGroup(props, ref) { + const { children, label, ...rest } = props + return ( + + {label} + {children} + + ) + } +) export const SelectLabel = ChakraSelect.Label export const SelectItemText = ChakraSelect.ItemText diff --git a/frontend/src/hooks/useSearchPage.ts b/frontend/src/hooks/useSearchPage.ts index 0348f292c..938b6704b 100644 --- a/frontend/src/hooks/useSearchPage.ts +++ b/frontend/src/hooks/useSearchPage.ts @@ -8,6 +8,7 @@ interface UseSearchPageOptions { indexName: string pageTitle: string defaultSortBy?: string + defaultOrder?: string } interface UseSearchPageReturn { @@ -17,15 +18,18 @@ interface UseSearchPageReturn { totalPages: number searchQuery: string sortBy: string + order: string handleSearch: (query: string) => void handlePageChange: (page: number) => void handleSortChange: (sort: string) => void + handleOrderChange: (order: string) => void } export function useSearchPage({ indexName, pageTitle, defaultSortBy = '', + defaultOrder = '', }: UseSearchPageOptions): UseSearchPageReturn { const navigate = useNavigate() const [searchParams, setSearchParams] = useSearchParams() @@ -33,6 +37,7 @@ export function useSearchPage({ const [currentPage, setCurrentPage] = useState(parseInt(searchParams.get('page') || '1')) const [searchQuery, setSearchQuery] = useState(searchParams.get('q') || '') const [sortBy, setSortBy] = useState(searchParams.get('sortBy') || defaultSortBy) + const [order, setOrder] = useState(searchParams.get('order') || defaultOrder) const [totalPages, setTotalPages] = useState(0) const [isLoaded, setIsLoaded] = useState(false) @@ -41,8 +46,9 @@ export function useSearchPage({ if (searchQuery) params.set('q', searchQuery) if (currentPage > 1) params.set('page', currentPage.toString()) if (sortBy && sortBy !== 'projects') params.set('sortBy', sortBy) + if (order && order !== '') params.set('order', order) setSearchParams(params) - }, [searchQuery, currentPage, sortBy, setSearchParams]) + }, [searchQuery, order, currentPage, sortBy, setSearchParams]) useEffect(() => { document.title = pageTitle @@ -51,7 +57,9 @@ export function useSearchPage({ const fetchData = async () => { try { const data: AlgoliaResponseType = await fetchAlgoliaData( - sortBy ? `${indexName}_${sortBy}` : indexName, + sortBy && sortBy !== 'default' + ? `${indexName}_${sortBy}${order ? `_${order}` : ''}` + : indexName, searchQuery, currentPage ) @@ -64,7 +72,7 @@ export function useSearchPage({ } fetchData() - }, [currentPage, searchQuery, sortBy, indexName, pageTitle, navigate]) + }, [currentPage, searchQuery, order, sortBy, indexName, pageTitle, navigate]) const handleSearch = (query: string) => { setSearchQuery(query) @@ -83,7 +91,10 @@ export function useSearchPage({ setSortBy(sort) setCurrentPage(1) } - + const handleOrderChange = (order: string) => { + setOrder(order) + setCurrentPage(1) + } return { items, isLoaded, @@ -91,8 +102,10 @@ export function useSearchPage({ totalPages, searchQuery, sortBy, + order, handleSearch, handlePageChange, handleSortChange, + handleOrderChange, } } diff --git a/frontend/src/pages/Projects.tsx b/frontend/src/pages/Projects.tsx index 1d7dc3d34..7db3cf7c0 100644 --- a/frontend/src/pages/Projects.tsx +++ b/frontend/src/pages/Projects.tsx @@ -2,13 +2,12 @@ import { useSearchPage } from 'hooks/useSearchPage' import { useNavigate } from 'react-router-dom' import { project } from 'types/project' import { level } from 'utils/data' -import { sortOptionsProject } from 'utils/sortingOptions' +import { sortOptionsProject, sortOrderOptions } from 'utils/sortingOptions' import { getFilteredIcons } from 'utils/utility' import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' import Card from 'components/Card' import SearchPageLayout from 'components/SearchPageLayout' import SortBy from 'components/SortBy' - const ProjectsPage = () => { const { items: projects, @@ -17,13 +16,16 @@ const ProjectsPage = () => { totalPages, searchQuery, sortBy, + order, handleSearch, handlePageChange, handleSortChange, + handleOrderChange, } = useSearchPage({ indexName: 'projects', pageTitle: 'OWASP Projects', - defaultSortBy: '', + defaultSortBy: 'default', + defaultOrder: 'asc', }) const navigate = useNavigate() @@ -68,9 +70,12 @@ const ProjectsPage = () => { searchPlaceholder="Search for OWASP projects..." sortChildren={ } > diff --git a/frontend/src/utils/sortingOptions.ts b/frontend/src/utils/sortingOptions.ts index 331d636e4..8a6c402af 100644 --- a/frontend/src/utils/sortingOptions.ts +++ b/frontend/src/utils/sortingOptions.ts @@ -1,15 +1,18 @@ -import { createListCollection } from "@chakra-ui/react"; +import { createListCollection } from '@chakra-ui/react' export const sortOptionsProject = createListCollection({ items: [ - { label: 'Default', value: '' }, - { label: 'Name (A-Z)', value: 'name_asc' }, - { label: 'Name (Z-A)', value: 'name_desc' }, - { label: 'Stars (Low to High)', value: 'stars_count_asc' }, - { label: 'Stars (High to Low)', value: 'stars_count_desc' }, - { label: 'Contributors (Low to High)', value: 'contributors_count_asc' }, - { label: 'Contributors (High to Low)', value: 'contributors_count_desc' }, - { label: 'Forks (Low to High)', value: 'forks_count_asc' }, - { label: 'Forks (High to Low)', value: 'forks_count_desc' }, + { label: 'Default', value: 'default' }, + { label: 'Name', value: 'name' }, + { label: 'Stars', value: 'stars_count' }, + { label: 'Contributors', value: 'contributors_count' }, + { label: 'Forks', value: 'forks_count' }, + ], +}) + +export const sortOrderOptions = createListCollection({ + items: [ + { label: 'Asc', value: 'asc' }, + { label: 'Desc', value: 'desc' }, ], }) From 98af894e9224378d5790fa198d0d4f94d09693d0 Mon Sep 17 00:00:00 2001 From: Rajgupta36 Date: Sat, 25 Jan 2025 03:22:08 +0530 Subject: [PATCH 3/9] UI_update --- frontend/src/components/SortBy.tsx | 56 +++++++++++++--------------- frontend/src/hooks/useSearchPage.ts | 16 +++++--- frontend/src/pages/Projects.tsx | 3 +- frontend/src/utils/sortingOptions.ts | 13 ++----- 4 files changed, 41 insertions(+), 47 deletions(-) diff --git a/frontend/src/components/SortBy.tsx b/frontend/src/components/SortBy.tsx index cbade725c..38db867b0 100644 --- a/frontend/src/components/SortBy.tsx +++ b/frontend/src/components/SortBy.tsx @@ -1,3 +1,5 @@ +import { faArrowDownWideShort, faArrowUpWideShort } from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { SelectContent, SelectItem, @@ -13,7 +15,6 @@ const SortBy = ({ selectedOrder, onSortChange, onOrderChange, - sortOrderOptions, }: any) => { if (!sortOptions || sortOptions.length === 0) return null @@ -32,8 +33,14 @@ const SortBy = ({ Sort By: - - + + item.value === selectedSortOption)?.label + } + /> @@ -52,34 +59,23 @@ const SortBy = ({ {/* Sort Order Dropdown */} {selectedSortOption !== 'default' && ( -
- { - onOrderChange(e.value) - }} +
+
)}
diff --git a/frontend/src/hooks/useSearchPage.ts b/frontend/src/hooks/useSearchPage.ts index 938b6704b..5e9de339e 100644 --- a/frontend/src/hooks/useSearchPage.ts +++ b/frontend/src/hooks/useSearchPage.ts @@ -40,13 +40,19 @@ export function useSearchPage({ const [order, setOrder] = useState(searchParams.get('order') || defaultOrder) const [totalPages, setTotalPages] = useState(0) const [isLoaded, setIsLoaded] = useState(false) - useEffect(() => { const params = new URLSearchParams() if (searchQuery) params.set('q', searchQuery) if (currentPage > 1) params.set('page', currentPage.toString()) - if (sortBy && sortBy !== 'projects') params.set('sortBy', sortBy) - if (order && order !== '') params.set('order', order) + + if (sortBy && sortBy !== 'default' && sortBy[0] !== 'default' && sortBy !== '') { + params.set('sortBy', sortBy) + } + + if (sortBy !== 'default' && sortBy[0] !== 'default' && order && order !== '') { + params.set('order', order) + } + setSearchParams(params) }, [searchQuery, order, currentPage, sortBy, setSearchParams]) @@ -57,8 +63,8 @@ export function useSearchPage({ const fetchData = async () => { try { const data: AlgoliaResponseType = await fetchAlgoliaData( - sortBy && sortBy !== 'default' - ? `${indexName}_${sortBy}${order ? `_${order}` : ''}` + sortBy && sortBy !== 'default' && sortBy[0] !== 'default' + ? `${indexName}_${sortBy}${order && order !== '' ? `_${order}` : ''}` : indexName, searchQuery, currentPage diff --git a/frontend/src/pages/Projects.tsx b/frontend/src/pages/Projects.tsx index 7db3cf7c0..7cf41315e 100644 --- a/frontend/src/pages/Projects.tsx +++ b/frontend/src/pages/Projects.tsx @@ -2,7 +2,7 @@ import { useSearchPage } from 'hooks/useSearchPage' import { useNavigate } from 'react-router-dom' import { project } from 'types/project' import { level } from 'utils/data' -import { sortOptionsProject, sortOrderOptions } from 'utils/sortingOptions' +import { sortOptionsProject } from 'utils/sortingOptions' import { getFilteredIcons } from 'utils/utility' import FontAwesomeIconWrapper from 'wrappers/FontAwesomeIconWrapper' import Card from 'components/Card' @@ -73,7 +73,6 @@ const ProjectsPage = () => { sortOptions={sortOptionsProject} selectedSortOption={sortBy} onSortChange={handleSortChange} - sortOrderOptions={sortOrderOptions} selectedOrder={order} onOrderChange={handleOrderChange} /> diff --git a/frontend/src/utils/sortingOptions.ts b/frontend/src/utils/sortingOptions.ts index 8a6c402af..817a6be0b 100644 --- a/frontend/src/utils/sortingOptions.ts +++ b/frontend/src/utils/sortingOptions.ts @@ -2,17 +2,10 @@ import { createListCollection } from '@chakra-ui/react' export const sortOptionsProject = createListCollection({ items: [ - { label: 'Default', value: 'default' }, - { label: 'Name', value: 'name' }, - { label: 'Stars', value: 'stars_count' }, + { label: 'Relevancy', value: 'default' }, { label: 'Contributors', value: 'contributors_count' }, { label: 'Forks', value: 'forks_count' }, - ], -}) - -export const sortOrderOptions = createListCollection({ - items: [ - { label: 'Asc', value: 'asc' }, - { label: 'Desc', value: 'desc' }, + { label: 'Name', value: 'name' }, + { label: 'Stars', value: 'stars_count' }, ], }) From 261ba66800f6bdcb5d1e59b1c38442fffea7852b Mon Sep 17 00:00:00 2001 From: Rajgupta36 Date: Sat, 25 Jan 2025 16:35:18 +0530 Subject: [PATCH 4/9] fix bugs --- frontend/jest.setup.ts | 2 +- frontend/src/components/SearchPageLayout.tsx | 2 +- frontend/src/components/SortBy.tsx | 29 ++++++++++++-------- frontend/src/types/sortBy.tsx | 8 ++++++ frontend/src/wrappers/testUtil.tsx | 8 ++++-- 5 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 frontend/src/types/sortBy.tsx diff --git a/frontend/jest.setup.ts b/frontend/jest.setup.ts index 928fcbe07..154ad5abe 100644 --- a/frontend/jest.setup.ts +++ b/frontend/jest.setup.ts @@ -7,7 +7,7 @@ dotenv.config() global.React = React global.TextEncoder = TextEncoder - +global.structuredClone = (val) => JSON.parse(JSON.stringify(val)) beforeEach(() => { jest.spyOn(console, 'error').mockImplementation((...args) => { throw new Error(`Console error: ${args.join(' ')}`) diff --git a/frontend/src/components/SearchPageLayout.tsx b/frontend/src/components/SearchPageLayout.tsx index f223023f3..dd56a377d 100644 --- a/frontend/src/components/SearchPageLayout.tsx +++ b/frontend/src/components/SearchPageLayout.tsx @@ -58,7 +58,7 @@ const SearchPageLayout = ({ ) : ( <>
-
{sortChildren}
+ {totalPages !== 0 &&
{sortChildren}
} {totalPages === 0 &&
{empty}
} {children}
diff --git a/frontend/src/components/SortBy.tsx b/frontend/src/components/SortBy.tsx index 38db867b0..e770b45b5 100644 --- a/frontend/src/components/SortBy.tsx +++ b/frontend/src/components/SortBy.tsx @@ -1,5 +1,7 @@ -import { faArrowDownWideShort, faArrowUpWideShort } from '@fortawesome/free-solid-svg-icons' +import { faArrowDownShortWide, faArrowUpWideShort } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { Tooltip } from 'react-tooltip' +import { SortByProps } from 'types/sortBy' import { SelectContent, SelectItem, @@ -8,15 +10,14 @@ import { SelectTrigger, SelectValueText, } from 'components/ui/select' - const SortBy = ({ sortOptions, selectedSortOption, selectedOrder, onSortChange, onOrderChange, -}: any) => { - if (!sortOptions || sortOptions.length === 0) return null +}: SortByProps) => { + if (!sortOptions || sortOptions.items.length === 0) return null return (
@@ -26,7 +27,7 @@ const SortBy = ({ collection={sortOptions} size="sm" onValueChange={(e) => { - onSortChange(e.value) + onSortChange(e.value[0]) }} >
@@ -36,9 +37,7 @@ const SortBy = ({ item.value === selectedSortOption)?.label + sortOptions.items.find((item) => item.value === selectedSortOption)?.label } /> @@ -59,23 +58,29 @@ const SortBy = ({ {/* Sort Order Dropdown */} {selectedSortOption !== 'default' && ( -
+
+
)}
diff --git a/frontend/src/types/sortBy.tsx b/frontend/src/types/sortBy.tsx new file mode 100644 index 000000000..fc251e08b --- /dev/null +++ b/frontend/src/types/sortBy.tsx @@ -0,0 +1,8 @@ +import { ListCollection } from '@chakra-ui/react' +export interface SortByProps { + sortOptions: ListCollection + selectedSortOption: string + selectedOrder: string + onSortChange: (value: string) => void + onOrderChange: (order: string) => void +} diff --git a/frontend/src/wrappers/testUtil.tsx b/frontend/src/wrappers/testUtil.tsx index 600789582..7a5114fad 100644 --- a/frontend/src/wrappers/testUtil.tsx +++ b/frontend/src/wrappers/testUtil.tsx @@ -1,9 +1,13 @@ +import { ChakraProvider, defaultSystem } from '@chakra-ui/react' import { render } from '@testing-library/react' import { ReactNode } from 'react' import { BrowserRouter } from 'react-router-dom' - const customRender = (ui: ReactNode) => { - return render({ui}) + return render( + + {ui} + + ) } export * from '@testing-library/react' From 1670c8e42c1caa3c65b5cc3a9d6384b3d6e18c21 Mon Sep 17 00:00:00 2001 From: Rajgupta36 Date: Sat, 25 Jan 2025 16:40:49 +0530 Subject: [PATCH 5/9] rm-shadcn dropdown component --- frontend/src/components/ui/dropdownMenu.tsx | 184 -------------------- 1 file changed, 184 deletions(-) delete mode 100644 frontend/src/components/ui/dropdownMenu.tsx diff --git a/frontend/src/components/ui/dropdownMenu.tsx b/frontend/src/components/ui/dropdownMenu.tsx deleted file mode 100644 index a52b7955a..000000000 --- a/frontend/src/components/ui/dropdownMenu.tsx +++ /dev/null @@ -1,184 +0,0 @@ -import { faCheck, faChevronRight, faDotCircle } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu' -import * as React from 'react' -import { cn } from 'utils/utility' - -const DropdownMenu = DropdownMenuPrimitive.Root - -const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger - -const DropdownMenuGroup = DropdownMenuPrimitive.Group - -const DropdownMenuPortal = DropdownMenuPrimitive.Portal - -const DropdownMenuSub = DropdownMenuPrimitive.Sub - -const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup - -const DropdownMenuSubTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, children, ...props }, ref) => ( - - {children} - - -)) -DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName - -const DropdownMenuSubContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName - -const DropdownMenuContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, sideOffset = 4, ...props }, ref) => ( - - - -)) -DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName - -const DropdownMenuItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, ...props }, ref) => ( - svg]:size-4 [&>svg]:shrink-0', - inset && 'pl-8', - className - )} - {...props} - /> -)) -DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName - -const DropdownMenuCheckboxItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, checked, ...props }, ref) => ( - - - - - - - {children} - -)) -DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName - -const DropdownMenuRadioItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - - - - - {children} - -)) -DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName - -const DropdownMenuLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, ...props }, ref) => ( - -)) -DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName - -const DropdownMenuSeparator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName - -const DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes) => { - return -} -DropdownMenuShortcut.displayName = 'DropdownMenuShortcut' - -export { - DropdownMenu, - DropdownMenuTrigger, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuCheckboxItem, - DropdownMenuRadioItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuShortcut, - DropdownMenuGroup, - DropdownMenuPortal, - DropdownMenuSub, - DropdownMenuSubContent, - DropdownMenuSubTrigger, - DropdownMenuRadioGroup, -} From 79c152dde972854364766b1581f044a94b35d500 Mon Sep 17 00:00:00 2001 From: Rajgupta36 Date: Sun, 26 Jan 2025 00:05:32 +0530 Subject: [PATCH 6/9] fixed_css --- frontend/src/components/SortBy.tsx | 7 +++++-- .../components/ui/{close-button.tsx => CloseButton.tsx} | 0 frontend/src/components/ui/{select.tsx => Select.tsx} | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) rename frontend/src/components/ui/{close-button.tsx => CloseButton.tsx} (100%) rename frontend/src/components/ui/{select.tsx => Select.tsx} (98%) diff --git a/frontend/src/components/SortBy.tsx b/frontend/src/components/SortBy.tsx index e770b45b5..f2e0025e3 100644 --- a/frontend/src/components/SortBy.tsx +++ b/frontend/src/components/SortBy.tsx @@ -9,7 +9,7 @@ import { SelectRoot, SelectTrigger, SelectValueText, -} from 'components/ui/select' +} from 'components/ui/Select' const SortBy = ({ sortOptions, selectedSortOption, @@ -34,8 +34,11 @@ const SortBy = ({ Sort By: - + item.value === selectedSortOption)?.label } diff --git a/frontend/src/components/ui/close-button.tsx b/frontend/src/components/ui/CloseButton.tsx similarity index 100% rename from frontend/src/components/ui/close-button.tsx rename to frontend/src/components/ui/CloseButton.tsx diff --git a/frontend/src/components/ui/select.tsx b/frontend/src/components/ui/Select.tsx similarity index 98% rename from frontend/src/components/ui/select.tsx rename to frontend/src/components/ui/Select.tsx index 80efdd986..a0bb643ae 100644 --- a/frontend/src/components/ui/select.tsx +++ b/frontend/src/components/ui/Select.tsx @@ -3,7 +3,7 @@ import type { CollectionItem } from '@chakra-ui/react' import { Select as ChakraSelect, Portal } from '@chakra-ui/react' import * as React from 'react' -import { CloseButton } from './close-button' +import { CloseButton } from './CloseButton' interface SelectTriggerProps extends ChakraSelect.ControlProps { clearable?: boolean From 50022bf6d3c507909c072756fd2fc261cec049be Mon Sep 17 00:00:00 2001 From: Rajgupta36 Date: Sun, 26 Jan 2025 16:27:05 +0530 Subject: [PATCH 7/9] fix_css --- frontend/src/components/SortBy.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/SortBy.tsx b/frontend/src/components/SortBy.tsx index f2e0025e3..7a5269975 100644 --- a/frontend/src/components/SortBy.tsx +++ b/frontend/src/components/SortBy.tsx @@ -22,7 +22,7 @@ const SortBy = ({ return (
{/* Sort Attribute Dropdown */} -
+
Date: Mon, 27 Jan 2025 01:38:50 +0530 Subject: [PATCH 8/9] added checkicon --- frontend/src/components/SortBy.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/SortBy.tsx b/frontend/src/components/SortBy.tsx index 7a5269975..595cc998e 100644 --- a/frontend/src/components/SortBy.tsx +++ b/frontend/src/components/SortBy.tsx @@ -1,4 +1,8 @@ -import { faArrowDownShortWide, faArrowUpWideShort } from '@fortawesome/free-solid-svg-icons' +import { + faArrowDownShortWide, + faArrowUpWideShort, + faCheck, +} from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Tooltip } from 'react-tooltip' import { SortByProps } from 'types/sortBy' @@ -24,6 +28,7 @@ const SortBy = ({ {/* Sort Attribute Dropdown */}
{ @@ -53,6 +58,12 @@ const SortBy = ({ className="p-1 hover:bg-[#D1DBE6] dark:hover:bg-[#454545]" > {attribute.label} + {attribute.value === selectedSortOption && ( + + )} ))} From 04437bda875e85b522c76ce73f3753da33ca7f8d Mon Sep 17 00:00:00 2001 From: Kate Date: Sun, 26 Jan 2025 14:10:53 -0800 Subject: [PATCH 9/9] Fix padding in sort menu --- frontend/src/components/SortBy.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/SortBy.tsx b/frontend/src/components/SortBy.tsx index 595cc998e..841cdf5b4 100644 --- a/frontend/src/components/SortBy.tsx +++ b/frontend/src/components/SortBy.tsx @@ -55,7 +55,7 @@ const SortBy = ({ {attribute.label} {attribute.value === selectedSortOption && (