diff --git a/package.json b/package.json index 04b3ef5..8a21119 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "next": "14.1.4", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-intersection-observer": "^8.29.1", "sharp": "^0.33.4", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d05e24a..e1def69 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ dependencies: react-dom: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) + react-intersection-observer: + specifier: ^8.29.1 + version: 8.29.1(react@18.3.1) sharp: specifier: ^0.33.4 version: 0.33.4 @@ -2857,6 +2860,14 @@ packages: scheduler: 0.23.2 dev: false + /react-intersection-observer@8.29.1(react@18.3.1): + resolution: {integrity: sha512-JLxJ4V0L73ailfvbYQ2/lfAyirtud1WsRsYnzHyVLMfQff1AIG1lWdC5XaGSK4yb9jZHVbbNsrVIO3PJm03koQ==} + peerDependencies: + react: ^15.0.0 || ^16.0.0 || ^17.0.0|| ^17.0.0 + dependencies: + react: 18.3.1 + dev: false + /react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} diff --git a/public/images/projects/war.gif b/public/images/projects/war.gif new file mode 100644 index 0000000..0df37bc Binary files /dev/null and b/public/images/projects/war.gif differ diff --git a/public/projects.json b/public/projects.json index ca7dc80..e60d95b 100644 --- a/public/projects.json +++ b/public/projects.json @@ -1,15 +1,14 @@ [ { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", + "name": "WAR", + "description": "Fully customizable Clan/Guild system with integrated Clan War", + "category": "Minecraft", + "imageUrl": "/images/projects/war.gif", "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" + "Github": "https://github.com/MatzHilven/WAR" }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] + "languages": ["Java"], + "tags": ["1.12", "Archived"] }, { "name": "Project Beta", @@ -37,1105 +36,5 @@ "socials": {}, "languages": ["Java"], "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - - { - "name": "Project Alpha", - "description": "Description for Project Alpha", - "category": "Web", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Java", "TypeScript"], - "tags": ["Frontend", "Backend"] - }, - { - "name": "Project Beta", - "description": "Description for Project Beta", - "category": "Minecraft", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "Github": "https://github.com" }, - "languages": ["Rust", "Go"], - "tags": ["1.8", "Fullstack"] - }, - { - "name": "Project Gamma", - "description": "Description for Project Gamma", - "category": "Discord", - "imageUrl": "https://via.placeholder.com/150", - "socials": { "YouTube": "https://youtube.com" }, - "languages": ["TypeScript"], - "tags": ["Backend", "Archived"] - }, - { - "name": "Project Delta", - "description": "Description for Project Delta", - "category": "Unity", - "imageUrl": "https://via.placeholder.com/150", - "socials": {}, - "languages": ["Java"], - "tags": ["1.17", "Frontend"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] - }, - { - "name": "Project Epsilon", - "description": "Description for Project Epsilon", - "category": "Misc", - "imageUrl": "https://via.placeholder.com/150", - "socials": { - "Github": "https://github.com", - "YouTube": "https://youtube.com" - }, - "languages": ["Go", "Rust"], - "tags": ["Fullstack", "Paper"] } ] diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 4d6cf5a..6e31a38 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,12 +2,9 @@ import './globals.css' import '@mantine/core/styles.css' import type { Metadata } from 'next' -import { Inter } from 'next/font/google' import React from 'react' import { ColorSchemeScript, MantineProvider } from '@mantine/core' -const inter = Inter({ subsets: ['latin'] }) - export const metadata: Metadata = { title: 'Matz Hilven', description: 'todo', @@ -23,7 +20,7 @@ export default function RootLayout({ - +
{children}
diff --git a/src/app/page.tsx b/src/app/page.tsx index 824df0a..ce71969 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,9 +1,10 @@ 'use client' -import React, { useState, useEffect } from 'react' -import { Project, Tag, projectsSchema } from '@/typings/project' +import React, { useState, useEffect, useMemo } from 'react' import { ProjectCard } from '@/components/ProjectCard' import projectsData from '../../public/projects.json' +import { projectsSchema, Project } from '@/typings/project' +import { useInView } from 'react-intersection-observer' const Page = () => { const parsedProjects = projectsSchema.safeParse(projectsData) @@ -16,63 +17,60 @@ const Page = () => { const projects: Project[] = parsedProjects.data const [currentPage, setCurrentPage] = useState(1) - const [itemsPerPage, setItemsPerPage] = useState(4) - const [filterTag, setFilterTag] = useState(null) + const [itemsPerPage] = useState(12) + const [filterTag, setFilterTag] = useState(null) const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('asc') + const { ref, inView } = useInView({ + threshold: 1.0, + }) + const handleFilterChange = (event: React.ChangeEvent) => { - setFilterTag( - event.target.value === 'All' ? null : (event.target.value as Tag) - ) - setCurrentPage(1) // Reset to the first page when filter changes + setFilterTag(event.target.value === 'All' ? null : event.target.value) + setCurrentPage(1) } const handleSortChange = (event: React.ChangeEvent) => { setSortOrder(event.target.value as 'asc' | 'desc') - setCurrentPage(1) // Reset to the first page when sort order changes + setCurrentPage(1) } + const filteredAndSortedProjects = useMemo(() => { + let updatedProjects = filterTag + ? projects.filter(project => project.tags.includes(filterTag)) + : projects + + updatedProjects = [...updatedProjects].sort((a, b) => { + if (sortOrder === 'asc') { + return a.name.localeCompare(b.name) + } else { + return b.name.localeCompare(a.name) + } + }) + + return updatedProjects + }, [projects, filterTag, sortOrder]) + + const visibleProjects = useMemo(() => { + return filteredAndSortedProjects.slice(0, currentPage * itemsPerPage) + }, [filteredAndSortedProjects, currentPage, itemsPerPage]) + useEffect(() => { - const handleResize = () => { - const cardWidth = 240 // Width of a single card (adjust as needed) - const windowWidth = window.innerWidth - const newItemsPerPage = Math.floor(windowWidth / cardWidth) - setItemsPerPage(newItemsPerPage > 0 ? newItemsPerPage : 1) + if ( + inView && + currentPage * itemsPerPage < filteredAndSortedProjects.length + ) { + setCurrentPage(prevPage => prevPage + 1) } - - handleResize() - - window.addEventListener('resize', handleResize) - - return () => window.removeEventListener('resize', handleResize) - }, []) - - const filteredProjects = filterTag - ? projects.filter(project => project.tags.includes(filterTag)) - : projects - - const sortedProjects = [...filteredProjects].sort((a, b) => { - if (sortOrder === 'asc') { - return a.name.localeCompare(b.name) - } else { - return b.name.localeCompare(a.name) - } - }) - - const indexOfLastItem = currentPage * itemsPerPage - const indexOfFirstItem = indexOfLastItem - itemsPerPage - const currentProjects = sortedProjects.slice( - indexOfFirstItem, - indexOfLastItem - ) - - const totalPages = Math.ceil(sortedProjects.length / itemsPerPage) + }, [inView, currentPage, itemsPerPage, filteredAndSortedProjects.length]) return ( -
-
Matz Hilven
+
- {[...new Set(projects.flatMap(project => project.tags))].map(tag => ( ))} -
-
- {currentProjects.map((project: Project, index: number) => ( +
+ {visibleProjects.map((project, index) => ( ))}
-
- - -
+
) } diff --git a/src/components/ProjectCard.tsx b/src/components/ProjectCard.tsx index cfde2e0..00de45b 100644 --- a/src/components/ProjectCard.tsx +++ b/src/components/ProjectCard.tsx @@ -6,6 +6,9 @@ import { IconBrandRust, IconBrandGolang, IconBrandTypescript, + IconDiamond, + IconBrandKotlin, + IconBrandPython, } from '@tabler/icons-react' type Props = { @@ -13,20 +16,24 @@ type Props = { } const socialIcons: Record = { - Github: , - YouTube: , + Github: , + YouTube: , } const languageIcons: Record = { - Java: , - Rust: , - Go: , - TypeScript: , + Java: , + Rust: , + Go: , + Ruby: , + Kotlin: , + TypeScript: , + Python: , } const tagStyles: Record = { '1.8': 'text-orange-500 border-orange-500', '1.17': 'text-orange-500 border-orange-500', + '1.12': 'text-orange-500 border-orange-500', Paper: 'text-blue-500 border-blue-500', Bungee: 'text-blue-500 border-blue-500', Frontend: 'text-cyan-500 border-cyan-500', @@ -37,48 +44,51 @@ const tagStyles: Record = { export const ProjectCard = ({ project }: Props) => { return ( -
+
{project.name} -
+
-
{project.name}
-
+
+ {project.name} +
+
{project.tags.map(tag => ( {tag} ))}
-
{project.description}
-
-
- {Object.entries(project.socials).map(([social, url]) => ( +
+ {project.description} +
+
+
+
+ {project.socials && + Object.entries(project.socials).map(([social, url]) => ( {socialIcons[social as Social]} ))} -
-
- {project.languages.map(language => ( - - {languageIcons[language]} - - ))} -
+
+
+ {project.languages.map(language => ( +
{languageIcons[language]}
+ ))}
diff --git a/src/typings/project.ts b/src/typings/project.ts index 94b53dc..6fab279 100644 --- a/src/typings/project.ts +++ b/src/typings/project.ts @@ -7,12 +7,16 @@ export const LanguageSchema = z.union([ z.literal('Java'), z.literal('Rust'), z.literal('Go'), + z.literal('Ruby'), + z.literal('Kotlin'), z.literal('TypeScript'), + z.literal('Python'), ]) export type Language = z.infer export const TagSchema = z.union([ z.literal('1.8'), + z.literal('1.12'), z.literal('1.17'), z.literal('Paper'), z.literal('Bungee'), @@ -36,7 +40,7 @@ export const ProjectSchema = z.object({ name: z.string(), description: z.string(), category: CategorySchema, - imageUrl: z.string().url(), + imageUrl: z.string(), socials: z.record(SocialSchema, z.string().url()).optional(), languages: z.array(LanguageSchema), tags: z.array(TagSchema), diff --git a/tailwind.config.ts b/tailwind.config.ts index 0a87ca9..70c2aeb 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -18,26 +18,24 @@ const config = { }, }, extend: { + dropShadow: { + glow: [ + '0 0px 20px rgba(255,255, 255, 0.35)', + '0 0px 65px rgba(255, 255,255, 0.2)', + ], + }, keyframes: { - 'accordion-down': { - from: { height: '0' }, - to: { height: 'var(--radix-accordion-content-height)' }, - }, - 'accordion-up': { - from: { height: 'var(--radix-accordion-content-height)' }, - to: { height: '0' }, + jump: { + '0%, 100%': { transform: 'translateY(0)' }, + '50%': { transform: 'translateY(-10px)' }, }, }, animation: { - 'accordion-down': 'accordion-down 0.2s ease-out', - 'accordion-up': 'accordion-up 0.2s ease-out', - }, - colors: { - bg: '#F9FAFB', + jump: 'jump 0.4s ease-in-out', }, }, }, - plugins: [require('tailwindcss-animate')], + plugins: [], } satisfies Config export default config