Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

agent catalog front-end #158

Merged
merged 1 commit into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions agent-catalog/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules

# next.js
/.next/
/out/

# production
/build

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
12 changes: 12 additions & 0 deletions agent-catalog/app/agent/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { AgentDetails } from "@/components/agent-details"
import { mockAgents } from "@/lib/mock-agents"

export default function AgentPage({ params }: { params: { id: string } }) {
const agent = mockAgents.find((a) => a.id === params.id) || mockAgents[0]
return (
<div className="min-h-screen bg-white">
<AgentDetails agent={agent} />
</div>
)
}

94 changes: 94 additions & 0 deletions agent-catalog/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

body {
font-family: Arial, Helvetica, sans-serif;
}

@layer utilities {
.text-balance {
text-wrap: balance;
}
}

@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem;
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
32 changes: 32 additions & 0 deletions agent-catalog/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Orbitron, Noto_Sans_JP, Roboto_Mono } from "next/font/google"

const orbitron = Orbitron({
subsets: ["latin"],
variable: "--font-orbitron",
})

const noto = Noto_Sans_JP({
subsets: ["latin"],
variable: "--font-noto-sans-jp",
})

const robotoMono = Roboto_Mono({
subsets: ["latin"],
variable: "--font-roboto-mono",
})

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" className={`${orbitron.variable} ${noto.variable} ${robotoMono.variable}`}>
<body>{children}</body>
</html>
)
}



import './globals.css'
21 changes: 21 additions & 0 deletions agent-catalog/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"use client"

import { AgentGrid } from "@/components/agent-grid"
import { Header } from "@/components/header"
import { mockAgents } from "@/lib/mock-agents"
import { motion, useScroll, useTransform } from "framer-motion"

export default function Home() {
const { scrollY } = useScroll()
const backgroundColor = useTransform(scrollY, [0, 300], ["rgb(26, 26, 46)", "rgb(255, 255, 255)"])

return (
<motion.main className="min-h-screen" style={{ backgroundColor }}>
<Header />
<div className="sticky top-0 z-20 bg-white/80 backdrop-blur-sm border-b">
<AgentGrid agents={mockAgents} />
</div>
</motion.main>
)
}

21 changes: 21 additions & 0 deletions agent-catalog/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
114 changes: 114 additions & 0 deletions agent-catalog/components/agent-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
"use client"

import type { Agent } from "@/types/agent"
import { Card, CardContent, CardHeader } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { MessageSquare, Info } from "lucide-react"
import Image from "next/image"
import { motion } from "framer-motion"
import Link from "next/link"
import { useState, useEffect, useRef } from "react"

interface AgentCardProps {
agent: Agent
index: number
}

