I am very much a learner, but I have this brutally simple form. It does the job. Good enough, but I have another very complicated similar form that needs simplifying.
The issue I have is that the lists of strings are really easy for me to modify and maintain as is, if I refactor after the example here I end up with a huge long “type msg” with a match for every option in every drop down, making it hard to keep it all straight (imagine many more drop downs)
GPT4 and Claude3 are useful but not really.
My next step is to take often_list and turn it into a type, without bloating “type msg” but I am unsure how to do this.
Input welcome, just be aware, step by step is the way I do things. I am not asking for everything, just the next most productive step. Bearing in mind I have another more complicated but similar form that I am aiming to refactor, it’s too long at 1300 lines.
Kindness
David
(* file: survey.ml *)
open Fmlib_browser
let often_list =
[ ""; "daily"; "weekly"; "monthly"; "quarterly"; "biannually"; "annually" ]
let where_list =
[
"";
"town";
"good tramping tracks";
"tough tramping tracks";
"off-track";
"scrub";
"the tops";
"the crags";
"the summit";
]
let what_list =
[
"";
"under 2 kg";
"2 to 5 kg";
"5 to 10 kg";
"10 to 20 kg";
"20 to 25 kg";
"+ 25 kg";
]
let first_element list = match list with [] -> "" | hd :: tail -> hd
(* Model*)
type state = {
often : string;
most_used : string;
where : string;
what : string;
message : string;
}
let init : state =
{
often = first_element often_list;
most_used = "";
where = first_element where_list;
what = first_element what_list;
message = "";
}
(* Messages *)
type msg =
| Often of string
| Most_used of string
| Where of string
| What of string
| Message of string
(* Views*)
let header_view state =
let open Html in
let open Attribute in
let img attrs nodes = node "img" attrs nodes in
div []
[
div [ class_ "grid" ] [ div [] []; img [ src "logo.svg" ] []; div [] [] ];
p []
[
text
"Please complete this survey. Help design the next Fiordland Pack.";
];
p []
[
text
"This is anonymous. No google analytics. No facebook pixel. \
No cookies."; (* Plausible is used though *)
];
]
let see_view state =
let open Html in
let open Attribute in
div []
[
li [] [ text "often: "; text state.often ];
li [] [ text "most used: "; text state.most_used ];
li [] [ text "where: "; text state.where ];
li [] [ text "what: "; text state.what ];
li [] [ text "message: "; text state.message ];
]
let view state =
let open Html in
let open Attribute in
let often str = Often str in
let most_used str = Most_used str in
let where str = Where str in
let what str = What str in
let message str = Message str in
let section attrs nodes = node "section" attrs nodes in
let form attrs nodes = node "form" attrs nodes in
div
[ class_ "container" ]
[
section [ id "header" ] [ header_view state ];
section
[ id "main" ]
[
form
[
attribute "action" "https://formspree.io/f/abcdefg";
attribute "method" "post";
]
[
section []
[
label
[ attribute "for" "how_often" ]
[
text "How often do you use a backpack?";
select
[
attribute "type" "text";
attribute "name" "how_often";
id "how_often";
value state.often;
on_input often;
]
(List.map
(fun x -> node "option" [] [ text x ])
often_list);
];
label
[ attribute "for" "where" ]
[
text "Where do you use your pack most?";
select
[
attribute "type" "text";
attribute "name" "where";
id "where";
value state.where;
on_input where;
]
(List.map
(fun x -> node "option" [] [ text x ])
where_list);
];
label
[ attribute "for" "what" ]
[
text "What kind of load do you carry?";
select
[
attribute "type" "text";
attribute "name" "what";
id "what";
value state.what;
on_input what;
]
(List.map
(fun x -> node "option" [] [ text x ])
what_list);
];
label
[ attribute "for" "most_used" ]
[
text "What is your all time most used backpack?";
input
[
attribute "type" "text";
attribute "name" "most_used";
id "most_used";
value state.most_used;
on_input most_used;
]
[];
];
label
[ attribute "for" "message" ]
[
text "What is most important in a backpack?";
textarea
[
attribute "type" "text";
attribute "name" "message";
id "message";
value state.message;
on_input message;
]
[];
];
button [ attribute "type" "submit" ] [ text "Send" ];
];
];
]
(* ; section [id "see"] [ see_view state ] *);
]
(* Update *)
let update (state : state) = function
| Often str -> { state with often = str }
| Most_used str -> { state with most_used = str }
| Where str -> { state with where = str }
| What str -> { state with what = str }
| Message str -> { state with message = str }
let _ =
sandbox
init
view
update