all repos

onasty @ 327757c

a one-time notes service

onasty/web/src/Pages/SignIn.elm (view raw)

Smirnov Oleksandr Smirnov Oleksandr
ss2316544@gmail.com
scaffold frontend app (#134)..., 11 months ago
1
module Pages.SignIn exposing (Model, Msg, page)
2
3
import Api
4
import Api.Auth
5
import Data.Credentials exposing (Credentials)
6
import Effect exposing (Effect)
7
import Html exposing (Html)
8
import Html.Attributes as Attr
9
import Html.Events
10
import Http
11
import Page exposing (Page)
12
import Route exposing (Route)
13
import Route.Path
14
import Shared
15
import View exposing (View)
16
17
18
page : Shared.Model -> Route () -> Page Model Msg
19
page shared _ =
20
    Page.new
21
        { init = init shared
22
        , update = update
23
        , subscriptions = subscriptions
24
        , view = view
25
        }
26
27
28
29
-- INIT
30
31
32
type alias Model =
33
    { email : String
34
    , password : String
35
    , isSubmittingForm : Bool
36
    , error : Maybe Http.Error
37
    }
38
39
40
init : Shared.Model -> () -> ( Model, Effect Msg )
41
init shared _ =
42
    ( { isSubmittingForm = False
43
      , email = ""
44
      , password = ""
45
      , error = Nothing
46
      }
47
    , case shared.credentials of
48
        Just _ ->
49
            Effect.pushRoutePath Route.Path.Home_
50
51
        Nothing ->
52
            Effect.none
53
    )
54
55
56
57
-- UPDATE
58
59
60
type Msg
61
    = UserUpdatedInput Field String
62
    | UserClickedSubmit
63
    | ApiSignInResponded (Result Http.Error Credentials)
64
65
66
type Field
67
    = Email
68
    | Password
69
70
71
update : Msg -> Model -> ( Model, Effect Msg )
72
update msg model =
73
    case msg of
74
        UserClickedSubmit ->
75
            ( { model | isSubmittingForm = True }
76
            , Api.Auth.signin
77
                { onResponse = ApiSignInResponded
78
                , email = model.email
79
                , password = model.password
80
                }
81
            )
82
83
        UserUpdatedInput Email email ->
84
            ( { model | email = email }, Effect.none )
85
86
        UserUpdatedInput Password password ->
87
            ( { model | password = password }, Effect.none )
88
89
        ApiSignInResponded (Ok credentials) ->
90
            ( { model | isSubmittingForm = False }
91
            , Effect.signin credentials
92
            )
93
94
        ApiSignInResponded (Err error) ->
95
            ( { model | isSubmittingForm = False, error = Just error }
96
            , Effect.none
97
            )
98
99
100
101
-- SUBSCRIPTIONS
102
103
104
subscriptions : Model -> Sub Msg
105
subscriptions _ =
106
    Sub.none
107
108
109
110
-- VIEW
111
112
113
view : Model -> View Msg
114
view model =
115
    { title = "Sign-in"
116
    , body =
117
        [ Html.div []
118
            [ Html.div []
119
                [ Html.div []
120
                    [ Html.h1 [] [ Html.text "Sign in" ]
121
                    , viewError model.error
122
                    , viewForm model
123
                    ]
124
                ]
125
            ]
126
        ]
127
    }
128
129
130
viewForm : Model -> Html Msg
131
viewForm model =
132
    Html.form [ Html.Events.onSubmit UserClickedSubmit ]
133
        [ viewFormInput { field = Email, value = model.email }
134
        , viewFormInput { field = Password, value = model.password }
135
        , viewFormControls model
136
        ]
137
138
139
viewError : Maybe Http.Error -> Html Msg
140
viewError maybeError =
141
    case maybeError of
142
        Just error ->
143
            Html.div [ Attr.style "color" "red" ]
144
                [ Html.text (Api.errorToFriendlyMessage error) ]
145
146
        Nothing ->
147
            Html.text ""
148
149
150
viewFormInput : { field : Field, value : String } -> Html Msg
151
viewFormInput opts =
152
    Html.div []
153
        [ Html.label [] [ Html.text (fromFieldToLabel opts.field) ]
154
        , Html.div []
155
            [ Html.input
156
                [ Attr.type_ (fromFieldToInputType opts.field)
157
                , Attr.value opts.value
158
                , Html.Events.onInput (UserUpdatedInput opts.field)
159
                ]
160
                []
161
            ]
162
        ]
163
164
165
viewFormControls : Model -> Html Msg
166
viewFormControls model =
167
    Html.div []
168
        [ Html.button
169
            [ Attr.disabled model.isSubmittingForm ]
170
            [ Html.text "Sign In" ]
171
        ]
172
173
174
fromFieldToLabel : Field -> String
175
fromFieldToLabel field =
176
    case field of
177
        Email ->
178
            "Email address"
179
180
        Password ->
181
            "Password"
182
183
184
fromFieldToInputType : Field -> String
185
fromFieldToInputType field =
186
    case field of
187
        Email ->
188
            "email"
189
190
        Password ->
191
            "password"