diff options
author | Akshay <[email protected]> | 2020-12-27 11:27:44 +0000 |
---|---|---|
committer | Akshay <[email protected]> | 2020-12-27 11:27:44 +0000 |
commit | d5aabbac71fcd12f31c82159fe0d7a58d0ad925d (patch) | |
tree | d4a0516cecc85dab18d4e76230da05752d74ba9a | |
parent | ab3ddc1fae1364afeefc0d2c30d8e11a31839948 (diff) |
add catalog filters, furbyLink component
-rw-r--r-- | frontend/src/Cart.elm | 4 | ||||
-rw-r--r-- | frontend/src/Catalog.elm | 89 | ||||
-rw-r--r-- | frontend/src/Login.elm | 2 | ||||
-rw-r--r-- | frontend/src/Main.elm | 31 | ||||
-rw-r--r-- | frontend/src/Product.elm | 24 | ||||
-rw-r--r-- | frontend/src/Signup.elm | 2 | ||||
-rw-r--r-- | frontend/src/Styles.elm | 15 | ||||
-rw-r--r-- | frontend/src/Utils.elm | 5 |
8 files changed, 128 insertions, 44 deletions
diff --git a/frontend/src/Cart.elm b/frontend/src/Cart.elm index 4f4cbef..f4697a8 100644 --- a/frontend/src/Cart.elm +++ b/frontend/src/Cart.elm | |||
@@ -193,7 +193,7 @@ viewCartItemListing listing = | |||
193 | -- , div [] [ a [ href ("/product/" ++ String.fromInt listing.productItem.id) ] [ text "View Product" ] ] | 193 | -- , div [] [ a [ href ("/product/" ++ String.fromInt listing.productItem.id) ] [ text "View Product" ] ] |
194 | -- ] | 194 | -- ] |
195 | tr [] | 195 | tr [] |
196 | [ td [] [ a [ href ("/product/" ++ String.fromInt listing.productItem.id) ] [ text listing.productItem.name ] ] | 196 | [ td [] [ furbyLink [ href ("/product/" ++ String.fromInt listing.productItem.id) ] [ text listing.productItem.name ] ] |
197 | , td [] [ text <| String.fromFloat listing.productItem.price ] | 197 | , td [] [ text <| String.fromFloat listing.productItem.price ] |
198 | , td [] | 198 | , td [] |
199 | [ furbyButton [ onClick (RemoveFromCart listing.productItem.id) ] [ div [ style "font-family" "monospace" ] [ text "-" ] ] | 199 | [ furbyButton [ onClick (RemoveFromCart listing.productItem.id) ] [ div [ style "font-family" "monospace" ] [ text "-" ] ] |
@@ -250,6 +250,6 @@ view model = | |||
250 | [ css [ textAlign right ] ] | 250 | [ css [ textAlign right ] ] |
251 | [ furbyButton | 251 | [ furbyButton |
252 | [] | 252 | [] |
253 | [ a [ href "/checkout" ] [ text "Checkout" ] ] | 253 | [ furbyLink [ href "/checkout" ] [ text "Checkout" ] ] |
254 | ] | 254 | ] |
255 | ] | 255 | ] |
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 | ] |
diff --git a/frontend/src/Login.elm b/frontend/src/Login.elm index 87657bb..92a894f 100644 --- a/frontend/src/Login.elm +++ b/frontend/src/Login.elm | |||
@@ -134,5 +134,5 @@ view model = | |||
134 | , div [ fieldPadding ] [ viewInput "password" "Password" model.password PassEntered ] | 134 | , div [ fieldPadding ] [ viewInput "password" "Password" model.password PassEntered ] |
135 | , div [ css [ textAlign center ], fieldPadding ] [ furbyButton [ onClick LoginPressed ] [ text "Login" ] ] | 135 | , div [ css [ textAlign center ], fieldPadding ] [ furbyButton [ onClick LoginPressed ] [ text "Login" ] ] |
136 | , div [ css [ textAlign center ] ] [ text (viewStatus model.loginStatus) ] | 136 | , div [ css [ textAlign center ] ] [ text (viewStatus model.loginStatus) ] |
137 | , div [ fieldPadding ] [ text "Don't have an account? ", a [ href "/signup" ] [ text "Register now!" ] ] | 137 | , div [ fieldPadding ] [ text "Don't have an account? ", furbyLink [ href "/signup" ] [ text "Register now!" ] ] |
138 | ] | 138 | ] |
diff --git a/frontend/src/Main.elm b/frontend/src/Main.elm index 09a851d..07b029d 100644 --- a/frontend/src/Main.elm +++ b/frontend/src/Main.elm | |||
@@ -315,23 +315,24 @@ view model = | |||
315 | HomePage -> | 315 | HomePage -> |
316 | { title = "Login" | 316 | { title = "Login" |
317 | , body = | 317 | , body = |
318 | -- model.loginModel | 318 | model.loginModel |
319 | -- |> Login.view | 319 | |> Login.view |
320 | -- |> Html.Styled.map LoginMessage | 320 | |> Html.Styled.map LoginMessage |
321 | -- |> toUnstyled | ||
322 | -- |> List.singleton | ||
323 | div [] | ||
324 | [ ul [] | ||
325 | (List.map | ||
326 | (\l -> | ||
327 | li [] | ||
328 | [ a [ href l ] [ text l ] ] | ||
329 | ) | ||
330 | [ "/login", "/catalog", "/cart" ] | ||
331 | ) | ||
332 | ] | ||
333 | |> toUnstyled | 321 | |> toUnstyled |
334 | |> List.singleton | 322 | |> List.singleton |
323 | |||
324 | --div [] | ||
325 | -- [ ul [] | ||
326 | -- (List.map | ||
327 | -- (\l -> | ||
328 | -- li [] | ||
329 | -- [ a [ href l ] [ text l ] ] | ||
330 | -- ) | ||
331 | -- [ "/login", "/catalog", "/cart" ] | ||
332 | -- ) | ||
333 | -- ] | ||
334 | -- |> toUnstyled | ||
335 | -- |> List.singleton | ||
335 | } | 336 | } |
336 | 337 | ||
337 | LoginPage -> | 338 | LoginPage -> |
diff --git a/frontend/src/Product.elm b/frontend/src/Product.elm index 964538b..bedb22d 100644 --- a/frontend/src/Product.elm +++ b/frontend/src/Product.elm | |||
@@ -257,7 +257,7 @@ viewProduct p = | |||
257 | div | 257 | div |
258 | [ css | 258 | [ css |
259 | [ marginBottom (px 20) | 259 | [ marginBottom (px 20) |
260 | , padding (px 20) | 260 | , paddingTop (px 20) |
261 | , Css.width (pct 100) | 261 | , Css.width (pct 100) |
262 | ] | 262 | ] |
263 | ] | 263 | ] |
@@ -265,6 +265,7 @@ viewProduct p = | |||
265 | [ css | 265 | [ css |
266 | [ float left | 266 | [ float left |
267 | , Css.width (pct 50) | 267 | , Css.width (pct 50) |
268 | , Css.height (px 400) | ||
268 | ] | 269 | ] |
269 | ] | 270 | ] |
270 | [ modelViewer | 271 | [ modelViewer |
@@ -274,6 +275,7 @@ viewProduct p = | |||
274 | , arIosSrc p.iosSrc | 275 | , arIosSrc p.iosSrc |
275 | , loading "eager" | 276 | , loading "eager" |
276 | , arModes "webxr" | 277 | , arModes "webxr" |
278 | , css [ Css.height (pct 100), Css.width (pct 100) ] | ||
277 | ] | 279 | ] |
278 | [] | 280 | [] |
279 | ] | 281 | ] |
@@ -312,12 +314,11 @@ viewProduct p = | |||
312 | , money | 314 | , money |
313 | ] | 315 | ] |
314 | ] | 316 | ] |
315 | [ text <| String.fromFloat p.price | 317 | [ text <| String.fromFloat p.price ] |
316 | , div [] | ||
317 | [ furbyButton [ onClick AddToCartPressed ] [ text "Add To Cart" ] | ||
318 | ] | ||
319 | ] | ||
320 | ] | 318 | ] |
319 | , div | ||
320 | [ css [ textAlign center, float bottom ] ] | ||
321 | [ furbyButton [ onClick AddToCartPressed, style "width" "100%" ] [ text "Add To Cart" ] ] | ||
321 | , div [ style "clear" "both" ] [] | 322 | , div [ style "clear" "both" ] [] |
322 | ] | 323 | ] |
323 | 324 | ||
@@ -377,7 +378,7 @@ viewInput t p v toMsg = | |||
377 | , placeholder p | 378 | , placeholder p |
378 | , value v | 379 | , value v |
379 | , onInput toMsg | 380 | , onInput toMsg |
380 | , css [ Css.width (pct 100), Css.height (px 100) ] | 381 | , css [ Css.width (pct 100) ] |
381 | ] | 382 | ] |
382 | [] | 383 | [] |
383 | 384 | ||
@@ -457,7 +458,14 @@ view model = | |||
457 | [ viewStars model | 458 | [ viewStars model |
458 | , div | 459 | , div |
459 | [] | 460 | [] |
460 | [ viewInput "textarea" "Enter Comment Text" model.ratingText AddRatingComment ] | 461 | [ textarea |
462 | [ onInput AddRatingComment | ||
463 | , rows 5 | ||
464 | , placeholder "Enter comment text" | ||
465 | , css [ Css.width (pct 100) ] | ||
466 | ] | ||
467 | [ text model.ratingText ] | ||
468 | ] | ||
461 | , div | 469 | , div |
462 | [ css | 470 | [ css |
463 | [ textAlign center ] | 471 | [ textAlign center ] |
diff --git a/frontend/src/Signup.elm b/frontend/src/Signup.elm index 028af9c..64c744e 100644 --- a/frontend/src/Signup.elm +++ b/frontend/src/Signup.elm | |||
@@ -217,7 +217,7 @@ view model = | |||
217 | ] | 217 | ] |
218 | , div [ fieldPadding ] | 218 | , div [ fieldPadding ] |
219 | [ text "Already have a account? " | 219 | [ text "Already have a account? " |
220 | , a [ href "/login" ] [ text "Login >" ] | 220 | , furbyLink [ href "/login" ] [ text "Login >" ] |
221 | ] | 221 | ] |
222 | , text (viewStatus model.status) | 222 | , text (viewStatus model.status) |
223 | ] | 223 | ] |
diff --git a/frontend/src/Styles.elm b/frontend/src/Styles.elm index 4222024..08cd6f3 100644 --- a/frontend/src/Styles.elm +++ b/frontend/src/Styles.elm | |||
@@ -47,8 +47,7 @@ headerLink = | |||
47 | , padding (px 12) | 47 | , padding (px 12) |
48 | , textDecoration Css.none | 48 | , textDecoration Css.none |
49 | , hover | 49 | , hover |
50 | [ backgroundColor theme.secondary | 50 | [ textDecoration underline |
51 | , textDecoration underline | ||
52 | ] | 51 | ] |
53 | ] | 52 | ] |
54 | 53 | ||
@@ -71,6 +70,17 @@ furbyButton = | |||
71 | ] | 70 | ] |
72 | 71 | ||
73 | 72 | ||
73 | furbyLink : List (Attribute msg) -> List (Html msg) -> Html msg | ||
74 | furbyLink = | ||
75 | styled a | ||
76 | [ color theme.fgLight | ||
77 | , textDecoration Css.none | ||
78 | , hover | ||
79 | [ backgroundColor theme.secondary | ||
80 | ] | ||
81 | ] | ||
82 | |||
83 | |||
74 | furbyRadio : String -> msg -> Html msg | 84 | furbyRadio : String -> msg -> Html msg |
75 | furbyRadio value msg = | 85 | furbyRadio value msg = |
76 | label | 86 | label |
@@ -108,6 +118,7 @@ loginInputField = | |||
108 | , color theme.fg | 118 | , color theme.fg |
109 | , border (px 0) | 119 | , border (px 0) |
110 | , borderBottom3 (px 1) solid theme.bgLight | 120 | , borderBottom3 (px 1) solid theme.bgLight |
121 | , outline Css.none | ||
111 | , focus | 122 | , focus |
112 | [ borderBottom3 (px 2) solid theme.fg | 123 | [ borderBottom3 (px 2) solid theme.fg |
113 | ] | 124 | ] |
diff --git a/frontend/src/Utils.elm b/frontend/src/Utils.elm index b6c4bd5..3a308ca 100644 --- a/frontend/src/Utils.elm +++ b/frontend/src/Utils.elm | |||
@@ -11,6 +11,11 @@ between ( l, u ) v = | |||
11 | v >= l && v <= u | 11 | v >= l && v <= u |
12 | 12 | ||
13 | 13 | ||
14 | flip : (a -> b -> c) -> (b -> a -> c) | ||
15 | flip f = | ||
16 | \b a -> f a b | ||
17 | |||
18 | |||
14 | range : Int -> Int -> Int -> List Int | 19 | range : Int -> Int -> Int -> List Int |
15 | range start stop step = | 20 | range start stop step = |
16 | if start >= stop then | 21 | if start >= stop then |