feat(usernames): verification step during Justin intro for social users

This commit is contained in:
Sabe Jones
2018-10-27 12:37:22 -05:00
parent 5299c8d406
commit bb90dde1b6
9 changed files with 317 additions and 251 deletions

View File

@@ -65,6 +65,7 @@ input, textarea, input.form-control, textarea.form-control {
padding-right: 40px; padding-right: 40px;
background-image: url(~client/assets/svg/for-css/alert.svg); background-image: url(~client/assets/svg/for-css/alert.svg);
background-size: 16px 16px; background-size: 16px 16px;
margin-bottom: 0.1rem;
} }
} }

View File

@@ -5,7 +5,7 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
h3(v-once) {{$t('welcomeTo')}} h3(v-once) {{$t('welcomeTo')}}
.svg-icon.logo(v-html='icons.logoPurple') .svg-icon.logo(v-html='icons.logoPurple')
.avatar-section.row(:class='{"page-2": modalPage === 2}') .avatar-section.row(v-if='modalPage > 1 || user.auth.local.email', :class='{"page-2": modalPage === 2}')
.col-6.offset-3 .col-6.offset-3
.user-creation-bg(v-if='!editing') .user-creation-bg(v-if='!editing')
avatar(:member='user', :avatarOnly='!editing', :class='{"edit-avatar": editing}') avatar(:member='user', :avatarOnly='!editing', :class='{"edit-avatar": editing}')
@@ -187,18 +187,18 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
#extra.section.container.customize-section(v-if='activeTopPage === "extra"') #extra.section.container.customize-section(v-if='activeTopPage === "extra"')
.row.sub-menu .row.sub-menu
.col-3.offset-1.text-center.sub-menu-item(@click='changeSubPage("glasses")', :class='{active: activeSubPage === "glasses"}') .col-3.offset-1.text-center.sub-menu-item(@click='changeSubPage("glasses")', :class='{active: activeSubPage === "glasses"}')
strong(v-once) {{$t('glasses')}} strong(v-once) {{ $t('glasses') }}
.col-4.text-center.sub-menu-item(@click='changeSubPage("wheelchair")', :class='{active: activeSubPage === "wheelchair"}') .col-4.text-center.sub-menu-item(@click='changeSubPage("wheelchair")', :class='{active: activeSubPage === "wheelchair"}')
strong(v-once) {{$t('wheelchair')}} strong(v-once) {{ $t('wheelchair') }}
.col-3.text-center.sub-menu-item(@click='changeSubPage("flower")', :class='{active: activeSubPage === "flower"}') .col-3.text-center.sub-menu-item(@click='changeSubPage("flower")', :class='{active: activeSubPage === "flower"}')
strong(v-once) {{$t('accent')}} strong(v-once) {{ $t('accent') }}
.row.sub-menu(v-if='editing') .row.sub-menu(v-if='editing')
.col-4.text-center.sub-menu-item(@click='changeSubPage("ears")' :class='{active: activeSubPage === "ears"}') .col-4.text-center.sub-menu-item(@click='changeSubPage("ears")' :class='{active: activeSubPage === "ears"}')
strong(v-once) {{$t('animalEars')}} strong(v-once) {{ $t('animalEars') }}
.col-4.text-center.sub-menu-item(@click='changeSubPage("tails")' :class='{active: activeSubPage === "tails"}') .col-4.text-center.sub-menu-item(@click='changeSubPage("tails")' :class='{active: activeSubPage === "tails"}')
strong(v-once) {{$t('animalTails')}} strong(v-once) {{ $t('animalTails') }}
.col-4.text-center.sub-menu-item(@click='changeSubPage("headband")' :class='{active: activeSubPage === "headband"}') .col-4.text-center.sub-menu-item(@click='changeSubPage("headband")' :class='{active: activeSubPage === "headband"}')
strong(v-once) {{$t('headband')}} strong(v-once) {{ $t('headband') }}
#glasses.row(v-if='activeSubPage === "glasses"') #glasses.row(v-if='activeSubPage === "glasses"')
.col-12.customize-options .col-12.customize-options
.option(v-for='option in eyewear', :class='{active: option.active}') .option(v-for='option in eyewear', :class='{active: option.active}')
@@ -305,7 +305,7 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
) )
span.svg-icon.inline.icon-12.color(v-html="icons.pin") span.svg-icon.inline.icon-12.color(v-html="icons.pin")
.purchase-background.set(v-if='!ownsSet("background", set.items) && set.identifier !== "incentiveBackgrounds"' @click='unlock(setKeys("background", set.items))') .purchase-background.set(v-if='!ownsSet("background", set.items) && set.identifier !== "incentiveBackgrounds"' @click='unlock(setKeys("background", set.items))')
span.label Purchase Set span.label {{ $t('purchaseAll') }}
.svg-icon.gem(v-html='icons.gem') .svg-icon.gem(v-html='icons.gem')
span.price 15 span.price 15
.row.customize-menu(v-if='filterBackgrounds') .row.customize-menu(v-if='filterBackgrounds')
@@ -320,7 +320,7 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
.container.interests-section(v-if='modalPage === 3 && !editing') .container.interests-section(v-if='modalPage === 3 && !editing')
.section.row .section.row
.col-12.text-center .col-12.text-center
h2 I want to work on: h2 {{ $t('wantToWorkOn') }}
.section.row .section.row
.col-6 .col-6
.task-option .task-option
@@ -353,28 +353,36 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
input.custom-control-input#self_care(type="checkbox", value='self_care', v-model='taskCategories') input.custom-control-input#self_care(type="checkbox", value='self_care', v-model='taskCategories')
label.custom-control-label(v-once, for="self_care") {{ $t('self_care') }} label.custom-control-label(v-once, for="self_care") {{ $t('self_care') }}
.section.row.justin-message-section(:class='{top: modalPage > 1}', v-if='!editing') .section.d-flex.justify-content-center(:class='{top: modalPage > 1}', v-if='!editing')
.col-12 .justin-section.d-flex.align-items-center
.justin-message.d-flex.flex-column.justify-content-center .featured-label
.featured-label span.rectangle
span.rectangle span.text Justin
span.text Justin span.rectangle
span.rectangle .justin-message
.npc_justin_textbox .corner-decoration(:style="{top: '-2px', right: '-2px'}")
.corner-decoration(:style="{top: '-2px', left: '-2px'}")
.corner-decoration(:style="{bottom: '-2px', right: '-2px'}")
.corner-decoration(:style="{bottom: '-2px', left: '-2px'}")
div(v-if='modalPage === 1') div(v-if='modalPage === 1')
p(v-once) {{$t('justinIntroMessage1')}} p(v-once, v-html='$t("justinIntroMessage1")')
p(v-once) {{$t('justinIntroMessage2')}} p(v-once, v-if='user.auth.local.email') {{ $t('justinIntroMessage2') }}
p(v-once, v-if='!user.auth.local.email') {{ $t('justinIntroMessageUsername') }}
div(v-if='modalPage === 2') div(v-if='modalPage === 2')
p So how would you like to look? Dont worry, you can change this later. p {{ $t('justinIntroMessageAppearance') }}
div(v-if='modalPage === 3') div(v-if='modalPage === 3')
p(v-once) {{$t('justinIntroMessage3')}} p(v-once) {{ $t('justinIntroMessage3') }}
.npc-justin-textbox
.section.mr-5.ml-5(v-if='modalPage === 1 && !user.auth.local.email')
username-form(@usernameConfirmed='modalPage += 1', :avatarIntro='"true"')
.small.text-center(v-html="$t('usernameTOSRequirements')")
.section.container.footer(v-if='!editing') .section.container.footer
.row .row(v-if='!editing && !(modalPage === 1 && !user.auth.local.email)')
.col-3.offset-1.text-center .col-3.offset-1.text-center
div(v-if='modalPage > 1', @click='prev()') div(v-if='modalPage > 1', @click='prev()')
.prev-arrow .prev-arrow
.prev(v-once) {{$t('prev')}} .prev(v-once) {{ $t('prev') }}
.col-4.text-center.circles .col-4.text-center.circles
.circle(:class="{active: modalPage === 1}") .circle(:class="{active: modalPage === 1}")
.circle(:class="{active: modalPage === 2}") .circle(:class="{active: modalPage === 2}")
@@ -390,12 +398,9 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
<style> <style>
/* @TODO do not rely on avatar-modal___BV_modal_body_, /* @TODO do not rely on avatar-modal___BV_modal_body_,
it already changed once when bootstrap-vue reached version 1 */ it already changed once when bootstrap-vue reached version 1 */
.page-2 #avatar-modal___BV_modal_body_ {
margin-top: 9em;
}
.page-2 .modal-content { .page-2 #avatar-modal___BV_modal_body_ {
margin-top: 7em; margin-top: 2rem;
} }
#avatar-modal___BV_modal_body_, #avatar-modal___BV_modal_body_ { #avatar-modal___BV_modal_body_, #avatar-modal___BV_modal_body_ {
@@ -421,6 +426,25 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
position: relative; position: relative;
} }
.corner-decoration {
position: absolute;
width: 6px;
height: 6px;
background-color: #ffbe5d;
border: inherit;
outline: inherit;
}
.small {
color: $gray-200;
}
h3 {
font-size: 20px;
font-weight: normal;
color: $gray-200;
}
.purchase-all { .purchase-all {
margin-bottom: 1em; margin-bottom: 1em;
} }
@@ -444,7 +468,7 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
.logo { .logo {
width: 190px; width: 190px;
margin: 0 auto; margin: 0 auto 1.25em;
} }
.user-creation-bg { .user-creation-bg {
@@ -464,32 +488,22 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
left: 9.2em; left: 9.2em;
} }
.justin-message { .justin-section {
background-image: url('~client/assets/svg/for-css/tutorial-border.svg');
height: 144px;
width: 400px;
padding: 2em;
margin: 0 auto;
position: relative; position: relative;
}
.featured-label { .justin-message {
position: absolute; border-color: #ffa623;
top: -1em; border-style: solid;
border-width: 2px;
.text { outline-color: #b36213;
min-height: auto; outline-style: solid;
color: $white; outline-width: 2px;
} position: relative;
} padding: 2em;
margin: 2px;
.npc_justin_textbox { height: 100%;
position: absolute; width: 400px;
right: 1em;
top: -3.6em;
width: 48px;
height: 52px;
background-image: url('~client/assets/images/justin_textbox.png');
}
p { p {
margin: auto; margin: auto;
@@ -500,15 +514,27 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
} }
} }
.justin-message-section { .npc-justin-textbox {
margin-top: 4em; position: absolute;
margin-bottom: 2em; right: 1rem;
top: -3.1rem;
width: 48px;
height: 48px;
background-image: url('~client/assets/images/justin_textbox.png');
} }
.justin-message-section.top { .featured-label {
position: absolute; position: absolute;
top: -16em; top: -1rem;
left: 3.5em; left: 1.5rem;
border-radius: 2px;
margin: auto;
.text {
font-size: 12px;
min-height: auto;
color: $white;
}
} }
.circles { .circles {
@@ -865,6 +891,7 @@ import get from 'lodash/get';
import groupBy from 'lodash/groupBy'; import groupBy from 'lodash/groupBy';
import { mapState } from 'client/libs/store'; import { mapState } from 'client/libs/store';
import avatar from './avatar'; import avatar from './avatar';
import usernameForm from './settings/usernameForm';
import { getBackgroundShopSets } from '../../common/script/libs/shops'; import { getBackgroundShopSets } from '../../common/script/libs/shops';
import unlock from '../../common/script/ops/unlock'; import unlock from '../../common/script/ops/unlock';
import buy from '../../common/script/ops/buy/buy'; import buy from '../../common/script/ops/buy/buy';
@@ -1022,6 +1049,7 @@ export default {
components: { components: {
avatar, avatar,
toggleSwitch, toggleSwitch,
usernameForm,
}, },
mounted () { mounted () {
if (this.editing) this.modalPage = 2; if (this.editing) this.modalPage = 2;

View File

@@ -0,0 +1,216 @@
<template lang="pug">
div
.form-group
.d-flex.align-items-center
label.mr-3(for='displayName') {{ $t('displayName') }}
.flex-grow-1
input#displayName.form-control(
type='text',
:placeholder="$t('newDisplayName')",
v-model='temporaryDisplayName',
@blur='restoreEmptyDisplayName()',
:class='{"is-invalid input-invalid": displayNameInvalid, "input-valid": displayNameValid, "text-darker": temporaryDisplayName.length > 0}')
.mb-3(v-if="displayNameIssues.length > 0")
.input-error.text-center(v-for="issue in displayNameIssues") {{ issue }}
.form-group
.d-flex.align-items-center
label.mr-3(for='username') {{ $t('username') }}
.flex-grow-1
.input-group-prepend.input-group-text @
input#username.form-control(
type='text',
:placeholder="$t('newUsername')",
v-model='temporaryUsername',
@blur='restoreEmptyUsername()',
:class='{"is-invalid input-invalid": usernameInvalid, "input-valid": usernameValid, "text-darker": temporaryUsername.length > 0}')
.mb-3(v-if="usernameIssues.length > 0")
.input-error.text-center(v-for="issue in usernameIssues") {{ issue }}
.small.text-center(v-if='!avatarIntro') {{ $t('usernameLimitations') }}
.row.justify-content-center
button.btn.btn-primary(type='submit', @click='submitNames()' :disabled='usernameCannotSubmit') {{ $t(avatarIntro ? 'getStarted' : 'saveAndConfirm') }}
</template>
<style lang="scss" scoped>
@import '~client/assets/scss/colors.scss';
button {
margin: 0.25rem auto 1rem;
}
.col-3 {
padding-right: 0rem;
}
.form-group {
background-color: $gray-700;
border-radius: 2px;
border: solid 1px $gray-500;
}
input {
border: 0px;
}
.input-error {
color: $red-50;
font-size: 90%;
width: 100%;
}
.input-group-prepend {
margin-right: 0px;
}
.input-group-text {
border: 0px;
background-color: $white;
color: $gray-300;
padding: 0rem 0rem 0rem 0.75rem;
}
label {
color: $gray-100;
font-weight: bold;
margin-bottom: 0rem;
margin-left: 1rem;
min-width: 90px;
}
.small {
color: $gray-200;
}
.text-darker {
color: $gray-50;
}
#username {
padding-left: 0.25rem;
}
</style>
<script>
import axios from 'axios';
import debounce from 'lodash/debounce';
import { mapState } from 'client/libs/store';
export default {
computed: {
...mapState({
user: 'user.data',
}),
displayNameInvalid () {
if (this.temporaryDisplayName.length < 1) return false;
return !this.displayNameValid;
},
displayNameValid () {
if (this.temporaryDisplayName.length < 1) return false;
return this.displayNameIssues.length === 0;
},
usernameCannotSubmit () {
if (this.temporaryUsername.length < 1) return true;
return !this.usernameValid || !this.displayNameValid;
},
usernameInvalid () {
if (this.temporaryUsername.length < 1) return false;
return !this.usernameValid;
},
usernameValid () {
if (this.temporaryUsername.length < 1) return false;
return this.usernameIssues.length === 0;
},
},
data () {
return {
displayNameIssues: [],
temporaryDisplayName: '',
temporaryUsername: '',
usernameIssues: [],
};
},
methods: {
async close () {
this.$root.$emit('habitica::resync-requested');
await this.$store.dispatch('user:fetch', {forceLoad: true});
this.$root.$emit('habitica::resync-completed');
if (this.avatarIntro) {
this.$emit('usernameConfirmed');
} else {
this.$root.$emit('bv::hide::modal', 'verify-username');
this.$router.go(0);
}
},
restoreEmptyDisplayName () {
if (this.temporaryDisplayName.length < 1) {
this.temporaryDisplayName = this.user.profile.name;
}
},
restoreEmptyUsername () {
if (this.temporaryUsername.length < 1) {
this.temporaryUsername = this.user.auth.local.username;
}
},
async submitNames () {
if (this.temporaryDisplayName !== this.user.profile.name) {
await axios.put('/api/v4/user/', {'profile.name': this.temporaryDisplayName});
}
await axios.put('/api/v4/user/auth/update-username', {username: this.temporaryUsername});
this.close();
},
validateDisplayName: debounce(function checkName (displayName) {
if (displayName.length <= 1 || displayName === this.user.profile.name) {
this.displayNameIssues = [];
return;
}
this.$store.dispatch('auth:verifyDisplayName', {
displayName,
}).then(res => {
if (res.issues !== undefined) {
this.displayNameIssues = res.issues;
} else {
this.displayNameIssues = [];
}
});
}, 500),
validateUsername: debounce(function checkName (username) {
if (username.length <= 1 || username === this.user.auth.local.username) {
this.usernameIssues = [];
return;
}
this.$store.dispatch('auth:verifyUsername', {
username,
}).then(res => {
if (res.issues !== undefined) {
this.usernameIssues = res.issues;
} else {
this.usernameIssues = [];
}
});
}, 500),
},
mounted () {
this.temporaryDisplayName = this.user.profile.name;
this.temporaryUsername = this.user.auth.local.username;
},
props: {
avatarIntro: {
type: Boolean,
default: false,
},
},
watch: {
temporaryDisplayName: {
handler () {
this.validateDisplayName(this.temporaryDisplayName);
},
deep: true,
},
temporaryUsername: {
handler () {
this.validateUsername(this.temporaryUsername);
},
deep: true,
},
},
};
</script>

View File

@@ -10,36 +10,7 @@
div.nametag-header(v-html='icons.helloNametag') div.nametag-header(v-html='icons.helloNametag')
h2.text-center {{ $t('usernameTime') }} h2.text-center {{ $t('usernameTime') }}
p.text-center(v-html="$t('usernameInfo')") p.text-center(v-html="$t('usernameInfo')")
.form-group username-form
.row.align-items-center
.col-3
label(for='displayName') {{ $t('displayName') }}
.col-9
input#displayName.form-control(
type='text',
:placeholder="$t('newDisplayName')",
v-model='temporaryDisplayName',
@blur='restoreEmptyDisplayName()',
:class='{"is-invalid input-invalid": displayNameInvalid, "input-valid": displayNameValid, "text-darker": temporaryDisplayName.length > 0}')
.mb-3(v-if="displayNameIssues.length > 0")
.input-error.text-center(v-for="issue in displayNameIssues") {{ issue }}
.form-group
.row.align-items-center
.col-3
label(for='username') {{ $t('username') }}
.col-9
.input-group-prepend.input-group-text @
input#username.form-control(
type='text',
:placeholder="$t('newUsername')",
v-model='temporaryUsername',
@blur='restoreEmptyUsername()',
:class='{"is-invalid input-invalid": usernameInvalid, "input-valid": usernameValid, "text-darker": temporaryUsername.length > 0}')
.mb-3(v-if="usernameIssues.length > 0")
.input-error.text-center(v-for="issue in usernameIssues") {{ issue }}
.small.text-center {{ $t('usernameLimitations') }}
.row.justify-content-center
button.btn.btn-primary(type='submit', @click='submitNames()' :disabled='usernameCannotSubmit') {{ $t('saveAndConfirm') }}
.scene_veteran_pets.center-block .scene_veteran_pets.center-block
.small.text-center.mb-3 {{ $t('verifyUsernameVeteranPet') }} .small.text-center.mb-3 {{ $t('verifyUsernameVeteranPet') }}
.small.text-center.tos-footer(v-html="$t('usernameTOSRequirements')") .small.text-center.tos-footer(v-html="$t('usernameTOSRequirements')")
@@ -62,57 +33,15 @@
<style lang="scss" scoped> <style lang="scss" scoped>
@import '~client/assets/scss/colors.scss'; @import '~client/assets/scss/colors.scss';
button {
margin: 1rem;
}
.center-block { .center-block {
margin: 0 auto 1em auto; margin: 0 auto 1em auto;
} }
.col-3 {
padding-right: 0rem;
}
.form-group {
background-color: $gray-700;
border-radius: 2px;
border: solid 1px $gray-500;
}
h2 { h2 {
color: $purple-200; color: $purple-200;
margin-top: 1.5rem; margin-top: 1.5rem;
} }
input {
border: 0px;
}
.input-error {
color: $red-50;
font-size: 90%;
width: 100%;
}
.input-group-prepend {
margin-right: 0px;
}
.input-group-text {
border: 0px;
background-color: $white;
color: $gray-300;
padding: 0rem 0rem 0rem 0.75rem;
}
label {
color: $gray-100;
font-weight: bold;
margin-bottom: 0rem;
margin-left: 1rem;
}
.nametag-header { .nametag-header {
background-color: $gray-700; background-color: $gray-700;
border-radius: 0.3rem 0.3rem 0rem 0rem; border-radius: 0.3rem 0.3rem 0rem 0rem;
@@ -122,17 +51,13 @@
} }
p { p {
color: #686274; color: $gray-100;
} }
.small { .small {
color: $gray-200; color: $gray-200;
} }
.text-darker {
color: $gray-50;
}
.tos-footer { .tos-footer {
background-color: $gray-700; background-color: $gray-700;
border-radius: 0rem 0rem 0.3rem 0.3rem; border-radius: 0rem 0rem 0.3rem 0.3rem;
@@ -140,129 +65,22 @@
margin-right: -3rem; margin-right: -3rem;
padding: 1rem 4rem 1rem 4rem; padding: 1rem 4rem 1rem 4rem;
} }
#username {
padding-left: 0.25rem;
}
</style> </style>
<script> <script>
import axios from 'axios';
import debounce from 'lodash/debounce';
import helloNametag from 'assets/svg/hello-habitican.svg'; import helloNametag from 'assets/svg/hello-habitican.svg';
import { mapState } from 'client/libs/store'; import usernameForm from './usernameForm';
export default { export default {
computed: { components: {
...mapState({ usernameForm,
user: 'user.data',
}),
displayNameInvalid () {
if (this.temporaryDisplayName.length < 1) return false;
return !this.displayNameValid;
},
displayNameValid () {
if (this.temporaryDisplayName.length < 1) return false;
return this.displayNameIssues.length === 0;
},
usernameCannotSubmit () {
if (this.temporaryUsername.length < 1) return true;
return !this.usernameValid || !this.displayNameValid;
},
usernameInvalid () {
if (this.temporaryUsername.length < 1) return false;
return !this.usernameValid;
},
usernameValid () {
if (this.temporaryUsername.length < 1) return false;
return this.usernameIssues.length === 0;
},
}, },
data () { data () {
return { return {
icons: Object.freeze({ icons: Object.freeze({
helloNametag, helloNametag,
}), }),
displayNameIssues: [],
temporaryDisplayName: '',
temporaryUsername: '',
usernameIssues: [],
}; };
}, },
methods: {
async submitNames () {
if (this.temporaryDisplayName !== this.user.profile.name) {
await axios.put('/api/v4/user/', {'profile.name': this.temporaryDisplayName});
}
await axios.put('/api/v4/user/auth/update-username', {username: this.temporaryUsername});
this.close();
},
async close () {
this.$root.$emit('habitica::resync-requested');
await this.$store.dispatch('user:fetch', {forceLoad: true});
this.$root.$emit('habitica::resync-completed');
this.$root.$emit('bv::hide::modal', 'verify-username');
this.$router.go(0);
},
restoreEmptyDisplayName () {
if (this.temporaryDisplayName.length < 1) {
this.temporaryDisplayName = this.user.profile.name;
}
},
restoreEmptyUsername () {
if (this.temporaryUsername.length < 1) {
this.temporaryUsername = this.user.auth.local.username;
}
},
validateDisplayName: debounce(function checkName (displayName) {
if (displayName.length <= 1 || displayName === this.user.profile.name) {
this.displayNameIssues = [];
return;
}
this.$store.dispatch('auth:verifyDisplayName', {
displayName,
}).then(res => {
if (res.issues !== undefined) {
this.displayNameIssues = res.issues;
} else {
this.displayNameIssues = [];
}
});
}, 500),
validateUsername: debounce(function checkName (username) {
if (username.length <= 1 || username === this.user.auth.local.username) {
this.usernameIssues = [];
return;
}
this.$store.dispatch('auth:verifyUsername', {
username,
}).then(res => {
if (res.issues !== undefined) {
this.usernameIssues = res.issues;
} else {
this.usernameIssues = [];
}
});
}, 500),
},
mounted () {
this.temporaryDisplayName = this.user.profile.name;
this.temporaryUsername = this.user.auth.local.username;
},
watch: {
temporaryDisplayName: {
handler () {
this.validateDisplayName(this.temporaryDisplayName);
},
deep: true,
},
temporaryUsername: {
handler () {
this.validateUsername(this.temporaryUsername);
},
deep: true,
},
},
}; };
</script> </script>

