Dashboard
The dashboard provides a high-level operational summary and quick-entry links. It is the main landing page after authentication.Chemical records
Current capabilities:- create and edit chemical test records
- capture free chlorine, total chlorine, combined chlorine, pH, alkalinity, calcium hardness, cyanuric acid, temperatures, water clarity, backwash, and notes
- automatically compute chemistry status by field and overall summary
- compute Langelier Saturation Index
- show detail pages and history/comments
- configure pool-specific chemistry thresholds
- Illinois closure thresholds are supported
- cloudy water can force a closure-required status
- tested-by and CPO-verifier attribution are captured
- trend charts and CSV bulk import are available
- reason-required corrections on saved records, held pending unless the requester holds
chemical_records:correct
Compliance operations
Current capabilities:- manual closure incidents with status, comments, and evidence
- corrective actions tied to incidents
- scheduled closures kept separate from compliance incidents
- facility status, exception ledger, and timeline views (with a closure-vs-scheduled split)
- print-friendly compliance pages
- Illinois IDPH-oriented reporting support
- inspection packet builder (
/compliance/packet) - daily/weekly compliance digest email
- reopen attestation/sign-off workflow
- policy/SOP document library and jurisdiction checklist templates (
/compliance/library)
Alerts and exports
Current capabilities:- warning and critical alert events with acknowledge flow
- dashboard alert summary
- per-user email alert preference toggle
- chemical-record CSV export
- closure-incident-history CSV export
- IDPH daily operational report PDF export
- export job history
Maintenance logs
Current capabilities:- create, edit, list, and view maintenance logs
- optionally scope a log to a pool
- use logs for chemical additions, repairs, media changes, and general operational work
- reason-required corrections on saved logs
- preventive maintenance schedule templates (by pool/equipment/frequency), a computed due list, and dashboard overdue alerts
Tenant and admin management
Current capabilities:- manage organization details
- manage locations
- manage pools
- manage users, each with a directly-assigned permission checklist (no separate role entity —
org:manageis the only wildcard)
Forms
Current capabilities:- template builder at
Settings > Forms(list, create, edit, version) - seed a template from an existing checklist template
- field types: short text, long text, number, dropdown, multi-select, checkbox, multiple choice, date, signature
- conditional show/hide rules with 16 comparison operators, filtered by source field type (text, number, date, option) and correct value arity (0 for
is (not) empty, 2 foris (not) between, 1 otherwise) - one-click “add explanation field” action that generates a required follow-up short-text field wired to
is_not_emptyon the source field - custom formula mode with a hand-written parser/evaluator; formulas reference earlier fields as
[Field Label]and combine comparisons withAND/OR - draft/published/archived status; edits to published templates roll forward to a new version, drafts are mutated in place
- legacy
{ fieldId, equals }conditionals are upgraded on read vianormalizeSchema - one-click form-level Location/Pool/Signature fields (
schema.formLevelFields), rendered before every section, never shown as an editable row in a section — the pool picker narrows to whichever location was selected - runtime submission renderer (
Custom FormsandCompleted Forms): fill out, save as draft, submit, and review (approve/reject/request changes) - recurring form schedules with a computed due list
- file attachments and hand-drawn signature capture at submission time
- completed-form CSV export
- reason-required corrections on an approved or rejected submission
- notification recipients wired to actually send email (the field exists on a template today; sending isn’t wired up yet)
- public, unauthenticated submission links
Corrections
Applies to chemical records, maintenance logs, and decided (approved/rejected) form submissions:- every edit to an already-saved record requires a reason
- applies immediately if the requester holds the domain’s
*:correctpermission (chemical_records:correct,maintenance_logs:correct,form_submissions:correct); otherwise heldpendinguntil a*:correctholder approves or rejects it - shared
correctionstable + service layer (src/lib/actions/corrections.ts) across all three domains, with a per-entitybuildApplyPayloadtransform where the display-friendly diff shape diverges from the actual update payload - a “Corrected” badge and full before/after history render on the record’s own page (
src/components/corrections/corrections-panel.tsx)