end-to-end working

This commit is contained in:
SwiftyOS
2024-11-11 15:37:10 +01:00
parent f539c24571
commit d3e7aab796
12 changed files with 164 additions and 196 deletions

View File

@@ -7,6 +7,10 @@ const nextConfig = {
"images.unsplash.com",
"ddz4ak4pa3d19.cloudfront.net",
"upload.wikimedia.org",
"picsum.photos", // for placeholder images
"dummyimage.com", // for placeholder images
"placekitten.com", // for placeholder images
],
},
// async redirects() {

View File

@@ -1,123 +1,62 @@
import * as React from "react";
import { HeroSection } from "@/components/agptui/composite/HeroSection";
import { FeaturedSection } from "@/components/agptui/composite/FeaturedSection";
import { AgentsSection } from "@/components/agptui/composite/AgentsSection";
import {
FeaturedSection,
FeaturedAgent,
} from "@/components/agptui/composite/FeaturedSection";
import {
AgentsSection,
Agent,
} from "@/components/agptui/composite/AgentsSection";
import { BecomeACreator } from "@/components/agptui/BecomeACreator";
import { FeaturedCreators } from "@/components/agptui/composite/FeaturedCreators";
import {
FeaturedCreators,
FeaturedCreator,
} from "@/components/agptui/composite/FeaturedCreators";
import { Separator } from "@/components/ui/separator";
import { getFeaturedAgents } from "@/app/api/featuredAgents/getFeaturedAgents";
import AutoGPTServerAPI from "@/lib/autogpt-server-api";
interface PageProps {
featuredAgents: {
agentName: string;
agentImage: string;
creatorName: string;
description: string;
runs: number;
rating: number;
}[];
topAgents: {
agentName: string;
agentImage: string;
avatarSrc: string;
description: string;
runs: number;
rating: number;
}[];
featuredCreators: {
creatorName: string;
creatorImage: string;
bio: string;
agentsUploaded: number;
avatarSrc: string;
}[];
// Remove client-side hook since we're doing server-side data fetching
// import { useSupabase } from "@/components/providers/SupabaseProvider";
async function getStoreData() {
const api = new AutoGPTServerAPI();
const [featuredAgents, topAgents, featuredCreators] = await Promise.all([
api.getStoreAgents({ featured: true }),
api.getStoreAgents({ sorted_by: "runs" }),
api.getStoreCreators({ featured: true }),
]);
return {
featuredAgents,
topAgents,
featuredCreators,
};
}
export default async function Page() {
let featuredAgents = await getFeaturedAgents();
let topAgents = [
{
agentName: "Data Analyzer Pro",
agentImage:
"https://ddz4ak4pa3d19.cloudfront.net/cache/07/78/0778415062f8dff56a046a7eca44567c.jpg",
avatarSrc: "https://github.com/shadcn.png",
description:
"Powerful tool for analyzing large datasets and generating insights.",
runs: 50000,
rating: 5,
},
{
agentName: "Image Recognition Master",
agentImage:
"https://ddz4ak4pa3d19.cloudfront.net/cache/59/b9/59b9415d4044f48f9b9e318c4c5a7984.jpg",
avatarSrc: "https://example.com/avatar2.jpg",
description:
"Accurately identify and classify objects in images using state-of-the-art machine learning algorithms.",
runs: 60000,
rating: 4.6,
},
];
let featuredCreators = [
{
creatorName: "AI Labs",
creatorImage:
"https://ddz4ak4pa3d19.cloudfront.net/cache/53/b2/53b2bc7d7900f0e1e60bf64ebf38032d.jpg",
bio: "Pioneering AI solutions for everyday problems",
agentsUploaded: 25,
avatarSrc: "https://github.com/shadcn.png",
},
{
creatorName: "WriteRight Inc.",
creatorImage:
"https://ddz4ak4pa3d19.cloudfront.net/cache/40/f7/40f7bc97c952f8df0f9c88d29defe8d4.jpg",
bio: "Empowering content creators with AI-driven tools",
agentsUploaded: 18,
avatarSrc: "https://example.com/writeright-avatar.jpg",
},
];
const handleSearch = (query: string) => {
console.log("Search query:", query);
// Implement search functionality
};
const handleFilterChange = (selectedFilters: string[]) => {
console.log("Selected filters:", selectedFilters);
// Implement filter functionality
};
const handleCardClick = (agentName: string) => {
console.log("Clicked on agent:", agentName);
// Implement card click functionality
};
const handleBecomeCreator = () => {
console.log("Become a Creator clicked");
// Implement become a creator functionality
};
export default async function Page({
params: { lang },
}: {
params: { lang: string };
}) {
// Get data server-side
const { featuredAgents, topAgents, featuredCreators } = await getStoreData();
return (
<div className="mx-auto w-screen max-w-[1360px]">
<main className="px-4">
<HeroSection
onSearch={handleSearch}
onFilterChange={handleFilterChange}
/>
<HeroSection />
<FeaturedSection
featuredAgents={featuredAgents}
onCardClick={handleCardClick}
featuredAgents={featuredAgents.agents as FeaturedAgent[]}
/>
<Separator />
<AgentsSection
sectionTitle="Top Agents"
agents={topAgents}
onCardClick={handleCardClick}
agents={topAgents.agents as Agent[]}
/>
<Separator />
<FeaturedCreators
featuredCreators={featuredCreators}
onCardClick={handleCardClick}
featuredCreators={featuredCreators.creators as FeaturedCreator[]}
/>
<Separator />
<BecomeACreator
@@ -125,7 +64,6 @@ export default async function Page() {
heading="We're always looking for more Creators!"
description="Join our ever-growing community of hackers and tinkerers"
buttonText="Become a Creator"
onButtonClick={handleBecomeCreator}
/>
</main>
</div>

View File

@@ -31,14 +31,14 @@ export default async function RootLayout({
const supabase = createServerClient();
const {
data: { session },
} = await supabase.auth.getSession();
data: { user },
} = await supabase.auth.getUser();
return (
<html lang="en">
<body className={cn("antialiased transition-colors", inter.className)}>
<Providers
initialSession={session}
initialUser={user}
attribute="class"
defaultTheme="light"
// Feel free to remove this line if you want to use the system theme by default

View File

@@ -6,16 +6,16 @@ import { ThemeProviderProps } from "next-themes";
import { TooltipProvider } from "@/components/ui/tooltip";
import SupabaseProvider from "@/components/providers/SupabaseProvider";
import CredentialsProvider from "@/components/integrations/credentials-provider";
import { Session } from "@supabase/supabase-js";
import { User } from "@supabase/supabase-js";
export function Providers({
children,
initialSession,
initialUser,
...props
}: ThemeProviderProps & { initialSession: Session | null }) {
}: ThemeProviderProps & { initialUser: User | null }) {
return (
<NextThemesProvider {...props}>
<SupabaseProvider initialSession={initialSession}>
<SupabaseProvider initialUser={initialUser}>
<CredentialsProvider>
<TooltipProvider>{children}</TooltipProvider>
</CredentialsProvider>

View File

@@ -1,3 +1,5 @@
"use client";
import * as React from "react";
import { Button } from "./Button";
@@ -6,7 +8,6 @@ interface BecomeACreatorProps {
heading: string;
description: string;
buttonText: string;
onButtonClick: () => void;
}
export const BecomeACreator: React.FC<BecomeACreatorProps> = ({
@@ -14,8 +15,11 @@ export const BecomeACreator: React.FC<BecomeACreatorProps> = ({
heading = "We're always looking for more Creators!",
description = "Join our ever-growing community of hackers and tinkerers",
buttonText = "Become a Creator",
onButtonClick = () => {},
}) => {
const handleButtonClick = () => {
console.log("Become a Creator clicked");
};
return (
<div className="flex w-full flex-col items-center justify-between space-y-4 py-8 leading-9 md:space-y-8">
<div className="mb:mb-8 mb-4 self-start font-neue text-xl font-bold tracking-tight text-[#282828] md:text-[23px]">
@@ -27,7 +31,7 @@ export const BecomeACreator: React.FC<BecomeACreatorProps> = ({
<div className="max-w-full text-center font-neue text-xl font-medium tracking-tight text-[#737373] md:text-[26px]">
{description}
</div>
<Button onClick={onButtonClick} className="mt-8">
<Button onClick={handleButtonClick} className="mt-8">
{buttonText}
</Button>
</div>

View File

@@ -99,64 +99,64 @@ export const MultiRowAgents: Story = {
agents: [
...mockTopAgents,
{
agentName: "Image Recognition AI",
agentImage:
agent_name: "Image Recognition AI",
agent_image:
"https://upload.wikimedia.org/wikipedia/commons/c/c5/Big_buck_bunny_poster_big.jpg",
description:
"Accurately identify and classify objects in images using state-of-the-art machine learning algorithms.",
runs: 60000,
rating: 4.6,
avatarSrc: "https://example.com/avatar4.jpg",
creator_avatar: "https://example.com/avatar4.jpg",
},
{
agentName: "Natural Language Processor",
agentImage:
agent_name: "Natural Language Processor",
agent_image:
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
description:
"Analyze and understand human language with advanced NLP techniques.",
runs: 80000,
rating: 4.8,
avatarSrc: "https://example.com/avatar5.jpg",
creator_avatar: "https://example.com/avatar5.jpg",
},
{
agentName: "Sentiment Analyzer",
agentImage:
agent_name: "Sentiment Analyzer",
agent_image:
"https://upload.wikimedia.org/wikipedia/commons/c/c5/Big_buck_bunny_poster_big.jpg",
description:
"Determine the emotional tone of text data for customer feedback analysis.",
runs: 45000,
rating: 4.3,
avatarSrc: "https://example.com/avatar6.jpg",
creator_avatar: "https://example.com/avatar6.jpg",
},
{
agentName: "Chatbot Builder",
agentImage:
agent_name: "Chatbot Builder",
agent_image:
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
description:
"Create intelligent chatbots for customer service and engagement.",
runs: 55000,
rating: 4.4,
avatarSrc: "https://example.com/avatar7.jpg",
creator_avatar: "https://example.com/avatar7.jpg",
},
{
agentName: "Predictive Analytics Tool",
agentImage:
agent_name: "Predictive Analytics Tool",
agent_image:
"https://upload.wikimedia.org/wikipedia/commons/c/c5/Big_buck_bunny_poster_big.jpg",
description:
"Forecast future trends and outcomes based on historical data.",
runs: 40000,
rating: 4.2,
avatarSrc: "https://example.com/avatar8.jpg",
creator_avatar: "https://example.com/avatar8.jpg",
},
{
agentName: "Text-to-Speech Converter",
agentImage:
agent_name: "Text-to-Speech Converter",
agent_image:
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
description:
"Convert written text into natural-sounding speech in multiple languages.",
runs: 35000,
rating: 4.1,
avatarSrc: "https://example.com/avatar9.jpg",
creator_avatar: "https://example.com/avatar9.jpg",
},
],
onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),

View File

@@ -1,3 +1,5 @@
"use client";
import * as React from "react";
import { StoreCard } from "@/components/agptui/StoreCard";
import {
@@ -5,29 +7,36 @@ import {
CarouselContent,
CarouselItem,
} from "@/components/ui/carousel";
interface Agent {
agentName: string;
agentImage: string;
import { useRouter } from "next/navigation";
export interface Agent {
slug: string;
agent_name: string;
agent_image: string;
creator: string;
creator_avatar: string;
sub_heading: string;
description: string;
runs: number;
rating: number;
avatarSrc: string;
}
interface AgentsSectionProps {
sectionTitle: string;
agents: Agent[];
hideAvatars?: boolean;
onCardClick: (agentName: string) => void;
}
export const AgentsSection: React.FC<AgentsSectionProps> = ({
sectionTitle,
agents: topAgents,
hideAvatars = false,
onCardClick,
}) => {
const router = useRouter();
const handleCardClick = (creator: string, slug: string) => {
router.push(`/store/${creator}/${slug}`);
};
return (
<div className="flex flex-col items-center justify-center py-4 lg:py-8">
<div className="w-full">
@@ -44,14 +53,14 @@ export const AgentsSection: React.FC<AgentsSectionProps> = ({
{topAgents.map((agent, index) => (
<CarouselItem key={index} className="min-w-64 max-w-68">
<StoreCard
agentName={agent.agentName}
agentImage={agent.agentImage}
agentName={agent.agent_name}
agentImage={agent.agent_image}
description={agent.description}
runs={agent.runs}
rating={agent.rating}
avatarSrc={agent.avatarSrc}
avatarSrc={agent.creator_avatar}
hideAvatar={hideAvatars}
onClick={() => onCardClick(agent.agentName)}
onClick={() => handleCardClick(agent.creator, agent.slug)}
/>
</CarouselItem>
))}
@@ -61,14 +70,14 @@ export const AgentsSection: React.FC<AgentsSectionProps> = ({
{topAgents.map((agent, index) => (
<StoreCard
key={index}
agentName={agent.agentName}
agentImage={agent.agentImage}
agentName={agent.agent_name}
agentImage={agent.agent_image}
description={agent.description}
runs={agent.runs}
rating={agent.rating}
avatarSrc={agent.avatarSrc}
avatarSrc={agent.creator_avatar}
hideAvatar={hideAvatars}
onClick={() => onCardClick(agent.agentName)}
onClick={() => handleCardClick(agent.creator, agent.slug)}
/>
))}
</div>

View File

@@ -68,20 +68,20 @@ export const ManyCreators: Story = {
featuredCreators: [
...defaultCreators,
{
creatorName: "ML Master",
creatorImage:
name: "ML Master",
avatar_url:
"https://upload.wikimedia.org/wikipedia/commons/c/c5/Big_buck_bunny_poster_big.jpg",
bio: "Specializing in machine learning algorithms",
agentsUploaded: 20,
avatarSrc: "https://example.com/avatar4.jpg",
description: "Specializing in machine learning algorithms",
num_agents: 20,
avatar_url: "https://example.com/avatar4.jpg",
},
{
creatorName: "NLP Ninja",
creatorImage:
name: "NLP Ninja",
avatar_url:
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
bio: "Expert in natural language processing",
agentsUploaded: 18,
avatarSrc: "https://example.com/avatar5.jpg",
description: "Expert in natural language processing",
num_agents: 18,
avatar_url: "https://example.com/avatar5.jpg",
},
],
onCardClick: (creatorName) => console.log(`Clicked on ${creatorName}`),

View File

@@ -1,3 +1,5 @@
"use client";
import * as React from "react";
import { CreatorCard } from "@/components/agptui/CreatorCard";
import {
@@ -5,24 +7,28 @@ import {
CarouselContent,
CarouselItem,
} from "@/components/ui/carousel";
interface FeaturedCreator {
creatorName: string;
creatorImage: string;
bio: string;
agentsUploaded: number;
avatarSrc: string;
import { useRouter } from "next/navigation";
export interface FeaturedCreator {
name: string;
username: string;
description: string;
avatar_url: string;
num_agents: number;
}
interface FeaturedCreatorsProps {
featuredCreators: FeaturedCreator[];
onCardClick: (creatorName: string) => void;
}
export const FeaturedCreators: React.FC<FeaturedCreatorsProps> = ({
featuredCreators,
onCardClick,
}) => {
const router = useRouter();
const handleCardClick = (creator: string) => {
router.push(`/store/${creator}`);
};
return (
<div className="flex w-screen flex-col items-center justify-center gap-6 py-8 md:w-full lg:items-start">
<div className="font-neue text-[23px] font-bold leading-9 tracking-tight text-[#282828]">
@@ -42,12 +48,12 @@ export const FeaturedCreators: React.FC<FeaturedCreatorsProps> = ({
className="min-w-[13.125rem] max-w-[14.125rem] basis-4/5 sm:basis-3/5"
>
<CreatorCard
creatorName={creator.creatorName}
creatorImage={creator.creatorImage}
bio={creator.bio}
agentsUploaded={creator.agentsUploaded}
avatarSrc={creator.avatarSrc}
onClick={() => onCardClick(creator.creatorName)}
creatorName={creator.username}
creatorImage={creator.avatar_url}
bio={creator.description}
agentsUploaded={creator.num_agents}
avatarSrc={creator.avatar_url}
onClick={() => handleCardClick(creator.username)}
/>
</CarouselItem>
))}
@@ -57,12 +63,12 @@ export const FeaturedCreators: React.FC<FeaturedCreatorsProps> = ({
{featuredCreators.map((creator, index) => (
<CreatorCard
key={index}
creatorName={creator.creatorName}
creatorImage={creator.creatorImage}
bio={creator.bio}
agentsUploaded={creator.agentsUploaded}
avatarSrc={creator.avatarSrc}
onClick={() => onCardClick(creator.creatorName)}
creatorName={creator.username}
creatorImage={creator.avatar_url}
bio={creator.description}
agentsUploaded={creator.num_agents}
avatarSrc={creator.avatar_url}
onClick={() => handleCardClick(creator.username)}
/>
))}
</div>

View File

@@ -9,12 +9,14 @@ import {
} from "@/components/ui/carousel";
import { useCallback, useState } from "react";
import { IconLeftArrow, IconRightArrow } from "@/components/ui/icons";
interface FeaturedAgent {
agentName: string;
subHeading: string;
agentImage: string;
creatorName: string;
import { useRouter } from "next/navigation";
export interface FeaturedAgent {
slug: string;
agent_name: string;
agent_image: string;
creator: string;
creator_avatar: string;
sub_heading: string;
description: string;
runs: number;
rating: number;
@@ -22,14 +24,17 @@ interface FeaturedAgent {
interface FeaturedSectionProps {
featuredAgents: FeaturedAgent[];
onCardClick: (agentName: string) => void;
}
export const FeaturedSection: React.FC<FeaturedSectionProps> = ({
featuredAgents,
onCardClick,
}) => {
const [currentSlide, setCurrentSlide] = useState(0);
const router = useRouter();
const handleCardClick = (creator: string, slug: string) => {
router.push(`/store/${creator}/${slug}`);
};
const handlePrevSlide = useCallback(() => {
setCurrentSlide((prev) =>
@@ -66,14 +71,14 @@ export const FeaturedSection: React.FC<FeaturedSectionProps> = ({
className="ml-0 min-w-64 max-w-68 basis-2/3 basis-auto"
>
<FeaturedStoreCard
agentName={agent.agentName}
subHeading={agent.subHeading}
agentImage={agent.agentImage}
creatorName={agent.creatorName}
agentName={agent.agent_name}
subHeading={agent.sub_heading}
agentImage={agent.agent_image}
creatorName={agent.creator}
description={agent.description}
runs={agent.runs}
rating={agent.rating}
onClick={() => onCardClick(agent.agentName)}
onClick={() => handleCardClick(agent.creator, agent.slug)}
/>
</CarouselItem>
))}

View File

@@ -131,7 +131,6 @@ export const AgentPage: React.FC<AgentPageProps> = ({
heading="We're always looking for more Creators!"
description="Join our ever-growing community of hackers and tinkerers"
buttonText="Become a Creator"
onButtonClick={handleBecomeCreator}
/>
</main>
</div>

View File

@@ -1,7 +1,7 @@
"use client";
import { createClient } from "@/lib/supabase/client";
import { SupabaseClient } from "@supabase/supabase-js";
import { SupabaseClient, User } from "@supabase/supabase-js";
import { Session } from "@supabase/supabase-js";
import { useRouter } from "next/navigation";
import { createContext, useContext, useEffect, useState } from "react";
@@ -10,18 +10,19 @@ import AutoGPTServerAPI from "@/lib/autogpt-server-api";
type SupabaseContextType = {
supabase: SupabaseClient | null;
isLoading: boolean;
user: User | null;
};
const Context = createContext<SupabaseContextType | undefined>(undefined);
export default function SupabaseProvider({
children,
initialSession,
initialUser,
}: {
children: React.ReactNode;
initialSession: Session | null;
initialUser: User | null;
}) {
const [session, setSession] = useState<Session | null>(initialSession);
const [user, setUser] = useState<User | null>(initialUser);
const [supabase, setSupabase] = useState<SupabaseClient | null>(null);
const [isLoading, setIsLoading] = useState(true);
const router = useRouter();
@@ -38,7 +39,9 @@ export default function SupabaseProvider({
const {
data: { subscription },
} = client.auth.onAuthStateChange((event, session) => {
setSession(session);
client.auth.getUser().then((user) => {
setUser(user.data.user);
});
if (event === "SIGNED_IN") {
api.createUser();
}
@@ -55,7 +58,7 @@ export default function SupabaseProvider({
}, [router]);
return (
<Context.Provider value={{ supabase, isLoading }}>
<Context.Provider value={{ supabase, isLoading, user }}>
{children}
</Context.Provider>
);