Files
2026-07-13 13:33:09 +08:00

170 lines
3.6 KiB
Elm

module Example exposing (..)
import Browser
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Http
import Json.Decode as Decode exposing (Decoder)
import Json.Encode as Encode
-- MODEL
type alias Model =
{ users : List User
, inputText : String
, error : Maybe String
}
type alias User =
{ id : Int
, name : String
, email : String
}
init : () -> (Model, Cmd Msg)
init _ =
( { users = []
, inputText = ""
, error = Nothing
}
, fetchUsers
)
-- UPDATE
type Msg
= GotUsers (Result Http.Error (List User))
| InputChanged String
| AddUser
| UserAdded (Result Http.Error User)
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
GotUsers result ->
case result of
Ok users ->
( { model | users = users, error = Nothing }
, Cmd.none
)
Err _ ->
( { model | error = Just "Failed to fetch users" }
, Cmd.none
)
InputChanged text ->
( { model | inputText = text }
, Cmd.none
)
AddUser ->
( model
, addUser model.inputText
)
UserAdded result ->
case result of
Ok user ->
( { model
| users = user :: model.users
, inputText = ""
, error = Nothing
}
, Cmd.none
)
Err _ ->
( { model | error = Just "Failed to add user" }
, Cmd.none
)
-- HTTP
fetchUsers : Cmd Msg
fetchUsers =
Http.get
{ url = "/api/users"
, expect = Http.expectJson GotUsers usersDecoder
}
addUser : String -> Cmd Msg
addUser name =
Http.post
{ url = "/api/users"
, body = Http.jsonBody (userEncoder name)
, expect = Http.expectJson UserAdded userDecoder
}
-- JSON
userEncoder : String -> Encode.Value
userEncoder name =
Encode.object
[ ("name", Encode.string name)
]
userDecoder : Decoder User
userDecoder =
Decode.map3 User
(Decode.field "id" Decode.int)
(Decode.field "name" Decode.string)
(Decode.field "email" Decode.string)
usersDecoder : Decoder (List User)
usersDecoder =
Decode.list userDecoder
-- VIEW
view : Model -> Html Msg
view model =
div []
[ h1 [] [ text "User Management" ]
, viewError model.error
, viewInput model.inputText
, viewUsers model.users
]
viewError : Maybe String -> Html Msg
viewError maybeError =
case maybeError of
Just error ->
div [ class "error" ] [ text error ]
Nothing ->
text ""
viewInput : String -> Html Msg
viewInput inputText =
div []
[ input
[ value inputText
, onInput InputChanged
, placeholder "Enter user name"
] []
, button [ onClick AddUser ] [ text "Add User" ]
]
viewUsers : List User -> Html Msg
viewUsers users =
div []
[ h2 [] [ text "Users" ]
, ul [] (List.map viewUser users)
]
viewUser : User -> Html Msg
viewUser user =
li []
[ text (user.name ++ " (" ++ user.email ++ ")")
]
-- MAIN
main : Program () Model Msg
main =
Browser.element
{ init = init
, update = update
, view = view
, subscriptions = \_ -> Sub.none
}