export function AgentCard({ agent, index }: AgentCardProps) {
const [isExpanded, setIsExpanded] = useState(false)
const descriptionRef = useRef<HTMLParagraphElement>(null)
const [needsExpand, setNeedsExpand] = useState(false)

useEffect(() => {
if (descriptionRef.current) {
const isOverflowing = descriptionRef.current.scrollHeight > descriptionRef.current.clientHeight
setNeedsExpand(isOverflowing)
}
}, [descriptionRef])

return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: index * 0.1 }}
whileHover={{ y: -5 }}
className="h-full"
>
<Card className="overflow-hidden group bg-scifi-dark border-neon-blue/20 hover:border-neon-blue/40 transition-colors h-full flex flex-col">
<CardHeader className="p-0">
<div className="relative h-[320px] w-full overflow-hidden">
<motion.div whileHover={{ scale: 1.05 }} transition={{ duration: 0.4 }} className="h-full w-full">
<Image
src={agent.avatar || "/placeholder.svg"}
alt={agent.name}
className="object-cover object-center"
fill
priority
/>
</motion.div>
</div>
</CardHeader>
<CardContent className="p-4 flex-grow flex flex-col justify-between space-y-4">
<div className="space-y-2">
<div className="flex items-center justify-between">
<h3 className="font-orbitron font-semibold text-lg text-white">{agent.name}</h3>
<div className="flex items-center gap-2">
<span className="text-sm font-medium text-neon-pink font-orbitron">{agent.price} AIUS</span>
<Badge
variant="secondary"
className="bg-neon-blue border-0 text-white font-roboto-mono hover:bg-neon-blue"
>
{agent.status}
</Badge>
</div>
</div>
<div className="space-y-1">
<p className="text-sm text-blue-100/70 font-roboto-mono">Token: {agent.token}</p>
<p className="text-sm text-blue-100/70 font-roboto-mono">
Tier: {agent.tier.name} (Level {agent.tier.level})
</p>
</div>
<div className="relative">
<p
ref={descriptionRef}
className={`text-sm text-blue-100/70 font-roboto-mono ${!isExpanded ? "line-clamp-3" : ""}`}
>
{agent.description}
</p>
{needsExpand && !isExpanded && (
<button
onClick={() => setIsExpanded(true)}
className="absolute bottom-0 right-0 text-xs text-neon-blue hover:text-neon-pink transition-colors bg-scifi-dark pl-2"
>
Read more
</button>
)}
</div>
</div>
<div className="grid grid-cols-2 gap-2">
<Button
variant="outline"
size="sm"
className="w-full font-roboto-mono border-neon-blue/50 text-neon-blue hover:bg-neon-blue/20 hover:text-white transition-colors"
>
<MessageSquare className="h-4 w-4 mr-2" />
Chat
</Button>
<Link href={`/agent/${agent.id}`} passHref className="w-full">
<Button
variant="outline"
size="sm"
className="w-full font-roboto-mono border-neon-pink/50 text-neon-pink hover:bg-neon-pink/20 hover:text-white transition-colors"
>
<Info className="h-4 w-4 mr-2" />
Details
</Button>
</Link>
</div>
</CardContent>
</Card>
</motion.div>
)
}

13 changes: 13 additions & 0 deletions agent-catalog/components/agent-description.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
interface AgentDescriptionProps {
description: string
}

export function AgentDescription({ description }: AgentDescriptionProps) {
return (
<div className="bg-white p-6 rounded-lg border border-gray-200 shadow-sm">
<h2 className="text-2xl font-orbitron mb-4 text-gray-800">About</h2>
<p className="font-roboto-mono text-gray-600 leading-relaxed text-sm">{description}</p>
</div>
)
}

53 changes: 53 additions & 0 deletions agent-catalog/components/agent-details.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"use client"

import type { Agent } from "@/types/agent"
import { VRMDemo } from "./vrm-demo"
import { PriceChart } from "./price-chart"
import { TokenData } from "./token-data"
import { AgentDescription } from "./agent-description"
import { SocialMediaButtons } from "./social-media-buttons"
import { AgentTags } from "./agent-tags"
import { AgentTiers } from "./agent-tiers"
import { Button } from "./ui/button"
import { MessageSquare, ArrowRightLeft } from "lucide-react"
import { Integrations } from "./integrations"

interface AgentDetailsProps {
agent: Agent
}

export function AgentDetails({ agent }: AgentDetailsProps) {
return (
<div className="min-h-screen bg-white text-gray-800">
<div className="container mx-auto px-4 py-12">
<h1 className="text-5xl font-orbitron font-bold text-gray-900 mb-2 text-center">{agent.name}</h1>
<p className="text-center text-gray-500 mb-2 font-roboto-mono">
{agent.token} | {agent.tier.name} (Level {agent.tier.level})
</p>
<TokenData />
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 mt-12">
<div className="space-y-12">
<VRMDemo />
<PriceChart />
</div>
<div className="space-y-8">
<div className="flex justify-center space-x-4 mb-8">
<Button className="bg-blue-500 hover:bg-blue-600 text-white font-roboto-mono">
<MessageSquare className="mr-2 h-4 w-4" /> Chat
</Button>
<Button className="bg-pink-500 hover:bg-pink-600 text-white font-roboto-mono">
<ArrowRightLeft className="mr-2 h-4 w-4" /> Buy/Sell on Uniswap
</Button>
</div>
<AgentDescription description={agent.description} />
<SocialMediaButtons />
<AgentTags tags={agent.tags} />
<AgentTiers currentTier={agent.tier} />
<Integrations />
</div>
</div>
</div>
</div>
)
}

Loading