92 lines
No EOL
3.4 KiB
TypeScript
92 lines
No EOL
3.4 KiB
TypeScript
import { Badge } from "@/components/ui/badge"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Activity, Pause, Play, Clock, AlertTriangle } from "lucide-react"
|
|
import { useBedPressureStore } from "@/stores/bedPressureStore"
|
|
import { useEffect, useState } from "react"
|
|
|
|
export function BedPressureHeader() {
|
|
const { isMonitoring, setIsMonitoring, sensorData } = useBedPressureStore()
|
|
const [countdowns, setCountdowns] = useState<Record<string, number>>({})
|
|
|
|
// Update countdowns every second
|
|
useEffect(() => {
|
|
const interval = setInterval(() => {
|
|
const newCountdowns: Record<string, number> = {}
|
|
const now = Date.now()
|
|
|
|
Object.values(sensorData).forEach(sensor => {
|
|
if (sensor.status === 'warning' && sensor.warningStartTime && sensor.warningDelayMs) {
|
|
const elapsed = now - sensor.warningStartTime
|
|
const remaining = Math.max(0, sensor.warningDelayMs - elapsed)
|
|
if (remaining > 0) {
|
|
newCountdowns[sensor.id] = remaining
|
|
}
|
|
}
|
|
})
|
|
|
|
setCountdowns(newCountdowns)
|
|
}, 1000)
|
|
|
|
return () => clearInterval(interval)
|
|
}, [sensorData])
|
|
|
|
const formatCountdown = (ms: number) => {
|
|
const minutes = Math.floor(ms / 60000)
|
|
const seconds = Math.floor((ms % 60000) / 1000)
|
|
return `${minutes}:${seconds.toString().padStart(2, '0')}`
|
|
}
|
|
|
|
const warningCountdowns = Object.entries(countdowns).filter(([, time]) => time > 0)
|
|
|
|
return (
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center gap-4">
|
|
<div className="flex items-center gap-2">
|
|
<Activity className="w-8 h-8 text-blue-600" />
|
|
<h1 className="text-3xl font-bold text-gray-900">Bed Pressure Monitor</h1>
|
|
</div>
|
|
<Badge variant={isMonitoring ? "default" : "secondary"} className="px-3 py-1">
|
|
{isMonitoring ? "Live" : "Paused"}
|
|
</Badge>
|
|
|
|
{/* Warning Countdown Indicators */}
|
|
{warningCountdowns.length > 0 && (
|
|
<div className="flex items-center gap-2">
|
|
{warningCountdowns.slice(0, 3).map(([sensorId, timeRemaining]) => {
|
|
const sensor = sensorData[sensorId]
|
|
return (
|
|
<div
|
|
key={sensorId}
|
|
className="flex items-center gap-1 px-2 py-1 bg-yellow-100 border border-yellow-300 rounded-md text-sm"
|
|
>
|
|
<AlertTriangle className="w-4 h-4 text-yellow-600" />
|
|
<span className="text-yellow-800 font-medium">
|
|
{sensor?.label}
|
|
</span>
|
|
<div className="flex items-center gap-1 text-yellow-700">
|
|
<Clock className="w-3 h-3" />
|
|
<span className="font-mono text-xs">
|
|
{formatCountdown(timeRemaining)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
{warningCountdowns.length > 3 && (
|
|
<Badge variant="secondary" className="text-xs">
|
|
+{warningCountdowns.length - 3} more
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2">
|
|
<Button variant="outline" size="sm" onClick={() => setIsMonitoring(!isMonitoring)}>
|
|
{isMonitoring ? <Pause className="w-4 h-4" /> : <Play className="w-4 h-4" />}
|
|
{isMonitoring ? "Pause" : "Resume"}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
)
|
|
} |