type page = Dream_html.node
val login :
Dream.request -> ?error:string -> ?registration_open:bool -> unit -> page
(** [registration_open] shows the "Register" link. Defaults to [false]. *)
val register : Dream.request -> ?error:string -> unit -> page
val choose_routine :
Dream.request ->
logging:bool ->
viewer:View_model.Viewer.t ->
routines:View_model.Routine_choice.t list ->
page
val home :
Dream.request -> viewer:View_model.Viewer.t -> home:View_model.Home.t -> page
val workout_in_progress :
Dream.request -> viewer:View_model.Viewer.t -> workout_name:string -> page
(** The Home card shown while a workout is in progress. Links to the current
workout so it stays one tap away. *)
val routine :
Dream.request ->
?logging:bool ->
viewer:View_model.Viewer.t ->
View_model.Routine.t ->
page
val workout :
Dream.request ->
viewer:View_model.Viewer.t ->
?errors:(string * string) list ->
?editing:int ->
?logging:bool ->
record_id:string option ->
active_slot:int ->
View_model.Workout.t ->
page
(** Renders one prescribed slot at a time under a dropdown that selects the
exercise. Authenticated pages carry generic progressive-enhancement markers.
Current workouts additionally mark slot links and forms, while saved-record
edits use the generic authenticated form path. [active_slot] is the slot the
view opens on. A handler clamps a requested slot and falls back to the first
outstanding slot. [record_id] is [None] for the workout in progress and
[Some id] for a saved history record. [logging] sets the middle navigation
action. It defaults to a live workout view (true when [record_id] is
[None]). *)
type feedback_flow = { step : int; answers : (string * string) list }
val feedback_factors : (string * string) list
(** Ordered factor codes and labels used by the sequential feedback flow. *)
val logbook :
Dream.request ->
?logging:bool ->
viewer:View_model.Viewer.t ->
?feedback:View_model.Feedback.report list ->
?suggest_feedback:bool ->
?feedback_flow:feedback_flow ->
?feedback_open:bool ->
View_model.Logbook_entry.t list ->
page
(** The logbook: recorded workouts and a modal sequential subjective feedback
flow. [feedback] lists past reports, most recent first. [suggest_feedback]
shows a prompt inviting feedback, set after a workout finishes. *)
val profile :
Dream.request ->
?logging:bool ->
viewer:View_model.Viewer.t ->
?username_error:string ->
?password_error:string ->
?notice:string ->
unit ->
page
(** The account profile page: rename the account and change the password, each
an independent form. [username_error] and [password_error] report a refused
change inline. [notice] confirms a successful one. *)
val settings :
Dream.request ->
?logging:bool ->
viewer:View_model.Viewer.t ->
theme:string ->
unit ->
page
(** The session-scoped theme settings page. *)
val import_review :
Dream.request ->
viewer:View_model.Viewer.t ->
View_model.Import_review.t ->
page
(** The review of a provisional Hevy import batch. Lists the rows dropped on
parse, then each workout with its sets, blockers, and acknowledgement state.
Renders a mapping form per distinct source name, a normal-set confirmation
form, a per-workout promote form, and a batch promote form. Basic accessible
HTML: it names no core entity, only the view model. *)
val problem : title:string -> detail:string -> page
val error_page :
?viewer:View_model.Viewer.t ->
?request:Dream.request ->
status:int ->
unit ->
page
(** A branded page for an HTTP failure. It names only the class of failure, so
no server-supplied string leaks, and keeps the navigation affordances: top
on desktop, bottom on mobile. *)
val app_feedback :
Dream.request ->
?logging:bool ->
viewer:View_model.Viewer.t ->
?tab:[ `Write | `Submitted ] ->
?error:string ->
View_model.App_feedback.t list ->
page
(** The authenticated application feedback page. One tab accepts a freeform
message. The other lists the trainee's submitted messages. *)