More about me stuff

This commit is contained in:
Daniel Kluge 2022-10-20 17:48:27 +02:00
parent aa28e1a8a7
commit 4953da3aee
5 changed files with 235 additions and 50 deletions

19
data/achievements.tsx Normal file
View File

@ -0,0 +1,19 @@
import Icon from "@mdi/react";
import { mdiSeal, mdiRobotIndustrial } from "@mdi/js";
interface Achievement {
description: string;
icon: JSX.Element;
}
export const achievements = (size?: string): Achievement[] => [
{
"description": "Awarded with the Deutschlandstipendium",
"icon": <Icon path={mdiSeal} size={size || "2em"} />
}, {
"description": "Developer of the official testbed for Digital Twins in Industry 4.0 of the TU Dresden",
"icon": <Icon path={mdiRobotIndustrial} size={size || "2em"} />
}
];
export default achievements;

View File

@ -1,14 +0,0 @@
{
"cards": [
{
"title": "Web Technologies",
"skillBars": [
{
"name": "JavaScript/TypeScript",
"icons": ["FileJs", "FileTs"],
"pct": 100
}
]
}
]
}

148
data/skills.tsx Normal file
View File

@ -0,0 +1,148 @@
import Icon from "@mdi/react";
import { mdiBash, mdiLanguageCpp, mdiLanguageCsharp, mdiLanguageJava, mdiLanguageJavascript, mdiLanguagePhp, mdiLanguagePython, mdiLanguageRust, mdiLanguageTypescript, mdiReact } from "@mdi/js";
import { Android, Arduino, CssThree, Espressif, Express, Html5, Linux, Sass, Springboot, Windows } from "@icons-pack/react-simple-icons";
export interface Skill {
name: string;
icon?: JSX.Element;
pct: number;
}
export interface AdditionalSkill {
name: string;
icon?: JSX.Element;
}
export interface SkillCard {
title: string;
skillBars: Skill[];
additional?: AdditionalSkill[];
}
export interface SkillSet {
cards: SkillCard[];
additional?: AdditionalSkill[];
}
export const skills = (size?: string): SkillSet => {
return {
cards: [{
title: "Programming Languages",
skillBars: [{
name: "TypeScript",
icon: <Icon path={mdiLanguageTypescript} size={size || "2em"} />,
pct: 100
}, {
name: "JavaScript",
icon: <Icon path={mdiLanguageJavascript} size={size || "2em"} />,
pct: 100
}, {
name: "Java",
icon: <Icon path={mdiLanguageJava} size={size || "2em"} />,
pct: 80
}, {
name: "Python 3",
icon: <Icon path={mdiLanguagePython} size={size || "2em"} />,
pct: 95
}, {
name: "PHP",
icon: <Icon path={mdiLanguagePhp} size={size || "2em"} />,
pct: 50
}, {
name: "Bash",
icon: <Icon path={mdiBash} size={size || "2em"} />,
pct: 60
}, {
name: "C/C++",
icon: <Icon path={mdiLanguageCpp} size={size || "2em"} />,
pct: 60
}, {
name: "Rust",
icon: <Icon path={mdiLanguageRust} size={size || "2em"} />,
pct: 80
}, {
name: "C#",
icon: <Icon path={mdiLanguageCsharp} size={size || "2em"} />,
pct: 40
}]
}, {
title: "Web Technologies",
skillBars: [{
name: "TypeScript",
icon: <Icon path={mdiLanguageTypescript} size={size || "2em"} />,
pct: 100
}, {
name: "JavaScript",
icon: <Icon path={mdiLanguageJavascript} size={size || "2em"} />,
pct: 100
}, {
name: "React",
icon: <Icon path={mdiReact} size={size || "2em"} />,
pct: 80
}, {
name: "HTML5",
icon: <Html5 size={size || "2em"} />,
pct: 80
}, {
name: "CSS3",
icon: <CssThree size={size || "2em"} />,
pct: 90
}],
additional: [{
name: "Express",
icon: <Express size={size || "2em"} />
}, {
name: "Sass",
icon: <Sass size={size || "2em"} />
}, {
name: "Spring Boot",
icon: <Springboot size={size || "2em"} />
}]
}, {
title: "Embedded Programming",
skillBars: [{
name: "C/C++",
icon: <Icon path={mdiLanguageCpp} size={size || "2em"} />,
pct: 60
}],
additional: [{
name: "Arduino",
icon: <Arduino size={size || "2em"} />
}, {
name: "ESP",
icon: <Espressif size={size || "2em"} />
}]
}, {
title: "Operating Systems",
skillBars: [],
additional: [{
name: "Windows",
icon: <Windows size={size || "2em"} />
}, {
name: "Linux",
icon: <Linux size={size || "2em"} />
}, {
name: "Android",
icon: <Android size={size || "2em"} />
}]
}, {
title: "Languages",
skillBars: [{
name: "German (native)",
icon: <span style={{ fontSize: size || "2em" }}>🇩🇪</span>,
pct: 100
}, {
name: "English (C1)",
icon: <span style={{ fontSize: size || "2em" }}>🇬🇧</span>,
pct: 90
}, {
name: "Russian (basics)",
icon: <span style={{ fontSize: size || "2em", fontFamily: "Arial" }}>🇷🇺</span>,
pct: 30
}],
additional: []
}]
};
};
export default skills;