View File

@@ -7,7 +7,7 @@
"noPhoto": "This Habitican hasn't added a photo.", "noPhoto": "This Habitican hasn't added a photo.",
"other": "Other", "other": "Other",
"fullName": "Full Name", "fullName": "Full Name",
"displayName": "Display Name", "displayName": "Display name",
"changeDisplayName": "Change Display Name", "changeDisplayName": "Change Display Name",
"newDisplayName": "New Display Name", "newDisplayName": "New Display Name",
"displayPhoto": "Photo", "displayPhoto": "Photo",

View File

@@ -329,7 +329,7 @@
"joinToday": "Join Habitica Today", "joinToday": "Join Habitica Today",
"featuredIn": "Featured in", "featuredIn": "Featured in",
"signup": "Sign Up", "signup": "Sign Up",
"getStarted": "Get Started", "getStarted": "Get Started!",
"mobileApps": "Mobile Apps", "mobileApps": "Mobile Apps",
"learnMore": "Learn More" "learnMore": "Learn More"
} }

View File

@@ -254,6 +254,7 @@
"resetFilters": "Clear all filters", "resetFilters": "Clear all filters",
"applyFilters": "Apply Filters", "applyFilters": "Apply Filters",
"wantToWorkOn": "I want to work on:",
"categories": "Categories", "categories": "Categories",
"habiticaOfficial": "Habitica Official", "habiticaOfficial": "Habitica Official",
"animals": "Animals", "animals": "Animals",

