devforms
Safe HaskellSafe-Inferred
LanguageGHC2021

DevForms

Description

DevForms lets you define multi-page survey forms using a concise monadic builder DSL. Forms are served via a built-in web server (Scotty), and submissions are stored as JSONL files.

Example

main :: IO ()
main = devFormServer 9000 $ do
    form "Animal Survey" "animals" $ do
        questionLikert "I enjoy seeing animals"
        questionChoice "Favourite animal"
            [Alpaca, Bumblebee, Camel, Duck]
        questionDate "When would you like to visit the zoo?"
        questionInteger "How many tickets?" $ do
            setLowerBoundInclusive 1
            setUpperBoundInclusive 10
Synopsis

Documentation

type ServerBuilder = Writer (Endo Server) Source #

A builder monad for configuring the devforms server. Use form to add forms.

type FormBuilder = Writer (Endo Form) Source #

A builder monad for adding questions to a form. Use the question* functions to add questions.

type QuestionBuilder = Writer (Endo QuestionOptions) Source #

A builder monad for configuring question options (e.g. bounds for integer questions).

devFormServer :: Int -> ServerBuilder () -> IO () Source #

Start the devforms web server on the given port.

This is the top-level entry point for a devforms application. The second argument is a ServerBuilder block in which you define one or more forms using form. The server provides:

  • Individual form pages with client-side validation
  • A submission endpoint that stores answers in answers-<formId>.jsonl

form :: Text -> Text -> FormBuilder () -> ServerBuilder () Source #

Define a survey form.

The first argument is the human-readable title displayed at the top of the form page. The second argument is a form identifier used for:

  • URL routing — the form is served at form<formId>
  • Persistent storage — submissions are appended to answers-<formId>.jsonl

The third argument is a FormBuilder block where you add questions using the question* functions.

questionCheckbox :: Text -> FormBuilder () Source #

Add a yes/no checkbox question. Renders as a single checkbox that the respondent can tick or leave unticked.

questionLikert :: Text -> FormBuilder () Source #

Add a Likert-scale question. Renders as a 5-point agreement scale (Strongly disagree … Strongly agree) plus a "Cannot say" option.

questionChoice :: Text -> [Text] -> FormBuilder () Source #

Add a multiple-choice question. Renders as a group of radio buttons — the respondent must select exactly one of the provided options.

The first argument is the question label; the second is the list of choices.

questionDate :: Text -> FormBuilder () Source #

Add a date-picker question. Renders as an HTML date input and stores the answer in YYYY-MM-DD format.

questionTime :: Text -> FormBuilder () Source #

Add a time-picker question. Renders as an HTML time input and stores the answer in HH:MM format.

questionInteger :: Text -> QuestionBuilder () -> FormBuilder () Source #

Add an integer input question. The second argument is a QuestionBuilder block where you can optionally configure bounds using setLowerBoundInclusive and setUpperBoundInclusive. Bounds are enforced both client-side (via HTML attributes) and server-side on submission.

Example

questionInteger "How many pets do you have?" $ do
    setLowerBoundInclusive 0
    setUpperBoundInclusive 50

setLowerBoundInclusive :: Integer -> QuestionBuilder () Source #

Set the minimum allowed value (inclusive) for a questionInteger.

setUpperBoundInclusive :: Integer -> QuestionBuilder () Source #

Set the maximum allowed value (inclusive) for a questionInteger.