initial commit

This commit is contained in:
Youwen Wu 2025-02-16 16:54:16 -08:00
commit cfe0001846
Signed by: youwen5
GPG key ID: 865658ED1FE61EC3
4 changed files with 119 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
elm-stuff/

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# elm experiments
a collection of various experiments to learn [Elm](https://elm-lang.org/)

24
elm.json Normal file
View file

@ -0,0 +1,24 @@
{
"type": "application",
"source-directories": [
"src"
],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
"elm/html": "1.0.0"
},
"indirect": {
"elm/json": "1.1.3",
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.3"
}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}

View file

@ -0,0 +1,91 @@
module PasswordValidation exposing (..)
import Browser
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)
-- MAIN
main =
Browser.sandbox { init = init, update = update, view = view }
-- MODEL
type alias Model =
{ name : String
, password : String
, passwordAgain : String
}
init : Model
init = Model "" "" ""
-- UPDATE
type Msg
= Name String
| Password String
| PasswordAgain String
update : Msg -> Model -> Model
update msg model =
case msg of
Name name ->
{ model | name = name }
Password password ->
{ model | password = password }
PasswordAgain password ->
{ model | passwordAgain = password }
-- VIEW
view : Model -> Html Msg
view model =
div []
[ viewInput "text" "Name" model.name Name
, viewInput "password" "Password" model.password Password
, viewInput "password" "Re-enter Password" model.passwordAgain PasswordAgain
, viewValidation model
]
viewInput : String -> String -> String -> (String -> msg) -> Html msg
viewInput t p v toMsg =
input [ type_ t, placeholder p, value v, onInput toMsg ] []
viewValidation : Model -> Html msg
viewValidation model =
if List.length (passwordHints model.password) > 0 then
div [ style "color" "red" ] (passwordHints model.password)
else if model.password /= model.passwordAgain then
div [ style "color" "red" ] [ text "Passwords do not match!" ]
else
div [ style "color" "green" ] [ text "OK" ]
passwordHints : String -> List (Html msg)
passwordHints s =
(optional (String.length s <= 8) (text "Password must be at least 8 characters. "))
++ (optional (String.toUpper s == s) (text "Password must contain an uppercase letter. "))
++ (optional (String.toLower s == s) (text "Password must contain a lowercase letter. "))
++ (optional (not (containsNumeric s)) (text "Password must contain a number. "))
optional : Bool -> Html msg -> List (Html msg)
optional b xs = if b then [xs] else []
containsNumeric : String -> Bool
containsNumeric s = List.any (\b -> b) (List.map (\x -> String.contains x s) ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"])