diff --git a/src/components/DashboardLayout.tsx b/src/components/DashboardLayout.tsx index d8dd334..c9d30e4 100644 --- a/src/components/DashboardLayout.tsx +++ b/src/components/DashboardLayout.tsx @@ -1,24 +1,22 @@ -import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react' +import { useState, useEffect, useCallback, useRef, useMemo } from 'react' import { motion } from 'framer-motion' -import { ChevronRight } from 'lucide-react' import Sidebar from './Sidebar' import { CommandPalette } from './CommandPalette' import { DetailPanel } from './DetailPanel' -import { CardHeader } from './Card' import { PatientSummaryTile } from './tiles/PatientSummaryTile' import { ProjectsTile } from './tiles/ProjectsTile' import { ParentSection } from './ParentSection' import CareerConstellation from './constellation/CareerConstellation' import { TimelineInterventionsSubsection } from './TimelineInterventionsSubsection' import { RepeatMedicationsSubsection } from './RepeatMedicationsSubsection' +import { LastConsultationCard } from './LastConsultationCard' import { ChatWidget } from './ChatWidget' import { useActiveSection } from '@/hooks/useActiveSection' import { useDetailPanel } from '@/contexts/DetailPanelContext' import { timelineConsultations } from '@/data/timeline' import { skills } from '@/data/skills' import type { PaletteAction } from '@/lib/search' -import { hexToRgba, prefersReducedMotion, motionSafeTransition } from '@/lib/utils' -import { DEFAULT_ORG_COLOR } from '@/lib/theme-colors' +import { prefersReducedMotion, motionSafeTransition } from '@/lib/utils' const sidebarVariants = { hidden: prefersReducedMotion ? { x: 0, opacity: 1 } : { x: -272, opacity: 0 }, @@ -37,203 +35,6 @@ const contentVariants = { }, } -interface LastConsultationSubsectionProps { - highlightedRoleId?: string | null -} - -function LastConsultationSubsection({ highlightedRoleId }: LastConsultationSubsectionProps) { - const { openPanel } = useDetailPanel() - const consultation = timelineConsultations[0] - if (!consultation) { - return null - } - const isHighlighted = highlightedRoleId === consultation.id - - const handleOpenPanel = () => { - openPanel({ type: 'consultation', consultation }) - } - - const handleKeyDown = (e: React.KeyboardEvent) => { - if (e.key === 'Enter' || e.key === ' ') { - e.preventDefault() - handleOpenPanel() - } - } - - const formatDate = (dateStr: string): string => { - const date = new Date(dateStr) - return date.toLocaleDateString('en-GB', { month: 'long', year: 'numeric' }) - } - - const getEmploymentType = (): string => { - if (consultation.organization.includes('ICB')) { - return 'Permanent · Full-time' - } - return 'Permanent' - } - - const getBand = (): string => { - if (consultation.role.includes('Head')) { - return '8a' - } - return '—' - } - - const fieldLabelStyle: React.CSSProperties = { - fontSize: '12px', - textTransform: 'uppercase', - letterSpacing: '0.06em', - color: 'var(--text-tertiary)', - marginBottom: '3px', - } - - const fieldValueStyle: React.CSSProperties = { - fontSize: '13px', - fontWeight: 600, - color: 'var(--text-primary)', - } - - return ( -
- - -
{ - e.currentTarget.style.backgroundColor = hexToRgba(consultation.orgColor ?? DEFAULT_ORG_COLOR, 0.04) - }} - onMouseLeave={(e) => { - e.currentTarget.style.backgroundColor = 'transparent' - }} - aria-label={`View full details for ${consultation.role}`} - > -
-
Date
-
{formatDate(consultation.date)}
-
-
-
Organisation
-
{consultation.organization}
-
-
-
Type
-
{getEmploymentType()}
-
-
-
Band
-
{getBand()}
-
-
- -
- {consultation.role} -
- - - - -
- ) -} - export function DashboardLayout() { const [commandPaletteOpen, setCommandPaletteOpen] = useState(false) const [highlightedNodeId, setHighlightedNodeId] = useState(null) @@ -446,7 +247,7 @@ export function DashboardLayout() {
- +
diff --git a/src/components/LastConsultationCard.tsx b/src/components/LastConsultationCard.tsx new file mode 100644 index 0000000..255768f --- /dev/null +++ b/src/components/LastConsultationCard.tsx @@ -0,0 +1,204 @@ +import React from 'react' +import { ChevronRight } from 'lucide-react' +import { CardHeader } from './Card' +import { useDetailPanel } from '@/contexts/DetailPanelContext' +import { timelineConsultations } from '@/data/timeline' +import { hexToRgba } from '@/lib/utils' +import { DEFAULT_ORG_COLOR } from '@/lib/theme-colors' + +interface LastConsultationCardProps { + highlightedRoleId?: string | null +} + +export function LastConsultationCard({ highlightedRoleId }: LastConsultationCardProps) { + const { openPanel } = useDetailPanel() + const consultation = timelineConsultations[0] + if (!consultation) { + return null + } + const isHighlighted = highlightedRoleId === consultation.id + + const handleOpenPanel = () => { + openPanel({ type: 'consultation', consultation }) + } + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault() + handleOpenPanel() + } + } + + const formatDate = (dateStr: string): string => { + const date = new Date(dateStr) + return date.toLocaleDateString('en-GB', { month: 'long', year: 'numeric' }) + } + + const getEmploymentType = (): string => { + if (consultation.organization.includes('ICB')) { + return 'Permanent · Full-time' + } + return 'Permanent' + } + + const getBand = (): string => { + if (consultation.role.includes('Head')) { + return '8a' + } + return '—' + } + + const fieldLabelStyle: React.CSSProperties = { + fontSize: '12px', + textTransform: 'uppercase', + letterSpacing: '0.06em', + color: 'var(--text-tertiary)', + marginBottom: '3px', + } + + const fieldValueStyle: React.CSSProperties = { + fontSize: '13px', + fontWeight: 600, + color: 'var(--text-primary)', + } + + return ( +
+ + +
{ + e.currentTarget.style.backgroundColor = hexToRgba(consultation.orgColor ?? DEFAULT_ORG_COLOR, 0.04) + }} + onMouseLeave={(e) => { + e.currentTarget.style.backgroundColor = 'transparent' + }} + aria-label={`View full details for ${consultation.role}`} + > +
+
Date
+
{formatDate(consultation.date)}
+
+
+
Organisation
+
{consultation.organization}
+
+
+
Type
+
{getEmploymentType()}
+
+
+
Band
+
{getBand()}
+
+
+ +
+ {consultation.role} +
+ +
    + {consultation.examination.map((bullet, index) => ( +
  • +
  • + ))} +
+ + +
+ ) +}