aboutsummaryrefslogtreecommitdiff
path: root/client/src/Component/Select.hs
blob: 9f671d34f1f68b59e42ba8abaeb78f73fecc6f62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
module Component.Select
  ( SelectIn(..)
  , SelectOut(..)
  , select
  ) where

import           Data.Map   (Map)
import qualified Data.Map   as M
import           Data.Text  (Text)
import qualified Data.Text  as T
import           Reflex.Dom (Dynamic, Event, MonadWidget, Reflex)
import qualified Reflex.Dom as R

import qualified Common.Msg as Msg

data (Reflex t) => SelectIn t a b c = SelectIn
  { _selectIn_label        :: Text
  , _selectIn_initialValue :: a
  , _selectIn_values       :: Dynamic t (Map a Text)
  , _selectIn_reset        :: Event t b
  , _selectIn_isValid      :: a -> Bool
  , _selectIn_validate     :: Event t c
  }

data SelectOut t a = SelectOut
  { _selectOut_value :: Dynamic t a
  }

select :: forall t m a b c. (Ord a, MonadWidget t m) => SelectIn t a b c -> m (SelectOut t a)
select selectIn = do
  rec
    let containerAttr = R.ffor hasError (\e ->
          M.singleton "class" $ T.intercalate " "
            [ "selectInput"
            , if e then "error" else ""
            ])

    hasError <- R.holdDyn False $ R.attachWith
      (\v clearError -> not clearError && not (_selectIn_isValid selectIn v))
      (R.current value)
      (R.leftmost
        [ const False <$> _selectIn_validate selectIn
        , const True <$> _selectIn_reset selectIn
        ])

    value <- R.elDynAttr "div" containerAttr $ do
      R.el "label" $ R.text (_selectIn_label selectIn)

      let initialValue = _selectIn_initialValue selectIn

      value <- R._dropdown_value <$>
        R.dropdown
          initialValue
          (_selectIn_values selectIn)
          (R.def { R._dropdownConfig_setValue = fmap (const initialValue) (_selectIn_reset selectIn) })

      errorMessage <- R.holdDyn "" $ R.attachWith
        (\v _ -> if (_selectIn_isValid selectIn) v then "" else "ERROR!")
        (R.current value)
        (_selectIn_validate selectIn)

      R.divClass "errorMessage" . R.dynText $
        R.ffor hasError (\e -> if e then Msg.get Msg.Form_NonEmpty else "")

      return value

  return SelectOut
    { _selectOut_value = value
    }