This commit is contained in:
Youwen Wu 2025-02-16 19:15:39 -08:00
parent cfe0001846
commit 890037144b
Signed by: youwen5
GPG key ID: 865658ED1FE61EC3
3 changed files with 140 additions and 37 deletions

View file

@ -8,9 +8,12 @@
"direct": { "direct": {
"elm/browser": "1.0.2", "elm/browser": "1.0.2",
"elm/core": "1.0.5", "elm/core": "1.0.5",
"elm/html": "1.0.0" "elm/html": "1.0.0",
"elm/http": "2.0.0"
}, },
"indirect": { "indirect": {
"elm/bytes": "1.0.8",
"elm/file": "1.0.5",
"elm/json": "1.1.3", "elm/json": "1.1.3",
"elm/time": "1.0.0", "elm/time": "1.0.0",
"elm/url": "1.0.0", "elm/url": "1.0.0",

85
src/HTTP.elm Normal file
View file

@ -0,0 +1,85 @@
module HTTP exposing (..)
import Browser
import Html exposing (Html, pre, text)
import Http
-- MAIN
main : Program () Model Msg
main =
Browser.element
{ init = init
, update = update
, subscriptions = subscriptions
, view = view
}
-- MODEL
type Model
= Failure
| Loading
| Success String
init : () -> ( Model, Cmd Msg )
init _ =
( Loading
, Http.get
{ url = "https://elm-lang.org/assets/public-opinion.txt"
, expect = Http.expectString GotText
}
)
-- UPDATE
type Msg
= GotText (Result Http.Error String)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
GotText result ->
case result of
Ok fullText ->
( Success fullText, Cmd.none )
Err _ ->
( Failure, Cmd.none )
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
-- VIEW
view : Model -> Html Msg
view model =
case model of
Failure ->
text "I was unable to load your book."
Loading ->
text "Loading..."
Success fullText ->
pre [] [ text fullText ]

View file

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