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-02 19:05:50 +03:00
|
|
|
import Dict
|
2022-03-29 21:48:04 +03:00
|
|
|
import ErrorPage exposing (ErrorPage)
|
2022-01-17 02:29:06 +03:00
|
|
|
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
|
2022-07-02 19:05:50 +03:00
|
|
|
import Html.Styled
|
|
|
|
import Html.Styled.Attributes as StyledAttr
|
|
|
|
import Pages.Field as Field
|
|
|
|
import Pages.FieldRenderer
|
|
|
|
import Pages.Form as Form
|
2022-05-13 19:03:09 +03:00
|
|
|
import Pages.Msg
|
2022-01-01 23:50:03 +03:00
|
|
|
import Pages.PageUrl exposing (PageUrl)
|
|
|
|
import Pages.Url
|
2022-07-02 19:05:50 +03:00
|
|
|
import Route
|
2022-03-05 20:50:01 +03:00
|
|
|
import RouteBuilder exposing (StatelessRoute, StaticPayload)
|
2022-03-08 19:57:46 +03:00
|
|
|
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-07-02 19:05:50 +03:00
|
|
|
import Validation
|
2022-01-01 23:50:03 +03:00
|
|
|
import View exposing (View)
|
|
|
|
|
|
|
|
|
|
|
|
type alias Model =
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
type alias Msg =
|
2022-01-06 01:09:37 +03:00
|
|
|
()
|
2022-01-01 23:50:03 +03:00
|
|
|
|
|
|
|
|
|
|
|
type alias RouteParams =
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
2022-07-02 19:05:50 +03:00
|
|
|
type alias ActionData =
|
|
|
|
{ user : User
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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-02 19:05:50 +03:00
|
|
|
form : Form.HtmlForm String User User Msg
|
|
|
|
form =
|
|
|
|
Form.init
|
|
|
|
(\first last username email dob check ->
|
|
|
|
Validation.succeed User
|
2022-07-09 00:29:30 +03:00
|
|
|
|> Validation.andMap first
|
|
|
|
|> Validation.andMap last
|
|
|
|
|> Validation.andMap username
|
|
|
|
|> Validation.andMap email
|
|
|
|
|> Validation.andMap dob
|
|
|
|
|> Validation.andMap check
|
2022-07-02 19:05:50 +03:00
|
|
|
)
|
|
|
|
(\formState firstName lastName username email dob check ->
|
|
|
|
let
|
|
|
|
errors field =
|
|
|
|
formState.errors
|
2022-07-08 21:16:24 +03:00
|
|
|
|> Form.errorsForField field
|
2022-07-02 19:05:50 +03:00
|
|
|
|
|
|
|
errorsView field =
|
|
|
|
case ( formState.submitAttempted, field |> errors ) of
|
|
|
|
( True, first :: rest ) ->
|
|
|
|
Html.div []
|
|
|
|
[ Html.ul
|
|
|
|
[ Attr.style "border" "solid red"
|
|
|
|
]
|
|
|
|
(List.map
|
|
|
|
(\error ->
|
|
|
|
Html.li []
|
|
|
|
[ Html.text error
|
|
|
|
]
|
|
|
|
)
|
|
|
|
(first :: rest)
|
|
|
|
)
|
2022-01-03 19:43:00 +03:00
|
|
|
]
|
|
|
|
|
2022-07-02 19:05:50 +03:00
|
|
|
_ ->
|
|
|
|
Html.div [] []
|
2022-01-03 19:43:00 +03:00
|
|
|
|
2022-07-02 19:05:50 +03:00
|
|
|
fieldView label field =
|
2022-01-03 18:40:45 +03:00
|
|
|
Html.div []
|
2022-07-02 19:05:50 +03:00
|
|
|
[ Html.label []
|
|
|
|
[ Html.text (label ++ " ")
|
|
|
|
, field |> Pages.FieldRenderer.input []
|
2022-01-03 18:40:45 +03:00
|
|
|
]
|
2022-07-02 19:05:50 +03:00
|
|
|
, errorsView field
|
2022-01-03 18:40:45 +03:00
|
|
|
]
|
2022-07-02 19:05:50 +03:00
|
|
|
in
|
2022-07-08 21:09:52 +03:00
|
|
|
[ fieldView "Name" firstName
|
|
|
|
, fieldView "Description" lastName
|
|
|
|
, fieldView "Price" username
|
|
|
|
, fieldView "Image" email
|
|
|
|
, fieldView "Image" dob
|
|
|
|
, Html.button []
|
|
|
|
[ Html.text
|
|
|
|
(if formState.isTransitioning then
|
|
|
|
"Updating..."
|
2022-07-02 19:05:50 +03:00
|
|
|
|
2022-07-08 21:09:52 +03:00
|
|
|
else
|
|
|
|
"Update"
|
|
|
|
)
|
|
|
|
]
|
|
|
|
]
|
2022-07-02 19:05:50 +03:00
|
|
|
)
|
|
|
|
|> Form.field "first"
|
|
|
|
(Field.text
|
|
|
|
|> Field.required "Required"
|
|
|
|
|> Field.withInitialValue (.first >> Form.Value.string)
|
2022-01-01 23:50:03 +03:00
|
|
|
)
|
2022-07-02 19:05:50 +03:00
|
|
|
|> Form.field "last"
|
|
|
|
(Field.text
|
|
|
|
|> Field.required "Required"
|
|
|
|
|> Field.withInitialValue (.last >> Form.Value.string)
|
2022-01-01 23:50:03 +03:00
|
|
|
)
|
2022-07-02 19:05:50 +03:00
|
|
|
|> Form.field "username"
|
|
|
|
(Field.text
|
|
|
|
|> Field.required "Required"
|
|
|
|
|> Field.withInitialValue (.username >> Form.Value.string)
|
|
|
|
--|> Form.withServerValidation
|
|
|
|
-- (\username ->
|
|
|
|
-- if username == "asdf" then
|
|
|
|
-- DataSource.succeed [ "username is taken" ]
|
|
|
|
--
|
|
|
|
-- else
|
|
|
|
-- DataSource.succeed []
|
|
|
|
-- )
|
2022-01-01 23:50:03 +03:00
|
|
|
)
|
2022-07-02 19:05:50 +03:00
|
|
|
|> Form.field "email"
|
|
|
|
(Field.text
|
|
|
|
|> Field.required "Required"
|
|
|
|
|> Field.withInitialValue (.email >> Form.Value.string)
|
|
|
|
)
|
|
|
|
|> Form.field "dob"
|
|
|
|
(Field.date
|
2022-01-16 05:28:47 +03:00
|
|
|
{ invalid = \_ -> "Invalid date"
|
2022-01-14 19:42:14 +03:00
|
|
|
}
|
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-01-03 21:04:42 +03:00
|
|
|
)
|
2022-07-02 19:05:50 +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
|
2022-03-05 21:35:17 +03:00
|
|
|
route =
|
2022-03-05 20:50:01 +03:00
|
|
|
RouteBuilder.serverRender
|
2022-01-01 23:50:03 +03:00
|
|
|
{ head = head
|
|
|
|
, data = data
|
2022-05-04 21:06:23 +03:00
|
|
|
, 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-05-04 21:06:23 +03:00
|
|
|
{}
|
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
|
2022-05-04 21:06:23 +03:00
|
|
|
|> 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 =
|
|
|
|
Request.formParserResultNew [ form ]
|
|
|
|
|> Request.map
|
|
|
|
(\userResult ->
|
|
|
|
ActionData
|
|
|
|
(userResult
|
|
|
|
-- TODO nicer error handling
|
|
|
|
-- TODO wire up DataSource server-side validation errors
|
|
|
|
|> Result.withDefault defaultUser
|
|
|
|
)
|
|
|
|
|> Server.Response.render
|
|
|
|
|> DataSource.succeed
|
|
|
|
)
|
|
|
|
|
|
|
|
|
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
|
2022-05-13 19:03:09 +03:00
|
|
|
-> View (Pages.Msg.Msg Msg)
|
2022-07-09 01:25:48 +03:00
|
|
|
view maybeUrl sharedModel app =
|
2022-01-01 23:50:03 +03:00
|
|
|
let
|
2022-01-02 21:23:36 +03:00
|
|
|
user : User
|
2022-01-01 23:50:03 +03:00
|
|
|
user =
|
2022-07-09 01:25:48 +03:00
|
|
|
app.action
|
2022-07-02 19:05:50 +03:00
|
|
|
|> Maybe.map .user
|
2022-01-14 01:18:53 +03:00
|
|
|
|> Maybe.withDefault defaultUser
|
2022-01-01 23:50:03 +03:00
|
|
|
in
|
|
|
|
{ title = "Form Example"
|
|
|
|
, body =
|
2022-07-09 01:25:48 +03:00
|
|
|
[ Html.pre []
|
|
|
|
[ app.action
|
|
|
|
|> Debug.toString
|
|
|
|
|> Html.text
|
|
|
|
]
|
|
|
|
, app.action
|
2022-07-02 19:05:50 +03:00
|
|
|
|> Maybe.map .user
|
2022-01-03 21:07:06 +03:00
|
|
|
|> Maybe.map
|
2022-01-14 01:18:53 +03:00
|
|
|
(\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
|
|
|
)
|
2022-01-14 01:18:53 +03:00
|
|
|
|> Maybe.withDefault (Html.p [] [])
|
2022-01-03 21:07:06 +03:00
|
|
|
, Html.h1
|
|
|
|
[]
|
|
|
|
[ Html.text <| "Edit profile " ++ user.first ++ " " ++ user.last ]
|
2022-07-08 20:57:22 +03:00
|
|
|
, form
|
|
|
|
|> Form.toDynamicTransition "test1"
|
2022-07-08 21:09:52 +03:00
|
|
|
|> Form.renderHtml
|
|
|
|
[ Attr.style "display" "flex"
|
|
|
|
, Attr.style "flex-direction" "column"
|
|
|
|
, Attr.style "gap" "20px"
|
|
|
|
]
|
2022-07-09 01:25:48 +03:00
|
|
|
app
|
2022-07-08 21:09:52 +03:00
|
|
|
defaultUser
|
2022-01-01 23:50:03 +03:00
|
|
|
]
|
|
|
|
}
|