MediTrack is an internal healthcare system that replaces manual medicine ordering processes such as paper-based lists and email communication within hospital units.
It ensures that nurses, pharmacists, and warehouse staff have access to accurate and up-to-date information about medicine orders and inventory, reducing the risk of ordering errors and improving operational safety and efficiency.
Key flows:
- Nurses browse medicines, add them to an order request, and submit to the pharmacist
- Pharmacists review and confirm orders
- Warehouse staff marks confirmed orders as delivered, automatically updating stock levelsDescribe your project briefly.
- List medicines with name, ATC code, form, strength, and stock level
- Search by name or ATC code, filter by form
- Stock status indicator β In Stock /
β οΈ Low Stock (when below threshold) - Add, edit, and soft-delete medicines (Pharmacist only)
- ATC code uniqueness validation on create and update
- Soft delete β inactive medicines are hidden but preserved in order history
- Nurses create order requests via a request basket (localStorage-based draft)
- Orders follow a strict status flow:
DRAFT β SENT β CONFIRMED β DELIVERED - Stock is automatically decreased when an order is marked as DELIVERED
- Filter orders by ID, unit, and status
- Role-based status visibility (Nurse / Pharmacist / Warehouse)
- Login as Nurse, Pharmacist, or Warehouse (no authentication β mock only)
- UI controls and navigation adapt per role
- Role state persisted in localStorage
| Layer | Technology |
|---|---|
| Frontend | React 18, TypeScript, Vite, React Bootstrap |
| Backend | Node.js, Express.js, TypeScript |
| Database | PostgreSQL 16 |
| Containerization | Docker, Docker Compose |
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β React Frontend ββββββββΆβ Express Backend ββββββββΆβ PostgreSQL DB β
β (port 4173) β β (port 3000) β β (port 5433) β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
Backend structure follows separation of concerns:
Controller β Service β Repository β Database
- Controller β handles HTTP request/response
- Service β business logic, validation, status transition rules
- Repository β database queries only
Nurse adds medicines to Order Request (localStorage)
β
Submits β POST /api/orders β status: SENT
β
Pharmacist reviews β PATCH /api/orders/:id/status β CONFIRMED
β
Warehouse ships β PATCH /api/orders/:id/status β DELIVERED
β
Stock automatically decreased for each medicine in the order
git clone
cd MediTrack# Server
PORT=3000
# Database
DB_HOST=postgres
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your_password
DB_NAME=meditrack
# Frontend
FRONTEND_ORIGIN=http://localhost:4173
VITE_BACKEND_URL=http://localhost:3000- See Docker Container Setup
- Start Containers
docker compose up -d --buildThis command automatically builds and starts all containers. You donβt need to manually create the database or register knowledge β these are handled automatically when the backend container starts.
- Check backed logs
Verify that the knowledge base is successfully registered and the server is running.
docker logs meditrack-backend- Stop and Remove Containers (Optional)
docker compose down
β οΈ Note: The knowledge embeddings are stored in the persistent PostgreSQL volume (postgres_data). You do not need to re-run the registration script or rebuild the containers unless the volume or database is deleted.
You donβt need to do anything manually to set up the database.
It is automatically created by docker-compose.yml.
The postgres_data volume is persistent, which means that even if you delete the container, the volume (and thus the database data) will remain. This is why the database may continue to operate with old data.
environment:
- POSTGRES_DB=${DB_NAME}
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- ./init.sql:/docker-entrypoint-initdb.d/init.sqlIf you want to completely delete chatdb and create a new one:
docker compose down -vThis will remove both the container and the persistent volume, so the database is recreated from scratch
- Rebuilds the image from the Dockerfile.
- All latest code and dependency changes are applied.
docker compose up -d --buildOR
- Reuses the existing image.
- Code changes are not reflected in the container.
docker compose up -dLogin to the Postgres container (you will need to enter the password):
docker exec -it meditrack-postgres psql -U postgres -d meditrack\dt -- list tables
SELECT * FROM medicines;
SELECT * FROM orders;| Method | Endpoint | Description |
|---|---|---|
| GET | /api/medicines |
Get all active medicines (search, form filter) |
| GET | /api/medicines/:id |
Get medicine by ID |
| POST | /api/medicines |
Create medicine |
| PATCH | /api/medicines/:id |
Update medicine |
| DELETE | /api/medicines/:id |
Soft delete medicine |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/orders |
Get all orders (unit, status, id filter) |
| GET | /api/orders/:id |
Get order with items |
| POST | /api/orders |
Create order (status: SENT) |
| PATCH | /api/orders/:id/status |
Update order status |
cd backend
npm run test| Test file | Tests |
|---|---|
medicine.service.test.ts |
15 tests |
order.service.test.ts |
17 tests |
Unit tests cover service layer business logic including:
- Input validation
- ATC code uniqueness check
- Soft delete and inactive medicine protection
- Order status transition rules
- Stock decrease on DELIVERED
DRAFT orders are managed client-side via localStorage and are never persisted to the database. DB entries start at SENT when the nurse submits the order.
Trade-offs:
- β Simpler backend, no draft cleanup needed
- β Draft is lost on browser refresh or device switch
- β Cannot be shared between nurses on the same unit
In production, DRAFT would be persisted in DB to support multi-device access and shift handover.
When an order is marked as DELIVERED, stock is decreased for each medicine item individually. This is not wrapped in a transaction β if one update fails midway, partial stock decreases may occur.
Medicines are never hard-deleted. Setting is_active = false preserves order history integrity.
Authentication is not implemented. Role selection at login is for UI demonstration only. In production, role-based access would be enforced via JWT and backend middleware.
Order filtering by role is currently handled on the frontend. In production, filtering should be enforced on the backend based on the authenticated user's role.
| Area | Current | Future |
|---|---|---|
| Authentication | Mock role selection | JWT + role-based middleware |
| Draft orders | localStorage only | Persist in DB, shareable between nurses |
| Medicine forms & units | Hardcoded | Managed via database tables |
| Ward/Unit list | Hardcoded | Managed via units table |
| Order editing | Not supported | Edit draft items before SENT |
| Soft delete admin API | DB access only | Admin endpoint with role protection |
| Medicine activation date | Not tracked | activated_at / deactivated_at timestamps |
| Integration tests | Not implemented | Supertest for API endpoints |
| E2E tests | Not implemented | Cypress for critical user flows |
| Concurrent updates | Not handled | Optimistic locking to prevent race conditions on stock updates |