From efcc17d4d2f68e602ed29bc753ef4672d10bb574 Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Fri, 24 Apr 2026 15:53:17 +0200 Subject: [PATCH] Update portfolio apps and skills --- components/apps.tsx | 29 +++------ components/skills.tsx | 104 +++++++++++++++++++++++++++------ lib/cv-data.ts | 13 ++++- public/images/app-scrum4me.svg | 89 ++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 40 deletions(-) create mode 100644 public/images/app-scrum4me.svg diff --git a/components/apps.tsx b/components/apps.tsx index b469056..3312206 100644 --- a/components/apps.tsx +++ b/components/apps.tsx @@ -11,10 +11,16 @@ const APPS = [ screenshotMobile: "/images/app-inspannings-monitor-mobile.png", href: "https://inspannings-monitor.jp-visser.nl/dashboard", }, + { + title: "Scrum4Me", + subtitle: "DevPlanner voor kleine teams", + description: + "Een desktop-first fullstack webapplicatie voor solo developers en kleine Scrum Teams die meerdere softwareprojecten parallel beheren. De app organiseert werk hierarchisch (product -> PBI -> story -> taak), biedt gesplitste planningsschermen met drag-and-drop, en integreert met Claude Code via een REST API.", + screenshot: "/images/app-scrum4me.svg", + href: "https://scrum4me.jp-visser.nl", + }, ]; -const PLACEHOLDER_APPS = [{ label: "App 2 — binnenkort" }]; - export function AppsSection() { return (
{/* Mobile screenshot overlay */} {app.screenshotMobile && ( @@ -118,24 +125,6 @@ export function AppsSection() { ))} - {PLACEHOLDER_APPS.map((app, i) => ( - -
-

- {app.label} -

-
-
- ))}
); diff --git a/components/skills.tsx b/components/skills.tsx index d9a1644..d35ae51 100644 --- a/components/skills.tsx +++ b/components/skills.tsx @@ -6,6 +6,7 @@ import { CV_DATA } from "@/lib/cv-data"; const DEVICONS = "https://cdn.jsdelivr.net/gh/devicons/devicon/icons"; const SIMPLE = "https://cdn.simpleicons.org"; +const FLAGS = "https://cdn.jsdelivr.net/gh/lipis/flag-icons/flags/4x3"; const SKILL_ICONS: Record = { // Languages @@ -23,7 +24,7 @@ const SKILL_ICONS: Record = { "Tailwind CSS": `${SIMPLE}/tailwindcss/06B6D4`, Angular: `${DEVICONS}/angularjs/angularjs-original.svg`, "Angular Material": `${SIMPLE}/angular/DD0031`, - Nx: `${SIMPLE}/nx/143055`, + Redux: `${SIMPLE}/redux/764ABC`, "ASP.NET": `${SIMPLE}/dotnet/512BD4`, "ASP.NET Core": `${SIMPLE}/dotnet/512BD4`, // Databases @@ -33,21 +34,37 @@ const SKILL_ICONS: Record = { MariaDB: `${DEVICONS}/mariadb/mariadb-original.svg`, // Tools Claude: `${SIMPLE}/anthropic/c5a880`, - ChatGPT: `${SIMPLE}/openai/ffffff`, + "Claude Code": `${SIMPLE}/anthropic/c5a880`, Git: `${DEVICONS}/git/git-original.svg`, + GitHub: `${SIMPLE}/github/ffffff`, Supabase: `${SIMPLE}/supabase/3ECF8E`, - Vercel: `${SIMPLE}/vercel/ffffff`, + Obsidian: `${SIMPLE}/obsidian/7C3AED`, + NotebookLM: `${SIMPLE}/googlegemini/8E75B2`, }; -const LANGUAGE_FLAGS: Record = { - Nederlands: "🇳🇱", - Engels: "🇬🇧", - Duits: "🇩🇪", +const BADGE_ICONS: Record = { + ChatGPT: "AI", + Neon: "N", + Vercel: "▲", +}; + +const LANGUAGE_ICONS: Record = { + Nederlands: `${FLAGS}/nl.svg`, + Engels: `${FLAGS}/gb.svg`, + Duits: `${FLAGS}/de.svg`, +}; + +const LANGUAGE_PROGRESS: Record = { + Nederlands: 100, + Engels: 85, + Duits: 55, }; function SkillPill({ label }: { label: string }) { - const icon = SKILL_ICONS[label]; - const flag = LANGUAGE_FLAGS[label]; + const icon = SKILL_ICONS[label] ?? LANGUAGE_ICONS[label]; + const badge = BADGE_ICONS[label]; + const isLanguage = label in LANGUAGE_ICONS; + return ( - {flag && {flag}} - {!flag && icon && ( + {icon && ( {label} )} + {!icon && badge && ( + + {badge} + + )} {label} ); } +function LanguageProgress({ label }: { label: string }) { + const icon = LANGUAGE_ICONS[label]; + const progress = LANGUAGE_PROGRESS[label] ?? 0; + + return ( +
+
+ {icon && ( + {label} + )} + {label} +
+
+
+
+
+ ); +} + const SKILL_GROUPS = [ { title: "Programmeertalen", items: CV_DATA.skills.languages }, { title: "Frameworks", items: CV_DATA.skills.frameworks }, { title: "Databases", items: CV_DATA.skills.databases }, + { title: "AI / AI-tools", items: CV_DATA.skills.aiTools }, { title: "Talen", items: CV_DATA.skills.spoken }, ]; @@ -127,9 +195,9 @@ export function SkillsSection() { {group.title}
- {group.items.map((s) => ( - - ))} + {group.title === "Talen" + ? group.items.map((s) => ) + : group.items.map((s) => )}
diff --git a/lib/cv-data.ts b/lib/cv-data.ts index 28cc980..53b5883 100644 --- a/lib/cv-data.ts +++ b/lib/cv-data.ts @@ -96,7 +96,7 @@ export const CV_DATA = { "Tailwind CSS", "Angular", "Angular Material", - "Nx", + "Redux", "ASP.NET", "ASP.NET Core", ], @@ -106,7 +106,16 @@ export const CV_DATA = { "Oracle", "MySQL", "MariaDB", - "Microsoft Access", + ], + aiTools: [ + "ChatGPT", + "Claude Code", + "Supabase", + "Neon", + "Vercel", + "Obsidian", + "NotebookLM", + "GitHub", ], tools: ["Claude", "ChatGPT", "Git", "Supabase", "Vercel"], spoken: ["Nederlands", "Engels", "Duits"], diff --git a/public/images/app-scrum4me.svg b/public/images/app-scrum4me.svg new file mode 100644 index 0000000..148d41b --- /dev/null +++ b/public/images/app-scrum4me.svg @@ -0,0 +1,89 @@ + + Scrum4Me DevPlanner screenshot + A desktop planning interface with product backlog and story planning columns. + + + + + + + + Scrum4Me + + Demo + Producten + Todo's + + DevPlanner + Een lichtgewicht Scrum-gebaseerde projectplanner voor solo developers en kleine Scrum Teams. + + + + + Product Backlog + all + + Stories + + + + Kritiek + + Authenticatie & gebruikersbeheer + + Productbeheer + Product Backlog + Story-beheer + Infrastructuur & deployment + + + Hoog + + Todo-lijst + Sprint Backlog & Sprint Planning + Sprint Planning (taken per story) + Claude Code integratie + + + + + Kritiek + + + + Product + aanmaken + + Kritiek + + Open + + + Productenlijst + bekijken + + Kritiek + + Open + + + Hoog + + + + Product + bewerken + + Hoog + + Open + + + Product + archiveren + + Hoog + + Open + +