refactor: remove dead code — orphaned files, unused types and functions
Delete 3 orphaned files (SubNav, TopBar, problems.ts), remove 4 unused type definitions from pmr.ts (ViewId, NavItem, ReferralFormData, Problem), trim types/index.ts to only Phase, and remove unused utility functions (calculateSkillOffset, formatBootLine, getProfileContent, DotColorName).
This commit is contained in:
@@ -1,96 +0,0 @@
|
|||||||
interface NavSection {
|
|
||||||
id: string
|
|
||||||
label: string
|
|
||||||
tileId: string // data-tile-id to scroll to
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SubNavProps {
|
|
||||||
activeSection: string
|
|
||||||
onSectionClick: (sectionId: string) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
const sections: NavSection[] = [
|
|
||||||
{ id: 'overview', label: 'Overview', tileId: 'patient-summary' },
|
|
||||||
{ id: 'skills', label: 'Skills', tileId: 'section-skills' },
|
|
||||||
{ id: 'experience', label: 'Experience', tileId: 'section-experience' },
|
|
||||||
{ id: 'projects', label: 'Significant Interventions', tileId: 'projects' },
|
|
||||||
{ id: 'education', label: 'Education', tileId: 'section-education' },
|
|
||||||
]
|
|
||||||
|
|
||||||
export function SubNav({ activeSection, onSectionClick }: SubNavProps) {
|
|
||||||
const handleSectionClick = (section: NavSection) => {
|
|
||||||
// Scroll to the tile
|
|
||||||
const tileEl = document.querySelector(`[data-tile-id="${section.tileId}"]`)
|
|
||||||
if (tileEl) {
|
|
||||||
tileEl.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
|
||||||
}
|
|
||||||
// Notify parent of section change
|
|
||||||
onSectionClick(section.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<nav
|
|
||||||
aria-label="Section navigation"
|
|
||||||
className="subnav-scroll md:justify-center"
|
|
||||||
style={{
|
|
||||||
position: 'sticky',
|
|
||||||
top: 'var(--topbar-height)',
|
|
||||||
zIndex: 99,
|
|
||||||
height: 'var(--subnav-height)',
|
|
||||||
background: 'var(--surface)',
|
|
||||||
borderBottom: '1px solid var(--border-light)',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '24px',
|
|
||||||
overflowX: 'auto',
|
|
||||||
overflowY: 'hidden',
|
|
||||||
padding: '0 16px',
|
|
||||||
scrollbarWidth: 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{sections.map((section) => {
|
|
||||||
const isActive = activeSection === section.id
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
key={section.id}
|
|
||||||
onClick={() => handleSectionClick(section)}
|
|
||||||
aria-current={isActive ? 'true' : undefined}
|
|
||||||
style={{
|
|
||||||
position: 'relative',
|
|
||||||
fontSize: '14px',
|
|
||||||
fontWeight: 500,
|
|
||||||
color: isActive ? 'var(--accent)' : 'var(--text-secondary)',
|
|
||||||
background: 'none',
|
|
||||||
border: 'none',
|
|
||||||
padding: '0 4px 2px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
transition: 'color 200ms ease-out',
|
|
||||||
fontFamily: 'var(--font-ui)',
|
|
||||||
flexShrink: 0,
|
|
||||||
minHeight: '42px',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{section.label}
|
|
||||||
{isActive && (
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
height: '2px',
|
|
||||||
background: 'var(--accent)',
|
|
||||||
transition: 'all 200ms ease-out',
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</nav>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,208 +0,0 @@
|
|||||||
import { useState, useEffect } from 'react'
|
|
||||||
import { Search } from 'lucide-react'
|
|
||||||
import { CvmisLogo } from './CvmisLogo'
|
|
||||||
|
|
||||||
interface TopBarProps {
|
|
||||||
onSearchClick?: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export function TopBar({ onSearchClick }: TopBarProps) {
|
|
||||||
const [currentTime, setCurrentTime] = useState(() => formatTime(new Date()))
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
setCurrentTime(formatTime(new Date()))
|
|
||||||
}, 60_000)
|
|
||||||
return () => clearInterval(interval)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<header
|
|
||||||
className="fixed top-0 left-0 right-0 flex items-center justify-between font-ui"
|
|
||||||
style={{
|
|
||||||
height: 'var(--topbar-height)',
|
|
||||||
background: 'var(--surface)',
|
|
||||||
borderBottom: '1px solid var(--border)',
|
|
||||||
padding: '0 20px',
|
|
||||||
zIndex: 100,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/* Skip to main content link (only visible on focus) */}
|
|
||||||
<a
|
|
||||||
href="#main-content"
|
|
||||||
className="skip-link"
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
top: '-40px',
|
|
||||||
left: '0',
|
|
||||||
background: 'var(--accent)',
|
|
||||||
color: '#FFFFFF',
|
|
||||||
padding: '8px 16px',
|
|
||||||
textDecoration: 'none',
|
|
||||||
zIndex: 101,
|
|
||||||
borderRadius: '0 0 4px 0',
|
|
||||||
fontSize: '14px',
|
|
||||||
fontWeight: 600,
|
|
||||||
}}
|
|
||||||
onFocus={(e) => {
|
|
||||||
e.currentTarget.style.top = '0'
|
|
||||||
}}
|
|
||||||
onBlur={(e) => {
|
|
||||||
e.currentTarget.style.top = '-40px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Skip to main content
|
|
||||||
</a>
|
|
||||||
{/* Brand */}
|
|
||||||
<div className="flex items-center gap-2 shrink-0">
|
|
||||||
<CvmisLogo size={24} />
|
|
||||||
<span
|
|
||||||
className="font-ui hidden sm:inline"
|
|
||||||
style={{
|
|
||||||
fontSize: '15px',
|
|
||||||
fontWeight: 600,
|
|
||||||
color: 'var(--text-primary)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Headhunt Medical Center
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="font-ui sm:hidden"
|
|
||||||
style={{
|
|
||||||
fontSize: '15px',
|
|
||||||
fontWeight: 600,
|
|
||||||
color: 'var(--text-primary)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
HMC
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="hidden lg:inline"
|
|
||||||
style={{
|
|
||||||
fontSize: '12px',
|
|
||||||
fontWeight: 400,
|
|
||||||
color: 'var(--text-tertiary)',
|
|
||||||
marginLeft: '2px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Remote
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Search bar (center) — triggers command palette, no inline search */}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={onSearchClick}
|
|
||||||
className="hidden lg:flex items-center gap-2 cursor-pointer font-ui"
|
|
||||||
style={{
|
|
||||||
maxWidth: '560px',
|
|
||||||
minWidth: '400px',
|
|
||||||
height: '46px',
|
|
||||||
border: '1.5px solid var(--border)',
|
|
||||||
borderRadius: 'var(--radius-card)',
|
|
||||||
padding: '0 14px',
|
|
||||||
background: 'var(--surface)',
|
|
||||||
transition: 'border-color 150ms, box-shadow 150ms',
|
|
||||||
}}
|
|
||||||
onMouseEnter={(e) => {
|
|
||||||
e.currentTarget.style.borderColor = 'var(--accent-border)'
|
|
||||||
}}
|
|
||||||
onMouseLeave={(e) => {
|
|
||||||
if (document.activeElement !== e.currentTarget) {
|
|
||||||
e.currentTarget.style.borderColor = 'var(--border)'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onFocus={(e) => {
|
|
||||||
e.currentTarget.style.borderColor = 'var(--accent)'
|
|
||||||
e.currentTarget.style.boxShadow = '0 0 0 3px rgba(13,110,110,0.12)'
|
|
||||||
}}
|
|
||||||
onBlur={(e) => {
|
|
||||||
e.currentTarget.style.borderColor = 'var(--border)'
|
|
||||||
e.currentTarget.style.boxShadow = 'none'
|
|
||||||
}}
|
|
||||||
aria-label="Search records, experience, skills. Press Control plus K"
|
|
||||||
>
|
|
||||||
<Search
|
|
||||||
size={17}
|
|
||||||
style={{ color: 'var(--text-tertiary)', flexShrink: 0 }}
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
className="flex-1 text-left"
|
|
||||||
style={{
|
|
||||||
fontSize: '14px',
|
|
||||||
color: 'var(--text-tertiary)',
|
|
||||||
fontFamily: 'var(--font-ui)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Search records, experience, skills...
|
|
||||||
</span>
|
|
||||||
<kbd
|
|
||||||
className="font-geist"
|
|
||||||
style={{
|
|
||||||
fontSize: '11px',
|
|
||||||
color: 'var(--text-tertiary)',
|
|
||||||
background: 'var(--bg-dashboard)',
|
|
||||||
border: '1px solid var(--border)',
|
|
||||||
padding: '2px 6px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
lineHeight: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Ctrl+K
|
|
||||||
</kbd>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{/* Session info (right) */}
|
|
||||||
<div
|
|
||||||
className="flex items-center gap-2 sm:gap-3 shrink-0"
|
|
||||||
aria-label="Active session information"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="hidden sm:inline"
|
|
||||||
style={{
|
|
||||||
fontSize: '13px',
|
|
||||||
color: 'var(--text-secondary)',
|
|
||||||
fontFamily: 'var(--font-ui)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
A.RECRUITER
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="font-geist hidden xs:inline"
|
|
||||||
style={{
|
|
||||||
fontSize: '12px',
|
|
||||||
color: 'var(--text-tertiary)',
|
|
||||||
background: 'var(--accent-light)',
|
|
||||||
padding: '3px 10px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid var(--accent-border)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Active Session · {currentTime}
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className="font-geist xs:hidden"
|
|
||||||
style={{
|
|
||||||
fontSize: '12px',
|
|
||||||
color: 'var(--text-tertiary)',
|
|
||||||
background: 'var(--accent-light)',
|
|
||||||
padding: '3px 8px',
|
|
||||||
borderRadius: '4px',
|
|
||||||
border: '1px solid var(--accent-border)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{currentTime}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatTime(date: Date): string {
|
|
||||||
return date.toLocaleTimeString('en-GB', {
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
hour12: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
import type { Problem } from '@/types/pmr'
|
|
||||||
|
|
||||||
export const problems: Problem[] = [
|
|
||||||
{
|
|
||||||
id: 'prob-budget',
|
|
||||||
code: 'MGT001',
|
|
||||||
description: '£220M prescribing budget oversight and management',
|
|
||||||
since: 'Jul 2024',
|
|
||||||
status: 'Active',
|
|
||||||
narrative: 'Responsible for managing the £220M prescribing budget for NHS Norfolk & Waveney ICB. Developed sophisticated forecasting models identifying cost pressures and enabling proactive financial planning. This is an ongoing responsibility requiring continuous monitoring and strategic intervention.',
|
|
||||||
linkedConsultations: ['deputy-head-2024'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'prob-sql-transform',
|
|
||||||
code: 'TRN001',
|
|
||||||
description: 'Patient-level SQL analytics transformation',
|
|
||||||
since: '2025',
|
|
||||||
status: 'In Progress',
|
|
||||||
narrative: 'Leading transformation from practice-level data to patient-level SQL analytics, enabling targeted interventions and a self-serve model for the wider team. This foundational change will unlock previously impossible analysis at population scale.',
|
|
||||||
linkedConsultations: ['interim-head-2025', 'deputy-head-2024'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'prob-data-literacy',
|
|
||||||
code: 'LEA001',
|
|
||||||
description: 'Team data literacy programme',
|
|
||||||
since: 'Jul 2024',
|
|
||||||
status: 'In Progress',
|
|
||||||
narrative: 'Educating colleagues on data interpretation and analytics best practices, improving data fluency across the team through training, documentation, and self-serve tools. Ongoing initiative to build sustainable analytical capability.',
|
|
||||||
linkedConsultations: ['deputy-head-2024'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'prob-efficiency',
|
|
||||||
code: 'EFF001',
|
|
||||||
description: 'Manual prescribing analysis inefficiency',
|
|
||||||
resolved: 'Oct 2025',
|
|
||||||
status: 'Resolved',
|
|
||||||
outcome: 'Python algorithm: 14,000 pts, £2.6M/yr',
|
|
||||||
narrative: 'Built Python-based switching algorithm using real-world GP prescribing data to automatically identify patients on expensive drugs suitable for cost-effective alternatives. Compressed months of manual analysis into 3 days. Identified 14,000 patients and £2.6M in annual savings, with £2M on target for delivery this financial year.',
|
|
||||||
linkedConsultations: ['interim-head-2025'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'prob-efficiency-target',
|
|
||||||
code: 'EFF002',
|
|
||||||
description: '£14.6M efficiency target identification and delivery',
|
|
||||||
resolved: 'Oct 2025',
|
|
||||||
status: 'Resolved',
|
|
||||||
outcome: 'Over-target performance achieved',
|
|
||||||
narrative: 'Identified and prioritised a £14.6M efficiency programme through comprehensive data analysis. Achieved over-target performance by October 2025 through targeted, evidence-based interventions across the integrated care system.',
|
|
||||||
linkedConsultations: ['interim-head-2025'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'prob-blueteq-backlog',
|
|
||||||
code: 'AUT001',
|
|
||||||
description: 'Blueteq form creation backlog',
|
|
||||||
resolved: '2023',
|
|
||||||
status: 'Resolved',
|
|
||||||
outcome: '70% reduction, 200hrs saved',
|
|
||||||
narrative: 'Developed software automating Blueteq prior approval form creation. Achieved 70% reduction in required forms, 200 hours immediate savings, and ongoing 7–8 hours weekly efficiency gains.',
|
|
||||||
linkedConsultations: ['high-cost-drugs-2022'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'prob-asthma-screening',
|
|
||||||
code: 'INN001',
|
|
||||||
description: 'Asthma screening scalability',
|
|
||||||
resolved: '2019',
|
|
||||||
status: 'Resolved',
|
|
||||||
outcome: 'National rollout: ~300 branches, ~£1M',
|
|
||||||
narrative: 'Identified and shared an asthma screening process that was adopted nationally across the Tesco pharmacy estate (~300 branches). Reduced pharmacist time from approximately 60 hours to 6 hours per store per month, enabling the network to claim approximately £1M in revenue.',
|
|
||||||
linkedConsultations: ['pharmacy-manager-2017'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'prob-incentive-calc',
|
|
||||||
code: 'AUT002',
|
|
||||||
description: 'Incentive scheme manual calculation',
|
|
||||||
resolved: '2025',
|
|
||||||
status: 'Resolved',
|
|
||||||
outcome: 'Automated: 50% Rx reduction in 2 months',
|
|
||||||
narrative: 'Automated incentive scheme analysis, improving accuracy and targeting precision whilst enabling a novel GP payment system linking rewards to delivered savings. Achieved 50% reduction in targeted prescribing within the first two months of deployment.',
|
|
||||||
linkedConsultations: ['interim-head-2025'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'prob-hcd-tracking',
|
|
||||||
code: 'DAT001',
|
|
||||||
description: 'High-cost drug spend tracking gaps',
|
|
||||||
resolved: '2023',
|
|
||||||
status: 'Resolved',
|
|
||||||
outcome: 'Blueteq-secondary care data integration',
|
|
||||||
narrative: 'Integrated Blueteq data with secondary care activity databases, resolving critical data-matching limitations and enabling accurate high-cost drug spend tracking across the system.',
|
|
||||||
linkedConsultations: ['high-cost-drugs-2022'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'prob-pathway-opacity',
|
|
||||||
code: 'VIS001',
|
|
||||||
description: 'Patient pathway opacity',
|
|
||||||
resolved: '2023',
|
|
||||||
status: 'Resolved',
|
|
||||||
outcome: 'Sankey chart analysis tool',
|
|
||||||
narrative: 'Created Python-based Sankey chart analysis tool visualising patient journeys through high-cost drug pathways, enabling trusts to audit compliance and identify improvement opportunities.',
|
|
||||||
linkedConsultations: ['high-cost-drugs-2022'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'prob-opioid-monitoring',
|
|
||||||
code: 'MON001',
|
|
||||||
description: 'Population opioid exposure monitoring',
|
|
||||||
resolved: '2024',
|
|
||||||
status: 'Resolved',
|
|
||||||
outcome: 'CD monitoring system: OME tracking',
|
|
||||||
narrative: 'Developed Python-based controlled drug monitoring system calculating oral morphine equivalents across all opioid prescriptions to track patient-level exposure over time, identifying high-risk patients and potential diversion—enabling previously impossible patient safety analysis at population scale.',
|
|
||||||
linkedConsultations: ['deputy-head-2024'],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
@@ -5,16 +5,11 @@ import type {
|
|||||||
EducationCopyEntry,
|
EducationCopyEntry,
|
||||||
ExperienceEducationUICopy,
|
ExperienceEducationUICopy,
|
||||||
LatestResultsCopy,
|
LatestResultsCopy,
|
||||||
ProfileContent,
|
|
||||||
QuickActionCopyEntry,
|
QuickActionCopyEntry,
|
||||||
SidebarCopy,
|
SidebarCopy,
|
||||||
SkillsUICopy,
|
SkillsUICopy,
|
||||||
} from '@/types/profile-content'
|
} from '@/types/profile-content'
|
||||||
|
|
||||||
export function getProfileContent(): DeepReadonly<ProfileContent> {
|
|
||||||
return profileContent
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getProfileSummaryText(): string {
|
export function getProfileSummaryText(): string {
|
||||||
return profileContent.profile.patientSummaryNarrative
|
return profileContent.profile.patientSummaryNarrative
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ export const DOT_COLORS = {
|
|||||||
purple: '#7C3AED',
|
purple: '#7C3AED',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export type DotColorName = keyof typeof DOT_COLORS
|
|
||||||
|
|
||||||
/** KPI color variants (subset of DOT_COLORS) */
|
/** KPI color variants (subset of DOT_COLORS) */
|
||||||
export const KPI_COLORS: Record<'green' | 'amber' | 'teal', string> = {
|
export const KPI_COLORS: Record<'green' | 'amber' | 'teal', string> = {
|
||||||
green: DOT_COLORS.green,
|
green: DOT_COLORS.green,
|
||||||
|
|||||||
@@ -1,12 +1,3 @@
|
|||||||
export function calculateSkillOffset(level: number, radius: number): number {
|
|
||||||
const circumference = 2 * Math.PI * radius
|
|
||||||
return circumference * (1 - level / 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatBootLine(text: string): string {
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
|
|
||||||
export function hexToRgba(hex: string, opacity: number): string {
|
export function hexToRgba(hex: string, opacity: number): string {
|
||||||
const r = parseInt(hex.slice(1, 3), 16)
|
const r = parseInt(hex.slice(1, 3), 16)
|
||||||
const g = parseInt(hex.slice(3, 5), 16)
|
const g = parseInt(hex.slice(3, 5), 16)
|
||||||
|
|||||||
@@ -1,41 +1 @@
|
|||||||
export interface Skill {
|
|
||||||
name: string
|
|
||||||
level: number
|
|
||||||
category: 'Technical' | 'Clinical' | 'Strategic'
|
|
||||||
color: 'teal' | 'coral'
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Experience {
|
|
||||||
role: string
|
|
||||||
org: string
|
|
||||||
date: string
|
|
||||||
bullets: string[]
|
|
||||||
isCurrent?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Education {
|
|
||||||
degree: string
|
|
||||||
institution: string
|
|
||||||
period: string
|
|
||||||
detail: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Project {
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
link?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ContactItem {
|
|
||||||
icon: 'phone' | 'mail' | 'linkedin' | 'mapPin'
|
|
||||||
value: string
|
|
||||||
label: string
|
|
||||||
href?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Phase = 'boot' | 'ecg' | 'login' | 'pmr'
|
export type Phase = 'boot' | 'ecg' | 'login' | 'pmr'
|
||||||
|
|
||||||
export interface BootLine {
|
|
||||||
html: string
|
|
||||||
delay: number
|
|
||||||
}
|
|
||||||
|
|||||||
+1
-45
@@ -48,34 +48,6 @@ export interface PrescribingHistoryEntry {
|
|||||||
description: string
|
description: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Medication {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
dose: number
|
|
||||||
frequency: 'Daily' | 'Weekly' | 'Monthly' | 'As needed'
|
|
||||||
startYear: number
|
|
||||||
status: 'Active' | 'Historical'
|
|
||||||
category: 'Active' | 'Clinical' | 'PRN'
|
|
||||||
prescribingHistory: PrescribingHistoryEntry[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Problem {
|
|
||||||
id: string
|
|
||||||
code: string
|
|
||||||
description: string
|
|
||||||
since?: string
|
|
||||||
resolved?: string
|
|
||||||
status: 'Active' | 'In Progress' | 'Resolved'
|
|
||||||
outcome?: string
|
|
||||||
narrative?: string
|
|
||||||
linkedConsultations?: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface InvestigationResult {
|
|
||||||
label: string
|
|
||||||
value: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Investigation {
|
export interface Investigation {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
@@ -123,23 +95,6 @@ export interface Patient {
|
|||||||
registrationYear: string
|
registrationYear: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ViewId = 'summary' | 'consultations' | 'medications' | 'problems' | 'investigations' | 'documents' | 'referrals'
|
|
||||||
|
|
||||||
export interface NavItem {
|
|
||||||
id: ViewId
|
|
||||||
label: string
|
|
||||||
icon: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ReferralFormData {
|
|
||||||
priority: 'Urgent' | 'Routine' | 'Two-Week Wait'
|
|
||||||
referrerName: string
|
|
||||||
referrerEmail: string
|
|
||||||
referrerOrg?: string
|
|
||||||
reason: string
|
|
||||||
contactMethod: 'Email' | 'Phone' | 'LinkedIn'
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Tag {
|
export interface Tag {
|
||||||
label: string
|
label: string
|
||||||
colorVariant: 'teal' | 'amber' | 'green'
|
colorVariant: 'teal' | 'amber' | 'green'
|
||||||
@@ -171,6 +126,7 @@ export interface SkillMedication {
|
|||||||
category: 'Technical' | 'Domain' | 'Leadership'
|
category: 'Technical' | 'Domain' | 'Leadership'
|
||||||
status: 'Active' | 'Historical'
|
status: 'Active' | 'Historical'
|
||||||
icon: string
|
icon: string
|
||||||
|
prescribingHistory?: PrescribingHistoryEntry[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skill categories for grouped display
|
// Skill categories for grouped display
|
||||||
|
|||||||
Reference in New Issue
Block a user