mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
@@ -3,49 +3,70 @@ import { AgentsSection } from "@/components/agptui/composite/AgentsSection";
|
||||
import { SearchBar } from "@/components/agptui/SearchBar";
|
||||
import { FeaturedCreators } from "@/components/agptui/composite/FeaturedCreators";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { FilterChips } from "@/components/agptui/FilterChips";
|
||||
import { SearchFilterChips } from "@/components/agptui/SearchFilterChips";
|
||||
import { SortDropdown } from "@/components/agptui/SortDropdown";
|
||||
|
||||
export default async function Page({
|
||||
params,
|
||||
searchParams,
|
||||
}: {
|
||||
params: { lang: string };
|
||||
searchParams: { searchTerm?: string };
|
||||
searchParams: { searchTerm?: string; sort?: string };
|
||||
}) {
|
||||
const search_term = searchParams.searchTerm || "";
|
||||
const sort = searchParams.sort || "trending";
|
||||
|
||||
const api = new AutoGPTServerAPIServerSide();
|
||||
const { agents } = await api.getStoreAgents({ search_query: search_term });
|
||||
const { agents } = await api.getStoreAgents({
|
||||
search_query: search_term,
|
||||
sort: sort
|
||||
});
|
||||
const { creators } = await api.getStoreCreators({
|
||||
search_query: search_term,
|
||||
});
|
||||
|
||||
const handleFilterChange = (selectedFilters: string[]) => {
|
||||
console.log(selectedFilters);
|
||||
};
|
||||
const agentsCount = agents?.length || 0;
|
||||
const creatorsCount = creators?.length || 0;
|
||||
const totalCount = agentsCount + creatorsCount;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex flex-col">
|
||||
<h2 className="font-['Geist'] text-base font-medium leading-normal">
|
||||
Results for:
|
||||
</h2>
|
||||
<h1 className="font-['Poppins'] text-2xl font-semibold leading-loose">
|
||||
{search_term}
|
||||
</h1>
|
||||
<div className="w-full bg-white">
|
||||
<div className="px-10 max-w-[1440px] mx-auto">
|
||||
<div className="flex items-center justify-between mt-8">
|
||||
<div className="flex flex-col">
|
||||
<h2 className="font-['Geist'] text-base font-medium text-neutral-800">
|
||||
Results for:
|
||||
</h2>
|
||||
<h1 className="font-['Poppins'] text-2xl font-semibold text-neutral-800">
|
||||
{search_term}
|
||||
</h1>
|
||||
</div>
|
||||
<div>
|
||||
<SearchBar width="w-[439px]" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-32 px-6 py-3.5">
|
||||
<SearchBar />
|
||||
|
||||
<div className="mt-8 flex justify-between items-center">
|
||||
<SearchFilterChips
|
||||
totalCount={totalCount}
|
||||
agentsCount={agentsCount}
|
||||
creatorsCount={creatorsCount}
|
||||
/>
|
||||
<SortDropdown />
|
||||
</div>
|
||||
|
||||
<div className="mt-6">
|
||||
<h2 className="text-neutral-800 text-lg font-semibold font-['Poppins'] mb-4">Agents</h2>
|
||||
<AgentsSection agents={agents} sectionTitle="Search Results" />
|
||||
</div>
|
||||
|
||||
<Separator className="my-6" />
|
||||
|
||||
<div className="mb-8">
|
||||
<h2 className="text-neutral-800 text-lg font-semibold font-['Poppins'] mb-4">Creators</h2>
|
||||
<FeaturedCreators featuredCreators={creators} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
{/* TODO: Add filter chips */}
|
||||
{/* <FilterChips badges={["All", "Agents", "Creators"]} onFilterChange={handleFilterChange} /> */}
|
||||
<div className="w-32 px-6 py-3.5">Sort By</div>
|
||||
</div>
|
||||
<AgentsSection agents={agents} sectionTitle="Search Results" />
|
||||
<Separator />
|
||||
<FeaturedCreators featuredCreators={creators} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ interface SearchBarProps {
|
||||
iconColor?: string;
|
||||
textColor?: string;
|
||||
placeholderColor?: string;
|
||||
width?: string;
|
||||
}
|
||||
|
||||
/** SearchBar component for user input and search functionality. */
|
||||
@@ -20,6 +21,7 @@ export const SearchBar: React.FC<SearchBarProps> = ({
|
||||
iconColor = "text-[#646464]",
|
||||
textColor = "text-[#707070]",
|
||||
placeholderColor = "text-[#707070]",
|
||||
width = "w-9/10 lg:w-[56.25rem]",
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
|
||||
@@ -39,7 +41,7 @@ export const SearchBar: React.FC<SearchBarProps> = ({
|
||||
return (
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className="w-9/10 lg:w-[56.25rem]"
|
||||
className={width}
|
||||
data-testid="store-search-bar"
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
interface FilterOption {
|
||||
label: string;
|
||||
count: number;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface SearchFilterChipsProps {
|
||||
totalCount?: number;
|
||||
agentsCount?: number;
|
||||
creatorsCount?: number;
|
||||
}
|
||||
|
||||
export const SearchFilterChips: React.FC<SearchFilterChipsProps> = ({
|
||||
totalCount = 10,
|
||||
agentsCount = 8,
|
||||
creatorsCount = 2,
|
||||
}) => {
|
||||
const [selected, setSelected] = React.useState("all");
|
||||
|
||||
const filters: FilterOption[] = [
|
||||
{ label: "All", count: totalCount, value: "all" },
|
||||
{ label: "Agents", count: agentsCount, value: "agents" },
|
||||
{ label: "Creators", count: creatorsCount, value: "creators" },
|
||||
];
|
||||
|
||||
const handleFilterClick = (value: string) => {
|
||||
setSelected(value);
|
||||
console.log(`Filter selected: ${value}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex gap-2.5">
|
||||
{filters.map((filter) => (
|
||||
<button
|
||||
key={filter.value}
|
||||
onClick={() => handleFilterClick(filter.value)}
|
||||
className={`px-5 py-2 rounded-[34px] flex items-center gap-2.5 ${
|
||||
selected === filter.value
|
||||
? "bg-neutral-800 text-white"
|
||||
: "border border-neutral-600 text-neutral-800"
|
||||
}`}
|
||||
>
|
||||
<span className={`text-base ${selected === filter.value ? "font-medium" : ""}`}>
|
||||
{filter.label}
|
||||
</span>
|
||||
<span className={`text-base ${selected === filter.value ? "font-medium" : ""}`}>
|
||||
{filter.count}
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { ChevronDownIcon } from "@radix-ui/react-icons";
|
||||
|
||||
const sortOptions: SortOption[] = [
|
||||
{ label: "Trending", value: "trending" },
|
||||
{ label: "Most Recent", value: "recent" },
|
||||
{ label: "Most Popular", value: "popular" },
|
||||
{ label: "Highest Rated", value: "rating" },
|
||||
{ label: "Most Runs", value: "runs" },
|
||||
];
|
||||
|
||||
interface SortOption {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export const SortDropdown: React.FC = () => {
|
||||
const [selected, setSelected] = React.useState(sortOptions[0]);
|
||||
|
||||
const handleSelect = (option: SortOption) => {
|
||||
setSelected(option);
|
||||
console.log(`Sorting by: ${option.label} (${option.value})`);
|
||||
};
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger className="flex items-center gap-1.5 focus:outline-none">
|
||||
<span className="text-neutral-800 text-base font-medium">Sort by</span>
|
||||
<span className="text-neutral-800 text-base font-medium">{selected.label}</span>
|
||||
<ChevronDownIcon className="h-4 w-4 text-neutral-800" />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-[200px] bg-white rounded-lg shadow-lg">
|
||||
{sortOptions.map((option) => (
|
||||
<DropdownMenuItem
|
||||
key={option.value}
|
||||
className={`px-4 py-2 text-base cursor-pointer hover:bg-neutral-100 ${
|
||||
selected.value === option.value ? "text-neutral-800 font-medium" : "text-neutral-600"
|
||||
}`}
|
||||
onClick={() => handleSelect(option)}
|
||||
>
|
||||
{option.label}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user