Task 11: Build CoreSkills tile ("Repeat Medications")

Created CoreSkillsTile component that presents skills as medications
with frequency dosing metaphor:
- Half-width card with amber dot header "REPEAT MEDICATIONS"
- 5 skill items with teal icon containers (lucide-react icons)
- Each item shows: skill name, frequency (e.g., "Twice daily"),
  start year, years of experience, and "Active" status badge
- Uses medication metaphor: "Data Analysis · Twice daily · Since
  2016 · 9 yrs"
- Data from src/data/skills.ts with user-specified frequencies
- Styled to match GP System concept with 6px radius items on
  dashboard background (#F0F5F4)
- Integrated into DashboardLayout in right column next to
  LatestResultsTile

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 17:24:26 +00:00
parent 5ad67a512f
commit 6d47f2a948
2 changed files with 98 additions and 0 deletions
+2
View File
@@ -4,6 +4,7 @@ import { TopBar } from './TopBar'
import Sidebar from './Sidebar' import Sidebar from './Sidebar'
import { PatientSummaryTile } from './tiles/PatientSummaryTile' import { PatientSummaryTile } from './tiles/PatientSummaryTile'
import { LatestResultsTile } from './tiles/LatestResultsTile' import { LatestResultsTile } from './tiles/LatestResultsTile'
import { CoreSkillsTile } from './tiles/CoreSkillsTile'
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
@@ -101,6 +102,7 @@ export function DashboardLayout() {
{/* LatestResultsTile — half width (left) */} {/* LatestResultsTile — half width (left) */}
<LatestResultsTile /> <LatestResultsTile />
{/* CoreSkillsTile — half width (right) */} {/* CoreSkillsTile — half width (right) */}
<CoreSkillsTile />
{/* LastConsultationTile — full width */} {/* LastConsultationTile — full width */}
{/* CareerActivityTile — full width */} {/* CareerActivityTile — full width */}
{/* EducationTile — full width */} {/* EducationTile — full width */}
+96
View File
@@ -0,0 +1,96 @@
import { BarChart3, Code2, Database, PieChart, FileCode2 } from 'lucide-react'
import { Card, CardHeader } from '../Card'
import { skills } from '@/data/skills'
const iconMap = {
BarChart3,
Code2,
Database,
PieChart,
FileCode2,
}
export function CoreSkillsTile() {
return (
<Card>
<CardHeader dotColor="amber" title="REPEAT MEDICATIONS" />
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
{skills.map((skill) => {
const IconComponent = iconMap[skill.icon as keyof typeof iconMap]
return (
<div
key={skill.id}
style={{
display: 'flex',
alignItems: 'center',
gap: '10px',
fontSize: '12.5px',
padding: '10px 12px',
background: 'var(--bg-dashboard)',
borderRadius: 'var(--radius-sm)',
border: '1px solid var(--border-light)',
cursor: 'default',
}}
>
{/* Icon container */}
<div
style={{
width: '28px',
height: '28px',
borderRadius: '6px',
background: 'var(--accent-light)',
color: 'var(--accent)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
}}
>
{IconComponent && <IconComponent size={14} />}
</div>
{/* Text block */}
<div style={{ flex: 1, minWidth: 0 }}>
<div
style={{
fontWeight: 600,
color: 'var(--text-primary)',
marginBottom: '2px',
}}
>
{skill.name}
</div>
<div
style={{
fontSize: '11px',
color: 'var(--text-tertiary)',
fontFamily: '"Geist Mono", monospace',
}}
>
{skill.frequency} · Since {skill.startYear} · {skill.yearsOfExperience} yrs
</div>
</div>
{/* Status badge */}
<div
style={{
fontSize: '10px',
fontWeight: 500,
padding: '3px 8px',
borderRadius: '20px',
background: 'var(--success-light)',
color: 'var(--success)',
border: '1px solid var(--success-border)',
flexShrink: 0,
}}
>
{skill.status}
</div>
</div>
)
})}
</div>
</Card>
)
}