module Page ( component , Query , init ) where import Control.Monad.Aff (Aff) import Data.Array (sortBy, filter, reverse) import Data.Maybe (Maybe(..)) import Data.String (contains, Pattern(..)) import DOM (DOM) import Halogen as H import Halogen.HTML as HH import Halogen.HTML.Events as HE import Halogen.HTML.Properties as HP import Prelude import Food (Aliment) import Food as Food import Format as Format import Indicator as Indicator import Order (Order, OrderKind) import Order as Order data Query a = UpdateSearch String a | SelectOrder OrderKind a type State = { search :: String , order :: Order } init :: State init = { search: "" , order: Order.init } type Message = Unit component :: forall eff. H.Component HH.HTML Query State Message (Aff (dom :: DOM | eff)) component = H.component { initialState: const init , render , eval , receiver: const Nothing } where render :: State -> H.ComponentHTML Query render state = HH.div [ HP.class_ $ HH.ClassName "page" ] [ renderHeader state.order.kind state.search , HH.div [ HP.class_ $ HH.ClassName "aliments" ] ( Food.all # filter (\a -> contains (Pattern $ Format.string state.search) (Format.string a.name)) # sortBy compareAliments # (if state.order.direction == Order.Ascending then id else reverse) # map renderAliment ) ] where compareAliments :: Aliment -> Aliment -> Ordering compareAliments a b = case state.order.kind of Order.Name -> compare (Format.string a.name) (Format.string b.name) Order.GlycemicIndex -> compare a.glycemicIndex b.glycemicIndex Order.Carbohydrates -> compare a.carbohydrates b.carbohydrates Order.GlycemicLoad -> compare (Food.glycemicLoad a) (Food.glycemicLoad b) eval :: Query ~> H.ComponentDSL State Query Message (Aff (dom :: DOM | eff)) eval = case _ of UpdateSearch search next -> do state <- H.get H.put $ state { search = search } pure next SelectOrder kind next -> do state <- H.get H.put $ state { order = Order.select kind state.order } pure next renderHeader :: OrderKind -> String -> H.ComponentHTML Query renderHeader orderKind search = HH.div [ HP.class_ $ HH.ClassName "header" ] [ HH.div [ HP.class_ $ HH.ClassName "title line" ] [ button Order.Name "Aliment" , button Order.GlycemicIndex "Index glycémique" , button Order.Carbohydrates "Glucides pour 100 g" , button Order.GlycemicLoad "Charge glycémique" ] , HH.input [ HP.class_ $ HH.ClassName "search line" , HP.placeholder "Rechercher…" , HE.onValueInput (HE.input UpdateSearch) , HP.value search ] ] where button :: OrderKind -> String -> H.ComponentHTML Query button kind label = HH.button [ HE.onClick (HE.input_ (SelectOrder kind)) , HP.class_ $ HH.ClassName (if orderKind == kind then "sorted" else "") ] [ HH.text label ] renderAliment :: Aliment -> H.ComponentHTML Query renderAliment aliment = HH.div [ HP.class_ $ HH.ClassName "aliment line" ] [ HH.div [] [ HH.text aliment.name ] , HH.div [ HP.class_ $ HH.ClassName "number" ] [ HH.text (show aliment.glycemicIndex) ] , HH.div [ HP.class_ $ HH.ClassName "number" ] [ HH.text (show aliment.carbohydrates <> " g") ] , let glycemicLoad = Food.glycemicLoad aliment in HH.div [ HP.class_ $ HH.ClassName ("number " <> (Indicator.className $ Indicator.fromGlycemicLoad glycemicLoad)) ] [ HH.text (Format.number 2 glycemicLoad) ] ]