feat: add projects component
- add projects section to data.json - add projects types - add css variables - update headline styles - rename intro to profile
This commit is contained in:
@@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
div {
|
div {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
color: var(--color-text-secondary);
|
color: var(--color-text-tertiary);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Intro } from '$lib/types/data';
|
import type { Profile } from '$lib/types/data';
|
||||||
import profileImage from '$lib/assets/images/profile_picture.png';
|
import profileImage from '$lib/assets/images/profile_picture.png';
|
||||||
|
|
||||||
let { name, title, text }: Intro = $props();
|
let { name, title, anchorId, text }: Profile = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section>
|
<section id={anchorId}>
|
||||||
<div>
|
<div>
|
||||||
<div class="image-wrapper">
|
<div class="image-wrapper">
|
||||||
<img src={profileImage} alt="">
|
<img src={profileImage} alt="">
|
||||||
</div>
|
</div>
|
||||||
<h1>{name}</h1>
|
<h1>{name}</h1>
|
||||||
<h2>{title}</h2>
|
<p class="title">{title}</p>
|
||||||
<p>{text}</p>
|
<p class="text">{text}</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
div {
|
div {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: stretch;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
|
||||||
@@ -65,11 +65,7 @@
|
|||||||
margin: unset;
|
margin: unset;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
font-size: 2.25rem;
|
font-size: 2.25rem;
|
||||||
background-image: linear-gradient(
|
background-image: var(--color-headline-background-image);
|
||||||
to right,
|
|
||||||
var(--color-intro-subtitle-text-primary) 0%,
|
|
||||||
var(--color-intro-subtitle-text-secondary) 60%,
|
|
||||||
var(--color-intro-subtitle-text-tertiary) 100%);
|
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
@@ -77,7 +73,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
.title {
|
||||||
|
|
||||||
margin: unset;
|
margin: unset;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
@@ -89,7 +85,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
.text {
|
||||||
margin: unset;
|
margin: unset;
|
||||||
color: var(--color-intro-text);
|
color: var(--color-intro-text);
|
||||||
font-size: 1.125rem;
|
font-size: 1.125rem;
|
||||||
20
src/lib/components/ProjectEntry.svelte
Normal file
20
src/lib/components/ProjectEntry.svelte
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { ProjectEntry } from '$lib/types/data';
|
||||||
|
|
||||||
|
let {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
taskHeadline,
|
||||||
|
tasks,
|
||||||
|
toolsHeadline,
|
||||||
|
tools
|
||||||
|
}: ProjectEntry = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
63
src/lib/components/Projects.svelte
Normal file
63
src/lib/components/Projects.svelte
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { Projects } from '$lib/types/data';
|
||||||
|
import ProjectEntry from '$lib/components/ProjectEntry.svelte';
|
||||||
|
|
||||||
|
let { title, anchorId, subtitle, entries }: Projects = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section id={anchorId}>
|
||||||
|
<h2>{title}</h2>
|
||||||
|
{#if (subtitle)}
|
||||||
|
<p>{subtitle}</p>
|
||||||
|
{/if}
|
||||||
|
<div>
|
||||||
|
{#each entries as entry, i (i)}
|
||||||
|
<ProjectEntry {...entry} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 5rem 1rem;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
padding: 6rem 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: unset;
|
||||||
|
|
||||||
|
font-size: 1.875rem;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
color: transparent;
|
||||||
|
background-image: var(--color-headline-background-image);
|
||||||
|
background-clip: text;
|
||||||
|
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
font-size: 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: unset;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
|
font-size: 1.125rem;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -26,9 +26,93 @@
|
|||||||
},
|
},
|
||||||
"copyright": "© 2026 Adrian Fennert. Alle Rechte vorbehalten."
|
"copyright": "© 2026 Adrian Fennert. Alle Rechte vorbehalten."
|
||||||
},
|
},
|
||||||
"intro": {
|
"profile": {
|
||||||
"name": "Adrian Fennert",
|
"name": "Adrian Fennert",
|
||||||
"title": "Senior Fullstack Engineer",
|
"title": "Senior Fullstack Engineer",
|
||||||
|
"anchorId": "profile",
|
||||||
"text": "Erfahrener Full-Stack Developer mit Fokus auf moderne Web-Technologien. Spezialisiert auf skalierbare Anwendungen, Teamführung und Integration komplexer Systeme. Leidenschaft für sauberen Code und benutzerzentrierte Lösungen."
|
"text": "Erfahrener Full-Stack Developer mit Fokus auf moderne Web-Technologien. Spezialisiert auf skalierbare Anwendungen, Teamführung und Integration komplexer Systeme. Leidenschaft für sauberen Code und benutzerzentrierte Lösungen."
|
||||||
|
},
|
||||||
|
"projects": {
|
||||||
|
"title": "Projekte",
|
||||||
|
"anchorId": "projects",
|
||||||
|
"subtitle": "Aktuelle und Vergangenne Projekte and denen ich erfolgreich mitgewirkt habe",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"title": "Custom Frontend für GPT-Anwendung mit Dokumentenverwaltung",
|
||||||
|
"description": "Entwicklung einer modernen Single-Page-Application für die interne KI-Nutzung mit umfassender Dokumentenverwaltung.",
|
||||||
|
"taskHeadline": "Tätigkeiten",
|
||||||
|
"tasks": "Konzeption und Implementierung benutzerspezifischer Dokument-Kollektionen, Integration von MSAL für SSO.",
|
||||||
|
"toolsHeadline": "Tools",
|
||||||
|
"tools": [
|
||||||
|
"Next.JS",
|
||||||
|
"assistant-ui",
|
||||||
|
"Microsoft Authentication Library",
|
||||||
|
"Typescript",
|
||||||
|
"Model Context Protocol - MCP"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "B2B-Customer-Portal Erweiterung",
|
||||||
|
"description": "Erweiterung eines Portals für Produktregistrierungen und Garantieabwicklungen.",
|
||||||
|
"taskHeadline": "Tätigkeiten",
|
||||||
|
"tasks": "Umsetzung kundenspezifischer Prozesse, Optimierung der User Journeys in Zusammenarbeit mit Fachbereichen.",
|
||||||
|
"toolsHeadline": "Tools",
|
||||||
|
"tools": [
|
||||||
|
"SAP Commerce Cloud",
|
||||||
|
"SAP Composable Storefront",
|
||||||
|
"Smartedit",
|
||||||
|
"Angular",
|
||||||
|
"Typescript"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Frontend Lead für B2B-Portal",
|
||||||
|
"description": "Fachliche Führung und Entwicklung eines Customer-Portals.",
|
||||||
|
"taskHeadline": "Tätigkeiten",
|
||||||
|
"tasks": "Coaching des Teams, Know-how-Aufbau in Angular und Spartacus, Integration von Such- und IAM-Diensten.",
|
||||||
|
"toolsHeadline": "Tools",
|
||||||
|
"tools": [
|
||||||
|
"SAP Commerce Cloud",
|
||||||
|
"SAP Composable Storefront",
|
||||||
|
"Smartedit",
|
||||||
|
"Angular",
|
||||||
|
"Typescript",
|
||||||
|
"Keyloak",
|
||||||
|
"Coveo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Backend-Migrationen und Testframework upgrades",
|
||||||
|
"description": "Migration von Testumgebungen und Integrations-Frameworks.",
|
||||||
|
"taskHeadline": "Tätigkeiten",
|
||||||
|
"tasks": "Upgrade Unit- und Integrationstests, Migration Apache Camel zu Spring Integration.",
|
||||||
|
"toolsHeadline": "Tools",
|
||||||
|
"tools": [
|
||||||
|
"SAP Commerce Cloud",
|
||||||
|
"Spring Boot",
|
||||||
|
"Spring Integration",
|
||||||
|
"SAP Integration Suite",
|
||||||
|
"Typescript",
|
||||||
|
"OData",
|
||||||
|
"SAP ERP"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Storefront-Migration zu SPA",
|
||||||
|
"description": "Rolling-Release-Migration und Neuentwicklung eines Online-Shops.",
|
||||||
|
"taskHeadline": "Tätigkeiten",
|
||||||
|
"tasks": "Integration Suchdienst und Headless CMS.",
|
||||||
|
"toolsHeadline": "Tools",
|
||||||
|
"tools": [
|
||||||
|
"SAP Commerce Cloud",
|
||||||
|
"Spring Boot",
|
||||||
|
"React",
|
||||||
|
"Next.JS",
|
||||||
|
"Typescript",
|
||||||
|
"Algolia",
|
||||||
|
"Contentful"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
--color-body-background: oklch(0.21 0.034 264.665);
|
--color-body-background: oklch(0.21 0.034 264.665);
|
||||||
|
|
||||||
--color-text-primary: oklch(0.872 0.01 258.338);
|
--color-text-primary: oklch(0.872 0.01 258.338);
|
||||||
--color-text-secondary: oklch(0.551 0.027 264.364);
|
--color-text-secondary: oklch(0.707 0.022 261.325);
|
||||||
|
--color-text-tertiary: oklch(0.551 0.027 264.364);
|
||||||
|
|
||||||
|
|
||||||
--color-header-border: oklab(0.623 -0.0378409 -0.210628 / 0.3);
|
--color-header-border: oklab(0.623 -0.0378409 -0.210628 / 0.3);
|
||||||
--color-header-background: oklab(0.21 -0.00316128 -0.0338527 / 0.95);
|
--color-header-background: oklab(0.21 -0.00316128 -0.0338527 / 0.95);
|
||||||
@@ -16,9 +18,15 @@
|
|||||||
--color-intro-image-background-secondary: oklch(0.511 0.262 276.966);
|
--color-intro-image-background-secondary: oklch(0.511 0.262 276.966);
|
||||||
--color-intro-text: oklch(0.967 0.003 264.542);
|
--color-intro-text: oklch(0.967 0.003 264.542);
|
||||||
--color-intro-title-text: oklch(0.809 0.105 251.813);
|
--color-intro-title-text: oklch(0.809 0.105 251.813);
|
||||||
--color-intro-subtitle-text-primary: oklch(0.707 0.165 254.624);
|
|
||||||
--color-intro-subtitle-text-secondary: oklch(0.673 0.182 276.935);
|
--color-headline-primary: oklch(0.707 0.165 254.624);
|
||||||
--color-intro-subtitle-text-tertiary: oklch(0.714 0.203 305.504);
|
--color-headline-secondary: oklch(0.673 0.182 276.935);
|
||||||
|
--color-headline-tertiary: oklch(0.714 0.203 305.504);
|
||||||
|
--color-headline-background-image: linear-gradient(
|
||||||
|
to right,
|
||||||
|
var(--color-headline-primary) 0%,
|
||||||
|
var(--color-headline-secondary) 60%,
|
||||||
|
var(--color-headline-tertiary) 100%);
|
||||||
|
|
||||||
--z-index-header: 50;
|
--z-index-header: 50;
|
||||||
}
|
}
|
||||||
@@ -37,4 +45,5 @@ html, body {
|
|||||||
margin: unset;
|
margin: unset;
|
||||||
background-color: var(--color-body-background);
|
background-color: var(--color-body-background);
|
||||||
font-family: 'AdwaitaSans', 'AdwaitaMono', sans-serif;
|
font-family: 'AdwaitaSans', 'AdwaitaMono', sans-serif;
|
||||||
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
export type Data = {
|
export type Data = {
|
||||||
header: Header;
|
header: Header;
|
||||||
footer: Footer;
|
footer: Footer;
|
||||||
intro: Intro;
|
profile: Profile;
|
||||||
|
projects: Projects;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Header = {
|
export type Header = {
|
||||||
@@ -24,8 +25,25 @@ export type FooterLink = {
|
|||||||
|
|
||||||
export type FooterLinkKey = 'git' | 'linkedin';
|
export type FooterLinkKey = 'git' | 'linkedin';
|
||||||
|
|
||||||
export type Intro = {
|
export type Profile = {
|
||||||
name: string;
|
name: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
anchorId: string;
|
||||||
text: string;
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Projects = {
|
||||||
|
title: string;
|
||||||
|
anchorId: string;
|
||||||
|
subtitle?: string;
|
||||||
|
entries: ProjectEntry[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ProjectEntry = {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
taskHeadline: string;
|
||||||
|
tasks: string;
|
||||||
|
toolsHeadline: string;
|
||||||
|
tools: string[];
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import content from '$lib/data/data.json';
|
import content from '$lib/data/data.json';
|
||||||
import type { Data } from '$lib/types/data';
|
import type { Data } from '$lib/types/data';
|
||||||
import Intro from '$lib/components/Intro.svelte';
|
import Profile from '$lib/components/Profile.svelte';
|
||||||
|
import Projects from '$lib/components/Projects.svelte';
|
||||||
|
|
||||||
let data: Data = content;
|
let data: Data = content;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Intro {...data.intro} />
|
<Profile {...data.profile} />
|
||||||
|
<Projects {...data.projects} />
|
||||||
Reference in New Issue
Block a user