Files

194 lines
8.1 KiB
TypeScript

"use client";
import React, { useMemo } from "react";
import { motion } from "framer-motion";
import {
ChevronRight,
Terminal,
Cpu,
Network,
Code2
} from "lucide-react";
import { usePortfolioData } from "@/lib/usePortfolioData";
// --- Tipagem e Configuração (Otimização Pareto 80/20) ---
const CONFIG = {
"innovo-tecnologia": { color: "text-blue-400", bg: "bg-blue-400/10", border: "border-blue-400/20", icon: Cpu },
"apolo-energia": { color: "text-emerald-400", bg: "bg-emerald-400/10", border: "border-emerald-400/20", icon: Network },
default: { color: "text-slate-400", bg: "bg-slate-400/10", border: "border-slate-400/20", icon: Code2 }
};
export default function Experience() {
const { data, loading, error } = usePortfolioData();
// Memória: Evita re-processamento de regex em cada re-render (Princípio de Eficiência)
const sortedExperiences = useMemo(() => {
if (!data?.experiences) return [];
return [...data.experiences]
.filter((exp) => exp.featured)
.sort((a, b) => {
const yearA = parseInt(a.period.match(/\d{4}/)?.[0] || "0");
const yearB = parseInt(b.period.match(/\d{4}/)?.[0] || "0");
return yearB - yearA; // Da mais recente para a mais antiga (Padrão Senior)
});
}, [data]);
if (loading) return <ExperienceSkeleton />;
return (
<section id="experience" className="relative py-32">
{/* Background Gradients */}
<div className="absolute top-0 left-0 w-full h-full pointer-events-none">
<div className="absolute top-[20%] left-[-10%] w-[500px] h-[500px] bg-blue-900/10 rounded-full blur-[100px]" />
<div className="absolute bottom-[20%] right-[-10%] w-[500px] h-[500px] bg-indigo-900/10 rounded-full blur-[100px]" />
</div>
<div className="max-w-6xl mx-auto px-6 relative z-10">
{/* Header com Identidade Visual */}
<div className="mb-24 text-center md:text-left">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-blue-950/30 border border-blue-500/20 text-blue-400 font-mono text-xs tracking-wider mb-6"
>
<Terminal className="w-3 h-3" />
<span>SYSTEM_LOGS.history</span>
</motion.div>
<motion.h2
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: 0.1 }}
className="text-4xl md:text-6xl font-black text-white tracking-tighter"
>
Trajetória <span className="bg-gradient-to-r from-blue-500 to-indigo-500 bg-clip-text text-transparent">Profissional</span>
</motion.h2>
</div>
<div className="relative">
{/* Timeline Desktop (Linha Central com Gradiente) */}
<div className="absolute left-[50%] top-0 bottom-0 w-[2px] bg-gradient-to-b from-blue-500/50 via-indigo-500/20 to-transparent hidden lg:block translate-x-[-50%]" />
<div className="space-y-24">
{sortedExperiences.map((exp, index) => (
<ExperienceCard key={exp.id} exp={exp} index={index} />
))}
</div>
</div>
</div>
</section>
);
}
// --- Sub-componente Card (Encapsulamento de Lógica de Transição) ---
function ExperienceCard({ exp, index }: { exp: any, index: number }) {
const isEven = index % 2 === 0;
const config = (CONFIG as any)[exp.company.toLowerCase().replace(/\s+/g, "-")] || CONFIG.default;
const Icon = config.icon;
return (
<div className={`relative flex flex-col ${isEven ? 'lg:flex-row' : 'lg:flex-row-reverse'} items-center gap-8 lg:gap-16`}>
{/* Node Central (O "Ponto" da Timeline) */}
<motion.div
initial={{ scale: 0, opacity: 0 }}
whileInView={{ scale: 1, opacity: 1 }}
viewport={{ once: true }}
transition={{ delay: 0.2, duration: 0.5 }}
className="hidden lg:flex absolute left-[50%] top-0 translate-x-[-50%] w-4 h-4 rounded-full bg-blue-500 shadow-[0_0_20px_rgba(59,130,246,0.5)] z-20 items-center justify-center"
>
<div className="w-2 h-2 rounded-full bg-white animate-pulse" />
</motion.div>
{/* Indicador de Data na Timeline */}
<div className="hidden lg:flex flex-1 justify-end items-start pt-2">
<motion.div
initial={{ opacity: 0, x: isEven ? -20 : 20 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ delay: 0.3 }}
className={`${isEven ? 'text-right' : 'text-left'} flex-1`}
>
<span className="text-4xl font-black text-transparent bg-clip-text bg-gradient-to-b from-slate-700 to-slate-800 tracking-tighter opacity-50 select-none">
{exp.period.split(' ')[0]}
</span>
</motion.div>
</div>
{/* Card Principal */}
<div className="flex-1 w-full relative group perspective-1000">
<motion.div
initial={{ opacity: 0, x: isEven ? 50 : -50 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true, margin: "-100px" }}
transition={{ duration: 0.6, delay: 0.1 * index }}
whileHover={{ y: -5, transition: { duration: 0.2 } }}
className={`p-8 rounded-3xl bg-zinc-900/40 border border-white/5 backdrop-blur-md relative overflow-hidden transition-all duration-300 hover:shadow-[0_0_30px_rgba(59,130,246,0.1)] hover:border-blue-500/20`}
>
{/* Background Glow Effect on Hover */}
<div className="absolute inset-0 bg-gradient-to-br from-blue-500/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
{/* Badge de Empresa & Header */}
<div className="relative z-10">
<div className="flex flex-wrap justify-between items-start gap-4 mb-6">
<div className="space-y-2">
<div className="flex items-center gap-3">
<div className={`p-2 rounded-lg ${config.bg} ${config.color}`}>
<Icon className="w-5 h-5" />
</div>
<span className={`text-xs font-bold uppercase tracking-widest ${config.color}`}>
{exp.company}
</span>
</div>
<h3 className="text-2xl font-bold text-white group-hover:text-blue-400 transition-colors">
{exp.title}
</h3>
</div>
<div className="px-3 py-1 rounded-full bg-white/5 border border-white/10 text-[10px] font-mono font-bold text-slate-400 uppercase tracking-wide">
{exp.period}
</div>
</div>
<p className="text-slate-400 leading-relaxed mb-8 text-sm">
{exp.description}
</p>
{/* Conquistas (Checklist Técnico) */}
<div className="grid grid-cols-1 gap-3 mb-8">
{exp.achievements?.map((ach: string, i: number) => (
<div key={i} className="flex gap-3 text-sm text-slate-300 items-start">
<div className="mt-1.5 w-1.5 h-1.5 rounded-full bg-blue-500 flex-shrink-0" />
<span>{ach}</span>
</div>
))}
</div>
{/* Tags de Tech */}
<div className="flex flex-wrap gap-2 pt-6 border-t border-white/5">
{exp.technologies?.map((tech: string) => (
<span key={tech} className="px-3 py-1 bg-black/20 border border-white/5 text-slate-500 text-[10px] rounded-full font-mono hover:text-blue-400 hover:border-blue-400/30 transition-all cursor-default">
{tech}
</span>
))}
</div>
</div>
</motion.div>
</div>
{/* Spacer para Timeline Desktop */}
<div className="hidden lg:block flex-1" />
</div>
);
}
function ExperienceSkeleton() {
return (
<div className="h-96 flex flex-col items-center justify-center gap-4 text-slate-600 font-mono animate-pulse">
<Cpu className="w-8 h-8 animate-spin" />
<span>BOOTING_SYSTEM_HISTORY...</span>
</div>
);
}