From b8a744f6e7e02f67551124063d3dd97faba5fb0b Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 26 Dec 2020 20:13:50 +0530 Subject: begin work on frontend --- frontend/src/Cart.elm | 7 +-- frontend/src/Catalog.elm | 62 ++++++++++++++++------- frontend/src/Checkout.elm | 7 +-- frontend/src/Icons.elm | 15 ++++++ frontend/src/Login.elm | 41 +++++++++++---- frontend/src/Main.elm | 125 +++++++++++++++++++++++++++++++++------------- frontend/src/Product.elm | 35 +++++++++---- frontend/src/Signup.elm | 49 +++++++++++++----- frontend/src/Styles.elm | 104 ++++++++++++++++++++++++++++++++++++++ frontend/src/Utils.elm | 45 +++++++++++++++++ 10 files changed, 398 insertions(+), 92 deletions(-) create mode 100644 frontend/src/Icons.elm create mode 100644 frontend/src/Styles.elm (limited to 'frontend/src') 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 (..) import Browser import Browser.Navigation as Nav -import Html exposing (..) -import Html.Attributes exposing (..) -import Html.Events exposing (..) +import Html +import Html.Styled exposing (..) +import Html.Styled.Attributes exposing (..) +import Html.Styled.Events exposing (..) import Http import Json.Decode as D 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 (..) import Browser import Browser.Navigation as Nav -import Html exposing (..) -import Html.Attributes exposing (..) -import Html.Events exposing (..) +import Css exposing (..) +import Html +import Html.Styled exposing (..) +import Html.Styled.Attributes exposing (..) +import Html.Styled.Events exposing (..) import Http import Json.Decode as D import Json.Encode as Encode +import Styles exposing (..) import Tuple exposing (..) -import Url -import Url.Parser as P exposing ((), Parser, int, oneOf, s, string) import Utils exposing (..) @@ -37,7 +38,7 @@ type alias Filters = defaultFilters : Filters defaultFilters = - Filters ( -1, 10000 ) ( 0, 5 ) + Filters ( -1, 100000 ) ( 0, 5 ) type alias Model = @@ -199,18 +200,26 @@ viewFilters model = inp = Maybe.withDefault 0 << String.toFloat in - div [] - [ div [] - [ text "Price" - , select [ onInput (ChangePriceLower << inp) ] (viewRange 0 priceRange) + div + [] + [ div + [ css + [ bigHeading + , paddingBottom (px 12) + ] + ] + [ text "Filters" ] + , div [] + [ div [] [ text "Price" ] + , furbySelect [ onInput (ChangePriceLower << inp), style "appearance" "none" ] (viewRange 0 priceRange) , text "to" - , select [ onInput (ChangePriceUpper << inp) ] (viewRange 50000 priceRange) + , furbySelect [ onInput (ChangePriceUpper << inp), style "appearance" "none" ] (viewRange 50000 priceRange) ] , div [] - [ text "Rating" - , select [ onInput (ChangeRatingLower << inp) ] (viewRange 1 ratingRange) + [ div [] [ text "Rating" ] + , furbySelect [ onInput (ChangeRatingLower << inp), style "appearance" "none" ] (viewRange 1 ratingRange) , text "to" - , select [ onInput (ChangeRatingUpper << inp) ] (viewRange 5 ratingRange) + , furbySelect [ onInput (ChangeRatingUpper << inp), style "appearance" "none" ] (viewRange 5 ratingRange) ] ] @@ -234,8 +243,25 @@ view model = div [] [ text <| viewStatus Loading ] _ -> - div [] - [ div [] [ viewFilters model ] - , ul [] - (filterProducts model |> List.map viewProduct) + div + [ css [ padding (px 40) ] ] + [ div + [ css + [ float left + , Css.width (pct 20) + ] + ] + [ viewFilters model ] + , div + [ css + [ float left + , Css.width (pct 80) + ] + ] + [ div [ css [ bigHeading ] ] [ text "Products" ] + , ul + [ css [ padding (px 0) ] + ] + (filterProducts model |> List.map viewProduct) + ] ] 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 (..) import Browser import Browser.Navigation as Nav -import Html exposing (..) -import Html.Attributes exposing (..) -import Html.Events exposing (..) +import Html +import Html.Styled exposing (..) +import Html.Styled.Attributes exposing (..) +import Html.Styled.Events exposing (..) import Http import Json.Decode as D 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 @@ +module Icons exposing (..) + +import FeatherIcons exposing (toHtml) +import Html +import Html.Styled exposing (..) +import Html.Styled.Attributes exposing (..) +import Html.Styled.Events exposing (..) + + +convert = + Html.Styled.fromUnstyled << toHtml [] + + +loginIcon = + 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 (..) import Browser import Browser.Navigation as Nav -import Html exposing (..) -import Html.Attributes exposing (..) -import Html.Events exposing (..) +import Css exposing (..) +import Html +import Html.Styled exposing (..) +import Html.Styled.Attributes exposing (..) +import Html.Styled.Events exposing (..) import Http +import Icons exposing (..) import Json.Encode as Encode +import Styles exposing (..) import Url import Url.Parser as P exposing ((), Parser, int, oneOf, s, string) @@ -91,7 +95,7 @@ viewStatus : LoginStatus -> String viewStatus ls = case ls of NotLoggedIn -> - "Not Logged In" + "" InvalidLogin -> "Invalid Login" @@ -105,15 +109,30 @@ viewStatus ls = viewInput : String -> String -> String -> (String -> msg) -> Html msg viewInput t p v toMsg = - input [ type_ t, placeholder p, value v, onInput toMsg ] [] + loginInputField [ type_ t, placeholder p, value v, onInput toMsg ] [] + + +fieldPadding = + css + [ paddingTop (px 10) + , paddingBottom (px 10) + ] view : Model -> Html Msg view model = - div [] - [ div [] [ viewInput "text" "Enter name here" model.username UserEntered ] - , div [] [ viewInput "password" "Password" model.password PassEntered ] - , div [] [ button [ onClick LoginPressed ] [ text "Login" ] ] - , div [] [ text (viewStatus model.loginStatus) ] - , div [] [ text "Don't have an account? ", a [ href "/signup" ] [ text "Register now!" ] ] + div + [ css + [ margin auto + , marginTop (pct 10) + , padding (px 20) + , Css.width (pct 30) + ] + ] + [ div [ fieldPadding, css [ bigHeading ] ] [ text "Login" ] + , div [ fieldPadding ] [ viewInput "text" "Enter name here" model.username UserEntered ] + , div [ fieldPadding ] [ viewInput "password" "Password" model.password PassEntered ] + , div [ css [ textAlign center ], fieldPadding ] [ furbyButton [ onClick LoginPressed ] [ text "Login" ] ] + , div [ css [ textAlign center ] ] [ text (viewStatus model.loginStatus) ] + , div [ fieldPadding ] [ text "Don't have an account? ", a [ href "/signup" ] [ text "Register now!" ] ] ] 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 import Cart import Catalog import Checkout -import Html exposing (..) -import Html.Attributes exposing (..) -import Html.Events exposing (..) +import Css exposing (..) +import Html +import Html.Styled exposing (..) +import Html.Styled.Attributes exposing (..) +import Html.Styled.Events exposing (..) import Http import Json.Encode as Encode import Login import Product import Signup +import Styles exposing (..) import Url import Url.Parser as P exposing ((), Parser, int, oneOf, s, string) @@ -276,56 +279,93 @@ subscriptions _ = view : Model -> Browser.Document Msg view model = case model.location of + HomePage -> + { title = "Login" + , body = + -- model.loginModel + -- |> Login.view + -- |> Html.Styled.map LoginMessage + -- |> toUnstyled + -- |> List.singleton + div [] + [ ul [] + (List.map + (\l -> + li [] + [ a [ href l ] [ text l ] ] + ) + [ "/login", "/catalog", "/cart" ] + ) + ] + |> toUnstyled + |> List.singleton + } + LoginPage -> { title = "Login" - , body = [ Html.map LoginMessage (Login.view model.loginModel) ] + , body = + model.loginModel + |> Login.view + |> Html.Styled.map LoginMessage + |> toUnstyled + |> List.singleton } SignupPage -> { title = "Signup" - , body = [ Html.map SignupMessage (Signup.view model.signupModel) ] - } - - HomePage -> - { title = "URL Interceptor" , body = - [ text "The current URL is: " - , b [] [ text (Url.toString model.url) ] - , ul [] - [ viewLink "/login" - , viewLink "/catalog" - , viewLink "/cart" - , viewLink "/signup" - ] - ] + model.signupModel + |> Signup.view + |> Html.Styled.map SignupMessage + |> toUnstyled + |> List.singleton } NotFoundPage -> { title = "404 - Not Found" , body = - [ text "404 - Not Found" - , a [ href "/" ] [ text "Go back >" ] - ] + div [] + [ text "404 - Not Found" + , a [ href "/" ] [ text "Go back >" ] + ] + |> toUnstyled + |> List.singleton } CatalogPage -> { title = "Catalog" - , body = pageWrap model (Html.map CatalogMessage (Catalog.view model.catalogModel)) + , body = + model.catalogModel + |> Catalog.view + |> Html.Styled.map CatalogMessage + |> pageWrap model } CartPage -> { title = "Cart" - , body = pageWrap model (Html.map CartMessage (Cart.view model.cartModel)) + , body = + model.cartModel + |> Cart.view + |> Html.Styled.map CartMessage + |> pageWrap model } CheckoutPage -> { title = "Checkout" - , body = pageWrap model (Html.map CheckoutMessage (Checkout.view model.checkoutModel)) + , body = + model.checkoutModel + |> Checkout.view + |> Html.Styled.map CheckoutMessage + |> pageWrap model } ProductPage item -> { title = "Product " ++ String.fromInt item - , body = pageWrap model (Html.map ProductMessage (Product.view model.productModel)) + , body = + model.productModel + |> Product.view + |> Html.Styled.map ProductMessage + |> pageWrap model } @@ -333,36 +373,49 @@ viewHeader : Model -> Html Msg viewHeader model = let links = - [ ( "Home", "/" ) - , ( "Catalog", "/catalog" ) + [ ( "Catalog", "/catalog" ) , ( "Cart", "/cart" ) ] in - div [] + div + [ css + [ padding (px 40) + , paddingTop (px 3) + , paddingBottom (px 3) + , textAlign left + , backgroundColor theme.secondary + ] + ] [ List.map (\( name, loc ) -> - li [] - [ a [ href loc ] [ text name ] + li [ css [ display inline ] ] + [ headerLink [ href loc ] [ text name ] ] ) links ++ [ if model.loginModel.loginStatus /= Login.LoggedIn then - li [] [ a [ href "/login" ] [ text "Login" ] ] + li [ css [ display inline ] ] [ headerLink [ href "/login" ] [ text "Login" ] ] else - button [ onClick LogoutPressed ] [ text "Logout" ] + furbyButton [ onClick LogoutPressed ] [ text "Logout" ] ] - |> ul [] + |> ul + [ css + [ listStyle Css.none + , padding (px 0) + ] + ] ] -pageWrap : Model -> Html Msg -> List (Html Msg) +pageWrap : Model -> Html Msg -> List (Html.Html Msg) pageWrap model page = - [ div [] + div [] [ viewHeader model , page ] - ] + |> toUnstyled + |> List.singleton 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 (..) import Browser import Browser.Navigation as Nav -import Html exposing (..) -import Html.Attributes exposing (..) -import Html.Events exposing (..) +import Html +import Html.Styled exposing (..) +import Html.Styled.Attributes exposing (..) +import Html.Styled.Events exposing (..) import Http import Json.Decode as D import Json.Encode as Encode import Url import Url.Parser as P exposing ((), Parser, int, oneOf, s, string) +import Utils exposing (..) type SubmitStatus @@ -25,11 +27,13 @@ type alias Product = , kind : Maybe String , price : Float , description : Maybe String + , src : String + , iosSrc : String } emptyProduct = - Product -1 "" Nothing 0 Nothing + Product -1 "" Nothing 0 Nothing "" "" type alias Rating = @@ -140,12 +144,14 @@ update msg model = decodeProduct : D.Decoder Product decodeProduct = - D.map5 Product + D.map7 Product (D.field "id" D.int) (D.field "name" D.string) (D.field "kind" (D.nullable D.string)) (D.field "price" D.float) (D.field "description" (D.nullable D.string)) + (D.field "src" D.string) + (D.field "ios_src" D.string) decodeRating : D.Decoder Rating @@ -246,10 +252,21 @@ viewStatus s = viewProduct : Product -> Html Msg viewProduct p = div [] - [ text p.name - , text <| Maybe.withDefault "" p.kind - , text <| Maybe.withDefault "" p.description - , text <| String.fromFloat p.price + [ div [] [ text p.name ] + , div [] [ text <| Maybe.withDefault "" p.kind ] + , div [] [ text <| Maybe.withDefault "" p.description ] + , div [] [ text <| String.fromFloat p.price ] + , div [] + [ modelViewer + [ cameraControls + , autoRotate + , arSrc p.src + , arIosSrc p.iosSrc + , loading "eager" + , arModes "webxr" + ] + [] + ] ] 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 (..) import Browser import Browser.Navigation as Nav -import Html exposing (..) -import Html.Attributes exposing (..) -import Html.Events exposing (..) +import Css exposing (..) +import Html +import Html.Styled exposing (..) +import Html.Styled.Attributes exposing (..) +import Html.Styled.Events exposing (..) import Http import Json.Encode as Encode +import Styles exposing (..) import Url import Url.Parser as P exposing ((), Parser, int, oneOf, s, string) @@ -178,19 +181,41 @@ viewStatus s = viewInput : String -> String -> String -> (String -> msg) -> Html msg viewInput t p v toMsg = - input [ type_ t, placeholder p, value v, onInput toMsg ] [] + loginInputField [ type_ t, placeholder p, value v, onInput toMsg ] [] + + +fieldPadding = + css + [ paddingTop (px 10) + , paddingBottom (px 10) + ] view : Model -> Html Msg view model = - div [] - [ div [] [ viewInput "text" "Enter Username" model.username UserEntered ] - , div [] [ viewInput "password" "Password" model.password PassEntered ] - , div [] [ viewInput "text" "Email" model.emailId EmailEntered ] - , div [] [ viewInput "text" "Enter your Phone number" model.phoneNumber PhoneEntered ] - , div [] [ viewInput "text" "Enter Shipping address" (Maybe.withDefault "" model.address) AddressEntered ] - , div [] [ button [ onClick CreatePressed ] [ text "Create" ] ] - , div [] + div + [ css + [ margin auto + , marginTop (pct 10) + , padding (px 20) + , Css.width (pct 30) + ] + ] + [ div [ fieldPadding, css [ bigHeading ] ] [ text "Signup" ] + , div [ fieldPadding ] [ viewInput "text" "Username" model.username UserEntered ] + , div [ fieldPadding ] [ viewInput "password" "Password" model.password PassEntered ] + , div [ fieldPadding ] [ viewInput "text" "Email" model.emailId EmailEntered ] + , div [ fieldPadding ] [ viewInput "text" "Phone Number" model.phoneNumber PhoneEntered ] + , div [ fieldPadding ] [ viewInput "text" "Shipping Address" (Maybe.withDefault "" model.address) AddressEntered ] + , div + [ fieldPadding + , css [ textAlign center ] + ] + [ furbyButton + [ onClick CreatePressed ] + [ text "Create Account" ] + ] + , div [ fieldPadding ] [ text "Already have a account? " , a [ href "/login" ] [ text "Login >" ] ] 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 @@ +module Styles exposing (..) + +import Css exposing (..) +import Html +import Html.Styled exposing (..) +import Html.Styled.Attributes exposing (..) +import Html.Styled.Events exposing (..) + + +type alias Theme = + { primary : Color + , secondary : Color + , bad : Color + , fg : Color + , bg : Color + , fgLight : Color + , bgLight : Color + } + + +theme : Theme +theme = + Theme + (hex "fedbd0") + -- primary + (hex "feeae6") + -- secondary + (hex "ff0000") + -- bad + (hex "442c2e") + -- fg + (hex "ffffff") + -- bg + (hex "442c2e") + -- fgLight + (hex "feeae6") + + + +-- bgLight + + +headerLink : List (Attribute msg) -> List (Html msg) -> Html msg +headerLink = + styled a + [ color theme.fgLight + , padding (px 12) + , textDecoration Css.none + , hover + [ backgroundColor theme.secondary + , textDecoration underline + ] + ] + + +furbyButton : List (Attribute msg) -> List (Html msg) -> Html msg +furbyButton = + styled button + [ margin (px 12) + , color theme.fg + , Css.height (px 40) + , border (px 0) + , padding2 (px 6) (px 12) + , backgroundColor theme.primary + , hover + [ backgroundColor theme.secondary + , color theme.fg + , margin (px 12) + ] + ] + + +furbySelect : List (Attribute msg) -> List (Html msg) -> Html msg +furbySelect = + styled select + [ margin (px 6) + , color theme.fg + , border (px 0) + , borderBottom3 (px 2) solid theme.bgLight + , textAlign right + , padding2 (px 3) (px 3) + , backgroundColor theme.bg + , hover + [ borderBottom3 (px 2) solid theme.fg + ] + ] + + +loginInputField : List (Attribute msg) -> List (Html msg) -> Html msg +loginInputField = + styled input + [ Css.width (pct 100) + , color theme.fg + , border (px 0) + , borderBottom3 (px 1) solid theme.bgLight + , focus + [ borderBottom3 (px 2) solid theme.fg + ] + ] + + +bigHeading : Style +bigHeading = + 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 @@ module Utils exposing (..) +import Html +import Html.Styled exposing (..) +import Html.Styled.Attributes exposing (..) +import Html.Styled.Events exposing (..) + between : ( Float, Float ) -> Float -> Bool between ( l, u ) v = @@ -13,3 +18,43 @@ range start stop step = else start :: range (start + step) stop step + + +modelViewer : List (Attribute msg) -> List (Html msg) -> Html msg +modelViewer attributes children = + node "model-viewer" attributes children + + +cameraControls : Attribute msg +cameraControls = + attribute "camera-controls" "" + + +autoRotate : Attribute msg +autoRotate = + attribute "auto-rotate" "" + + +ar : Attribute msg +ar = + attribute "ar" "" + + +arSrc : String -> Attribute msg +arSrc src = + attribute "src" src + + +arIosSrc : String -> Attribute msg +arIosSrc src = + attribute "ios-src" src + + +arModes : String -> Attribute msg +arModes mode = + attribute "ar-modes" mode + + +loading : String -> Attribute msg +loading mode = + attribute "loading" mode -- cgit v1.2.3