| 1 | import { Search, Settings } from "lucide-react"; |
| 2 | import { Input } from "@/components/ui/input"; |
| 3 | import type { SortOption, StatusFilter } from "@/types/filters"; |
| 4 | import { TagCombobox } from "@/components/TagCombobox"; |
| 5 | import type { Dispatch, SetStateAction } from "react"; |
| 6 | import { StatusSelect } from "@/components/select/StatusSelect"; |
| 7 | import { SortbySelect } from "@/components/select/SortbySelect"; |
| 8 | |
| 9 | interface SearchBarProps { |
| 10 | searchQuery: string; |
| 11 | onSearchChange: (value: string) => void; |
| 12 | status: StatusFilter; |
| 13 | onStatusChange: (value: StatusFilter) => void; |
| 14 | sortBy: SortOption; |
| 15 | onSortByChange: (value: SortOption) => void; |
| 16 | availableTags: string[]; |
| 17 | selectedTags: string[]; |
| 18 | onAddTag: (tag: string) => void; |
| 19 | onRemoveTag: (tag: string) => void; |
| 20 | hideFiltersOnMobile?: boolean; |
| 21 | setShowFilterModal?: Dispatch<SetStateAction<boolean>>; |
| 22 | } |
| 23 | |
| 24 | export function SearchBar({ |
| 25 | searchQuery, |
| 26 | onSearchChange, |
| 27 | status, |
| 28 | onStatusChange, |
| 29 | sortBy, |
| 30 | onSortByChange, |
| 31 | availableTags, |
| 32 | selectedTags, |
| 33 | onAddTag, |
| 34 | onRemoveTag, |
| 35 | hideFiltersOnMobile = false, |
| 36 | setShowFilterModal, |
| 37 | }: SearchBarProps) { |
| 38 | return ( |
| 39 | <div className="flex flex-wrap mt-4 sm:mt-6 items-center gap-3 px-0"> |
| 40 | <div className="flex gap-2 items-center w-full"> |
| 41 | <label className="flex min-w-55 flex-1 items-stretch h-10 relative"> |
| 42 | <div className="left-0 h-full absolute text-text-muted flex items-center justify-center pl-3 pr-2 rounded-l-md bg-border border border-border"> |
| 43 | <Search className="w-4 h-4" /> |
| 44 | </div> |
| 45 | <Input |
| 46 | placeholder="Search live apps..." |
| 47 | value={searchQuery} |
| 48 | onChange={(e) => onSearchChange(e.target.value)} |
| 49 | className="h-10 pl-12 border border-border rounded-md" |
| 50 | /> |
| 51 | </label> |
| 52 | {hideFiltersOnMobile && setShowFilterModal && ( |
| 53 | <button |
| 54 | onClick={() => setShowFilterModal(true)} |
| 55 | className="sm:hidden flex items-center justify-center w-10 h-10 rounded-lg bg-secondary hover:bg-secondary/80 transition-colors" |
| 56 | aria-label="Filter settings" |
| 57 | > |
| 58 | <Settings className="w-5 h-5 text-secondary-foreground" /> |
| 59 | </button> |
| 60 | )} |
| 61 | </div> |
| 62 | |
| 63 | <StatusSelect |
| 64 | status={status} |
| 65 | onStatusChange={onStatusChange} |
| 66 | hideFiltersOnMobile={hideFiltersOnMobile} |
| 67 | /> |
| 68 | |
| 69 | <SortbySelect |
| 70 | sortBy={sortBy} |
| 71 | onSortByChange={onSortByChange} |
| 72 | hideFiltersOnMobile={hideFiltersOnMobile} |
| 73 | /> |
| 74 | |
| 75 | <div |
| 76 | className={`relative flex w-full sm:w-auto sm:min-w-[320px] flex-1 ${ |
| 77 | hideFiltersOnMobile ? "hidden sm:flex" : "" |
| 78 | }`} |
| 79 | > |
| 80 | <TagCombobox |
| 81 | availableTags={availableTags} |
| 82 | selectedTags={selectedTags} |
| 83 | onAdd={onAddTag} |
| 84 | onRemove={onRemoveTag} |
| 85 | /> |
| 86 | </div> |
| 87 | </div> |
| 88 | ); |
| 89 | } |