diff --git a/apps/cyberstorm-nextjs/app/communities/@searchAndOrder/SearchAndOrder.module.css b/apps/cyberstorm-nextjs/app/communities/@searchAndOrder/SearchAndOrder.module.css new file mode 100644 index 000000000..f2c73c21c --- /dev/null +++ b/apps/cyberstorm-nextjs/app/communities/@searchAndOrder/SearchAndOrder.module.css @@ -0,0 +1,34 @@ +.root { + display: flex; + flex-direction: column; + gap: var(--gap--16); +} + +.searchTextInput { + width: 100%; +} + +@media (min-width: 40rem) { + .searchTextInput { + width: 50%; + } + + .root { + flex-direction: row; + justify-content: space-between; + } +} + +.searchFilters { + display: flex; + flex: 1 1 auto; + gap: var(--gap--16); + align-content: center; + justify-content: flex-end; +} + +.searchFiltersSortLabel { + align-self: center; + color: var(--color-text--tertiary); + font-weight: var(--font-weight-bold); +} diff --git a/apps/cyberstorm-nextjs/app/communities/@searchAndOrder/page.tsx b/apps/cyberstorm-nextjs/app/communities/@searchAndOrder/page.tsx new file mode 100644 index 000000000..06b4fbe5e --- /dev/null +++ b/apps/cyberstorm-nextjs/app/communities/@searchAndOrder/page.tsx @@ -0,0 +1,94 @@ +"use client"; +import styles from "./SearchAndOrder.module.css"; +import { TextInput, Select } from "@thunderstore/cyberstorm"; +import { useCallback, useEffect, useState } from "react"; +import { useDebounce } from "use-debounce"; + +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faSearch, + faArrowDownAZ, + faStar, +} from "@fortawesome/free-solid-svg-icons"; +import { faFire } from "@fortawesome/pro-solid-svg-icons"; +import { usePathname, useSearchParams } from "next/navigation"; +import { useRouter } from "next/navigation"; + +enum SortOptions { + Name = "name", + Latest = "-datetime_created", + Popular = "-aggregated_fields__download_count", +} + +export default function Page() { + const router = useRouter(); + const pathname = usePathname(); + const searchParams = useSearchParams(); + + const createQueryString = useCallback( + (name: string, value: string, isDefault?: boolean) => { + const params = new URLSearchParams(searchParams.toString()); + if (isDefault || value.length === 0) { + params.delete(name); + } else { + params.set(name, value); + } + + return params.toString(); + }, + [searchParams] + ); + + const [order, setOrder] = useState(SortOptions.Popular); + + const changeOrder = (v: SortOptions) => { + setOrder(v); + router.push( + pathname + "?" + createQueryString("order", v, v === SortOptions.Popular) + ); + }; + + const [searchValue, setSearchValue] = useState(""); + const [debouncedSearchValue] = useDebounce(searchValue, 300); + + useEffect(() => { + router.push( + pathname + "?" + createQueryString("search", debouncedSearchValue) + ); + }, [createQueryString, debouncedSearchValue, pathname, router]); + + return ( +
+
+ setSearchValue(e.target.value)} + value={searchValue} + placeholder="Search communities..." + leftIcon={} + /> +
+
+
Sort by
+ -
-
+ }> + {searchAndOrder} + }> {communityList} @@ -104,21 +33,3 @@ export default function CommunitiesLayout({ ); } - -const selectOptions = [ - { - value: SortOptions.Name, - label: "Name", - leftIcon: , - }, - { - value: SortOptions.Latest, - label: "Latest", - leftIcon: , - }, - { - value: SortOptions.Popular, - label: "Popular", - leftIcon: , - }, -];