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.
326 lines
13 KiB
TypeScript
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>
|
|
);
|
|
}
|