module View.Payment.Table ( widget , TableIn(..) , TableOut(..) ) where import qualified Data.List as L import qualified Data.Map as M import Data.Text (Text) import qualified Data.Text as T import Prelude hiding (init) import Reflex.Dom (Dynamic, Event, MonadWidget) import qualified Reflex.Dom as R import Common.Model (Category (..), Init (..), Payment (..), PaymentCategory (..), User (..)) import qualified Common.Model as CM import qualified Common.Msg as Msg import qualified Common.View.Format as Format import Component (ButtonIn (..), ButtonOut (..), ModalIn (..), ModalOut (..)) import qualified Component as Component import View.Payment.Delete (DeleteIn (..), DeleteOut (..)) import qualified View.Payment.Delete as Delete import qualified Icon import qualified Util.Dom as DomUtil data TableIn t = TableIn { _tableIn_init :: Init , _tableIn_currentPage :: Dynamic t Int , _tableIn_payments :: Dynamic t [Payment] , _tableIn_perPage :: Int , _tableIn_paymentCategories :: Dynamic t [PaymentCategory] } data TableOut t = TableOut { _tableOut_deletePayment :: Event t Payment } widget :: forall t m. MonadWidget t m => TableIn t -> m (TableOut t) widget tableIn = do R.divClass "table" $ do deletePayment <- R.divClass "lines" $ do R.divClass "header" $ do R.divClass "cell name" $ R.text $ Msg.get Msg.Payment_Name R.divClass "cell cost" $ R.text $ Msg.get Msg.Payment_Cost R.divClass "cell user" $ R.text $ Msg.get Msg.Payment_User R.divClass "cell category" $ R.text $ Msg.get Msg.Payment_Category R.divClass "cell date" $ R.text $ Msg.get Msg.Payment_Date R.divClass "cell" $ R.blank R.divClass "cell" $ R.blank R.divClass "cell" $ R.blank (R.switch . R.current . fmap R.leftmost) <$> (R.simpleList paymentRange (paymentRow init paymentCategories)) DomUtil.divClassVisibleIf (null <$> payments) "emptyTableMsg" $ R.text $ Msg.get Msg.Payment_Empty return $ TableOut { _tableOut_deletePayment = deletePayment } where init = _tableIn_init tableIn currentPage = _tableIn_currentPage tableIn payments = _tableIn_payments tableIn paymentRange = getPaymentRange (_tableIn_perPage tableIn) <$> payments <*> currentPage paymentCategories = _tableIn_paymentCategories tableIn getPaymentRange :: Int -> [Payment] -> Int -> [Payment] getPaymentRange perPage payments currentPage = take perPage . drop ((currentPage - 1) * perPage) . reverse . L.sortOn _payment_date $ payments paymentRow :: forall t m. MonadWidget t m => Init -> Dynamic t [PaymentCategory] -> Dynamic t Payment -> m (Event t Payment) paymentRow init paymentCategories payment = R.divClass "row" $ do R.divClass "cell name" $ R.dynText $ fmap _payment_name payment R.divClass "cell cost" $ R.dynText $ fmap (Format.price (_init_currency init) . _payment_cost) payment let user = R.ffor payment (\p -> CM.findUser (_payment_user p) (_init_users init)) R.divClass "cell user" $ R.dynText $ flip fmap user $ \mbUser -> case mbUser of Just u -> _user_name u _ -> "" let category = do p <- payment pcs <- paymentCategories return $ findCategory (_init_categories init) pcs (_payment_name p) R.divClass "cell category" $ do let attrs = flip fmap category $ \maybeCategory -> case maybeCategory of Just c -> M.fromList [ ("class", "tag") , ("style", T.concat [ "background-color: ", _category_color c ]) ] Nothing -> M.singleton "display" "none" R.elDynAttr "span" attrs $ R.dynText $ flip fmap category $ \mbCategory -> case mbCategory of Just c -> _category_name c _ -> "" R.divClass "cell date" $ do R.elClass "span" "shortDate" . R.dynText . fmap (Format.shortDay . _payment_date) $ payment R.elClass "span" "longDate" . R.dynText . fmap (Format.longDay . _payment_date) $ payment R.divClass "cell button" $ R.el "button" Icon.clone let isFromCurrentUser = R.ffor payment (\p -> _payment_user p == _init_currentUser init) R.divClass "cell button" $ DomUtil.divVisibleIf isFromCurrentUser $ R.el "button" Icon.edit deletePayment <- R.divClass "cell button" $ DomUtil.divVisibleIf isFromCurrentUser $ _buttonOut_clic <$> (Component.button $ (Component.defaultButtonIn Icon.delete) { _buttonIn_class = R.constDyn "deletePayment" }) rec modalOut <- Component.modal $ ModalIn { _modalIn_show = deletePayment , _modalIn_hide = R.leftmost $ [ _deleteOut_cancel . _modalOut_content $ modalOut , fmap (const ()) . _deleteOut_validate . _modalOut_content $ modalOut ] , _modalIn_content = Delete.view (DeleteIn { _deleteIn_payment = payment }) } return (_deleteOut_validate . _modalOut_content $ modalOut) findCategory :: [Category] -> [PaymentCategory] -> Text -> Maybe Category findCategory categories paymentCategories paymentName = do paymentCategory <- L.find ((== T.toLower paymentName) . _paymentCategory_name) paymentCategories L.find ((== (_paymentCategory_category paymentCategory)) . _category_id) categories