View File

@@ -6,9 +6,11 @@
"welcomeTo": "Welcome to", "welcomeTo": "Welcome to",
"welcomeBack": "Welcome back!", "welcomeBack": "Welcome back!",
"justin": "Justin", "justin": "Justin",
"justinIntroMessage1": "Hello there! You must be new here. My name is Justin, your guide to Habitica.", "justinIntroMessage1": "Hello there! You must be new here. My name is <strong>Justin</strong>, and I'll be your guide in Habitica.",
"justinIntroMessage2": "To start, you'll need to create an avatar.", "justinIntroMessage2": "To start, you'll need to create an avatar.",
"justinIntroMessage3": "Great! Now, what are you interested in working on throughout this journey?", "justinIntroMessage3": "Great! Now, what are you interested in working on throughout this journey?",
"justinIntroMessageUsername": "Before we begin, lets figure out what to call you. Below youll find a display name and username Ive generated for you. After youve picked a display name and username, well get started by creating an avatar!",
"justinIntroMessageAppearance": "So how would you like to look? Dont worry, you can change this later.",
"introTour": "Here we are! I've filled out some Tasks for you based on your interests, so you can get started right away. Click a Task to edit or add new Tasks to fit your routine!", "introTour": "Here we are! I've filled out some Tasks for you based on your interests, so you can get started right away. Click a Task to edit or add new Tasks to fit your routine!",
"prev": "Prev", "prev": "Prev",
"next": "Next", "next": "Next",

