mirror of
https://github.com/AmanTahiliani/FHIR-Sandbox.git
synced 2026-08-07 11:53:56 -04:00
125 lines
4.1 KiB
Go
125 lines
4.1 KiB
Go
package handlers
|
|
|
|
import (
|
|
"log"
|
|
"net/http"
|
|
|
|
"github.com/AmanTahiliani/FHIR-Sandbox/app/fhir"
|
|
"github.com/AmanTahiliani/FHIR-Sandbox/app/middleware"
|
|
"github.com/AmanTahiliani/FHIR-Sandbox/app/models"
|
|
)
|
|
|
|
// HandleDashboard renders the stable patient dashboard.
|
|
// On first load (no prior sync), automatically triggers a sync to populate data.
|
|
// All other clinical data is read from the local database; no live FHIR calls are
|
|
// made here. Use POST /dashboard/sync to refresh data from the EHR.
|
|
//
|
|
// GET /dashboard
|
|
func (h *Handler) HandleDashboard(w http.ResponseWriter, r *http.Request) {
|
|
sess := middleware.SessionFromContext(r.Context())
|
|
practitionerUser := middleware.UserFromContext(r.Context())
|
|
|
|
if sess == nil || practitionerUser == nil {
|
|
h.handleUnauthorized(w, r)
|
|
return
|
|
}
|
|
|
|
ehrURL := sess.EHRURL
|
|
patientID := sess.PatientFHIRID
|
|
|
|
// Allow overriding the patient context via a query parameter.
|
|
if overrideID := r.URL.Query().Get("patient_id"); overrideID != "" {
|
|
patientID = overrideID
|
|
}
|
|
|
|
// Check if this is the first load and trigger auto-sync
|
|
latestSync, err := h.store.LatestSync(patientID, ehrURL)
|
|
if err != nil {
|
|
log.Printf("handlers: dashboard LatestSync Patient/%s: %v", patientID, err)
|
|
}
|
|
|
|
if latestSync == nil {
|
|
// First load — redirect to sync endpoint for auto-sync
|
|
syncURL := "/dashboard/sync"
|
|
if overrideID := r.URL.Query().Get("patient_id"); overrideID != "" {
|
|
syncURL += "?patient_id=" + overrideID
|
|
}
|
|
http.Redirect(w, r, syncURL, http.StatusSeeOther)
|
|
return
|
|
}
|
|
|
|
// Fetch patient demographics from the FHIR server. This is a cheap single
|
|
// resource call and keeps the patient card always current.
|
|
fhirClient := fhir.NewClient(ehrURL, sess.AccessToken)
|
|
patient, err := fhirClient.GetPatient(patientID)
|
|
if err != nil {
|
|
log.Printf("handlers: dashboard fetch Patient/%s failed: %v", patientID, err)
|
|
h.renderError(w, http.StatusBadGateway, "Failed to fetch patient details from the FHIR server.")
|
|
return
|
|
}
|
|
patientUser := fhir.ExtractUserFromPatient(patient, ehrURL)
|
|
|
|
// Read clinical data from the local database.
|
|
observations, err := h.store.ListObservations(patientID, ehrURL)
|
|
if err != nil {
|
|
log.Printf("handlers: dashboard ListObservations Patient/%s: %v", patientID, err)
|
|
// Non-fatal; render with empty slice.
|
|
}
|
|
|
|
conditions, err := h.store.ListConditions(patientID, ehrURL)
|
|
if err != nil {
|
|
log.Printf("handlers: dashboard ListConditions Patient/%s: %v", patientID, err)
|
|
}
|
|
|
|
docRefs, err := h.store.ListDocumentReferences(patientID, ehrURL)
|
|
if err != nil {
|
|
log.Printf("handlers: dashboard ListDocumentReferences Patient/%s: %v", patientID, err)
|
|
}
|
|
|
|
medications, err := h.store.ListMedicationRequests(patientID, ehrURL)
|
|
if err != nil {
|
|
log.Printf("handlers: dashboard ListMedicationRequests Patient/%s: %v", patientID, err)
|
|
}
|
|
|
|
allergies, err := h.store.ListAllergyIntolerances(patientID, ehrURL)
|
|
if err != nil {
|
|
log.Printf("handlers: dashboard ListAllergyIntolerances Patient/%s: %v", patientID, err)
|
|
}
|
|
|
|
synced := r.URL.Query().Get("synced") == "true"
|
|
|
|
h.render(w, "dashboard.html", dashboardData{
|
|
Patient: patientUser,
|
|
Practitioner: practitionerUser,
|
|
RawPatient: patient,
|
|
Observations: observations,
|
|
Conditions: conditions,
|
|
DocumentReferences: docRefs,
|
|
Medications: medications,
|
|
Allergies: allergies,
|
|
LatestSync: latestSync,
|
|
Session: sess,
|
|
Synced: synced,
|
|
})
|
|
}
|
|
|
|
// dashboardData is the view model passed to the dashboard template.
|
|
type dashboardData struct {
|
|
Patient *models.User
|
|
Practitioner *models.User
|
|
RawPatient *fhir.Patient
|
|
Observations []models.Observation
|
|
Conditions []models.Condition
|
|
DocumentReferences []models.DocumentReference
|
|
Medications []models.MedicationRequest
|
|
Allergies []models.AllergyIntolerance
|
|
LatestSync *models.PatientSync
|
|
Session *models.Session
|
|
Synced bool
|
|
}
|
|
|
|
// handleUnauthorized redirects to root for dashboard requests.
|
|
func (h *Handler) handleUnauthorized(w http.ResponseWriter, r *http.Request) {
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
}
|