1
0
Fork 0
mirror of https://github.com/TheTaz25/denis.ergin.git synced 2025-07-07 05:08:46 +00:00

initial setup

This commit is contained in:
Denis Ergin 2024-09-17 08:55:20 +02:00
commit f29b97ac06
23 changed files with 5114 additions and 0 deletions

View file

@ -0,0 +1,81 @@
---
interface Props {
to: string
}
const { to } = Astro.props;
const currentPath = new URL(Astro.url).pathname.split('/')[1];
---
<a href={to} class={`/${currentPath}` === to ? 'current' : undefined}>
<slot />
</a>
<style lang="scss">
a {
text-decoration: none;
color: white;
font-size: larger;
position: relative;
&::before {
content: "{";
transform: translateX(-2rem);
left: 0;
position: absolute;
transition-property: transform, opacity;
transition-duration: 150ms;
transition-timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86);
}
&::after {
content: "}";
transform: translateX(2rem);
right: 0;
position: absolute;
transition-property: transform, opacity;
transition-duration: 150ms;
transition-timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86);
}
&:not(.current) {
&::after,
&::before {
opacity: 0;
}
&:hover,
&:focus-within {
&::before,
&::after {
opacity: 1;
}
&::before { transform: translateX(-1rem); }
&::after { transform: translateX(1rem); }
}
}
&.current {
&::before {
transition: transform 100ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
transform: translateX(-2rem);
}
&:hover::before,
&:focus-visible::before {
transform: translateX(-1rem);
}
&::after {
transform: translateX(2rem);
transition: transform 100ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
}
&:hover::after,
&:focus-visible::after {
transform: translateX(1rem);
}
}
}
</style>

View file

@ -0,0 +1,39 @@
---
interface Props {
title: string;
points: Array<string>;
}
const { title, points } = Astro.props;
---
<div>
<p>{title}</p>
<ul>
{ points.map((skill) => (
<li>
{skill}
</li>
))}
</ul>
</div>
<style lang="scss">
p {
text-align: center;
font-size: 1.75rem;
}
div {
width: calc(100% * 1/3);
}
ul {
list-style: none;
padding: unset;
text-align: center;
li {
font-size: 1.25rem;
padding-bottom: 0.25rem;
}
}
</style>

12
src/content/config.ts Normal file
View file

@ -0,0 +1,12 @@
import { defineCollection, z } from 'astro:content';
const skillCollection = defineCollection({
type: 'data',
schema: z.object({
skills: z.array(z.string())
}),
});
export const collections = {
'skills': skillCollection,
}

View file

@ -0,0 +1,10 @@
---
---
# Hallo Welt!
Mein Name ist Denis und ich arbeite als Frontend Engineer in Karlsruhe!
Diese Website hat aktuell nicht viel zu bieten, aber das wird sich über die Zeit verändern. Ich wurde vor kurzem als Teilzeit-Lehrkraft an der DHBW in Karlsruhe angenommen. Dort werde ich die Module Web Engineering 1 & 2 lehren. Diese Website soll unter anderem dazu dienen Inhalte zu vermitteln.
Des weiteren sollen zusätzliche Inhalte wie private Projekte, Infos zu meiner selbst und mehr hier präsentiert werden.

View file

@ -0,0 +1,14 @@
{
"skills": [
"React",
"Vue",
"TypeScript",
"PostgreSQL",
"Rust",
"Frontend",
"Backend",
"UX & UI Design",
"Copy",
"Dungeon Master"
]
}

2
src/env.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />

24
src/i18n/ui.ts Normal file
View file

