Files
portfolio/src/components/tiles/EducationTile.tsx
T
admin 52ee98d8aa US-015: Modify EducationTile: richer content, panel trigger
- Add OSCE score (80%) to MPharm inline details via educationExtras data
- Show research project with full description (Drug delivery & cocrystals, 75.1%)
- Display A-level grades as Mathematics (A*) · Chemistry (B) · Politics (C)
- Include Mary Seacole programme detail from educationExtras
- Import and use educationExtras data for dynamic inline content
- Add osceScore field to EducationExtra type
- Each entry clickable to open detail panel, hover border shift intact

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 00:33:44 +00:00

160 lines
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState } from 'react'
import { Card, CardHeader } from '../Card'
import { useDetailPanel } from '@/contexts/DetailPanelContext'
import { documents } from '@/data/documents'
import { educationExtras } from '@/data/educationExtras'
/**
* Education tile - displays academic qualifications
* Full-width card below Career Activity
* Each entry is clickable to open detail panel
*/
export function EducationTile() {
const { openPanel } = useDetailPanel()
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
// Filter to main education entries in reverse chronological order
const educationDocuments = [
documents.find((d) => d.id === 'doc-mary-seacole')!,
documents.find((d) => d.id === 'doc-mpharm')!,
documents.find((d) => d.id === 'doc-alevels')!,
]
// Look up education extras by document ID
const getExtras = (docId: string) =>
educationExtras.find((e) => e.documentId === docId)
// Build rich inline content for each entry
const getInlineDetails = (doc: (typeof educationDocuments)[0]) => {
const extras = getExtras(doc.id)
switch (doc.id) {
case 'doc-mpharm':
return {
title: 'MPharm (Hons) — 2:1',
institution: 'University of East Anglia',
year: '20112015',
details: [
`Research project: Drug delivery & cocrystals, 75.1% (Distinction)`,
...(extras?.osceScore ? [`4th year OSCE: ${extras.osceScore}`] : []),
],
}
case 'doc-mary-seacole':
return {
title: 'NHS Leadership Academy — Mary Seacole Programme',
institution: 'NHS Leadership Academy',
year: '2018',
details: [
`Programme score: 78%`,
...(extras?.programmeDetail ? [extras.programmeDetail] : []),
],
}
case 'doc-alevels':
return {
title: 'A-Levels',
institution: 'Highworth Grammar School',
year: '20092011',
details: ['Mathematics (A*) · Chemistry (B) · Politics (C)'],
}
default:
return {
title: doc.title,
institution: doc.institution,
year: doc.date,
details: doc.classification ? [doc.classification] : [],
}
}
}
return (
<Card full tileId="education">
<CardHeader dotColor="purple" title="EDUCATION" />
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
{educationDocuments.map((doc, index) => {
const content = getInlineDetails(doc)
const isHovered = hoveredIndex === index
return (
<button
key={doc.id}
onClick={() => openPanel({ type: 'education', document: doc })}
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(null)}
style={{
padding: '10px 12px',
background: 'var(--surface)',
border: `1px solid ${isHovered ? 'var(--accent)' : 'var(--border-light)'}`,
borderRadius: 'var(--radius-sm)',
fontSize: '12px',
color: 'var(--text-primary)',
cursor: 'pointer',
textAlign: 'left',
transition: 'border-color 150ms ease-out, box-shadow 150ms ease-out',
boxShadow: isHovered
? '0 2px 8px rgba(26,43,42,0.08)'
: '0 1px 2px rgba(26,43,42,0.05)',
}}
>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'baseline',
gap: '12px',
marginBottom: '4px',
}}
>
<span style={{ fontWeight: 600, fontSize: '12.5px' }}>
{content.title}
</span>
<span
style={{
fontFamily: 'var(--font-geist-mono)',
fontSize: '10px',
color: 'var(--text-tertiary)',
whiteSpace: 'nowrap',
}}
>
{content.year}
</span>
</div>
<div
style={{
color: 'var(--text-secondary)',
fontSize: '11px',
marginBottom: content.details.length > 0 ? '6px' : '0',
}}
>
{content.institution}
</div>
{content.details.length > 0 && (
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '2px',
}}
>
{content.details.map((detail, i) => (
<div
key={i}
style={{
color: 'var(--text-tertiary)',
fontSize: '10.5px',
fontFamily: 'var(--font-geist-mono)',
}}
>
{detail}
</div>
))}
</div>
)}
</button>
)
})}
</div>
</Card>
)
}