From 181c76980a19a9979b7200cd2a4a5ecbbcc5a70b Mon Sep 17 00:00:00 2001 From: zhom <2717306+zhom@users.noreply.github.com> Date: Sun, 24 Aug 2025 21:49:08 +0400 Subject: [PATCH] feat: add profile search --- src/app/page.tsx | 36 ++++++++++++++++++++++++++++++---- src/components/home-header.tsx | 33 +++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index b493f1d..3400d41 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -80,6 +80,7 @@ export default function Home() { string[] >([]); const [selectedProfiles, setSelectedProfiles] = useState([]); + const [searchQuery, setSearchQuery] = useState(""); const [pendingUrls, setPendingUrls] = useState([]); const [currentProfileForCamoufoxConfig, setCurrentProfileForCamoufoxConfig] = useState(null); @@ -655,14 +656,39 @@ export default function Home() { } }, [isInitialized, checkAllPermissions]); - // Filter data by selected group + // Filter data by selected group and search query const filteredProfiles = useMemo(() => { + let filtered = profiles; + + // Filter by group if (!selectedGroupId || selectedGroupId === "default") { - return profiles.filter((profile) => !profile.group_id); + filtered = profiles.filter((profile) => !profile.group_id); + } else { + filtered = profiles.filter( + (profile) => profile.group_id === selectedGroupId, + ); } - return profiles.filter((profile) => profile.group_id === selectedGroupId); - }, [profiles, selectedGroupId]); + // Filter by search query + if (searchQuery.trim()) { + const query = searchQuery.toLowerCase().trim(); + filtered = filtered.filter((profile) => { + // Search in profile name + if (profile.name.toLowerCase().includes(query)) return true; + + // Search in browser name + if (profile.browser.toLowerCase().includes(query)) return true; + + // Search in tags + if (profile.tags?.some((tag) => tag.toLowerCase().includes(query))) + return true; + + return false; + }); + } + + return filtered; + }, [profiles, selectedGroupId, searchQuery]); // Update loading states const isLoading = profilesLoading || groupsLoading || proxiesLoading; @@ -680,6 +706,8 @@ export default function Home() { onImportProfileDialogOpen={setImportProfileDialogOpen} onProxyManagementDialogOpen={setProxyManagementDialogOpen} onSettingsDialogOpen={setSettingsDialogOpen} + searchQuery={searchQuery} + onSearchQueryChange={setSearchQuery} />
diff --git a/src/components/home-header.tsx b/src/components/home-header.tsx index fb8c820..7539977 100644 --- a/src/components/home-header.tsx +++ b/src/components/home-header.tsx @@ -1,7 +1,7 @@ import { FaDownload } from "react-icons/fa"; import { FiWifi } from "react-icons/fi"; import { GoGear, GoKebabHorizontal, GoPlus } from "react-icons/go"; -import { LuTrash2, LuUsers } from "react-icons/lu"; +import { LuSearch, LuTrash2, LuUsers, LuX } from "react-icons/lu"; import { Logo } from "./icons/logo"; import { Button } from "./ui/button"; import { CardTitle } from "./ui/card"; @@ -11,6 +11,7 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from "./ui/dropdown-menu"; +import { Input } from "./ui/input"; import { RippleButton } from "./ui/ripple"; import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip"; @@ -23,6 +24,8 @@ type Props = { onGroupManagementDialogOpen: (open: boolean) => void; onImportProfileDialogOpen: (open: boolean) => void; onCreateProfileDialogOpen: (open: boolean) => void; + searchQuery: string; + onSearchQueryChange: (query: string) => void; }; const HomeHeader = ({ @@ -34,6 +37,8 @@ const HomeHeader = ({ onGroupManagementDialogOpen, onImportProfileDialogOpen, onCreateProfileDialogOpen, + searchQuery, + onSearchQueryChange, }: Props) => { const handleLogoClick = () => { // Trigger the same URL handling logic as if the URL came from the system @@ -76,7 +81,7 @@ const HomeHeader = ({ className="flex gap-2 items-center" > - Delete Selected + Delete
@@ -85,12 +90,32 @@ const HomeHeader = ({ )}
+
+ onSearchQueryChange(e.target.value)} + className="pr-8 pl-10 w-48" + /> + + {searchQuery && ( + + )} +
@@ -138,7 +163,7 @@ const HomeHeader = ({ onClick={() => { onCreateProfileDialogOpen(true); }} - className="flex gap-2 items-center" + className="flex gap-2 items-center h-[36px]" >