feature: Clinical Review Mode: Charts, Replay Controls & Alert Reasoning
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
export function formatTime(iso) {
|
||||
if (!iso) return ''
|
||||
return new Date(iso).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
|
||||
}
|
||||
|
||||
const CODE_COLORS = {
|
||||
HEART_RATE: '#ef4444',
|
||||
RESP_RATE: '#3b82f6',
|
||||
SYSTOLIC_BP: '#8b5cf6',
|
||||
SPO2: '#06b6d4',
|
||||
TEMP_C: '#f59e0b',
|
||||
}
|
||||
|
||||
export function getColorForCode(code) {
|
||||
return CODE_COLORS[code] ?? '#6b7280'
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { computed } from 'vue'
|
||||
import { formatTime, getColorForCode } from './chartFormat'
|
||||
|
||||
export function useChartData(observations, code) {
|
||||
const source = computed(() =>
|
||||
(typeof observations === 'function' ? observations() : observations) ?? [])
|
||||
|
||||
const chartData = computed(() => {
|
||||
const filtered = source.value
|
||||
.filter(o => o.observationCode === code)
|
||||
.sort((a, b) => new Date(a.recordedAt) - new Date(b.recordedAt))
|
||||
|
||||
return {
|
||||
labels: filtered.map(o => formatTime(o.recordedAt)),
|
||||
datasets: [{
|
||||
label: code,
|
||||
data: filtered.map(o => o.value),
|
||||
borderColor: getColorForCode(code),
|
||||
tension: 0.3,
|
||||
pointRadius: 4,
|
||||
}],
|
||||
}
|
||||
})
|
||||
|
||||
return { chartData }
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
export function useReplayControls() {
|
||||
const isPaused = ref(false)
|
||||
const speed = ref(60)
|
||||
const currentOffsetMinutes = ref(0)
|
||||
const scenarioDurationMinutes = ref(0)
|
||||
|
||||
const progress = computed(() =>
|
||||
scenarioDurationMinutes.value > 0
|
||||
? (currentOffsetMinutes.value / scenarioDurationMinutes.value) * 100
|
||||
: 0
|
||||
)
|
||||
|
||||
const formattedTime = computed(() => {
|
||||
const h = Math.floor(currentOffsetMinutes.value / 60)
|
||||
const m = Math.floor(currentOffsetMinutes.value % 60)
|
||||
return `${h}:${String(m).padStart(2, '0')}`
|
||||
})
|
||||
|
||||
function pause() { isPaused.value = true }
|
||||
function resume() { isPaused.value = false }
|
||||
function setSpeed(s) { speed.value = s }
|
||||
|
||||
function jumpToOffset(offset) {
|
||||
currentOffsetMinutes.value = offset
|
||||
}
|
||||
|
||||
return { isPaused, speed, currentOffsetMinutes, scenarioDurationMinutes, progress, formattedTime, pause, resume, setSpeed, jumpToOffset }
|
||||
}
|
||||
Reference in New Issue
Block a user