elm-pages-v3-beta/examples/pokedex/app/Route/Form.elm

277 lines
8.3 KiB
Elm
Raw Normal View History

2022-05-03 21:51:32 +03:00
module Route.Form exposing (ActionData, Data, Model, Msg, route)
2022-01-01 23:50:03 +03:00
import DataSource exposing (DataSource)
2022-01-04 08:17:07 +03:00
import Date exposing (Date)
2022-07-12 12:54:13 +03:00
import Dict exposing (Dict)
2022-03-29 21:48:04 +03:00
import ErrorPage exposing (ErrorPage)
2022-07-09 04:00:30 +03:00
import Form
2022-07-09 03:56:52 +03:00
import Form.Field as Field
2022-07-09 03:58:41 +03:00
import Form.FieldView
2022-07-24 22:00:47 +03:00
import Form.Validation as Validation exposing (Combined)
import Form.Value
2022-01-01 23:50:03 +03:00
import Head
import Head.Seo as Seo
2022-01-03 21:07:06 +03:00
import Html exposing (Html)
import Html.Attributes as Attr
import Pages.Msg
2022-01-01 23:50:03 +03:00
import Pages.PageUrl exposing (PageUrl)
import Pages.Url
2022-03-05 20:50:01 +03:00
import RouteBuilder exposing (StatelessRoute, StaticPayload)
import Server.Request as Request exposing (Parser)
2022-07-02 19:05:50 +03:00
import Server.Response
2022-01-01 23:50:03 +03:00
import Shared
2022-01-04 08:17:07 +03:00
import Time
2022-01-01 23:50:03 +03:00
import View exposing (View)
type alias Model =
{}
type alias Msg =
()
2022-01-01 23:50:03 +03:00
type alias RouteParams =
{}
2022-07-02 19:05:50 +03:00
type alias ActionData =
{ user : Maybe User
2022-07-12 12:54:13 +03:00
, formResponse : Maybe { fields : List ( String, String ), errors : Dict String (List String) }
2022-07-02 19:05:50 +03:00
}
2022-01-01 23:50:03 +03:00
type alias User =
{ first : String
, last : String
, username : String
, email : String
2022-01-04 08:17:07 +03:00
, birthDay : Date
2022-01-04 22:47:57 +03:00
, checkbox : Bool
2022-01-01 23:50:03 +03:00
}
defaultUser : User
defaultUser =
2022-01-02 05:35:36 +03:00
{ first = "Jane"
, last = "Doe"
, username = "janedoe"
, email = "janedoe@example.com"
2022-01-04 08:17:07 +03:00
, birthDay = Date.fromCalendarDate 1969 Time.Jul 20
2022-01-04 22:47:57 +03:00
, checkbox = False
2022-01-01 23:50:03 +03:00
}
2022-07-24 10:09:20 +03:00
form : Form.HtmlForm String User User Msg
2022-07-02 19:05:50 +03:00
form =
2022-07-24 10:11:12 +03:00
Form.init
(\firstName lastName username email dob check ->
{ combine =
Validation.succeed User
|> Validation.andMap firstName
|> Validation.andMap lastName
|> Validation.andMap username
|> Validation.andMap email
|> Validation.andMap dob
|> Validation.andMap check
, view =
\formState ->
let
errors field =
formState.errors
2022-07-24 10:11:12 +03:00
|> Form.errorsForField field
errorsView field =
case
( formState.submitAttempted
, errors field
)
of
( _, first :: rest ) ->
Html.div []
[ Html.ul
[ Attr.style "border" "solid red"
]
(List.map
(\error ->
Html.li []
[ Html.text error
]
)
(first :: rest)
)
]
_ ->
Html.div [] []
fieldView label field =
2022-07-02 19:05:50 +03:00
Html.div []
[ Html.label []
[ Html.text (label ++ " ")
2022-07-24 10:18:10 +03:00
, field |> Form.FieldView.input []
2022-07-02 19:05:50 +03:00
]
, errorsView field
2022-01-03 19:43:00 +03:00
]
in
[ fieldView "First" firstName
, fieldView "Last" lastName
, fieldView "Price" username
, fieldView "Image" email
, fieldView "Image" dob
, Html.button []
[ Html.text
(if formState.isTransitioning then
"Updating..."
else
"Update"
)
2022-01-03 18:40:45 +03:00
]
]
}
2022-07-02 19:05:50 +03:00
)
2022-07-24 10:11:12 +03:00
|> Form.field "first"
2022-07-02 19:05:50 +03:00
(Field.text
|> Field.required "Required"
|> Field.withInitialValue (.first >> Form.Value.string)
2022-01-01 23:50:03 +03:00
)
2022-07-24 10:11:12 +03:00
|> Form.field "last"
2022-07-02 19:05:50 +03:00
(Field.text
|> Field.required "Required"
|> Field.withInitialValue (.last >> Form.Value.string)
2022-01-01 23:50:03 +03:00
)
2022-07-24 10:11:12 +03:00
|> Form.field "username"
2022-07-02 19:05:50 +03:00
(Field.text
|> Field.required "Required"
|> Field.withInitialValue (.username >> Form.Value.string)
2022-01-01 23:50:03 +03:00
)
2022-07-24 10:11:12 +03:00
|> Form.field "email"
2022-07-02 19:05:50 +03:00
(Field.text
|> Field.required "Required"
|> Field.withInitialValue (.email >> Form.Value.string)
)
2022-07-24 10:11:12 +03:00
|> Form.field "dob"
2022-07-02 19:05:50 +03:00
(Field.date
{ invalid = \_ -> "Invalid date"
}
2022-07-02 19:05:50 +03:00
|> Field.required "Required"
|> Field.withInitialValue (.birthDay >> Form.Value.date)
--|> Field.withMin (Date.fromCalendarDate 1900 Time.Jan 1 |> Form.Value.date)
--|> Field.withMax (Date.fromCalendarDate 2022 Time.Jan 1 |> Form.Value.date)
)
2022-07-24 10:11:12 +03:00
|> Form.field "checkbox" Field.checkbox
2022-01-01 23:50:03 +03:00
2022-05-03 21:51:32 +03:00
route : StatelessRoute RouteParams Data ActionData
route =
2022-03-05 20:50:01 +03:00
RouteBuilder.serverRender
2022-01-01 23:50:03 +03:00
{ head = head
, data = data
, action = action
2022-01-01 23:50:03 +03:00
}
2022-03-05 20:50:01 +03:00
|> RouteBuilder.buildNoState { view = view }
2022-01-01 23:50:03 +03:00
type alias Data =
{}
2022-01-01 23:50:03 +03:00
2022-07-02 19:05:50 +03:00
data : RouteParams -> Parser (DataSource (Server.Response.Response Data ErrorPage))
2022-01-01 23:50:03 +03:00
data routeParams =
2022-07-02 19:05:50 +03:00
Data
|> Server.Response.render
|> DataSource.succeed
|> Request.succeed
2022-01-01 23:50:03 +03:00
2022-07-02 19:05:50 +03:00
action : RouteParams -> Parser (DataSource (Server.Response.Response ActionData ErrorPage))
action routeParams =
2022-08-25 06:12:06 +03:00
Request.formData (form |> Form.initCombined identity)
2022-07-02 19:05:50 +03:00
|> Request.map
2022-08-08 16:47:47 +03:00
(\userResult ->
(case userResult of
Ok user ->
{ user = Just user
, formResponse = Nothing
}
Err error ->
{ user = Nothing
, formResponse = Just error
}
)
|> Server.Response.render
|> DataSource.succeed
2022-07-02 19:05:50 +03:00
)
2022-01-01 23:50:03 +03:00
head :
2022-05-03 21:51:32 +03:00
StaticPayload Data ActionData RouteParams
2022-01-01 23:50:03 +03:00
-> List Head.Tag
head static =
2022-07-02 19:05:50 +03:00
Seo.summary
{ canonicalUrlOverride = Nothing
, siteName = "elm-pages"
, image =
{ url = Pages.Url.external "TODO"
, alt = "elm-pages logo"
, dimensions = Nothing
, mimeType = Nothing
}
, description = "TODO"
, locale = Nothing
, title = "TODO title" -- metadata.title -- TODO
}
|> Seo.website
2022-01-01 23:50:03 +03:00
view :
Maybe PageUrl
-> Shared.Model
2022-05-03 21:51:32 +03:00
-> StaticPayload Data ActionData RouteParams
-> View (Pages.Msg.Msg Msg)
view maybeUrl sharedModel app =
2022-01-01 23:50:03 +03:00
let
user : User
2022-01-01 23:50:03 +03:00
user =
app.action
|> Maybe.andThen .user
|> Maybe.withDefault defaultUser
2022-01-01 23:50:03 +03:00
in
{ title = "Form Example"
, body =
[ Html.pre []
[ app.action
|> Debug.toString
|> Html.text
]
, app.action
|> Maybe.andThen .user
2022-01-03 21:07:06 +03:00
|> Maybe.map
(\user_ ->
Html.p
[ Attr.style "padding" "10px"
, Attr.style "background-color" "#a3fba3"
]
[ Html.text <| "Successfully received user " ++ user_.first ++ " " ++ user_.last
]
2022-01-03 21:07:06 +03:00
)
|> Maybe.withDefault (Html.p [] [])
2022-01-03 21:07:06 +03:00
, Html.h1
[]
[ Html.text <| "Edit profile " ++ user.first ++ " " ++ user.last ]
, form
2022-07-24 10:11:12 +03:00
|> Form.toDynamicTransition "test1"
|> Form.renderHtml
[ Attr.style "display" "flex"
, Attr.style "flex-direction" "column"
, Attr.style "gap" "20px"
]
(app.action |> Maybe.andThen .formResponse)
app
defaultUser
2022-01-01 23:50:03 +03:00
]
}