module View.Payment.Header ( widget , HeaderIn(..) , HeaderOut(..) ) where import Control.Monad (forM_) import Control.Monad.IO.Class (liftIO) import qualified Data.List as L hiding (groupBy) import Data.Maybe (fromMaybe) import qualified Data.Text as T import qualified Data.Time as Time import Prelude hiding (init) import Reflex.Dom (MonadWidget) import qualified Reflex.Dom as R import Common.Model (Currency, ExceedingPayer (..), Frequency (..), Income (..), Init (..), Payment (..), User (..), UserId) import qualified Common.Model as CM import qualified Common.Msg as Msg import qualified Common.View.Format as Format import Component (ButtonIn (..)) import qualified Component as Component import qualified Util.List as L data HeaderIn t = HeaderIn { _headerIn_init :: Init } data HeaderOut = HeaderOut { } widget :: forall t m. MonadWidget t m => HeaderIn t -> m HeaderOut widget headerIn = R.divClass "header" $ do payerAndAdd incomes payments users currency infos payments users currency return $ HeaderOut {} where init = _headerIn_init headerIn incomes = _init_incomes init payments = filter ((==) Punctual . _payment_frequency) (_init_payments init) users = _init_users init currency = _init_currency init payerAndAdd :: forall t m. MonadWidget t m => [Income] -> [Payment] -> [User] -> Currency -> m () payerAndAdd incomes payments users currency = do time <- liftIO Time.getCurrentTime R.divClass "payerAndAdd" $ do R.divClass "exceedingPayers" $ forM_ (CM.getExceedingPayers time users incomes payments) (\p -> R.elClass "span" "exceedingPayer" $ do R.elClass "span" "userName" $ R.text . fromMaybe "" . fmap _user_name $ CM.findUser (_exceedingPayer_userId p) users R.elClass "span" "amount" $ do R.text "+ " R.text . Format.price currency $ _exceedingPayer_amount p ) _ <- Component.button $ ButtonIn { _buttonIn_class = R.constDyn "addPayment" , _buttonIn_content = R.text $ Msg.get Msg.Payment_Add , _buttonIn_waiting = R.never } return () infos :: forall t m. MonadWidget t m => [Payment] -> [User] -> Currency -> m () infos payments users currency = R.divClass "infos" $ do R.elClass "span" "total" $ do R.text . Msg.get $ Msg.Payment_Worth (T.intercalate " " [ (Format.number paymentCount) , if paymentCount > 1 then Msg.get Msg.Payment_Many else Msg.get Msg.Payment_One ]) (Format.price currency total) R.elClass "span" "partition" . R.text $ T.intercalate ", " . map (\(userId, userTotal) -> Msg.get $ Msg.Payment_By (fromMaybe "" . fmap _user_name $ CM.findUser userId users) (Format.price currency userTotal) ) $ totalByUser where paymentCount = length payments total = sum . map _payment_cost $ payments totalByUser :: [(UserId, Int)] totalByUser = L.sortBy (\(_, t1) (_, t2) -> compare t2 t1) . map (\(u, xs) -> (u, sum . map snd $ xs)) . L.groupBy fst . map (\p -> (_payment_user p, _payment_cost p)) $ payments