From 9ec71ae0eda4f8617b6279619501a083f1c3273f Mon Sep 17 00:00:00 2001 From: Andy Charlwood Date: Sat, 14 Feb 2026 02:30:53 +0000 Subject: [PATCH] US-020: Create SkillDetail renderer for detail panel --- .claude/skills/ralph/prd.json | 4 +- src/components/DetailPanel.tsx | 6 +- src/components/detail/SkillDetail.tsx | 271 ++++++++++++++++++++++++++ 3 files changed, 278 insertions(+), 3 deletions(-) create mode 100644 src/components/detail/SkillDetail.tsx diff --git a/.claude/skills/ralph/prd.json b/.claude/skills/ralph/prd.json index d898377..49d0871 100644 --- a/.claude/skills/ralph/prd.json +++ b/.claude/skills/ralph/prd.json @@ -332,8 +332,8 @@ "Verify in browser using dev-browser skill" ], "priority": 18, - "passes": false, - "notes": "" + "passes": true, + "notes": "Already implemented by prior iteration. Component exists with full content, wired into DetailPanel for consultation and career-role types." }, { "id": "US-019", diff --git a/src/components/DetailPanel.tsx b/src/components/DetailPanel.tsx index ad0a211..490a1ea 100644 --- a/src/components/DetailPanel.tsx +++ b/src/components/DetailPanel.tsx @@ -6,6 +6,7 @@ import { DetailPanelContent } from '@/types/pmr' import type { CardHeaderProps } from './Card' import { KPIDetail } from './detail/KPIDetail' import { ConsultationDetail } from './detail/ConsultationDetail' +import { SkillDetail } from './detail/SkillDetail' // Width mapping from content type const widthMap: Record = { @@ -215,10 +216,13 @@ export function DetailPanel() { )} + {content.type === 'skill' && } + {/* Other content types - placeholder for future stories */} {content.type !== 'kpi' && content.type !== 'consultation' && - content.type !== 'career-role' && ( + content.type !== 'career-role' && + content.type !== 'skill' && (
= { + Technical: 'Technical', + Domain: 'Healthcare Domain', + Leadership: 'Strategic & Leadership', +} + +// Proficiency bar color based on value +function getProficiencyColor(proficiency: number): string { + if (proficiency >= 90) return 'var(--success)' + if (proficiency >= 75) return 'var(--accent)' + return 'var(--amber)' +} + +export function SkillDetail({ skill }: SkillDetailProps) { + // Find roles that use this skill from constellation data + const usedInRoles = roleSkillMappings + .filter((mapping) => mapping.skillIds.includes(skill.id)) + .map((mapping) => { + const node = constellationNodes.find((n) => n.id === mapping.roleId && n.type === 'role') + return node + }) + .filter(Boolean) + // Sort chronologically (earliest first) + .sort((a, b) => (a!.startYear ?? 0) - (b!.startYear ?? 0)) + + return ( +
+ {/* Skill header */} +
+
+ {skill.name} +
+ + {/* Medication metaphor badges */} +
+ + {skill.frequency} + + + {skill.status} + +
+
+ + {/* Category label */} +
+ + {categoryLabels[skill.category]} + +
+ + {/* Proficiency bar */} +
+

+ Proficiency +

+
+
+
+
+ + {skill.proficiency}% + +
+
+ + {/* Years of experience */} +
+

+ Experience +

+
+ + {skill.yearsOfExperience} + + + {skill.yearsOfExperience === 1 ? 'year' : 'years'} + + + Since {skill.startYear} + +
+
+ + {/* Used in roles */} + {usedInRoles.length > 0 && ( +
+

+ Used In +

+
+ {usedInRoles.map((node) => ( +
+ + ))} +
+
+ )} +
+ ) +}