diff --git a/src/components/FeatureCardsGrid.tsx b/src/components/FeatureCardsGrid.tsx new file mode 100644 index 0000000..d8a6e4e --- /dev/null +++ b/src/components/FeatureCardsGrid.tsx @@ -0,0 +1,58 @@ +import type { Service } from '../data/Service'; + +interface FeatureCardsGridProps { + featureCards: Service[]; +} + +export default function FeatureCardsGrid({ featureCards }: FeatureCardsGridProps) { + return ( +
+

My Areas of Expertise

+ +
+ {featureCards.map((card, index) => { + const IconComponent = card.icon; + const cardId = card.title.toLowerCase().replaceAll(/\s+/g, '-'); + return ( +
+
+
+
+

+ {card.description} +

+
+ + {/* Status indicator for screen readers */} +
+ Expertise area {index + 1} of {featureCards.length} +
+
+ ); + })} +
+
+ ); +} diff --git a/src/components/sections/AboutSection.tsx b/src/components/sections/AboutSection.tsx index 2ada3d9..faf3f93 100644 --- a/src/components/sections/AboutSection.tsx +++ b/src/components/sections/AboutSection.tsx @@ -1,5 +1,6 @@ import { Code, Palette, ShieldCheck, Eye } from 'lucide-react'; import { useLanguage } from '../../contexts/LanguageContext'; +import FeatureCardsGrid from '../FeatureCardsGrid'; import type { Service } from '../../data/Service'; import saschaImage from '../../assets/sascha.png'; @@ -28,7 +29,7 @@ export default function AboutSection(props: AboutSectionProps = {}) { icon: [Code, Palette, ShieldCheck, Eye][index] || Code, title: card.title, description: card.description, - colorClass: ["primary", "secondary", "tertiary", "quaternary"][index] || "primary" + colorClass: (["primary", "secondary", "tertiary", "quaternary"][index] || "primary") as "primary" | "secondary" | "tertiary" | "quaternary" })) } = props; @@ -79,54 +80,7 @@ export default function AboutSection(props: AboutSectionProps = {}) { {/* Feature Cards Grid */} -
-

My Areas of Expertise

- -
- {featureCards.map((card, index) => { - const IconComponent = card.icon; - const cardId = card.title.toLowerCase().replaceAll(/\s+/g, '-'); - return ( -
-
-
-
-

- {card.description} -

-
- - {/* Status indicator for screen readers */} -
- Expertise area {index + 1} of {featureCards.length} -
-
- ); - })} -
-
+ ); diff --git a/src/components/sections/CertificationsSection.tsx b/src/components/sections/CertificationsSection.tsx index a04aea4..36c4640 100644 --- a/src/components/sections/CertificationsSection.tsx +++ b/src/components/sections/CertificationsSection.tsx @@ -1,5 +1,6 @@ import { Award } from 'lucide-react'; import { useLanguage } from '../../contexts/LanguageContext'; +import { certificationsData } from '../../config/certifications-config'; import type { Certification } from '../../data/Certification'; interface CertificationsSectionProps { @@ -17,12 +18,7 @@ export default function CertificationsSection(props: CertificationsSectionProps const { title = texts.title, subtitle = texts.subtitle, - certifications = texts.certificationItems.map((cert, index) => ({ - name: cert.name, - issuer: cert.issuer, - year: ["2025", "2025", "2020", "2020", "2015"][index] || "2025", - icon: "" - })) + certifications = certificationsData } = props; // Sort certifications by year in descending order (newest first) diff --git a/src/config/certifications-config.ts b/src/config/certifications-config.ts new file mode 100644 index 0000000..b58b17d --- /dev/null +++ b/src/config/certifications-config.ts @@ -0,0 +1,46 @@ +import { certifications } from './locales/en/certifications'; +import type { Certification } from '../data/Certification'; + +const getCertificationText = (id: number) => { + const item = certifications.certificationItems.find(c => c.id === id); + if (!item) throw new Error(`Certification with id ${id} not found`); + return item; +}; + +export const certificationsData: Certification[] = [ + { + id: 1, + name: getCertificationText(1).name, + issuer: getCertificationText(1).issuer, + year: '2025', + icon: '', + }, + { + id: 2, + name: getCertificationText(2).name, + issuer: getCertificationText(2).issuer, + year: '2025', + icon: '', + }, + { + id: 3, + name: getCertificationText(3).name, + issuer: getCertificationText(3).issuer, + year: '2020', + icon: '', + }, + { + id: 4, + name: getCertificationText(4).name, + issuer: getCertificationText(4).issuer, + year: '2020', + icon: '', + }, + { + id: 5, + name: getCertificationText(5).name, + issuer: getCertificationText(5).issuer, + year: '2015', + icon: '', + }, +].sort((a, b) => Number.parseInt(b.year) - Number.parseInt(a.year)); diff --git a/src/config/locales/de/certifications.ts b/src/config/locales/de/certifications.ts index 5227ecc..39bb08c 100644 --- a/src/config/locales/de/certifications.ts +++ b/src/config/locales/de/certifications.ts @@ -3,22 +3,27 @@ export const certifications = { subtitle: 'Meine beruflichen Qualifikationen und kontinuierliche Weiterbildung', certificationItems: [ { + id: 1, name: 'Practical Prompt Engineering Masterclass: Hands-On Learning', issuer: 'Udemy Kurs - Asif Farooqi, Abdullah Dar', }, { + id: 2, name: 'Understanding Typescript', issuer: 'Udemy Kurs - Maximilian Schwarzmüller', }, { + id: 3, name: 'Angular Step by Step', issuer: 'Udemy Kurs - Shivprasad Koirala', }, { + id: 4, name: 'Angular and Typescript', issuer: 'LinkedIn TestDome', }, { + id: 5, name: 'Bachelor of Science in Informatik', issuer: 'TU Darmstadt', }, diff --git a/src/config/locales/en/certifications.ts b/src/config/locales/en/certifications.ts index 5591266..7b9db80 100644 --- a/src/config/locales/en/certifications.ts +++ b/src/config/locales/en/certifications.ts @@ -3,22 +3,27 @@ export const certifications = { subtitle: 'My professional qualifications and continuous learning', certificationItems: [ { + id: 1, name: 'Practical Prompt Engineering Masterclass: Hands-On Learning', issuer: 'Udemy Lecture - Asif Farooqi, Abdullah Dar', }, { + id: 2, name: 'Understanding Typescript', issuer: 'Udemy Lecture - Maximilian Schwarzmüller', }, { + id: 3, name: 'Angular Step by Step', issuer: 'Udemy Lecture - Shivprasad Koirala', }, { + id: 4, name: 'Angular and Typescript', issuer: 'LinkedIn TestDome', }, { + id: 5, name: 'Bachelor of Science in Computer Science', issuer: 'TU Darmstadt', },