diff options
Diffstat (limited to 'frontend/src/Catalog.elm')
-rw-r--r-- | frontend/src/Catalog.elm | 89 |
1 files changed, 74 insertions, 15 deletions
diff --git a/frontend/src/Catalog.elm b/frontend/src/Catalog.elm index d4cbf96..666245e 100644 --- a/frontend/src/Catalog.elm +++ b/frontend/src/Catalog.elm | |||
@@ -10,6 +10,7 @@ import Html.Styled.Events exposing (..) | |||
10 | import Http | 10 | import Http |
11 | import Json.Decode as D | 11 | import Json.Decode as D |
12 | import Json.Encode as Encode | 12 | import Json.Encode as Encode |
13 | import Set | ||
13 | import Styles exposing (..) | 14 | import Styles exposing (..) |
14 | import Tuple exposing (..) | 15 | import Tuple exposing (..) |
15 | import Utils exposing (..) | 16 | import Utils exposing (..) |
@@ -35,12 +36,13 @@ type alias Product = | |||
35 | type alias Filters = | 36 | type alias Filters = |
36 | { price : ( Float, Float ) | 37 | { price : ( Float, Float ) |
37 | , rating : ( Float, Float ) | 38 | , rating : ( Float, Float ) |
39 | , kinds : Set.Set String | ||
38 | } | 40 | } |
39 | 41 | ||
40 | 42 | ||
41 | defaultFilters : Filters | 43 | defaultFilters : Filters |
42 | defaultFilters = | 44 | defaultFilters = |
43 | Filters ( -1, 100000 ) ( 0, 5 ) | 45 | Filters ( -1, 100000 ) ( 0, 5 ) (Set.fromList [ "Chair", "Sofa", "Bed", "Table", "Lamp" ]) |
44 | 46 | ||
45 | 47 | ||
46 | type alias Model = | 48 | type alias Model = |
@@ -63,6 +65,7 @@ type Msg | |||
63 | | ChangePriceUpper Float | 65 | | ChangePriceUpper Float |
64 | | ChangeRatingLower Float | 66 | | ChangeRatingLower Float |
65 | | ChangeRatingUpper Float | 67 | | ChangeRatingUpper Float |
68 | | FilterCheck String Bool | ||
66 | 69 | ||
67 | 70 | ||
68 | init : Model | 71 | init : Model |
@@ -128,6 +131,28 @@ update msg model = | |||
128 | in | 131 | in |
129 | ( { model | filters = nfs }, Cmd.none ) | 132 | ( { model | filters = nfs }, Cmd.none ) |
130 | 133 | ||
134 | FilterCheck field val -> | ||
135 | case val of | ||
136 | True -> | ||
137 | let | ||
138 | fs = | ||
139 | model.filters | ||
140 | |||
141 | nfs = | ||
142 | { fs | kinds = Set.insert field fs.kinds } | ||
143 | in | ||
144 | ( { model | filters = nfs }, Cmd.none ) | ||
145 | |||
146 | False -> | ||
147 | let | ||
148 | fs = | ||
149 | model.filters | ||
150 | |||
151 | nfs = | ||
152 | { fs | kinds = Set.remove field fs.kinds } | ||
153 | in | ||
154 | ( { model | filters = nfs }, Cmd.none ) | ||
155 | |||
131 | 156 | ||
132 | decodeProduct : D.Decoder Product | 157 | decodeProduct : D.Decoder Product |
133 | decodeProduct = | 158 | decodeProduct = |
@@ -181,13 +206,13 @@ viewProduct p = | |||
181 | , borderRadius (px 4) | 206 | , borderRadius (px 4) |
182 | , padding (px 20) | 207 | , padding (px 20) |
183 | , Css.width (pct 100) | 208 | , Css.width (pct 100) |
184 | , maxWidth (px 650) | 209 | , maxWidth (px 350) |
185 | ] | 210 | ] |
186 | ] | 211 | ] |
187 | [ div | 212 | [ div |
188 | [ css | 213 | [ css |
189 | [ float left | 214 | [ Css.width (pct 100) |
190 | , Css.width (pct 50) | 215 | , Css.height (px 350) |
191 | ] | 216 | ] |
192 | ] | 217 | ] |
193 | [ modelViewer | 218 | [ modelViewer |
@@ -197,13 +222,13 @@ viewProduct p = | |||
197 | , arIosSrc p.iosSrc | 222 | , arIosSrc p.iosSrc |
198 | , loading "eager" | 223 | , loading "eager" |
199 | , arModes "webxr" | 224 | , arModes "webxr" |
225 | , css [ Css.width (pct 100), Css.height (pct 100) ] | ||
200 | ] | 226 | ] |
201 | [] | 227 | [] |
202 | ] | 228 | ] |
203 | , div | 229 | , div |
204 | [ css | 230 | [ css |
205 | [ float left | 231 | [ Css.width (pct 100) |
206 | , Css.width (pct 50) | ||
207 | ] | 232 | ] |
208 | ] | 233 | ] |
209 | [ div | 234 | [ div |
@@ -220,7 +245,7 @@ viewProduct p = | |||
220 | , paddingBottom (px 3) | 245 | , paddingBottom (px 3) |
221 | ] | 246 | ] |
222 | ] | 247 | ] |
223 | [ a [ href ("/product/" ++ String.fromInt p.id) ] [ text p.name ] ] | 248 | [ furbyLink [ href ("/product/" ++ String.fromInt p.id) ] [ text p.name ] ] |
224 | , div | 249 | , div |
225 | [ css | 250 | [ css |
226 | [ cardSecondaryText | 251 | [ cardSecondaryText |
@@ -274,22 +299,57 @@ viewFilters model = | |||
274 | [ div | 299 | [ div |
275 | [ css | 300 | [ css |
276 | [ bigHeading | 301 | [ bigHeading |
277 | , paddingBottom (px 12) | 302 | , paddingBottom (px 18) |
278 | ] | 303 | ] |
279 | ] | 304 | ] |
280 | [ text "Filters" ] | 305 | [ text "Filters" ] |
281 | , div [] | 306 | , div |
307 | [ css | ||
308 | [ paddingBottom (px 12) | ||
309 | ] | ||
310 | ] | ||
282 | [ div [] [ text "Price" ] | 311 | [ div [] [ text "Price" ] |
283 | , furbySelect [ onInput (ChangePriceLower << inp), style "appearance" "none" ] (viewRange 0 priceRange) | 312 | , furbySelect [ onInput (ChangePriceLower << inp), style "appearance" "none" ] (viewRange 0 priceRange) |
284 | , text "to" | 313 | , text "to" |
285 | , furbySelect [ onInput (ChangePriceUpper << inp), style "appearance" "none" ] (viewRange 50000 priceRange) | 314 | , furbySelect [ onInput (ChangePriceUpper << inp), style "appearance" "none" ] (viewRange 50000 priceRange) |
286 | ] | 315 | ] |
287 | , div [] | 316 | , div |
317 | [ css | ||
318 | [ paddingBottom (px 12) | ||
319 | ] | ||
320 | ] | ||
288 | [ div [] [ text "Rating" ] | 321 | [ div [] [ text "Rating" ] |
289 | , furbySelect [ onInput (ChangeRatingLower << inp), style "appearance" "none" ] (viewRange 1 ratingRange) | 322 | , furbySelect [ onInput (ChangeRatingLower << inp), style "appearance" "none" ] (viewRange 1 ratingRange) |
290 | , text "to" | 323 | , text "to" |
291 | , furbySelect [ onInput (ChangeRatingUpper << inp), style "appearance" "none" ] (viewRange 5 ratingRange) | 324 | , furbySelect [ onInput (ChangeRatingUpper << inp), style "appearance" "none" ] (viewRange 5 ratingRange) |
292 | ] | 325 | ] |
326 | , let | ||
327 | kinds = | ||
328 | [ "Chair", "Sofa", "Bed", "Table", "Lamp" ] | ||
329 | in | ||
330 | div [] | ||
331 | ([ div | ||
332 | [ css | ||
333 | [ paddingBottom (px 12) | ||
334 | ] | ||
335 | ] | ||
336 | [ text "Furniture Kind" ] | ||
337 | ] | ||
338 | ++ List.map | ||
339 | (\k -> | ||
340 | div | ||
341 | [] | ||
342 | [ input | ||
343 | [ type_ "checkbox" | ||
344 | , onCheck (FilterCheck k) | ||
345 | , Html.Styled.Attributes.checked (Set.member k model.filters.kinds) | ||
346 | ] | ||
347 | [] | ||
348 | , text k | ||
349 | ] | ||
350 | ) | ||
351 | kinds | ||
352 | ) | ||
293 | ] | 353 | ] |
294 | 354 | ||
295 | 355 | ||
@@ -297,6 +357,7 @@ filterProducts : Model -> List Product | |||
297 | filterProducts model = | 357 | filterProducts model = |
298 | model.products | 358 | model.products |
299 | |> List.filter (between model.filters.price << .price) | 359 | |> List.filter (between model.filters.price << .price) |
360 | |> List.filter (flip Set.member model.filters.kinds << Maybe.withDefault "Chair" << .kind) | ||
300 | |> List.filter | 361 | |> List.filter |
301 | (\p -> | 362 | (\p -> |
302 | p.averageRating | 363 | p.averageRating |
@@ -328,11 +389,9 @@ view model = | |||
328 | ] | 389 | ] |
329 | ] | 390 | ] |
330 | [ div [ css [ bigHeading ] ] [ text "Products" ] | 391 | [ div [ css [ bigHeading ] ] [ text "Products" ] |
331 | , ul | 392 | , div |
332 | [ css | 393 | [ style "display" "grid" |
333 | [ padding (px 0) | 394 | , style "grid-template-columns" "auto auto auto" |
334 | , listStyle Css.none | ||
335 | ] | ||
336 | ] | 395 | ] |
337 | (filterProducts model |> List.map viewProduct) | 396 | (filterProducts model |> List.map viewProduct) |
338 | ] | 397 | ] |