1
1
<template >
2
2
<div class =" form" >
3
+ <div v-if =" emailExistsError" class =" input-error" >{{ $t('emailDoesNotExist') }}</div >
3
4
<div class =" form-group row text-center" >
4
5
<div class =" col-12" >
5
6
<div
6
7
class =" btn btn-secondary social-button"
7
8
@click =" socialAuth('google')"
8
9
>
9
- <div
10
- class =" svg-icon social-icon"
11
- v-html =" icons.googleIcon"
12
- ></div >
10
+ <div class =" svg-icon social-icon" v-html =" icons.googleIcon" ></div >
13
11
<span >{{ registering
14
12
? $t('signUpWithSocial', {social: 'Google'})
15
13
: $t('loginWithSocial', {social: 'Google'}) }}</span >
22
20
class =" btn btn-secondary social-button"
23
21
@click =" socialAuth('apple')"
24
22
>
25
- <div
26
- class =" svg-icon social-icon apple-icon"
27
- v-html =" icons.appleIcon"
28
- ></div >
23
+ <div class =" svg-icon social-icon apple-icon" v-html =" icons.appleIcon" ></div >
29
24
<span >{{ registering
30
25
? $t('signUpWithSocial', {social: 'Apple'})
31
26
: $t('loginWithSocial', {social: 'Apple'}) }}</span >
32
27
</div >
33
28
</div >
34
29
</div >
35
- <div
36
- v-if =" registering"
37
- class =" form-group"
38
- >
39
- <label
40
- v-once
41
- for =" usernameInput"
42
- >{{ $t('username') }}</label >
30
+ <div v-if =" registering" class =" form-group" >
31
+ <label v-once for =" usernameInput" >{{ $t('username') }}</label >
43
32
<input
44
33
id =" usernameInput"
45
34
v-model =" username"
48
37
:placeholder =" $t('usernamePlaceholder')"
49
38
:class =" {'input-valid': usernameValid, 'input-invalid': usernameInvalid}"
50
39
>
51
- <div
52
- v-for =" issue in usernameIssues"
53
- :key =" issue"
54
- class =" input-error"
55
- >
40
+ <div v-for =" issue in usernameIssues" :key =" issue" class =" input-error" >
56
41
{{ issue }}
57
42
</div >
58
43
</div >
59
- <div
60
- v-if =" !registering"
61
- class =" form-group"
62
- >
63
- <label
64
- v-once
65
- for =" usernameInput"
66
- >{{ $t('emailOrUsername') }}</label >
44
+ <div v-if =" !registering" class =" form-group" >
45
+ <label v-once for =" usernameInput" >{{ $t('emailOrUsername') }}</label >
67
46
<input
68
47
id =" usernameInput"
69
48
v-model =" username"
72
51
:placeholder =" $t('emailOrUsername')"
73
52
>
74
53
</div >
75
- <div
76
- v-if =" registering"
77
- class =" form-group"
78
- >
79
- <label
80
- v-once
81
- for =" emailInput"
82
- >{{ $t('email') }}</label >
54
+ <div v-if =" registering" class =" form-group" >
55
+ <label v-once for =" emailInput" >{{ $t('email') }}</label >
83
56
<input
84
57
id =" emailInput"
85
58
v-model =" email"
86
59
class =" form-control"
87
60
type =" email"
88
61
:placeholder =" $t('emailPlaceholder')"
89
- :class =" {'input-invalid': emailInvalid, 'input-valid': emailValid}"
62
+ :class =" {'input-invalid': emailInvalid || emailExistsError, 'input-valid': emailValid}"
63
+ @blur =" checkEmailExists"
90
64
>
91
65
</div >
92
66
<div class =" form-group" >
93
- <label
94
- v-once
95
- for =" passwordInput"
96
- >{{ $t('password') }}</label >
97
- <a
98
- v-if =" !registering"
99
- v-once
100
- class =" float-right forgot-password"
101
- @click =" forgotPassword = true"
102
- >{{ $t('forgotPassword') }}</a >
67
+ <label v-once for =" passwordInput" >{{ $t('password') }}</label >
68
+ <a v-if =" !registering" v-once class =" float-right forgot-password" @click =" forgotPassword = true" >{{ $t('forgotPassword') }}</a >
103
69
<input
104
70
id =" passwordInput"
105
71
v-model =" password"
108
74
:placeholder =" $t(registering ? 'passwordPlaceholder' : 'password')"
109
75
:class =" {
110
76
'input-valid': registering ? passwordValid : false,
111
- 'input-invalid': registering ? passwordInvalid: false,
77
+ 'input-invalid': registering ? passwordInvalid : false,
112
78
}"
113
79
>
114
- <div
115
- v-if =" passwordInvalid && registering"
116
- class =" input-error"
117
- >
80
+ <div v-if =" passwordInvalid && registering" class =" input-error" >
118
81
{{ $t('minPasswordLength') }}
119
82
</div >
120
83
</div >
121
- <div
122
- v-if =" registering"
123
- class =" form-group"
124
- >
125
- <label
126
- v-once
127
- for =" confirmPasswordInput"
128
- >{{ $t('confirmPassword') }}</label >
84
+ <div v-if =" registering" class =" form-group" >
85
+ <label v-once for =" confirmPasswordInput" >{{ $t('confirmPassword') }}</label >
129
86
<input
130
87
id =" confirmPasswordInput"
131
88
v-model =" passwordConfirm"
134
91
:placeholder =" $t('confirmPasswordPlaceholder')"
135
92
:class =" {'input-invalid': passwordConfirmInvalid, 'input-valid': passwordConfirmValid}"
136
93
>
137
- <div
138
- v-if =" passwordConfirmInvalid"
139
- class =" input-error"
140
- >
94
+ <div v-if =" passwordConfirmInvalid" class =" input-error" >
141
95
{{ $t('passwordConfirmationMatch') }}
142
96
</div >
143
- <small
144
- v-once
145
- class =" form-text"
146
- v-html =" $t('termsAndAgreement')"
147
- ></small >
97
+ <small v-once class =" form-text" v-html =" $t('termsAndAgreement')" ></small >
148
98
</div >
149
99
<div class =" text-center" >
150
- <div
151
- v-if =" registering"
152
- v-once
153
- class =" btn btn-info"
154
- @click =" register()"
155
- >
100
+ <div v-if =" registering" v-once class =" btn btn-info" @click =" register" >
156
101
{{ $t('joinHabitica') }}
157
102
</div >
158
- <div
159
- v-if =" !registering"
160
- v-once
161
- class =" btn btn-info"
162
- @click =" login()"
163
- >
103
+ <div v-if =" !registering" v-once class =" btn btn-info" @click =" login" >
164
104
{{ $t('login') }}
165
105
</div >
166
106
</div >
167
107
</div >
168
108
</template >
169
109
170
- <style lang="scss" scoped>
171
- @import ' ~@/assets/scss/colors.scss' ;
172
-
173
- .form {
174
- margin : 0 auto ;
175
- width : 100% ;
176
- padding-top : 2em ;
177
- padding-bottom : 4em ;
178
- position : relative ;
179
- z-index : 1 ;
180
-
181
- .form-group {
182
- text-align : left ;
183
- font-weight : bold ;
184
- }
185
-
186
- .social-button {
187
- width : 100% ;
188
- height : 100% ;
189
- white-space : inherit ;
190
- text-align : center ;
191
-
192
- .text {
193
- display : inline-block ;
194
- min-height : 0px ;
195
- }
196
- }
197
-
198
- .social-icon {
199
- margin-right : 1em ;
200
- width : 18px ;
201
- height : 18px ;
202
- display : inline-block ;
203
- vertical-align : top ;
204
- margin-top : .1em ;
205
- }
206
-
207
- .apple-icon {
208
- margin-top : -1px ;
209
- }
210
-
211
- small .form-text {
212
- text-align : center ;
213
- }
214
-
215
- .input-error {
216
- margin-top : 0.25em ;
217
- font-weight : normal ;
218
- font-size : 90% ;
219
- width : 100% ;
220
- }
221
- }
222
- </style >
223
-
224
110
<script >
225
111
import hello from ' hellojs' ;
226
112
import debounce from ' lodash/debounce' ;
@@ -240,6 +126,7 @@ export default {
240
126
password: ' ' ,
241
127
passwordConfirm: ' ' ,
242
128
usernameIssues: [],
129
+ emailExistsError: false ,
243
130
};
244
131
245
132
data .icons = Object .freeze ({
@@ -283,69 +170,27 @@ export default {
283
170
return ! this .passwordConfirmValid ;
284
171
},
285
172
},
286
- watch: {
287
- username () {
288
- this .validateUsername (this .username );
289
- },
290
- },
291
- mounted () {
292
- hello .init ({
293
- google: process .env .GOOGLE_CLIENT_ID , // eslint-disable-line
294
- });
295
- },
296
173
methods: {
297
- // eslint-disable-next-line func-names
298
- validateUsername: debounce (function (username ) {
299
- if (username .length < 1 ) {
300
- return ;
301
- }
302
- this .$store .dispatch (' auth:verifyUsername' , {
303
- username: this .username ,
304
- }).then (res => {
305
- if (res .issues !== undefined ) {
306
- this .usernameIssues = res .issues ;
307
- } else {
308
- this .usernameIssues = [];
309
- }
310
- });
311
- }, 500 ),
312
- // @TODO: Abstract hello in to action or lib
313
- async socialAuth (network ) {
314
- if (network === ' apple' ) {
315
- window .location .href = buildAppleAuthUrl ();
316
- } else {
317
- try {
318
- await hello (network).logout ();
319
- } catch (e) {} // eslint-disable-line
320
-
321
- try {
322
- const redirectUrl = ` ${ window .location .protocol } //${ window .location .host } ` ;
323
- const auth = await hello (network).login ({
324
- scope: ' email' ,
325
- redirect_uri: redirectUrl, // eslint-disable-line camelcase
326
- });
174
+ async checkEmailExists () {
175
+ if (! this .emailValid ) return ;
327
176
328
- await this .$store .dispatch (' auth:socialAuth' , {
329
- auth,
330
- });
331
-
332
- await this .finishAuth ();
333
- } catch (err) {
334
- console .error (err); // eslint-disable-line no-console
335
- // logout the user
336
- await hello (network).logout ();
337
- this .socialAuth (network); // login again
338
- }
177
+ try {
178
+ const res = await this .$store .dispatch (' auth:verifyEmail' , { email: this .email });
179
+ this .emailExistsError = ! res .exists ;
180
+ } catch (e) {
181
+ console .error (e); // Handle error
339
182
}
340
183
},
341
184
async register () {
185
+ if (this .emailExistsError || ! this .emailValid ) return ;
186
+
342
187
if (! this .email ) {
343
- window .alert (this .$t (' missingEmail' )); // eslint-disable-line no-alert
188
+ window .alert (this .$t (' missingEmail' ));
344
189
return ;
345
190
}
346
191
347
192
if (this .password !== this .passwordConfirm ) {
348
- window .alert (this .$t (' passwordConfirmationMatch' )); // eslint-disable-line no-alert
193
+ window .alert (this .$t (' passwordConfirmationMatch' ));
349
194
return ;
350
195
}
351
196
@@ -361,7 +206,7 @@ export default {
361
206
} catch (e) {
362
207
if (e .response .data .data && e .response .data .data .errors ) {
363
208
const message = e .response .data .data .errors .map (error => ` ${ error .message } \n ` );
364
- window .alert (message); // eslint-disable-line no-alert
209
+ window .alert (message);
365
210
}
366
211
}
367
212
},
0 commit comments