[Cleaned] Removed images, comments, etc
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 729 B |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 423 KiB After Width: | Height: | Size: 423 KiB |
|
Before Width: | Height: | Size: 429 KiB After Width: | Height: | Size: 429 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 136 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 235 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 10 KiB |
@@ -20,14 +20,6 @@
|
||||
Contact details can be found below. Cheers!
|
||||
</p>
|
||||
|
||||
|
||||
<!-- <pre class="text-xl text-gray-600 text-center text-wrap">
|
||||
Full-Stack Developer with a strong interest in efficiency and reproduceability
|
||||
Below you'll find some noteworthy projects, with a demo and the source code linked inside (unless there is a NDA)
|
||||
Contact details can be found below. Cheers!
|
||||
</pre> -->
|
||||
|
||||
|
||||
<div class="flex justify-center mt-6">
|
||||
<a href="Ian Vink - Curriculum Vitae 2024.pdf" target="_blank" class=" border-2 border-black text-black font-semibold
|
||||
py-2 px-4 w-fit rounded-sm hover:bg-gray-800 hover:text-white
|
||||
|
||||
@@ -16,11 +16,9 @@ export class AboutComponent {
|
||||
iconItems: IconItem[] = [];
|
||||
|
||||
constructor() {
|
||||
//bi-chat bi-globe bi-translate
|
||||
this.iconItems.push({icon: "bi-translate", text: "Dutch, English"});
|
||||
this.iconItems.push({icon: "bi-geo-alt-fill", text: "Limburg, The Netherlands"});
|
||||
this.iconItems.push({icon: "bi-cake2-fill", text: this.getAge() +" years old"});
|
||||
// this.iconItems.push({icon: "bi-file-person-fill", text: "View my CV"});
|
||||
}
|
||||
|
||||
getAge(): number {
|
||||
|
||||
@@ -6,13 +6,6 @@
|
||||
<app-projects></app-projects>
|
||||
<app-contact></app-contact>
|
||||
</main>
|
||||
<!-- <a
|
||||
href="#header"
|
||||
class="bottom-4 right-4 bg-blue-500 text-white p-3 rounded-full shadow-lg hover:bg-blue-700 focus:outline-none fade-up-in"
|
||||
aria-label="Scroll to top"
|
||||
>
|
||||
<i class="bi bi-arrow-up"></i>
|
||||
</a> -->
|
||||
|
||||
<footer class="bg-gray-800 text-white text-center py-4">
|
||||
<p>© 2024 Ian Vink. All rights reserved.</p>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { AfterViewInit, Component } from '@angular/core';
|
||||
import { RouterOutlet } from '@angular/router';
|
||||
import { HeaderComponent } from './header/header.component';
|
||||
import { AboutComponent } from './about/about.component';
|
||||
import { ContactComponent } from './contact/contact.component';
|
||||
|
||||
@@ -2,20 +2,18 @@
|
||||
<div class="container mx-auto text-center px-6">
|
||||
<h2 class="text-3xl font-semibold text-gray-800 mb-6 relative">Contact</h2>
|
||||
<p class="text-xl text-gray-600 mb-6">Feel free to reach out to me via email or social media.</p>
|
||||
<!-- <a href="mailto:vink.ian@protonmail.ch" class="text-blue-500">Send me an email</a> -->
|
||||
<div class="mt-6">
|
||||
|
||||
<a href="mailto:vink.ian@protonmail.ch" target="_blank" class="text-gray-600 inline-block mx-3 p-4 rounded-full hover:text-orange-500 transition-all transform hover:rotate-[360deg] duration-700 ease-in-out">
|
||||
<i class="bi bi-envelope-fill text-4xl"></i> <!-- Larger icon with Tailwind -->
|
||||
<i class="bi bi-envelope-fill text-4xl"></i>
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/ninjaws" target="_blank" class="text-gray-600 inline-block mx-3 p-4 rounded-full hover:text-black transition-all transform hover:rotate-[360deg] duration-700 ease-in-out">
|
||||
<i class="bi bi-github text-4xl"></i> <!-- Larger icon with Tailwind -->
|
||||
<i class="bi bi-github text-4xl"></i>
|
||||
</a>
|
||||
|
||||
<!-- LinkedIn link with icon -->
|
||||
<a href="https://www.linkedin.com/in/vink-development" target="_blank" class="text-gray-600 inline-block mx-3 p-4 rounded-full hover:text-blue-700 transition-all transform hover:rotate-[360deg] duration-700 ease-in-out">
|
||||
<i class="bi bi-linkedin text-4xl"></i> <!-- Larger icon with Tailwind -->
|
||||
<i class="bi bi-linkedin text-4xl"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
<div class="text-2xl font-bold">Vink Development</div>
|
||||
<div class="flex items-center">
|
||||
<nav class="hidden md:flex space-x-6">
|
||||
<a *ngFor="let menuItem of menuItems" href="{{menuItem.href}}" class="hover:text-gray-400">{{menuItem.name}}</a>
|
||||
<a *ngFor="let menuItem of menuItems" href="{{menuItem.href}}"
|
||||
class="hover:text-gray-400">{{menuItem.name}}</a>
|
||||
</nav>
|
||||
|
||||
<div class="md:hidden">
|
||||
@@ -12,12 +13,6 @@
|
||||
<i class="bi bi-list text-3xl"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- <a href="path-to-your-cv.pdf" target="_blank"
|
||||
class="ml-6 border-2 border-white text-white font-semibold py-2 px-4 rounded-sm hover:bg-white hover:text-black
|
||||
hover:border-transparent flex items-center transition duration-300 ease-in-out">
|
||||
Resume
|
||||
</a> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -31,4 +26,3 @@
|
||||
<div *ngIf="isMenuOpen" class="fixed w-full h-full bg-black bg-opacity-50 z-40" (click)="closeMenu()">
|
||||
|
||||
</div>
|
||||
<!-- bg-opacity-50 --->
|
||||
@@ -1,5 +1,3 @@
|
||||
<!-- bg-white/5 -->
|
||||
|
||||
<div class="backface-hidden rounded-sm overflow-hidden shadow-lg md:hover:scale-105 transition-all
|
||||
duration-300 group relative fade-in-up bg-white/5 border-none flex flex-col h-full">
|
||||
<img src="{{project.image}}" alt="{{project.title}}" class="w-full max-h-56 aspect-[3/2] object-cover">
|
||||
@@ -13,11 +11,8 @@
|
||||
<span *ngFor="let technology of project.technologies"
|
||||
class="bg-gray-800/55 text-white text-sm sm:text-md px-1 sm:px-2 py-1 rounded-md">{{technology}}</span>
|
||||
</div>
|
||||
|
||||
<div class="relative mb-2"
|
||||
[class.mb-4]="project.links.length === 0"
|
||||
>
|
||||
<!-- [class.max-h-[textHeight]="isExpanded" [class.max-h-52]="!isExpanded" -->
|
||||
<!-- relative -->
|
||||
<div class="mb-2" [class.mb-4]="project.links.length === 0">
|
||||
<p #description
|
||||
class="text-gray-300 mb-4 overflow-hidden xl:whitespace-pre-line transition-all duration-500 ease-in-out"
|
||||
[ngStyle]="{ maxHeight: isExpanded ? getTextHeight(): '13rem' }"
|
||||
@@ -25,10 +20,10 @@
|
||||
{{ project.description }}
|
||||
</p>
|
||||
<button *ngIf="isTruncated && !isExpanded" (click)="toggleExpand()"
|
||||
class="text-teal-600 hover:text-teal-400">
|
||||
class="text-teal-500 hover:text-teal-300">
|
||||
Show More
|
||||
</button>
|
||||
<button *ngIf="isExpanded" (click)="toggleExpand()" class="text-teal-600 hover:text-teal-400">
|
||||
<button *ngIf="isExpanded" (click)="toggleExpand()" class="text-teal-500 hover:text-teal-300">
|
||||
Show Less
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef,
|
||||
HostListener,
|
||||
Input,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
@@ -15,9 +14,6 @@ export interface Project {
|
||||
image: string;
|
||||
technologies: string[];
|
||||
links: { address: string; type: 'source' | 'demo' | 'link' }[];
|
||||
// source?: string;
|
||||
// demo?: string;
|
||||
// link?: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
@@ -38,20 +34,18 @@ export class ProjectCardComponent {
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.checkIfTruncated();
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
checkIfTruncated() {
|
||||
const element = this.descriptionElement.nativeElement;
|
||||
// console.log(this.fullHeight);
|
||||
this.isTruncated = element.scrollHeight > element.offsetHeight;
|
||||
// this.updateTextHeight();
|
||||
}
|
||||
|
||||
getTextHeight() {
|
||||
return `${this.descriptionElement.nativeElement.scrollHeight}px`;
|
||||
}
|
||||
|
||||
// Toggle expand/collapse
|
||||
toggleExpand() {
|
||||
this.isExpanded = !this.isExpanded;
|
||||
if (this.isExpanded) {
|
||||
@@ -59,6 +53,6 @@ export class ProjectCardComponent {
|
||||
} else {
|
||||
this.isTruncated = true;
|
||||
}
|
||||
this.cdr.detectChanges(); // Notify Angular of the changes after toggling
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- <details class="text-gray-300 mb-4">
|
||||
<summary class="cursor-pointer list-none">
|
||||
</summary>
|
||||
<p class="whitespace-pre-line">{{project.description | slice:150}}</p>
|
||||
</details> -->
|
||||
@@ -16,15 +16,13 @@ export class ProjectsComponent {
|
||||
title: 'Quiz App',
|
||||
year: '2024',
|
||||
description:
|
||||
// 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +
|
||||
'A little quiz game, using questions from the Open Trivia Database. This API only allows one request per 5 seconds. ' +
|
||||
'\n\nTo combat this, the app collects all available questions in its own database. ' +
|
||||
'To ensure the data stays fresh, it repeats this process every night, by creating a backup table, and then swapping it with the active one once it is finished. ' +
|
||||
'\n\nDocker is used for the development and deployment. The app is self-hosted, the link can be found below.',
|
||||
image: 'Quiz 5.jpeg',
|
||||
image: 'Quiz.jpeg',
|
||||
technologies: [
|
||||
'Angular',
|
||||
// 'Sass',
|
||||
'Tailwind',
|
||||
'Spring Boot',
|
||||
'Docker',
|
||||
@@ -33,8 +31,6 @@ export class ProjectsComponent {
|
||||
'Gitea Workflows'
|
||||
],
|
||||
links: [{type: 'source', address: 'https://github.com/Ninjaws/Quiz'}, {type: 'link', address: 'https://quiz.ianvink.nl'}]
|
||||
// source: 'https://github.com/Ninjaws/Quiz',
|
||||
// link: 'https://quiz.ianvink.nl'
|
||||
});
|
||||
this.projects.push({
|
||||
title: 'Mobile-First ERP Solution',
|
||||
@@ -50,10 +46,7 @@ export class ProjectsComponent {
|
||||
…and much more.
|
||||
\nThe entire application is multilingual, and each component is designed to be fully responsive, ensuring a smooth experience on both large and small screens.
|
||||
\nThe application undergoes thorough testing, including unit tests, integration tests, and end-to-end tests. Deployments are rolled out in stages to catch potential bugs before going live.`,
|
||||
|
||||
// 'A full-fledged ERP solution, with modules for declarations (such as Cost, Time, Travel, Sickleave and Holidays), HRM (Managing employees), Sales (Relations, Contacts, Leads, Deals, Aftersales), Projectmanagement, Administration (Permission management, User management), and many more. ' +
|
||||
// '\n\nThe entire application is multi-lingual, with a system developed to enable multiple people add translations without causes merge errors. Every component is crafted in such a way that it supports both big and small screens. The application is throuroughly tested, with unittests, integrationtests and end-to-end tests. Deployments happen in stages, to ensure bugs are caught before going live.',
|
||||
image: 'classified2 cleaned.png',
|
||||
image: 'Classified.png',
|
||||
technologies: [
|
||||
'Angular',
|
||||
'Sass',
|
||||
@@ -76,7 +69,7 @@ export class ProjectsComponent {
|
||||
year: '2021',
|
||||
description:
|
||||
'An application that combines key-value detection and multiclass-classification, to identify the correct supplier for an invoice. It uses online machine learning to keep improving itself as the user provides feedback.',
|
||||
image: 'Supplier Recognition - Demo.png',
|
||||
image: 'Supplier Recognition.png',
|
||||
technologies: [
|
||||
'Angular (Typescript, HTML, CSS)',
|
||||
'ASP.NET Core (C#)',
|
||||
@@ -92,7 +85,6 @@ export class ProjectsComponent {
|
||||
description:
|
||||
'A tool for editing the seabed mesh in a maritime simulator. The collision map is automatically updated, enabling ships to interact with the modified terrain.'+
|
||||
'\n\nThis tool allows instructors to quickly create new environments for the training of ship crews.',
|
||||
// to edit the seabed mesh of a maritime simulator. The collisionmap is also updated, to allow ships to interact with this update terrain. \nThis tool allows instructors to rapidly create new terrain, for training shipcrews.',
|
||||
image: 'Seabed Modification.png',
|
||||
technologies: ['Unigine (C#)', 'AGX Dynamics (C++)', 'Qt Creator'],
|
||||
links: [],
|
||||
@@ -102,7 +94,7 @@ export class ProjectsComponent {
|
||||
year: '2019',
|
||||
description:
|
||||
'Tetris written in C, visualized on dot-matrix displays, with the score visible on a 7-segment display and a menu system visible on the ATMega128.',
|
||||
image: 'Setup 3.png',
|
||||
image: 'Microcontroller Tetris.png',
|
||||
technologies: [
|
||||
'C',
|
||||
'ATmega128',
|
||||
@@ -127,7 +119,7 @@ export class ProjectsComponent {
|
||||
description:
|
||||
'The application uses a vector field to direct particles towards a target. The vectors are calculated using a heatmap, which centers on the position of the target.'+
|
||||
'\n\nThe particles collide with the environment, which can be edited and saved/loaded using the GUI.',
|
||||
image: 'black2.png', //'Particle Flow - Demonstration.png', //"black.png",
|
||||
image: 'Flow Field Pathfinding Algorithm.png',
|
||||
technologies: ['Java', 'Swing', 'IntelliJ'],
|
||||
links: [{type:'source', address:'https://github.com/Ninjaws/2D-Computer-Graphics/tree/master/EindOpdracht/Pathfinding'}, {type:'demo', address: 'https://youtu.be/7rvWAWpkYus'}]
|
||||
});
|
||||
@@ -136,7 +128,7 @@ export class ProjectsComponent {
|
||||
year: '2015',
|
||||
description:
|
||||
'A platformer written in C++, with saving/loading, tile- and collisionmaps, enemy AI, collectibles and state management to switch between multiple screens (game, menu, victory, etc.)',
|
||||
image: 'Jelly Game - demo.png',
|
||||
image: 'Jelly Game.png',
|
||||
technologies: ['C++', 'SFML2.0', 'Platformer', 'Visual Studio'],
|
||||
links: [{type:'source', address:'https://github.com/Ninjaws/JellyGame'}, {type:'demo', address: 'https://youtu.be/jCUnqbxuySI'}]
|
||||
});
|
||||
|
||||
@@ -16,7 +16,6 @@ export class SkillsComponent {
|
||||
frontend: Category = { title: 'Frontend', skills: [] };
|
||||
backend: Category = { title: 'Backend', skills: [] };
|
||||
devOps: Category = { title: 'DevOps', skills: [] };
|
||||
// other: Category = {title: "Other", skills: []};
|
||||
|
||||
categories: Category[] = [];
|
||||
|
||||
@@ -61,7 +60,6 @@ export class SkillsComponent {
|
||||
'PowerShell',
|
||||
'Wireguard',
|
||||
);
|
||||
// this.other.skills.push("MS Office", "Machine Learning", "Computer Vision");
|
||||
this.categories.push(this.frontend, this.backend, this.devOps);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,27 +42,3 @@ html {
|
||||
.fade-in-left-ani {
|
||||
animation: fadeInLeft 0.95s ease-out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Custom scrollbar styles for Sass */
|
||||
// ::-webkit-scrollbar {
|
||||
// width: 4px;
|
||||
// }
|
||||
|
||||
// ::-webkit-scrollbar-track {
|
||||
// background: rgb(61, 61, 61);
|
||||
// }
|
||||
|
||||
// ::-webkit-scrollbar-thumb {
|
||||
// background:rgb(116, 116, 116);//rgb(226, 147, 0);
|
||||
// border-radius: 20px;
|
||||
// transition: background 0.3s;
|
||||
// }
|
||||
|
||||
// ::-webkit-scrollbar-thumb:hover {
|
||||
// background: #357ABD;
|
||||
// }
|
||||
|
||||
// scrollbar-width: thin;
|
||||
// scrollbar-color: #4A90E2 #f0f0f0;
|
||||