finish project
This commit is contained in:
parent
baa13ce916
commit
b0f2cb1b0e
27
package-lock.json
generated
27
package-lock.json
generated
@ -28,7 +28,7 @@
|
||||
"canvas-confetti": "^1.9.3",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"framer-motion": "^11.3.21",
|
||||
"framer-motion": "^11.18.2",
|
||||
"geist": "^1.3.1",
|
||||
"lucide-react": "^0.417.0",
|
||||
"motion": "^12.0.11",
|
||||
@ -45,7 +45,9 @@
|
||||
"remark-parse": "^11.0.0",
|
||||
"remark-rehype": "^11.1.1",
|
||||
"shiki": "^1.22.0",
|
||||
"simplex-noise": "^4.0.3",
|
||||
"sonner": "^1.7.4",
|
||||
"swiper": "^11.2.2",
|
||||
"tailwind-merge": "^2.4.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"unified": "^11.0.5",
|
||||
@ -10850,6 +10852,11 @@
|
||||
"is-arrayish": "^0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/simplex-noise": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/simplex-noise/-/simplex-noise-4.0.3.tgz",
|
||||
"integrity": "sha512-qSE2I4AngLQG7BXqoZj51jokT4WUXe8mOBrvfOXpci8+6Yu44+/dD5zqDpOx3Ux792eamTd2lLcI8jqFntk/lg=="
|
||||
},
|
||||
"node_modules/sonic-boom": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz",
|
||||
@ -11354,6 +11361,24 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/swiper": {
|
||||
"version": "11.2.2",
|
||||
"resolved": "https://registry.npmjs.org/swiper/-/swiper-11.2.2.tgz",
|
||||
"integrity": "sha512-FmAN6zACpVUbd/1prO9xQ9gKo9cc6RE2UKU/z4oXtS8fNyX4sdOW/HHT/e444WucLJs0jeMId6WjdWM2Lrs8zA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/swiperjs"
|
||||
},
|
||||
{
|
||||
"type": "open_collective",
|
||||
"url": "http://opencollective.com/swiper"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 4.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tabbable": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
|
||||
|
@ -29,7 +29,7 @@
|
||||
"canvas-confetti": "^1.9.3",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"framer-motion": "^11.3.21",
|
||||
"framer-motion": "^11.18.2",
|
||||
"geist": "^1.3.1",
|
||||
"lucide-react": "^0.417.0",
|
||||
"motion": "^12.0.11",
|
||||
@ -46,7 +46,9 @@
|
||||
"remark-parse": "^11.0.0",
|
||||
"remark-rehype": "^11.1.1",
|
||||
"shiki": "^1.22.0",
|
||||
"simplex-noise": "^4.0.3",
|
||||
"sonner": "^1.7.4",
|
||||
"swiper": "^11.2.2",
|
||||
"tailwind-merge": "^2.4.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"unified": "^11.0.5",
|
||||
|
BIN
public/background-6.png
Normal file
BIN
public/background-6.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 729 KiB |
@ -12,7 +12,7 @@ import BlurFade from "@/components/blur-fade";
|
||||
export function CTA() {
|
||||
return (
|
||||
<section>
|
||||
<div className="layout border-x px-3 sm:px-6">
|
||||
<div className="layout border-x border-primary px-3 sm:px-6">
|
||||
<BlurFade
|
||||
inView
|
||||
className="flex flex-col items-center justify-center gap-8 py-20"
|
||||
|
@ -70,7 +70,7 @@ const FEATURE_LIST = [
|
||||
export function Features() {
|
||||
return (
|
||||
<section id="features" className="">
|
||||
<div className="layout h-8 border-x"></div>
|
||||
<div className="layout h-8 border-x border-primary"></div>
|
||||
<BlurFade inView className="flex items-center justify-center">
|
||||
<hr className="w-full border-black" />
|
||||
<Badge className="hover:bg-primary rounded-md font-light">
|
||||
@ -80,17 +80,23 @@ export function Features() {
|
||||
</Badge>
|
||||
<hr className="w-full border-black" />
|
||||
</BlurFade>
|
||||
<div className="layout border-x px-3 sm:px-6 py-8">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8 ">
|
||||
<div className="layout border-x border-primary px-3 sm:px-6 py-8">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6 ">
|
||||
{FEATURE_LIST.map((feature, index) => (
|
||||
<BlurFade key={index} delay={0.2 + index * 0.2} inView>
|
||||
<Card className="bg-background border-none shadow-[0_0_23.1px_0_rgba(0,0,0,0.08)_inset]">
|
||||
<Card
|
||||
// className="bg-background border-none shadow-[0_0_23.1px_0_rgba(0,0,0,0.08)_inset]"
|
||||
className="border border-primary rounded-none bg-transparent"
|
||||
>
|
||||
<CardContent className="p-6 space-y-4">
|
||||
<div className="w-14 h-14 rounded-full flex items-center justify-center shadow-[0_-2px_4.4px_0_rgba(0,0,0,0.4)_inset]">
|
||||
{feature.icon}
|
||||
</div>
|
||||
<h3 className="text-xl font-bold">{feature.heading}</h3>
|
||||
<p className="text-muted-foreground">{feature.desc}</p>
|
||||
<div className="w-full border border-primary rounded-md bg-card flex items-center gap-1 px-2 py-1">
|
||||
<ChevronRight className="h-6 w-6"/>
|
||||
<h3 className="text-lg font-semibold">/{feature.heading}</h3>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">{feature.desc}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</BlurFade>
|
||||
|
@ -209,22 +209,10 @@ export function Hero() {
|
||||
|
||||
return (
|
||||
<section id="hero">
|
||||
<div className="relative">
|
||||
<div className="relative z-20">
|
||||
<div className="pt-8 px-3 sm:px-6 layout flex flex-col justify-center items-center border-x">
|
||||
<HeroPill />
|
||||
<HeroTitles />
|
||||
<HeroCTA privyAuth={privyAuth} />
|
||||
</div>
|
||||
</div>
|
||||
<LetterGlitch
|
||||
glitchSpeed={50}
|
||||
centerVignette={false}
|
||||
outerVignette={false}
|
||||
smooth={true}
|
||||
glitchColors={["#222222", "#BEBDBD"]}
|
||||
className="absolute top-0 left-0 right-0 bottom-0 bg-transparent opacity-20"
|
||||
/>
|
||||
<div className="pt-20 px-3 sm:px-6 layout flex flex-col justify-center items-center border-x border-primary">
|
||||
<HeroPill />
|
||||
<HeroTitles />
|
||||
<HeroCTA privyAuth={privyAuth} />
|
||||
</div>
|
||||
<HeroMarquee />
|
||||
</section>
|
||||
|
@ -23,7 +23,7 @@ export function Roadmap() {
|
||||
return (
|
||||
<section className="">
|
||||
<div className="layout relative">
|
||||
<div className="border-x border-b">
|
||||
<div className="border-x border-primary border-b">
|
||||
<BlurFade className="p-6" inView>
|
||||
<Badge className="hover:bg-primary rounded-md font-light mb-6">
|
||||
<ChevronLeft className="h-6 w-6" />
|
||||
@ -67,23 +67,24 @@ export function Roadmap() {
|
||||
</div>
|
||||
</BlurFade>
|
||||
</div>
|
||||
<ul className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 border-x ">
|
||||
<ul className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 border-x border-primary ">
|
||||
{ROADMAPS.map((roadmap, idx) => (
|
||||
<BlurFade
|
||||
<li
|
||||
key={idx}
|
||||
delay={0.2 * idx}
|
||||
inView
|
||||
className="border-r last:border-r-0 p-6 space-y-4 border-b last:border-b-0 sm:[&:nth-child(3)]:border-b-0 sm:[&:nth-child(4)]:border-b-0 lg:border-b-0"
|
||||
className="border-r border-primary last:border-r-0 p-6 px-4 space-y-4 border-b last:border-b-0 sm:[&:nth-child(3)]:border-b-0 sm:[&:nth-child(4)]:border-b-0 lg:border-b-0"
|
||||
>
|
||||
<li>
|
||||
<div className="flex items-center gap-3">
|
||||
<BlurFade delay={0.2 * idx} inView>
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<SevenSegmentDigit digit={`${idx + 1}`} />
|
||||
<p className="text-lg font-semibold">Q{idx + 1} 2025</p>
|
||||
</div>
|
||||
<h2 className="text-2xl font-semibold">Phase 0{idx + 1}</h2>
|
||||
<p className="text-[#222222]">{roadmap}</p>
|
||||
</li>
|
||||
</BlurFade>
|
||||
<div className="mb-2 w-full border border-primary rounded-md bg-card flex items-center gap-1 px-2 py-1">
|
||||
<ChevronRight className="h-6 w-6" />
|
||||
<h3 className="text-lg font-semibold">/Phase 0{idx + 1}</h3>
|
||||
</div>
|
||||
<p className="text-muted-foreground">{roadmap}</p>
|
||||
</BlurFade>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<LetterGlitch
|
||||
|
@ -62,7 +62,7 @@ const STATS = [
|
||||
export function Tokenomics() {
|
||||
return (
|
||||
<section id="tokenomics">
|
||||
<div className="layout h-8 border-x"></div>
|
||||
<div className="layout h-8 border-x border-primary"></div>
|
||||
<BlurFade className="flex items-center justify-center" inView>
|
||||
<hr className="w-full border-black" />
|
||||
<Badge className="hover:bg-primary rounded-md font-light">
|
||||
@ -72,7 +72,7 @@ export function Tokenomics() {
|
||||
</Badge>
|
||||
<hr className="w-full border-black" />
|
||||
</BlurFade>
|
||||
<div className="layout border-x px-3 sm:px-6 py-8">
|
||||
<div className="layout border-x border-primary px-3 sm:px-6 py-8">
|
||||
<Accordion type="multiple" className="w-full space-y-6">
|
||||
{STATS.map((stat, idx) => (
|
||||
<AccordionItem
|
||||
@ -82,16 +82,27 @@ export function Tokenomics() {
|
||||
className="border-b-0"
|
||||
>
|
||||
<BlurFade delay={0.2 + idx * 0.2} inView>
|
||||
<Card className="border-primary rounded-lg">
|
||||
<AccordionTrigger className="py-0 [&[data-state=open]>div>svg]:rotate-180 [&[data-state=closed]>div]:bg-primary [&[data-state=closed]>div]:text-white [&[data-state=open]>div]:mb-0 [&[data-state=open]>div]:sm:mb-0 [&[data-state=open]>div]:bg-[url(/background-3.png)] [&[data-state=open]>div]:text-primary hover:no-underline">
|
||||
<div className="transition-all grow m-2 p-3 sm:m-4 sm:p-6 flex justify-between items-center gap-3 rounded-lg">
|
||||
<div className="flex items-center gap-3">
|
||||
<p className="font-bold text-2xl sm:text-5xl">
|
||||
{stat.value}
|
||||
</p>
|
||||
<Card
|
||||
className="border-primary border-b-0 rounded-none"
|
||||
// style={{
|
||||
// borderWidth: "1px, 1px, 0px, 1px",
|
||||
// borderStyle: "solid",
|
||||
// borderImageSource:
|
||||
// "linear-gradient(178.02deg, #000000 -74.84%, #FFFFFF 71.94%)",
|
||||
// }}
|
||||
>
|
||||
<AccordionTrigger className="py-0 [&[data-state=closed]_.circle]:bg-white [&[data-state=open]_.circle]:bg-primary [&[data-state=open]_svg]:rotate-90 [&[data-state=closed]>div]:bg-primary [&[data-state=closed]>div]:text-white [&[data-state=open]>div]:mb-0 [&[data-state=open]>div]:sm:mb-0 [&[data-state=open]>div]:bg-[url(/background-3.png)] [&[data-state=open]>div]:text-primary hover:no-underline">
|
||||
<div className="transition-all grow m-2 p-3 sm:m-4 sm:p-6 flex justify-between items-center gap-3">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-3">
|
||||
<div className="flex items-center">
|
||||
<div className="transition-all circle h-6 w-6 rounded-full" />
|
||||
<ChevronRight className="mr-3 h-6 w-6 sm:h-10 sm:w-10 shrink-0 transition-transform duration-200" />
|
||||
<p className="font-bold text-2xl sm:text-5xl">
|
||||
{stat.value}
|
||||
</p>
|
||||
</div>
|
||||
<h2 className="text-xl sm:text-3xl">{stat.desc}</h2>
|
||||
</div>
|
||||
<ChevronDown className="h-6 w-6 sm:h-8 sm:w-8 shrink-0 transition-transform duration-200" />
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="m-2 mt-0 p-3 sm:m-4 sm:mt-0 sm:p-6 bg-[url(/background-3.png)] text-muted-foreground text-sm sm:text-lg">
|
||||
|
@ -179,7 +179,7 @@ const CardContent = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="p-6 bg-transparent">
|
||||
<Card className="relative z-20 bg-white p-6 border-primary rounded-none">
|
||||
<div className="flex flex-col-reverse sm:flex-row justify-between gap-3 mb-4">
|
||||
<div className="mr-auto">
|
||||
<div className="flex space-x-2 mb-2">
|
||||
|
@ -7,14 +7,15 @@ import { ANIMATION_EASE } from "@/lib/config";
|
||||
import { AuroraText } from "@/components/aurora-text";
|
||||
import { Section } from "@/components/section";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Icons } from "@/components/icons";
|
||||
|
||||
export function Heading() {
|
||||
return (
|
||||
<section id="heading">
|
||||
<div className="layout py-6 relative w-full border-x overflow-hidden">
|
||||
<div className="layout pt-24 pb-6 relative w-full overflow-hidden">
|
||||
<motion.h1
|
||||
className={cn(
|
||||
"text-center text-4xl font-semibold leading-tighter text-foreground sm:text-5xl md:text-6xl tracking-tighter"
|
||||
"flex justify-center items-center text-center text-4xl font-semibold leading-tighter text-foreground sm:text-5xl md:text-6xl tracking-tighter"
|
||||
)}
|
||||
initial={{ filter: "blur(10px)", opacity: 0, y: 50 }}
|
||||
animate={{ filter: "blur(0px)", opacity: 1, y: 0 }}
|
||||
@ -23,7 +24,9 @@ export function Heading() {
|
||||
ease: ANIMATION_EASE,
|
||||
}}
|
||||
>
|
||||
<AuroraText className="leading-normal">Ask a Question</AuroraText>
|
||||
<Icons.paranthesesLeftBig />
|
||||
<span className="mx-2">Ask a Question</span>
|
||||
<Icons.paranthesesRightBig />
|
||||
</motion.h1>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -18,6 +18,7 @@ import { Separator } from "@/components/ui/separator";
|
||||
import { Button, buttonVariants } from "@/components/ui/button";
|
||||
|
||||
import Spinner from "@/components/spinner";
|
||||
import { Card } from "@/components/ui/card";
|
||||
|
||||
type ResponseAgentCardProps = {
|
||||
agentResponseId: string;
|
||||
@ -80,7 +81,7 @@ const CardContent = ({
|
||||
const { id, agent_id, question, response, agents } = agentResponse;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card className="relative z-20 bg-white p-6 border-primary rounded-none">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<figure className="relative h-16 w-16 rounded-full overflow-hidden">
|
||||
<Image
|
||||
@ -163,6 +164,6 @@ const CardContent = ({
|
||||
Copy Link
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { Footer } from "@/components/footer";
|
||||
import { Heading } from "./_components/heading";
|
||||
import { AskAgentCard } from "./_components/ask-agent-card";
|
||||
import { Particles } from "@/components/particles";
|
||||
import { Header } from "@/components/header";
|
||||
|
||||
export default async function ChatToAgent({
|
||||
params,
|
||||
@ -8,18 +10,24 @@ export default async function ChatToAgent({
|
||||
params: Promise<{ agentId: string }>;
|
||||
}) {
|
||||
const { agentId } = await params;
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="relative">
|
||||
<Header />
|
||||
<Heading />
|
||||
<hr className="" />
|
||||
<section>
|
||||
<div className="layout border-x px-3 sm:px-6 py-8">
|
||||
<div className="layout px-3 sm:px-6 py-8">
|
||||
<AskAgentCard agentId={agentId} />
|
||||
</div>
|
||||
</section>
|
||||
<hr className="" />
|
||||
<Footer />
|
||||
</>
|
||||
<Particles
|
||||
className="absolute inset-0 z-0 opacity-30"
|
||||
quantity={5000}
|
||||
ease={90}
|
||||
color={"#000000"}
|
||||
refresh
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -7,14 +7,15 @@ import { ANIMATION_EASE } from "@/lib/config";
|
||||
import { AuroraText } from "@/components/aurora-text";
|
||||
import { Section } from "@/components/section";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Icons } from "@/components/icons";
|
||||
|
||||
export function Heading() {
|
||||
return (
|
||||
<section id="heading">
|
||||
<div className="layout py-6 relative w-full border-x overflow-hidden">
|
||||
<div className="layout pt-24 pb-6 relative w-full overflow-hidden">
|
||||
<motion.h1
|
||||
className={cn(
|
||||
"text-center text-4xl font-semibold leading-tighter text-foreground sm:text-5xl md:text-6xl tracking-tighter"
|
||||
"flex justify-center items-center text-center text-4xl font-semibold leading-tighter text-foreground sm:text-5xl md:text-6xl tracking-tighter"
|
||||
)}
|
||||
initial={{ filter: "blur(10px)", opacity: 0, y: 50 }}
|
||||
animate={{ filter: "blur(0px)", opacity: 1, y: 0 }}
|
||||
@ -23,7 +24,9 @@ export function Heading() {
|
||||
ease: ANIMATION_EASE,
|
||||
}}
|
||||
>
|
||||
<AuroraText className="leading-normal">Ask a Question</AuroraText>
|
||||
<Icons.paranthesesLeftBig />
|
||||
<span className="mx-2">Ask a Question</span>
|
||||
<Icons.paranthesesRightBig />
|
||||
</motion.h1>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -2,6 +2,8 @@ import { Footer } from "@/components/footer";
|
||||
import { Heading } from "./_components/heading";
|
||||
import { AskAgentCard } from "../../_components/ask-agent-card";
|
||||
import ResponseAgentCard from "../../_components/response-agent-card";
|
||||
import { Header } from "@/components/header";
|
||||
import { Particles } from "@/components/particles";
|
||||
|
||||
export default async function AgentResponse({
|
||||
params,
|
||||
@ -11,22 +13,27 @@ export default async function AgentResponse({
|
||||
const { agentId, responseId } = await params;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="relative">
|
||||
<Header />
|
||||
<Heading />
|
||||
<hr className="" />
|
||||
<section>
|
||||
<div className="layout border-x px-3 sm:px-6 py-8">
|
||||
<div className="layout px-3 sm:px-6 py-8">
|
||||
<AskAgentCard agentId={agentId} disabled={true} />
|
||||
</div>
|
||||
</section>
|
||||
<hr className="" />
|
||||
<section>
|
||||
<div className="layout border-x px-3 sm:px-6 py-8">
|
||||
<div className="layout px-3 sm:px-6 py-8">
|
||||
<ResponseAgentCard agentResponseId={responseId} />
|
||||
</div>
|
||||
</section>
|
||||
<hr className="" />
|
||||
<Footer />
|
||||
</>
|
||||
<Particles
|
||||
className="absolute inset-0 z-0 opacity-30"
|
||||
quantity={5000}
|
||||
ease={90}
|
||||
color={"#000000"}
|
||||
refresh
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -3,23 +3,21 @@ import Image from "next/image";
|
||||
|
||||
import { User } from "@privy-io/react-auth";
|
||||
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { Pencil, Play, Share2 } from "lucide-react";
|
||||
import { ChevronRight } from "lucide-react";
|
||||
|
||||
import { Tables } from "@/utils/supabase/database.types";
|
||||
|
||||
import { cn, formatDate } from "@/lib/utils";
|
||||
import { ANIMATION_EASE } from "@/lib/config";
|
||||
|
||||
import { Button, buttonVariants } from "@/components/ui/button";
|
||||
import { Icons } from "@/components/icons";
|
||||
|
||||
type AgentCardProps = {
|
||||
data: Tables<"agents">;
|
||||
idx: number;
|
||||
user: User | null;
|
||||
isActive: boolean;
|
||||
};
|
||||
|
||||
export default function AgentCard(props: AgentCardProps) {
|
||||
@ -36,47 +34,94 @@ export default function AgentCard(props: AgentCardProps) {
|
||||
} = props.data;
|
||||
|
||||
return (
|
||||
<motion.li
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{
|
||||
duration: 0.8,
|
||||
delay: props.idx * 0.2,
|
||||
ease: ANIMATION_EASE,
|
||||
}}
|
||||
<li
|
||||
className={cn(
|
||||
"flex flex-col p-4",
|
||||
"bg-background rounded-lg transition-all duration-300 border hover:shadow-[0_0_23.1px_0_rgba(0,0,0,0.08)_inset]"
|
||||
"relative flex flex-col p-4",
|
||||
"bg-background transition-all border border-primary hover:shadow-[0_0_23.1px_0_rgba(0,0,0,0.08)_inset]"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"absolute top-0 left-0 right-0 bottom-0 h-full w-full",
|
||||
!props.isActive &&
|
||||
" bg-white bg-opacity-50 backdrop-blur-[3.9000000953674316px]"
|
||||
)}
|
||||
/>
|
||||
{image_url && (
|
||||
<Image
|
||||
className="object-cover mb-3 rounded-lg overflow-hidden"
|
||||
src={"/agent.png"}
|
||||
className="object-cover mb-3 overflow-hidden"
|
||||
src={image_url}
|
||||
width={1200}
|
||||
height={630}
|
||||
alt={name}
|
||||
/>
|
||||
)}
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-xl font-bold mb-2">{name}</h3>
|
||||
<div
|
||||
className="mb-2 text-white px-2 py-0.5 rounded-md"
|
||||
style={{
|
||||
background: "linear-gradient(90deg, #FF512F 0%, #F09819 100%)",
|
||||
}}
|
||||
>
|
||||
{conversation} chats
|
||||
<div className="flex items-center mb-2">
|
||||
<ChevronRight className="h-5 w-5" />
|
||||
<h3 className="text-xl">/{name}</h3>
|
||||
</div>
|
||||
|
||||
<div className="mb-2 bg-[#EDEDED] px-2 py-0.5 rounded-md">
|
||||
{conversation} chat{conversation > 1 && "s"}
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground mb-2">{description}</p>
|
||||
<p className="mb-2 text-primary">
|
||||
<time dateTime={created_at} className="text-xs">
|
||||
<span className="font-bold">Last Active: </span>
|
||||
<time dateTime={created_at} className="text-sm">
|
||||
<span className="font-bold">Last Active__</span>
|
||||
{last_conv ? formatDate(last_conv) : "-"}
|
||||
</time>
|
||||
</p>
|
||||
<div className="mt-auto grid sm:grid-cols-2 gap-2">
|
||||
{!props.user || user_id !== props.user.id ? (
|
||||
<Button
|
||||
className="justify-start px-0 py-0 mt-auto mb-2"
|
||||
variant={"link"}
|
||||
disabled={true}
|
||||
>
|
||||
<Icons.paranthesesLeft className="fill-black mr-2" />
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 19 19"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mr-2"
|
||||
>
|
||||
<path
|
||||
d="M18.3103 4.87866L14.1216 0.688973C13.9823 0.549649 13.8169 0.439129 13.6349 0.363725C13.4529 0.288322 13.2578 0.249512 13.0608 0.249512C12.8638 0.249512 12.6687 0.288322 12.4867 0.363725C12.3047 0.439129 12.1393 0.549649 12 0.688973L0.439695 12.2502C0.299801 12.389 0.188889 12.5542 0.113407 12.7362C0.0379245 12.9183 -0.000621974 13.1135 7.58902e-06 13.3105V17.5002C7.58902e-06 17.898 0.158043 18.2796 0.439347 18.5609C0.720652 18.8422 1.10218 19.0002 1.50001 19.0002H5.6897C5.88675 19.0009 6.08197 18.9623 6.26399 18.8868C6.44602 18.8113 6.61122 18.7004 6.75001 18.5605L18.3103 7.00022C18.4496 6.86093 18.5602 6.69556 18.6356 6.51355C18.711 6.33153 18.7498 6.13645 18.7498 5.93944C18.7498 5.74243 18.711 5.54735 18.6356 5.36534C18.5602 5.18333 18.4496 5.01795 18.3103 4.87866ZM15 8.18897L10.8103 4.00022L13.0603 1.75022L17.25 5.93897L15 8.18897Z"
|
||||
fill="#222222"
|
||||
/>
|
||||
</svg>
|
||||
<span>Edit</span>
|
||||
<Icons.paranthesesRight className="fill-black ml-2" />
|
||||
</Button>
|
||||
) : (
|
||||
<Link
|
||||
href={`/agents/${id}/edit`}
|
||||
className={cn(
|
||||
"hover:underline flex items-center justify-start px-0 py-0 p-0 mt-auto mb-4 w-min"
|
||||
)}
|
||||
>
|
||||
<Icons.paranthesesLeft className="fill-black mr-2" />
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 19 19"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mr-2"
|
||||
>
|
||||
<path
|
||||
d="M18.3103 4.87866L14.1216 0.688973C13.9823 0.549649 13.8169 0.439129 13.6349 0.363725C13.4529 0.288322 13.2578 0.249512 13.0608 0.249512C12.8638 0.249512 12.6687 0.288322 12.4867 0.363725C12.3047 0.439129 12.1393 0.549649 12 0.688973L0.439695 12.2502C0.299801 12.389 0.188889 12.5542 0.113407 12.7362C0.0379245 12.9183 -0.000621974 13.1135 7.58902e-06 13.3105V17.5002C7.58902e-06 17.898 0.158043 18.2796 0.439347 18.5609C0.720652 18.8422 1.10218 19.0002 1.50001 19.0002H5.6897C5.88675 19.0009 6.08197 18.9623 6.26399 18.8868C6.44602 18.8113 6.61122 18.7004 6.75001 18.5605L18.3103 7.00022C18.4496 6.86093 18.5602 6.69556 18.6356 6.51355C18.711 6.33153 18.7498 6.13645 18.7498 5.93944C18.7498 5.74243 18.711 5.54735 18.6356 5.36534C18.5602 5.18333 18.4496 5.01795 18.3103 4.87866ZM15 8.18897L10.8103 4.00022L13.0603 1.75022L17.25 5.93897L15 8.18897Z"
|
||||
fill="#222222"
|
||||
/>
|
||||
</svg>
|
||||
<span>Edit</span>
|
||||
<Icons.paranthesesRight className="fill-black ml-2" />
|
||||
</Link>
|
||||
)}
|
||||
<div className="grid sm:grid-cols-2 gap-2">
|
||||
<Link
|
||||
href={`/agents/${id}`}
|
||||
target="blank"
|
||||
@ -96,7 +141,7 @@ export default function AgentCard(props: AgentCardProps) {
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<span>Try it</span>
|
||||
<span>__ Try it</span>
|
||||
</Link>
|
||||
<Button
|
||||
variant={"outline"}
|
||||
@ -120,47 +165,9 @@ export default function AgentCard(props: AgentCardProps) {
|
||||
fill="#222222"
|
||||
/>
|
||||
</svg>
|
||||
<span>Share</span>
|
||||
<span>__ Share</span>
|
||||
</Button>
|
||||
</div>
|
||||
{!props.user || user_id !== props.user.id ? (
|
||||
<Button className="mt-2" variant={"dots"} disabled={true}>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 19 19"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mr-2"
|
||||
>
|
||||
<path
|
||||
d="M18.3103 4.87866L14.1216 0.688973C13.9823 0.549649 13.8169 0.439129 13.6349 0.363725C13.4529 0.288322 13.2578 0.249512 13.0608 0.249512C12.8638 0.249512 12.6687 0.288322 12.4867 0.363725C12.3047 0.439129 12.1393 0.549649 12 0.688973L0.439695 12.2502C0.299801 12.389 0.188889 12.5542 0.113407 12.7362C0.0379245 12.9183 -0.000621974 13.1135 7.58902e-06 13.3105V17.5002C7.58902e-06 17.898 0.158043 18.2796 0.439347 18.5609C0.720652 18.8422 1.10218 19.0002 1.50001 19.0002H5.6897C5.88675 19.0009 6.08197 18.9623 6.26399 18.8868C6.44602 18.8113 6.61122 18.7004 6.75001 18.5605L18.3103 7.00022C18.4496 6.86093 18.5602 6.69556 18.6356 6.51355C18.711 6.33153 18.7498 6.13645 18.7498 5.93944C18.7498 5.74243 18.711 5.54735 18.6356 5.36534C18.5602 5.18333 18.4496 5.01795 18.3103 4.87866ZM15 8.18897L10.8103 4.00022L13.0603 1.75022L17.25 5.93897L15 8.18897Z"
|
||||
fill="#222222"
|
||||
/>
|
||||
</svg>
|
||||
Edit
|
||||
</Button>
|
||||
) : (
|
||||
<Link
|
||||
href={`/agents/${id}/edit`}
|
||||
className={cn("mt-2", buttonVariants({ variant: "dots" }))}
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 19 19"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mr-2"
|
||||
>
|
||||
<path
|
||||
d="M18.3103 4.87866L14.1216 0.688973C13.9823 0.549649 13.8169 0.439129 13.6349 0.363725C13.4529 0.288322 13.2578 0.249512 13.0608 0.249512C12.8638 0.249512 12.6687 0.288322 12.4867 0.363725C12.3047 0.439129 12.1393 0.549649 12 0.688973L0.439695 12.2502C0.299801 12.389 0.188889 12.5542 0.113407 12.7362C0.0379245 12.9183 -0.000621974 13.1135 7.58902e-06 13.3105V17.5002C7.58902e-06 17.898 0.158043 18.2796 0.439347 18.5609C0.720652 18.8422 1.10218 19.0002 1.50001 19.0002H5.6897C5.88675 19.0009 6.08197 18.9623 6.26399 18.8868C6.44602 18.8113 6.61122 18.7004 6.75001 18.5605L18.3103 7.00022C18.4496 6.86093 18.5602 6.69556 18.6356 6.51355C18.711 6.33153 18.7498 6.13645 18.7498 5.93944C18.7498 5.74243 18.711 5.54735 18.6356 5.36534C18.5602 5.18333 18.4496 5.01795 18.3103 4.87866ZM15 8.18897L10.8103 4.00022L13.0603 1.75022L17.25 5.93897L15 8.18897Z"
|
||||
fill="#222222"
|
||||
/>
|
||||
</svg>
|
||||
Edit
|
||||
</Link>
|
||||
)}
|
||||
</motion.li>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import React, { Fragment } from "react";
|
||||
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
|
||||
@ -7,30 +9,36 @@ import { parseAsInteger, useQueryState } from "nuqs";
|
||||
|
||||
import { PrivyInterface, usePrivy } from "@privy-io/react-auth";
|
||||
|
||||
import { BadgePlus, ChevronLeft, ChevronRight, Search } from "lucide-react";
|
||||
import { ChevronLeft, ChevronRight, Search } from "lucide-react";
|
||||
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import Spline from "@splinetool/react-spline";
|
||||
|
||||
import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
|
||||
|
||||
import PostgrestError, { ANIMATION_EASE } from "@/lib/config";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn, getRange } from "@/lib/utils";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Section } from "@/components/section";
|
||||
import { Button, buttonVariants } from "@/components/ui/button";
|
||||
import {
|
||||
Pagination,
|
||||
PaginationContent,
|
||||
PaginationItem,
|
||||
} from "@/components/ui/pagination";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Particles } from "@/components/particles";
|
||||
import { Icons } from "@/components/icons";
|
||||
|
||||
import { createClient } from "@/utils/supabase/client";
|
||||
|
||||
import AgentCard from "./agent-card";
|
||||
import AgentCardSkeleton from "./agent-card-skeleton";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
import { Autoplay, EffectCoverflow, Navigation } from "swiper/modules";
|
||||
import "swiper/css";
|
||||
import "swiper/css/effect-coverflow";
|
||||
import "swiper/css/pagination";
|
||||
import "swiper/css/navigation";
|
||||
import "swiper/css/navigation";
|
||||
|
||||
const DATA_DISPLAY = 9;
|
||||
|
||||
@ -67,8 +75,8 @@ function AgentListFilter({ privyAuth }: { privyAuth: PrivyInterface }) {
|
||||
aria-label="search"
|
||||
id="search"
|
||||
type="search"
|
||||
placeholder="Search..."
|
||||
className="min-w-64 pl-7"
|
||||
placeholder=">>>_Awaiting input..."
|
||||
className="min-w-64 pl-7 border-primary rounded-none"
|
||||
value={searchFilter}
|
||||
onChange={(e) => {
|
||||
setPaginationFilter(0);
|
||||
@ -77,7 +85,7 @@ function AgentListFilter({ privyAuth }: { privyAuth: PrivyInterface }) {
|
||||
: setSearchFilter(e.target.value);
|
||||
}}
|
||||
/>
|
||||
<Search className="absolute w-4 h-4 left-2 top-1/2 -translate-y-1/2 text-gray-300" />
|
||||
<Search className="absolute w-4 h-4 left-2 top-1/2 -translate-y-1/2 text-gray-400" />
|
||||
</div>
|
||||
{!ready ? (
|
||||
<Skeleton className="h-10 w-32" />
|
||||
@ -97,6 +105,7 @@ function AgentListFilter({ privyAuth }: { privyAuth: PrivyInterface }) {
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mr-2"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
@ -105,7 +114,9 @@ function AgentListFilter({ privyAuth }: { privyAuth: PrivyInterface }) {
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
Create new Agent
|
||||
<Icons.paranthesesLeft />
|
||||
<span className="">Create new Agent</span>
|
||||
<Icons.paranthesesRight />
|
||||
</Link>
|
||||
) : (
|
||||
<Button
|
||||
@ -118,6 +129,7 @@ function AgentListFilter({ privyAuth }: { privyAuth: PrivyInterface }) {
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mr-2"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
@ -126,7 +138,9 @@ function AgentListFilter({ privyAuth }: { privyAuth: PrivyInterface }) {
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
Connect your wallet first
|
||||
<Icons.paranthesesLeft />
|
||||
<span className="">Create new Agent</span>
|
||||
<Icons.paranthesesRight />
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
@ -145,24 +159,18 @@ function AgentListCards({ privyAuth }: { privyAuth: PrivyInterface }) {
|
||||
history: "push",
|
||||
});
|
||||
|
||||
const [paginationFilter, setPaginationFilter] = useQueryState(
|
||||
"page",
|
||||
parseAsInteger
|
||||
.withOptions({
|
||||
shallow: false,
|
||||
history: "push",
|
||||
scroll: false,
|
||||
})
|
||||
.withDefault(0)
|
||||
);
|
||||
|
||||
const {
|
||||
data: agentsData,
|
||||
isLoading,
|
||||
error,
|
||||
} = useQuery({
|
||||
queryKey: ["agents", searchFilter, paginationFilter],
|
||||
queryFn: async ({ signal }) => {
|
||||
isFetchingNextPage,
|
||||
hasNextPage,
|
||||
fetchNextPage,
|
||||
} = useInfiniteQuery({
|
||||
queryKey: ["agents", searchFilter],
|
||||
queryFn: async ({ signal, pageParam }) => {
|
||||
const range = getRange(pageParam, DATA_DISPLAY);
|
||||
|
||||
const supabase = createClient();
|
||||
|
||||
const response = await supabase
|
||||
@ -170,21 +178,30 @@ function AgentListCards({ privyAuth }: { privyAuth: PrivyInterface }) {
|
||||
.select("*", { count: "exact" })
|
||||
.ilike("name", `%${searchFilter}%`)
|
||||
.order("id", { ascending: false })
|
||||
.range(
|
||||
paginationFilter * DATA_DISPLAY,
|
||||
paginationFilter * DATA_DISPLAY + DATA_DISPLAY - 1
|
||||
);
|
||||
.range(range[0], range[1]);
|
||||
|
||||
console.log(response);
|
||||
if (response.error) throw new PostgrestError(response.error);
|
||||
|
||||
return response;
|
||||
},
|
||||
initialPageParam: 0,
|
||||
getNextPageParam: (lastPage, allPages) => {
|
||||
// console.log({ lastPage, allPages });
|
||||
|
||||
if (!lastPage.count) return undefined;
|
||||
|
||||
const nextPage: number | undefined =
|
||||
allPages.length * DATA_DISPLAY < lastPage.count
|
||||
? allPages?.length
|
||||
: undefined;
|
||||
|
||||
return nextPage;
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{agentsData && agentsData.data.length === 0 && (
|
||||
{agentsData && agentsData.pages.length === 0 && (
|
||||
<div className="flex flex-col justify-center items-center ">
|
||||
<figure className="relative w-full sm:w-1/2 h-72 sm:h-96 mb-6">
|
||||
<Image
|
||||
@ -204,74 +221,152 @@ function AgentListCards({ privyAuth }: { privyAuth: PrivyInterface }) {
|
||||
transition={{ duration: 0.8, ease: ANIMATION_EASE }}
|
||||
className="px-3 sm:px-6 mb-10 grid grid-cols-1 lg:grid-cols-3 gap-6"
|
||||
>
|
||||
{[...Array(9)].map((_, idx) => (
|
||||
{[...Array(3)].map((_, idx) => (
|
||||
<li key={idx}>
|
||||
<AgentCardSkeleton />
|
||||
</li>
|
||||
))}
|
||||
</motion.ul>
|
||||
) : (
|
||||
<ul className="px-3 sm:px-6 mb-10 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{agentsData &&
|
||||
agentsData.data?.map((agent, idx) => (
|
||||
<AgentCard key={agent.name} data={agent} idx={idx} user={user} />
|
||||
))}
|
||||
</ul>
|
||||
<>
|
||||
{agentsData && (
|
||||
<div className="relative mb-8">
|
||||
<Swiper
|
||||
spaceBetween={50}
|
||||
effect={"coverflow"}
|
||||
centeredSlides={true}
|
||||
allowTouchMove={false}
|
||||
slidesPerView={1}
|
||||
coverflowEffect={{
|
||||
rotate: 0,
|
||||
stretch: 0,
|
||||
depth: 100,
|
||||
modifier: 2.5,
|
||||
}}
|
||||
pagination={true}
|
||||
navigation={{
|
||||
prevEl: "#prev-button",
|
||||
nextEl: "#next-button",
|
||||
}}
|
||||
breakpoints={{
|
||||
720: {
|
||||
slidesPerView: 2,
|
||||
},
|
||||
1024: {
|
||||
slidesPerView: 3,
|
||||
},
|
||||
}}
|
||||
onReachEnd={(swiper) => {
|
||||
if (hasNextPage) fetchNextPage();
|
||||
}}
|
||||
modules={[EffectCoverflow, Autoplay, Navigation]}
|
||||
>
|
||||
{agentsData.pages.map((page, idx) => (
|
||||
<Fragment key={idx}>
|
||||
{page.data.map((agent, idx2) => (
|
||||
<SwiperSlide key={agent.id}>
|
||||
{({ isActive }) => (
|
||||
<AgentCard
|
||||
key={agent.name}
|
||||
data={agent}
|
||||
user={user}
|
||||
isActive={isActive}
|
||||
/>
|
||||
)}
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Fragment>
|
||||
))}
|
||||
{isFetchingNextPage && (
|
||||
<SwiperSlide>
|
||||
<AgentCardSkeleton />
|
||||
</SwiperSlide>
|
||||
)}
|
||||
</Swiper>
|
||||
<ul
|
||||
role="group"
|
||||
className="absolute top-1/2 z-10 w-full flex justify-between -translate-y-full"
|
||||
>
|
||||
<SwiperButton variant="prev" />
|
||||
<SwiperButton variant="next" />
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{agentsData ? (
|
||||
<Pagination className="mb-8">
|
||||
<PaginationContent className="bg-primary rounded-md p-2">
|
||||
<PaginationItem>
|
||||
<Button
|
||||
variant={"outline"}
|
||||
size={"icon"}
|
||||
disabled={paginationFilter === 0}
|
||||
onClick={() => setPaginationFilter((old) => old - 1)}
|
||||
className="h-8 w-8"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
</Button>
|
||||
</PaginationItem>
|
||||
<p className="text-sm font-semibold text-white mx-2">
|
||||
Page {paginationFilter + 1} of{" "}
|
||||
{agentsData.count
|
||||
? Math.ceil(agentsData.count / DATA_DISPLAY)
|
||||
: 1}
|
||||
</p>
|
||||
<PaginationItem>
|
||||
<Button
|
||||
variant={"outline"}
|
||||
size={"icon"}
|
||||
disabled={
|
||||
agentsData.count === 0
|
||||
? true
|
||||
: paginationFilter + 1 ===
|
||||
Math.ceil(agentsData.count! / DATA_DISPLAY)
|
||||
}
|
||||
onClick={() => setPaginationFilter((old) => old + 1)}
|
||||
className="h-8 w-8"
|
||||
>
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
</Button>
|
||||
</PaginationItem>
|
||||
</PaginationContent>
|
||||
</Pagination>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function AgentList() {
|
||||
const [showCirlce, setShowCircle] = React.useState(true);
|
||||
|
||||
const privyAuth = usePrivy();
|
||||
|
||||
const swiperCss = `
|
||||
.swiper{
|
||||
width: 90%;
|
||||
}
|
||||
.swiper-3d .swiper-slide-shadow-left {
|
||||
background-image: none;
|
||||
}
|
||||
.swiper-3d .swiper-slide-shadow-right{
|
||||
background: none;
|
||||
}
|
||||
`;
|
||||
|
||||
return (
|
||||
<section id="agent-list" className="relative z-20">
|
||||
<div className="layout border-x">
|
||||
<div className="relative w-full overflow-hidden pt-4">
|
||||
<AgentListFilter privyAuth={privyAuth} />
|
||||
<>
|
||||
<style>{swiperCss}</style>
|
||||
<section id="agent-list" className="relative z-20">
|
||||
<div className="layout">
|
||||
{showCirlce ? (
|
||||
<motion.div className="flex flex-col items-center">
|
||||
<div className=" h-[460px] w-[580px] mb-8">
|
||||
<Spline scene="https://prod.spline.design/KfOmDzJBqmDFKlzQ/scene.splinecode" />
|
||||
</div>
|
||||
<Button size={"lg"} onClick={() => setShowCircle(false)}>
|
||||
Agent List
|
||||
</Button>
|
||||
</motion.div>
|
||||
) : (
|
||||
<>
|
||||
<div className="relative w-full overflow-hidden pt-4">
|
||||
<AgentListFilter privyAuth={privyAuth} />
|
||||
</div>
|
||||
<AgentListCards privyAuth={privyAuth} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<AgentListCards privyAuth={privyAuth} />
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
{!showCirlce && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{
|
||||
ease: ANIMATION_EASE,
|
||||
}}
|
||||
>
|
||||
<Particles
|
||||
className="absolute inset-0 z-0 opacity-30"
|
||||
quantity={5000}
|
||||
ease={90}
|
||||
color={"#000000"}
|
||||
refresh
|
||||
/>
|
||||
</motion.div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function SwiperButton({ variant }: { variant: "prev" } | { variant: "next" }) {
|
||||
return (
|
||||
<Button
|
||||
id={variant === "prev" ? "prev-button" : "next-button"}
|
||||
className={cn("px-0 py-8")}
|
||||
>
|
||||
{variant === "prev" ? <ChevronLeft /> : <ChevronRight />}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
@ -7,14 +7,15 @@ import { ANIMATION_EASE } from "@/lib/config";
|
||||
import { AuroraText } from "@/components/aurora-text";
|
||||
import { Section } from "@/components/section";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Icons } from "@/components/icons";
|
||||
|
||||
export function Heading() {
|
||||
return (
|
||||
<section id="heading">
|
||||
<div className="layout py-6 relative w-full border-x overflow-hidden">
|
||||
<div className="layout pt-24 pb-6 relative w-full overflow-hidden">
|
||||
<motion.h1
|
||||
className={cn(
|
||||
"text-center text-4xl font-semibold leading-tighter text-foreground sm:text-5xl md:text-6xl tracking-tighter"
|
||||
"flex justify-center items-center text-center text-4xl font-semibold leading-tighter text-foreground sm:text-5xl md:text-6xl tracking-tighter"
|
||||
)}
|
||||
initial={{ filter: "blur(10px)", opacity: 0, y: 50 }}
|
||||
animate={{ filter: "blur(0px)", opacity: 1, y: 0 }}
|
||||
@ -23,7 +24,9 @@ export function Heading() {
|
||||
ease: ANIMATION_EASE,
|
||||
}}
|
||||
>
|
||||
<AuroraText className="leading-normal">Explore Agents</AuroraText>
|
||||
<Icons.paranthesesLeftBig />
|
||||
<span className="mx-2">Explore Agents</span>
|
||||
<Icons.paranthesesRightBig />
|
||||
</motion.h1>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -41,6 +41,8 @@ import { Separator } from "@/components/ui/separator";
|
||||
import AgentForm from "./agent-form";
|
||||
|
||||
import Spinner from "@/components/spinner";
|
||||
import { WavyBackground } from "@/components/ui/wavy-background";
|
||||
import { Particles } from "@/components/particles";
|
||||
|
||||
const data = [
|
||||
{
|
||||
@ -172,96 +174,120 @@ export function FormStepper() {
|
||||
};
|
||||
|
||||
return (
|
||||
<section>
|
||||
<div className="layout border-x px-3 sm:px-6 py-8">
|
||||
<motion.div
|
||||
initial={{ filter: "blur(10px)", opacity: 0, y: 50 }}
|
||||
animate={{ filter: "blur(0px)", opacity: 1, y: 0 }}
|
||||
transition={{
|
||||
duration: 1,
|
||||
delay: 0.5,
|
||||
ease: ANIMATION_EASE,
|
||||
}}
|
||||
>
|
||||
{/* form title */}
|
||||
<div className="flex justify-between mb-8">
|
||||
<div>
|
||||
<h2 className="text-primary text-lg font-bold mb-1">
|
||||
Agent Form
|
||||
</h2>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{stepper.current.description}
|
||||
</p>
|
||||
<>
|
||||
<section>
|
||||
<div className={cn("relative py-8", currentIndex !== 3 && "z-20 ")}>
|
||||
<motion.div
|
||||
initial={{ filter: "blur(10px)", opacity: 0, y: 50 }}
|
||||
animate={{ filter: "blur(0px)", opacity: 1, y: 0 }}
|
||||
transition={{
|
||||
duration: 1,
|
||||
delay: 0.5,
|
||||
ease: ANIMATION_EASE,
|
||||
}}
|
||||
>
|
||||
{currentIndex !== 3 && (
|
||||
<>
|
||||
{/* form title */}
|
||||
<div className="layout px-3 sm:px-6 flex justify-between mb-8">
|
||||
<div>
|
||||
<h2 className="text-primary text-lg font-bold mb-1">
|
||||
Agent Form
|
||||
</h2>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{stepper.current.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{/* form nav */}
|
||||
<nav
|
||||
aria-label="Checkout Steps"
|
||||
className="layout px-3 sm:px-6 group mb-8"
|
||||
>
|
||||
<ol
|
||||
className="flex items-center justify-between gap-2"
|
||||
aria-orientation="horizontal"
|
||||
>
|
||||
{stepper.all.map((step, index, array) => (
|
||||
<React.Fragment key={step.id}>
|
||||
<li className="flex items-center gap-4 flex-shrink-0">
|
||||
<Button
|
||||
type="button"
|
||||
role="tab"
|
||||
variant={
|
||||
index <= currentIndex ? "default" : "outline"
|
||||
}
|
||||
aria-current={
|
||||
stepper.current.id === step.id
|
||||
? "step"
|
||||
: undefined
|
||||
}
|
||||
aria-posinset={index + 1}
|
||||
aria-setsize={steps.length}
|
||||
aria-selected={stepper.current.id === step.id}
|
||||
className={cn(
|
||||
"flex size-8 items-center justify-center rounded-full",
|
||||
index > currentIndex && "border border-dashed"
|
||||
)}
|
||||
>
|
||||
{index + 1}
|
||||
</Button>
|
||||
<span className="text-sm font-bold">
|
||||
{step.title}
|
||||
</span>
|
||||
</li>
|
||||
{index < array.length - 1 && (
|
||||
<Separator
|
||||
className={`border-t border-dashed flex-1 ${
|
||||
index < currentIndex ? "bg-primary" : "bg-muted"
|
||||
}`}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</ol>
|
||||
</nav>
|
||||
</>
|
||||
)}
|
||||
{/* form content */}
|
||||
<div className="space-y-8">
|
||||
{stepper.switch({
|
||||
agentType: () => <AgentTypeComponent stepper={stepper} />,
|
||||
agentForm: () => (
|
||||
<AgentFormComponent
|
||||
stepper={stepper}
|
||||
form={form}
|
||||
isPending={createAgentMutation.isPending}
|
||||
// onSubmit={handleSubmit}
|
||||
onSubmit={() => stepper.next()}
|
||||
/>
|
||||
),
|
||||
confirmation: () => (
|
||||
<AgentConfirmationComponent
|
||||
stepper={stepper}
|
||||
form={form}
|
||||
isPending={createAgentMutation.isPending}
|
||||
onSubmit={handleSubmit}
|
||||
/>
|
||||
),
|
||||
complete: () => (
|
||||
<CompleteComponent agentId={agentId} agentName={agentName} />
|
||||
),
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{/* form nav */}
|
||||
<nav aria-label="Checkout Steps" className="group mb-8">
|
||||
<ol
|
||||
className="flex items-center justify-between gap-2"
|
||||
aria-orientation="horizontal"
|
||||
>
|
||||
{stepper.all.map((step, index, array) => (
|
||||
<React.Fragment key={step.id}>
|
||||
<li className="flex items-center gap-4 flex-shrink-0">
|
||||
<Button
|
||||
type="button"
|
||||
role="tab"
|
||||
variant={index <= currentIndex ? "default" : "outline"}
|
||||
aria-current={
|
||||
stepper.current.id === step.id ? "step" : undefined
|
||||
}
|
||||
aria-posinset={index + 1}
|
||||
aria-setsize={steps.length}
|
||||
aria-selected={stepper.current.id === step.id}
|
||||
className={cn(
|
||||
"flex size-8 items-center justify-center rounded-full",
|
||||
index > currentIndex && "border border-dashed"
|
||||
)}
|
||||
>
|
||||
{index + 1}
|
||||
</Button>
|
||||
<span className="text-sm font-bold">{step.title}</span>
|
||||
</li>
|
||||
{index < array.length - 1 && (
|
||||
<Separator
|
||||
className={`border-t border-dashed flex-1 ${
|
||||
index < currentIndex ? "bg-primary" : "bg-muted"
|
||||
}`}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</ol>
|
||||
</nav>
|
||||
{/* form content */}
|
||||
<div className="space-y-8">
|
||||
{stepper.switch({
|
||||
agentType: () => <AgentTypeComponent stepper={stepper} />,
|
||||
agentForm: () => (
|
||||
<AgentFormComponent
|
||||
stepper={stepper}
|
||||
form={form}
|
||||
isPending={createAgentMutation.isPending}
|
||||
// onSubmit={handleSubmit}
|
||||
onSubmit={() => stepper.next()}
|
||||
/>
|
||||
),
|
||||
confirmation: () => (
|
||||
<AgentConfirmationComponent
|
||||
stepper={stepper}
|
||||
form={form}
|
||||
isPending={createAgentMutation.isPending}
|
||||
onSubmit={handleSubmit}
|
||||
/>
|
||||
),
|
||||
complete: () => (
|
||||
<CompleteComponent agentId={agentId} agentName={agentName} />
|
||||
),
|
||||
})}
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
{currentIndex !== 3 && (
|
||||
<Particles
|
||||
className="absolute inset-0 z-0 opacity-30"
|
||||
quantity={5000}
|
||||
ease={90}
|
||||
color={"#000000"}
|
||||
refresh
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -280,14 +306,14 @@ const AgentTypeComponent = ({
|
||||
{
|
||||
icon: (
|
||||
<svg
|
||||
width="65"
|
||||
height="56"
|
||||
viewBox="0 0 65 56"
|
||||
width="66"
|
||||
height="66"
|
||||
viewBox="0 0 66 66"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M60 0.5H5C3.67392 0.5 2.40215 1.02678 1.46447 1.96447C0.526784 2.90215 0 4.17392 0 5.5V50.5C0 51.8261 0.526784 53.0979 1.46447 54.0355C2.40215 54.9732 3.67392 55.5 5 55.5H60C61.3261 55.5 62.5979 54.9732 63.5355 54.0355C64.4732 53.0979 65 51.8261 65 50.5V5.5C65 4.17392 64.4732 2.90215 63.5355 1.96447C62.5979 1.02678 61.3261 0.5 60 0.5ZM24.2688 38.7312C24.501 38.9635 24.6853 39.2393 24.811 39.5428C24.9367 39.8462 25.0014 40.1715 25.0014 40.5C25.0014 40.8285 24.9367 41.1538 24.811 41.4572C24.6853 41.7607 24.501 42.0365 24.2688 42.2688C24.0365 42.501 23.7607 42.6853 23.4572 42.811C23.1538 42.9367 22.8285 43.0014 22.5 43.0014C22.1715 43.0014 21.8462 42.9367 21.5428 42.811C21.2393 42.6853 20.9635 42.501 20.7312 42.2688L8.23125 29.7688C7.99881 29.5366 7.81441 29.2608 7.6886 28.9574C7.56279 28.6539 7.49803 28.3285 7.49803 28C7.49803 27.6715 7.56279 27.3461 7.6886 27.0426C7.81441 26.7392 7.99881 26.4634 8.23125 26.2312L20.7312 13.7312C21.2003 13.2621 21.8366 12.9986 22.5 12.9986C23.1634 12.9986 23.7997 13.2621 24.2688 13.7312C24.7379 14.2004 25.0014 14.8366 25.0014 15.5C25.0014 16.1634 24.7379 16.7997 24.2688 17.2688L13.5344 28L24.2688 38.7312ZM56.7688 29.7688L44.2688 42.2688C43.7996 42.7379 43.1634 43.0014 42.5 43.0014C41.8366 43.0014 41.2004 42.7379 40.7312 42.2688C40.2621 41.7996 39.9986 41.1634 39.9986 40.5C39.9986 39.8366 40.2621 39.2004 40.7312 38.7312L51.4656 28L40.7312 17.2688C40.2621 16.7997 39.9986 16.1634 39.9986 15.5C39.9986 14.8366 40.2621 14.2004 40.7312 13.7312C41.2004 13.2621 41.8366 12.9986 42.5 12.9986C43.1634 12.9986 43.7996 13.2621 44.2688 13.7312L56.7688 26.2312C57.0012 26.4634 57.1856 26.7392 57.3114 27.0426C57.4372 27.3461 57.502 27.6715 57.502 28C57.502 28.3285 57.4372 28.6539 57.3114 28.9574C57.1856 29.2608 57.0012 29.5366 56.7688 29.7688Z"
|
||||
d="M33 0.500001C27.389 0.498776 21.8732 1.95028 16.9895 4.71322C12.1059 7.47616 8.02077 11.4564 5.13179 16.2666C2.2428 21.0767 0.648378 26.5529 0.503711 32.1621C0.359043 37.7712 1.66906 43.3223 4.30625 48.275L0.759374 58.9156C0.465576 59.7966 0.422938 60.742 0.636242 61.6459C0.849545 62.5497 1.31036 63.3763 1.96703 64.033C2.62371 64.6896 3.45029 65.1505 4.35415 65.3638C5.258 65.5771 6.20339 65.5344 7.08437 65.2406L17.725 61.6938C22.0837 64.012 26.9132 65.3069 31.847 65.48C36.7808 65.6531 41.6892 64.7 46.1996 62.6929C50.71 60.6858 54.7039 57.6776 57.8782 53.8965C61.0524 50.1154 63.3235 45.6609 64.5191 40.871C65.7148 36.0812 65.8035 31.0819 64.7785 26.2526C63.7536 21.4233 61.6419 16.8911 58.6038 12.9997C55.5658 9.10843 51.6811 5.96038 47.2447 3.79455C42.8083 1.62871 37.9368 0.502026 33 0.500001ZM19.25 36.75C18.5083 36.75 17.7833 36.5301 17.1666 36.118C16.5499 35.706 16.0693 35.1203 15.7855 34.4351C15.5016 33.7498 15.4274 32.9958 15.5721 32.2684C15.7168 31.541 16.0739 30.8728 16.5983 30.3483C17.1228 29.8239 17.791 29.4667 18.5184 29.3221C19.2458 29.1774 19.9998 29.2516 20.6851 29.5355C21.3703 29.8193 21.956 30.2999 22.368 30.9166C22.7801 31.5333 23 32.2583 23 33C23 33.9946 22.6049 34.9484 21.9017 35.6516C21.1984 36.3549 20.2446 36.75 19.25 36.75ZM33 36.75C32.2583 36.75 31.5333 36.5301 30.9166 36.118C30.2999 35.706 29.8193 35.1203 29.5355 34.4351C29.2516 33.7498 29.1774 32.9958 29.3221 32.2684C29.4667 31.541 29.8239 30.8728 30.3483 30.3483C30.8728 29.8239 31.541 29.4667 32.2684 29.3221C32.9958 29.1774 33.7498 29.2516 34.4351 29.5355C35.1203 29.8193 35.706 30.2999 36.118 30.9166C36.5301 31.5333 36.75 32.2583 36.75 33C36.75 33.9946 36.3549 34.9484 35.6516 35.6516C34.9484 36.3549 33.9946 36.75 33 36.75ZM46.75 36.75C46.0083 36.75 45.2833 36.5301 44.6666 36.118C44.0499 35.706 43.5693 35.1203 43.2855 34.4351C43.0016 33.7498 42.9274 32.9958 43.0721 32.2684C43.2168 31.541 43.5739 30.8728 44.0984 30.3483C44.6228 29.8239 45.291 29.4667 46.0184 29.3221C46.7458 29.1774 47.4998 29.2516 48.1851 29.5355C48.8703 29.8193 49.456 30.2999 49.868 30.9166C50.2801 31.5333 50.5 32.2583 50.5 33C50.5 33.9946 50.1049 34.9484 49.4017 35.6516C48.6984 36.3549 47.7446 36.75 46.75 36.75Z"
|
||||
fill="#222222"
|
||||
/>
|
||||
</svg>
|
||||
@ -335,7 +361,7 @@ const AgentTypeComponent = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
|
||||
<div className="layout px-3 sm:px-6 grid grid-cols-1 lg:grid-cols-3 gap-4">
|
||||
{agentTypes.map((agentType, idx) => (
|
||||
<Button
|
||||
disabled={idx !== 0}
|
||||
@ -343,8 +369,8 @@ const AgentTypeComponent = ({
|
||||
variant={"outline"}
|
||||
className={cn(
|
||||
idx === 0 &&
|
||||
"bg-background rounded-xl transition-all duration-300 border shadow-[0_0_23.1px_0_rgba(0,0,0,0.08)_inset]",
|
||||
"py-14 px-6 border-2"
|
||||
"bg-white rounded-xl transition-all duration-300 border shadow-[0_0_23.1px_0_rgba(0,0,0,0.08)_inset]",
|
||||
"py-14 px-6 border border-primary"
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
@ -358,7 +384,7 @@ const AgentTypeComponent = ({
|
||||
))}
|
||||
</div>
|
||||
{/* form footer */}
|
||||
<div>
|
||||
<div className="layout px-3 sm:px-6">
|
||||
<div className="flex justify-end gap-4">
|
||||
<Button variant="outline" disabled={true}>
|
||||
Back
|
||||
@ -388,12 +414,14 @@ const AgentFormComponent = ({
|
||||
isPending: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<AgentForm
|
||||
stepper={stepper}
|
||||
form={form}
|
||||
onSubmit={onSubmit}
|
||||
isPending={isPending}
|
||||
/>
|
||||
<div className="layout px-3 sm:px-6">
|
||||
<AgentForm
|
||||
stepper={stepper}
|
||||
form={form}
|
||||
onSubmit={onSubmit}
|
||||
isPending={isPending}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -415,8 +443,8 @@ const AgentConfirmationComponent = ({
|
||||
isPending: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<Terminal className="max-w-none max-h-none">
|
||||
<div className="layout px-3 sm:px-6">
|
||||
<Terminal className="max-w-none max-h-none mb-4">
|
||||
<TypingAnimation duration={30}>
|
||||
> This action will create your agent with following details:
|
||||
</TypingAnimation>
|
||||
@ -451,7 +479,7 @@ const AgentConfirmationComponent = ({
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -464,106 +492,119 @@ const CompleteComponent = ({
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col justify-center items-center py-4">
|
||||
<div className="h-20 w-20 flex flex-col justify-center items-center rounded-full bg-primary">
|
||||
<svg
|
||||
width="61"
|
||||
height="41"
|
||||
viewBox="0 0 61 41"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
x="0.5"
|
||||
y="14.6426"
|
||||
width="5.85703"
|
||||
height="4.39277"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="6.35693"
|
||||
y="19.0342"
|
||||
width="7.32129"
|
||||
height="8.78555"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="13.6787"
|
||||
y="27.8223"
|
||||
width="5.85703"
|
||||
height="4.39277"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="19.5354"
|
||||
y="32.2148"
|
||||
width="7.32129"
|
||||
height="8.78555"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="26.8567"
|
||||
y="27.8223"
|
||||
width="5.85703"
|
||||
height="4.39277"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="32.7136"
|
||||
y="19.0342"
|
||||
width="8.78555"
|
||||
height="8.78555"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="41.4993"
|
||||
y="14.6426"
|
||||
width="5.85703"
|
||||
height="4.39277"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="47.3562"
|
||||
y="5.85645"
|
||||
width="8.78555"
|
||||
height="8.78555"
|
||||
fill="white"
|
||||
/>
|
||||
<rect x="56.1418" width="4.39277" height="5.85703" fill="white" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-xl py-4 font-bold">Agent succesfully created!</h3>
|
||||
<p className="text-lg text-muted-foreground mb-3">
|
||||
You can try to have a conversation with your agent.
|
||||
</p>
|
||||
<Link
|
||||
href={`/agents/${agentId}`}
|
||||
target="blank"
|
||||
className={buttonVariants({ variant: "default" })}
|
||||
<div className="relative">
|
||||
<WavyBackground
|
||||
className="mx-auto"
|
||||
containerClassName="h-max py-24"
|
||||
backgroundFill="white"
|
||||
colors={["#000000"]}
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 17 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mr-2"
|
||||
>
|
||||
<path
|
||||
d="M8.50006 0.875C7.0973 0.874694 5.71836 1.23757 4.49745 1.9283C3.27654 2.61904 2.25526 3.6141 1.53301 4.81664C0.810765 6.01918 0.412159 7.38822 0.375993 8.79052C0.339826 10.1928 0.66733 11.5806 1.32663 12.8188L0.439908 15.4789C0.366459 15.6992 0.355799 15.9355 0.409125 16.1615C0.462451 16.3874 0.577655 16.5941 0.741823 16.7582C0.905992 16.9224 1.11264 17.0376 1.3386 17.0909C1.56456 17.1443 1.80091 17.1336 2.02116 17.0602L4.68131 16.1734C5.77098 16.753 6.97836 17.0767 8.21181 17.12C9.44525 17.1633 10.6724 16.925 11.8 16.4232C12.9276 15.9215 13.926 15.1694 14.7196 14.2241C15.5132 13.2789 16.0809 12.1652 16.3799 10.9678C16.6788 9.77029 16.7009 8.52047 16.4447 7.31315C16.1885 6.10584 15.6605 4.97276 14.901 3.99993C14.1415 3.02711 13.1703 2.24009 12.0612 1.69864C10.9521 1.15718 9.73427 0.875506 8.50006 0.875ZM5.06256 9.9375C4.87714 9.9375 4.69589 9.88252 4.54172 9.7795C4.38755 9.67649 4.26739 9.53007 4.19643 9.35876C4.12547 9.18746 4.1069 8.99896 4.14308 8.8171C4.17925 8.63525 4.26854 8.4682 4.39965 8.33709C4.53076 8.20598 4.69781 8.11669 4.87967 8.08051C5.06152 8.04434 5.25002 8.06291 5.42133 8.13386C5.59264 8.20482 5.73905 8.32498 5.84207 8.47915C5.94508 8.63332 6.00006 8.81458 6.00006 9C6.00006 9.24864 5.90129 9.4871 5.72548 9.66291C5.54966 9.83873 5.31121 9.9375 5.06256 9.9375ZM8.50006 9.9375C8.31464 9.9375 8.13339 9.88252 7.97922 9.7795C7.82505 9.67649 7.70489 9.53007 7.63393 9.35876C7.56297 9.18746 7.5444 8.99896 7.58058 8.8171C7.61675 8.63525 7.70604 8.4682 7.83715 8.33709C7.96826 8.20598 8.13531 8.11669 8.31717 8.08051C8.49902 8.04434 8.68752 8.06291 8.85883 8.13386C9.03014 8.20482 9.17655 8.32498 9.27957 8.47915C9.38258 8.63332 9.43756 8.81458 9.43756 9C9.43756 9.24864 9.33879 9.4871 9.16298 9.66291C8.98716 9.83873 8.74871 9.9375 8.50006 9.9375ZM11.9376 9.9375C11.7521 9.9375 11.5709 9.88252 11.4167 9.7795C11.2625 9.67649 11.1424 9.53007 11.0714 9.35876C11.0005 9.18746 10.9819 8.99896 11.0181 8.8171C11.0543 8.63525 11.1435 8.4682 11.2747 8.33709C11.4058 8.20598 11.5728 8.11669 11.7547 8.08051C11.9365 8.04434 12.125 8.06291 12.2963 8.13386C12.4676 8.20482 12.6141 8.32498 12.7171 8.47915C12.8201 8.63332 12.8751 8.81458 12.8751 9C12.8751 9.24864 12.7763 9.4871 12.6005 9.66291C12.4247 9.83873 12.1862 9.9375 11.9376 9.9375Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
Chat with {agentName}
|
||||
</Link>
|
||||
</div>
|
||||
{/* form footer */}
|
||||
<div>
|
||||
<div className="flex justify-end gap-4">
|
||||
<Link href="/" className={buttonVariants({ variant: "default" })}>
|
||||
Back to home
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex flex-col justify-center items-center bg-white px-8 py-4 bg-opacity-40 border">
|
||||
<div className="h-28 w-28 mb-8 flex flex-col justify-center items-center rounded-full bg-primary">
|
||||
<svg
|
||||
width="61"
|
||||
height="41"
|
||||
viewBox="0 0 61 41"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
x="0.5"
|
||||
y="14.6426"
|
||||
width="5.85703"
|
||||
height="4.39277"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="6.35693"
|
||||
y="19.0342"
|
||||
width="7.32129"
|
||||
height="8.78555"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="13.6787"
|
||||
y="27.8223"
|
||||
width="5.85703"
|
||||
height="4.39277"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="19.5354"
|
||||
y="32.2148"
|
||||
width="7.32129"
|
||||
height="8.78555"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="26.8567"
|
||||
y="27.8223"
|
||||
width="5.85703"
|
||||
height="4.39277"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="32.7136"
|
||||
y="19.0342"
|
||||
width="8.78555"
|
||||
height="8.78555"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="41.4993"
|
||||
y="14.6426"
|
||||
width="5.85703"
|
||||
height="4.39277"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="47.3562"
|
||||
y="5.85645"
|
||||
width="8.78555"
|
||||
height="8.78555"
|
||||
fill="white"
|
||||
/>
|
||||
<rect
|
||||
x="56.1418"
|
||||
width="4.39277"
|
||||
height="5.85703"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-2xl py-4 font-bold">
|
||||
Agent succesfully created!
|
||||
</h3>
|
||||
<p className="text-lg text-muted-foreground mb-8">
|
||||
You can try to have a conversation with your agent.
|
||||
</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<Link
|
||||
href={`/agents/${agentId}`}
|
||||
target="blank"
|
||||
className={buttonVariants({ variant: "default" })}
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 17 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mr-2"
|
||||
>
|
||||
<path
|
||||
d="M8.50006 0.875C7.0973 0.874694 5.71836 1.23757 4.49745 1.9283C3.27654 2.61904 2.25526 3.6141 1.53301 4.81664C0.810765 6.01918 0.412159 7.38822 0.375993 8.79052C0.339826 10.1928 0.66733 11.5806 1.32663 12.8188L0.439908 15.4789C0.366459 15.6992 0.355799 15.9355 0.409125 16.1615C0.462451 16.3874 0.577655 16.5941 0.741823 16.7582C0.905992 16.9224 1.11264 17.0376 1.3386 17.0909C1.56456 17.1443 1.80091 17.1336 2.02116 17.0602L4.68131 16.1734C5.77098 16.753 6.97836 17.0767 8.21181 17.12C9.44525 17.1633 10.6724 16.925 11.8 16.4232C12.9276 15.9215 13.926 15.1694 14.7196 14.2241C15.5132 13.2789 16.0809 12.1652 16.3799 10.9678C16.6788 9.77029 16.7009 8.52047 16.4447 7.31315C16.1885 6.10584 15.6605 4.97276 14.901 3.99993C14.1415 3.02711 13.1703 2.24009 12.0612 1.69864C10.9521 1.15718 9.73427 0.875506 8.50006 0.875ZM5.06256 9.9375C4.87714 9.9375 4.69589 9.88252 4.54172 9.7795C4.38755 9.67649 4.26739 9.53007 4.19643 9.35876C4.12547 9.18746 4.1069 8.99896 4.14308 8.8171C4.17925 8.63525 4.26854 8.4682 4.39965 8.33709C4.53076 8.20598 4.69781 8.11669 4.87967 8.08051C5.06152 8.04434 5.25002 8.06291 5.42133 8.13386C5.59264 8.20482 5.73905 8.32498 5.84207 8.47915C5.94508 8.63332 6.00006 8.81458 6.00006 9C6.00006 9.24864 5.90129 9.4871 5.72548 9.66291C5.54966 9.83873 5.31121 9.9375 5.06256 9.9375ZM8.50006 9.9375C8.31464 9.9375 8.13339 9.88252 7.97922 9.7795C7.82505 9.67649 7.70489 9.53007 7.63393 9.35876C7.56297 9.18746 7.5444 8.99896 7.58058 8.8171C7.61675 8.63525 7.70604 8.4682 7.83715 8.33709C7.96826 8.20598 8.13531 8.11669 8.31717 8.08051C8.49902 8.04434 8.68752 8.06291 8.85883 8.13386C9.03014 8.20482 9.17655 8.32498 9.27957 8.47915C9.38258 8.63332 9.43756 8.81458 9.43756 9C9.43756 9.24864 9.33879 9.4871 9.16298 9.66291C8.98716 9.83873 8.74871 9.9375 8.50006 9.9375ZM11.9376 9.9375C11.7521 9.9375 11.5709 9.88252 11.4167 9.7795C11.2625 9.67649 11.1424 9.53007 11.0714 9.35876C11.0005 9.18746 10.9819 8.99896 11.0181 8.8171C11.0543 8.63525 11.1435 8.4682 11.2747 8.33709C11.4058 8.20598 11.5728 8.11669 11.7547 8.08051C11.9365 8.04434 12.125 8.06291 12.2963 8.13386C12.4676 8.20482 12.6141 8.32498 12.7171 8.47915C12.8201 8.63332 12.8751 8.81458 12.8751 9C12.8751 9.24864 12.7763 9.4871 12.6005 9.66291C12.4247 9.83873 12.1862 9.9375 11.9376 9.9375Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
Chat with {agentName}
|
||||
</Link>
|
||||
<Link href="/" className={buttonVariants({ variant: "outline" })}>
|
||||
Back to home
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</WavyBackground>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -7,14 +7,15 @@ import { ANIMATION_EASE } from "@/lib/config";
|
||||
import { AuroraText } from "@/components/aurora-text";
|
||||
import { Section } from "@/components/section";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Icons } from "@/components/icons";
|
||||
|
||||
export function Heading() {
|
||||
return (
|
||||
<section id="heading">
|
||||
<div className="layout py-6 relative w-full border-x overflow-hidden">
|
||||
<div className="layout pt-24 pb-6 relative w-full overflow-hidden">
|
||||
<motion.h1
|
||||
className={cn(
|
||||
"text-center text-4xl font-semibold leading-tighter text-foreground sm:text-5xl md:text-6xl tracking-tighter"
|
||||
"flex justify-center items-center text-center text-4xl font-semibold leading-tighter text-foreground sm:text-5xl md:text-6xl tracking-tighter"
|
||||
)}
|
||||
initial={{ filter: "blur(10px)", opacity: 0, y: 50 }}
|
||||
animate={{ filter: "blur(0px)", opacity: 1, y: 0 }}
|
||||
@ -23,7 +24,9 @@ export function Heading() {
|
||||
ease: ANIMATION_EASE,
|
||||
}}
|
||||
>
|
||||
<AuroraText className="leading-normal">Create you Own Agent</AuroraText>
|
||||
<Icons.paranthesesLeftBig />
|
||||
<span className="mx-2">Create your Own Agent</span>
|
||||
<Icons.paranthesesRightBig />
|
||||
</motion.h1>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -3,15 +3,17 @@ import { CheckSessionProvider } from "@/providers/check-session-provider";
|
||||
import { Footer } from "@/components/footer";
|
||||
import { FormStepper } from "./_components/form-stepper";
|
||||
import { Heading } from "./_components/heading";
|
||||
import { Header } from "@/components/header";
|
||||
|
||||
export default function CreateAgent() {
|
||||
return (
|
||||
<CheckSessionProvider>
|
||||
<Heading />
|
||||
<hr className="" />
|
||||
<FormStepper />
|
||||
<hr className="" />
|
||||
<Footer />
|
||||
<div>
|
||||
<Header />
|
||||
<Heading />
|
||||
<FormStepper />
|
||||
<Footer />
|
||||
</div>
|
||||
</CheckSessionProvider>
|
||||
);
|
||||
}
|
||||
|
@ -1,25 +1,20 @@
|
||||
import { Section } from "@/components/section";
|
||||
|
||||
import { Heading } from "./_components/heading";
|
||||
|
||||
// import { Blog } from "../_components/blog";
|
||||
import { AgentList } from "./_components/agent-list";
|
||||
import { Footer } from "@/components/footer";
|
||||
import { Suspense } from "react";
|
||||
import { Header } from "@/components/header";
|
||||
|
||||
export default function Explore() {
|
||||
return (
|
||||
<>
|
||||
<Heading />
|
||||
<hr className="" />
|
||||
<div className="relative">
|
||||
<Header />
|
||||
<Heading />
|
||||
<Suspense>
|
||||
<AgentList />
|
||||
</Suspense>
|
||||
<hr className="" />
|
||||
<div className="absolute -bottom-64 left-0 w-full bg-[url(/background-2.png)] bg-center pt-72">
|
||||
<Footer />
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -5,22 +5,26 @@ import { Tokenomics } from "./_components/tokenomics";
|
||||
import { Roadmap } from "./_components/roadmap";
|
||||
|
||||
import { Footer } from "@/components/footer";
|
||||
import { Header } from "@/components/header";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<div >
|
||||
<div
|
||||
className="bg-[url(/background-6.png)] bg-cover bg-center bg-opacity-10"
|
||||
>
|
||||
<Header />
|
||||
<Hero />
|
||||
<Features />
|
||||
<hr className="" />
|
||||
</div>
|
||||
<Features />
|
||||
<hr className="border-primary" />
|
||||
<Tokenomics />
|
||||
<hr className="" />
|
||||
<hr className="border-primary" />
|
||||
<Roadmap />
|
||||
<hr className="" />
|
||||
<hr className="border-primary" />
|
||||
<div className="bg-[url(/background-2.png)] bg-bottom">
|
||||
<CTA />
|
||||
<hr className="" />
|
||||
<hr className="border-primary" />
|
||||
<Footer />
|
||||
</div>
|
||||
</>
|
||||
|
@ -36,7 +36,7 @@
|
||||
--color-4: 195 100% 63%;
|
||||
--color-5: 90 100% 63%;
|
||||
|
||||
--header-height: 3.5rem;
|
||||
--header-height: 4rem;
|
||||
}
|
||||
|
||||
/* .dark {
|
||||
@ -134,4 +134,4 @@
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
scroll-padding-top: 5.5rem;
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ export default function RootLayout({
|
||||
defaultTheme="dark"
|
||||
enableSystem={false}
|
||||
>
|
||||
<Header />
|
||||
{/* <Header /> */}
|
||||
{/* <main></main> */}
|
||||
{children}
|
||||
{/* <Footer /> */}
|
||||
|
@ -1,103 +0,0 @@
|
||||
import { Icons } from "@/components/icons";
|
||||
import { siteConfig } from "@/lib/config";
|
||||
import { ImageResponse } from "next/og";
|
||||
import { NextRequest } from "next/server";
|
||||
|
||||
export const runtime = "edge";
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const { searchParams } = req.nextUrl;
|
||||
const postTitle = searchParams.get("title") || siteConfig.description;
|
||||
const font = fetch(
|
||||
new URL("../../assets/fonts/Inter-SemiBold.ttf", import.meta.url)
|
||||
).then((res) => res.arrayBuffer());
|
||||
const fontData = await font;
|
||||
|
||||
return new ImageResponse(
|
||||
(
|
||||
<div
|
||||
style={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
backgroundColor: "#fff",
|
||||
// set background image if needed
|
||||
backgroundImage: `url(${siteConfig.url}/og.png)`,
|
||||
fontSize: 32,
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: "relative",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
top: "125px",
|
||||
}}
|
||||
>
|
||||
<Icons.logo
|
||||
style={{
|
||||
color: "#fff",
|
||||
width: "64px",
|
||||
height: "64px",
|
||||
}}
|
||||
/>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
fontSize: "64px",
|
||||
fontWeight: "600",
|
||||
marginTop: "24px",
|
||||
textAlign: "center",
|
||||
color: "#fff",
|
||||
width: "60%",
|
||||
letterSpacing: "-0.05em", // Added tighter tracking
|
||||
}}
|
||||
>
|
||||
{postTitle}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
fontSize: "16px",
|
||||
fontWeight: "500",
|
||||
marginTop: "16px",
|
||||
color: "#fff",
|
||||
}}
|
||||
>
|
||||
{siteConfig.name}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<img
|
||||
src={`${siteConfig.url}/cube.png`}
|
||||
width={500}
|
||||
style={{
|
||||
position: "relative",
|
||||
bottom: -100,
|
||||
aspectRatio: "auto",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
{
|
||||
width: 1200,
|
||||
height: 630,
|
||||
fonts: [
|
||||
{
|
||||
name: "Inter",
|
||||
data: fontData,
|
||||
style: "normal",
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
}
|
@ -14,7 +14,7 @@ export function Footer() {
|
||||
<footer className="pb-16 pt-8">
|
||||
<div className="layout ">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex items-center gap-x-2 p-2 rounded-md bg-[#D7D7D799] bg-opacity-60 shadow-[0_4px_7px_0_rgba(255,255,255,0.12)_inset] backdrop-blur-xs">
|
||||
<div className="flex items-center gap-x-2 p-2 rounded-md bg-opacity-60 shadow-[0_4px_7px_0_rgba(255,255,255,0.12)_inset] backdrop-blur-xs">
|
||||
<figure className="relative h-[23px] w-[18px] sm:h-[43px] sm:w-[38px]">
|
||||
<Image src={"/logo.png"} alt="logo" fill={true} />
|
||||
</figure>
|
||||
|
@ -62,8 +62,13 @@ export function Header() {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 h-[var(--header-height)] z-50 p-0 pb-16 bg-background/60 backdrop-blur">
|
||||
<div className="flex justify-between items-center layout mx-auto py-2 px-3 sm:px-6 border-x">
|
||||
<header
|
||||
className={cn(
|
||||
"fixed top-0 left-0 right-0 h-[var(--header-height)] z-50 p-0 ",
|
||||
addBorder ? "bg-background/60 backdrop-blur" : "bg-transparent"
|
||||
)}
|
||||
>
|
||||
<div className="h-full flex justify-between items-center layout mx-auto px-3 sm:px-6 border-x border-primary">
|
||||
<Link
|
||||
href="/"
|
||||
title="brand-logo"
|
||||
@ -74,12 +79,12 @@ export function Header() {
|
||||
<span className="font-bold text-xl">{siteConfig.name}</span>
|
||||
</Link>
|
||||
<nav className="hidden lg:block">
|
||||
<ul className="flex gap-4">
|
||||
<ul className="flex gap-5">
|
||||
<li>
|
||||
<Link
|
||||
href={"/#features"}
|
||||
className={cn(
|
||||
"transition-all hover:font-bold hover:border-b hover:pb-1"
|
||||
"transition-all font-medium hover:font-bold hover:border-b hover:pb-1"
|
||||
)}
|
||||
>
|
||||
Features
|
||||
@ -89,7 +94,7 @@ export function Header() {
|
||||
<Link
|
||||
href={"/#tokenomics"}
|
||||
className={cn(
|
||||
"transition-all hover:font-bold hover:border-b hover:pb-1"
|
||||
"transition-all font-medium hover:font-bold hover:border-b hover:pb-1"
|
||||
)}
|
||||
>
|
||||
Tokenomics
|
||||
@ -100,7 +105,7 @@ export function Header() {
|
||||
href={"https://soviro.gitbook.io/soviro"}
|
||||
target="_blank"
|
||||
className={cn(
|
||||
"transition-all hover:font-bold hover:border-b hover:pb-1"
|
||||
"transition-all font-medium hover:font-bold hover:border-b hover:pb-1"
|
||||
)}
|
||||
>
|
||||
Docs
|
||||
@ -190,7 +195,9 @@ export function Header() {
|
||||
onClick={login}
|
||||
className={buttonVariants({ variant: "default" })}
|
||||
>
|
||||
Connect Wallet
|
||||
<Icons.paranthesesLeft />
|
||||
<span className="mx-2 block">Connect Wallet</span>
|
||||
<Icons.paranthesesRight />
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
@ -202,7 +209,7 @@ export function Header() {
|
||||
</div>
|
||||
<hr
|
||||
className={cn(
|
||||
"absolute w-full bottom-0 transition-opacity duration-300 ease-in-out"
|
||||
"absolute w-full bottom-0 transition-opacity duration-300 ease-in-out border-primary"
|
||||
)}
|
||||
/>
|
||||
</header>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { DiscordLogoIcon } from "@radix-ui/react-icons";
|
||||
|
||||
type IconProps = React.HTMLAttributes<SVGElement>;
|
||||
@ -141,4 +142,81 @@ export const Icons = {
|
||||
<path d="M21 12a9 9 0 1 1-6.219-8.56" />
|
||||
</svg>
|
||||
),
|
||||
paranthesesLeft: (props: IconProps) => (
|
||||
<svg
|
||||
width="6"
|
||||
height="24"
|
||||
viewBox="0 0 6 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={cn("fill-white", props.className)}
|
||||
{...props}
|
||||
>
|
||||
<mask id="path-1-inside-1_144_51166">
|
||||
<path d="M0.5 0H5.5V24H0.5V0Z" />
|
||||
</mask>
|
||||
<path
|
||||
d="M0.5 0V-2H-1.5V0H0.5ZM0.5 24H-1.5V26H0.5V24ZM0.5 2H5.5V-2H0.5V2ZM5.5 22H0.5V26H5.5V22ZM2.5 24V0H-1.5V24H2.5Z"
|
||||
mask="url(#path-1-inside-1_144_51166)"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
paranthesesRight: ({ className, ...rest }: IconProps) => (
|
||||
<svg
|
||||
width="6"
|
||||
height="24"
|
||||
viewBox="0 0 6 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={cn("fill-white", className)}
|
||||
{...rest}
|
||||
>
|
||||
<mask id="path-1-inside-1_144_51169">
|
||||
<path d="M5.5 0H0.5V24H5.5V0Z" />
|
||||
</mask>
|
||||
<path
|
||||
d="M5.5 0V-2H7.5V0H5.5ZM5.5 24H7.5V26H5.5V24ZM5.5 2H0.5V-2H5.5V2ZM0.5 22H5.5V26H0.5V22ZM3.5 24V0H7.5V24H3.5Z"
|
||||
mask="url(#path-1-inside-1_144_51169)"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
paranthesesLeftBig: ({ className, ...rest }: IconProps) => (
|
||||
<svg
|
||||
width="19"
|
||||
height="82"
|
||||
viewBox="0 0 19 82"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={cn("fill-white", className)}
|
||||
{...rest}
|
||||
>
|
||||
<mask id="path-1-inside-1_152_6155" fill="white">
|
||||
<path d="M0 0H19V82H0V0Z" />
|
||||
</mask>
|
||||
<path
|
||||
d="M0 0V-2H-2V0H0ZM0 82H-2V84H0V82ZM0 2H19V-2H0V2ZM19 80H0V84H19V80ZM2 82V0H-2V82H2Z"
|
||||
fill="black"
|
||||
mask="url(#path-1-inside-1_152_6155)"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
paranthesesRightBig: (props: IconProps) => (
|
||||
<svg
|
||||
width="19"
|
||||
height="82"
|
||||
viewBox="0 0 19 82"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<mask id="path-1-inside-1_152_6156" fill="white">
|
||||
<path d="M19 0H0V82H19V0Z" />
|
||||
</mask>
|
||||
<path
|
||||
d="M19 0V-2H21V0H19ZM19 82H21V84H19V82ZM19 2H0V-2H19V2ZM0 80H19V84H0V80ZM17 82V0H21V82H17Z"
|
||||
fill="black"
|
||||
mask="url(#path-1-inside-1_152_6156)"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
};
|
||||
|
313
src/components/particles.tsx
Normal file
313
src/components/particles.tsx
Normal file
@ -0,0 +1,313 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import React, {
|
||||
ComponentPropsWithoutRef,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
interface MousePosition {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
function MousePosition(): MousePosition {
|
||||
const [mousePosition, setMousePosition] = useState<MousePosition>({
|
||||
x: 0,
|
||||
y: 0,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const handleMouseMove = (event: MouseEvent) => {
|
||||
setMousePosition({ x: event.clientX, y: event.clientY });
|
||||
};
|
||||
|
||||
window.addEventListener("mousemove", handleMouseMove);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("mousemove", handleMouseMove);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return mousePosition;
|
||||
}
|
||||
|
||||
interface ParticlesProps extends ComponentPropsWithoutRef<"div"> {
|
||||
className?: string;
|
||||
quantity?: number;
|
||||
staticity?: number;
|
||||
ease?: number;
|
||||
size?: number;
|
||||
refresh?: boolean;
|
||||
color?: string;
|
||||
vx?: number;
|
||||
vy?: number;
|
||||
}
|
||||
|
||||
function hexToRgb(hex: string): number[] {
|
||||
hex = hex.replace("#", "");
|
||||
|
||||
if (hex.length === 3) {
|
||||
hex = hex
|
||||
.split("")
|
||||
.map((char) => char + char)
|
||||
.join("");
|
||||
}
|
||||
|
||||
const hexInt = parseInt(hex, 16);
|
||||
const red = (hexInt >> 16) & 255;
|
||||
const green = (hexInt >> 8) & 255;
|
||||
const blue = hexInt & 255;
|
||||
return [red, green, blue];
|
||||
}
|
||||
|
||||
type Circle = {
|
||||
x: number;
|
||||
y: number;
|
||||
translateX: number;
|
||||
translateY: number;
|
||||
size: number;
|
||||
alpha: number;
|
||||
targetAlpha: number;
|
||||
dx: number;
|
||||
dy: number;
|
||||
magnetism: number;
|
||||
};
|
||||
|
||||
export const Particles: React.FC<ParticlesProps> = ({
|
||||
className = "",
|
||||
quantity = 100,
|
||||
staticity = 50,
|
||||
ease = 50,
|
||||
size = 0.4,
|
||||
refresh = false,
|
||||
color = "#ffffff",
|
||||
vx = 0,
|
||||
vy = 0,
|
||||
...props
|
||||
}) => {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const canvasContainerRef = useRef<HTMLDivElement>(null);
|
||||
const context = useRef<CanvasRenderingContext2D | null>(null);
|
||||
const circles = useRef<Circle[]>([]);
|
||||
const mousePosition = MousePosition();
|
||||
const mouse = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
|
||||
const canvasSize = useRef<{ w: number; h: number }>({ w: 0, h: 0 });
|
||||
const dpr = typeof window !== "undefined" ? window.devicePixelRatio : 1;
|
||||
const rafID = useRef<number | null>(null);
|
||||
const resizeTimeout = useRef<NodeJS.Timeout>();
|
||||
|
||||
useEffect(() => {
|
||||
if (canvasRef.current) {
|
||||
context.current = canvasRef.current.getContext("2d");
|
||||
}
|
||||
initCanvas();
|
||||
animate();
|
||||
|
||||
const handleResize = () => {
|
||||
if (resizeTimeout.current) {
|
||||
clearTimeout(resizeTimeout.current);
|
||||
}
|
||||
resizeTimeout.current = setTimeout(() => {
|
||||
initCanvas();
|
||||
}, 200);
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
|
||||
return () => {
|
||||
if (rafID.current != null) {
|
||||
window.cancelAnimationFrame(rafID.current);
|
||||
}
|
||||
if (resizeTimeout.current) {
|
||||
clearTimeout(resizeTimeout.current);
|
||||
}
|
||||
window.removeEventListener("resize", handleResize);
|
||||
};
|
||||
}, [color]);
|
||||
|
||||
useEffect(() => {
|
||||
onMouseMove();
|
||||
}, [mousePosition.x, mousePosition.y]);
|
||||
|
||||
useEffect(() => {
|
||||
initCanvas();
|
||||
}, [refresh]);
|
||||
|
||||
const initCanvas = () => {
|
||||
resizeCanvas();
|
||||
drawParticles();
|
||||
};
|
||||
|
||||
const onMouseMove = () => {
|
||||
if (canvasRef.current) {
|
||||
const rect = canvasRef.current.getBoundingClientRect();
|
||||
const { w, h } = canvasSize.current;
|
||||
const x = mousePosition.x - rect.left - w / 2;
|
||||
const y = mousePosition.y - rect.top - h / 2;
|
||||
const inside = x < w / 2 && x > -w / 2 && y < h / 2 && y > -h / 2;
|
||||
if (inside) {
|
||||
mouse.current.x = x;
|
||||
mouse.current.y = y;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const resizeCanvas = () => {
|
||||
if (canvasContainerRef.current && canvasRef.current && context.current) {
|
||||
canvasSize.current.w = canvasContainerRef.current.offsetWidth;
|
||||
canvasSize.current.h = canvasContainerRef.current.offsetHeight;
|
||||
|
||||
canvasRef.current.width = canvasSize.current.w * dpr;
|
||||
canvasRef.current.height = canvasSize.current.h * dpr;
|
||||
canvasRef.current.style.width = `${canvasSize.current.w}px`;
|
||||
canvasRef.current.style.height = `${canvasSize.current.h}px`;
|
||||
context.current.scale(dpr, dpr);
|
||||
|
||||
// Clear existing particles and create new ones with exact quantity
|
||||
circles.current = [];
|
||||
for (let i = 0; i < quantity; i++) {
|
||||
const circle = circleParams();
|
||||
drawCircle(circle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const circleParams = (): Circle => {
|
||||
const x = Math.floor(Math.random() * canvasSize.current.w);
|
||||
const y = Math.floor(Math.random() * canvasSize.current.h);
|
||||
const translateX = 0;
|
||||
const translateY = 0;
|
||||
const pSize = Math.floor(Math.random() * 2) + size;
|
||||
const alpha = 0;
|
||||
const targetAlpha = parseFloat((Math.random() * 0.6 + 0.1).toFixed(1));
|
||||
const dx = (Math.random() - 0.5) * 0.1;
|
||||
const dy = (Math.random() - 0.5) * 0.1;
|
||||
const magnetism = 0.1 + Math.random() * 4;
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
translateX,
|
||||
translateY,
|
||||
size: pSize,
|
||||
alpha,
|
||||
targetAlpha,
|
||||
dx,
|
||||
dy,
|
||||
magnetism,
|
||||
};
|
||||
};
|
||||
|
||||
const rgb = hexToRgb(color);
|
||||
|
||||
const drawCircle = (circle: Circle, update = false) => {
|
||||
if (context.current) {
|
||||
const { x, y, translateX, translateY, size, alpha } = circle;
|
||||
context.current.translate(translateX, translateY);
|
||||
context.current.beginPath();
|
||||
context.current.arc(x, y, size, 0, 2 * Math.PI);
|
||||
context.current.fillStyle = `rgba(${rgb.join(", ")}, ${alpha})`;
|
||||
context.current.fill();
|
||||
context.current.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||||
|
||||
if (!update) {
|
||||
circles.current.push(circle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const clearContext = () => {
|
||||
if (context.current) {
|
||||
context.current.clearRect(
|
||||
0,
|
||||
0,
|
||||
canvasSize.current.w,
|
||||
canvasSize.current.h,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const drawParticles = () => {
|
||||
clearContext();
|
||||
const particleCount = quantity;
|
||||
for (let i = 0; i < particleCount; i++) {
|
||||
const circle = circleParams();
|
||||
drawCircle(circle);
|
||||
}
|
||||
};
|
||||
|
||||
const remapValue = (
|
||||
value: number,
|
||||
start1: number,
|
||||
end1: number,
|
||||
start2: number,
|
||||
end2: number,
|
||||
): number => {
|
||||
const remapped =
|
||||
((value - start1) * (end2 - start2)) / (end1 - start1) + start2;
|
||||
return remapped > 0 ? remapped : 0;
|
||||
};
|
||||
|
||||
const animate = () => {
|
||||
clearContext();
|
||||
circles.current.forEach((circle: Circle, i: number) => {
|
||||
// Handle the alpha value
|
||||
const edge = [
|
||||
circle.x + circle.translateX - circle.size, // distance from left edge
|
||||
canvasSize.current.w - circle.x - circle.translateX - circle.size, // distance from right edge
|
||||
circle.y + circle.translateY - circle.size, // distance from top edge
|
||||
canvasSize.current.h - circle.y - circle.translateY - circle.size, // distance from bottom edge
|
||||
];
|
||||
const closestEdge = edge.reduce((a, b) => Math.min(a, b));
|
||||
const remapClosestEdge = parseFloat(
|
||||
remapValue(closestEdge, 0, 20, 0, 1).toFixed(2),
|
||||
);
|
||||
if (remapClosestEdge > 1) {
|
||||
circle.alpha += 0.02;
|
||||
if (circle.alpha > circle.targetAlpha) {
|
||||
circle.alpha = circle.targetAlpha;
|
||||
}
|
||||
} else {
|
||||
circle.alpha = circle.targetAlpha * remapClosestEdge;
|
||||
}
|
||||
circle.x += circle.dx + vx;
|
||||
circle.y += circle.dy + vy;
|
||||
circle.translateX +=
|
||||
(mouse.current.x / (staticity / circle.magnetism) - circle.translateX) /
|
||||
ease;
|
||||
circle.translateY +=
|
||||
(mouse.current.y / (staticity / circle.magnetism) - circle.translateY) /
|
||||
ease;
|
||||
|
||||
drawCircle(circle, true);
|
||||
|
||||
// circle gets out of the canvas
|
||||
if (
|
||||
circle.x < -circle.size ||
|
||||
circle.x > canvasSize.current.w + circle.size ||
|
||||
circle.y < -circle.size ||
|
||||
circle.y > canvasSize.current.h + circle.size
|
||||
) {
|
||||
// remove the circle from the array
|
||||
circles.current.splice(i, 1);
|
||||
// create a new circle
|
||||
const newCircle = circleParams();
|
||||
drawCircle(newCircle);
|
||||
}
|
||||
});
|
||||
rafID.current = window.requestAnimationFrame(animate);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn("pointer-events-none", className)}
|
||||
ref={canvasContainerRef}
|
||||
aria-hidden="true"
|
||||
{...props}
|
||||
>
|
||||
<canvas ref={canvasRef} className="size-full" />
|
||||
</div>
|
||||
);
|
||||
};
|
@ -42,7 +42,7 @@ export function SevenSegmentDigit({ digit }: { digit: string }) {
|
||||
<div
|
||||
key={seg.name}
|
||||
className={`absolute rounded-full ${seg.className} ${
|
||||
segmentMap[digit]?.includes(seg.name) ? "bg-black" : "bg-gray-400"
|
||||
segmentMap[digit]?.includes(seg.name) ? "bg-black" : "bg-gray-300"
|
||||
}`}
|
||||
/>
|
||||
))}
|
||||
|
132
src/components/ui/wavy-background.tsx
Normal file
132
src/components/ui/wavy-background.tsx
Normal file
@ -0,0 +1,132 @@
|
||||
"use client";
|
||||
import { cn } from "@/lib/utils";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { createNoise3D } from "simplex-noise";
|
||||
|
||||
export const WavyBackground = ({
|
||||
children,
|
||||
className,
|
||||
containerClassName,
|
||||
colors,
|
||||
waveWidth,
|
||||
backgroundFill,
|
||||
blur = 10,
|
||||
speed = "fast",
|
||||
waveOpacity = 0.5,
|
||||
...props
|
||||
}: {
|
||||
children?: any;
|
||||
className?: string;
|
||||
containerClassName?: string;
|
||||
colors?: string[];
|
||||
waveWidth?: number;
|
||||
backgroundFill?: string;
|
||||
blur?: number;
|
||||
speed?: "slow" | "fast";
|
||||
waveOpacity?: number;
|
||||
[key: string]: any;
|
||||
}) => {
|
||||
const noise = createNoise3D();
|
||||
let w: number,
|
||||
h: number,
|
||||
nt: number,
|
||||
i: number,
|
||||
x: number,
|
||||
ctx: any,
|
||||
canvas: any;
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const getSpeed = () => {
|
||||
switch (speed) {
|
||||
case "slow":
|
||||
return 0.001;
|
||||
case "fast":
|
||||
return 0.002;
|
||||
default:
|
||||
return 0.001;
|
||||
}
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
canvas = canvasRef.current;
|
||||
ctx = canvas.getContext("2d");
|
||||
w = ctx.canvas.width = window.innerWidth;
|
||||
h = ctx.canvas.height = window.innerHeight;
|
||||
ctx.filter = `blur(${blur}px)`;
|
||||
nt = 0;
|
||||
window.onresize = function () {
|
||||
w = ctx.canvas.width = window.innerWidth;
|
||||
h = ctx.canvas.height = window.innerHeight;
|
||||
ctx.filter = `blur(${blur}px)`;
|
||||
};
|
||||
render();
|
||||
};
|
||||
|
||||
const waveColors = colors ?? [
|
||||
"#38bdf8",
|
||||
"#818cf8",
|
||||
"#c084fc",
|
||||
"#e879f9",
|
||||
"#22d3ee",
|
||||
];
|
||||
const drawWave = (n: number) => {
|
||||
nt += getSpeed();
|
||||
for (i = 0; i < n; i++) {
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = waveWidth || 50;
|
||||
ctx.strokeStyle = waveColors[i % waveColors.length];
|
||||
for (x = 0; x < w; x += 5) {
|
||||
var y = noise(x / 800, 0.3 * i, nt) * 100;
|
||||
ctx.lineTo(x, y + h * 0.5); // adjust for height, currently at 50% of the container
|
||||
}
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
}
|
||||
};
|
||||
|
||||
let animationId: number;
|
||||
const render = () => {
|
||||
ctx.fillStyle = backgroundFill || "black";
|
||||
ctx.globalAlpha = waveOpacity || 0.5;
|
||||
ctx.fillRect(0, 0, w, h);
|
||||
drawWave(5);
|
||||
animationId = requestAnimationFrame(render);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
init();
|
||||
return () => {
|
||||
cancelAnimationFrame(animationId);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const [isSafari, setIsSafari] = useState(false);
|
||||
useEffect(() => {
|
||||
// I'm sorry but i have got to support it on safari.
|
||||
setIsSafari(
|
||||
typeof window !== "undefined" &&
|
||||
navigator.userAgent.includes("Safari") &&
|
||||
!navigator.userAgent.includes("Chrome")
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"h-screen flex flex-col items-center justify-center",
|
||||
containerClassName
|
||||
)}
|
||||
>
|
||||
<canvas
|
||||
className="absolute top-0 left-0 right-0 bottom-0 size-full z-0"
|
||||
ref={canvasRef}
|
||||
id="canvas"
|
||||
style={{
|
||||
...(isSafari ? { filter: `blur(${blur}px)` } : {}),
|
||||
}}
|
||||
></canvas>
|
||||
<div className={cn("relative z-10", className)} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -92,3 +92,10 @@ export const getInitials = (string: string) =>
|
||||
string
|
||||
.split(/\s/)
|
||||
.reduce((response, word) => (response += word.slice(0, 1)), "");
|
||||
|
||||
export function getRange(page: number, limit: number) {
|
||||
const from = page * limit;
|
||||
const to = from + limit - 1;
|
||||
|
||||
return [from, to];
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user