feat: add projects page and rework home page

This commit is contained in:
2026-07-09 16:24:51 +02:00
parent 8aa5aca650
commit 834d7ed00f
32 changed files with 720 additions and 77 deletions
+25
View File
@@ -0,0 +1,25 @@
export interface CrateMeta {
crate: Crate;
}
export interface Crate {
id: string;
name: string;
updated_at: string;
versions: number[];
keywords: string[];
created_at: string;
downloads: number;
recent_downloads: number;
default_version: string;
num_versions: number;
yanked: boolean;
max_version: string;
newest_version: string;
max_stable_version: string;
description: string;
homepage: string;
repository: string;
exact_match: boolean;
trustpub_only: boolean;
}
+108
View File
@@ -0,0 +1,108 @@
export interface GithubRepository {
id: number;
node_id: string;
name: string;
full_name: string;
private: boolean;
owner: Owner;
html_url: string;
description: string;
fork: boolean;
url: string;
forks_url: string;
keys_url: string;
collaborators_url: string;
teams_url: string;
hooks_url: string;
issue_events_url: string;
events_url: string;
assignees_url: string;
branches_url: string;
tags_url: string;
blobs_url: string;
git_tags_url: string;
git_refs_url: string;
trees_url: string;
statuses_url: string;
languages_url: string;
stargazers_url: string;
contributors_url: string;
subscribers_url: string;
subscription_url: string;
commits_url: string;
git_commits_url: string;
comments_url: string;
issue_comment_url: string;
contents_url: string;
compare_url: string;
merges_url: string;
archive_url: string;
downloads_url: string;
issues_url: string;
pulls_url: string;
milestones_url: string;
notifications_url: string;
labels_url: string;
releases_url: string;
deployments_url: string;
created_at: string;
updated_at: string;
pushed_at: string;
git_url: string;
ssh_url: string;
clone_url: string;
svn_url: string;
homepage: string;
size: number;
stargazers_count: number;
watchers_count: number;
language: string;
has_issues: boolean;
has_projects: boolean;
has_downloads: boolean;
has_wiki: boolean;
has_pages: boolean;
has_discussions: boolean;
forks_count: number;
mirror_url: any;
archived: boolean;
disabled: boolean;
open_issues_count: number;
license: any;
allow_forking: boolean;
is_template: boolean;
web_commit_signoff_required: boolean;
has_pull_requests: boolean;
pull_request_creation_policy: string;
topics: any[];
visibility: string;
forks: number;
open_issues: number;
watchers: number;
default_branch: string;
temp_clone_token: any;
network_count: number;
subscribers_count: number;
}
export interface Owner {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
user_view_type: string;
site_admin: boolean;
}
+23
View File
@@ -0,0 +1,23 @@
import type { TimePeriod } from './time';
import type { Tool } from './tool';
export type ProjectLinkType = 'github' | 'gitea' | 'cargo' | 'melpa';
export interface ProjectLink {
url: string;
display: string;
type: ProjectLinkType;
}
export interface Project {
name: string;
description: string;
role: string;
dates: TimePeriod;
links: ProjectLink[];
tools: Tool[];
}
export interface ProjectsWrapper {
projects: Project[];
}
+47 -3
View File
@@ -1,14 +1,58 @@
import type { TimelineItem } from '@nuxt/ui';
import type { Tool } from './tool';
import { timeToString, type TimePeriod } from './time';
export class ResumeExperience implements TimelineItem {
tools: Tool[] = [];
export interface ResumeExperience {
dates: TimePeriod;
title: string;
company: string;
description: string;
tools: Tool[];
icon: string;
}
export class ResumeExperienceTimelineItem implements TimelineItem {
tools: Tool[];
description?: string;
date: string;
title: string;
icon: string;
constructor(from: ResumeExperience) {
this.date = timeToString(from.dates);
this.title = `${from.title}${from.company}`;
this.description = from.description;
this.icon = from.icon;
this.tools = from.tools;
}
}
export interface Education {
dates: TimePeriod;
degree: string;
institution: string;
location: string;
description?: string;
icon: string;
}
export class EducationTimelineItem implements TimelineItem {
date: string;
description?: string;
title: string;
icon: string;
constructor(from: Education) {
this.date = timeToString(from.dates);
this.description = from.description;
this.title = `${from.degree}${from.institution}, ${from.location}`;
this.icon = from.icon;
}
}
export class ResumeContent {
experience: ResumeExperience[] = [];
education: TimelineItem[] = [];
education: Education[] = [];
otherTools: Tool[] = [];
devops: Tool[] = [];
os: Tool[] = [];
+9
View File
@@ -0,0 +1,9 @@
import { t } from '../utils/i18n';
export interface TimePeriod {
start: string;
end?: string;
}
export const timeToString = (time: TimePeriod): string =>
time.end ? `${time.start}${time.end}` : `${t('misc.since')} ${time.start}`;