rubyforgood / rubyforgood/alongwithyou

[FEATURE] Add Vitals Log

Open
#203 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement Rails App RFG Conference
Dominant language
TypeScript
Stars
9
Forks
4
Avg merge
9h 34m
Merged PRs (30d)
16

Description

Description

A vitals reading is a kind of log entry. It is a Log delegated type, and the Log carries the date.

On a given date, a user may record measurements for multiple vitals. The nature of each measurement is open: the user can choose from a list of vital types or enter their own.

VitalType — what is being measured. Lookup table, seeded, user-extensible.

  • Name (String, required, unique)
  • Unit (String, optional) — e.g. lb, °F, mmHg
  • Seeded with: weight, blood pressure, temperature

VitalsReading — one dated set of measurements. The Log delegated type.

  • Is a Log delegated type (required) — the date lives on the Log
  • Notes (Text, optional)
  • Has many vital measurements

VitalMeasurement — one value

  • Belongs to a VitalsReading (required)
  • Belongs to a VitalType (required)
  • Value (String, required)

Relationships: Log, VitalType, VitalMeasurement

Why Value is a String

Blood pressure is "120/80" — two numbers in one cell. Weight and temperature are decimals. A single numeric column can't hold all three, and per-type columns are impossible once the list is user-extensible. String keeps every measurement uniform, which is the point of this design.

The cost is that we can't chart or compare values yet. That's accepted for now. When charting comes up, the fix is to give VitalType a value shape (numeric, paired, text) and parse against it — that's a follow-up, not this ticket.

UI

Standard scaffolding, plus the pieces that make a reading visible from the log:

  • Index — follows the same tabular presentation pattern as app/views/prescriptions/index.html.erb. Copy that structure: the .table-scroll wrapper carrying tabindex="0", role="region" and an aria-label; <th scope="col"> headers; the first cell as <th scope="row"> linking to the show page; or_dash for optional values; table-note spans for secondary detail; and an empty-state paragraph when there are none. One row per reading, date order. Columns: Date, then one column per seeded VitalType (Weight, Blood pressure, Temperature), then a column summarising any other measurements. This is the journal's table, on screen.
  • Form — one field per VitalType, all optional. A reading saves with only the values that were filled in; blanks do not create empty measurements.
  • Show — every measurement in the reading, with its unit, plus notes.
  • Register VitalsReading in Log's delegated_type list so it appears in the log type selector.
  • Add a partial in app/views/vitals_readings/ that renders a reading's measurements in a log context.
  • Modify the Log index and show to render that partial, dispatching on the loggable type — the same mechanism the Appointment ticket establishes. Keep the generic fallback intact.
  • Add VitalType to admin_sections in ApplicationHelper — it's reference data, same as medication types and forms.

Acceptance Criteria

  • A user can add, view, edit and delete a vitals reading
  • Saving requires a date
  • A reading can hold any number of measurements, one per VitalType
  • The same VitalType cannot appear twice in one reading
  • A blank field in the form does not create a measurement
  • VitalType is seeded with weight, blood pressure and temperature, is manageable, and appears on /admin
  • Adding a VitalType makes it available on the vitals form without a migration
  • Units display next to values wherever a value is shown
  • The index matches the prescriptions index pattern: scrollable labelled region, scoped table headers, row header linking to show, dashes for blanks, empty state
  • VitalsReading appears in the log type selector
  • The log index and show render vitals details via the partial
  • Log entries of a type with no partial still render via the fallback
  • Model tests cover the three models, the one-value-per-type rule, and a reading with only some values filled in

Notes

  • Scope is vitals only, not diagnostics. The ERD names this node "DiagnosticLog/Vitals", but the diagnostic half is TestResult and Diagnosis, and both currently sit in the ERD's "May not be needed" box. Build vitals; leave diagnostics alone until that box is resolved. Worth renaming the ERD node to match.
  • Open: adding a vital type currently means a trip to /admin. On paper the user just writes a name in a blank column header. Letting them create a VitalType inline from the vitals form would match the journal better — worth doing, but as a follow-up rather than growing this ticket.
  • The journal asks "Can there be seven entries (a week) per table?" That's a print layout question about rows per page, not a data question. It doesn't affect this model.
  • The four "Other" columns are a paper constraint, not a real limit. There is no cap on vital types here.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the data relationships and delegated-type registration described for Log, VitalType, and VitalMeasurement, then compare app/views/prescriptions/index.html.erb for the vitals index structure. Trace the Appointment log rendering mechanism before adding the vitals log partial and checking the Log index and show fallback. Done means the listed acceptance criteria pass, including model tests, seeded and manageable vital types, CRUD screens, and log rendering.

Written by the indexing model from the issue text.

Assessment

Tech stack
rails, ruby
Domain
database, full-stack
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.