Skip to content

dotku/readyrx-lab-testing

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ReadyRX

Lab testing application: lab orders, result ingestion (FHIR), patient biomarker history, and reference data management. Backend API (Express + Firestore) and React frontend (Vite + Tailwind).


Installation

Backend

  1. Prerequisites: Node.js (v18+), npm or yarn.
  2. Install dependencies:
    cd backend
    npm install
  3. Environment: Copy .env.example to .env and configure:
    • PORT — Server port (default 4000).
    • USE_FIRESTORE=true — Required to use Firestore.
    • Firebase credentials (one of):
      • GOOGLE_APPLICATION_CREDENTIALS — Path to Firebase service account JSON (e.g. ./firebase-service-account.json).
      • FIREBASE_SERVICE_ACCOUNT_JSON — Inline JSON string of the service account (do not commit). Do not commit credentials; add the JSON file to .gitignore.
  4. Build and run:
    npm run build
    npm start
    Or for development with watch:
    npm run dev
    API runs at http://localhost:4000. Health: GET /health. API docs: http://localhost:4000/docs.
  5. Seed data (optional): npm run seed — seeds Firestore with sample patients, labs, biomarkers, lab tests, orders, and results (uses seedFirestore(true)). With default store behavior, empty Firestore is also auto-seeded on first use.

Frontend

  1. Prerequisites: Node.js (v18+), npm or yarn.
  2. Install dependencies:
    cd frontend
    npm install
  3. Environment: Copy .env.example to .env.local (or .env) and set:
    • VITE_API_URL=http://localhost:4000 — Backend API base URL (no trailing slash).
  4. Run:
    npm run dev
    App runs at http://localhost:3000 (Vite default). For production build: npm run build; preview: npm run preview.

Architecture

Backend

  • Runtime: Node.js, Express, TypeScript (compiled to dist/).
  • Entry: src/index.ts — loads dotenv, mounts app, listens on PORT (default 4000).
  • App: src/app.ts — CORS, JSON body parser, serves openapi.json, Scalar API docs at /docs, health at /health, and mounts:
    • /orders — lab orders (create, list, get, patch, delete, send to lab).
    • /results — lab results (list, delete) and FHIR ingest at POST /results/ingest.
    • /patients — patient get and biomarker history.
    • / (reference) — reference data: /labs, /biomarkers, /lab-tests (CRUD) and treatment options.
  • Store: Single persistence abstraction IStore in src/store/types.ts, implemented by Firestore in src/store/firestore.ts. getStore() in src/store/index.ts returns the singleton; it requires USE_FIRESTORE=true and valid Firebase credentials. Firestore is initialized from GOOGLE_APPLICATION_CREDENTIALS (file path) or FIREBASE_SERVICE_ACCOUNT_JSON (inline JSON). Empty Firestore is auto-seeded once with sample data.
  • Routes → services → store: Routes in src/routes/ call services in src/services/ (e.g. orders, results, patients, referenceData), which use getStore() and domain types from src/types/lab.ts.
  • FHIR/HL7: Result ingestion uses src/mapping/fhirToResult.ts (FHIR Observation/Bundle → internal LabResult). Outbound lab integration uses adapters in src/adapters/: hl7Adapter and fhirAdapter (selected by lab’s integrationType). Order → HL7/FHIR mapping lives in src/mapping/orderToHl7.ts and orderToFhir.ts.
  • API spec: openapi.json at repo root describes the ReadyRX Lab Testing API; Scalar consumes it for /docs.

Frontend

  • Stack: React 18, TypeScript, Vite, React Router v6, Tailwind CSS.
  • Entry: index.html/src/main.tsxBrowserRouter (with v7 future flags), App, global index.css.
  • Routing: App.tsx/ (dashboard), /admin/* (nested: labs, biomarkers, lab-tests, orders, results); admin index redirects to /admin/labs; catch-all redirects to /.
  • Pages: Dashboard at src/pages/DashboardPage.tsx; admin under src/pages/admin/ (AdminLayout, AdminLabsPage, AdminBiomarkersPage, AdminLabTestsPage, AdminOrdersPage, AdminResultsPage).
  • API client: src/lib/api.ts — base URL from import.meta.env.VITE_API_URL (default http://localhost:4000). Functions for patients, orders, results, labs, biomarkers, lab tests (CRUD and list); all list responses normalized to arrays.
  • UI: Reusable components in src/components/ui/ (button, card, input, label, select, table, badge, textarea) using Tailwind, class-variance-authority (cva), and cn() from src/lib/utils.ts (clsx + tailwind-merge). Dashboard-specific components in src/components/dashboard/ (e.g. LabOrdersSection, RecentLabResults, BiomarkerTrendChart, AITreatmentSuggestion).
  • Data: Shared types in src/types/lab.ts; src/data/mockData.ts and src/data/trendHelpers.ts for dashboard/trend helpers.

Design Decisions

Backend

  • Firestore-only persistence: The app uses a single IStore implementation (Firestore). No in-memory or other backends; getStore() throws if Firestore is not enabled or credentials are missing. This keeps deployment simple and aligns with a single source of truth.
  • OpenAPI + Scalar: API contract is defined in openapi.json and served at /openapi.json; Scalar provides interactive docs at /docs without requiring code generation from the spec.
  • FHIR ingest, internal model: Results can be ingested via FHIR Observation/Bundle at POST /results/ingest; mapping normalizes to internal LabResult and stores in Firestore. This allows interoperability while keeping the rest of the API and UI on a stable internal schema.
  • Lab-specific adapters (HL7 vs FHIR): Labs have an integrationType (HL7 or FHIR). Adapters in src/adapters/ produce outbound payloads; mapping from internal orders to HL7/FHIR lives in src/mapping/. This keeps integration logic pluggable per lab.
  • Simulated inbound results: Creating an order triggers a delayed, simulated inbound result (after a few seconds) for demo/development, writing one result and updating the order status. Production would replace this with real lab integrations.
  • Seed script and auto-seed: npm run seed runs seedFirestore(true). The Firestore store also runs a one-time auto-seed when the DB is empty so the app is usable without running the seed script explicitly.
  • Port and env: Server port is configurable via PORT; all secrets and config come from environment variables (and .env via dotenv), with .env gitignored.

Frontend

  • Vite + React: Vite for fast dev and ESM-based builds; React 18 with createRoot. Path alias @src/ for cleaner imports.
  • Single API base URL: Backend URL is configured once via VITE_API_URL; the API module uses it for all requests and normalizes list responses to arrays for predictable consumption.
  • Route-based structure: Dashboard and admin are separate route trees; admin uses a shared layout (AdminLayout) and nested routes for labs, biomarkers, lab tests, orders, and results. This keeps feature boundaries clear.
  • Tailwind + CVA + cn(): Styling is utility-first with Tailwind. Components use class-variance-authority for variant props (e.g. button variant/size) and a small cn() helper (clsx + tailwind-merge) to merge and override classes without conflicts.
  • No global state library: Data is fetched via the API module and local state; no Redux or similar. Suitable for current scope and keeps the frontend simple.
  • Shared types: src/types/lab.ts mirrors domain concepts (Patient, Lab, Biomarker, LabTest, LabOrder, LabResult, etc.) used by the API client and components, keeping the frontend aligned with the backend contract.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages