diff options
author | Akshay <[email protected]> | 2020-12-26 14:43:50 +0000 |
---|---|---|
committer | Akshay <[email protected]> | 2020-12-26 14:43:50 +0000 |
commit | b8a744f6e7e02f67551124063d3dd97faba5fb0b (patch) | |
tree | c219b2177d4608a1862de0d66e978086c06e63f8 /frontend/src | |
parent | a7881f40ccaa623d757e762d1215d5e9bc9d1a7a (diff) |
begin work on frontend
Diffstat (limited to 'frontend/src')
-rw-r--r-- | frontend/src/Cart.elm | 7 | ||||
-rw-r--r-- | frontend/src/Catalog.elm | 62 | ||||
-rw-r--r-- | frontend/src/Checkout.elm | 7 | ||||
-rw-r--r-- | frontend/src/Icons.elm | 15 | ||||
-rw-r--r-- | frontend/src/Login.elm | 41 | ||||
-rw-r--r-- | frontend/src/Main.elm | 125 | ||||
-rw-r--r-- | frontend/src/Product.elm | 35 | ||||
-rw-r--r-- | frontend/src/Signup.elm | 49 | ||||
-rw-r--r-- | frontend/src/Styles.elm | 104 | ||||
-rw-r--r-- | frontend/src/Utils.elm | 45 |
10 files changed, 398 insertions, 92 deletions
diff --git a/frontend/src/Cart.elm b/frontend/src/Cart.elm index 58fb72e..44d5a0d 100644 --- a/frontend/src/Cart.elm +++ b/frontend/src/Cart.elm | |||
@@ -2,9 +2,10 @@ module Cart exposing (..) | |||
2 | 2 | ||
3 | import Browser | 3 | import Browser |
4 | import Browser.Navigation as Nav | 4 | import Browser.Navigation as Nav |
5 | import Html exposing (..) | 5 | import Html |
6 | import Html.Attributes exposing (..) | 6 | import Html.Styled exposing (..) |
7 | import Html.Events exposing (..) | 7 | import Html.Styled.Attributes exposing (..) |
8 | import Html.Styled.Events exposing (..) | ||
8 | import Http | 9 | import Http |
9 | import Json.Decode as D | 10 | import Json.Decode as D |
10 | import Json.Encode as Encode | 11 | import Json.Encode as Encode |
diff --git a/frontend/src/Catalog.elm b/frontend/src/Catalog.elm index d00cb92..5b233f2 100644 --- a/frontend/src/Catalog.elm +++ b/frontend/src/Catalog.elm | |||
@@ -2,15 +2,16 @@ module Catalog exposing (..) | |||
2 | 2 | ||
3 | import Browser | 3 | import Browser |
4 | import Browser.Navigation as Nav | 4 | import Browser.Navigation as Nav |
5 | import Html exposing (..) | 5 | import Css exposing (..) |
6 | import Html.Attributes exposing (..) | 6 | import Html |
7 | import Html.Events exposing (..) | 7 | import Html.Styled exposing (..) |
8 | import Html.Styled.Attributes exposing (..) | ||
9 | import Html.Styled.Events exposing (..) | ||
8 | import Http | 10 | import Http |
9 | import Json.Decode as D | 11 | import Json.Decode as D |
10 | import Json.Encode as Encode | 12 | import Json.Encode as Encode |
13 | import Styles exposing (..) | ||
11 | import Tuple exposing (..) | 14 | import Tuple exposing (..) |
12 | import Url | ||
13 | import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string) | ||
14 | import Utils exposing (..) | 15 | import Utils exposing (..) |
15 | 16 | ||
16 | 17 | ||
@@ -37,7 +38,7 @@ type alias Filters = | |||
37 | 38 | ||
38 | defaultFilters : Filters | 39 | defaultFilters : Filters |
39 | defaultFilters = | 40 | defaultFilters = |
40 | Filters ( -1, 10000 ) ( 0, 5 ) | 41 | Filters ( -1, 100000 ) ( 0, 5 ) |
41 | 42 | ||
42 | 43 | ||
43 | type alias Model = | 44 | type alias Model = |
@@ -199,18 +200,26 @@ viewFilters model = | |||
199 | inp = | 200 | inp = |
200 | Maybe.withDefault 0 << String.toFloat | 201 | Maybe.withDefault 0 << String.toFloat |
201 | in | 202 | in |
202 | div [] | 203 | div |
203 | [ div [] | 204 | [] |
204 | [ text "Price" | 205 | [ div |
205 | , select [ onInput (ChangePriceLower << inp) ] (viewRange 0 priceRange) | 206 | [ css |
207 | [ bigHeading | ||
208 | , paddingBottom (px 12) | ||
209 | ] | ||
210 | ] | ||
211 | [ text "Filters" ] | ||
212 | , div [] | ||
213 | [ div [] [ text "Price" ] | ||
214 | , furbySelect [ onInput (ChangePriceLower << inp), style "appearance" "none" ] (viewRange 0 priceRange) | ||
206 | , text "to" | 215 | , text "to" |
207 | , select [ onInput (ChangePriceUpper << inp) ] (viewRange 50000 priceRange) | 216 | , furbySelect [ onInput (ChangePriceUpper << inp), style "appearance" "none" ] (viewRange 50000 priceRange) |
208 | ] | 217 | ] |
209 | , div [] | 218 | , div [] |
210 | [ text "Rating" | 219 | [ div [] [ text "Rating" ] |
211 | , select [ onInput (ChangeRatingLower << inp) ] (viewRange 1 ratingRange) | 220 | , furbySelect [ onInput (ChangeRatingLower << inp), style "appearance" "none" ] (viewRange 1 ratingRange) |
212 | , text "to" | 221 | , text "to" |
213 | , select [ onInput (ChangeRatingUpper << inp) ] (viewRange 5 ratingRange) | 222 | , furbySelect [ onInput (ChangeRatingUpper << inp), style "appearance" "none" ] (viewRange 5 ratingRange) |
214 | ] | 223 | ] |
215 | ] | 224 | ] |
216 | 225 | ||
@@ -234,8 +243,25 @@ view model = | |||
234 | div [] [ text <| viewStatus Loading ] | 243 | div [] [ text <| viewStatus Loading ] |
235 | 244 | ||
236 | _ -> | 245 | _ -> |
237 | div [] | 246 | div |
238 | [ div [] [ viewFilters model ] | 247 | [ css [ padding (px 40) ] ] |
239 | , ul [] | 248 | [ div |
240 | (filterProducts model |> List.map viewProduct) | 249 | [ css |
250 | [ float left | ||
251 | , Css.width (pct 20) | ||
252 | ] | ||
253 | ] | ||
254 | [ viewFilters model ] | ||
255 | , div | ||
256 | [ css | ||
257 | [ float left | ||
258 | , Css.width (pct 80) | ||
259 | ] | ||
260 | ] | ||
261 | [ div [ css [ bigHeading ] ] [ text "Products" ] | ||
262 | , ul | ||
263 | [ css [ padding (px 0) ] | ||
264 | ] | ||
265 | (filterProducts model |> List.map viewProduct) | ||
266 | ] | ||
241 | ] | 267 | ] |
diff --git a/frontend/src/Checkout.elm b/frontend/src/Checkout.elm index c60da0d..4df20d8 100644 --- a/frontend/src/Checkout.elm +++ b/frontend/src/Checkout.elm | |||
@@ -2,9 +2,10 @@ module Checkout exposing (..) | |||
2 | 2 | ||
3 | import Browser | 3 | import Browser |
4 | import Browser.Navigation as Nav | 4 | import Browser.Navigation as Nav |
5 | import Html exposing (..) | 5 | import Html |
6 | import Html.Attributes exposing (..) | 6 | import Html.Styled exposing (..) |
7 | import Html.Events exposing (..) | 7 | import Html.Styled.Attributes exposing (..) |
8 | import Html.Styled.Events exposing (..) | ||
8 | import Http | 9 | import Http |
9 | import Json.Decode as D | 10 | import Json.Decode as D |
10 | import Json.Encode as Encode | 11 | import Json.Encode as Encode |
diff --git a/frontend/src/Icons.elm b/frontend/src/Icons.elm new file mode 100644 index 0000000..d3b862f --- /dev/null +++ b/frontend/src/Icons.elm | |||
@@ -0,0 +1,15 @@ | |||
1 | module Icons exposing (..) | ||
2 | |||
3 | import FeatherIcons exposing (toHtml) | ||
4 | import Html | ||
5 | import Html.Styled exposing (..) | ||
6 | import Html.Styled.Attributes exposing (..) | ||
7 | import Html.Styled.Events exposing (..) | ||
8 | |||
9 | |||
10 | convert = | ||
11 | Html.Styled.fromUnstyled << toHtml [] | ||
12 | |||
13 | |||
14 | loginIcon = | ||
15 | convert FeatherIcons.logIn | ||
diff --git a/frontend/src/Login.elm b/frontend/src/Login.elm index dd168f0..87657bb 100644 --- a/frontend/src/Login.elm +++ b/frontend/src/Login.elm | |||
@@ -2,11 +2,15 @@ module Login exposing (..) | |||
2 | 2 | ||
3 | import Browser | 3 | import Browser |
4 | import Browser.Navigation as Nav | 4 | import Browser.Navigation as Nav |
5 | import Html exposing (..) | 5 | import Css exposing (..) |
6 | import Html.Attributes exposing (..) | 6 | import Html |
7 | import Html.Events exposing (..) | 7 | import Html.Styled exposing (..) |
8 | import Html.Styled.Attributes exposing (..) | ||
9 | import Html.Styled.Events exposing (..) | ||
8 | import Http | 10 | import Http |
11 | import Icons exposing (..) | ||
9 | import Json.Encode as Encode | 12 | import Json.Encode as Encode |
13 | import Styles exposing (..) | ||
10 | import Url | 14 | import Url |
11 | import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string) | 15 | import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string) |
12 | 16 | ||
@@ -91,7 +95,7 @@ viewStatus : LoginStatus -> String | |||
91 | viewStatus ls = | 95 | viewStatus ls = |
92 | case ls of | 96 | case ls of |
93 | NotLoggedIn -> | 97 | NotLoggedIn -> |
94 | "Not Logged In" | 98 | "" |
95 | 99 | ||
96 | InvalidLogin -> | 100 | InvalidLogin -> |
97 | "Invalid Login" | 101 | "Invalid Login" |
@@ -105,15 +109,30 @@ viewStatus ls = | |||
105 | 109 | ||
106 | viewInput : String -> String -> String -> (String -> msg) -> Html msg | 110 | viewInput : String -> String -> String -> (String -> msg) -> Html msg |
107 | viewInput t p v toMsg = | 111 | viewInput t p v toMsg = |
108 | input [ type_ t, placeholder p, value v, onInput toMsg ] [] | 112 | loginInputField [ type_ t, placeholder p, value v, onInput toMsg ] [] |
113 | |||
114 | |||
115 | fieldPadding = | ||
116 | css | ||
117 | [ paddingTop (px 10) | ||
118 | , paddingBottom (px 10) | ||
119 | ] | ||
109 | 120 | ||
110 | 121 | ||
111 | view : Model -> Html Msg | 122 | view : Model -> Html Msg |
112 | view model = | 123 | view model = |
113 | div [] | 124 | div |
114 | [ div [] [ viewInput "text" "Enter name here" model.username UserEntered ] | 125 | [ css |
115 | , div [] [ viewInput "password" "Password" model.password PassEntered ] | 126 | [ margin auto |
116 | , div [] [ button [ onClick LoginPressed ] [ text "Login" ] ] | 127 | , marginTop (pct 10) |
117 | , div [] [ text (viewStatus model.loginStatus) ] | 128 | , padding (px 20) |
118 | , div [] [ text "Don't have an account? ", a [ href "/signup" ] [ text "Register now!" ] ] | 129 | , Css.width (pct 30) |
130 | ] | ||
131 | ] | ||
132 | [ div [ fieldPadding, css [ bigHeading ] ] [ text "Login" ] | ||
133 | , div [ fieldPadding ] [ viewInput "text" "Enter name here" model.username UserEntered ] | ||
134 | , div [ fieldPadding ] [ viewInput "password" "Password" model.password PassEntered ] | ||
135 | , div [ css [ textAlign center ], fieldPadding ] [ furbyButton [ onClick LoginPressed ] [ text "Login" ] ] | ||
136 | , div [ css [ textAlign center ] ] [ text (viewStatus model.loginStatus) ] | ||
137 | , div [ fieldPadding ] [ text "Don't have an account? ", a [ href "/signup" ] [ text "Register now!" ] ] | ||
119 | ] | 138 | ] |
diff --git a/frontend/src/Main.elm b/frontend/src/Main.elm index f1883a1..ea80921 100644 --- a/frontend/src/Main.elm +++ b/frontend/src/Main.elm | |||
@@ -5,14 +5,17 @@ import Browser.Navigation as Nav | |||
5 | import Cart | 5 | import Cart |
6 | import Catalog | 6 | import Catalog |
7 | import Checkout | 7 | import Checkout |
8 | import Html exposing (..) | 8 | import Css exposing (..) |
9 | import Html.Attributes exposing (..) | 9 | import Html |
10 | import Html.Events exposing (..) | 10 | import Html.Styled exposing (..) |
11 | import Html.Styled.Attributes exposing (..) | ||
12 | import Html.Styled.Events exposing (..) | ||
11 | import Http | 13 | import Http |
12 | import Json.Encode as Encode | 14 | import Json.Encode as Encode |
13 | import Login | 15 | import Login |
14 | import Product | 16 | import Product |
15 | import Signup | 17 | import Signup |
18 | import Styles exposing (..) | ||
16 | import Url | 19 | import Url |
17 | import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string) | 20 | import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string) |
18 | 21 | ||
@@ -276,56 +279,93 @@ subscriptions _ = | |||
276 | view : Model -> Browser.Document Msg | 279 | view : Model -> Browser.Document Msg |
277 | view model = | 280 | view model = |
278 | case model.location of | 281 | case model.location of |
282 | HomePage -> | ||
283 | { title = "Login" | ||
284 | , body = | ||
285 | -- model.loginModel | ||
286 | -- |> Login.view | ||
287 | -- |> Html.Styled.map LoginMessage | ||
288 | -- |> toUnstyled | ||
289 | -- |> List.singleton | ||
290 | div [] | ||
291 | [ ul [] | ||
292 | (List.map | ||
293 | (\l -> | ||
294 | li [] | ||
295 | [ a [ href l ] [ text l ] ] | ||
296 | ) | ||
297 | [ "/login", "/catalog", "/cart" ] | ||
298 | ) | ||
299 | ] | ||
300 | |> toUnstyled | ||
301 | |> List.singleton | ||
302 | } | ||
303 | |||
279 | LoginPage -> | 304 | LoginPage -> |
280 | { title = "Login" | 305 | { title = "Login" |
281 | , body = [ Html.map LoginMessage (Login.view model.loginModel) ] | 306 | , body = |
307 | model.loginModel | ||
308 | |> Login.view | ||
309 | |> Html.Styled.map LoginMessage | ||
310 | |> toUnstyled | ||
311 | |> List.singleton | ||
282 | } | 312 | } |
283 | 313 | ||
284 | SignupPage -> | 314 | SignupPage -> |
285 | { title = "Signup" | 315 | { title = "Signup" |
286 | , body = [ Html.map SignupMessage (Signup.view model.signupModel) ] | ||
287 | } | ||
288 | |||
289 | HomePage -> | ||
290 | { title = "URL Interceptor" | ||
291 | , body = | 316 | , body = |
292 | [ text "The current URL is: " | 317 | model.signupModel |
293 | , b [] [ text (Url.toString model.url) ] | 318 | |> Signup.view |
294 | , ul [] | 319 | |> Html.Styled.map SignupMessage |
295 | [ viewLink "/login" | 320 | |> toUnstyled |
296 | , viewLink "/catalog" | 321 | |> List.singleton |
297 | , viewLink "/cart" | ||
298 | , viewLink "/signup" | ||
299 | ] | ||
300 | ] | ||
301 | } | 322 | } |
302 | 323 | ||
303 | NotFoundPage -> | 324 | NotFoundPage -> |
304 | { title = "404 - Not Found" | 325 | { title = "404 - Not Found" |
305 | , body = | 326 | , body = |
306 | [ text "404 - Not Found" | 327 | div [] |
307 | , a [ href "/" ] [ text "Go back >" ] | 328 | [ text "404 - Not Found" |
308 | ] | 329 | , a [ href "/" ] [ text "Go back >" ] |
330 | ] | ||
331 | |> toUnstyled | ||
332 | |> List.singleton | ||
309 | } | 333 | } |
310 | 334 | ||
311 | CatalogPage -> | 335 | CatalogPage -> |
312 | { title = "Catalog" | 336 | { title = "Catalog" |
313 | , body = pageWrap model (Html.map CatalogMessage (Catalog.view model.catalogModel)) | 337 | , body = |
338 | model.catalogModel | ||
339 | |> Catalog.view | ||
340 | |> Html.Styled.map CatalogMessage | ||
341 | |> pageWrap model | ||
314 | } | 342 | } |
315 | 343 | ||
316 | CartPage -> | 344 | CartPage -> |
317 | { title = "Cart" | 345 | { title = "Cart" |
318 | , body = pageWrap model (Html.map CartMessage (Cart.view model.cartModel)) | 346 | , body = |
347 | model.cartModel | ||
348 | |> Cart.view | ||
349 | |> Html.Styled.map CartMessage | ||
350 | |> pageWrap model | ||
319 | } | 351 | } |
320 | 352 | ||
321 | CheckoutPage -> | 353 | CheckoutPage -> |
322 | { title = "Checkout" | 354 | { title = "Checkout" |
323 | , body = pageWrap model (Html.map CheckoutMessage (Checkout.view model.checkoutModel)) | 355 | , body = |
356 | model.checkoutModel | ||
357 | |> Checkout.view | ||
358 | |> Html.Styled.map CheckoutMessage | ||
359 | |> pageWrap model | ||
324 | } | 360 | } |
325 | 361 | ||
326 | ProductPage item -> | 362 | ProductPage item -> |
327 | { title = "Product " ++ String.fromInt item | 363 | { title = "Product " ++ String.fromInt item |
328 | , body = pageWrap model (Html.map ProductMessage (Product.view model.productModel)) | 364 | , body = |
365 | model.productModel | ||
366 | |> Product.view | ||
367 | |> Html.Styled.map ProductMessage | ||
368 | |> pageWrap model | ||
329 | } | 369 | } |
330 | 370 | ||
331 | 371 | ||
@@ -333,36 +373,49 @@ viewHeader : Model -> Html Msg | |||
333 | viewHeader model = | 373 | viewHeader model = |
334 | let | 374 | let |
335 | links = | 375 | links = |
336 | [ ( "Home", "/" ) | 376 | [ ( "Catalog", "/catalog" ) |
337 | , ( "Catalog", "/catalog" ) | ||
338 | , ( "Cart", "/cart" ) | 377 | , ( "Cart", "/cart" ) |
339 | ] | 378 | ] |
340 | in | 379 | in |
341 | div [] | 380 | div |
381 | [ css | ||
382 | [ padding (px 40) | ||
383 | , paddingTop (px 3) | ||
384 | , paddingBottom (px 3) | ||
385 | , textAlign left | ||
386 | , backgroundColor theme.secondary | ||
387 | ] | ||
388 | ] | ||
342 | [ List.map | 389 | [ List.map |
343 | (\( name, loc ) -> | 390 | (\( name, loc ) -> |
344 | li [] | 391 | li [ css [ display inline ] ] |
345 | [ a [ href loc ] [ text name ] | 392 | [ headerLink [ href loc ] [ text name ] |
346 | ] | 393 | ] |
347 | ) | 394 | ) |
348 | links | 395 | links |
349 | ++ [ if model.loginModel.loginStatus /= Login.LoggedIn then | 396 | ++ [ if model.loginModel.loginStatus /= Login.LoggedIn then |
350 | li [] [ a [ href "/login" ] [ text "Login" ] ] | 397 | li [ css [ display inline ] ] [ headerLink [ href "/login" ] [ text "Login" ] ] |
351 | 398 | ||
352 | else | 399 | else |
353 | button [ onClick LogoutPressed ] [ text "Logout" ] | 400 | furbyButton [ onClick LogoutPressed ] [ text "Logout" ] |
354 | ] | 401 | ] |
355 | |> ul [] | 402 | |> ul |
403 | [ css | ||
404 | [ listStyle Css.none | ||
405 | , padding (px 0) | ||
406 | ] | ||
407 | ] | ||
356 | ] | 408 | ] |
357 | 409 | ||
358 | 410 | ||
359 | pageWrap : Model -> Html Msg -> List (Html Msg) | 411 | pageWrap : Model -> Html Msg -> List (Html.Html Msg) |
360 | pageWrap model page = | 412 | pageWrap model page = |
361 | [ div [] | 413 | div [] |
362 | [ viewHeader model | 414 | [ viewHeader model |
363 | , page | 415 | , page |
364 | ] | 416 | ] |
365 | ] | 417 | |> toUnstyled |
418 | |> List.singleton | ||
366 | 419 | ||
367 | 420 | ||
368 | viewLink : String -> Html msg | 421 | viewLink : String -> Html msg |
diff --git a/frontend/src/Product.elm b/frontend/src/Product.elm index 0ea0ce1..b97a847 100644 --- a/frontend/src/Product.elm +++ b/frontend/src/Product.elm | |||
@@ -2,14 +2,16 @@ module Product exposing (..) | |||
2 | 2 | ||
3 | import Browser | 3 | import Browser |
4 | import Browser.Navigation as Nav | 4 | import Browser.Navigation as Nav |
5 | import Html exposing (..) | 5 | import Html |
6 | import Html.Attributes exposing (..) | 6 | import Html.Styled exposing (..) |
7 | import Html.Events exposing (..) | 7 | import Html.Styled.Attributes exposing (..) |
8 | import Html.Styled.Events exposing (..) | ||
8 | import Http | 9 | import Http |
9 | import Json.Decode as D | 10 | import Json.Decode as D |
10 | import Json.Encode as Encode | 11 | import Json.Encode as Encode |
11 | import Url | 12 | import Url |
12 | import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string) | 13 | import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string) |
14 | import Utils exposing (..) | ||
13 | 15 | ||
14 | 16 | ||
15 | type SubmitStatus | 17 | type SubmitStatus |
@@ -25,11 +27,13 @@ type alias Product = | |||
25 | , kind : Maybe String | 27 | , kind : Maybe String |
26 | , price : Float | 28 | , price : Float |
27 | , description : Maybe String | 29 | , description : Maybe String |
30 | , src : String | ||
31 | , iosSrc : String | ||
28 | } | 32 | } |
29 | 33 | ||
30 | 34 | ||
31 | emptyProduct = | 35 | emptyProduct = |
32 | Product -1 "" Nothing 0 Nothing | 36 | Product -1 "" Nothing 0 Nothing "" "" |
33 | 37 | ||
34 | 38 | ||
35 | type alias Rating = | 39 | type alias Rating = |
@@ -140,12 +144,14 @@ update msg model = | |||
140 | 144 | ||
141 | decodeProduct : D.Decoder Product | 145 | decodeProduct : D.Decoder Product |
142 | decodeProduct = | 146 | decodeProduct = |
143 | D.map5 Product | 147 | D.map7 Product |
144 | (D.field "id" D.int) | 148 | (D.field "id" D.int) |
145 | (D.field "name" D.string) | 149 | (D.field "name" D.string) |
146 | (D.field "kind" (D.nullable D.string)) | 150 | (D.field "kind" (D.nullable D.string)) |
147 | (D.field "price" D.float) | 151 | (D.field "price" D.float) |
148 | (D.field "description" (D.nullable D.string)) | 152 | (D.field "description" (D.nullable D.string)) |
153 | (D.field "src" D.string) | ||
154 | (D.field "ios_src" D.string) | ||
149 | 155 | ||
150 | 156 | ||
151 | decodeRating : D.Decoder Rating | 157 | decodeRating : D.Decoder Rating |
@@ -246,10 +252,21 @@ viewStatus s = | |||
246 | viewProduct : Product -> Html Msg | 252 | viewProduct : Product -> Html Msg |
247 | viewProduct p = | 253 | viewProduct p = |
248 | div [] | 254 | div [] |
249 | [ text p.name | 255 | [ div [] [ text p.name ] |
250 | , text <| Maybe.withDefault "" p.kind | 256 | , div [] [ text <| Maybe.withDefault "" p.kind ] |
251 | , text <| Maybe.withDefault "" p.description | 257 | , div [] [ text <| Maybe.withDefault "" p.description ] |
252 | , text <| String.fromFloat p.price | 258 | , div [] [ text <| String.fromFloat p.price ] |
259 | , div [] | ||
260 | [ modelViewer | ||
261 | [ cameraControls | ||
262 | , autoRotate | ||
263 | , arSrc p.src | ||
264 | , arIosSrc p.iosSrc | ||
265 | , loading "eager" | ||
266 | , arModes "webxr" | ||
267 | ] | ||
268 | [] | ||
269 | ] | ||
253 | ] | 270 | ] |
254 | 271 | ||
255 | 272 | ||
diff --git a/frontend/src/Signup.elm b/frontend/src/Signup.elm index 30794e7..028af9c 100644 --- a/frontend/src/Signup.elm +++ b/frontend/src/Signup.elm | |||
@@ -2,11 +2,14 @@ module Signup exposing (..) | |||
2 | 2 | ||
3 | import Browser | 3 | import Browser |
4 | import Browser.Navigation as Nav | 4 | import Browser.Navigation as Nav |
5 | import Html exposing (..) | 5 | import Css exposing (..) |
6 | import Html.Attributes exposing (..) | 6 | import Html |
7 | import Html.Events exposing (..) | 7 | import Html.Styled exposing (..) |
8 | import Html.Styled.Attributes exposing (..) | ||
9 | import Html.Styled.Events exposing (..) | ||
8 | import Http | 10 | import Http |
9 | import Json.Encode as Encode | 11 | import Json.Encode as Encode |
12 | import Styles exposing (..) | ||
10 | import Url | 13 | import Url |
11 | import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string) | 14 | import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string) |
12 | 15 | ||
@@ -178,19 +181,41 @@ viewStatus s = | |||
178 | 181 | ||
179 | viewInput : String -> String -> String -> (String -> msg) -> Html msg | 182 | viewInput : String -> String -> String -> (String -> msg) -> Html msg |
180 | viewInput t p v toMsg = | 183 | viewInput t p v toMsg = |
181 | input [ type_ t, placeholder p, value v, onInput toMsg ] [] | 184 | loginInputField [ type_ t, placeholder p, value v, onInput toMsg ] [] |
185 | |||
186 | |||
187 | fieldPadding = | ||
188 | css | ||
189 | [ paddingTop (px 10) | ||
190 | , paddingBottom (px 10) | ||
191 | ] | ||
182 | 192 | ||
183 | 193 | ||
184 | view : Model -> Html Msg | 194 | view : Model -> Html Msg |
185 | view model = | 195 | view model = |
186 | div [] | 196 | div |
187 | [ div [] [ viewInput "text" "Enter Username" model.username UserEntered ] | 197 | [ css |
188 | , div [] [ viewInput "password" "Password" model.password PassEntered ] | 198 | [ margin auto |
189 | , div [] [ viewInput "text" "Email" model.emailId EmailEntered ] | 199 | , marginTop (pct 10) |
190 | , div [] [ viewInput "text" "Enter your Phone number" model.phoneNumber PhoneEntered ] | 200 | , padding (px 20) |
191 | , div [] [ viewInput "text" "Enter Shipping address" (Maybe.withDefault "" model.address) AddressEntered ] | 201 | , Css.width (pct 30) |
192 | , div [] [ button [ onClick CreatePressed ] [ text "Create" ] ] | 202 | ] |
193 | , div [] | 203 | ] |
204 | [ div [ fieldPadding, css [ bigHeading ] ] [ text "Signup" ] | ||
205 | , div [ fieldPadding ] [ viewInput "text" "Username" model.username UserEntered ] | ||
206 | , div [ fieldPadding ] [ viewInput "password" "Password" model.password PassEntered ] | ||
207 | , div [ fieldPadding ] [ viewInput "text" "Email" model.emailId EmailEntered ] | ||
208 | , div [ fieldPadding ] [ viewInput "text" "Phone Number" model.phoneNumber PhoneEntered ] | ||
209 | , div [ fieldPadding ] [ viewInput "text" "Shipping Address" (Maybe.withDefault "" model.address) AddressEntered ] | ||
210 | , div | ||
211 | [ fieldPadding | ||
212 | , css [ textAlign center ] | ||
213 | ] | ||
214 | [ furbyButton | ||
215 | [ onClick CreatePressed ] | ||
216 | [ text "Create Account" ] | ||
217 | ] | ||
218 | , div [ fieldPadding ] | ||
194 | [ text "Already have a account? " | 219 | [ text "Already have a account? " |
195 | , a [ href "/login" ] [ text "Login >" ] | 220 | , a [ href "/login" ] [ text "Login >" ] |
196 | ] | 221 | ] |
diff --git a/frontend/src/Styles.elm b/frontend/src/Styles.elm new file mode 100644 index 0000000..36f2a81 --- /dev/null +++ b/frontend/src/Styles.elm | |||
@@ -0,0 +1,104 @@ | |||
1 | module Styles exposing (..) | ||
2 | |||
3 | import Css exposing (..) | ||
4 | import Html | ||
5 | import Html.Styled exposing (..) | ||
6 | import Html.Styled.Attributes exposing (..) | ||
7 | import Html.Styled.Events exposing (..) | ||
8 | |||
9 | |||
10 | type alias Theme = | ||
11 | { primary : Color | ||
12 | , secondary : Color | ||
13 | , bad : Color | ||
14 | , fg : Color | ||
15 | , bg : Color | ||
16 | , fgLight : Color | ||
17 | , bgLight : Color | ||
18 | } | ||
19 | |||
20 | |||
21 | theme : Theme | ||
22 | theme = | ||
23 | Theme | ||
24 | (hex "fedbd0") | ||
25 | -- primary | ||
26 | (hex "feeae6") | ||
27 | -- secondary | ||
28 | (hex "ff0000") | ||
29 | -- bad | ||
30 | (hex "442c2e") | ||
31 | -- fg | ||
32 | (hex "ffffff") | ||
33 | -- bg | ||
34 | (hex "442c2e") | ||
35 | -- fgLight | ||
36 | (hex "feeae6") | ||
37 | |||
38 | |||
39 | |||
40 | -- bgLight | ||
41 | |||
42 | |||
43 | headerLink : List (Attribute msg) -> List (Html msg) -> Html msg | ||
44 | headerLink = | ||
45 | styled a | ||
46 | [ color theme.fgLight | ||
47 | , padding (px 12) | ||
48 | , textDecoration Css.none | ||
49 | , hover | ||
50 | [ backgroundColor theme.secondary | ||
51 | , textDecoration underline | ||
52 | ] | ||
53 | ] | ||
54 | |||
55 | |||
56 | furbyButton : List (Attribute msg) -> List (Html msg) -> Html msg | ||
57 | furbyButton = | ||
58 | styled button | ||
59 | [ margin (px 12) | ||
60 | , color theme.fg | ||
61 | , Css.height (px 40) | ||
62 | , border (px 0) | ||
63 | , padding2 (px 6) (px 12) | ||
64 | , backgroundColor theme.primary | ||
65 | , hover | ||
66 | [ backgroundColor theme.secondary | ||
67 | , color theme.fg | ||
68 | , margin (px 12) | ||
69 | ] | ||
70 | ] | ||
71 | |||
72 | |||
73 | furbySelect : List (Attribute msg) -> List (Html msg) -> Html msg | ||
74 | furbySelect = | ||
75 | styled select | ||
76 | [ margin (px 6) | ||
77 | , color theme.fg | ||
78 | , border (px 0) | ||
79 | , borderBottom3 (px 2) solid theme.bgLight | ||
80 | , textAlign right | ||
81 | , padding2 (px 3) (px 3) | ||
82 | , backgroundColor theme.bg | ||
83 | , hover | ||
84 | [ borderBottom3 (px 2) solid theme.fg | ||
85 | ] | ||
86 | ] | ||
87 | |||
88 | |||
89 | loginInputField : List (Attribute msg) -> List (Html msg) -> Html msg | ||
90 | loginInputField = | ||
91 | styled input | ||
92 | [ Css.width (pct 100) | ||
93 | , color theme.fg | ||
94 | , border (px 0) | ||
95 | , borderBottom3 (px 1) solid theme.bgLight | ||
96 | , focus | ||
97 | [ borderBottom3 (px 2) solid theme.fg | ||
98 | ] | ||
99 | ] | ||
100 | |||
101 | |||
102 | bigHeading : Style | ||
103 | bigHeading = | ||
104 | fontSize (px 24) | ||
diff --git a/frontend/src/Utils.elm b/frontend/src/Utils.elm index 825e4b7..b6c4bd5 100644 --- a/frontend/src/Utils.elm +++ b/frontend/src/Utils.elm | |||
@@ -1,5 +1,10 @@ | |||
1 | module Utils exposing (..) | 1 | module Utils exposing (..) |
2 | 2 | ||
3 | import Html | ||
4 | import Html.Styled exposing (..) | ||
5 | import Html.Styled.Attributes exposing (..) | ||
6 | import Html.Styled.Events exposing (..) | ||
7 | |||
3 | 8 | ||
4 | between : ( Float, Float ) -> Float -> Bool | 9 | between : ( Float, Float ) -> Float -> Bool |
5 | between ( l, u ) v = | 10 | between ( l, u ) v = |
@@ -13,3 +18,43 @@ range start stop step = | |||
13 | 18 | ||
14 | else | 19 | else |
15 | start :: range (start + step) stop step | 20 | start :: range (start + step) stop step |
21 | |||
22 | |||
23 | modelViewer : List (Attribute msg) -> List (Html msg) -> Html msg | ||
24 | modelViewer attributes children = | ||
25 | node "model-viewer" attributes children | ||
26 | |||
27 | |||
28 | cameraControls : Attribute msg | ||
29 | cameraControls = | ||
30 | attribute "camera-controls" "" | ||
31 | |||
32 | |||
33 | autoRotate : Attribute msg | ||
34 | autoRotate = | ||
35 | attribute "auto-rotate" "" | ||
36 | |||
37 | |||
38 | ar : Attribute msg | ||
39 | ar = | ||
40 | attribute "ar" "" | ||
41 | |||
42 | |||
43 | arSrc : String -> Attribute msg | ||
44 | arSrc src = | ||
45 | attribute "src" src | ||
46 | |||
47 | |||
48 | arIosSrc : String -> Attribute msg | ||
49 | arIosSrc src = | ||
50 | attribute "ios-src" src | ||
51 | |||
52 | |||
53 | arModes : String -> Attribute msg | ||
54 | arModes mode = | ||
55 | attribute "ar-modes" mode | ||
56 | |||
57 | |||
58 | loading : String -> Attribute msg | ||
59 | loading mode = | ||
60 | attribute "loading" mode | ||