Overview
MediGuide tracks 11 essential biometric parameters to provide comprehensive health monitoring. All data is stored with timestamps and associated with individual user accounts.
Tracked Parameters
The system monitors the following health metrics:
Glucose Level Blood glucose measurement in mg/dL
Range: 0-999 mg/dL
Type: Number (integer)
Blood Oxygen Oxygen saturation (SpO₂) percentage
Range: 0-100%
Type: Number (integer)
Blood Pressure Systolic and Diastolic measurements
Systolic: 0-300 mmHg
Diastolic: 0-200 mmHg
Body Temperature Core body temperature in Celsius
Range: 0-50°C
Type: Number (decimal, step 0.1)
Heart Rate Beats per minute (bpm)
Range: 0-300 bpm
Type: Number (integer)
Respiratory Rate Breaths per minute
Range: 0-150 resp/min
Type: Number (integer)
Age Patient age in years
Range: 0-150 years
Type: Number (integer)
Height Body height in meters
Range: 0-3 meters
Type: Number (decimal, step 0.01)
Weight Body weight in kilograms
Range: 0-500 kg
Type: Number (decimal, step 0.1)
Blood Type ABO blood type classification
Options: O+, O-, A+, A-, B+, B-, AB+, AB-
The medical tracking form collects all parameters with proper validation:
const [ formData , setFormData ] = useState ({
glucose: '' ,
oxygenBlood: '' ,
bloodPressureSystolic: '' ,
bloodPressureDiastolic: '' ,
temperature: '' ,
age: '' ,
height: '' ,
weight: '' ,
respiratoryRate: '' ,
bloodType: '' ,
heartRate: ''
});
Field Specifications
Glucose
Oxygen Saturation
Blood Pressure
Temperature
Heart Rate
Respiratory Rate
Biometrics
Blood Type
< label htmlFor = 'Glucose' > Nivel de Glucosa (mg/dl) </ label >
< input
type = 'number'
name = 'glucose'
id = 'Glucose'
value = { formData . glucose }
onChange = { handleChange }
min = "0"
max = "999"
required
/>
< label htmlFor = 'OxigenBlood' > Oxigenación de la sangre (%) </ label >
< input
type = 'number'
name = 'oxygenBlood'
id = 'OxigenBlood'
value = { formData . oxygenBlood }
onChange = { handleChange }
min = "0"
max = "100"
required
/>
{ /* Systolic */ }
< label htmlFor = 'BloodPresSystolic' >
Presión Arterial Sistólica - (Número superior) (mmHg)
</ label >
< input
type = 'number'
name = 'bloodPressureSystolic'
id = 'BloodPresSystolic'
value = { formData . bloodPressureSystolic }
onChange = { handleChange }
min = "0"
max = "300"
required
/>
{ /* Diastolic */ }
< label htmlFor = 'BloodPresDiastolic' >
Presión Arterial Diastólica - (Número inferior) (mmHg)
</ label >
< input
type = 'number'
name = 'bloodPressureDiastolic'
id = 'BloodPresDiastolic'
value = { formData . bloodPressureDiastolic }
onChange = { handleChange }
min = "0"
max = "200"
required
/>
< label htmlFor = 'Temperature' > Temperatura Corporal (C°) </ label >
< input
type = 'number'
name = 'temperature'
id = 'Temperature'
value = { formData . temperature }
onChange = { handleChange }
min = "0"
max = "50"
step = "0.1"
required
/>
< label htmlFor = 'HeartRate' > Frecuencia Cardíaca (lat/min) </ label >
< input
type = 'number'
name = 'heartRate'
id = 'HeartRate'
value = { formData . heartRate }
onChange = { handleChange }
min = "0"
max = "300"
required
/>
< label htmlFor = 'RespiratoryRate' > Frecuencia Respiratoria (resp/min) </ label >
< input
type = 'number'
name = 'respiratoryRate'
id = 'RespiratoryRate'
value = { formData . respiratoryRate }
onChange = { handleChange }
min = "0"
max = "150"
required
/>
{ /* Age */ }
< label htmlFor = 'Age' > Edad (Años) </ label >
< input
type = 'number'
name = 'age'
id = 'Age'
value = { formData . age }
onChange = { handleChange }
min = "0"
max = "150"
required
/>
{ /* Height */ }
< label htmlFor = 'Height' > Altura (Metros) </ label >
< input
type = 'number'
name = 'height'
id = 'Height'
value = { formData . height }
onChange = { handleChange }
step = "0.01"
min = "0"
max = "3"
required
/>
{ /* Weight */ }
< label htmlFor = 'Weight' > Peso (Kilogramos) </ label >
< input
type = 'number'
name = 'weight'
id = 'Weight'
value = { formData . weight }
onChange = { handleChange }
step = "0.1"
min = "0"
max = "500"
required
/>
< label htmlFor = 'BloodType' > Tipo de Sangre </ label >
< select
name = 'bloodType'
id = 'BloodType'
value = { formData . bloodType }
onChange = { handleChange }
required
>
< option value = "" ></ option >
< option value = "O+" > O+ </ option >
< option value = "O-" > O- </ option >
< option value = "A+" > A+ </ option >
< option value = "A-" > A- </ option >
< option value = "B+" > B+ </ option >
< option value = "B-" > B- </ option >
< option value = "AB+" > AB+ </ option >
< option value = "AB-" > AB- </ option >
</ select >
Data Submission
API Endpoint
POST / api / medical - info
Content - Type : application / json
Request Body
All 11 parameters plus userId:
{
"userId" : 123 ,
"glucose" : 95 ,
"oxygenBlood" : 98 ,
"bloodPressureSystolic" : 120 ,
"bloodPressureDiastolic" : 80 ,
"temperature" : 36.5 ,
"age" : 35 ,
"height" : 1.75 ,
"weight" : 70.5 ,
"respiratoryRate" : 16 ,
"bloodType" : "O+" ,
"heartRate" : 72
}
Implementation
const handleSubmit = async ( e ) => {
e . preventDefault ();
setLoading ( true );
setMessage ( '' );
try {
const userId = localStorage . getItem ( 'userId' );
const response = await fetch ( 'http://localhost:3001/api/medical-info' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ({ ... formData , userId })
});
const data = await response . json ();
if ( response . ok ) {
setMessage ( '¡Información guardada exitosamente!' );
medicalDataEmitter . emit (); // Trigger real-time updates
// Reset form
setFormData ({
glucose: '' ,
oxygenBlood: '' ,
bloodPressureSystolic: '' ,
bloodPressureDiastolic: '' ,
temperature: '' ,
age: '' ,
height: '' ,
weight: '' ,
respiratoryRate: '' ,
bloodType: '' ,
heartRate: ''
});
} else {
setMessage ( `Error: ${ data . error } ` );
}
} catch ( error ) {
setMessage ( `Error de conexión: ${ error . message } ` );
} finally {
setLoading ( false );
}
};
Success Response
{
"message" : "Medical record saved" ,
"id" : 456
}
Data Retrieval
Get Latest Medical Record
Endpoint: GET /api/medical-info/latest?userId={userId}
const fetchMedicalData = async () => {
const userId = localStorage . getItem ( 'userId' );
const response = await fetch (
`http://localhost:3001/api/medical-info/latest?userId= ${ userId } `
);
const data = await response . json ();
if ( response . ok ) {
setMedicalData ( data );
}
};
Response Structure
{
"id" : 456 ,
"user_id" : 123 ,
"glucose" : 95 ,
"oxygen_blood" : 98 ,
"blood_pressure_systolic" : 120 ,
"blood_pressure_diastolic" : 80 ,
"temperature" : 36.5 ,
"age" : 35 ,
"height" : 1.75 ,
"weight" : 70.5 ,
"respiratory_rate" : 16 ,
"blood_type" : "O+" ,
"heart_rate" : 72 ,
"created_at" : "2026-03-05T14:30:00.000Z"
}
Database Schema
CREATE TABLE medical_records (
id SERIAL PRIMARY KEY ,
user_id INTEGER NOT NULL ,
glucose NUMERIC ,
oxygen_blood NUMERIC ,
blood_pressure_systolic NUMERIC ,
blood_pressure_diastolic NUMERIC ,
temperature NUMERIC ,
age INTEGER ,
height NUMERIC ,
weight NUMERIC ,
respiratory_rate NUMERIC ,
blood_type VARCHAR ,
heart_rate NUMERIC ,
created_at TIMESTAMP DEFAULT NOW ()
);
Real-Time Updates
The system uses an event emitter for real-time data synchronization:
import { medicalDataEmitter } from '../utils/medicalDataContext' ;
// After successful save
medicalDataEmitter . emit ();
// Subscribe to updates in other components
useEffect (() => {
const unsubscribe = medicalDataEmitter . subscribe (() => {
console . log ( 'Medical data updated, refreshing...' );
fetchMedicalData ();
});
return unsubscribe ;
}, []);
Client-Side Validation
Required Fields
All 11 parameters are marked as required, preventing form submission with missing data.
Numeric Ranges
Each input has min and max attributes to enforce valid ranges.
Decimal Precision
Temperature (step 0.1), height (step 0.01), and weight (step 0.1) allow decimal values.
Dropdown Selection
Blood type uses a dropdown to ensure only valid values (O+, O-, A+, A-, B+, B-, AB+, AB-) are submitted.
Field Name Mapping
Note the difference between client-side field names (camelCase) and database column names (snake_case):
oxygenBlood → oxygen_blood
bloodPressureSystolic → blood_pressure_systolic
bloodPressureDiastolic → blood_pressure_diastolic
respiratoryRate → respiratory_rate
bloodType → blood_type
heartRate → heart_rate
Loading States
const [ loading , setLoading ] = useState ( false );
< button type = 'submit' disabled = { loading } >
{ loading ? 'Guardando...' : 'Guardar Información' }
</ button >
User Feedback
Dynamic messaging based on operation result:
const [ message , setMessage ] = useState ( '' );
{ message && (
< p style = { { color: message . includes ( 'Error' ) ? 'red' : 'green' } } >
{ message }
</ p >
)}
State Management
const handleChange = ( e ) => {
const { name , value } = e . target ;
setFormData ( prev => ({
... prev ,
[name]: value
}));
};
Medical data is associated with the logged-in user via userId from localStorage. Ensure users are authenticated before submitting medical information.