Skip to content

Commit 468e207

Browse files
committed
Added Validiation in registration & login section
1 parent f1993db commit 468e207

File tree

2 files changed

+73
-239
lines changed

2 files changed

+73
-239
lines changed

website/client/src/components/auth/authForm.vue

+35-190
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
<template>
22
<div class="form">
3+
<div v-if="emailExistsError" class="input-error">{{ $t('emailDoesNotExist') }}</div>
34
<div class="form-group row text-center">
45
<div class="col-12">
56
<div
67
class="btn btn-secondary social-button"
78
@click="socialAuth('google')"
89
>
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>
1311
<span>{{ registering
1412
? $t('signUpWithSocial', {social: 'Google'})
1513
: $t('loginWithSocial', {social: 'Google'}) }}</span>
@@ -22,24 +20,15 @@
2220
class="btn btn-secondary social-button"
2321
@click="socialAuth('apple')"
2422
>
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>
2924
<span>{{ registering
3025
? $t('signUpWithSocial', {social: 'Apple'})
3126
: $t('loginWithSocial', {social: 'Apple'}) }}</span>
3227
</div>
3328
</div>
3429
</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>
4332
<input
4433
id="usernameInput"
4534
v-model="username"
@@ -48,22 +37,12 @@
4837
:placeholder="$t('usernamePlaceholder')"
4938
:class="{'input-valid': usernameValid, 'input-invalid': usernameInvalid}"
5039
>
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">
5641
{{ issue }}
5742
</div>
5843
</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>
6746
<input
6847
id="usernameInput"
6948
v-model="username"
@@ -72,34 +51,21 @@
7251
:placeholder="$t('emailOrUsername')"
7352
>
7453
</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>
8356
<input
8457
id="emailInput"
8558
v-model="email"
8659
class="form-control"
8760
type="email"
8861
:placeholder="$t('emailPlaceholder')"
89-
:class="{'input-invalid': emailInvalid, 'input-valid': emailValid}"
62+
:class="{'input-invalid': emailInvalid || emailExistsError, 'input-valid': emailValid}"
63+
@blur="checkEmailExists"
9064
>
9165
</div>
9266
<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>
10369
<input
10470
id="passwordInput"
10571
v-model="password"
@@ -108,24 +74,15 @@
10874
:placeholder="$t(registering ? 'passwordPlaceholder' : 'password')"
10975
:class="{
11076
'input-valid': registering ? passwordValid : false,
111-
'input-invalid': registering ? passwordInvalid: false,
77+
'input-invalid': registering ? passwordInvalid : false,
11278
}"
11379
>
114-
<div
115-
v-if="passwordInvalid && registering"
116-
class="input-error"
117-
>
80+
<div v-if="passwordInvalid && registering" class="input-error">
11881
{{ $t('minPasswordLength') }}
11982
</div>
12083
</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>
12986
<input
13087
id="confirmPasswordInput"
13188
v-model="passwordConfirm"
@@ -134,93 +91,22 @@
13491
:placeholder="$t('confirmPasswordPlaceholder')"
13592
:class="{'input-invalid': passwordConfirmInvalid, 'input-valid': passwordConfirmValid}"
13693
>
137-
<div
138-
v-if="passwordConfirmInvalid"
139-
class="input-error"
140-
>
94+
<div v-if="passwordConfirmInvalid" class="input-error">
14195
{{ $t('passwordConfirmationMatch') }}
14296
</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>
14898
</div>
14999
<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">
156101
{{ $t('joinHabitica') }}
157102
</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">
164104
{{ $t('login') }}
165105
</div>
166106
</div>
167107
</div>
168108
</template>
169109

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-
224110
<script>
225111
import hello from 'hellojs';
226112
import debounce from 'lodash/debounce';
@@ -240,6 +126,7 @@ export default {
240126
password: '',
241127
passwordConfirm: '',
242128
usernameIssues: [],
129+
emailExistsError: false,
243130
};
244131
245132
data.icons = Object.freeze({
@@ -283,69 +170,27 @@ export default {
283170
return !this.passwordConfirmValid;
284171
},
285172
},
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-
},
296173
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;
327176
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
339182
}
340183
},
341184
async register () {
185+
if (this.emailExistsError || !this.emailValid) return;
186+
342187
if (!this.email) {
343-
window.alert(this.$t('missingEmail')); // eslint-disable-line no-alert
188+
window.alert(this.$t('missingEmail'));
344189
return;
345190
}
346191
347192
if (this.password !== this.passwordConfirm) {
348-
window.alert(this.$t('passwordConfirmationMatch')); // eslint-disable-line no-alert
193+
window.alert(this.$t('passwordConfirmationMatch'));
349194
return;
350195
}
351196
@@ -361,7 +206,7 @@ export default {
361206
} catch (e) {
362207
if (e.response.data.data && e.response.data.data.errors) {
363208
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);
365210
}
366211
}
367212
},

0 commit comments

Comments
 (0)