packages feed

casa-reoc-0.1.0.0: src/ReOC/Render/Error.hs

{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wall #-}

{- | The errors of filling in a form, as text: where each is, what is wrong,
and the help text of its field.

>>> import qualified Data.Text.IO as Text
>>> import ReOC.Model
>>> Text.putStrLn (renderPath [StepField ReOCOperator, StepField OperatorFleet, StepIndex 1, StepField OperatedTypeAirframes])
operator › fleet › 2 › airframes
-}
module ReOC.Render.Error (
  renderPath,
  renderInvalidValue,
  renderReOCError,
  renderReOCErrors,
) where

import Data.Foldable (toList)
import Data.Text (Text)
import qualified Data.Text as Text
import ReOC.Help (fieldHelp, fieldLabel)
import ReOC.Model

-- | A path, as the labels of its fields, and each index of a list counted from 1.
renderPath :: [Step] -> Text
renderPath =
  Text.intercalate " › " . map label
 where
  label = \case
    StepField f -> fieldLabel f
    StepIndex i -> Text.pack (show (i + 1))

-- | What is wrong with an invalid value.
renderInvalidValue :: InvalidValue -> Text
renderInvalidValue = \case
  InvalidText1 t -> quoted t <> " is blank, or has a character that a document cannot hold"
  InvalidFormText t -> quoted t <> " does not fit its box on the form, or has a character that the form cannot show"
  InvalidABN t -> quoted t <> " is not an ABN: 11 digits with valid check digits"
  InvalidARN t -> quoted t <> " is not an ARN: digits only"
  InvalidEmailAddress t -> quoted t <> " is not an email address that fits the form"
  InvalidPhoneNumber t -> quoted t <> " is not an Australian phone number"
  InvalidPostcode t -> quoted t <> " is not a four-digit postcode"
  InvalidPositive n -> number n <> " is not a positive number"
  InvalidPercentage n -> number n <> " is not a percentage from 0 to 100"
  InvalidGrossWeight n -> number n <> " g is not a gross weight from 1 g to 25 kg"
  InvalidReviewMonths n -> number n <> " is not a number of months from 1 to 12"
  InvalidPassMark n -> number n <> " is not a pass mark from 70 to 100"
 where
  quoted t = "“" <> t <> "”"
  number = Text.pack . show

-- The help text of the field at the end of a path, if it ends at a field.
helpAt :: [Step] -> Text
helpAt p =
  case [f | StepField f <- reverse p] of
    f : _ -> " (" <> fieldHelp f <> ")"
    [] -> ""

-- | An error: where it is, what is wrong, and the help text of the field.
renderReOCError :: ReOCError -> Text
renderReOCError = \case
  ReOCErrorUnfilled (Unfilled p) -> renderPath p <> ": not filled in" <> helpAt p
  ReOCErrorInvalid (Invalid p v) -> renderPath p <> ": " <> renderInvalidValue v <> helpAt p
  ReOCErrorTooMany (TooMany p most given) ->
    renderPath p <> ": " <> Text.pack (show given) <> " given, but it holds at most " <> Text.pack (show most) <> helpAt p

-- | Errors, one to a line.
renderReOCErrors :: (Foldable t) => t ReOCError -> Text
renderReOCErrors =
  Text.unlines . map renderReOCError . toList