module View.Income.Form ( view , FormIn(..) , HttpMethod(..) , FormOut(..) ) where import Data.Aeson (ToJSON) import Data.Text (Text) import qualified Data.Text as T import Data.Time.Calendar (Day) import qualified Data.Time.Calendar as Calendar import qualified Data.Validation as V import Reflex.Dom (Event, MonadWidget) import qualified Reflex.Dom as R import Common.Model (Income) import qualified Common.Msg as Msg import qualified Common.Validation.Income as IncomeValidation import Component (ButtonIn (..), InputIn (..), InputOut (..)) import qualified Component as Component import qualified Util.Ajax as Ajax import qualified Util.Either as EitherUtil import qualified Util.Validation as ValidationUtil import qualified Util.WaitFor as WaitFor data FormIn t i = FormIn { _formIn_cancel :: Event t () , _formIn_headerLabel :: Text , _formIn_amount :: Text , _formIn_date :: Day , _formIn_mkPayload :: Text -> Text -> i , _formIn_httpMethod :: HttpMethod } data HttpMethod = Put | Post data FormOut t = FormOut { _formOut_hide :: Event t () , _formOut_addIncome :: Event t Income } view :: forall t m i. (MonadWidget t m, ToJSON i) => FormIn t i -> m (FormOut t) view formIn = do R.divClass "form" $ do R.divClass "formHeader" $ R.text (_formIn_headerLabel formIn) R.divClass "formContent" $ do rec let reset = R.leftmost [ "" <$ cancel , "" <$ addIncome , "" <$ _formIn_cancel formIn ] amount <- _inputOut_raw <$> (Component.input (Component.defaultInputIn { _inputIn_label = Msg.get Msg.Income_Amount , _inputIn_initialValue = _formIn_amount formIn , _inputIn_validation = IncomeValidation.amount }) (_formIn_amount formIn <$ reset) confirm) let initialDate = T.pack . Calendar.showGregorian . _formIn_date $ formIn date <- _inputOut_raw <$> (Component.input (Component.defaultInputIn { _inputIn_label = Msg.get Msg.Income_Date , _inputIn_initialValue = initialDate , _inputIn_inputType = "date" , _inputIn_hasResetButton = False , _inputIn_validation = IncomeValidation.date }) (initialDate <$ reset) confirm) let income = do a <- amount d <- date return . V.Success $ (_formIn_mkPayload formIn) a d (addIncome, cancel, confirm) <- R.divClass "buttons" $ do rec cancel <- Component._buttonOut_clic <$> (Component.button $ (Component.defaultButtonIn (R.text $ Msg.get Msg.Dialog_Undo)) { _buttonIn_class = R.constDyn "undo" }) confirm <- Component._buttonOut_clic <$> (Component.button $ (Component.defaultButtonIn (R.text $ Msg.get Msg.Dialog_Confirm)) { _buttonIn_class = R.constDyn "confirm" , _buttonIn_waiting = waiting , _buttonIn_submit = True }) (addIncome, waiting) <- WaitFor.waitFor (ajax "/api/income") (ValidationUtil.fireValidation income confirm) return (R.fmapMaybe EitherUtil.eitherToMaybe addIncome, cancel, confirm) return FormOut { _formOut_hide = R.leftmost [ cancel, () <$ addIncome ] , _formOut_addIncome = addIncome } where ajax = case _formIn_httpMethod formIn of Post -> Ajax.postJson Put -> Ajax.putJson