Skip to content
Open
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
209 changes: 139 additions & 70 deletions components/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ declare global {

import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Carousel } from "@/components/ui/carousel";
import { Downloads } from "@/lib/types";
import { DeviceDetails } from "@/lib/ua";
import {
Expand All @@ -21,6 +22,9 @@ import {
CheckCircle2,
Sprout,
Play,
Rocket,
Shield,
Globe,
} from "lucide-react";
import Image from "next/image";
import Link from "next/link";
Expand Down Expand Up @@ -243,78 +247,143 @@ export default function Component({

{/* Feature Cards */}
<div className="relative w-full pb-16 md:pb-24">
<div className="grid grid-cols-1 gap-4 md:grid-cols-3 md:gap-8">
<FeatureCard
icon={<Brain className="h-8 w-8" />}
title="Zero Setup"
description="GitHub native integration"
gradient="from-[#ff6bfd] to-indigo-500"
details={[
{
icon: <Code className="h-5 w-5" />,
text: "One-Click Setup",
},
{
icon: <Zap className="h-5 w-5" />,
text: "10-second task creation",
},
{
icon: (
<CheckCircle2 className="h-5 w-5" />
),
text: "Parallel Execution",
},
]}
/>
<FeatureCard
icon={<GitPullRequest className="h-8 w-8" />}
title="Iterate on PR"
description="Automated PR workflow"
gradient="from-indigo-400 to-cyan-400"
details={[
{
icon: <Code className="h-5 w-5" />,
text: "Smart PR suggestions",
},
{
icon: <Zap className="h-5 w-5" />,
text: "Automatic code reviews",
},
{
icon: (
<CheckCircle2 className="h-5 w-5" />
),
text: "Continuous improvements",
},
]}
/>
<FeatureCard
icon={<Clock className="h-8 w-8" />}
title="Parallel Execution"
description="Run agents in parallel"
gradient="from-cyan-400 to-[#ff6bfd]"
details={[
{
icon: <Code className="h-5 w-5" />,
text: "AGENTS AGENTS AGENTS",
},
{
icon: <Zap className="h-5 w-5" />,
text: "Efficient task distribution",
},
{
icon: (
<CheckCircle2 className="h-5 w-5" />
),
text: "Real-time progress tracking",
},
]}
/>
<div className="absolute -right-8 -top-8 h-64 w-64 animate-pulse rounded-full bg-indigo-500/10 blur-3xl filter"></div>
</div>
<h2 className={`text-center text-3xl font-bold mb-12 text-white ${delaGothic.className}`}>
Our Features
</h2>
<Carousel showArrows={true} showDots={true} className="h-[400px]" cardsToShow={3}>
{[
<FeatureCard
key="card1"
icon={<Brain className="h-8 w-8" />}
title="Zero Setup"
description="GitHub native integration"
gradient="from-[#ff6bfd] to-indigo-500"
details={[
{
icon: <Code className="h-5 w-5" />,
text: "One-Click Setup",
},
{
icon: <Zap className="h-5 w-5" />,
text: "10-second task creation",
},
{
icon: <CheckCircle2 className="h-5 w-5" />,
text: "Parallel Execution",
},
]}
/>,
<FeatureCard
key="card2"
icon={<GitPullRequest className="h-8 w-8" />}
title="Iterate on PR"
description="Automated PR workflow"
gradient="from-indigo-400 to-cyan-400"
details={[
{
icon: <Code className="h-5 w-5" />,
text: "Smart PR suggestions",
},
{
icon: <Zap className="h-5 w-5" />,
text: "Automatic code reviews",
},
{
icon: <CheckCircle2 className="h-5 w-5" />,
text: "Continuous improvements",
},
]}
/>,
<FeatureCard
key="card3"
icon={<Clock className="h-8 w-8" />}
title="Parallel Execution"
description="Run agents in parallel"
gradient="from-cyan-400 to-[#ff6bfd]"
details={[
{
icon: <Code className="h-5 w-5" />,
text: "AGENTS AGENTS AGENTS",
},
{
icon: <Zap className="h-5 w-5" />,
text: "Efficient task distribution",
},
{
icon: <CheckCircle2 className="h-5 w-5" />,
text: "Real-time progress tracking",
},
]}
/>,
<FeatureCard
key="card4"
icon={<Rocket className="h-8 w-8" />}
title="Accelerated Development"
description="Boost your productivity"
gradient="from-green-400 to-blue-500"
details={[
{
icon: <Code className="h-5 w-5" />,
text: "Automated code generation",
},
{
icon: <Zap className="h-5 w-5" />,
text: "Intelligent refactoring",
},
{
icon: <CheckCircle2 className="h-5 w-5" />,
text: "Optimized workflows",
},
]}
/>,
<FeatureCard
key="card5"
icon={<Shield className="h-8 w-8" />}
title="Enhanced Security"
description="Protect your codebase"
gradient="from-red-400 to-yellow-400"
details={[
{
icon: <Code className="h-5 w-5" />,
text: "Vulnerability scanning",
},
{
icon: <Zap className="h-5 w-5" />,
text: "Security best practices",
},
{
icon: <CheckCircle2 className="h-5 w-5" />,
text: "Compliance monitoring",
},
]}
/>,
<FeatureCard
key="card6"
icon={<Globe className="h-8 w-8" />}
title="Global Collaboration"
description="Work together seamlessly"
gradient="from-purple-400 to-pink-400"
details={[
{
icon: <Code className="h-5 w-5" />,
text: "Real-time collaboration",
},
{
icon: <Zap className="h-5 w-5" />,
text: "Cross-team integration",
},
{
icon: <CheckCircle2 className="h-5 w-5" />,
text: "Unified workflow",
},
]}
/>,
]}
</Carousel>
<div className="absolute -right-8 -top-8 h-64 w-64 animate-pulse rounded-full bg-indigo-500/10 blur-3xl filter"></div>
</div>
</div>
</div>
</div>
);
}
}
163 changes: 163 additions & 0 deletions components/ui/carousel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
"use client";

