Skip to content

Commit

Permalink
Support searching links in command menu
Browse files Browse the repository at this point in the history
  • Loading branch information
brendanv committed Aug 24, 2024
1 parent 014f438 commit d0212e8
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 28 deletions.
18 changes: 16 additions & 2 deletions frontend/src/components/CommandMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback } from "react";
import React, { useCallback, useState } from "react";
import { useNavigate } from "react-router-dom";
import {
CommandDialog,
Expand All @@ -23,6 +23,7 @@ const CommandMenu: React.FC<CommandMenuProps> = ({
customCommands,
}) => {
const navigate = useNavigate();
const [search, setSearch] = useState("");
const runCommand = (command: () => void) => {
onOpenChange(false);
command();
Expand Down Expand Up @@ -54,7 +55,11 @@ const CommandMenu: React.FC<CommandMenuProps> = ({

return (
<CommandDialog open={open} onOpenChange={onOpenChange}>
<CommandInput placeholder="Type a command or search..." />
<CommandInput
value={search}
onValueChange={setSearch}
placeholder="Type a command or search..."
/>
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
{(customCommands || []).map((group) => (
Expand All @@ -75,6 +80,15 @@ const CommandMenu: React.FC<CommandMenuProps> = ({
<CommandItem onSelect={navigateFeeds}>Feeds</CommandItem>
<CommandItem onSelect={navigateAddLink}>Add Link</CommandItem>
</CommandGroup>
<CommandGroup heading="Search">
<CommandItem
onSelect={() =>
runCommand(() => navigate(URLS.HOME_WITH_SEARCH_STRING(search)))
}
>
Search for "{search}"
</CommandItem>
</CommandGroup>
</CommandList>
</CommandDialog>
);
Expand Down
64 changes: 42 additions & 22 deletions frontend/src/components/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,16 @@ export type SearchParams = {
};

type SearchBarProps = {
searchParams: SearchParams;
onSearchParamsChange: (params: SearchParams) => void;
};

const SearchBar: React.FC<SearchBarProps> = ({ onSearchParamsChange }) => {
const SearchBar: React.FC<SearchBarProps> = ({
searchParams,
onSearchParamsChange,
}) => {
const [filterOpen, setFilterOpen] = useState(false);
const [sortOpen, setSortOpen] = useState(false);
const [searchParams, setSearchParams] = useState<SearchParams>({
searchText: "",
readState: "all",
tagId: undefined,
sortBy: "added_to_library",
});
const [tags, setTags] = useState<{ id: string; name: string }[]>([]);
const { pb } = usePocketBase();

Expand All @@ -53,7 +51,6 @@ const SearchBar: React.FC<SearchBarProps> = ({ onSearchParamsChange }) => {

const updateSearchParams = (newParams: Partial<SearchParams>) => {
const updatedParams = { ...searchParams, ...newParams };
setSearchParams(updatedParams);
onSearchParamsChange(updatedParams);
};

Expand All @@ -64,7 +61,6 @@ const SearchBar: React.FC<SearchBarProps> = ({ onSearchParamsChange }) => {
tagId: undefined,
sortBy: "added_to_library",
};
setSearchParams(clearedParams);
onSearchParamsChange(clearedParams);
};

Expand All @@ -79,9 +75,8 @@ const SearchBar: React.FC<SearchBarProps> = ({ onSearchParamsChange }) => {
{ value: "article_date", label: "Article Date" },
];

const activeFiltersCount =
(searchParams.readState !== "all" ? 1 : 0) +
(searchParams.tagId ? 1 : 0);
const activeFiltersCount =
(searchParams.readState !== "all" ? 1 : 0) + (searchParams.tagId ? 1 : 0);

return (
<div className="flex flex-col space-y-2">
Expand All @@ -99,7 +94,10 @@ const SearchBar: React.FC<SearchBarProps> = ({ onSearchParamsChange }) => {
<Filter className="h-4 w-4" />
<span className="ml-2 hidden sm:inline">Filters</span>
{activeFiltersCount > 0 && (
<Badge variant="secondary" className="absolute -top-2 -right-2 h-5 w-5 p-0 flex items-center justify-center">
<Badge
variant="secondary"
className="absolute -top-2 -right-2 h-5 w-5 p-0 flex items-center justify-center"
>
{activeFiltersCount}
</Badge>
)}
Expand All @@ -113,12 +111,18 @@ const SearchBar: React.FC<SearchBarProps> = ({ onSearchParamsChange }) => {
key={state.value}
variant="ghost"
className="w-full justify-start"
onClick={() => updateSearchParams({ readState: state.value as "all" | "read" | "unread" })}
onClick={() =>
updateSearchParams({
readState: state.value as "all" | "read" | "unread",
})
}
>
<Check
className={cn(
"mr-2 h-4 w-4",
searchParams.readState === state.value ? "opacity-100" : "opacity-0"
searchParams.readState === state.value
? "opacity-100"
: "opacity-0",
)}
/>
{state.label}
Expand All @@ -130,12 +134,18 @@ const SearchBar: React.FC<SearchBarProps> = ({ onSearchParamsChange }) => {
key={tag.id}
variant="ghost"
className="w-full justify-start"
onClick={() => updateSearchParams({ tagId: searchParams.tagId === tag.id ? undefined : tag.id })}
onClick={() =>
updateSearchParams({
tagId: searchParams.tagId === tag.id ? undefined : tag.id,
})
}
>
<Check
className={cn(
"mr-2 h-4 w-4",
searchParams.tagId === tag.id ? "opacity-100" : "opacity-0"
searchParams.tagId === tag.id
? "opacity-100"
: "opacity-0",
)}
/>
{tag.name}
Expand All @@ -160,14 +170,20 @@ const SearchBar: React.FC<SearchBarProps> = ({ onSearchParamsChange }) => {
variant="ghost"
className="w-full justify-start"
onClick={() => {
updateSearchParams({ sortBy: option.value as "added_to_library" | "article_date" });
updateSearchParams({
sortBy: option.value as
| "added_to_library"
| "article_date",
});
setSortOpen(false);
}}
>
<Check
className={cn(
"mr-2 h-4 w-4",
searchParams.sortBy === option.value ? "opacity-100" : "opacity-0"
searchParams.sortBy === option.value
? "opacity-100"
: "opacity-0",
)}
/>
{option.label}
Expand Down Expand Up @@ -198,14 +214,18 @@ const SearchBar: React.FC<SearchBarProps> = ({ onSearchParamsChange }) => {
)}
{searchParams.sortBy !== "added_to_library" && (
<Badge variant="secondary">
Sorted by: {searchParams.sortBy === "article_date" ? "Article Date" : "Date Added"}
Sorted by:{" "}
{searchParams.sortBy === "article_date"
? "Article Date"
: "Date Added"}
<X
className="ml-1 h-3 w-3 cursor-pointer"
onClick={() => updateSearchParams({ sortBy: "added_to_library" })}
/>
</Badge>
)}
{(activeFiltersCount > 0 || searchParams.sortBy !== "added_to_library") && (
{(activeFiltersCount > 0 ||
searchParams.sortBy !== "added_to_library") && (
<Button variant="outline" size="sm" onClick={clearFilters}>
Clear Filters & Sort
</Button>
Expand All @@ -215,4 +235,4 @@ const SearchBar: React.FC<SearchBarProps> = ({ onSearchParamsChange }) => {
);
};

export default SearchBar;
export default SearchBar;
19 changes: 15 additions & 4 deletions frontend/src/components/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ import SearchBar, { SearchParams } from "@/components/SearchBar";
import Paginator from "@/components/Paginator";
import { usePageTitle } from "@/hooks/usePageTitle";
import { Toaster } from "@/components/ui/toaster";
import { useSearchParams } from "react-router-dom";

const Home: React.FC = () => {
usePageTitle("My Feed")
usePageTitle("My Feed");
const [urlParams, setUrlParams] = useSearchParams();
const [page, setPage] = useState(1);
const [searchParams, setSearchParams] = useState<SearchParams>({
searchText: "",
const [searchParams, setSearchParams] = useState<
Omit<SearchParams, "searchText">
>({
readState: "all",
sortBy: "added_to_library",
});
const searchText = urlParams.get("s") || "";

const {
loading: feedLoading,
Expand All @@ -25,10 +29,14 @@ const Home: React.FC = () => {
} = useLinksFeedQuery({
page,
...searchParams,
searchText,
});

const handleSearchParamsChange = (newSearchParams: SearchParams) => {
setSearchParams(newSearchParams);
setUrlParams({
s: newSearchParams.searchText,
});
setPage(1);
};

Expand Down Expand Up @@ -76,7 +84,10 @@ const Home: React.FC = () => {
<>
<Header />
<main className="container mx-auto mt-20 p-4">
<SearchBar onSearchParamsChange={handleSearchParamsChange} />
<SearchBar
searchParams={{ ...searchParams, searchText }}
onSearchParamsChange={handleSearchParamsChange}
/>
<div className="mt-6">{renderContent()}</div>
</main>
<Toaster />
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lib/urls.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export default {
HOME: "/",
HOME_WITH_SEARCH_STRING: (search: string) => `/?s=${search}`,
LOGIN: "/login",
PROFILE: "/profile",
FEEDS: "/feeds",
Expand Down

0 comments on commit d0212e8

Please sign in to comment.