From 7c209f271ffc3122ada0331094e01dc6e409c2fb Mon Sep 17 00:00:00 2001 From: Joris Date: Sun, 9 Apr 2017 18:50:36 +0200 Subject: Add search input --- README.md | 2 +- public/main.css | 73 +++++++++++++++++++++++++++++-------------------- src/Food.purs | 9 ++---- src/Format.purs | 13 ++++----- src/Indicator.purs | 9 +++--- src/Main.purs | 2 +- src/Page.purs | 80 +++++++++++++++++++++++++++++++++++------------------- 7 files changed, 111 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index cf929f9..29c343f 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,6 @@ Sources ------- - http://www.aprifel.com/fiche-nutri-composant-glucides,6.html -- http://www.aly-abbara.com/livre_gyn_obs/termes/diabete/index_glycemique.html#glucides - http://www.montignac.com/fr/rechercher-l-index-glycemique-d-un-aliment/ - http://www.monmenu.fr/ +- https://www.lanutrition.fr/ diff --git a/public/main.css b/public/main.css index 0f092cf..fc0850a 100644 --- a/public/main.css +++ b/public/main.css @@ -1,44 +1,59 @@ -h1 { - text-align: center; - margin-bottom: 1em; - font-size: 46px; - color: #33AA00; -} +body { margin: 0; } -ul.aliments { - display: table; - margin: 0 auto; -} +/* Box sizing */ +html { box-sizing: border-box; } +*, *:before, *:after { box-sizing: inherit; } -ul.aliments > li { - display: table-row; +@media screen and (min-width: 700px) { + .page { + width: 700px; + margin: 0 auto; + } } -ul.aliments > li.title { - font-weight: bold; +@media screen and (max-width: 700px) { + .page { width: 100%; } } -ul.aliments > li > div { - display: table-cell; - padding: 15px; +.header { + position: fixed; + top: 0; + width: inherit; } -ul.aliments > li > .Good { - color: green; +.line { + height: 50px; + display: flex; + align-items: center; } -ul.aliments > li > .Medium { - color: orange; +.line.title { + background-color: #333333; + color: white; + font-size: 18px; + height: 60px; } -ul.aliments > li > .Bad { - color: red; +.line.search { + width: 100%; + padding: 0 15px; + border: none; + box-shadow: 0px 4px 2px -2px rgba(0, 0, 0, 0.2); + font-size: 14px; } -ul.aliments > li > .number { - text-align: right; -} +.aliments { margin-top: 110px; } -ul.aliments > li:nth-child(2n+3) { - background-color: #EEEEEE; -} +.line > * { padding: 15px; } + +.line > *:nth-child(1) { width: 40%; } +.line > *:nth-child(2) { width: 20%; } +.line > *:nth-child(3) { width: 20%; } +.line > *:nth-child(4) { width: 20%; } + +.line > .good { color: green; } +.line > .medium { color: orange; } +.line > .bad { color: red; } +.line > .number { text-align: right; } + +.aliment:nth-child(2n+1) { background-color: #F6F6F6; } diff --git a/src/Food.purs b/src/Food.purs index 9253959..980eb44 100644 --- a/src/Food.purs +++ b/src/Food.purs @@ -35,8 +35,6 @@ all = , { name: "Banane", glycemicIndex: 60, carbohydrates: 22 } , { name: "Betterave crue", glycemicIndex: 30, carbohydrates: 9 } , { name: "Betterave cuite", glycemicIndex: 65, carbohydrates: 7 } - -- , { name: "Blé (farine blanche)", glycemicIndex: 77, carbohydrates: 76 } - -- , { name: "Blé (farine complète)", glycemicIndex: 40, carbohydrates: 73 } , { name: "Boulghour", glycemicIndex: 55, carbohydrates: 20 } , { name: "Brocoli", glycemicIndex: 15, carbohydrates: 5 } , { name: "Brugnon", glycemicIndex: 35, carbohydrates: 14 } @@ -54,6 +52,7 @@ all = , { name: "Cerneaux de noix", glycemicIndex: 15, carbohydrates: 11 } , { name: "Champignon", glycemicIndex: 0, carbohydrates: 1 } , { name: "Chataigne grillée", glycemicIndex: 60, carbohydrates: 42 } + , { name: "Croissant", glycemicIndex: 60, carbohydrates: 57 } , { name: "Choux blanc", glycemicIndex: 15, carbohydrates: 4 } , { name: "Choux chinois", glycemicIndex: 15, carbohydrates: 1 } @@ -83,10 +82,8 @@ all = , { name: "Endive", glycemicIndex: 15, carbohydrates: 4 } , { name: "Épinard", glycemicIndex: 15, carbohydrates: 3 } - , { name: "Faisselle 0%", glycemicIndex: 30, carbohydrates: 4 } , { name: "Faisselle 40%", glycemicIndex: 30, carbohydrates: 3 } - , { name: "Farine de blé", glycemicIndex: 85, carbohydrates: 71 } , { name: "Farine de blé à levure incorporée", glycemicIndex: 85, carbohydrates: 71 } , { name: "Farine de blé complète T130", glycemicIndex: 45, carbohydrates: 64 } @@ -180,9 +177,9 @@ all = , { name: "Pain au seigle", glycemicIndex: 65, carbohydrates: 50 } , { name: "pain aux céréales", glycemicIndex: 65, carbohydrates: 55 } , { name: "Pain aux raisins", glycemicIndex: 70, carbohydrates: 46 } - , { name: "Pain chocolat", glycemicIndex: 65, carbohydrates: 33 } + , { name: "Pain au chocolat", glycemicIndex: 65, carbohydrates: 49 } , { name: "Pain complet", glycemicIndex: 65, carbohydrates: 44 } - , { name: "pain hamburger complet", glycemicIndex: 20, carbohydrates: 48 } + , { name: "pain hamburger complet", glycemicIndex: 48, carbohydrates: 48 } , { name: "Pastèque", glycemicIndex: 75, carbohydrates: 7 } , { name: "Pâte", glycemicIndex: 70, carbohydrates: 20 } , { name: "Pâte de fruit", glycemicIndex: 70, carbohydrates: 53 } diff --git a/src/Format.purs b/src/Format.purs index bed5927..e8ab661 100644 --- a/src/Format.purs +++ b/src/Format.purs @@ -1,17 +1,15 @@ module Format ( number - , compare + , string , unaccent ) where -import Data.Int (toNumber, fromNumber) import Data.Array (replicate) +import Data.Int (toNumber, fromNumber) import Data.Maybe (fromMaybe) import Data.String (length, joinWith, fromCharArray, toCharArray, toLower) import Math (round, trunc, pow) - -import Prelude hiding (compare) -import Prelude as Prelude +import Prelude number :: Int -> Number -> String number decimalLength num = formattedIntegerPart <> formattedDecimalPart @@ -33,9 +31,8 @@ number decimalLength num = formattedIntegerPart <> formattedDecimalPart else "" -compare :: String -> String -> Ordering -compare xs ys = Prelude.compare (formatString xs) (formatString ys) - where formatString = unaccent <<< toLower +string :: String -> String +string = unaccent <<< toLower unaccent :: String -> String unaccent = fromCharArray <<< map unaccentChar <<< toCharArray diff --git a/src/Indicator.purs b/src/Indicator.purs index 39a98ca..751c069 100644 --- a/src/Indicator.purs +++ b/src/Indicator.purs @@ -1,5 +1,6 @@ module Indicator ( Indicator(..) + , className , fromGlycemicLoad ) where @@ -7,10 +8,10 @@ import Prelude data Indicator = Good | Medium | Bad -instance showIndicator :: Show Indicator where - show Good = "Good" - show Medium = "Medium" - show Bad = "Bad" +className :: Indicator -> String +className Good = "good" +className Medium = "medium" +className Bad = "bad" fromGlycemicLoad :: Number -> Indicator fromGlycemicLoad n diff --git a/src/Main.purs b/src/Main.purs index e00f4ce..85346b3 100644 --- a/src/Main.purs +++ b/src/Main.purs @@ -12,4 +12,4 @@ import Page as Page main :: Eff (HA.HalogenEffects ()) Unit main = HA.runHalogenAff do body <- HA.awaitBody - runUI Page.component unit body + runUI Page.component "" body diff --git a/src/Page.purs b/src/Page.purs index c0b641c..850875a 100644 --- a/src/Page.purs +++ b/src/Page.purs @@ -3,10 +3,14 @@ module Page , Query ) where -import Data.Array ((:), sortBy) +import Control.Monad.Aff (Aff) +import Data.Array (sortBy, filter) 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 @@ -15,14 +19,18 @@ import Food as Food import Format as Format import Indicator as Indicator -data Query a = NoOp a -type State = Unit +data Query a = + NoOp a + | UpdateSearch String a + +type State = String + type Message = Unit -component :: forall m . H.Component HH.HTML Query State Message m +component :: forall eff. H.Component HH.HTML Query State Message (Aff (dom :: DOM | eff)) component = H.component - { initialState: const unit + { initialState: const "" , render , eval , receiver: const Nothing @@ -31,39 +39,55 @@ component = render :: State -> H.ComponentHTML Query render state = HH.div - [] - [ HH.h1 [] [ HH.text "Glycémie" ] - , HH.ul + [ HP.class_ $ HH.ClassName "page" ] + [ renderHeader state + , HH.div [ HP.class_ $ HH.ClassName "aliments" ] - (renderTitle : (map renderAliment <<< sortBy (\a b -> Format.compare a.name b.name) $ Food.all)) + ( Food.all + # filter (\a -> contains (Pattern $ Format.string state) (Format.string a.name)) + # sortBy (\a b -> compare (Format.string a.name) (Format.string b.name)) + # map renderAliment + ) ] - eval :: Query ~> H.ComponentDSL State Query Message m + eval :: Query ~> H.ComponentDSL State Query Message (Aff (dom :: DOM | eff)) eval = case _ of NoOp next -> pure next + UpdateSearch search next -> do + H.put search + pure next -renderTitle :: H.ComponentHTML Query -renderTitle = - HH.li - [ HP.class_ $ HH.ClassName "title" ] +renderHeader :: String -> H.ComponentHTML Query +renderHeader search = + HH.div + [ HP.class_ $ HH.ClassName "header" ] [ HH.div - [] - [ HH.text "Aliment" ] - , HH.div - [] - [ HH.text "Index glycémique" ] - , HH.div - [] - [ HH.text "Glucides pour 100 g" ] - , HH.div - [] - [ HH.text "Charge glycémique" ] + [ HP.class_ $ HH.ClassName "title line" ] + [ HH.div + [] + [ HH.text "Aliment" ] + , HH.div + [] + [ HH.text "Index glycémique" ] + , HH.div + [] + [ HH.text "Glucides pour 100g" ] + , HH.div + [] + [ HH.text "Charge glycémique" ] + ] + , HH.input + [ HP.class_ $ HH.ClassName "search line" + , HP.placeholder "Rechercher…" + , HE.onValueInput (HE.input UpdateSearch) + , HP.value search + ] ] renderAliment :: Aliment -> H.ComponentHTML Query renderAliment aliment = - HH.li - [] + HH.div + [ HP.class_ $ HH.ClassName "aliment line" ] [ HH.div [] [ HH.text aliment.name ] @@ -75,6 +99,6 @@ renderAliment aliment = [ HH.text (show aliment.carbohydrates) ] , let glycemicLoad = Food.glycemicLoad aliment in HH.div - [ HP.class_ $ HH.ClassName ("number " <> (show $ Indicator.fromGlycemicLoad glycemicLoad)) ] + [ HP.class_ $ HH.ClassName ("number " <> (Indicator.className $ Indicator.fromGlycemicLoad glycemicLoad)) ] [ HH.text (Format.number 2 glycemicLoad) ] ] -- cgit v1.2.3