open Dream_html open Page_kit open Page_shell (* The review of a provisional import batch. It renders the parse warnings, then each workout with its sets, blockers, and forms. Every form is a plain POST carrying its CSRF token, so cleaning and promotion need no script. The page names only the view model: the controller has already phrased set types, blockers, and warnings, so no core entity crosses the boundary here. *) let import_review request ~viewer (vm : View_model.Import_review.t) = let warnings_block = match vm.View_model.Import_review.warnings with | [] -> [] | warnings -> [ tag "section" [ class_ "import-warnings" ] [ tag "h2" [] [ txt "Dropped rows" ]; tag "ul" [] (List.map (fun (w : View_model.Import_warning.t) -> tag "li" [] [ txt "Row %d: %s" w.View_model.Import_warning.row w.View_model.Import_warning.detail; ]) warnings); ]; ] in (* One row per set. A mapped set shows the catalog name it resolves to. *) let set_row (s : View_model.Import_set.t) = let mapping = match s.View_model.Import_set.mapping with | Some name -> Printf.sprintf " → %s" name | None -> " → unmapped" in tag "li" [] [ txt "Row %d: %s (%s) %s kg × %s reps%s" s.View_model.Import_set.row s.View_model.Import_set.exercise_name s.View_model.Import_set.set_type s.View_model.Import_set.weight s.View_model.Import_set.reps mapping; ] in (* One mapping form per distinct source name in the workout. The source name is fixed by a hidden field; the trainee supplies the catalog exercise id. *) let mapping_form batch_id workout_id source_name = tag "form" [ action Routes.import_map batch_id workout_id; post_form; class_ "import-map-form"; ] [ Dream_html.csrf_tag request; void "input" [ type_ "hidden"; name "source_name"; Dream_html.string_attr "value" "%s" source_name; ]; tag "div" [ class_ "field" ] [ tag "label" [] [ txt "Map %s to exercise id" source_name ]; void "input" [ type_ "text"; name "exercise_id"; required ]; ]; void "input" [ type_ "submit"; value "Map exercise" ]; ] in let confirm_form batch_id workout_id acknowledgement = tag "form" [ action Routes.import_confirm batch_id workout_id; post_form; class_ "import-confirm-form"; ] [ Dream_html.csrf_tag request; tag "div" [ class_ "field" ] [ tag "label" [] [ txt "Confirm normal sets" ]; void "input" ([ type_ "text"; name "acknowledgement"; required ] @ match acknowledgement with | Some ack -> [ Dream_html.string_attr "value" "%s" ack ] | None -> []); ]; void "input" [ type_ "submit"; value "Confirm normal sets" ]; ] in let promote_workout_form batch_id workout_id = tag "form" [ action Routes.import_promote_workout batch_id workout_id; post_form; class_ "import-promote-workout-form"; ] [ Dream_html.csrf_tag request; void "input" [ type_ "submit"; value "Promote workout" ]; ] in let blockers_block (w : View_model.Import_workout.t) = match w.View_model.Import_workout.blockers with | [] -> [ tag "p" [ class_ "import-ready" ] [ txt "Ready to promote." ] ] | blockers -> [ tag "p" [] [ txt "Blocked:" ]; tag "ul" [ class_ "import-blockers" ] (List.map (fun b -> tag "li" [] [ txt "%s" b ]) blockers); ] in let workout_section (w : View_model.Import_workout.t) = let batch_id = vm.View_model.Import_review.batch_id in let workout_id = w.View_model.Import_workout.id in (* Every distinct source name, in first-appearance order. *) let source_names = List.fold_left (fun acc (s : View_model.Import_set.t) -> let n = s.View_model.Import_set.exercise_name in if List.mem n acc then acc else acc @ [ n ]) [] w.View_model.Import_workout.sets in tag "section" [ class_ "import-workout" ] ([ tag "h2" [] [ txt "%s" w.View_model.Import_workout.title ]; tag "ul" [ class_ "import-sets" ] (List.map set_row w.View_model.Import_workout.sets); ] @ blockers_block w @ List.map (mapping_form batch_id workout_id) source_names @ [ confirm_form batch_id workout_id w.View_model.Import_workout.acknowledgement; promote_workout_form batch_id workout_id; ]) in let batch_promote_form = tag "form" [ action Routes.import_promote_batch vm.View_model.Import_review.batch_id; post_form; class_ "import-promote-batch-form"; ] [ Dream_html.csrf_tag request; void "input" [ type_ "submit"; value "Promote whole batch" ]; ] in html_page ~viewer ~request ~active:"profile" "Import review" ([ tag "h1" [] [ txt "Import review" ] ] @ warnings_block @ List.map workout_section vm.View_model.Import_review.workouts @ [ batch_promote_form ])