module View.Payment.Add ( view , AddIn(..) , AddOut(..) ) where import Control.Monad.IO.Class (liftIO) import qualified Data.Map as M import qualified Data.Maybe as Maybe import qualified Data.Text as T import qualified Data.Time.Calendar as Calendar import qualified Data.Time.Clock as Time import Reflex.Dom (Event, MonadWidget, Reflex) import qualified Reflex.Dom as R import qualified Text.Read as T import Common.Model (Category (..), CreatePayment (..), Frequency (..), Payment (..)) import qualified Common.Msg as Msg import qualified Common.Util.Time as Time import Component (ButtonIn (..), InputIn (..), InputOut (..), SelectIn (..), SelectOut (..)) import qualified Component as Component import qualified Util.Ajax as Ajax import qualified Util.Either as EitherUtil import qualified Util.WaitFor as WaitFor data AddIn t = AddIn { _addIn_categories :: [Category] , _addIn_show :: Event t () } data AddOut t = AddOut { _addOut_cancel :: Event t () , _addOut_addedPayment :: Event t Payment } view :: forall t m. MonadWidget t m => AddIn t -> m (AddOut t) view addIn = do R.divClass "add" $ do R.divClass "addHeader" $ R.text $ Msg.get Msg.Payment_Add R.divClass "addContent" $ do name <- _inputOut_value <$> (Component.input (Component.defaultInputIn { _inputIn_label = Msg.get Msg.Payment_Name }) (_addIn_show addIn)) cost <- _inputOut_value <$> (Component.input (Component.defaultInputIn { _inputIn_label = Msg.get Msg.Payment_Cost }) (_addIn_show addIn)) currentDay <- liftIO $ Time.getCurrentTime >>= Time.timeToDay date <- _inputOut_value <$> (Component.input (Component.defaultInputIn { _inputIn_label = Msg.get Msg.Payment_Date , _inputIn_initialValue = T.pack . Calendar.showGregorian $ currentDay , _inputIn_inputType = "date" , _inputIn_hasResetButton = False }) (_addIn_show addIn)) frequency <- _selectOut_value <$> (Component.select $ SelectIn { _selectIn_label = Msg.get Msg.Payment_Frequency , _selectIn_initialValue = Punctual , _selectIn_values = R.constDyn frequencies , _selectIn_reset = _addIn_show addIn }) category <- _selectOut_value <$> (Component.select $ SelectIn { _selectIn_label = Msg.get Msg.Payment_Category , _selectIn_initialValue = 0 , _selectIn_values = R.constDyn categories , _selectIn_reset = _addIn_show addIn }) let payment = CreatePayment <$> name <*> fmap (Maybe.fromMaybe 0 . T.readMaybe . T.unpack) cost <*> fmap (Maybe.fromMaybe currentDay . Time.parseDay) date <*> category <*> frequency (addedPayment, cancel) <- R.divClass "buttons" $ do rec validate <- 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 }) (result, waiting) <- WaitFor.waitFor (Ajax.postJson "/payment") (R.tag (R.current payment) validate) cancel <- Component._buttonOut_clic <$> (Component.button $ (Component.defaultButtonIn (R.text $ Msg.get Msg.Dialog_Undo)) { _buttonIn_class = R.constDyn "undo" }) return (R.fmapMaybe EitherUtil.eitherToMaybe result, cancel) return AddOut { _addOut_cancel = cancel , _addOut_addedPayment = addedPayment } where frequencies = M.fromList [ (Punctual, Msg.get Msg.Payment_PunctualMale) , (Monthly, Msg.get Msg.Payment_MonthlyMale) ] categories = M.fromList . flip map (_addIn_categories addIn) $ \c -> (_category_id c, _category_name c)