init
This commit is contained in:
224
src/features/projects/projects-section.tsx
Normal file
224
src/features/projects/projects-section.tsx
Normal file
@@ -0,0 +1,224 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { AnimatedSection } from "@/shared/components/animated-section";
|
||||
import { SectionHeading } from "@/shared/components/section-heading";
|
||||
import {
|
||||
ExternalLink,
|
||||
GitFork,
|
||||
TrendingUp,
|
||||
Server,
|
||||
Smartphone,
|
||||
Globe,
|
||||
Layers,
|
||||
} from "lucide-react";
|
||||
|
||||
interface Project {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
category: "backend" | "frontend" | "mobile";
|
||||
tags: string[];
|
||||
metrics?: string;
|
||||
repoUrl?: string;
|
||||
liveUrl?: string;
|
||||
}
|
||||
|
||||
const projects: Project[] = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Core Banking API Gateway",
|
||||
description:
|
||||
"High-performance API Gateway handling 500K+ daily transactions with rate limiting, circuit breaker pattern, and distributed tracing across 12 microservices.",
|
||||
category: "backend",
|
||||
tags: ["Spring Boot", "Kafka", "Redis", "Docker"],
|
||||
metrics: "Increased throughput by 40%, 99.9% uptime",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Payment Processing Engine",
|
||||
description:
|
||||
"Event-driven payment system with Saga pattern for distributed transactions, supporting real-time transfers, bill payments, and batch processing.",
|
||||
category: "backend",
|
||||
tags: ["Java", "Kafka", "PostgreSQL", "gRPC"],
|
||||
metrics: "Processing 200K+ payments/day",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "Customer Onboarding Portal",
|
||||
description:
|
||||
"Modern onboarding portal with multi-step KYC verification, document upload, and real-time status tracking for banking customers.",
|
||||
category: "frontend",
|
||||
tags: ["React", "Next.js", "TypeScript", "Tailwind"],
|
||||
repoUrl: "#",
|
||||
liveUrl: "#",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: "Internal Dashboard",
|
||||
description:
|
||||
"Admin dashboard for monitoring API performance, user analytics, and system health with real-time WebSocket updates.",
|
||||
category: "frontend",
|
||||
tags: ["React", "Chart.js", "WebSocket", "REST"],
|
||||
repoUrl: "#",
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
title: "Mobile Banking App",
|
||||
description:
|
||||
"Cross-platform mobile banking application with biometric authentication, push notifications, and offline transaction history.",
|
||||
category: "mobile",
|
||||
tags: ["React Native", "TypeScript", "Redux"],
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
title: "Authentication Microservice",
|
||||
description:
|
||||
"Centralized auth service with OAuth2, JWT, MFA, and session management. Supports SSO across 8 internal applications.",
|
||||
category: "backend",
|
||||
tags: ["Spring Security", "OAuth2", "JWT", "Redis"],
|
||||
metrics: "Securing 50K+ active users",
|
||||
},
|
||||
];
|
||||
|
||||
const filters = [
|
||||
{ value: "all", label: "All Projects", icon: <Layers size={16} /> },
|
||||
{ value: "backend", label: "Backend", icon: <Server size={16} /> },
|
||||
{ value: "frontend", label: "Frontend", icon: <Globe size={16} /> },
|
||||
{ value: "mobile", label: "Mobile", icon: <Smartphone size={16} /> },
|
||||
];
|
||||
|
||||
export function ProjectsSection() {
|
||||
const [activeFilter, setActiveFilter] = useState("all");
|
||||
|
||||
const filteredProjects =
|
||||
activeFilter === "all"
|
||||
? projects
|
||||
: projects.filter((p) => p.category === activeFilter);
|
||||
|
||||
return (
|
||||
<section id="projects" className="section-padding relative">
|
||||
<div className="max-w-6xl mx-auto px-6">
|
||||
<AnimatedSection>
|
||||
<SectionHeading
|
||||
badge="Portfolio"
|
||||
title="Projects & Case Studies"
|
||||
subtitle="Real-world enterprise solutions built for scale, security, and reliability."
|
||||
/>
|
||||
</AnimatedSection>
|
||||
|
||||
{/* Filter tabs */}
|
||||
<AnimatedSection delay={0.1}>
|
||||
<div className="flex flex-wrap items-center justify-center gap-2 mb-12">
|
||||
{filters.map((filter) => (
|
||||
<button
|
||||
key={filter.value}
|
||||
onClick={() => setActiveFilter(filter.value)}
|
||||
className={`inline-flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-300 ${activeFilter === filter.value
|
||||
? "bg-accent text-accent-foreground shadow-lg shadow-accent/25"
|
||||
: "bg-muted/50 text-muted-foreground border border-border/50 hover:border-accent/30 hover:text-foreground"
|
||||
}`}
|
||||
>
|
||||
{filter.icon}
|
||||
{filter.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</AnimatedSection>
|
||||
|
||||
{/* Projects grid */}
|
||||
<motion.div
|
||||
layout
|
||||
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5"
|
||||
>
|
||||
<AnimatePresence mode="popLayout">
|
||||
{filteredProjects.map((project) => (
|
||||
<motion.div
|
||||
key={project.id}
|
||||
layout
|
||||
initial={{ opacity: 0, scale: 0.9 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
exit={{ opacity: 0, scale: 0.9 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<div className="group relative h-full flex flex-col p-6 rounded-2xl bg-card border border-border/50 hover:border-accent/30 transition-all duration-500 hover:shadow-lg hover:shadow-accent/5">
|
||||
{/* Category badge */}
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<span
|
||||
className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-[10px] font-mono font-semibold uppercase tracking-wider ${project.category === "backend"
|
||||
? "bg-blue-500/10 text-blue-500 dark:text-blue-400"
|
||||
: project.category === "frontend"
|
||||
? "bg-violet-500/10 text-violet-500 dark:text-violet-400"
|
||||
: "bg-orange-500/10 text-orange-500 dark:text-orange-400"
|
||||
}`}
|
||||
>
|
||||
{project.category === "backend" ? (
|
||||
<Server size={12} />
|
||||
) : project.category === "frontend" ? (
|
||||
<Globe size={12} />
|
||||
) : (
|
||||
<Smartphone size={12} />
|
||||
)}
|
||||
{project.category}
|
||||
</span>
|
||||
<div className="flex items-center gap-1.5">
|
||||
{project.repoUrl && (
|
||||
<a
|
||||
href={project.repoUrl}
|
||||
className="p-1.5 rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors"
|
||||
aria-label="GitHub"
|
||||
>
|
||||
<GitFork size={14} />
|
||||
</a>
|
||||
)}
|
||||
{project.liveUrl && (
|
||||
<a
|
||||
href={project.liveUrl}
|
||||
className="p-1.5 rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors"
|
||||
aria-label="Live demo"
|
||||
>
|
||||
<ExternalLink size={14} />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Title & description */}
|
||||
<h3 className="text-lg font-bold mb-2 group-hover:text-accent transition-colors">
|
||||
{project.title}
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4 flex-1">
|
||||
{project.description}
|
||||
</p>
|
||||
|
||||
{/* Metrics badge */}
|
||||
{project.metrics && (
|
||||
<div className="flex items-center gap-2 mb-4 px-3 py-2 rounded-lg bg-success/5 border border-success/10">
|
||||
<TrendingUp size={14} className="text-success" />
|
||||
<span className="text-xs font-mono font-medium text-success">
|
||||
{project.metrics}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Tags */}
|
||||
<div className="flex flex-wrap gap-1.5 mt-auto">
|
||||
{project.tags.map((tag) => (
|
||||
<span
|
||||
key={tag}
|
||||
className="px-2 py-1 rounded-md text-[10px] font-mono bg-muted/50 text-muted-foreground border border-border/30"
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user