// Form configuration for all sepsis prediction input fields // Organized by category with metadata for dynamic form generation export interface ValidationRange { normal: { min: number; max: number }; // Normal range warning: { min: number; max: number }; // Warning range (show yellow) critical: { min: number; max: number }; // Critical range (show red) } export interface FieldConfig { name: string; label: string; type: 'number' | 'select' | 'text'; unit?: string; hasMinMax?: boolean; // If true, generates _min and _max fields IN PAYLOAD, but shows single input options?: { value: string; label: string }[]; required?: boolean; placeholder?: string; step?: string; validation?: ValidationRange; } export interface CategoryConfig { id: string; label: string; icon: string; // lucide icon name description: string; fields: FieldConfig[]; } export const formCategories: CategoryConfig[] = [ { id: 'demographics', label: 'Patient Demographics', icon: 'User', description: 'Basic patient information and identifiers', fields: [ { name: 'age', label: 'Age', type: 'number', unit: 'years', required: true, placeholder: '65', validation: { normal: { min: 18, max: 100 }, warning: { min: 0, max: 120 }, critical: { min: 0, max: 150 } } }, { name: 'f0_', label: 'Gender', type: 'select', required: true, options: [ { value: 'M', label: 'Male' }, { value: 'F', label: 'Female' } ] }, { name: 'height', label: 'Height', type: 'number', unit: 'cm', placeholder: '170', validation: { normal: { min: 100, max: 220 }, warning: { min: 50, max: 250 }, critical: { min: 30, max: 300 } } }, ] }, { id: 'vitals', label: 'Vital Signs', icon: 'Activity', description: 'Core vital sign measurements', fields: [ { name: 'heart_rate', label: 'Heart Rate', type: 'number', unit: 'bpm', hasMinMax: true, validation: { normal: { min: 60, max: 100 }, warning: { min: 40, max: 150 }, critical: { min: 20, max: 250 } } }, { name: 'sbp', label: 'Systolic BP', type: 'number', unit: 'mmHg', hasMinMax: true, validation: { normal: { min: 90, max: 140 }, warning: { min: 70, max: 180 }, critical: { min: 40, max: 260 } } }, { name: 'dbp', label: 'Diastolic BP', type: 'number', unit: 'mmHg', hasMinMax: true, validation: { normal: { min: 60, max: 90 }, warning: { min: 40, max: 120 }, critical: { min: 20, max: 180 } } }, { name: 'mbp', label: 'Mean Arterial Pressure', type: 'number', unit: 'mmHg', hasMinMax: true, validation: { normal: { min: 70, max: 100 }, warning: { min: 50, max: 130 }, critical: { min: 30, max: 180 } } }, { name: 'resp_rate', label: 'Respiratory Rate', type: 'number', unit: '/min', hasMinMax: true, validation: { normal: { min: 12, max: 20 }, warning: { min: 8, max: 35 }, critical: { min: 4, max: 60 } } }, { name: 'temperature', label: 'Temperature', type: 'number', unit: '°C', hasMinMax: true, step: '0.1', validation: { normal: { min: 36, max: 37.5 }, warning: { min: 35, max: 40 }, critical: { min: 30, max: 45 } } }, { name: 'spo2', label: 'SpO2', type: 'number', unit: '%', hasMinMax: true, validation: { normal: { min: 95, max: 100 }, warning: { min: 88, max: 100 }, critical: { min: 50, max: 100 } } }, { name: 'glucose', label: 'Glucose', type: 'number', unit: 'mg/dL', hasMinMax: true, validation: { normal: { min: 70, max: 140 }, warning: { min: 40, max: 300 }, critical: { min: 10, max: 600 } } }, ] }, { id: 'labs', label: 'Laboratory Results', icon: 'Beaker', description: 'Complete blood count and chemistry panel', fields: [ { name: 'wbc', label: 'WBC', type: 'number', unit: 'K/µL', hasMinMax: true, validation: { normal: { min: 4, max: 11 }, warning: { min: 1, max: 25 }, critical: { min: 0, max: 100 } } }, { name: 'platelet', label: 'Platelets', type: 'number', unit: 'K/µL', hasMinMax: true, validation: { normal: { min: 150, max: 400 }, warning: { min: 50, max: 600 }, critical: { min: 0, max: 1000 } } }, { name: 'hemoglobin', label: 'Hemoglobin', type: 'number', unit: 'g/dL', hasMinMax: true, validation: { normal: { min: 12, max: 17 }, warning: { min: 7, max: 20 }, critical: { min: 3, max: 25 } } }, { name: 'neutrophils_abs', label: 'Neutrophils (Abs)', type: 'number', unit: 'K/µL', hasMinMax: true }, { name: 'bands', label: 'Bands', type: 'number', unit: '%', hasMinMax: true }, { name: 'immature_granulocytes', label: 'Immature Granulocytes', type: 'number', unit: '%', hasMinMax: true }, { name: 'lymphocytes_abs', label: 'Lymphocytes (Abs)', type: 'number', unit: 'K/µL', hasMinMax: true }, { name: 'fibrinogen', label: 'Fibrinogen', type: 'number', unit: 'mg/dL', hasMinMax: true }, { name: 'inr', label: 'INR', type: 'number', hasMinMax: true, step: '0.1', validation: { normal: { min: 0.8, max: 1.2 }, warning: { min: 0.5, max: 5 }, critical: { min: 0, max: 10 } } }, { name: 'pt', label: 'PT', type: 'number', unit: 'sec', hasMinMax: true }, { name: 'antibiotic_count', label: 'Antibiotic Count', type: 'number', placeholder: '0' }, ] }, { id: 'bloodgas', label: 'Blood Gas Analysis', icon: 'Wind', description: 'Arterial blood gas and oxygenation parameters', fields: [ { name: 'so2', label: 'SaO2', type: 'number', unit: '%', hasMinMax: true }, { name: 'po2', label: 'PaO2', type: 'number', unit: 'mmHg', hasMinMax: true }, { name: 'pco2', label: 'PaCO2', type: 'number', unit: 'mmHg', hasMinMax: true }, { name: 'fio2', label: 'FiO2', type: 'number', unit: '%', hasMinMax: true }, { name: 'pfratio', label: 'P/F Ratio', type: 'number', hasMinMax: true }, { name: 'ventilation_flag', label: 'On Ventilation', type: 'select', options: [ { value: '0', label: 'No' }, { value: '1', label: 'Yes' } ] }, { name: 'ph', label: 'pH', type: 'number', hasMinMax: true, step: '0.01', validation: { normal: { min: 7.35, max: 7.45 }, warning: { min: 7.1, max: 7.6 }, critical: { min: 6.8, max: 7.8 } } }, { name: 'baseexcess', label: 'Base Excess', type: 'number', unit: 'mEq/L', hasMinMax: true }, { name: 'bicarbonate', label: 'Bicarbonate', type: 'number', unit: 'mEq/L', hasMinMax: true }, { name: 'totalco2', label: 'Total CO2', type: 'number', unit: 'mEq/L', hasMinMax: true }, { name: 'lactate', label: 'Lactate', type: 'number', unit: 'mmol/L', hasMinMax: true, validation: { normal: { min: 0.5, max: 2 }, warning: { min: 0, max: 4 }, critical: { min: 0, max: 20 } } }, ] }, { id: 'electrolytes', label: 'Electrolytes', icon: 'Droplets', description: 'Serum electrolyte panel', fields: [ { name: 'sodium', label: 'Sodium', type: 'number', unit: 'mEq/L', hasMinMax: true, validation: { normal: { min: 136, max: 145 }, warning: { min: 120, max: 160 }, critical: { min: 100, max: 180 } } }, { name: 'potassium', label: 'Potassium', type: 'number', unit: 'mEq/L', hasMinMax: true, step: '0.1', validation: { normal: { min: 3.5, max: 5 }, warning: { min: 2.5, max: 6.5 }, critical: { min: 1.5, max: 8 } } }, { name: 'chloride', label: 'Chloride', type: 'number', unit: 'mEq/L', hasMinMax: true }, { name: 'calcium', label: 'Calcium', type: 'number', unit: 'mg/dL', hasMinMax: true, step: '0.1' }, { name: 'glucose_1', label: 'Glucose (Lab)', type: 'number', unit: 'mg/dL', hasMinMax: true }, { name: 'albumin', label: 'Albumin', type: 'number', unit: 'g/dL', hasMinMax: true, step: '0.1' }, { name: 'aniongap', label: 'Anion Gap', type: 'number', unit: 'mEq/L', hasMinMax: true }, { name: 'bun', label: 'BUN', type: 'number', unit: 'mg/dL', hasMinMax: true, validation: { normal: { min: 7, max: 20 }, warning: { min: 3, max: 50 }, critical: { min: 0, max: 150 } } }, { name: 'creatinine', label: 'Creatinine', type: 'number', unit: 'mg/dL', hasMinMax: true, step: '0.1', validation: { normal: { min: 0.6, max: 1.2 }, warning: { min: 0.3, max: 5 }, critical: { min: 0, max: 15 } } }, { name: 'total_protein', label: 'Total Protein', type: 'number', unit: 'g/dL', hasMinMax: true }, { name: 'globulin', label: 'Globulin', type: 'number', unit: 'g/dL', hasMinMax: true }, ] }, { id: 'liver', label: 'Liver Function', icon: 'Pill', description: 'Hepatic function and enzyme levels', fields: [ { name: 'alt', label: 'ALT', type: 'number', unit: 'U/L', hasMinMax: true, validation: { normal: { min: 7, max: 56 }, warning: { min: 0, max: 200 }, critical: { min: 0, max: 1000 } } }, { name: 'ast', label: 'AST', type: 'number', unit: 'U/L', hasMinMax: true, validation: { normal: { min: 10, max: 40 }, warning: { min: 0, max: 200 }, critical: { min: 0, max: 1000 } } }, { name: 'alp', label: 'Alkaline Phosphatase', type: 'number', unit: 'U/L', hasMinMax: true }, { name: 'ggt', label: 'GGT', type: 'number', unit: 'U/L', hasMinMax: true }, { name: 'bilirubin_total', label: 'Bilirubin (Total)', type: 'number', unit: 'mg/dL', hasMinMax: true, step: '0.1', validation: { normal: { min: 0.1, max: 1.2 }, warning: { min: 0, max: 5 }, critical: { min: 0, max: 30 } } }, { name: 'bilirubin_direct', label: 'Bilirubin (Direct)', type: 'number', unit: 'mg/dL', hasMinMax: true, step: '0.1' }, { name: 'bilirubin_indirect', label: 'Bilirubin (Indirect)', type: 'number', unit: 'mg/dL', hasMinMax: true, step: '0.1' }, ] }, { id: 'neuro', label: 'Neurological', icon: 'Brain', description: 'Glasgow Coma Scale and CNS assessment', fields: [ { name: 'gcs', label: 'GCS Total', type: 'number', hasMinMax: true, validation: { normal: { min: 15, max: 15 }, warning: { min: 9, max: 14 }, critical: { min: 3, max: 8 } } }, { name: 'gcs_motor', label: 'GCS Motor', type: 'number', hasMinMax: true, validation: { normal: { min: 6, max: 6 }, warning: { min: 4, max: 5 }, critical: { min: 1, max: 3 } } }, { name: 'gcs_verbal', label: 'GCS Verbal', type: 'number', hasMinMax: true, validation: { normal: { min: 5, max: 5 }, warning: { min: 3, max: 4 }, critical: { min: 1, max: 2 } } }, { name: 'gcs_eyes', label: 'GCS Eyes', type: 'number', hasMinMax: true, validation: { normal: { min: 4, max: 4 }, warning: { min: 3, max: 3 }, critical: { min: 1, max: 2 } } }, ] }, { id: 'cardiac', label: 'Cardiac & Inflammation', icon: 'Heart', description: 'Cardiac biomarkers and inflammatory markers', fields: [ { name: 'crp', label: 'CRP', type: 'number', unit: 'mg/L', hasMinMax: true, validation: { normal: { min: 0, max: 10 }, warning: { min: 0, max: 50 }, critical: { min: 0, max: 500 } } }, { name: 'urineoutput', label: 'Urine Output', type: 'number', unit: 'mL/hr', hasMinMax: true, validation: { normal: { min: 30, max: 100 }, warning: { min: 10, max: 200 }, critical: { min: 0, max: 500 } } }, { name: 'troponin_t', label: 'Troponin T', type: 'number', unit: 'ng/mL', hasMinMax: true, step: '0.001' }, { name: 'ck_mb', label: 'CK-MB', type: 'number', unit: 'ng/mL', hasMinMax: true }, { name: 'ntprobnp', label: 'NT-proBNP', type: 'number', unit: 'pg/mL', hasMinMax: true }, ] }, ]; // Get validation status for a value export function getValidationStatus(field: FieldConfig, value: string): 'normal' | 'warning' | 'critical' | 'invalid' | null { if (!field.validation || value === '' || value === null || value === undefined) { return null; } const numValue = parseFloat(value); if (isNaN(numValue)) return null; const { normal, warning, critical } = field.validation; // Check if outside critical range (invalid) if (numValue < critical.min || numValue > critical.max) { return 'invalid'; } // Check normal range if (numValue >= normal.min && numValue <= normal.max) { return 'normal'; } // Check warning range if (numValue >= warning.min && numValue <= warning.max) { return 'warning'; } // Outside warning but inside critical = critical return 'critical'; } // Helper to generate field keys for form state export function generateFormFields(): Record { const fields: Record = {}; formCategories.forEach(category => { category.fields.forEach(field => { // Simplified: Just one field for the input fields[field.name] = field.type === 'select' && field.options ? field.options[0]?.value : ''; }); }); return fields; } // Helper to prepare payload for API export function preparePayload(formData: Record): Record { const payload: Record = {}; // First copy all known fields Object.entries(formData).forEach(([key, value]) => { if (value === '' || value === null || value === undefined) { return; } const numValue = parseFloat(value as string); payload[key] = isNaN(numValue) ? value : numValue; }); // Now auto-populate min/max if they don't exist // Loop through all defined categories/fields formCategories.forEach(category => { category.fields.forEach(field => { if (field.hasMinMax) { const val = formData[field.name]; if (val !== '' && val !== null && val !== undefined) { const numVal = parseFloat(val); if (!isNaN(numVal)) { // Assuming single measurement means min = max = value payload[`${field.name}_min`] = numVal; payload[`${field.name}_max`] = numVal; } } } }); }); return payload; }