link start!
This commit is contained in:
@@ -0,0 +1,368 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Activity, AlertCircle, Clock, Users, Bell, Heart, Thermometer, Wind, CheckCircle, UserX } from 'lucide-react';
|
||||
|
||||
const StaffDashboard = () => {
|
||||
const [patients, setPatients] = useState([]);
|
||||
const [stats, setStats] = useState({
|
||||
total_patients: 0,
|
||||
active_patients: 0,
|
||||
tier_breakdown: { EMERGENCY: 0, ALERT: 0, NORMAL: 0 },
|
||||
average_wait_minutes: 0
|
||||
});
|
||||
const [selectedPatient, setSelectedPatient] = useState(null);
|
||||
const [filter, setFilter] = useState('all');
|
||||
|
||||
useEffect(() => {
|
||||
const generateMockPatients = () => {
|
||||
const mockPatients = [
|
||||
{
|
||||
patient_id: 'P100001',
|
||||
band_id: 'VitalLink-A1B2',
|
||||
name: 'John Smith',
|
||||
tier: 'NORMAL',
|
||||
priority_score: 15.2,
|
||||
wait_time_minutes: 22,
|
||||
last_hr: 76,
|
||||
last_spo2: 98,
|
||||
last_temp: 36.8,
|
||||
symptoms: ['Chest Pain', 'Nausea']
|
||||
},
|
||||
{
|
||||
patient_id: 'P100002',
|
||||
band_id: 'VitalLink-C3D4',
|
||||
name: 'Sarah Johnson',
|
||||
tier: 'ALERT',
|
||||
priority_score: 68.5,
|
||||
wait_time_minutes: 45,
|
||||
last_hr: 118,
|
||||
last_spo2: 93,
|
||||
last_temp: 38.4,
|
||||
symptoms: ['Fever', 'Difficulty Breathing']
|
||||
},
|
||||
{
|
||||
patient_id: 'P100003',
|
||||
band_id: 'VitalLink-E5F6',
|
||||
name: 'Michael Chen',
|
||||
tier: 'EMERGENCY',
|
||||
priority_score: 142.8,
|
||||
wait_time_minutes: 8,
|
||||
last_hr: 148,
|
||||
last_spo2: 86,
|
||||
last_temp: 39.7,
|
||||
symptoms: ['Severe Headache', 'Chest Pain']
|
||||
},
|
||||
{
|
||||
patient_id: 'P100004',
|
||||
band_id: 'VitalLink-G7H8',
|
||||
name: 'Emily Davis',
|
||||
tier: 'NORMAL',
|
||||
priority_score: 18.0,
|
||||
wait_time_minutes: 35,
|
||||
last_hr: 82,
|
||||
last_spo2: 97,
|
||||
last_temp: 37.1,
|
||||
symptoms: ['Abdominal Pain']
|
||||
},
|
||||
{
|
||||
patient_id: 'P100005',
|
||||
band_id: 'VitalLink-I9J0',
|
||||
name: 'Robert Williams',
|
||||
tier: 'ALERT',
|
||||
priority_score: 72.3,
|
||||
wait_time_minutes: 52,
|
||||
last_hr: 124,
|
||||
last_spo2: 91,
|
||||
last_temp: 38.8,
|
||||
symptoms: ['Fever', 'Dizziness']
|
||||
}
|
||||
];
|
||||
|
||||
setPatients(mockPatients);
|
||||
setStats({
|
||||
total_patients: 5,
|
||||
active_patients: 5,
|
||||
tier_breakdown: { EMERGENCY: 1, ALERT: 2, NORMAL: 2 },
|
||||
average_wait_minutes: 32.4
|
||||
});
|
||||
};
|
||||
|
||||
generateMockPatients();
|
||||
|
||||
const interval = setInterval(() => {
|
||||
setPatients(prev => prev.map(p => ({
|
||||
...p,
|
||||
wait_time_minutes: p.wait_time_minutes + 1,
|
||||
last_hr: Math.max(40, Math.min(180, p.last_hr + Math.floor(Math.random() * 5) - 2)),
|
||||
last_spo2: Math.max(70, Math.min(100, p.last_spo2 + Math.floor(Math.random() * 3) - 1)),
|
||||
last_temp: Math.max(35, Math.min(41, p.last_temp + (Math.random() * 0.2 - 0.1)))
|
||||
})));
|
||||
}, 3000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const getTierColor = (tier) => {
|
||||
switch(tier) {
|
||||
case 'EMERGENCY': return 'bg-red-100 text-red-800 border-red-300';
|
||||
case 'ALERT': return 'bg-yellow-100 text-yellow-800 border-yellow-300';
|
||||
case 'NORMAL': return 'bg-green-100 text-green-800 border-green-300';
|
||||
default: return 'bg-gray-100 text-gray-800 border-gray-300';
|
||||
}
|
||||
};
|
||||
|
||||
const getTierIcon = (tier) => {
|
||||
switch(tier) {
|
||||
case 'EMERGENCY': return <AlertCircle className="w-5 h-5" />;
|
||||
case 'ALERT': return <Bell className="w-5 h-5" />;
|
||||
case 'NORMAL': return <CheckCircle className="w-5 h-5" />;
|
||||
default: return <Activity className="w-5 h-5" />;
|
||||
}
|
||||
};
|
||||
|
||||
const getVitalStatus = (type, value) => {
|
||||
if (type === 'hr') {
|
||||
if (value > 110 || value < 50) return 'text-red-600 font-bold';
|
||||
if (value > 100 || value < 60) return 'text-yellow-600 font-semibold';
|
||||
return 'text-green-600';
|
||||
}
|
||||
if (type === 'spo2') {
|
||||
if (value < 88) return 'text-red-600 font-bold';
|
||||
if (value < 92) return 'text-yellow-600 font-semibold';
|
||||
return 'text-green-600';
|
||||
}
|
||||
if (type === 'temp') {
|
||||
if (value > 39.5 || value < 35.5) return 'text-red-600 font-bold';
|
||||
if (value > 38.3 || value < 36.0) return 'text-yellow-600 font-semibold';
|
||||
return 'text-green-600';
|
||||
}
|
||||
return 'text-gray-700';
|
||||
};
|
||||
|
||||
const handleDischarge = (patientId) => {
|
||||
setPatients(prev => prev.filter(p => p.patient_id !== patientId));
|
||||
setSelectedPatient(null);
|
||||
};
|
||||
|
||||
const filteredPatients = patients
|
||||
.filter(p => filter === 'all' || p.tier === filter)
|
||||
.sort((a, b) => b.priority_score - a.priority_score);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-100">
|
||||
<div className="bg-gradient-to-r from-blue-600 to-blue-700 text-white p-6 shadow-lg">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold mb-1">VitalLink Dashboard</h1>
|
||||
<p className="text-blue-100">Emergency Department Patient Monitoring</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="bg-white bg-opacity-20 rounded-lg px-4 py-2">
|
||||
<p className="text-sm text-blue-100">Last Update</p>
|
||||
<p className="text-lg font-semibold">{new Date().toLocaleTimeString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white border-b shadow-sm">
|
||||
<div className="max-w-7xl mx-auto p-6">
|
||||
<div className="grid grid-cols-4 gap-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="bg-blue-100 p-3 rounded-lg">
|
||||
<Users className="w-6 h-6 text-blue-600" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Active Patients</p>
|
||||
<p className="text-2xl font-bold text-gray-800">{stats.active_patients}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="bg-red-100 p-3 rounded-lg">
|
||||
<AlertCircle className="w-6 h-6 text-red-600" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Emergency</p>
|
||||
<p className="text-2xl font-bold text-red-600">{stats.tier_breakdown.EMERGENCY}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="bg-yellow-100 p-3 rounded-lg">
|
||||
<Bell className="w-6 h-6 text-yellow-600" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Alert</p>
|
||||
<p className="text-2xl font-bold text-yellow-600">{stats.tier_breakdown.ALERT}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="bg-green-100 p-3 rounded-lg">
|
||||
<Clock className="w-6 h-6 text-green-600" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Avg Wait Time</p>
|
||||
<p className="text-2xl font-bold text-gray-800">{stats.average_wait_minutes} min</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto p-6">
|
||||
<div className="bg-white rounded-lg shadow-sm p-4 mb-6">
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={() => setFilter('all')}
|
||||
className={`px-6 py-2 rounded-lg font-semibold transition-colors ${
|
||||
filter === 'all'
|
||||
? 'bg-blue-600 text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
All Patients ({patients.length})
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilter('EMERGENCY')}
|
||||
className={`px-6 py-2 rounded-lg font-semibold transition-colors ${
|
||||
filter === 'EMERGENCY'
|
||||
? 'bg-red-600 text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
Emergency ({stats.tier_breakdown.EMERGENCY})
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilter('ALERT')}
|
||||
className={`px-6 py-2 rounded-lg font-semibold transition-colors ${
|
||||
filter === 'ALERT'
|
||||
? 'bg-yellow-600 text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
Alert ({stats.tier_breakdown.ALERT})
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilter('NORMAL')}
|
||||
className={`px-6 py-2 rounded-lg font-semibold transition-colors ${
|
||||
filter === 'NORMAL'
|
||||
? 'bg-green-600 text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
Stable ({stats.tier_breakdown.NORMAL})
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
{filteredPatients.map((patient, index) => (
|
||||
<div
|
||||
key={patient.patient_id}
|
||||
className="bg-white rounded-lg shadow-sm hover:shadow-md transition-shadow"
|
||||
>
|
||||
<div className="p-6">
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="text-2xl font-bold text-gray-400 min-w-12 text-center pt-1">
|
||||
#{index + 1}
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-gray-800 mb-1">{patient.name}</h3>
|
||||
<div className="flex items-center gap-3 text-sm text-gray-600">
|
||||
<span className="font-mono">{patient.patient_id}</span>
|
||||
<span>•</span>
|
||||
<span className="font-mono">{patient.band_id}</span>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2 mt-2">
|
||||
{patient.symptoms.map(symptom => (
|
||||
<span key={symptom} className="bg-gray-100 text-gray-700 px-3 py-1 rounded-full text-xs font-medium">
|
||||
{symptom}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={`px-4 py-2 rounded-lg border-2 flex items-center gap-2 font-semibold ${getTierColor(patient.tier)}`}>
|
||||
{getTierIcon(patient.tier)}
|
||||
{patient.tier}
|
||||
</div>
|
||||
<button
|
||||
onClick={() => handleDischarge(patient.patient_id)}
|
||||
className="px-4 py-2 bg-gray-600 text-white rounded-lg hover:bg-gray-700 transition-colors flex items-center gap-2 font-semibold"
|
||||
>
|
||||
<UserX className="w-4 h-4" />
|
||||
Discharge
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-4 gap-4 pt-4 border-t">
|
||||
<div className="bg-gray-50 rounded-lg p-3">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<Heart className="w-4 h-4 text-gray-600" />
|
||||
<span className="text-xs text-gray-600 font-medium">Heart Rate</span>
|
||||
</div>
|
||||
<p className={`text-2xl font-bold ${getVitalStatus('hr', patient.last_hr)}`}>
|
||||
{patient.last_hr}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500 mt-1">bpm</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-gray-50 rounded-lg p-3">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<Wind className="w-4 h-4 text-gray-600" />
|
||||
<span className="text-xs text-gray-600 font-medium">SpO₂</span>
|
||||
</div>
|
||||
<p className={`text-2xl font-bold ${getVitalStatus('spo2', patient.last_spo2)}`}>
|
||||
{patient.last_spo2}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500 mt-1">%</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-gray-50 rounded-lg p-3">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<Thermometer className="w-4 h-4 text-gray-600" />
|
||||
<span className="text-xs text-gray-600 font-medium">Temperature</span>
|
||||
</div>
|
||||
<p className={`text-2xl font-bold ${getVitalStatus('temp', patient.last_temp)}`}>
|
||||
{patient.last_temp.toFixed(1)}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500 mt-1">°C</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-gray-50 rounded-lg p-3">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<Clock className="w-4 h-4 text-gray-600" />
|
||||
<span className="text-xs text-gray-600 font-medium">Wait Time</span>
|
||||
</div>
|
||||
<p className="text-2xl font-bold text-gray-700">
|
||||
{patient.wait_time_minutes}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500 mt-1">minutes</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{filteredPatients.length === 0 && (
|
||||
<div className="bg-white rounded-lg shadow-sm p-12 text-center">
|
||||
<Activity className="w-16 h-16 text-gray-300 mx-auto mb-4" />
|
||||
<h3 className="text-xl font-semibold text-gray-600 mb-2">No patients in this category</h3>
|
||||
<p className="text-gray-500">Patients will appear here as they check in</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(<StaffDashboard />);
|
||||
@@ -0,0 +1,265 @@
|
||||
import React, { useState } from 'react';
|
||||
import { AlertCircle, CheckCircle, Clock, User } from 'lucide-react';
|
||||
|
||||
const CheckInKiosk = () => {
|
||||
const [step, setStep] = useState('welcome');
|
||||
const [formData, setFormData] = useState({
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
dob: '',
|
||||
symptoms: [],
|
||||
severity: 'moderate'
|
||||
});
|
||||
const [assignedBand, setAssignedBand] = useState(null);
|
||||
|
||||
const symptoms = [
|
||||
'Chest Pain', 'Difficulty Breathing', 'Severe Headache',
|
||||
'Abdominal Pain', 'Fever', 'Nausea/Vomiting',
|
||||
'Dizziness', 'Injury/Trauma', 'Other'
|
||||
];
|
||||
|
||||
const handleSymptomToggle = (symptom) => {
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
symptoms: prev.symptoms.includes(symptom)
|
||||
? prev.symptoms.filter(s => s !== symptom)
|
||||
: [...prev.symptoms, symptom]
|
||||
}));
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
// Simulate API call to backend
|
||||
const patientId = `P${Date.now().toString().slice(-6)}`;
|
||||
const bandId = `VitalLink-${Math.floor(Math.random() * 65536).toString(16).toUpperCase().padStart(4, '0')}`;
|
||||
|
||||
setAssignedBand({
|
||||
patientId,
|
||||
bandId,
|
||||
station: Math.floor(Math.random() * 8) + 1
|
||||
});
|
||||
|
||||
// In production, send to backend:
|
||||
// await fetch('/api/checkin', { method: 'POST', body: JSON.stringify({...formData, patientId, bandId}) });
|
||||
|
||||
setStep('complete');
|
||||
};
|
||||
|
||||
if (step === 'welcome') {
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-blue-100 flex items-center justify-center p-4">
|
||||
<div className="bg-white rounded-2xl shadow-2xl p-12 max-w-2xl w-full text-center">
|
||||
<div className="mb-8">
|
||||
<div className="bg-blue-600 rounded-full w-24 h-24 flex items-center justify-center mx-auto mb-6">
|
||||
<User className="w-12 h-12 text-white" />
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold text-gray-800 mb-3">Welcome to VitalLink</h1>
|
||||
<p className="text-xl text-gray-600">Emergency Room Check-In</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4 mb-8 text-left bg-blue-50 p-6 rounded-xl">
|
||||
<h2 className="font-semibold text-lg text-gray-800 mb-3">What to expect:</h2>
|
||||
<div className="flex items-start gap-3">
|
||||
<CheckCircle className="w-5 h-5 text-green-600 mt-1 flex-shrink-0" />
|
||||
<p className="text-gray-700">Answer a few questions about your condition</p>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<CheckCircle className="w-5 h-5 text-green-600 mt-1 flex-shrink-0" />
|
||||
<p className="text-gray-700">Receive a smart wristband to monitor your vitals</p>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<CheckCircle className="w-5 h-5 text-green-600 mt-1 flex-shrink-0" />
|
||||
<p className="text-gray-700">Wait comfortably while we track your condition</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => setStep('form')}
|
||||
className="bg-blue-600 text-white px-12 py-4 rounded-xl text-xl font-semibold hover:bg-blue-700 transition-colors shadow-lg"
|
||||
>
|
||||
Start Check-In
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (step === 'form') {
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-blue-100 p-4">
|
||||
<div className="max-w-3xl mx-auto pt-8">
|
||||
<div className="bg-white rounded-2xl shadow-2xl p-8">
|
||||
<h2 className="text-3xl font-bold text-gray-800 mb-6">Patient Information</h2>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
First Name *
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.firstName}
|
||||
onChange={(e) => setFormData({...formData, firstName: e.target.value})}
|
||||
className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg focus:border-blue-500 focus:outline-none text-lg"
|
||||
placeholder="John"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Last Name *
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.lastName}
|
||||
onChange={(e) => setFormData({...formData, lastName: e.target.value})}
|
||||
className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg focus:border-blue-500 focus:outline-none text-lg"
|
||||
placeholder="Doe"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Date of Birth *
|
||||
</label>
|
||||
<input
|
||||
type="date"
|
||||
value={formData.dob}
|
||||
onChange={(e) => setFormData({...formData, dob: e.target.value})}
|
||||
className="w-full px-4 py-3 border-2 border-gray-300 rounded-lg focus:border-blue-500 focus:outline-none text-lg"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-3">
|
||||
Select Your Symptoms *
|
||||
</label>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
{symptoms.map((symptom) => (
|
||||
<button
|
||||
key={symptom}
|
||||
onClick={() => handleSymptomToggle(symptom)}
|
||||
className={`px-4 py-3 rounded-lg border-2 transition-all text-left font-medium ${
|
||||
formData.symptoms.includes(symptom)
|
||||
? 'bg-blue-100 border-blue-500 text-blue-700'
|
||||
: 'bg-white border-gray-300 text-gray-700 hover:border-blue-300'
|
||||
}`}
|
||||
>
|
||||
{symptom}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-3">
|
||||
How severe are your symptoms? *
|
||||
</label>
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
{['mild', 'moderate', 'severe'].map((level) => (
|
||||
<button
|
||||
key={level}
|
||||
onClick={() => setFormData({...formData, severity: level})}
|
||||
className={`px-6 py-4 rounded-lg border-2 transition-all font-semibold capitalize ${
|
||||
formData.severity === level
|
||||
? level === 'severe'
|
||||
? 'bg-red-100 border-red-500 text-red-700'
|
||||
: level === 'moderate'
|
||||
? 'bg-yellow-100 border-yellow-500 text-yellow-700'
|
||||
: 'bg-green-100 border-green-500 text-green-700'
|
||||
: 'bg-white border-gray-300 text-gray-700 hover:border-gray-400'
|
||||
}`}
|
||||
>
|
||||
{level}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4 mt-8">
|
||||
<button
|
||||
onClick={() => setStep('welcome')}
|
||||
className="flex-1 px-6 py-4 border-2 border-gray-300 text-gray-700 rounded-xl font-semibold hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
disabled={!formData.firstName || !formData.lastName || !formData.dob || formData.symptoms.length === 0}
|
||||
className="flex-1 px-6 py-4 bg-blue-600 text-white rounded-xl font-semibold hover:bg-blue-700 transition-colors disabled:bg-gray-300 disabled:cursor-not-allowed"
|
||||
>
|
||||
Complete Check-In
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (step === 'complete') {
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-green-50 to-green-100 flex items-center justify-center p-4">
|
||||
<div className="bg-white rounded-2xl shadow-2xl p-12 max-w-2xl w-full text-center">
|
||||
<div className="mb-6">
|
||||
<div className="bg-green-600 rounded-full w-24 h-24 flex items-center justify-center mx-auto mb-6">
|
||||
<CheckCircle className="w-12 h-12 text-white" />
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold text-gray-800 mb-3">Check-In Complete!</h1>
|
||||
<p className="text-xl text-gray-600">Your wristband has been assigned</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-gradient-to-r from-blue-500 to-blue-600 rounded-xl p-8 mb-8 text-white">
|
||||
<p className="text-sm uppercase tracking-wide mb-2 opacity-90">Your Patient ID</p>
|
||||
<p className="text-3xl font-bold mb-4">{assignedBand?.patientId}</p>
|
||||
<div className="border-t border-white/30 pt-4">
|
||||
<p className="text-sm uppercase tracking-wide mb-2 opacity-90">Wristband ID</p>
|
||||
<p className="text-2xl font-semibold">{assignedBand?.bandId}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4 text-left bg-blue-50 p-6 rounded-xl mb-8">
|
||||
<h2 className="font-bold text-lg text-gray-800 mb-3">Next Steps:</h2>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="bg-blue-600 text-white rounded-full w-8 h-8 flex items-center justify-center font-bold flex-shrink-0">1</div>
|
||||
<p className="text-gray-700 pt-1">
|
||||
<strong>Pick up your wristband</strong> from Station {assignedBand?.station}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="bg-blue-600 text-white rounded-full w-8 h-8 flex items-center justify-center font-bold flex-shrink-0">2</div>
|
||||
<p className="text-gray-700 pt-1">
|
||||
<strong>Wear it on your wrist</strong> - make sure it's snug but comfortable
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="bg-blue-600 text-white rounded-full w-8 h-8 flex items-center justify-center font-bold flex-shrink-0">3</div>
|
||||
<p className="text-gray-700 pt-1">
|
||||
<strong>Take a seat in the waiting area</strong> - your vitals are being monitored
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-center gap-2 text-gray-600 mb-6">
|
||||
<Clock className="w-5 h-5" />
|
||||
<p>A nurse will call you when it's your turn</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
setStep('welcome');
|
||||
setFormData({ firstName: '', lastName: '', dob: '', symptoms: [], severity: 'moderate' });
|
||||
setAssignedBand(null);
|
||||
}}
|
||||
className="text-blue-600 font-semibold hover:underline"
|
||||
>
|
||||
Return to Start
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default CheckInKiosk;
|
||||
Reference in New Issue
Block a user