22
33import { useState , useMemo } from 'react'
44import { useQuery } from '@tanstack/react-query'
5+ import { useSession } from 'next-auth/react'
56import { motion } from 'framer-motion'
67import {
78 Search ,
@@ -11,12 +12,15 @@ import {
1112 DollarSign ,
1213 Play ,
1314 Star ,
15+ Plus ,
16+ User ,
1417} from 'lucide-react'
1518import Link from 'next/link'
1619import { Card , CardContent , CardHeader , CardTitle } from '@/components/ui/card'
1720import { Badge } from '@/components/ui/badge'
1821import { Skeleton } from '@/components/ui/skeleton'
1922import { Input } from '@/components/ui/input'
23+ import { Button } from '@/components/ui/button'
2024import {
2125 Select ,
2226 SelectContent ,
@@ -27,6 +31,7 @@ import {
2731import { AnimatedElement } from '@/components/ui/landing/animated-element'
2832import { formatRelativeTime } from '@/lib/date-utils'
2933import { cn } from '@/lib/utils'
34+ import type { PublisherProfileResponse } from '@codebuff/common/types/publisher'
3035
3136interface AgentData {
3237 id : string
@@ -72,6 +77,7 @@ const EDITORS_CHOICE_AGENTS = [
7277const AgentStorePage = ( ) => {
7378 const [ searchQuery , setSearchQuery ] = useState ( '' )
7479 const [ sortBy , setSortBy ] = useState ( 'cost' )
80+ const { data : session } = useSession ( )
7581
7682 // Fetch agents from the API
7783 const { data : agents = [ ] , isLoading } = useQuery < AgentData [ ] > ( {
@@ -85,6 +91,19 @@ const AgentStorePage = () => {
8591 } ,
8692 } )
8793
94+ // Fetch user's publishers if signed in
95+ const { data : publishers = [ ] } = useQuery < PublisherProfileResponse [ ] > ( {
96+ queryKey : [ 'user-publishers' ] ,
97+ queryFn : async ( ) => {
98+ const response = await fetch ( '/api/publishers' )
99+ if ( ! response . ok ) {
100+ throw new Error ( 'Failed to load publishers' )
101+ }
102+ return response . json ( )
103+ } ,
104+ enabled : ! ! session ?. user ?. id ,
105+ } )
106+
88107 const editorsChoice = useMemo ( ( ) => {
89108 return agents . filter ( ( agent ) => EDITORS_CHOICE_AGENTS . includes ( agent . id ) )
90109 } , [ agents ] )
@@ -132,6 +151,35 @@ const AgentStorePage = () => {
132151 } )
133152 } , [ editorsChoice , searchQuery ] )
134153
154+ // Publisher button logic
155+ const renderPublisherButton = ( ) => {
156+ if ( ! session ) {
157+ return null // Don't show anything if signed out
158+ }
159+
160+ if ( publishers . length === 0 ) {
161+ // User is signed in but has no publishers - show create button
162+ return (
163+ < Link href = "/publishers/new" >
164+ < Button variant = "outline" className = "flex items-center gap-2" >
165+ < Plus className = "h-4 w-4" />
166+ Create Publisher
167+ </ Button >
168+ </ Link >
169+ )
170+ } else {
171+ // User has publishers - link to their publishers page
172+ return (
173+ < Link href = "/publishers" >
174+ < Button variant = "outline" className = "flex items-center gap-2" >
175+ < User className = "h-4 w-4" />
176+ My Publishers
177+ </ Button >
178+ </ Link >
179+ )
180+ }
181+ }
182+
135183 const formatCurrency = ( amount ?: number ) => {
136184 if ( ! amount ) return '$0.00'
137185 if ( amount >= 1000 ) return `$${ ( amount / 1000 ) . toFixed ( 1 ) } k`
@@ -309,7 +357,13 @@ const AgentStorePage = () => {
309357 < div className = "max-w-7xl mx-auto" >
310358 { /* Header */ }
311359 < AnimatedElement type = "fade" className = "text-center mb-12" >
312- < h1 className = "text-4xl font-bold mb-4 text-white" > Agent Store</ h1 >
360+ < div className = "flex items-center justify-between mb-4" >
361+ < div className = "flex-1" />
362+ < h1 className = "text-4xl font-bold text-white" > Agent Store</ h1 >
363+ < div className = "flex-1 flex justify-end" >
364+ { renderPublisherButton ( ) }
365+ </ div >
366+ </ div >
313367 < p className = "text-xl text-muted-foreground max-w-2xl mx-auto" >
314368 Browse all published AI agents. Run, compose, or fork them.
315369 </ p >
0 commit comments