style: upgrade dashboard vitals cards with clinical SVGs and patient demographics banner
This commit is contained in:
@@ -428,6 +428,13 @@
|
|||||||
0 0 0 1px rgba(0, 0, 0, 0.02);
|
0 0 0 1px rgba(0, 0, 0, 0.02);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vital-card.hr:hover { border-color: rgba(220, 38, 38, 0.3); }
|
||||||
|
.vital-card.spo2:hover { border-color: rgba(8, 145, 178, 0.3); }
|
||||||
|
.vital-card.bp:hover { border-color: rgba(124, 58, 237, 0.3); }
|
||||||
|
.vital-card.rr:hover { border-color: rgba(22, 163, 74, 0.3); }
|
||||||
|
.vital-card.temp:hover { border-color: rgba(234, 88, 12, 0.3); }
|
||||||
|
.vital-card.map-card:hover { border-color: rgba(219, 39, 119, 0.3); }
|
||||||
|
|
||||||
.vital-card::before {
|
.vital-card::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -766,6 +773,98 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === Patient Clinical Info Banner === */
|
||||||
|
.patient-banner {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 16px 24px;
|
||||||
|
background: var(--bg-card);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 20px;
|
||||||
|
box-shadow:
|
||||||
|
0 4px 6px -1px rgba(0, 0, 0, 0.02),
|
||||||
|
0 10px 15px -3px rgba(0, 0, 0, 0.03);
|
||||||
|
margin-bottom: 24px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.patient-banner-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.patient-avatar {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(8, 145, 178, 0.08);
|
||||||
|
color: var(--spo2-color);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.patient-avatar svg {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.patient-label {
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-weight: 700;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.patient-value-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.patient-banner-divider {
|
||||||
|
height: 24px;
|
||||||
|
width: 1px;
|
||||||
|
background: var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vital-svg {
|
||||||
|
stroke-width: 2.5;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vital-card:hover .vital-svg {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vital-card.hr .card-icon { color: var(--hr-color); }
|
||||||
|
.vital-card.spo2 .card-icon { color: var(--spo2-color); }
|
||||||
|
.vital-card.bp .card-icon { color: var(--bp-color); }
|
||||||
|
.vital-card.rr .card-icon { color: var(--rr-color); }
|
||||||
|
.vital-card.temp .card-icon { color: var(--temp-color); }
|
||||||
|
.vital-card.map-card .card-icon { color: var(--map-color); }
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.patient-banner-divider {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.patient-banner {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.patient-banner {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* === Scrollbar === */
|
/* === Scrollbar === */
|
||||||
::-webkit-scrollbar { width: 6px; }
|
::-webkit-scrollbar { width: 6px; }
|
||||||
::-webkit-scrollbar-track { background: transparent; }
|
::-webkit-scrollbar-track { background: transparent; }
|
||||||
@@ -805,6 +904,50 @@
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<!-- Patient Clinical Info Banner -->
|
||||||
|
<div class="patient-banner">
|
||||||
|
<div class="patient-banner-group">
|
||||||
|
<div class="patient-avatar">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
|
||||||
|
<circle cx="12" cy="7" r="4"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="patient-label">Active Patient</div>
|
||||||
|
<div class="patient-value-text" id="bannerPatientName">John Doe</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="patient-banner-divider"></div>
|
||||||
|
<div class="patient-banner-group">
|
||||||
|
<div>
|
||||||
|
<div class="patient-label">Patient ID</div>
|
||||||
|
<div class="patient-value-text" id="bannerPatientId">N/A</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="patient-banner-divider"></div>
|
||||||
|
<div class="patient-banner-group">
|
||||||
|
<div>
|
||||||
|
<div class="patient-label">Location / Bed</div>
|
||||||
|
<div class="patient-value-text">ICU - Bed 12</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="patient-banner-divider"></div>
|
||||||
|
<div class="patient-banner-group">
|
||||||
|
<div>
|
||||||
|
<div class="patient-label">Monitor Status</div>
|
||||||
|
<div class="patient-value-text" id="bannerMonitorModel">CMS8500</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="patient-banner-divider"></div>
|
||||||
|
<div class="patient-banner-group">
|
||||||
|
<div>
|
||||||
|
<div class="patient-label">Last Transmission</div>
|
||||||
|
<div class="patient-value-text" id="bannerLastSeen">Never</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Setup Guide -->
|
<!-- Setup Guide -->
|
||||||
<div class="setup-guide" id="setupGuide">
|
<div class="setup-guide" id="setupGuide">
|
||||||
<div class="setup-guide-header" onclick="toggleSetupGuide()">
|
<div class="setup-guide-header" onclick="toggleSetupGuide()">
|
||||||
@@ -872,7 +1015,11 @@
|
|||||||
<div class="vital-card hr" id="card-hr">
|
<div class="vital-card hr" id="card-hr">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="card-label">
|
<div class="card-label">
|
||||||
<div class="card-icon">❤️</div>
|
<div class="card-icon">
|
||||||
|
<svg class="vital-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
<span class="card-name">Heart Rate</span>
|
<span class="card-name">Heart Rate</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="status-badge offline" id="status-hr">No Data</span>
|
<span class="status-badge offline" id="status-hr">No Data</span>
|
||||||
@@ -893,7 +1040,14 @@
|
|||||||
<div class="vital-card spo2" id="card-spo2">
|
<div class="vital-card spo2" id="card-spo2">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="card-label">
|
<div class="card-label">
|
||||||
<div class="card-icon">🫁</div>
|
<div class="card-icon">
|
||||||
|
<svg class="vital-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M7 3a3 3 0 0 0-3 3v6a3 3 0 0 0 3 3h1a2 2 0 0 0 2-2V6a3 3 0 0 0-3-3z"/>
|
||||||
|
<path d="M17 3a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3h-1a2 2 0 0 1-2-2V6a3 3 0 0 1 3-3z"/>
|
||||||
|
<path d="M9 20h6"/>
|
||||||
|
<path d="M12 16v4"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
<span class="card-name">SpO₂</span>
|
<span class="card-name">SpO₂</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="status-badge offline" id="status-spo2">No Data</span>
|
<span class="status-badge offline" id="status-spo2">No Data</span>
|
||||||
@@ -914,7 +1068,11 @@
|
|||||||
<div class="vital-card bp" id="card-bp">
|
<div class="vital-card bp" id="card-bp">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="card-label">
|
<div class="card-label">
|
||||||
<div class="card-icon">🩸</div>
|
<div class="card-icon">
|
||||||
|
<svg class="vital-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M12 22a7 7 0 0 0 7-7c0-4.3-7-13-7-13S5 10.7 5 15a7 7 0 0 0 7 7z"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
<span class="card-name">Blood Pressure</span>
|
<span class="card-name">Blood Pressure</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="status-badge offline" id="status-bp">No Data</span>
|
<span class="status-badge offline" id="status-bp">No Data</span>
|
||||||
@@ -935,7 +1093,13 @@
|
|||||||
<div class="vital-card rr" id="card-rr">
|
<div class="vital-card rr" id="card-rr">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="card-label">
|
<div class="card-label">
|
||||||
<div class="card-icon">🌬️</div>
|
<div class="card-icon">
|
||||||
|
<svg class="vital-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M2 8h16a4 4 0 0 1 4 4v0a4 4 0 0 1-4 4H2"/>
|
||||||
|
<path d="M6 12h12a2 2 0 0 0 2-2v0a2 2 0 0 0-2-2H6"/>
|
||||||
|
<path d="M2 16h8"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
<span class="card-name">Respiratory Rate</span>
|
<span class="card-name">Respiratory Rate</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="status-badge offline" id="status-rr">No Data</span>
|
<span class="status-badge offline" id="status-rr">No Data</span>
|
||||||
@@ -956,7 +1120,12 @@
|
|||||||
<div class="vital-card temp" id="card-temp">
|
<div class="vital-card temp" id="card-temp">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="card-label">
|
<div class="card-label">
|
||||||
<div class="card-icon">🌡️</div>
|
<div class="card-icon">
|
||||||
|
<svg class="vital-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M14 14.76V3.5a2.5 2.5 0 0 0-5 0v11.26a4.5 4.5 0 1 0 5 0z"/>
|
||||||
|
<line x1="11.5" y1="5" x2="11.5" y2="13"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
<span class="card-name">Temperature</span>
|
<span class="card-name">Temperature</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="status-badge offline" id="status-temp">No Data</span>
|
<span class="status-badge offline" id="status-temp">No Data</span>
|
||||||
@@ -977,7 +1146,11 @@
|
|||||||
<div class="vital-card map-card" id="card-map">
|
<div class="vital-card map-card" id="card-map">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="card-label">
|
<div class="card-label">
|
||||||
<div class="card-icon">💓</div>
|
<div class="card-icon">
|
||||||
|
<svg class="vital-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
<span class="card-name">Mean Arterial Pressure</span>
|
<span class="card-name">Mean Arterial Pressure</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="status-badge offline" id="status-map">No Data</span>
|
<span class="status-badge offline" id="status-map">No Data</span>
|
||||||
@@ -1191,6 +1364,12 @@
|
|||||||
});
|
});
|
||||||
document.getElementById('deviceId').textContent = 'Waiting...';
|
document.getElementById('deviceId').textContent = 'Waiting...';
|
||||||
document.getElementById('patientId').textContent = 'Waiting...';
|
document.getElementById('patientId').textContent = 'Waiting...';
|
||||||
|
|
||||||
|
document.getElementById('bannerPatientId').textContent = 'N/A';
|
||||||
|
document.getElementById('bannerPatientName').textContent = 'John Doe';
|
||||||
|
document.getElementById('bannerMonitorModel').textContent = 'CMS8500';
|
||||||
|
document.getElementById('bannerLastSeen').textContent = 'Never';
|
||||||
|
|
||||||
lastReadingId = null;
|
lastReadingId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1386,6 +1565,22 @@
|
|||||||
document.getElementById('lastUpdateTime').textContent =
|
document.getElementById('lastUpdateTime').textContent =
|
||||||
now.toLocaleTimeString('en-US', { hour12: false });
|
now.toLocaleTimeString('en-US', { hour12: false });
|
||||||
|
|
||||||
|
// Update patient clinical banner
|
||||||
|
if (data.patient_id) {
|
||||||
|
document.getElementById('bannerPatientId').textContent = data.patient_id;
|
||||||
|
document.getElementById('bannerPatientName').textContent = data.patient_name || `Patient #${data.patient_id}`;
|
||||||
|
}
|
||||||
|
if (data.device_id) {
|
||||||
|
let deviceModel = 'CMS8500';
|
||||||
|
if (data.device_id.includes('CMS7000')) {
|
||||||
|
deviceModel = 'CMS7000PLUS';
|
||||||
|
}
|
||||||
|
const parts = data.device_id.split('_');
|
||||||
|
const suffix = parts.length > 1 ? ` (${parts.pop()})` : '';
|
||||||
|
document.getElementById('bannerMonitorModel').textContent = `${deviceModel}${suffix}`;
|
||||||
|
}
|
||||||
|
document.getElementById('bannerLastSeen').textContent = now.toLocaleTimeString('en-US', { hour12: false });
|
||||||
|
|
||||||
// Push waveform data
|
// Push waveform data
|
||||||
pushWaveformPoint('hr', data.heart_rate);
|
pushWaveformPoint('hr', data.heart_rate);
|
||||||
pushWaveformPoint('spo2', data.spo2);
|
pushWaveformPoint('spo2', data.spo2);
|
||||||
|
|||||||
Reference in New Issue
Block a user