US-018: Create ConsultationDetail renderer for detail panel
- Created ConsultationDetail.tsx component to render full role details - Displays role title, organization, dates with current badge - Renders history paragraph (consultation.history) - Shows achievement bullets (consultation.examination) - Displays outcomes/impact (consultation.plan) - Renders coded entries as badges with code + description - Wired into DetailPanel for both 'consultation' and 'career-role' types - Styled consistently with dashboard design system - Typecheck and build pass successfully Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import { useFocusTrap } from '@/hooks/useFocusTrap'
|
|||||||
import { DetailPanelContent } from '@/types/pmr'
|
import { DetailPanelContent } from '@/types/pmr'
|
||||||
import type { CardHeaderProps } from './Card'
|
import type { CardHeaderProps } from './Card'
|
||||||
import { KPIDetail } from './detail/KPIDetail'
|
import { KPIDetail } from './detail/KPIDetail'
|
||||||
|
import { ConsultationDetail } from './detail/ConsultationDetail'
|
||||||
|
|
||||||
// Width mapping from content type
|
// Width mapping from content type
|
||||||
const widthMap: Record<DetailPanelContent['type'], 'narrow' | 'wide'> = {
|
const widthMap: Record<DetailPanelContent['type'], 'narrow' | 'wide'> = {
|
||||||
@@ -210,24 +211,29 @@ export function DetailPanel() {
|
|||||||
>
|
>
|
||||||
{/* Render content based on type */}
|
{/* Render content based on type */}
|
||||||
{content.type === 'kpi' && <KPIDetail kpi={content.kpi} />}
|
{content.type === 'kpi' && <KPIDetail kpi={content.kpi} />}
|
||||||
|
{(content.type === 'consultation' || content.type === 'career-role') && (
|
||||||
|
<ConsultationDetail consultation={content.consultation} />
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Other content types - placeholder for future stories */}
|
{/* Other content types - placeholder for future stories */}
|
||||||
{content.type !== 'kpi' && (
|
{content.type !== 'kpi' &&
|
||||||
<div
|
content.type !== 'consultation' &&
|
||||||
style={{
|
content.type !== 'career-role' && (
|
||||||
fontFamily: 'var(--font-ui)',
|
<div
|
||||||
color: 'var(--text-secondary)',
|
style={{
|
||||||
fontSize: '14px',
|
fontFamily: 'var(--font-ui)',
|
||||||
}}
|
color: 'var(--text-secondary)',
|
||||||
>
|
fontSize: '14px',
|
||||||
<p>
|
}}
|
||||||
Detail panel for: <strong>{content.type}</strong>
|
>
|
||||||
</p>
|
<p>
|
||||||
<p style={{ marginTop: '8px', fontSize: '12px' }}>
|
Detail panel for: <strong>{content.type}</strong>
|
||||||
Content renderers will be implemented in subsequent user stories.
|
</p>
|
||||||
</p>
|
<p style={{ marginTop: '8px', fontSize: '12px' }}>
|
||||||
</div>
|
Content renderers will be implemented in subsequent user stories.
|
||||||
)}
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -0,0 +1,236 @@
|
|||||||
|
import type { Consultation } from '@/types/pmr'
|
||||||
|
|
||||||
|
interface ConsultationDetailProps {
|
||||||
|
consultation: Consultation
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ConsultationDetail({ consultation }: ConsultationDetailProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontFamily: 'var(--font-ui)',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: '24px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Role header */}
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: '20px',
|
||||||
|
fontWeight: 700,
|
||||||
|
color: 'var(--text-primary)',
|
||||||
|
lineHeight: '1.3',
|
||||||
|
marginBottom: '4px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{consultation.role}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: '14px',
|
||||||
|
fontWeight: 600,
|
||||||
|
color: consultation.orgColor,
|
||||||
|
marginBottom: '8px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{consultation.organization}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: '12px',
|
||||||
|
fontFamily: 'var(--font-geist)',
|
||||||
|
color: 'var(--text-tertiary)',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: '8px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>{consultation.duration}</span>
|
||||||
|
{consultation.isCurrent && (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
padding: '2px 8px',
|
||||||
|
backgroundColor: 'var(--success-light)',
|
||||||
|
color: 'var(--success)',
|
||||||
|
fontSize: '10px',
|
||||||
|
fontWeight: 600,
|
||||||
|
borderRadius: 'var(--radius-sm)',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
letterSpacing: '0.05em',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Current
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* History (presenting complaint) */}
|
||||||
|
<div>
|
||||||
|
<h3
|
||||||
|
style={{
|
||||||
|
fontSize: '12px',
|
||||||
|
fontWeight: 600,
|
||||||
|
color: 'var(--text-secondary)',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
letterSpacing: '0.05em',
|
||||||
|
marginBottom: '8px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
History
|
||||||
|
</h3>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
fontSize: '14px',
|
||||||
|
lineHeight: '1.6',
|
||||||
|
color: 'var(--text-primary)',
|
||||||
|
margin: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{consultation.history}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Examination (achievements) */}
|
||||||
|
{consultation.examination && consultation.examination.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<h3
|
||||||
|
style={{
|
||||||
|
fontSize: '12px',
|
||||||
|
fontWeight: 600,
|
||||||
|
color: 'var(--text-secondary)',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
letterSpacing: '0.05em',
|
||||||
|
marginBottom: '8px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Key Achievements
|
||||||
|
</h3>
|
||||||
|
<ul
|
||||||
|
style={{
|
||||||
|
margin: 0,
|
||||||
|
paddingLeft: '20px',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: '8px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{consultation.examination.map((item, index) => (
|
||||||
|
<li
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
fontSize: '14px',
|
||||||
|
lineHeight: '1.6',
|
||||||
|
color: 'var(--text-primary)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Plan (outcomes) */}
|
||||||
|
{consultation.plan && consultation.plan.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<h3
|
||||||
|
style={{
|
||||||
|
fontSize: '12px',
|
||||||
|
fontWeight: 600,
|
||||||
|
color: 'var(--text-secondary)',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
letterSpacing: '0.05em',
|
||||||
|
marginBottom: '8px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Outcomes & Impact
|
||||||
|
</h3>
|
||||||
|
<ul
|
||||||
|
style={{
|
||||||
|
margin: 0,
|
||||||
|
paddingLeft: '20px',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: '8px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{consultation.plan.map((item, index) => (
|
||||||
|
<li
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
fontSize: '14px',
|
||||||
|
lineHeight: '1.6',
|
||||||
|
color: 'var(--text-primary)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Coded entries (technical environment / tags) */}
|
||||||
|
{consultation.codedEntries && consultation.codedEntries.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<h3
|
||||||
|
style={{
|
||||||
|
fontSize: '12px',
|
||||||
|
fontWeight: 600,
|
||||||
|
color: 'var(--text-secondary)',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
letterSpacing: '0.05em',
|
||||||
|
marginBottom: '8px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Coded Entries
|
||||||
|
</h3>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
gap: '8px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{consultation.codedEntries.map((entry, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: '6px',
|
||||||
|
padding: '6px 12px',
|
||||||
|
backgroundColor: 'var(--bg-dashboard)',
|
||||||
|
border: '1px solid var(--border-light)',
|
||||||
|
borderRadius: 'var(--radius-sm)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
fontSize: '11px',
|
||||||
|
fontFamily: 'var(--font-geist)',
|
||||||
|
fontWeight: 600,
|
||||||
|
color: 'var(--accent)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{entry.code}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
fontSize: '11px',
|
||||||
|
color: 'var(--text-secondary)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{entry.description}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user