diff --git a/src/app/components/pages/skills/skill-card/skill-card.html b/src/app/components/pages/skills/skill-card/skill-card.html new file mode 100644 index 0000000..43ae59a --- /dev/null +++ b/src/app/components/pages/skills/skill-card/skill-card.html @@ -0,0 +1,18 @@ +
+

{{ title }}

+
+ @for (skill of skills; track skill.icon) { + + + + } +
+
diff --git a/src/app/components/pages/skills/skill-card/skill-card.scss b/src/app/components/pages/skills/skill-card/skill-card.scss new file mode 100644 index 0000000..e2d0637 --- /dev/null +++ b/src/app/components/pages/skills/skill-card/skill-card.scss @@ -0,0 +1,63 @@ +// skill-card.component.scss +.card { + background: linear-gradient( + 135deg, + rgba(255, 255, 255, 0.1) 0%, + rgba(255, 255, 255, 0.05) 100% + ); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); + border: 1px solid rgba(255, 255, 255, 0.15); + border-radius: 16px; + padding: 1.5rem; + height: 100%; + display: flex; + flex-direction: column; + box-shadow: + 0 4px 24px rgba(0, 0, 0, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.1); + transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease; + + &:hover { + transform: translateY(-4px); + box-shadow: + 0 8px 32px rgba(99, 102, 241, 0.2), + inset 0 1px 0 rgba(255, 255, 255, 0.15); + border-color: rgba(255, 255, 255, 0.25); + } + + h3 { + margin: 0 0 1rem; + font-size: 0.875rem; + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0.1em; + color: rgba(255, 255, 255, 0.6); + } + + .icons { + display: flex; + flex-wrap: wrap; + gap: 1rem; + align-items: center; + flex: 1; + + a { + position: relative; + display: flex; + + img { + width: 40px; + height: 40px; + object-fit: contain; + filter: grayscale(100%) brightness(0.8); + transition: filter 0.2s ease, transform 0.2s ease; + } + + &:hover img { + filter: none; + transform: scale(1.1); + } + } + } +} diff --git a/src/app/components/pages/skills/skill-card/skill-card.spec.ts b/src/app/components/pages/skills/skill-card/skill-card.spec.ts new file mode 100644 index 0000000..cf24ce9 --- /dev/null +++ b/src/app/components/pages/skills/skill-card/skill-card.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SkillCard } from './skill-card'; + +describe('SkillCard', () => { + let component: SkillCard; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [SkillCard] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SkillCard); + component = fixture.componentInstance; + await fixture.whenStable(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/pages/skills/skill-card/skill-card.ts b/src/app/components/pages/skills/skill-card/skill-card.ts new file mode 100644 index 0000000..1e33b75 --- /dev/null +++ b/src/app/components/pages/skills/skill-card/skill-card.ts @@ -0,0 +1,14 @@ +import {Component, Input} from '@angular/core'; +import {Skill} from '../../../../models/skill'; + +@Component({ + selector: 'app-skill-card', + imports: [], + templateUrl: './skill-card.html', + styleUrl: './skill-card.scss', +}) +export class SkillCard { + @Input({ required: true }) title!: string; + @Input({ required: true }) category!: string; + @Input({ required: true }) skills!: Skill[]; +} diff --git a/src/app/components/pages/skills/skills-grid/skills-grid.html b/src/app/components/pages/skills/skills-grid/skills-grid.html new file mode 100644 index 0000000..53c6b51 --- /dev/null +++ b/src/app/components/pages/skills/skills-grid/skills-grid.html @@ -0,0 +1,10 @@ +
+ @for (cat of categories; track cat.category) { + + } +
diff --git a/src/app/components/pages/skills/skills-grid/skills-grid.scss b/src/app/components/pages/skills/skills-grid/skills-grid.scss new file mode 100644 index 0000000..d7ace0f --- /dev/null +++ b/src/app/components/pages/skills/skills-grid/skills-grid.scss @@ -0,0 +1,6 @@ +.grid { + display: flex; + flex-wrap: wrap; + flex-direction: column; + gap: 10px; +} diff --git a/src/app/components/pages/skills/skills-grid/skills-grid.spec.ts b/src/app/components/pages/skills/skills-grid/skills-grid.spec.ts new file mode 100644 index 0000000..25bd879 --- /dev/null +++ b/src/app/components/pages/skills/skills-grid/skills-grid.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SkillsGrid } from './skills-grid'; + +describe('SkillsGrid', () => { + let component: SkillsGrid; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [SkillsGrid] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SkillsGrid); + component = fixture.componentInstance; + await fixture.whenStable(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/pages/skills/skills-grid/skills-grid.ts b/src/app/components/pages/skills/skills-grid/skills-grid.ts new file mode 100644 index 0000000..1cc03fa --- /dev/null +++ b/src/app/components/pages/skills/skills-grid/skills-grid.ts @@ -0,0 +1,96 @@ +import {Component} from '@angular/core'; +import {SkillCategory} from '../../../../models/skill-category'; +import {SkillCard} from '../skill-card/skill-card'; + +@Component({ + selector: 'app-skills-grid', + imports: [ + SkillCard + ], + templateUrl: './skills-grid.html', + styleUrl: './skills-grid.scss', +}) +export class SkillsGrid { + categories: SkillCategory[] = [ + { + title: 'Programming', + category: 'programming', + gridArea: 'prog', + skills: [ + {name: 'TypeScript', icon: 'typescript', url: 'https://www.typescriptlang.org/'}, + {name: 'JavaScript', icon: 'javascript', url: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript'}, + {name: 'Angular', icon: 'angular', url: 'https://angular.dev/'}, + {name: 'Java', icon: 'java', url: 'https://www.java.com/'}, + {name: 'Spring', icon: 'java-spring', url: 'https://spring.io/'}, + {name: 'C#', icon: 'c-sharp', url: 'https://learn.microsoft.com/en-us/dotnet/csharp/'}, + {name: '.NET', icon: 'c-sharp-net', url: 'https://dotnet.microsoft.com/'}, + {name: 'Kafka', icon: 'kafka', url: 'https://kafka.apache.org/'}, + {name: 'Elasticsearch', icon: 'elasticseach', url: 'https://www.elastic.co/'}, + ], + }, + { + title: 'Databases', + category: 'db', + gridArea: 'db', + skills: [ + {name: 'SQL Server', icon: 'microsoftsqlserver', url: 'https://www.microsoft.com/en-us/sql-server'}, + {name: 'PostgreSQL', icon: 'postgresql', url: 'https://www.postgresql.org/'}, + {name: 'MySQL', icon: 'mysql', url: 'https://www.mysql.com/'}, + {name: 'MariaDB', icon: 'mariadb', url: 'https://mariadb.org/'}, + ], + }, + { + title: 'DevOps', + category: 'devops', + gridArea: 'devops', + skills: [ + {name: 'Kubernetes', icon: 'kubernetes', url: 'https://kubernetes.io/'}, + {name: 'Docker', icon: 'docker', url: 'https://www.docker.com/'}, + {name: 'GitLab', icon: 'gitlab', url: 'https://gitlab.com/'}, + {name: 'Azure DevOps', icon: 'devops', url: 'https://azure.microsoft.com/en-us/products/devops'}, + {name: 'Azure', icon: 'azure', url: 'https://azure.microsoft.com/'}, + {name: 'Hetzner', icon: 'hetzner', url: 'https://www.hetzner.com/'}, + {name: 'Netcup', icon: 'netcup', url: 'https://www.netcup.eu/'}, + ], + }, + { + title: 'Operating Systems', + category: 'os', + gridArea: 'os', + skills: [ + {name: 'Arch Linux', icon: 'arch', url: 'https://archlinux.org/'}, + {name: 'Ubuntu', icon: 'ubuntu', url: 'https://ubuntu.com/'}, + {name: 'macOS', icon: 'macos', url: 'https://www.apple.com/macos/'}, + {name: 'Windows', icon: 'windows', url: 'https://www.microsoft.com/windows'}, + ], + }, + { + title: 'Infrastructure as Code', + category: 'iac', + gridArea: 'iac', + skills: [ + {name: 'Terraform', icon: 'terraform', url: 'https://www.terraform.io/'}, + {name: 'Ansible', icon: 'ansible', url: 'https://www.ansible.com/'}, + ], + }, + { + title: 'Hypervisors', + category: 'hyperviser', + gridArea: 'hyper', + skills: [ + {name: 'Proxmox', icon: 'proxmox', url: 'https://www.proxmox.com/'}, + {name: 'Hyper-V', icon: 'hyperv', url: 'https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/'}, + ], + }, + { + title: 'Tools', + category: 'tools', + gridArea: 'tools', + skills: [ + {name: 'JetBrains', icon: 'jetbrains', url: 'https://www.jetbrains.com/'}, + {name: 'Visual Studio', icon: 'vs', url: 'https://visualstudio.microsoft.com/'}, + {name: 'Microsoft Office', icon: 'office', url: 'https://www.microsoft.com/microsoft-365'}, + ], + }, + ]; +} diff --git a/src/app/components/pages/skills/skills.html b/src/app/components/pages/skills/skills.html new file mode 100644 index 0000000..bcdc830 --- /dev/null +++ b/src/app/components/pages/skills/skills.html @@ -0,0 +1,5 @@ +
+

Antonio Ledebuhr

+

Software Engineering & DevOps

+ +
diff --git a/src/app/components/pages/skills/skills.scss b/src/app/components/pages/skills/skills.scss new file mode 100644 index 0000000..baf6a79 --- /dev/null +++ b/src/app/components/pages/skills/skills.scss @@ -0,0 +1,20 @@ +.main { + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + color: #fff; + font-family: system-ui, sans-serif; +} + +h1 { + font-size: 3rem; + font-weight: 600; + margin: 0; +} + +p { + color: rgba(255, 255, 255, 0.5); + margin: 0.5rem 0 3rem; +} diff --git a/src/app/components/pages/skills/skills.spec.ts b/src/app/components/pages/skills/skills.spec.ts new file mode 100644 index 0000000..8e19e0a --- /dev/null +++ b/src/app/components/pages/skills/skills.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { Skills } from './skills'; + +describe('Skills', () => { + let component: Skills; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [Skills] + }) + .compileComponents(); + + fixture = TestBed.createComponent(Skills); + component = fixture.componentInstance; + await fixture.whenStable(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/pages/skills/skills.ts b/src/app/components/pages/skills/skills.ts new file mode 100644 index 0000000..4dcd0d8 --- /dev/null +++ b/src/app/components/pages/skills/skills.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; +import {SkillsGrid} from './skills-grid/skills-grid'; + +@Component({ + selector: 'app-skills', + imports: [ + SkillsGrid + ], + templateUrl: './skills.html', + styleUrl: './skills.scss', +}) +export class Skills { + +}