diff --git a/Controllers/HomeController.cs b/Controllers/HomeController.cs index a028ade..e78f796 100644 --- a/Controllers/HomeController.cs +++ b/Controllers/HomeController.cs @@ -1,23 +1,61 @@ using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using SimpleLIS.Models; +using SimpleLIS.Services; namespace SimpleLIS.Controllers; public class HomeController : Controller { private readonly ILogger _logger; + private readonly MessageService _messageService; + private readonly PatientService _patientService; + private readonly ObservationService _observationService; - public HomeController(ILogger logger) + public HomeController( + ILogger logger, + MessageService messageService, + PatientService patientService, + ObservationService observationService) { _logger = logger; + _messageService = messageService; + _patientService = patientService; + _observationService = observationService; } - public IActionResult Index() + public async Task Index() { + var patients = await _patientService.ListPatientsAsync(); + var messages = await _messageService.ListMessagesAsync(); + var observations = await _observationService.ListObservationsAsync(); + + ViewBag.TotalPatients = patients.Count(); + ViewBag.TotalMessages = messages.Count(); + ViewBag.TotalObservations = observations.Count(); + ViewBag.RecentMessages = messages.OrderByDescending(m => m.Timestamp).Take(5); + return View(); } + public async Task Patients() + { + var patients = await _patientService.ListPatientsAsync(); + return View(patients); + } + + public async Task Messages() + { + var messages = await _messageService.ListMessagesAsync(); + return View(messages.OrderByDescending(m => m.Timestamp)); + } + + public async Task Observations() + { + var observations = await _observationService.ListObservationsAsync(); + return View(observations); + } + public IActionResult Privacy() { return View(); diff --git a/Services/MessageService.cs b/Services/MessageService.cs index 3a2dc9a..b79b861 100644 --- a/Services/MessageService.cs +++ b/Services/MessageService.cs @@ -28,7 +28,10 @@ public class MessageService public async Task> ListMessagesAsync() { - return await _context.Messages.Include(m => m.Observations).ToListAsync(); + return await _context.Messages + .Include(m => m.Observations) + .Include(m => m.Patient) + .ToListAsync(); } public async Task UpdateMessageAsync(Message message) diff --git a/Services/ObservationService.cs b/Services/ObservationService.cs index 1fd2678..6872e76 100644 --- a/Services/ObservationService.cs +++ b/Services/ObservationService.cs @@ -28,7 +28,10 @@ public class ObservationService public async Task> ListObservationsAsync() { - return await _context.Observations.Include(o => o.Message).ToListAsync(); + return await _context.Observations + .Include(o => o.Message) + .ThenInclude(m => m.Patient) + .ToListAsync(); } public async Task UpdateObservationAsync(Observation observation) diff --git a/Services/PatientService.cs b/Services/PatientService.cs index bdff4ce..84fb2e4 100644 --- a/Services/PatientService.cs +++ b/Services/PatientService.cs @@ -38,7 +38,9 @@ public class PatientService public async Task> ListPatientsAsync() { - return await _context.Patients.ToListAsync(); + return await _context.Patients + .Include(p => p.Messages) + .ToListAsync(); } public async Task UpdatePatientAsync(Patient patient) diff --git a/Views/Home/Index.cshtml b/Views/Home/Index.cshtml index bcfd79a..10fbb6b 100644 --- a/Views/Home/Index.cshtml +++ b/Views/Home/Index.cshtml @@ -1,8 +1,145 @@ @{ - ViewData["Title"] = "Home Page"; + ViewData["Title"] = "Dashboard"; } -
-

Welcome

-

Learn about building Web apps with ASP.NET Core.

+
+
+
+

Dashboard

+

Laboratory Information System - Real-time HL7 Message Processing

+
+
+ + +
+
+
+
+
+
+
Total Patients
+

@ViewBag.TotalPatients

+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
HL7 Messages
+

@ViewBag.TotalMessages

+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
Lab Observations
+

@ViewBag.TotalObservations

+
+
+ +
+
+
+
+
+
+ + +
+
+
+
+
Recent HL7 Messages
+
+
+ @if (ViewBag.RecentMessages != null && ((IEnumerable)ViewBag.RecentMessages).Any()) + { +
+ + + + + + + + + + + + + @foreach (var message in (IEnumerable)ViewBag.RecentMessages) + { + + + + + + + + + } + +
Control IDMessage TypePatientSending FacilityTimestampObservations
@message.ControlId@message.MessageType@message.Patient.FirstName @message.Patient.LastName@message.SendingFacility@message.Timestamp.ToString("yyyy-MM-dd HH:mm:ss")@message.Observations.Count tests
+
+ } + else + { +
+ No messages yet. Start Mirth Connect and send HL7 messages to see them appear here! +
+ } +
+ +
+
+
+ + +
+
+
+
+
Quick Actions
+
+ +
+
+
diff --git a/Views/Home/Messages.cshtml b/Views/Home/Messages.cshtml new file mode 100644 index 0000000..e085e0b --- /dev/null +++ b/Views/Home/Messages.cshtml @@ -0,0 +1,115 @@ +@model IEnumerable +@{ + ViewData["Title"] = "HL7 Messages"; +} + +
+
+
+

HL7 Messages

+

All received HL7 messages from Mirth Connect

+
+
+ +
+
+
+
+
Message Log
+ @Model.Count() Total +
+
+ @if (Model.Any()) + { +
+ + + + + + + + + + + + + + + + @foreach (var message in Model) + { + + + + + + + + + + + + } + +
Message IDControl IDTypePatientSendingReceivingTimestampVersionTests
@message.MessageId@message.ControlId@message.MessageType + @message.Patient.LastName, @message.Patient.FirstName +
+ ID: @message.Patient.HL7PatientId +
+ @message.SendingApp +
+ @message.SendingFacility +
+ @message.ReceivingApp +
+ @message.ReceivingFacility +
+ @message.Timestamp.ToString("yyyy-MM-dd") +
+ @message.Timestamp.ToString("HH:mm:ss") +
@message.Version + @message.Observations.Count +
+
+ } + else + { +
+ No messages received yet. +
+ } +
+
+
+
+ + +
+ +@section Scripts { + +} diff --git a/Views/Home/Observations.cshtml b/Views/Home/Observations.cshtml new file mode 100644 index 0000000..142bdef --- /dev/null +++ b/Views/Home/Observations.cshtml @@ -0,0 +1,261 @@ +@model IEnumerable +@{ + ViewData["Title"] = "Lab Observations"; +} + +
+
+
+

Laboratory Observations

+

All lab test results and observations

+
+
+ @if (Model.Any()) + { + var abnormalCount = Model.Count(o => !string.IsNullOrEmpty(o.AbnormalFlag) && o.AbnormalFlag != "N"); + var finalCount = Model.Count(o => o.ResultStatus == "F"); + var uniqueTests = Model.Select(o => o.ObservationCode).Distinct().Count(); + +
+
+
+
+

@Model.Count()

+

Total Observations

+
+
+
+
+
+
+

@abnormalCount

+

Abnormal Results

+
+
+
+
+
+
+

@uniqueTests

+

Unique Test Types

+
+
+
+
+ } + +
+
+
+
+
Test Results
+ @Model.Count() Total +
+
+ @if (Model.Any()) + { +
+ + + + + + + + + + + + + + + @foreach (var obs in Model) + { + + + + + + + + + + + } + +
Observation IDPatientTest CodeResult ValueUnitsAbnormal FlagStatusMessage Date
@obs.ObservationId + @obs.Message.Patient.LastName, @obs.Message.Patient.FirstName +
+ @obs.Message.Patient.HL7PatientId +
+ @obs.ObservationCode + + + @obs.ObservationValue + + @obs.Units + @if (string.IsNullOrEmpty(obs.AbnormalFlag) || obs.AbnormalFlag == "N") + { + Normal + } + else if (obs.AbnormalFlag == "H") + { + High + } + else if (obs.AbnormalFlag == "L") + { + Low + } + else + { + @obs.AbnormalFlag + } + + @if (obs.ResultStatus == "F") + { + Final + } + else if (obs.ResultStatus == "P") + { + Preliminary + } + else if (obs.ResultStatus == "C") + { + Corrected + } + else + { + @obs.ResultStatus + } + + @obs.Message.Timestamp.ToString("yyyy-MM-dd") +
+ @obs.Message.Timestamp.ToString("HH:mm:ss") +
+
+ } + else + { +
+ No observations found. Lab observations will appear here once HL7 messages with OBX segments are processed. +
+ } +
+
+
+
+ + + @if (Model.Any()) + { + var abnormalCount = Model.Count(o => !string.IsNullOrEmpty(o.AbnormalFlag) && o.AbnormalFlag != "N"); + var finalCount = Model.Count(o => o.ResultStatus == "F"); + var uniqueTests = Model.Select(o => o.ObservationCode).Distinct().Count(); + + @*
+
+
+
+

@Model.Count()

+

Total Observations

+
+
+
+
+
+
+

@abnormalCount

+

Abnormal Results

+
+
+
+
+
+
+

@uniqueTests

+

Unique Test Types

+
+
+
+
*@ + + +
+
+
+
+
Test Type Distribution
+
+
+
+ @foreach (var testGroup in Model.GroupBy(o => o.ObservationCode).OrderByDescending(g => g.Count()).Take(6)) + { +
+
+ @testGroup.Key + @testGroup.Count() results +
+
+ } +
+
+
+
+
+ } + + +
+ +@section Scripts { + +} diff --git a/Views/Home/Patients.cshtml b/Views/Home/Patients.cshtml new file mode 100644 index 0000000..acb82e1 --- /dev/null +++ b/Views/Home/Patients.cshtml @@ -0,0 +1,112 @@ +@model IEnumerable +@{ + ViewData["Title"] = "Patients"; +} + +
+
+
+

Patients

+

All registered patients in the system

+
+
+ +
+
+
+
+
Patient List
+ @Model.Count() Total +
+
+ @if (Model.Any()) + { +
+ + + + + + + + + + + + + + @foreach (var patient in Model) + { + var age = DateTime.Now.Year - patient.DateOfBirth.Year; + if (DateTime.Now.DayOfYear < patient.DateOfBirth.DayOfYear) age--; + + + + + + + + + + + } + +
Patient IDHL7 Patient IDNameDate of BirthAgeGenderMessages
@patient.PatientId@patient.HL7PatientId + @patient.LastName, @patient.FirstName + @patient.DateOfBirth.ToString("yyyy-MM-dd")@age years + @if (patient.Gender?.ToUpper() == "M") + { + Male + } + else if (patient.Gender?.ToUpper() == "F") + { + Female + } + else + { + @patient.Gender + } + + @patient.Messages.Count messages +
+
+ } + else + { +
+ No patients found. Send HL7 messages through Mirth Connect to populate patient data. +
+ } +
+
+
+
+ + +
+ +@section Scripts { + +} diff --git a/Views/Shared/_Layout.cshtml b/Views/Shared/_Layout.cshtml index 2837733..342b310 100644 --- a/Views/Shared/_Layout.cshtml +++ b/Views/Shared/_Layout.cshtml @@ -5,6 +5,7 @@ @ViewData["Title"] - SimpleLIS + @@ -20,10 +21,31 @@ diff --git a/hl7.db-shm b/hl7.db-shm index e5e6b3d..fe9ac28 100644 Binary files a/hl7.db-shm and b/hl7.db-shm differ diff --git a/hl7.db-wal b/hl7.db-wal index 879eec8..e69de29 100644 Binary files a/hl7.db-wal and b/hl7.db-wal differ