View File

@ -1,56 +1,57 @@
import type { NextPage } from "next";
import { useEffect } from "react";
import Layout from "../components/Blog/Layout";
import * as phosphorIcons from "phosphor-react";
import styles from "../styles/Blog/AboutMe.module.scss";
import skills from "../data/skills.json";
interface Skill {
name: string;
icons: string[];
pct: number;
}
import skills, { AdditionalSkill, Skill, SkillCard } from "../data/skills";
import achievements from "../data/achievements";
interface AdditionalSkills {
name: string;
icon: string;
}
interface SkillCard {
title: string;
skillBars: Skill[];
additional?: AdditionalSkills[];
}
interface SkillSet {
cards: SkillCard[];
additional: AdditionalSkills[];
}
const getIcon = (iconName: string, key?: number) => {
const Icon = phosphorIcons[iconName as keyof typeof phosphorIcons] as any;
if (!Icon) return null;
else return <Icon key={key} />;
const Badge: NextPage<{ additional: AdditionalSkill }> = ({ additional }) => {
return <div className={styles.badge}>
{additional.icon || null} {additional.name}
</div>;
};
const SkillBar: NextPage<{ skill: Skill }> = ({ skill }) => {
return <div className={styles.bar}>
<div className={styles.barName}>{skill.name}{skill.icons.map(getIcon)}</div>
<div className={styles.barPct}>{skill.pct}%</div>
return <div className={styles.skillBar}>
<div className={styles.barName}>{skill.name}{skill.icon || null}</div>
<div className={styles.percentBar} style={{"--barPct": skill.pct + "%"} as React.CSSProperties}>
<div className={`${styles.front} vpAnimated`}></div>
</div>
</div>;
};
const SkillCard: NextPage<{ card: SkillCard }> = ({ card }) => {
return <div className={styles.card}>
<h3>{card.title}</h3>
{card.skillBars.map((skill, i) =>
{card.skillBars.sort((bar1, bar2) => bar2.pct - bar1.pct).map((skill, i) =>
<SkillBar key={i} skill={skill} />
)}
)}<br/>
{card.additional?.map((skill, i) => <Badge additional={skill} key={i} />)}
</div>;
};
const AboutMe: NextPage = () => {
useEffect(() => {
const handleScrollAnimation = () => {
document.querySelectorAll(".vpAnimated").forEach((element) => {
const rect = element.getBoundingClientRect();
const inVp = (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
if (inVp) (element as HTMLElement).style.animationPlayState = "running";
else (element as HTMLElement).style.animationPlayState = "paused";
});
};
handleScrollAnimation(); // First time so we don't _need_ scrolling
window.addEventListener("scroll", handleScrollAnimation);
}, []);
const age = new Date().getFullYear() - 1998 - (new Date().getMonth() < 10 ? 1 : 0);
return <Layout>
@ -59,10 +60,14 @@ const AboutMe: NextPage = () => {
Hi! My name is <strong>Daniel</strong> and I&apos;m an automation engineer from Germany.
</p>
<p>
I&apos;m currently studying <strong>Information Systems Engineering</strong> at the <strong>TU Dresden</strong><br/>
Currently I&apos;m {age} years old.
I&apos;m currently {age} years old and studying <strong>Information Systems Engineering</strong> at the <strong>TU Dresden</strong>.
</p>
{skills.cards.map((card, i) => <SkillCard key={i} card={card} />)}
<h2>Achievements</h2>
{achievements().map((achievement, i) => <div key={i} className={styles.achievement}>
<span>{achievement.icon}</span><span>{achievement.description}</span>
</div>)}
<h2>Skills</h2>
{skills().cards.map((card, i) => <SkillCard key={i} card={card} />)}
</Layout>;
};

View File

@ -1,3 +1,30 @@
.preText {
font-size: 1.2em;
}
.percentBar {
position: relative;
height: 1em;
width: 100%;
border-radius: 0.5em;
border: 1px solid var(--blog_content-border);
background: transparent;
.front {
border-radius: 0.5em;
height: 100%;
position: absolute;
background: var(--blog_color-accent);
animation: barFill 2s ease-in-out;
animation-fill-mode: forwards;
}
}
@keyframes barFill {
0% {
width: 1em;
}
100% {
width: var(--barPct);
}
}