@ -0,0 +1,24 @@
export const languages = {
de: 'Deutsch',
}
export const showDefaultLang = false;
export const defaultLang = 'de';
export const ui = {
de: {
'nav.home': 'Startseite',
'nav.knowledgeBase': 'Knowledge Base',
'home.welcome': 'Hallo Welt!',
'home.opening.1': 'Mein Name ist Denis und ich arbeite als Frontend Engineer in Karlsruhe!',
'home.opening.2': 'Diese Website hat aktuell nicht viel zu bieten, aber das wird sich über die Zeit verändern. Ich wurde vor kurzem als Teilzeit-Lehrkraft an der DHBW in Karlsruhe angenommen. Dort werde ich die Module Web Engineering 1 und 2 lehren. Diese Website soll unter anderem dazu dienen Inhalte zu vermitteln.',
'home.opening.3': 'Des weiteren sollen zusätzliche Inhalte wie private Projekte, Infos zu meiner selbst und mehr hier präsentiert werden.',
},
} as const;
export const routes = {
de: {
'': ''
}
} as const;

47
src/i18n/utils.ts Normal file
View file

@ -0,0 +1,47 @@
import { ui, defaultLang, showDefaultLang, routes } from './ui';
export function getLangFromUrl(url: URL) {
const [, lang] = url.pathname.split('/');
if (!lang) return defaultLang
if (lang in ui) return lang as keyof typeof ui;
return defaultLang;
}
export function useTranslations(lang: keyof typeof ui = defaultLang) {
return function t(key: keyof typeof ui[typeof defaultLang]) {
return ui[lang][key];
}
}
export function useTranslatedPath(lang: keyof typeof ui) {
return function translatePath(path: string, l: keyof typeof routes = lang) {
const pathName = path.replaceAll('/', '');
const hasTranslation = defaultLang !== l && routes[l] !== undefined && routes[l][pathName] !== undefined;
const translatedPath = hasTranslation ? '/' + routes[l][pathName] : path;
return !showDefaultLang && l === defaultLang ? translatedPath : `/${l}${path}`;
}
}
export function getRouteFromUrl(url: URL): string | undefined {
const pathname = new URL(url).pathname;
const parts = pathname?.split('/');
const path = (parts.pop() || parts.pop()) as keyof typeof routes['de'];
if (path === undefined) {
return undefined;
}
const currentLang = getLangFromUrl(url);
if (defaultLang === currentLang) {
const route = Object.values(routes)[0];
return route?.[path] !== undefined ? route[path] : undefined;
}
const getKeyByValue = (obj: Record<string, string>, value: string): string | undefined => {
return Object.keys(obj).find((key) => obj[key] === value);
};
return getKeyByValue(routes[currentLang], path);
}

1
src/icons/PersonLink.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 48 48"><path fill="currentColor" d="M24 4c-5.523 0-10 4.477-10 10s4.477 10 10 10s10-4.477 10-10S29.523 4 24 4M12.25 28A4.25 4.25 0 0 0 8 32.249V33c0 3.755 1.942 6.567 4.92 8.38c2.728 1.66 6.33 2.5 10.215 2.608A8.4 8.4 0 0 1 22 39.75c0-4.556 3.582-8.25 8-8.25h9.934A4.25 4.25 0 0 0 35.75 28zM24 39.75a6.25 6.25 0 0 1 6.25-6.25h1.5a1.25 1.25 0 1 1 0 2.5h-1.5a3.75 3.75 0 1 0 0 7.5h1.5a1.25 1.25 0 1 1 0 2.5h-1.5A6.25 6.25 0 0 1 24 39.75m22 0a6.25 6.25 0 0 0-6.25-6.25h-1.5a1.25 1.25 0 1 0 0 2.5h1.5a3.75 3.75 0 1 1 0 7.5h-1.5a1.25 1.25 0 1 0 0 2.5h1.5A6.25 6.25 0 0 0 46 39.75m-17 0c0-.69.56-1.25 1.25-1.25h9.5a1.25 1.25 0 1 1 0 2.5h-9.5c-.69 0-1.25-.56-1.25-1.25"/></svg>

After

Width:  |  Height:  |  Size: 748 B

1
src/icons/bracket.svg Normal file
View file