import React, { useState, useEffect } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";

interface CarouselProps {
children: React.ReactNode[];
autoPlay?: boolean;
interval?: number;
showArrows?: boolean;
showDots?: boolean;
className?: string;
cardsToShow?: number;
}

export function Carousel({
children,
autoPlay = true,
interval = 5000,
showArrows = true,
showDots = true,
className,
cardsToShow = 3,
}: CarouselProps) {
const [currentIndex, setCurrentIndex] = useState(0);
const [isPaused, setIsPaused] = useState(false);
const [visibleCardCount, setVisibleCardCount] = useState(cardsToShow);

// Update visible card count based on screen size
useEffect(() => {
const handleResize = () => {
if (typeof window !== 'undefined') {
if (window.innerWidth < 640) {
setVisibleCardCount(1);
} else if (window.innerWidth < 768) {
setVisibleCardCount(2);
} else {
setVisibleCardCount(cardsToShow);
}
}
};

// Set initial value
handleResize();

// Add event listener
window.addEventListener('resize', handleResize);

// Cleanup
return () => window.removeEventListener('resize', handleResize);
}, [cardsToShow]);

// Calculate the total number of "pages" based on the number of cards to show
const totalPages = Math.ceil(children.length / visibleCardCount);

const handleNext = () => {
setCurrentIndex((prevIndex) => {
const nextIndex = prevIndex + visibleCardCount;
return nextIndex >= children.length ? 0 : nextIndex;
});
};

const handlePrev = () => {
setCurrentIndex((prevIndex) => {
const nextIndex = prevIndex - visibleCardCount;
return nextIndex < 0 ? Math.max(0, children.length - visibleCardCount) : nextIndex;
});
};

const handleDotClick = (pageIndex: number) => {
setCurrentIndex(pageIndex * visibleCardCount);
};

useEffect(() => {
if (autoPlay && !isPaused) {
const timer = setTimeout(() => {
handleNext();
}, interval);

return () => clearTimeout(timer);
}
}, [currentIndex, autoPlay, interval, isPaused]);

// Get the current visible cards
const visibleCards = () => {
const cards = [];
for (let i = 0; i < visibleCardCount; i++) {
const index = currentIndex + i;
if (index < children.length) {
cards.push(children[index]);
}
}
return cards;
};

return (
<div
className={cn("relative w-full overflow-hidden", className)}
onMouseEnter={() => setIsPaused(true)}
onMouseLeave={() => setIsPaused(false)}
>
<div className="relative h-full w-full">
<AnimatePresence mode="wait">
<motion.div
key={currentIndex}
initial={{ opacity: 0, x: 100 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -100 }}
transition={{ duration: 0.5 }}
className="grid h-full w-full grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 md:gap-8"
>
{visibleCards().map((card, index) => (
<div key={index} className="h-full w-full">
{card}
</div>
))}
</motion.div>
</AnimatePresence>
</div>

{showArrows && (
<>
<button
onClick={handlePrev}
className="absolute left-4 top-1/2 z-10 -translate-y-1/2 rounded-full bg-black/30 p-2 text-white backdrop-blur-sm transition-all hover:bg-black/50"
aria-label="Previous slide"
>
<ChevronLeft className="h-6 w-6" />
</button>
<button
onClick={handleNext}
className="absolute right-4 top-1/2 z-10 -translate-y-1/2 rounded-full bg-black/30 p-2 text-white backdrop-blur-sm transition-all hover:bg-black/50"
aria-label="Next slide"
>
<ChevronRight className="h-6 w-6" />
</button>
</>
)}

{showDots && totalPages > 1 && (
<div className="absolute bottom-4 left-1/2 z-10 flex -translate-x-1/2 space-x-2">
{Array.from({ length: totalPages }).map((_, index) => {
const pageStartIndex = index * visibleCardCount;
return (
<button
key={index}
onClick={() => handleDotClick(index)}
className={`h-2 w-2 rounded-full transition-all ${
currentIndex >= pageStartIndex && currentIndex < pageStartIndex + visibleCardCount
? "bg-white w-4"
: "bg-white/50 hover:bg-white/80"
}`}
aria-label={`Go to page ${index + 1}`}
/>
);
})}
</div>
)}
</div>
);
}