feat: update personal information and localization in various components
Deploy Portfolio Selfmade / deploy (push) Failing after 15s

This commit is contained in:
2026-05-10 14:52:21 +02:00
parent 4ff07915b8
commit 430e02c8ce
14 changed files with 337 additions and 186 deletions
@@ -118,7 +118,7 @@ export const ContactSection: React.FC = () => {
</div>
<div>
<p className="text-gray-400 text-sm">Email</p>
<p className="text-white font-medium">alex@himetoprogram.com</p>
<p className="text-white font-medium">robert@bretz.dev</p>
</div>
</div>
@@ -128,7 +128,7 @@ export const ContactSection: React.FC = () => {
</div>
<div>
<p className="text-gray-400 text-sm">Location</p>
<p className="text-white font-medium">San Francisco, CA</p>
<p className="text-white font-medium">Germany</p>
</div>
</div>
</div>
@@ -3,40 +3,40 @@ import type { Experience } from '../../../shared/types';
export const experienceData: Experience[] = [
{
id: '1',
position: 'Senior React Developer',
company: 'Tech Startup Inc.',
startYear: 2023,
position: 'Senior Software Engineer',
company: 'Enterprise Systems Group',
startYear: 2024,
description:
'Led the development of multiple high-performance React applications, mentored junior developers, and implemented modern design systems',
technologies: ['React', 'TypeScript', 'Next.js', 'GraphQL'],
'Designed scalable backend systems with .NET, SQL, Docker and advanced architecture patterns for enterprise workflows.',
technologies: ['.NET', 'SQL', 'Docker', 'Clean Architecture'],
},
{
id: '2',
position: 'Full Stack Developer',
company: 'Digital Agency Co.',
position: 'Full Stack Architect',
company: 'Innovative SaaS Labs',
startYear: 2022,
endYear: 2023,
endYear: 2024,
description:
'Developed responsive web applications for clients, collaborated with designers, and optimized performance metrics',
technologies: ['React', 'Node.js', 'MongoDB', 'Tailwind CSS'],
'Owned end-to-end product architecture using React, TypeScript, NestJS and Vertical Slice Architecture for high-performance applications.',
technologies: ['React', 'NestJS', 'TypeScript', 'Vertical Slice Architecture'],
},
{
id: '3',
position: 'Junior Frontend Developer',
company: 'Web Solutions Ltd.',
startYear: 2021,
position: 'Backend Developer',
company: 'Platform Engineering Co.',
startYear: 2020,
endYear: 2022,
description:
'Built responsive web interfaces, fixed bugs, and participated in code reviews to improve code quality',
technologies: ['React', 'JavaScript', 'CSS', 'HTML'],
'Built resilient APIs and development workflows with Express.js, Fastify, Node.js and Linux deployment automation.',
technologies: ['Express.js', 'Fastify', 'Node.js', 'Linux'],
},
{
id: '4',
position: 'Freelance Web Developer',
startYear: 2020,
endYear: 2021,
position: 'Creative Tech Consultant',
startYear: 2018,
endYear: 2020,
description:
'Created custom websites for various clients, managed projects independently, and delivered quality work on time',
technologies: ['React', 'WordPress', 'JavaScript', 'jQuery'],
'Delivered immersive digital experiences using Unity, Blender, Godot and LaTeX documentation for creative product storytelling.',
technologies: ['Unity', 'Blender', 'Godot', 'LaTeX'],
},
];
@@ -46,17 +46,17 @@ export const HeroSection: React.FC = () => {
<div className="inline-block px-4 py-2 border border-green-500/50 rounded-full bg-green-500/10 backdrop-blur-sm">
<span className="text-green-400 text-sm font-medium flex items-center gap-2">
<span className="w-2 h-2 bg-green-500 rounded-full"></span>
React Developer & UI/UX Enthusiast | Based in San Francisco, CA
Softwareentwickler & Architektur-Enthusiast | Deutschland
</span>
</div>
</motion.div>
{/* Main Heading */}
<motion.h1 variants={itemVariants} className="text-5xl sm:text-6xl lg:text-7xl font-bold mb-6">
<span className="text-white">React is Developer</span>
<motion.h1 variants={itemVariants} className="text-5xl sm:text-6xl lg:text-7xl font-bold mb-6 leading-tight">
<span className="text-white">Robert Bretz</span>
<br />
<span className="bg-gradient-to-r from-green-500 to-emerald-500 bg-clip-text text-transparent">
Portfolio
Crafting clean, performant digital products
</span>
</motion.h1>
@@ -65,44 +65,44 @@ export const HeroSection: React.FC = () => {
variants={itemVariants}
className="text-gray-300 text-lg sm:text-xl max-w-2xl mx-auto mb-8"
>
Building modern, scalable web applications with React, JavaScript, and cutting-edge technologies.
Transforming ideas into exceptional digital experiences.
Ich entwickle moderne Anwendungen mit React, TypeScript, Tailwind, .NET, NestJS und sauberer Architektur.
Mein Fokus liegt auf Performance, Vertical Slice Architecture, Docker-Deployments und skalierbaren Backend-Systemen.
</motion.p>
{/* Stats */}
<motion.div
variants={itemVariants}
className="grid grid-cols-3 gap-4 sm:gap-8 mb-12 max-w-2xl mx-auto"
className="grid grid-cols-1 sm:grid-cols-3 gap-4 sm:gap-8 mb-12 max-w-2xl mx-auto"
>
<div className="border border-green-500/30 rounded-lg p-4 bg-green-500/5">
<div className="text-2xl sm:text-3xl font-bold text-green-500">3+</div>
<div className="text-gray-400 text-sm">Years Experience</div>
<div className="border border-green-500/30 rounded-lg p-5 bg-green-500/5 backdrop-blur-sm">
<div className="text-3xl font-bold text-green-500">4+</div>
<div className="text-gray-400 text-sm">Years Engineering</div>
</div>
<div className="border border-green-500/30 rounded-lg p-4 bg-green-500/5">
<div className="text-2xl sm:text-3xl font-bold text-green-500">50+</div>
<div className="text-gray-400 text-sm">Projects Completed</div>
<div className="border border-green-500/30 rounded-lg p-5 bg-green-500/5 backdrop-blur-sm">
<div className="text-3xl font-bold text-green-500">30+</div>
<div className="text-gray-400 text-sm">Delivered Solutions</div>
</div>
<div className="border border-green-500/30 rounded-lg p-4 bg-green-500/5">
<div className="text-2xl sm:text-3xl font-bold text-green-500">98%</div>
<div className="text-gray-400 text-sm">Client Satisfaction</div>
<div className="border border-green-500/30 rounded-lg p-5 bg-green-500/5 backdrop-blur-sm">
<div className="text-3xl font-bold text-green-500">99%</div>
<div className="text-gray-400 text-sm">Performance Focus</div>
</div>
</motion.div>
{/* CTA Buttons */}
<motion.div variants={itemVariants} className="flex flex-col sm:flex-row gap-4 justify-center mb-12">
<Button variant="primary" size="lg">
Get in Touch
Lass uns sprechen
</Button>
<Button variant="secondary" size="lg">
View My Work
Projekte ansehen
</Button>
</motion.div>
{/* Scroll Indicator */}
<motion.div
variants={itemVariants}
animate={{ y: [0, 10, 0] }}
transition={{ duration: 2, repeat: Infinity }}
animate={{ y: [0, 12, 0] }}
transition={{ duration: 2, repeat: Infinity, ease: 'easeInOut' }}
className="flex justify-center"
>
<ArrowDown className="text-green-500" size={32} />
@@ -1,49 +1,54 @@
import React from 'react';
import { motion } from 'framer-motion';
import React, { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { Menu, X } from 'lucide-react';
import { useNavigation } from '../hooks/useNavigation';
import { useScrollToSection } from '../../../shared/hooks/useScrollToSection';
import Button from '../../../shared/components/Button';
const navItems = [
{ id: 'home', label: 'About' },
{ id: 'skills', label: 'Skills' },
{ id: 'projects', label: 'Projects' },
{ id: 'experience', label: 'Experience' },
{ id: 'contact', label: 'Contact' },
{ id: 'home', label: 'Über mich' },
{ id: 'skills', label: 'Fähigkeiten' },
{ id: 'projects', label: 'Projekte' },
{ id: 'experience', label: 'Erfahrung' },
{ id: 'contact', label: 'Kontakt' },
];
export const Navigation: React.FC = () => {
const [isOpen, setIsOpen] = useState(false);
const { activeSection, isScrolled } = useNavigation();
const { scrollToSection } = useScrollToSection();
const handleNavClick = (id: string) => {
setIsOpen(false);
scrollToSection(id);
};
return (
<motion.nav
initial={{ y: -100 }}
initial={{ y: -120 }}
animate={{ y: 0 }}
transition={{ duration: 0.5 }}
transition={{ duration: 0.45, ease: 'easeOut' }}
className={`fixed top-0 w-full z-50 transition-all duration-300 ${
isScrolled
? 'bg-black/80 backdrop-blur-md border-b border-green-500/20'
? 'bg-black/90 backdrop-blur-xl border-b border-green-500/20 shadow-lg shadow-emerald-500/5'
: 'bg-transparent'
}`}
>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
{/* Logo */}
<motion.div
whileHover={{ scale: 1.05 }}
className="text-2xl font-bold text-green-500 cursor-pointer"
onClick={() => scrollToSection('home')}
onClick={() => handleNavClick('home')}
>
&lt;/&gt; Alex
&lt;/&gt; Robert Bretz
</motion.div>
{/* Nav Items */}
<div className="hidden md:flex gap-8">
{navItems.map((item) => (
<motion.button
key={item.id}
onClick={() => scrollToSection(item.id)}
onClick={() => handleNavClick(item.id)}
className={`text-sm font-medium transition-colors duration-300 pb-2 border-b-2 ${
activeSection === item.id
? 'text-green-500 border-green-500'
@@ -57,12 +62,51 @@ export const Navigation: React.FC = () => {
))}
</div>
{/* CTA Button */}
<Button variant="primary" size="sm">
Hire Me
</Button>
<div className="flex items-center gap-3">
<div className="hidden md:block">
<Button variant="primary" size="sm">
Anfrage
</Button>
</div>
<button
type="button"
aria-label="Open mobile menu"
className="md:hidden p-2 rounded-full border border-green-500/20 bg-green-500/10 text-green-400 hover:text-white hover:border-green-500 transition-all"
onClick={() => setIsOpen((prev) => !prev)}
>
{isOpen ? <X size={22} /> : <Menu size={22} />}
</button>
</div>
</div>
</div>
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
className="md:hidden bg-black/95 border-t border-green-500/20"
>
<div className="px-6 py-6 space-y-4">
{navItems.map((item) => (
<button
key={item.id}
onClick={() => handleNavClick(item.id)}
className={`w-full text-left text-lg font-medium px-4 py-3 rounded-xl transition-colors duration-300 ${
activeSection === item.id
? 'bg-green-500/15 text-green-400'
: 'text-gray-300 hover:bg-white/5 hover:text-white'
}`}
>
{item.label}
</button>
))}
</div>
</motion.div>
)}
</AnimatePresence>
</motion.nav>
);
};
@@ -12,58 +12,58 @@ interface ProjectCardProps {
export const ProjectCard: React.FC<ProjectCardProps> = ({ project, index }) => {
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
layout
initial={{ opacity: 0, y: 22 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
whileHover={{ y: -10 }}
className="group rounded-xl overflow-hidden border border-green-500/30 bg-gradient-to-br from-green-500/5 to-emerald-500/5 backdrop-blur-sm hover:border-green-500/60 transition-all duration-300"
transition={{ duration: 0.45, delay: index * 0.08, ease: 'easeOut' }}
whileHover={{ y: -8, scale: 1.01 }}
className="group rounded-3xl overflow-hidden border border-green-500/25 bg-gradient-to-br from-green-500/5 to-emerald-500/5 backdrop-blur-sm hover:border-green-500/55 transition-all duration-300 shadow-[0_20px_60px_-40px_rgba(34,197,94,0.8)]"
>
{/* Image */}
<div className="relative h-64 overflow-hidden bg-gradient-to-br from-gray-900 to-black">
<img
src={project.image}
alt={project.title}
className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-500 ease-out"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/80 to-transparent"></div>
<div className="absolute inset-0 bg-gradient-to-t from-black/85 to-transparent"></div>
</div>
{/* Content */}
<div className="p-6">
{/* Category Badge */}
<div className="inline-block mb-4 px-3 py-1 rounded-full bg-green-500/20 border border-green-500/50">
<div className="inline-flex items-center gap-2 mb-4 px-3 py-1 rounded-full bg-green-500/15 border border-green-500/25">
<span className="text-green-400 text-xs font-semibold">{project.category}</span>
</div>
<h3 className="text-xl font-bold text-white mb-2">{project.title}</h3>
<p className="text-gray-400 text-sm mb-4 line-clamp-2">{project.description}</p>
<h3 className="text-2xl font-bold text-white mb-3">{project.title}</h3>
<p className="text-gray-400 text-sm mb-5 line-clamp-3">{project.description}</p>
{/* Tags */}
<div className="flex flex-wrap gap-2 mb-6">
{project.tags.slice(0, 3).map((tag) => (
<span
key={tag}
className="text-xs px-2 py-1 rounded border border-green-500/30 text-green-400"
className="text-xs px-2 py-1 rounded-full border border-green-500/25 text-green-300 bg-white/5"
>
{tag}
</span>
))}
{project.tags.length > 3 && (
<span className="text-xs px-2 py-1 text-gray-500">
<span className="text-xs px-2 py-1 rounded-full text-gray-400 bg-gray-900/40">
+{project.tags.length - 3}
</span>
)}
</div>
{/* Links */}
<div className="flex gap-3">
<div className="flex flex-wrap gap-3">
{project.link && (
<motion.a
href={project.link}
whileHover={{ scale: 1.1 }}
target="_blank"
rel="noreferrer"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
className="flex items-center gap-2 px-4 py-2 rounded-lg bg-green-500/20 hover:bg-green-500/30 text-green-400 transition-colors text-sm font-medium"
className="inline-flex items-center gap-2 px-4 py-2 rounded-2xl bg-green-500/20 hover:bg-green-500/30 text-green-300 transition-colors text-sm font-medium"
>
<ExternalLink size={16} />
Live
@@ -72,9 +72,11 @@ export const ProjectCard: React.FC<ProjectCardProps> = ({ project, index }) => {
{project.github && (
<motion.a
href={project.github}
whileHover={{ scale: 1.1 }}
target="_blank"
rel="noreferrer"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
className="flex items-center gap-2 px-4 py-2 rounded-lg border border-green-500/30 hover:border-green-500/60 text-gray-300 hover:text-white transition-colors text-sm font-medium"
className="inline-flex items-center gap-2 px-4 py-2 rounded-2xl border border-green-500/25 hover:border-green-500/50 text-gray-300 hover:text-white transition-colors text-sm font-medium"
>
<FaGithub size={16} />
Code
@@ -5,12 +5,12 @@ import { ProjectCard } from './ProjectCard';
import AnimatedSection from '../../../shared/components/AnimatedSection';
import type { Project } from '../../../shared/types';
type Category = 'All' | 'Web Apps' | 'UI Components' | 'Full Stack';
type Category = 'Alle' | 'Webanwendungen' | 'UI-Komponenten' | 'Fullstack';
export const ProjectsSection: React.FC = () => {
const [selectedCategory, setSelectedCategory] = useState<Category>('All');
const [selectedCategory, setSelectedCategory] = useState<Category>('Alle');
const categories: Category[] = ['All', 'Web Apps', 'UI Components', 'Full Stack'];
const categories: Category[] = ['Alle', 'Webanwendungen', 'UI-Komponenten', 'Fullstack'];
const filteredProjects = projectsData.filter(
(project: Project) =>
@@ -29,14 +29,14 @@ export const ProjectsSection: React.FC = () => {
transition={{ duration: 0.5 }}
className="inline-block px-4 py-2 rounded-full border border-green-500/50 bg-green-500/10 mb-6"
>
<span className="text-green-400 text-sm font-medium">My Work</span>
<span className="text-green-400 text-sm font-medium">Meine Projekte</span>
</motion.div>
<h2 className="text-4xl sm:text-5xl font-bold text-white mb-4">
Featured Projects
Ausgewählte Projekte
</h2>
<p className="text-gray-400 text-lg max-w-2xl mx-auto">
Showcasing my best work and achievements
Eine Auswahl meiner besten Lösungen und Erfolge
</p>
</div>
@@ -3,34 +3,34 @@ import type { Project } from '../../../shared/types';
export const projectsData: Project[] = [
{
id: '1',
title: 'E-Commerce Platform',
title: 'Order Flow Microservice Suite',
description:
'Full-stack e-commerce platform with product catalog, shopping cart, and payment integration using Stripe',
image: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=800&h=600&fit=crop',
tags: ['React', 'Next.js', 'TypeScript', 'Tailwind CSS', 'MongoDB'],
category: 'Full Stack',
'Skalierbare Auftragsverwaltung mit .NET, SQL, Docker und SQS für robuste, ereignisgesteuerte Commerce-Flows.',
image: 'https://images.unsplash.com/photo-1498050108023-c5249f4df085?w=800&h=600&fit=crop',
tags: ['.NET', 'Docker', 'SQL', 'SQS', 'Clean Architecture'],
category: 'Fullstack',
link: '#',
github: '#',
},
{
id: '2',
title: 'Task Management Dashboard',
title: 'Design System Engine',
description:
'A collaborative task management application with real-time updates, user authentication, and advanced filtering',
image: 'https://images.unsplash.com/photo-1552664730-d307ca884978?w=800&h=600&fit=crop',
tags: ['React', 'Firebase', 'TypeScript', 'Tailwind CSS'],
category: 'Web Apps',
'Wiederverwendbares UI-System mit React, Tailwind, Figma-Tokens und Storybook für teamübergreifende Konsistenz.',
image: 'https://images.unsplash.com/photo-1519389950473-47ba0277781c?w=800&h=600&fit=crop',
tags: ['React', 'Tailwind CSS', 'Figma', 'Storybook'],
category: 'UI-Komponenten',
link: '#',
github: '#',
},
{
id: '3',
title: 'Component Library',
title: 'Performance Platform',
description:
'A comprehensive reusable component library with Storybook documentation and design system tokens',
image: 'https://images.unsplash.com/photo-1517694712202-14dd9538aa97?w=800&h=600&fit=crop',
tags: ['React', 'Storybook', 'Tailwind CSS', 'TypeScript'],
category: 'UI Components',
'Leistungsstarkes Backend mit Node.js, Fastify, NestJS und Docker, optimiert für schnelle Deployments und Observability.',
image: 'https://images.unsplash.com/photo-1504384308090-c894fdcc538d?w=800&h=600&fit=crop',
tags: ['Node.js', 'Fastify', 'NestJS', 'Docker', 'Linux'],
category: 'Webanwendungen',
link: '#',
github: '#',
},
@@ -4,7 +4,7 @@ import { iconMap } from '../data/skillsData';
import type { Skill } from '../../../shared/types';
interface SkillCardProps {
skill: Skill;
skill: Skill & { iconName: keyof typeof iconMap };
index: number;
}
@@ -23,44 +23,41 @@ export const SkillCard: React.FC<SkillCardProps> = ({ skill, index }) => {
Beginner: 'bg-blue-500/20',
};
// Get icon from the mapped skill name
const IconComponent = iconMap[skill.name as keyof typeof iconMap];
const IconComponent = iconMap[skill.iconName];
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
layout
initial={{ opacity: 0, y: 24 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
whileHover={{ scale: 1.05, y: -10 }}
className="p-6 rounded-xl border border-green-500/30 bg-gradient-to-br from-green-500/5 to-emerald-500/5 backdrop-blur-sm hover:border-green-500/60 transition-all duration-300"
transition={{ duration: 0.45, delay: index * 0.08, ease: 'easeOut' }}
whileHover={{ scale: 1.025, y: -6 }}
className="p-6 rounded-3xl border border-green-500/25 bg-gradient-to-br from-green-500/5 to-emerald-500/5 backdrop-blur-sm hover:border-green-500/60 transition-all duration-300 shadow-[0_20px_60px_-40px_rgba(34,197,94,0.75)]"
>
<div className="flex items-start justify-between mb-4">
<div className="p-3 rounded-lg bg-green-500/20">
<div className="p-3 rounded-2xl bg-green-500/15">
{IconComponent && <IconComponent className="text-green-500" size={24} />}
</div>
<span
className={`text-xs font-semibold px-3 py-1 rounded-full ${levelBg[skill.level]}`}
>
<span className={`text-xs font-semibold px-3 py-1 rounded-full ${levelBg[skill.level]}`}>
<span className={levelColors[skill.level]}>{skill.level}</span>
</span>
</div>
<h3 className="text-lg font-bold text-white mb-2">{skill.name}</h3>
<h3 className="text-lg font-bold text-white mb-3">{skill.name}</h3>
<div className="space-y-3">
{/* Progress Bar */}
<div className="flex items-center justify-between text-sm">
<span className="text-gray-400">Proficiency</span>
<span className="text-gray-400">Experience</span>
<span className="text-green-400 font-medium">{skill.years}+ yrs</span>
</div>
<div className="h-2 bg-gray-700 rounded-full overflow-hidden">
<div className="h-2 bg-gray-800 rounded-full overflow-hidden">
<motion.div
initial={{ width: 0 }}
whileInView={{ width: `${(skill.years / 5) * 100}%` }}
whileInView={{ width: `${Math.min((skill.years / 5) * 100, 100)}%` }}
viewport={{ once: true }}
transition={{ duration: 1, delay: index * 0.1 + 0.3 }}
transition={{ duration: 0.9, delay: index * 0.1 + 0.2 }}
className="h-full bg-gradient-to-r from-green-500 to-emerald-500"
/>
</div>
@@ -4,12 +4,27 @@ import { skillsData } from '../data/skillsData';
import { SkillCard } from './SkillCard';
import AnimatedSection from '../../../shared/components/AnimatedSection';
type Category = 'All' | 'Frontend' | 'Backend' | 'Tools' | 'Design';
type Category =
| 'Alle'
| 'Frontend'
| 'Backend'
| 'Tools'
| 'Design'
| 'Architektur'
| 'Kreativ';
export const SkillsSection: React.FC = () => {
const [selectedCategory, setSelectedCategory] = useState<Category>('All');
const [selectedCategory, setSelectedCategory] = useState<Category>('Alle');
const categories: Category[] = ['All', 'Frontend', 'Backend', 'Tools', 'Design'];
const categories: Category[] = [
'Alle',
'Frontend',
'Backend',
'Tools',
'Design',
'Architektur',
'Kreativ',
];
const filteredSkills = skillsData.filter(
(skill) => selectedCategory === 'All' || skill.category === selectedCategory
@@ -27,14 +42,14 @@ export const SkillsSection: React.FC = () => {
transition={{ duration: 0.5 }}
className="inline-block px-4 py-2 rounded-full border border-green-500/50 bg-green-500/10 mb-6"
>
<span className="text-green-400 text-sm font-medium">My Expertise</span>
<span className="text-green-400 text-sm font-medium">Meine Expertise</span>
</motion.div>
<h2 className="text-4xl sm:text-5xl font-bold text-white mb-4">
Skills & Technologies
Fähigkeiten & Technologien
</h2>
<p className="text-gray-400 text-lg max-w-2xl mx-auto">
A comprehensive overview of my technical skills and proficiency levels
Ein Überblick über meine technischen Fähigkeiten und Erfahrungsstufen.
</p>
</div>
+146 -56
View File
@@ -6,20 +6,40 @@ import {
GitBranch,
Wind,
Package,
PenTool,
Layers,
Terminal,
Box,
FileText,
Gamepad,
ShieldCheck,
} from 'lucide-react';
import type { Skill } from '../../../shared/types';
export const iconMap = {
'React.js': Code,
'Vue.js': Code,
'JavaScript': Zap,
'TypeScript': Code,
'Next.js': Package,
'Node.js': Database,
'REST APIs': Code,
'Git & GitHub': GitBranch,
'Responsive Design': Layout,
'Figma': Wind,
'Tailwind CSS': Wind,
'CSS': Layout,
'.NET': ShieldCheck,
'Node.js': Database,
'Express.js': Zap,
'Fastify': Box,
'NestJS': Layers,
'SQL / SQS': Database,
'Git & GitHub': GitBranch,
'Docker': Box,
'Linux': Terminal,
'Clean Architecture': Layers,
'Vertical Slice Architecture': Layers,
'Design Patterns': Layout,
'Figma': PenTool,
'Unity': Gamepad,
'Blender': Package,
'Godot': Package,
'LaTeX': FileText,
};
export const skillsData: Array<Omit<Skill, 'icon'> & { iconName: keyof typeof iconMap }> = [
@@ -27,70 +47,140 @@ export const skillsData: Array<Omit<Skill, 'icon'> & { iconName: keyof typeof ic
name: 'React.js',
iconName: 'React.js',
level: 'Expert',
years: 3,
years: 4,
category: 'Frontend',
},
{
name: 'JavaScript',
iconName: 'JavaScript',
level: 'Expert',
years: 4,
name: 'Vue.js',
iconName: 'Vue.js',
level: 'Advanced',
years: 3,
category: 'Frontend',
},
{
name: 'TypeScript',
iconName: 'TypeScript',
level: 'Advanced',
years: 2,
category: 'Frontend',
},
{
name: 'Next.js',
iconName: 'Next.js',
level: 'Advanced',
years: 2,
category: 'Frontend',
},
{
name: 'Node.js',
iconName: 'Node.js',
level: 'Intermediate',
years: 2,
category: 'Backend',
},
{
name: 'REST APIs',
iconName: 'REST APIs',
level: 'Advanced',
years: 3,
category: 'Backend',
},
{
name: 'Git & GitHub',
iconName: 'Git & GitHub',
level: 'Advanced',
years: 4,
category: 'Tools',
},
{
name: 'Responsive Design',
iconName: 'Responsive Design',
level: 'Expert',
years: 3,
category: 'Design',
},
{
name: 'Figma',
iconName: 'Figma',
level: 'Intermediate',
years: 2,
category: 'Design',
years: 4,
category: 'Frontend',
},
{
name: 'Tailwind CSS',
iconName: 'Tailwind CSS',
level: 'Expert',
years: 3,
years: 4,
category: 'Frontend',
},
{
name: '.NET',
iconName: '.NET',
level: 'Advanced',
years: 3,
category: 'Backend',
},
{
name: 'Express.js',
iconName: 'Express.js',
level: 'Advanced',
years: 3,
category: 'Backend',
},
{
name: 'Fastify',
iconName: 'Fastify',
level: 'Advanced',
years: 2,
category: 'Backend',
},
{
name: 'NestJS',
iconName: 'NestJS',
level: 'Advanced',
years: 2,
category: 'Backend',
},
{
name: 'SQL / SQS',
iconName: 'SQL / SQS',
level: 'Advanced',
years: 3,
category: 'Backend',
},
{
name: 'Clean Architecture',
iconName: 'Clean Architecture',
level: 'Advanced',
years: 3,
category: 'Architektur',
},
{
name: 'Vertical Slice Architecture',
iconName: 'Vertical Slice Architecture',
level: 'Advanced',
years: 3,
category: 'Architektur',
},
{
name: 'Design Patterns',
iconName: 'Design Patterns',
level: 'Advanced',
years: 4,
category: 'Architektur',
},
{
name: 'Docker',
iconName: 'Docker',
level: 'Advanced',
years: 4,
category: 'Tools',
},
{
name: 'Git & GitHub',
iconName: 'Git & GitHub',
level: 'Expert',
years: 5,
category: 'Tools',
},
{
name: 'Linux',
iconName: 'Linux',
level: 'Advanced',
years: 4,
category: 'Tools',
},
{
name: 'Figma',
iconName: 'Figma',
level: 'Advanced',
years: 3,
category: 'Design',
},
{
name: 'Unity',
iconName: 'Unity',
level: 'Intermediate',
years: 2,
category: 'Kreativ',
},
{
name: 'Blender',
iconName: 'Blender',
level: 'Intermediate',
years: 2,
category: 'Kreativ',
},
{
name: 'Godot',
iconName: 'Godot',
level: 'Intermediate',
years: 2,
category: 'Kreativ',
},
{
name: 'LaTeX',
iconName: 'LaTeX',
level: 'Intermediate',
years: 3,
category: 'Kreativ',
},
];