From 334ea2c02f9501ece7c325efc7ee2a4056ff3ef6 Mon Sep 17 00:00:00 2001 From: A Charlwood Date: Fri, 13 Feb 2026 17:37:37 +0000 Subject: [PATCH] Task 15: Build ProjectsTile Co-Authored-By: Claude Opus 4.6 --- src/components/DashboardLayout.tsx | 2 + src/components/tiles/ProjectsTile.tsx | 97 +++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/components/tiles/ProjectsTile.tsx diff --git a/src/components/DashboardLayout.tsx b/src/components/DashboardLayout.tsx index a708e1b..6f9e25a 100644 --- a/src/components/DashboardLayout.tsx +++ b/src/components/DashboardLayout.tsx @@ -8,6 +8,7 @@ import { CoreSkillsTile } from './tiles/CoreSkillsTile' import { LastConsultationTile } from './tiles/LastConsultationTile' import { CareerActivityTile } from './tiles/CareerActivityTile' import { EducationTile } from './tiles/EducationTile' +import { ProjectsTile } from './tiles/ProjectsTile' const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches @@ -117,6 +118,7 @@ export function DashboardLayout() { {/* ProjectsTile — full width */} + diff --git a/src/components/tiles/ProjectsTile.tsx b/src/components/tiles/ProjectsTile.tsx new file mode 100644 index 0000000..9a68144 --- /dev/null +++ b/src/components/tiles/ProjectsTile.tsx @@ -0,0 +1,97 @@ +import { investigations } from '@/data/investigations' +import { Card, CardHeader } from '../Card' + +/** + * Projects tile - displays active projects as interactive items + * Full-width card, last tile in the dashboard grid + * Data sourced from investigations.ts + */ + +const statusColorMap: Record = { + Complete: '#059669', + Ongoing: '#0D6E6E', + Live: '#059669', +} + +export function ProjectsTile() { + return ( + + + +
+ {investigations.map((project) => ( + + ))} +
+
+ ) +} + +interface ProjectItemProps { + name: string + status: 'Complete' | 'Ongoing' | 'Live' + year: number +} + +function ProjectItem({ name, status, year }: ProjectItemProps) { + const dotColor = statusColorMap[status] || '#0D6E6E' + const isLive = status === 'Live' + + return ( +
{ + e.currentTarget.style.borderColor = 'var(--accent-border)' + }} + onMouseLeave={(e) => { + e.currentTarget.style.borderColor = 'var(--border-light)' + }} + > + {/* Status dot */} +
+ + {/* Project name */} + {name} + + {/* Year badge */} + + {year} + +
+ ) +}