Created
May 6, 2018 14:30
-
-
Save nloomans/55671f404a6ea2dece35c6a0209cf4be to your computer and use it in GitHub Desktop.
Elm Code Review
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main exposing (..) | |
import Html exposing (Html, div, form, input, button, br, text) | |
import Html.Events exposing (onSubmit, onClick, onInput) | |
import Html.Attributes exposing (type_, placeholder, value, style) | |
import Dict exposing (Dict) | |
main : Program Never Model Msg | |
main = | |
Html.beginnerProgram { model = model, view = view, update = update } | |
-- MODEL | |
type alias User = | |
{ username : String | |
, password : String | |
, fullName : String | |
, moto : String | |
} | |
type alias Users = | |
Dict String User | |
type LoginError | |
= InvalidUsername | |
| InvalidPassword | |
| NoError | |
type alias LoggedInState = | |
{ currentUsername : String } | |
type alias LoggedOutState = | |
{ usernameField : String | |
, passwordField : String | |
, error : LoginError | |
} | |
type State | |
= LoggedIn LoggedInState | |
| LoggedOut LoggedOutState | |
type alias Model = | |
{ state : State, users : Users } | |
model : Model | |
model = | |
{ state = | |
LoggedOut | |
{ usernameField = "" | |
, passwordField = "" | |
, error = NoError | |
} | |
, users = | |
Dict.empty | |
|> Dict.insert "nloomans" | |
(User | |
"nloomans" | |
"hunter2" | |
"Noah Loomans" | |
"Hi my name is Noah and I like to code stuff." | |
) | |
|> Dict.insert "foobar" | |
(User | |
"foobar" | |
"barfoo" | |
"Foo Baz Bar" | |
"Foo + Bar = Baz" | |
) | |
} | |
-- UPDATE | |
type Msg | |
= ToggleLogin | |
| UpdateUsernameField String | |
| UpdatePasswordField String | |
| UpdateMoto String String | |
update : Msg -> Model -> Model | |
update msg model = | |
case msg of | |
ToggleLogin -> | |
case model.state of | |
LoggedIn { currentUsername } -> | |
-- Log the user out | |
{ model | |
| state = | |
LoggedOut | |
{ usernameField = currentUsername | |
, passwordField = "" | |
, error = NoError | |
} | |
} | |
LoggedOut { usernameField, passwordField } -> | |
let | |
isUsernameCorrect = | |
model.users |> Dict.member usernameField | |
isPasswordCorrect = | |
case | |
model.users | |
|> Dict.get usernameField | |
of | |
Just user -> | |
user.password == passwordField | |
Nothing -> | |
False | |
in | |
if not isUsernameCorrect then | |
-- Invalid username, display an error | |
{ model | |
| state = | |
LoggedOut | |
{ usernameField = usernameField | |
, passwordField = "" | |
, error = InvalidUsername | |
} | |
} | |
else if not isPasswordCorrect then | |
-- Invalid password, display an error | |
{ model | |
| state = | |
LoggedOut | |
{ usernameField = usernameField | |
, passwordField = "" | |
, error = InvalidPassword | |
} | |
} | |
else | |
-- Log the user in | |
{ model | |
| state = | |
LoggedIn | |
{ currentUsername = usernameField } | |
} | |
UpdateUsernameField username -> | |
case model.state of | |
LoggedOut loggedOutState -> | |
{ model | |
| state = | |
LoggedOut | |
{ loggedOutState | |
| usernameField = | |
username | |
} | |
} | |
LoggedIn _ -> | |
Debug.crash "UpdateUsernameField is only valid when logged out" | |
UpdatePasswordField password -> | |
case model.state of | |
LoggedOut loggedOutState -> | |
{ model | |
| state = | |
LoggedOut | |
{ loggedOutState | |
| passwordField = | |
password | |
} | |
} | |
LoggedIn _ -> | |
Debug.crash "UpdatePasswordField is only valid when logged out" | |
UpdateMoto username moto -> | |
{ model | |
| users = | |
updateUser | |
username | |
(\user -> { user | moto = moto }) | |
model.users | |
} | |
updateUser : String -> (User -> User) -> Users -> Users | |
updateUser username updater users = | |
Dict.update username (Maybe.map updater) users | |
-- VIEW | |
viewLoggedOut : LoggedOutState -> Html Msg | |
viewLoggedOut { usernameField, passwordField, error } = | |
div [] | |
[ text "Hello there, please login to use our application!" | |
, br [] [] | |
, form [ onSubmit (ToggleLogin) ] | |
[ input | |
[ type_ "text" | |
, placeholder "Username" | |
, value usernameField | |
, onInput UpdateUsernameField | |
] | |
[] | |
, br [] [] | |
, input | |
[ type_ "password" | |
, placeholder "Password" | |
, value passwordField | |
, onInput UpdatePasswordField | |
] | |
[] | |
, br [] [] | |
, button [] [ text "Login" ] | |
] | |
, case error of | |
InvalidUsername -> | |
div [ style [ ( "background-color", "red" ) ] ] | |
[ text "Invalid username!" ] | |
InvalidPassword -> | |
div [ style [ ( "background-color", "red" ) ] ] | |
[ text "Invalid password!" ] | |
NoError -> | |
div [] [] | |
] | |
viewLoggedIn : User -> Html Msg | |
viewLoggedIn user = | |
div [] | |
[ button [ onClick ToggleLogin ] [ text "Logout" ] | |
, br [] [] | |
, text ("Hello there " ++ user.fullName) | |
, viewEditMoto user.username user.moto | |
] | |
viewEditMoto : String -> String -> Html Msg | |
viewEditMoto username moto = | |
div [] | |
[ text "String: " | |
, input | |
[ type_ "text" | |
, value moto | |
, onInput (UpdateMoto username) | |
, style [ ( "width", "300px" ) ] | |
] | |
[] | |
] | |
view : Model -> Html Msg | |
view { state, users } = | |
case state of | |
LoggedIn { currentUsername } -> | |
case users |> Dict.get currentUsername of | |
Just user -> | |
viewLoggedIn user | |
Nothing -> | |
Debug.crash "We already checked if the user exists during the login, so this should never happen, right???" | |
LoggedOut loggedOutState -> | |
viewLoggedOut loggedOutState |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment