Files
portifolio-evandrodevbr/app/components/Experience.tsx
T
Evandro Fonseca Junior 6ec67c8f5a feat(about): add story sections and core values to About component
Enhance the About page with new story sections detailing personal journey and core values, including icons and structured content for better user engagement and self-presentation.
2025-10-11 18:25:41 -03:00

326 lines
13 KiB
TypeScript

"use client";
import { motion } from "motion/react";
import {
Calendar,
MapPin,
Briefcase,
Zap,
TrendingUp,
Users,
Award,
ExternalLink,
} from "lucide-react";
import { usePortfolioData } from "@/lib/usePortfolioData";
export default function Experience() {
const { data, loading, error } = usePortfolioData();
if (loading) {
return (
<section id="experience" className="py-20 px-4">
<div className="max-w-7xl mx-auto text-center">
<div className="animate-pulse">
<div className="h-8 bg-gray-700 rounded w-1/3 mx-auto mb-4"></div>
<div className="h-4 bg-gray-700 rounded w-1/2 mx-auto"></div>
</div>
</div>
</section>
);
}
if (error || !data) {
return (
<section id="experience" className="py-20 px-4">
<div className="max-w-7xl mx-auto text-center">
<p className="text-red-400">Erro ao carregar dados de experiência.</p>
</div>
</section>
);
}
const experiences = data.experiences
.filter((exp) => exp.featured)
.sort((a, b) => {
// Extrair ano de início de cada experiência
const getStartYear = (period: string) => {
const yearMatch = period.match(/(\d{4})/);
return yearMatch ? parseInt(yearMatch[1]) : 0;
};
const yearA = getStartYear(a.period);
const yearB = getStartYear(b.period);
// Ordenar da mais antiga para a mais nova
return yearA - yearB;
});
// Configuração de cores por empresa/tipo
const experienceConfig = {
"innovo-tecnologia": {
color: "from-blue-500 to-cyan-600",
bgColor: "bg-blue-500/10",
borderColor: "border-blue-500/20",
iconColor: "text-blue-400",
accent: "blue",
},
"apolo-energia": {
color: "from-green-500 to-emerald-600",
bgColor: "bg-green-500/10",
borderColor: "border-green-500/20",
iconColor: "text-green-400",
accent: "green",
},
};
const getExperienceConfig = (company: string) => {
const key = company
.toLowerCase()
.replace(/\s+/g, "-")
.replace(/[^a-z0-9-]/g, "");
return (
experienceConfig[key as keyof typeof experienceConfig] ||
experienceConfig["innovo-tecnologia"]
);
};
const formatDuration = (period: string) => {
// Extrair meses da string de período (ex: "3 meses")
const monthsMatch = period.match(/(\d+)\s*meses?/i);
if (monthsMatch) {
const months = parseInt(monthsMatch[1]);
if (months < 12) {
return `${months} ${months === 1 ? "mês" : "meses"}`;
} else {
const years = Math.floor(months / 12);
const remainingMonths = months % 12;
if (remainingMonths === 0) {
return `${years} ${years === 1 ? "ano" : "anos"}`;
} else {
return `${years} ${
years === 1 ? "ano" : "anos"
} e ${remainingMonths} ${remainingMonths === 1 ? "mês" : "meses"}`;
}
}
}
// Extrair anos da string de período (ex: "3 anos 5 meses")
const yearsMatch = period.match(/(\d+)\s*anos?/i);
if (yearsMatch) {
const years = parseInt(yearsMatch[1]);
return `${years}+ ${years === 1 ? "ano" : "anos"}`;
}
return "Experiência relevante";
};
return (
<section id="experience" className="py-20 px-4 relative">
<div className="max-w-7xl mx-auto">
{/* Header */}
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
viewport={{ once: true }}
className="text-center mb-20"
>
<div className="inline-flex items-center gap-2 bg-gradient-to-r from-cyan-400/10 to-blue-500/10 px-6 py-3 rounded-full mb-6 border border-cyan-400/20">
<div className="w-2 h-2 bg-cyan-400 rounded-full animate-pulse"></div>
<span className="text-sm font-medium text-cyan-300">
Jornada Profissional
</span>
</div>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-bold mb-6 bg-gradient-to-r from-cyan-400 to-blue-500 bg-clip-text text-transparent">
Experiência Profissional
</h2>
<p className="text-xl text-gray-300 max-w-3xl mx-auto leading-relaxed">
Uma trajetória de crescimento técnico e impacto real, onde cada
projeto representou um novo nível de desafio e aprendizado
</p>
</motion.div>
{/* Experience Cards Grid */}
<div className="grid lg:grid-cols-2 gap-8">
{experiences.map((exp, index) => {
const config = getExperienceConfig(exp.company);
return (
<motion.div
key={exp.id}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: index * 0.2 }}
viewport={{ once: true }}
className="relative"
>
{/* Content Card */}
<div className="h-full">
<div className="relative group">
{/* Background Glow */}
<div
className={`absolute inset-0 bg-gradient-to-r ${config.color} opacity-10 rounded-2xl blur-xl group-hover:opacity-20 transition-opacity duration-500`}
></div>
{/* Main Card */}
<div className="relative bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-8 hover:border-cyan-500/30 transition-all duration-300 hover:scale-105">
{/* Header */}
<div className="flex items-start justify-between mb-6">
<div className="flex-1">
<div className="flex items-center gap-3 mb-3">
<div className={`p-3 rounded-xl ${config.bgColor}`}>
<Briefcase
className={`w-6 h-6 ${config.iconColor}`}
/>
</div>
<div>
<h3 className="text-2xl font-bold text-white mb-1">
{exp.title}
</h3>
<p
className={`text-lg font-semibold ${config.iconColor}`}
>
{exp.company}
</p>
</div>
</div>
{/* Meta Info */}
<div className="flex flex-wrap gap-4 text-sm text-gray-400 mb-4">
<div className="flex items-center gap-2">
<Calendar className="w-4 h-4" />
<span>{exp.period}</span>
</div>
{exp.location && (
<div className="flex items-center gap-2">
<MapPin className="w-4 h-4" />
<span>{exp.location}</span>
</div>
)}
<div className="flex items-center gap-2">
<Users className="w-4 h-4" />
<span>{exp.type}</span>
</div>
</div>
</div>
{/* Duration Badge */}
<div
className={`px-4 py-2 rounded-full ${config.bgColor} border ${config.borderColor}`}
>
<span
className={`text-sm font-bold ${config.iconColor}`}
>
{formatDuration(exp.period)}
</span>
</div>
</div>
{/* Description */}
<p className="text-gray-300 leading-relaxed mb-6 text-lg">
{exp.description}
</p>
{/* Achievements */}
{exp.achievements && exp.achievements.length > 0 && (
<div className="mb-6">
<h4 className="text-sm font-semibold text-gray-400 mb-4 uppercase tracking-wide flex items-center gap-2">
<Award className="w-4 h-4 text-yellow-400" />
Principais Conquistas
</h4>
<div className="grid gap-3">
{exp.achievements.map((achievement, idx) => (
<div
key={idx}
className="flex items-start gap-3 p-3 rounded-lg bg-white/5 border border-white/5 hover:border-blue-500/20 transition-colors"
>
<div className="w-2 h-2 bg-gradient-to-r from-blue-400 to-purple-400 rounded-full mt-2 flex-shrink-0"></div>
<span className="text-gray-300 text-sm leading-relaxed">
{achievement}
</span>
</div>
))}
</div>
</div>
)}
{/* Technologies */}
{exp.technologies && exp.technologies.length > 0 && (
<div>
<h4 className="text-sm font-semibold text-gray-400 mb-3 uppercase tracking-wide flex items-center gap-2">
<Zap className="w-4 h-4 text-orange-400" />
Stack Tecnológica
</h4>
<div className="flex flex-wrap gap-2">
{exp.technologies.slice(0, 6).map((tech) => (
<span
key={tech}
className="px-3 py-1 bg-gray-800/50 text-gray-300 text-xs rounded-full border border-gray-700/50 hover:border-blue-500/30 transition-colors"
>
{tech}
</span>
))}
{exp.technologies.length > 6 && (
<span className="px-3 py-1 bg-gray-800/30 text-gray-500 text-xs rounded-full">
+{exp.technologies.length - 6}
</span>
)}
</div>
</div>
)}
</div>
</div>
</div>
</motion.div>
);
})}
</div>
{/* Summary Stats */}
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.6 }}
viewport={{ once: true }}
className="mt-20"
>
<div className="relative max-w-4xl mx-auto">
<div className="absolute inset-0 bg-gradient-to-r from-blue-500/10 via-purple-500/10 to-green-500/10 rounded-2xl blur-xl"></div>
<div className="relative bg-gradient-to-r from-blue-500/5 to-green-500/5 border border-blue-500/20 rounded-2xl p-8 backdrop-blur-sm">
<h4 className="text-2xl font-bold text-white mb-6 text-center">
Impacto e Crescimento
</h4>
<div className="grid md:grid-cols-3 gap-6">
<div className="text-center">
<div className="text-3xl font-bold text-blue-400 mb-2">
3+
</div>
<div className="text-gray-400 text-sm">
Anos de Experiência
</div>
</div>
<div className="text-center">
<div className="text-3xl font-bold text-purple-400 mb-2">
2
</div>
<div className="text-gray-400 text-sm">
Empresas Diferentes
</div>
</div>
<div className="text-center">
<div className="text-3xl font-bold text-green-400 mb-2">
10+
</div>
<div className="text-gray-400 text-sm">
Tecnologias Dominadas
</div>
</div>
</div>
</div>
</div>
</motion.div>
</div>
</section>
);
}