mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-30 03:00:41 -04:00
Update frontend to use generated API types and React Query
This commit is contained in:
@@ -29,6 +29,7 @@ export default defineConfig({
|
||||
query: {
|
||||
useQuery: true,
|
||||
useMutation: true,
|
||||
usePrefetch: true,
|
||||
// Will add more as their use cases arise
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
"use server";
|
||||
|
||||
import BackendAPI, {
|
||||
CreatorsResponse,
|
||||
StoreAgentsResponse,
|
||||
} from "@/lib/autogpt-server-api";
|
||||
|
||||
const EMPTY_AGENTS_RESPONSE: StoreAgentsResponse = {
|
||||
agents: [],
|
||||
pagination: {
|
||||
total_items: 0,
|
||||
total_pages: 0,
|
||||
current_page: 0,
|
||||
page_size: 0,
|
||||
},
|
||||
};
|
||||
const EMPTY_CREATORS_RESPONSE: CreatorsResponse = {
|
||||
creators: [],
|
||||
pagination: {
|
||||
total_items: 0,
|
||||
total_pages: 0,
|
||||
current_page: 0,
|
||||
page_size: 0,
|
||||
},
|
||||
};
|
||||
|
||||
export async function getMarketplaceData(): Promise<{
|
||||
featuredAgents: StoreAgentsResponse;
|
||||
topAgents: StoreAgentsResponse;
|
||||
featuredCreators: CreatorsResponse;
|
||||
}> {
|
||||
const api = new BackendAPI();
|
||||
|
||||
const [featuredAgents, topAgents, featuredCreators] = await Promise.all([
|
||||
api.getStoreAgents({ featured: true }).catch((error) => {
|
||||
console.error("Error fetching featured marketplace agents:", error);
|
||||
return EMPTY_AGENTS_RESPONSE;
|
||||
}),
|
||||
api.getStoreAgents({ sorted_by: "runs" }).catch((error) => {
|
||||
console.error("Error fetching top marketplace agents:", error);
|
||||
return EMPTY_AGENTS_RESPONSE;
|
||||
}),
|
||||
api
|
||||
.getStoreCreators({ featured: true, sorted_by: "num_agents" })
|
||||
.catch((error) => {
|
||||
console.error("Error fetching featured marketplace creators:", error);
|
||||
return EMPTY_CREATORS_RESPONSE;
|
||||
}),
|
||||
]);
|
||||
|
||||
return {
|
||||
featuredAgents,
|
||||
topAgents,
|
||||
featuredCreators,
|
||||
};
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
CarouselItem,
|
||||
} from "@/components/ui/carousel";
|
||||
import { useAgentsSection } from "./useAgentsSection";
|
||||
import { StoreAgent } from "@/app/api/__generated__/models/storeAgent";
|
||||
|
||||
export interface Agent {
|
||||
slug: string;
|
||||
@@ -22,7 +23,7 @@ export interface Agent {
|
||||
|
||||
interface AgentsSectionProps {
|
||||
sectionTitle: string;
|
||||
agents: Agent[];
|
||||
agents: StoreAgent[];
|
||||
hideAvatars?: boolean;
|
||||
margin?: string;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { useState } from "react";
|
||||
import { StoreAgent } from "@/lib/autogpt-server-api";
|
||||
import { StoreAgent } from "@/app/api/__generated__/models/storeAgent";
|
||||
|
||||
interface FeaturedStoreCardProps {
|
||||
agent: StoreAgent;
|
||||
|
||||
@@ -2,18 +2,11 @@
|
||||
|
||||
import { CreatorCard } from "@/app/(platform)/marketplace/components/CreatorCard/CreatorCard";
|
||||
import { useFeaturedCreators } from "./useFeaturedCreators";
|
||||
|
||||
export interface FeaturedCreator {
|
||||
name: string;
|
||||
username: string;
|
||||
description: string;
|
||||
avatar_url: string;
|
||||
num_agents: number;
|
||||
}
|
||||
import { Creator } from "@/app/api/__generated__/models/creator";
|
||||
|
||||
interface FeaturedCreatorsProps {
|
||||
title?: string;
|
||||
featuredCreators: FeaturedCreator[];
|
||||
featuredCreators: Creator[];
|
||||
}
|
||||
|
||||
export const FeaturedCreators = ({
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Creator } from "@/app/api/__generated__/models/creator";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { FeaturedCreator } from "./FeaturedCreators";
|
||||
|
||||
interface useFeaturedCreatorsProps {
|
||||
featuredCreators: FeaturedCreator[];
|
||||
featuredCreators: Creator[];
|
||||
}
|
||||
|
||||
export const useFeaturedCreators = ({
|
||||
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
CarouselNext,
|
||||
CarouselIndicator,
|
||||
} from "@/components/ui/carousel";
|
||||
import { StoreAgent } from "@/lib/autogpt-server-api";
|
||||
import Link from "next/link";
|
||||
import { getBackgroundColor } from "./helper";
|
||||
import { useFeaturedSection } from "./useFeaturedSection";
|
||||
import { StoreAgent } from "@/app/api/__generated__/models/storeAgent";
|
||||
|
||||
interface FeaturedSectionProps {
|
||||
featuredAgents: StoreAgent[];
|
||||
@@ -22,6 +22,7 @@ export const FeaturedSection = ({ featuredAgents }: FeaturedSectionProps) => {
|
||||
const { handleNextSlide, handlePrevSlide } = useFeaturedSection({
|
||||
featuredAgents,
|
||||
});
|
||||
|
||||
return (
|
||||
<section className="w-full">
|
||||
<h2 className="mb-8 font-poppins text-2xl font-semibold leading-7 text-neutral-800 dark:text-neutral-200">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from "react";
|
||||
import { StoreAgent } from "@/lib/autogpt-server-api";
|
||||
import { StoreAgent } from "@/app/api/__generated__/models/storeAgent";
|
||||
|
||||
interface useFeaturedSectionProps {
|
||||
featuredAgents: StoreAgent[];
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
"use client";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { FeaturedSection } from "../FeaturedSection/FeaturedSection";
|
||||
import { HeroSection } from "../HeroSection/HeroSection";
|
||||
import { AgentsSection } from "../AgentsSection/AgentsSection";
|
||||
import { FeaturedCreators } from "../FeaturedCreators/FeaturedCreators";
|
||||
import { BecomeACreator } from "../BecomeACreator/BecomeACreator";
|
||||
import {
|
||||
useGetV2ListStoreAgents,
|
||||
useGetV2ListStoreCreators,
|
||||
} from "@/app/api/__generated__/endpoints/store/store";
|
||||
import { StoreAgentsResponse } from "@/app/api/__generated__/models/storeAgentsResponse";
|
||||
import { CreatorsResponse } from "@/app/api/__generated__/models/creatorsResponse";
|
||||
|
||||
export const MainMarkeplacePage = () => {
|
||||
// Below queries are already fetched on server and hydrated properly in cache, hence these requests are fast
|
||||
const {
|
||||
data: featuredAgents,
|
||||
isLoading: isFeaturedAgentsLoading,
|
||||
isError: isFeaturedAgentsError,
|
||||
} = useGetV2ListStoreAgents(
|
||||
{ featured: true },
|
||||
{
|
||||
query: {
|
||||
select: (x) => {
|
||||
return x.data as StoreAgentsResponse;
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
data: topAgents,
|
||||
isLoading: isTopAgentsLoading,
|
||||
isError: isTopAgentsError,
|
||||
} = useGetV2ListStoreAgents(
|
||||
{
|
||||
sorted_by: "runs",
|
||||
},
|
||||
{
|
||||
query: {
|
||||
select: (x) => {
|
||||
return x.data as StoreAgentsResponse;
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
data: featuredCreators,
|
||||
isLoading: isFeaturedCreatorsLoading,
|
||||
isError: isFeaturedCreatorsError,
|
||||
} = useGetV2ListStoreCreators(
|
||||
{ featured: true, sorted_by: "num_agents" },
|
||||
{
|
||||
query: {
|
||||
select: (x) => {
|
||||
return x.data as CreatorsResponse;
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const isLoading =
|
||||
isFeaturedAgentsLoading || isTopAgentsLoading || isFeaturedCreatorsLoading;
|
||||
const hasError =
|
||||
isFeaturedAgentsError || isTopAgentsError || isFeaturedCreatorsError;
|
||||
|
||||
// TODO : Add better Loading Skeletons
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="mx-auto w-screen max-w-[1360px]">
|
||||
<main className="px-4">
|
||||
<div className="flex min-h-[400px] items-center justify-center">
|
||||
<div className="text-lg">Loading...</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// TODO : Add better Error UI
|
||||
if (hasError) {
|
||||
return (
|
||||
<div className="mx-auto w-screen max-w-[1360px]">
|
||||
<main className="px-4">
|
||||
<div className="flex min-h-[400px] items-center justify-center">
|
||||
<div className="text-lg text-red-500">
|
||||
Error loading marketplace data. Please try again later.
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx-auto w-screen max-w-[1360px]">
|
||||
<main className="px-4">
|
||||
<HeroSection />
|
||||
{featuredAgents && (
|
||||
<FeaturedSection featuredAgents={featuredAgents.agents} />
|
||||
)}
|
||||
{/* 100px margin because our featured sections button are placed 40px below the container */}
|
||||
<Separator className="mb-6 mt-24" />
|
||||
|
||||
{topAgents && (
|
||||
<AgentsSection sectionTitle="Top Agents" agents={topAgents.agents} />
|
||||
)}
|
||||
<Separator className="mb-[25px] mt-[60px]" />
|
||||
{featuredCreators && (
|
||||
<FeaturedCreators featuredCreators={featuredCreators.creators} />
|
||||
)}
|
||||
<Separator className="mb-[25px] mt-[60px]" />
|
||||
<BecomeACreator
|
||||
title="Become a Creator"
|
||||
description="Join our ever-growing community of hackers and tinkerers"
|
||||
buttonText="Become a Creator"
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,17 +1,11 @@
|
||||
import React from "react";
|
||||
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Metadata } from "next";
|
||||
|
||||
import { getMarketplaceData } from "./actions";
|
||||
import { HeroSection } from "./components/HeroSection/HeroSection";
|
||||
import { Agent, AgentsSection } from "./components/AgentsSection/AgentsSection";
|
||||
import { MainMarkeplacePage } from "./components/MainMarkeplacePage/MainMarkeplacePage";
|
||||
import {
|
||||
FeaturedCreator,
|
||||
FeaturedCreators,
|
||||
} from "./components/FeaturedCreators/FeaturedCreators";
|
||||
import { BecomeACreator } from "./components/BecomeACreator/BecomeACreator";
|
||||
import { FeaturedSection } from "./components/FeaturedSection/FeaturedSection";
|
||||
prefetchGetV2ListStoreAgentsQuery,
|
||||
prefetchGetV2ListStoreCreatorsQuery,
|
||||
} from "@/app/api/__generated__/endpoints/store/store";
|
||||
import { getQueryClient } from "@/lib/react-query/queryClient";
|
||||
import { dehydrate, HydrationBoundary } from "@tanstack/react-query";
|
||||
|
||||
// Force dynamic rendering to avoid static generation issues with cookies
|
||||
export const dynamic = "force-dynamic";
|
||||
@@ -61,31 +55,24 @@ export const metadata: Metadata = {
|
||||
};
|
||||
|
||||
export default async function MarketplacePage(): Promise<React.ReactElement> {
|
||||
const { featuredAgents, topAgents, featuredCreators } =
|
||||
await getMarketplaceData();
|
||||
const queryClient = getQueryClient();
|
||||
|
||||
await Promise.all([
|
||||
prefetchGetV2ListStoreAgentsQuery(queryClient, {
|
||||
featured: true,
|
||||
}),
|
||||
prefetchGetV2ListStoreAgentsQuery(queryClient, {
|
||||
sorted_by: "runs",
|
||||
}),
|
||||
prefetchGetV2ListStoreCreatorsQuery(queryClient, {
|
||||
featured: true,
|
||||
sorted_by: "num_agents",
|
||||
}),
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className="mx-auto w-screen max-w-[1360px]">
|
||||
<main className="px-4">
|
||||
<HeroSection />
|
||||
<FeaturedSection featuredAgents={featuredAgents.agents} />
|
||||
{/* 100px margin because our featured sections button are placed 40px below the container */}
|
||||
<Separator className="mb-6 mt-24" />
|
||||
<AgentsSection
|
||||
sectionTitle="Top Agents"
|
||||
agents={topAgents.agents as Agent[]}
|
||||
/>
|
||||
<Separator className="mb-[25px] mt-[60px]" />
|
||||
<FeaturedCreators
|
||||
featuredCreators={featuredCreators.creators as FeaturedCreator[]}
|
||||
/>
|
||||
<Separator className="mb-[25px] mt-[60px]" />
|
||||
<BecomeACreator
|
||||
title="Become a Creator"
|
||||
description="Join our ever-growing community of hackers and tinkerers"
|
||||
buttonText="Become a Creator"
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
<HydrationBoundary state={dehydrate(queryClient)}>
|
||||
<MainMarkeplacePage />
|
||||
</HydrationBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
} from "../ui/icons";
|
||||
import Link from "next/link";
|
||||
import { ProfilePopoutMenuLogoutButton } from "./ProfilePopoutMenuLogoutButton";
|
||||
import { PublishAgentPopout } from "./composite/PublishAgentPopout";
|
||||
import { PublishAgentPopout } from "@/app/(platform)/marketplace/components/PublishAgentPopout/PublishAgentPopout";
|
||||
|
||||
interface ProfilePopoutMenuProps {
|
||||
userName?: string;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import { isServer, QueryClient } from "@tanstack/react-query";
|
||||
|
||||
function makeQueryClient() {
|
||||
|
||||
Reference in New Issue
Block a user