Files
fullstack-portfolio/src/components/sections/portfolio/PrincipleSection.tsx

252 lines
8.9 KiB
TypeScript

"use client";
import { useRef, useState, useEffect } from "react";
import { motion, useInView } from "framer-motion";
import {
Layers,
ShieldCheck,
Zap,
RefreshCcw,
GitBranch,
Box,
} from "lucide-react";
import { useTheme } from "next-themes";
import SyntaxHighlighter from "react-syntax-highlighter";
import {
atomOneDark,
atomOneLight,
} from "react-syntax-highlighter/dist/esm/styles/hljs";
const principles = [
{
icon: Layers,
title: "Clean Architecture Mindset",
description:
"I structure applications with clear separation of concerns so business logic stays maintainable and easy to evolve as the project grows.",
tag: "Architecture",
},
{
icon: Box,
title: "Modular Code Structure",
description:
"I organize features into well-defined modules to keep the codebase scalable and easier for teams to understand and maintain.",
tag: "Scalability",
},
{
icon: GitBranch,
title: "Abstraction & Reusability",
description:
"I prefer abstractions and reusable patterns to keep the codebase flexible and easier to extend in future iterations.",
tag: "Code Design",
},
{
icon: ShieldCheck,
title: "SOLID Principles",
description:
"I apply SOLID principles to write clean, understandable code where each component has a clear responsibility.",
tag: "Code Quality",
},
{
icon: Zap,
title: "Performance Awareness",
description:
"I consider performance early by applying efficient queries, pagination, and thoughtful data handling in web applications.",
tag: "Performance",
},
{
icon: RefreshCcw,
title: "Maintainable Development",
description:
"I focus on writing maintainable code, using version control effectively, and building systems that teams can work on confidently.",
tag: "Workflow",
},
];
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: { staggerChildren: 0.08, delayChildren: 0.1 },
},
};
const itemVariants = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0, transition: { duration: 0.5, ease: "easeOut" } },
};
export function PrincipleSection() {
const ref = useRef(null);
const isInView = useInView(ref, { once: true, margin: "-80px" });
const { resolvedTheme } = useTheme();
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
const isDark = resolvedTheme === "dark";
const codeSnippet = `// ✅ Application Layer — Pure Business Logic
@Injectable()
export class UserService {
constructor(
private readonly userRepository: IUserRepository, // Interface, not implementation
private readonly eventEmitter: IEventEmitter,
) {}
async createUser(dto: CreateUserDto): Promise<UserEntity> {
const exists = await this.userRepository.findByEmail(dto.email)
if (exists) throw new ConflictException('Email already registered')
const user = UserEntity.create(dto) // Domain entity handles business rules
await this.userRepository.save(user)
await this.eventEmitter.emit('user.created', user)
return user
}
}
// ✅ Infrastructure Layer — Implementation Detail
@Injectable()
export class PrismaUserRepository implements IUserRepository {
constructor(private prisma: PrismaService) {}
async findByEmail(email: string) { /* ... */ }
async save(user: UserEntity) { /* ... */ }
}`;
return (
<section id="principles" className="py-16 sm:py-20 lg:py-32 relative overflow-hidden">
{/* Background */}
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-surface/30 to-transparent" />
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[800px] h-[400px] bg-accent/4 rounded-full blur-[150px] pointer-events-none" />
<div className="relative z-10 max-w-6xl mx-auto px-6">
{/* Header */}
<div className="text-center mb-12 sm:mb-16">
<motion.span
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
className="text-accent font-mono text-xs sm:text-sm tracking-widest uppercase"
>
System Design
</motion.span>
<motion.h2
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.1 }}
className="font-display font-bold text-3xl sm:text-4xl md:text-5xl text-foreground mt-3"
>
Engineering
<span className="gradient-text-blue"> Principles</span>
</motion.h2>
<motion.p
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.2 }}
className="text-foreground-muted mt-4 max-w-2xl mx-auto leading-relaxed text-sm sm:text-base px-4"
>
I aim to build systems that are clean, maintainable, and ready to grow as products evolve.
These principles guide how I structure applications and approach technical decisions.
</motion.p>
</div>
{/* Principles Grid */}
<motion.div
ref={ref}
variants={containerVariants}
initial="hidden"
animate={isInView ? "visible" : "hidden"}
className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-5"
>
{principles.map((p) => {
const Icon = p.icon;
return (
<motion.div
key={p.title}
variants={itemVariants}
className="group p-4 sm:p-6 rounded-2xl bg-surface-elevated border border-border hover:border-accent/30 hover:shadow-glow transition-all duration-300"
>
<div className="flex items-start justify-between gap-4 mb-4">
<div className="w-10 h-10 rounded-xl bg-accent/10 border border-border flex items-center justify-center group-hover:bg-accent/20 transition-colors">
<Icon size={18} className="text-accent" />
</div>
<span className="text-xs font-mono text-foreground-subtle bg-surface border border-border-subtle px-2.5 py-1 rounded-lg">
{p.tag}
</span>
</div>
<h3 className="font-display font-semibold text-foreground text-sm sm:text-base mb-3 leading-snug">
{p.title}
</h3>
<p className="text-xs sm:text-sm text-foreground-muted leading-relaxed">
{p.description}
</p>
</motion.div>
);
})}
</motion.div>
{/* Code snippet preview */}
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: 0.3 }}
className="mt-8 sm:mt-10 rounded-2xl bg-surface-elevated border border-border overflow-hidden"
>
{/* macOS-style title bar */}
<div className="flex items-center gap-2 sm:gap-3 px-3 sm:px-5 py-3 sm:py-3.5 border-b border-border bg-surface">
<div className="flex gap-1.5">
<div className="w-3 h-3 rounded-full bg-red-500/70" />
<div className="w-3 h-3 rounded-full bg-yellow-500/70" />
<div className="w-3 h-3 rounded-full bg-green-500/70" />
</div>
<span className="text-xs font-mono text-foreground-muted ml-1 truncate">
user.service.ts
</span>
<span className="hidden sm:inline ml-auto text-xs font-mono text-foreground-subtle opacity-60">
Clean Architecture Example
</span>
</div>
{/* Syntax-highlighted code */}
{mounted ? (
<SyntaxHighlighter
language="typescript"
style={isDark ? atomOneDark : atomOneLight}
showLineNumbers={false}
wrapLongLines={true}
customStyle={{
margin: 0,
padding: "1rem 1.5rem",
fontSize: "0.6875rem",
lineHeight: "1.6",
background: "transparent",
overflowX: "auto",
}}
lineNumberStyle={{
color: isDark ? "#3d4451" : "#c4c9d4",
paddingRight: "1.5rem",
minWidth: "2.5rem",
userSelect: "none",
}}
>
{codeSnippet}
</SyntaxHighlighter>
) : (
<div
className="p-6 overflow-x-auto text-[0.75rem] font-mono leading-[1.7] opacity-0 text-transparent"
aria-hidden="true"
>
<pre>{codeSnippet}</pre>
</div>
)}
</motion.div>
</div>
</section>
);
}