aboutsummaryrefslogtreecommitdiff
path: root/src/Page.purs
blob: 40c8ddc0d900242c79b3475dc92f3b5606433b59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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) ]
    ]