199 lines
6.3 KiB
TypeScript
199 lines
6.3 KiB
TypeScript
import { motion } from 'framer-motion';
|
|
import { Code, Database, Smartphone, Globe, Server, Wrench } from 'lucide-react';
|
|
import { useLanguage } from '../contexts/LanguageContext';
|
|
|
|
const Skills = () => {
|
|
const { t } = useLanguage();
|
|
const skillCategories = [
|
|
{
|
|
id: 'mobile',
|
|
icon: <Smartphone size={32} />,
|
|
title: t('skills.category.mobile'),
|
|
color: "#4FC3F7",
|
|
skills: [
|
|
{ name: "Dart", level: 85, color: "#0175C2" },
|
|
{ name: "Flutter", level: 80, color: "#02569B" }
|
|
]
|
|
},
|
|
{
|
|
id: 'frontend',
|
|
icon: <Globe size={32} />,
|
|
title: t('skills.category.frontend'),
|
|
color: "#42A5F5",
|
|
skills: [
|
|
{ name: "React", level: 75, color: "#61DAFB" },
|
|
{ name: "TypeScript", level: 70, color: "#3178C6" },
|
|
{ name: "JavaScript", level: 80, color: "#F7DF1E" }
|
|
]
|
|
},
|
|
{
|
|
id: 'backend',
|
|
icon: <Server size={32} />,
|
|
title: t('skills.category.backend'),
|
|
color: "#66BB6A",
|
|
skills: [
|
|
{ name: "Java", level: 75, color: "#ED8B00" },
|
|
{ name: "C#", level: 65, color: "#239120" }
|
|
]
|
|
},
|
|
{
|
|
id: 'tools',
|
|
icon: <Wrench size={32} />,
|
|
title: t('skills.category.tools'),
|
|
color: "#AB47BC",
|
|
skills: [
|
|
{ name: "Git", level: 70, color: "#F05032" },
|
|
{ name: "VS Code", level: 90, color: "#007ACC" },
|
|
{ name: "Android Studio", level: 75, color: "#3DDC84" }
|
|
]
|
|
}
|
|
];
|
|
|
|
const containerVariants = {
|
|
hidden: { opacity: 0 },
|
|
visible: {
|
|
opacity: 1,
|
|
transition: {
|
|
staggerChildren: 0.2,
|
|
delayChildren: 0.3
|
|
}
|
|
}
|
|
};
|
|
|
|
const categoryVariants = {
|
|
hidden: { opacity: 0, y: 50 },
|
|
visible: {
|
|
opacity: 1,
|
|
y: 0,
|
|
transition: {
|
|
duration: 0.6,
|
|
ease: [0.25, 0.1, 0.25, 1] as const
|
|
}
|
|
}
|
|
};
|
|
|
|
return (
|
|
<section id="skills" className="skills">
|
|
<div className="container">
|
|
<motion.div
|
|
key="skills-header"
|
|
className="section-header"
|
|
initial={{ opacity: 0, y: 50 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.8 }}
|
|
viewport={{ once: true }}
|
|
>
|
|
<h2 className="section-title">{t('skills.title')}</h2>
|
|
<p className="section-subtitle">
|
|
{t('skills.subtitle')}
|
|
</p>
|
|
</motion.div>
|
|
|
|
<motion.div
|
|
key="skills-grid"
|
|
className="skills-grid"
|
|
variants={containerVariants}
|
|
initial="hidden"
|
|
whileInView="visible"
|
|
viewport={{ once: true }}
|
|
>
|
|
{skillCategories.map((category, categoryIndex) => (
|
|
<motion.div
|
|
key={category.id}
|
|
className="skill-category"
|
|
variants={categoryVariants}
|
|
whileHover={{
|
|
scale: 1.02,
|
|
y: -5,
|
|
transition: { duration: 0.3 }
|
|
}}
|
|
>
|
|
<div className="category-header">
|
|
<div
|
|
className="category-icon"
|
|
style={{ backgroundColor: `${category.color}20`, color: category.color }}
|
|
>
|
|
{category.icon}
|
|
</div>
|
|
<h3 className="category-title">{category.title}</h3>
|
|
</div>
|
|
|
|
<div className="skills-list">
|
|
{category.skills.map((skill, skillIndex) => (
|
|
<motion.div
|
|
key={skill.name}
|
|
className="skill-item"
|
|
initial={{ opacity: 0, x: -30 }}
|
|
whileInView={{ opacity: 1, x: 0 }}
|
|
transition={{
|
|
duration: 0.5,
|
|
delay: (categoryIndex * 0.2) + (skillIndex * 0.1)
|
|
}}
|
|
viewport={{ once: true }}
|
|
>
|
|
<div className="skill-header">
|
|
<span className="skill-name">{skill.name}</span>
|
|
<span className="skill-percentage">{skill.level}%</span>
|
|
</div>
|
|
|
|
<div className="skill-bar">
|
|
<motion.div
|
|
className="skill-progress"
|
|
style={{ backgroundColor: skill.color }}
|
|
initial={{ width: 0 }}
|
|
whileInView={{ width: `${skill.level}%` }}
|
|
transition={{
|
|
duration: 1.5,
|
|
delay: (categoryIndex * 0.2) + (skillIndex * 0.1) + 0.5,
|
|
ease: [0.25, 0.1, 0.25, 1] as const
|
|
}}
|
|
viewport={{ once: true }}
|
|
/>
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</motion.div>
|
|
|
|
{/* Section des soft skills */}
|
|
<motion.div
|
|
className="soft-skills"
|
|
initial={{ opacity: 0, y: 50 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.8, delay: 0.3 }}
|
|
viewport={{ once: true }}
|
|
>
|
|
<h3 className="soft-skills-title">{t('skills.otherSkills')}</h3>
|
|
<div className="soft-skills-grid">
|
|
{[
|
|
{ name: t('skills.problemSolving'), icon: <Wrench size={20} /> },
|
|
{ name: t('skills.teamwork'), icon: <Code size={20} /> },
|
|
{ name: t('skills.continuousLearning'), icon: <Database size={20} /> },
|
|
{ name: t('skills.communication'), icon: <Globe size={20} /> }
|
|
].map((softSkill, index) => (
|
|
<motion.div
|
|
key={softSkill.name}
|
|
className="soft-skill-tag"
|
|
initial={{ opacity: 0, scale: 0.8 }}
|
|
whileInView={{ opacity: 1, scale: 1 }}
|
|
transition={{ duration: 0.5, delay: index * 0.1 }}
|
|
whileHover={{
|
|
scale: 1.05,
|
|
transition: { duration: 0.2 }
|
|
}}
|
|
viewport={{ once: true }}
|
|
>
|
|
{softSkill.icon}
|
|
<span>{softSkill.name}</span>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</motion.div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export default Skills; |