Merge origin/master

This commit is contained in:
2026-01-25 19:38:30 +01:00
305 changed files with 67481 additions and 36716 deletions
+63 -13
View File
@@ -2,15 +2,54 @@
import { useState, useEffect, useCallback } from 'react';
import { useTranslations } from 'next-intl';
import { motion, AnimatePresence } from 'framer-motion';
import { motion } from 'framer-motion';
import { Database, Server, Code2, Bot, Workflow, FileCode2 } from 'lucide-react';
interface Skill {
name: string;
level: number;
description: string;
}
interface SkeletonProps {
className?: string;
}
const Skeleton: React.FC<SkeletonProps> = ({ className }) => (
<div className={`animate-pulse bg-zinc-700/50 rounded ${className}`}></div>
);
const SkillsSkeleton = () => (
<section id="skills" className="py-24 relative" aria-label="Loading skills" aria-busy="true">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<Skeleton className="h-8 w-48 mb-12" />
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{/* Skills Progress Bars Skeleton */}
<div className="space-y-6">
{[1, 2, 3, 4, 5, 6, 7, 8].map((i) => (
<div key={i} className="space-y-2">
<div className="flex justify-between items-center">
<Skeleton className="h-4 w-24" />
<Skeleton className="h-4 w-12" />
</div>
<Skeleton className="h-2 w-full rounded-full" />
</div>
))}
</div>
{/* Skills Icons Grid Skeleton */}
<div className="grid grid-cols-2 sm:grid-cols-3 gap-4">
{[1, 2, 3, 4, 5, 6].map((i) => (
<div key={i} className="p-6 rounded-xl bg-zinc-800/30 backdrop-blur-sm">
<Skeleton className="w-8 h-8 mx-auto mb-3" />
<Skeleton className="h-4 w-16 mx-auto" />
</div>
))}
</div>
</div>
</div>
</section>
);
const iconMap: Record<string, React.ReactNode> = {
'AI & LLMs': <Bot className="w-8 h-8" />,
'Automation': <Workflow className="w-8 h-8" />,
@@ -25,7 +64,6 @@ const iconMap: Record<string, React.ReactNode> = {
const Skills = () => {
const t = useTranslations('pages.home.skills');
const [selectedSkill, setSelectedSkill] = useState<string | null>(null);
const [skills, setSkills] = useState<Skill[]>([]);
const handleHoverStart = useCallback((skillName: string) => {
@@ -37,19 +75,24 @@ const Skills = () => {
}, []);
useEffect(() => {
try {
const translatedSkills = t.raw('skills') as Skill[];
if (Array.isArray(translatedSkills)) {
setSkills(translatedSkills);
// Temporary delay to see skeleton loading state
const timer = setTimeout(() => {
try {
const translatedSkills = t.raw('skills') as Skill[];
if (Array.isArray(translatedSkills)) {
setSkills(translatedSkills);
}
} catch (error) {
console.error('Error loading skills:', error);
setSkills([]);
}
} catch (error) {
console.error('Error loading skills:', error);
setSkills([]);
}
}, 2000);
return () => clearTimeout(timer);
}, [t]);
if (skills.length === 0) {
return <div className="py-24 text-center text-zinc-400">Loading skills...</div>;
return <SkillsSkeleton />;
}
return (
@@ -104,12 +147,13 @@ const Skills = () => {
{skills.map((skill, idx) => (
<motion.div
key={skill.name}
className="relative"
initial={{ opacity: 0, scale: 0.8 }}
whileInView={{ opacity: 1, scale: 1 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: idx * 0.1 }}
className="p-6 rounded-xl bg-zinc-800/30 backdrop-blur-sm flex flex-col items-center justify-center gap-3"
>
<<<<<<< HEAD
<motion.div
className={`relative p-6 rounded-xl bg-zinc-800/30 backdrop-blur-sm flex flex-col items-center justify-center gap-3 cursor-pointer transition-colors duration-300 hover:bg-zinc-700/50 ${
selectedSkill === skill.name ? 'ring-2 ring-zinc-500 z-20' : ''
@@ -152,6 +196,12 @@ const Skills = () => {
)}
</AnimatePresence>
</motion.div>
=======
<div className="text-white">
{iconMap[skill.name] || <Code2 className="w-8 h-8" />}
</div>
<span className="text-white text-sm text-center">{skill.name}</span>
>>>>>>> origin/master
</motion.div>
))}
</div>