Give every metrics list a localized heading, keep delivered Rösterei tools out of the offer boundary, and describe the skills grid as a familiarity overview with an evidence note instead of claiming public-case backing for every item. Co-authored-by: Cursor <cursoragent@cursor.com>
130 lines
4.3 KiB
TypeScript
130 lines
4.3 KiB
TypeScript
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
|
import { SkillCategory } from '../../../../models/skill-category';
|
|
import { SkillCard } from '../skill-card/skill-card';
|
|
|
|
const BASE_CATEGORIES: readonly 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',
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
export const SKILL_GRID_ITEM_NAMES: readonly string[] = BASE_CATEGORIES.flatMap((category) =>
|
|
category.skills.map((skill) => skill.name),
|
|
);
|
|
|
|
@Component({
|
|
selector: 'app-skills-grid',
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
imports: [SkillCard],
|
|
templateUrl: './skills-grid.html',
|
|
styleUrl: './skills-grid.scss',
|
|
})
|
|
export class SkillsGrid {
|
|
readonly categoryTitles = input<Readonly<Record<string, string>>>({});
|
|
|
|
protected readonly categories = computed(() => {
|
|
const titles = this.categoryTitles();
|
|
return BASE_CATEGORIES.map((category) => ({
|
|
...category,
|
|
title: titles[category.category] ?? category.title,
|
|
}));
|
|
});
|
|
}
|