@ -0,0 +1 @@
<svg viewBox="0 2 36 36" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M22.25 35.32h-2.34q-2.8 0-4.55-1.56-1.73-1.55-1.73-4.49v-2.33q0-2.64-1.3-4.12-1.3-1.5-3.97-1.5h-.8v-2.44h.8q2.67 0 3.97-1.48 1.3-1.5 1.3-4.14v-2.33q0-2.94 1.73-4.49 1.75-1.56 4.55-1.56h2.34v2.16h-1.78q-2.12 0-3.1.98-.95.99-.95 3.17v2.74q0 2.17-1.2 3.66-1.2 1.46-3.34 2.32v.38q2.14.86 3.34 2.34 1.2 1.47 1.2 3.64v2.74q0 2.18.96 3.17.97.98 3.1.98h1.77z"/></svg>

After

Width:  |  Height:  |  Size: 448 B

75
src/layouts/Layout.astro Normal file
View file

@ -0,0 +1,75 @@
---
import Link from '../components/atoms/Link.astro';
import { getLangFromUrl, useTranslations } from '../i18n/utils';
interface Props {
title: string;
}
const { title } = Astro.props;
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
---
<!doctype html>
<html lang={lang}>
<head>
<meta charset="UTF-8" />
<meta name="description" content="Astro description" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<title>{title}</title>
</head>
<body>
<header>
<nav>
<Link to="/">{t('nav.home')}</Link>
<Link to="/else">{t('nav.knowledgeBase')}</Link>
</nav>
</header>
<main>
<slot />
</main>
</body>
</html>
<style is:global lang="scss">
:root {
--accent: 136, 58, 234;
--accent-light: 224, 204, 250;
--accent-dark: 49, 10, 101;
--accent-gradient: linear-gradient(
45deg,
rgb(var(--accent)),
rgb(var(--accent-light)) 30%,
white 60%
);
}
html {
font-family: system-ui, sans-serif;
background: #13151a;
color: white;
}
main {
max-width: 1200px;
margin: 0 auto;
}
code {
font-family:
Menlo,
Monaco,
Lucida Console,
Liberation Mono,
DejaVu Sans Mono,
Bitstream Vera Sans Mono,
Courier New,
monospace;
}
nav {
display: flex;
align-items: center;
justify-content: center;
gap: 4rem;
margin: 1rem 0 2rem 0;
}
</style>

7
src/pages/else.astro Normal file
View file

@ -0,0 +1,7 @@
---
import Layout from '../layouts/Layout.astro';
---
<Layout title='Somewhere else...'>
Henlo!
</Layout>

47
src/pages/index.astro Normal file
View file

@ -0,0 +1,47 @@
---
import Layout from '../layouts/Layout.astro';
import { useTranslations } from '../i18n/utils';
import '../styles/homepage-markdown.scss';
import { Icon } from 'astro-icon/components';
const t = useTranslations();
---
<Layout title="Hallo Welt!">
<div class="opening-wrapper">
<div class="row">
<Icon name="bracket" class="bracket open" height="100px" width="unset" />
<h1>{t('home.welcome')}</h1>
</div>
<p class="mb-2">
{t('home.opening.1')}
</p>
<p>
{t('home.opening.2')}
</p>
<div class="row">
<p>{t('home.opening.3')}</p>
<Icon name="bracket" class="bracket close" height="100px" width="unset" />
</div>
</div>
</Layout>
<style lang="scss">
.row {
display: flex;
align-items: center;
h1 {
font-size: xxx-large;
margin: unset;
}
}
[data-icon="bracket"].bracket {
height: 100px;
color: #555;
&.close {
transform: rotate(180deg);
}
}
</style>

View file

@ -0,0 +1,22 @@
.md {
font-size: 1.3rem;
h1 {
font-size: 2.3rem;
}
}
.mb-1 {
margin-bottom: 1rem;
}
.mb-2 {
margin-bottom: 2rem;
}
.mb-3 {
margin-bottom: 3rem;
}
html {
font-size: 1.5rem;
}