View File

@@ -210,7 +210,7 @@
"haveCouponCode": "Do you have a coupon code?", "haveCouponCode": "Do you have a coupon code?",
"subscriptionAlreadySubscribedLeadIn": "Thanks for subscribing!", "subscriptionAlreadySubscribedLeadIn": "Thanks for subscribing!",
"subscriptionAlreadySubscribed1": "To see your subscription details and cancel, renew, or change your subscription, please go to <a href='/user/settings/subscription'>User icon &gt; Settings &gt; Subscription</a>.", "subscriptionAlreadySubscribed1": "To see your subscription details and cancel, renew, or change your subscription, please go to <a href='/user/settings/subscription'>User icon &gt; Settings &gt; Subscription</a>.",
"purchaseAll": "Purchase All", "purchaseAll": "Purchase Set",
"gemsPurchaseNote": "Subscribers can buy gems for gold in the Market! For easy access, you can also pin the gem to your Rewards column.", "gemsPurchaseNote": "Subscribers can buy gems for gold in the Market! For easy access, you can also pin the gem to your Rewards column.",
"gemsRemaining": "gems remaining", "gemsRemaining": "gems remaining",
"notEnoughGemsToBuy": "You are unable to buy that amount of gems" "notEnoughGemsToBuy": "You are unable to buy that amount of gems"