add categories filter in search

This commit is contained in:
Abhimanyu Yadav
2025-05-28 13:57:39 +05:30
parent 596824c1e7
commit 07c84a4757
4 changed files with 57 additions and 19 deletions

View File

@@ -24,9 +24,9 @@ export type DefaultStateType =
export type CategoryKey =
| "blocks"
| "integrations"
| "providers"
| "marketplace_agents"
| "my_agents"
| "templates";
| "my_agents";
export interface Filters {
categories: {
@@ -34,11 +34,13 @@ export interface Filters {
integrations: boolean;
marketplace_agents: boolean;
my_agents: boolean;
templates: boolean;
providers: boolean;
};
createdBy: string[];
}
export type CategoryCounts = Record<CategoryKey, number>;
interface BlockMenuContextType {
defaultState: DefaultStateType;
setDefaultState: React.Dispatch<React.SetStateAction<DefaultStateType>>;
@@ -56,6 +58,8 @@ interface BlockMenuContextType {
setCreators: React.Dispatch<React.SetStateAction<string[]>>;
searchData: SearchItem[];
setSearchData: React.Dispatch<React.SetStateAction<SearchItem[]>>;
categoryCounts: CategoryCounts;
setCategoryCounts: React.Dispatch<React.SetStateAction<CategoryCounts>>;
addNode: (
blockId: string,
nodeType: string,
@@ -93,7 +97,7 @@ export function BlockMenuStateProvider({
integrations: false,
marketplace_agents: false,
my_agents: false,
templates: false,
providers: false,
},
createdBy: [],
});
@@ -103,6 +107,14 @@ export function BlockMenuStateProvider({
const [searchId, setSearchId] = useState<string | undefined>(undefined);
const [categoryCounts, setCategoryCounts] = useState<CategoryCounts>({
blocks: 0,
integrations: 0,
marketplace_agents: 0,
my_agents: 0,
providers: 0,
});
return (
<BlockMenuContext.Provider
value={{
@@ -120,6 +132,8 @@ export function BlockMenuStateProvider({
setFilters,
searchData,
setSearchData,
categoryCounts,
setCategoryCounts,
addNode,
}}
>

View File

@@ -5,8 +5,14 @@ import { useBlockMenuContext } from "../block-menu-provider";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
const BlockMenuSearch: React.FC = ({}) => {
const { searchData, searchQuery, searchId, setSearchData } =
useBlockMenuContext();
const {
searchData,
searchQuery,
searchId,
setSearchData,
filters,
setCategoryCounts,
} = useBlockMenuContext();
const [isLoading, setIsLoading] = useState<boolean>(false);
const [hasMore, setHasMore] = useState<boolean>(true);
const [page, setPage] = useState<number>(0);
@@ -26,14 +32,31 @@ const BlockMenuSearch: React.FC = ({}) => {
}
try {
// Prepare filter array from active categories
const activeCategories = Object.entries(filters.categories)
.filter(([_, isActive]) => isActive)
.map(([category, _]) => category)
.filter((category) => category !== "templates") // API doesn't support templates filter
.map(
(category) =>
category as
| "blocks"
| "integrations"
| "marketplace_agents"
| "my_agents",
);
const response = await api.searchBlocks({
search_query: searchQuery,
search_id: searchId,
page: pageNum,
page_size: pageSize,
filter: activeCategories.length > 0 ? activeCategories : undefined,
by_creator:
filters.createdBy.length > 0 ? filters.createdBy : undefined,
});
await new Promise((resolve) => setTimeout(resolve, 2000));
setCategoryCounts(response.total_items);
if (isLoadMore) {
setSearchData((prev) => [...prev, ...response.items]);
@@ -58,7 +81,7 @@ const BlockMenuSearch: React.FC = ({}) => {
setLoadingMore(false);
}
},
[searchQuery, searchId, api, setSearchData, pageSize],
[searchQuery, searchId, filters, api, setSearchData, pageSize],
);
const handleScroll = useCallback(() => {
@@ -92,7 +115,7 @@ const BlockMenuSearch: React.FC = ({}) => {
setPage(0);
setHasMore(true);
}
}, [searchQuery, searchId, fetchSearchData, setSearchData]);
}, [searchQuery, searchId, filters, fetchSearchData, setSearchData]);
return (
<div

View File

@@ -69,7 +69,7 @@ export default function FilterSheet({
integrations: false,
marketplace_agents: false,
my_agents: false,
templates: false,
providers: false,
},
createdBy: [],
};

View File

@@ -2,23 +2,20 @@ import { useState, useEffect, useCallback } from "react";
import FilterChip from "../FilterChip";
import FilterSheet from "./FilterSheet";
import { CategoryKey, useBlockMenuContext } from "../block-menu-provider";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
const FiltersList = () => {
const { setCreators, filters, setFilters } = useBlockMenuContext();
const { filters, setFilters, categoryCounts, setCategoryCounts } =
useBlockMenuContext();
const api = useBackendAPI();
const categories: Array<{ key: CategoryKey; name: string }> = [
{ key: "blocks", name: "Blocks" },
{ key: "integrations", name: "Integrations" },
{ key: "marketplace_agents", name: "Marketplace agents" },
{ key: "my_agents", name: "My agents" },
{ key: "templates", name: "Templates" },
{ key: "providers", name: "Providers" },
];
// TEMPORARY FETCHING
useEffect(() => {
const mockCreators = ["Abhi", "Abhi 1", "Abhi 2", "Abhi 3", "Abhi 4"];
setCreators(mockCreators);
}, [setCreators]);
const handleCategoryFilter = (category: CategoryKey) => {
setFilters({
...filters,
@@ -43,6 +40,10 @@ const FiltersList = () => {
[filters, setFilters],
);
useEffect(() => {
console.log(categoryCounts);
}, [categoryCounts]);
return (
<div className="flex flex-nowrap gap-3 overflow-x-auto scrollbar-hide">
<FilterSheet categories={categories} />
@@ -64,7 +65,7 @@ const FiltersList = () => {
Object.values(filters.categories).filter(Boolean).length === 1 &&
filters.categories[category.key]
}
number={103}
number={categoryCounts[category.key]}
selected={filters.categories[category.key]}
onClick={() => handleCategoryFilter(category.key)}
/>