diff --git a/website/client/components/achievements/welcome.vue b/website/client/components/achievements/welcome.vue
new file mode 100644
index 0000000000..f4a0568cd2
--- /dev/null
+++ b/website/client/components/achievements/welcome.vue
@@ -0,0 +1,48 @@
+
+ b-modal#welcome(:title="$t('welcomeToHabit')", size='lg', :hide-footer="true")
+ .modal-body.container-fluid
+ .row
+ .col-4.col-centered
+ span(style='display:flex')
+ h1
+ | ①
+ h3(style='margin:auto auto auto .5em') {{ $t('welcome1') }}
+ .welcome_basic_avatars(style='margin: 1.5em auto 1.5em')
+ h4 {{ $t('welcome1notes') }}
+ .col-4.col-centered
+ span(style='display:flex')
+ h1
+ | ②
+ h3(style='margin:.3em auto auto .5em') {{ $t('welcome2') }}
+ .welcome_sample_tasks(style='margin: 2.5em auto 1.5em')
+ h4 {{ $t('welcome2notes') }}
+ .col-4.col-centered
+ span(style='display:flex')
+ h1
+ | ③
+ h3(style='margin:auto auto auto .5em') {{ $t('welcome3') }}
+ .welcome_promo_party(style='margin: 1em auto 1em')
+ h4 {{ $t('welcome3notes') }}
+ .modal-footer.text-center(style='margin-top:0')
+ .col-3
+ .col-6
+ button.btn.btn-primary.btn-lg.flex-column(@click='ready()') {{ $t('imReady') }}
+ .col-3
+
+
+
diff --git a/website/client/components/appFooter.vue b/website/client/components/appFooter.vue
index 170e9cb785..72907266de 100644
--- a/website/client/components/appFooter.vue
+++ b/website/client/components/appFooter.vue
@@ -1,46 +1,72 @@
-
+
.row
+ modify-inventory
footer.container-fluid
.row
.col-2
- h3 iOS App
- h3 Android App
+ h3
+ a(href='https://itunes.apple.com/us/app/habitica/id994882113?ls=1&mt=8', target='_blank') iOS App
+ h3
+ a(href='https://play.google.com/store/apps/details?id=com.habitrpg.android.habitica', target='_blank') Android App
.col-2
h3 Company
ul
- li How it Works
- li Blog
- li Tumblr
- li FAQ
- li News
- li Merchandis
- li Press Kit
- li Contact Us
+ li
+ a(href='/static/features') How it Works
+ li
+ a(href='https://habitica.wordpress.com/') Blog
+ li
+ a(href='http://blog.habitrpg.com/') Tumblr
+ li
+ a(href='/static/faq') FAQ
+ li
+ a(href='/static/old-news') News
+ li
+ a(href='/static/merch') Merchandise
+ li
+ a(href='/static/press-kit') Press Kit
+ li
+ a(href='/static/contact') Contact Us
.col-2
h3 Community
ul
- li Community Guidelines
- li Submit a Bug
- li Request a Feature
- li Add-Ons & Extensions
- li Forum
- li Kickstarter
- li Facebook
- li Reddit
+ li
+ a(href='/static/community-guidelines') Community Guidelines
+ li
+ router-link(to='/groups/a29da26b-37de-4a71-b0c6-48e72a900dac') Submit a Bug
+ li
+ a(href='https://trello.com/c/odmhIqyW/440-read-first-table-of-contents', target='_blank') Request a Feature
+ li
+ a(href='http://habitica.wikia.com/wiki/Extensions,_Add-Ons,_and_Customizations', target='_blank') Add-Ons & Extensions
+ li
+ a(href='http://habitica.wikia.com/wiki/Special:Forum', target='_blank') Forum
+ li
+ a(href='https://www.kickstarter.com/projects/lefnire/habitrpg-mobile', target='_blank') Kickstarter
+ li
+ a(href='https://www.facebook.com/Habitica', target='_blank') Facebook
+ li
+ a(href='https://www.reddit.com/r/habitrpg/', target='_blank') Reddit
.col-6
.row
.col-6
h3 Developers
ul
- li APIv3
- li Data Display Tool
- li Guidance for Blacksmiths
- li The Forge - Developer Blog
+ li
+ a(href='/apidoc', target='_blank') APIv3
+ li
+ a(href='http://data.habitrpg.com/?uuid=', target='_blank') Data Display Tool
+ li
+ a(href='http://habitica.wikia.com/wiki/Guidance_for_Blacksmiths', target='_blank') Guidance for Blacksmiths
+ li
+ a(href='http://devs.habitica.com/', target='_blank') The Forge - Developer Blog
.col-6
h3 Social
- .social-circle Twitter
- .social-circle Instagram
- .social-circle Facebook
+ .social-circle
+ a(href='https://twitter.com/habitica', target='_blank') Twitter
+ .social-circle
+ a(href='https://www.instagram.com/habitica/', target='_blank') Instagram
+ .social-circle
+ a(href='https://www.facebook.com/Habitica', target='_blank') Facebook
.row
.col-10
| We’re an open source project that depends on our users for support. The money you donate helps us keep the servers running, maintain a small staff, develop new features, and provide incentives for our volunteers.
@@ -56,6 +82,23 @@
.col-4.text-right
span Privacy Policy
span Terms of Use
+ .row
+ h4 Debug
+ .btn-group-vertical
+ a.btn.btn-default(@click='setHealthLow()') Health = 1
+ a.btn.btn-default(@click='addMissedDay(1)') +1 Missed Day
+ a.btn.btn-default(@click='addMissedDay(2)') +2 Missed Days
+ a.btn.btn-default(@click='addMissedDay(8)') +8 Missed Days
+ a.btn.btn-default(@click='addMissedDay(32)') +32 Missed Days
+ a.btn.btn-default(@click='addTenGems()') +10 Gems
+ a.btn.btn-default(@click='addHourglass()') +1 Mystic Hourglass
+ a.btn.btn-default(@click='addGold()') +500GP
+ a.btn.btn-default(@click='addMana()') +MP
+ a.btn.btn-default(@click='addLevelsAndGold()') +Exp +GP +MP
+ a.btn.btn-default(@click='addOneLevel()') +1 Level
+ a.btn.btn-default(@click='addQuestProgress()' tooltip="+1000 to boss quests. 300 items to collection quests") Quest Progress Up
+ a.btn.btn-default(@click='makeAdmin()') Make Admin
+ a.btn.btn-default(@click='openModifyInventoryModal()') Modify Inventory
diff --git a/website/client/components/appHeader.vue b/website/client/components/appHeader.vue
index e496347bd9..5b42e8d5a5 100644
--- a/website/client/components/appHeader.vue
+++ b/website/client/components/appHeader.vue
@@ -1,5 +1,6 @@
-#app-header.row(:class='{sticky: user.preferences.stickyHeader}')
+#app-header.row(:class='{sticky: user.preferences.stickyHeader}', v-if='showHeader')
+ create-party-modal
members-modal(:group='user.party', :hide-badge="true")
member-details(:member="user", @click="$router.push({name: 'avatar'})")
.view-party(v-if="user.party && user.party._id")
@@ -102,6 +103,10 @@ export default {
user: 'user:data',
partyMembers: 'party:members',
}),
+ showHeader () {
+ if (this.$store.state.hideHeader) return false;
+ return true;
+ },
},
methods: {
...mapActions({
@@ -115,7 +120,7 @@ export default {
}
},
openPartyModal () {
- this.$root.$emit('show::modal', 'members-modal');
+ this.$root.$emit('show::modal', 'create-party-modal');
},
},
created () {
diff --git a/website/client/components/appMenu.vue b/website/client/components/appMenu.vue
index 081a892d79..1fe8de3e52 100644
--- a/website/client/components/appMenu.vue
+++ b/website/client/components/appMenu.vue
@@ -33,7 +33,7 @@ div
a.nav-link(v-once) {{ $t('group') }}
router-link.nav-item(tag="li", :to="{name: 'myChallenges'}", exact)
a.nav-link(v-once) {{ $t('challenges') }}
- router-link.nav-item.dropdown(tag="li", to="/help", :class="{'active': $route.path.startsWith('/help')}")
+ router-link.nav-item.dropdown(tag="li", to="/help", :class="{'active': $route.path.startsWith('/help')}", :to="{name: 'faq'}")
a.nav-link(v-once) {{ $t('help') }}
.dropdown-menu
router-link.dropdown-item(:to="{name: 'faq'}") {{ $t('faq') }}
diff --git a/website/client/components/auth/registerLogin.vue b/website/client/components/auth/registerLogin.vue
index 7be5b3e007..f242ba3bcc 100644
--- a/website/client/components/auth/registerLogin.vue
+++ b/website/client/components/auth/registerLogin.vue
@@ -13,11 +13,11 @@
.col-6
.btn.btn-secondary.social-button(@click='socialAuth("facebook")', v-once)
.svg-icon.social-icon(v-html="icons.facebookIcon")
- | {{this.registering ? $t('signUpWithSocial', {social: 'Facebook'}) : $t('loginWithSocial', {social: 'Facebook'})}}
+ span {{this.registering ? $t('signUpWithSocial', {social: 'Facebook'}) : $t('loginWithSocial', {social: 'Facebook'})}}
.col-6
.btn.btn-secondary.social-button(@click='socialAuth("google")', v-once)
.svg-icon.social-icon(v-html="icons.googleIcon")
- | {{this.registering ? $t('signUpWithSocial', {social: 'Google'}) : $t('loginWithSocial', {social: 'Google'})}}
+ span {{this.registering ? $t('signUpWithSocial', {social: 'Google'}) : $t('loginWithSocial', {social: 'Google'})}}
.form-group
label(for='usernameInput', v-once) {{$t('username')}}
input#usernameInput.form-control(type='text', :placeholder='$t("usernamePlaceholder")', v-model='username')
@@ -30,10 +30,14 @@
.form-group(v-if='registering')
label(for='confirmPasswordInput', v-once) {{$t('confirmPassword')}}
input#confirmPasswordInput.form-control(type='password', :placeholder='$t("confirmPasswordPlaceholder")', v-model='passwordConfirm')
- small.form-text(v-once) {{$t('termsAndAgreement')}}
+ small.form-text(v-once, v-html="$t('termsAndAgreement')")
.text-center
.btn.btn-info(@click='register()', v-if='registering', v-once) {{$t('joinHabitica')}}
.btn.btn-info(@click='login()', v-if='!registering', v-once) {{$t('login')}}
+ router-link(tag="li", :to="{name: 'login'}", v-if='registering', exact)
+ a(v-once) {{ $t('login') }}
+ router-link(tag="li", :to="{name: 'register'}", v-if='!registering', exact)
+ a(v-once) {{ $t('joinHabitica') }}
#bottom-background
.seamless_mountains_demo_repeat
@@ -58,13 +62,14 @@
.gryphon {
width: 63.2px;
height: 69.4px;
+ color: $white;
+ margin: 0 auto;
}
.habitica-logo {
width: 144px;
height: 31px;
- margin-top: 2em;
- margin-bottom: 2em;
+ margin: 2em auto;
}
label {
@@ -107,6 +112,8 @@
.social-icon {
margin-right: 1em;
width: 13px;
+ display: inline-block;
+ height: 13px;
}
}
@@ -157,7 +164,6 @@ export default {
email: '',
password: '',
passwordConfirm: '',
- registering: true,
};
data.icons = Object.freeze({
@@ -169,11 +175,15 @@ export default {
return data;
},
+ computed: {
+ registering () {
+ if (this.$route.path.startsWith('/login')) {
+ return false;
+ }
+ return true;
+ },
+ },
mounted () {
- if (this.$route.path.startsWith('/login')) {
- this.registering = false;
- }
-
hello.init({
facebook: '',
// windows: WINDOWS_CLIENT_ID,
@@ -205,7 +215,7 @@ export default {
passwordConfirm: this.passwordConfirm,
});
- this.$router.go('/tasks');
+ this.$router.push('/tasks');
},
async login () {
await this.$store.dispatch('auth:login', {
@@ -214,7 +224,7 @@ export default {
password: this.password,
});
- this.$router.go('/tasks');
+ this.$router.push('/tasks');
},
async socialAuth (network) {
let auth = await hello(network).login({scope: 'email'});
@@ -223,7 +233,7 @@ export default {
auth,
});
- this.$router.go('/tasks');
+ this.$router.push('/tasks');
},
},
};
diff --git a/website/client/components/challenges/challengeDetail.vue b/website/client/components/challenges/challengeDetail.vue
index dddcfc28bc..f683705aaf 100644
--- a/website/client/components/challenges/challengeDetail.vue
+++ b/website/client/components/challenges/challengeDetail.vue
@@ -1,6 +1,6 @@
.row
- challenge-modal(:challenge='challenge')
+ challenge-modal(:challenge='challenge', v-on:updatedChallenge='updatedChallenge')
close-challenge-modal
.col-8.standard-page
@@ -10,17 +10,17 @@
div
strong(v-once) {{$t('createdBy')}}
span {{challenge.author}}
- strong.margin-left(v-once)
+ // @TODO: Implement in V2 strong.margin-left(v-once)
.svg-icon.calendar-icon(v-html="icons.calendarIcon")
| {{$t('endDate')}}
span {{challenge.endDate}}
.tags
span.tag(v-for='tag in challenge.tags') {{tag}}
.col-4
- .box
+ .box(@click="showMemberModal()")
.svg-icon.member-icon(v-html="icons.memberIcon")
| {{challenge.memberCount}}
- .details(v-once) {{$t('participants')}}
+ .details(v-once) {{$t('participantsTitle')}}
.box
.svg-icon.gem-icon(v-html="icons.gemIcon")
| {{challenge.prize}}
@@ -149,6 +149,7 @@ export default {
calendarIcon,
}),
challenge: {},
+ members: [],
};
},
computed: {
@@ -157,16 +158,18 @@ export default {
return this.user.challenges.indexOf(this.challenge._id) !== -1;
},
isLeader () {
- if (!this.leader) return false;
- return this.user._id === this.leader.id;
+ if (!this.challenge.leader) return false;
+ return this.user._id === this.challenge.leader._id;
},
},
- mounted () {
- this.getChallenge();
+ async mounted () {
+ this.challenge = await this.$store.dispatch('challenges:getChallenge', {challengeId: this.challengeId});
+ this.members = await this.$store.dispatch('members:getChallengeMembers', {challengeId: this.challengeId});
},
methods: {
- async getChallenge () {
- this.challenge = await this.$store.dispatch('challenges:getChallenge', {challengeId: this.challengeId});
+ showMemberModal () {
+ this.$store.state.viewingMembers = this.members;
+ this.$root.$emit('show::modal', 'members-modal');
},
async joinChallenge () {
this.user.challenges.push(this.challengeId);
@@ -187,6 +190,9 @@ export default {
this.$root.$emit('show::modal', 'challenge-modal');
},
// @TODO: view members
+ updatedChallenge (eventData) {
+ Object.assign(this.challenge, eventData.challenge);
+ },
},
};
diff --git a/website/client/components/challenges/challengeModal.vue b/website/client/components/challenges/challengeModal.vue
index 799d9c24cc..ad884464f8 100644
--- a/website/client/components/challenges/challengeModal.vue
+++ b/website/client/components/challenges/challengeModal.vue
@@ -1,16 +1,20 @@
b-modal#challenge-modal(:title="$t('createChallenge')", size='lg')
- form(@submit.stop.prevent="submit")
+ .form
.form-group
label
strong(v-once) {{$t('name')}}*
b-form-input(type="text", :placeholder="$t('challengeNamePlaceHolder')", v-model="workingChallenge.name")
+ .form-group
+ label
+ strong(v-once) {{$t('shortName')}}*
+ b-form-input(type="text", :placeholder="$t('challengeNamePlaceHolder')", v-model="workingChallenge.shortName")
.form-group
label
strong(v-once) {{$t('description')}}*
div.description-count.float-right {{charactersRemaining}} {{ $t('charactersRemaining') }}
b-form-input.description-textarea(type="text", textarea, :placeholder="$t('challengeDescriptionPlaceHolder')", v-model="workingChallenge.description")
- .form-group
+ // @TODO: Implemenet in V2 .form-group
label
strong(v-once) {{$t('guildInformation')}}*
a.float-right {{ $t('markdownFormattingHelp') }}
@@ -18,27 +22,38 @@
.form-group(v-if='creating')
label
strong(v-once) {{$t('where')}}
- b-dropdown(:text="$t('sort')", right=true)
- b-dropdown-item(@click='sort(option.value)')
- .form-group
+ select.form-control(v-model='workingChallenge.group')
+ option(v-for='group in groups', :value='group._id') {{group.name}}
+ .form-group(v-if='workingChallenge.categories')
label
strong(v-once) {{$t('categories')}}*
- b-dropdown(:text="$t('sort')", right=true)
- b-dropdown-item(@click='sort(option.value)')
- | Member
- .form-group
+ div.category-wrap(@click.prevent="toggleCategorySelect")
+ span.category-select(v-if='workingChallenge.categories.length === 0') {{$t('none')}}
+ .category-label(v-for='category in workingChallenge.categories') {{$t(categoriesHashByKey[category])}}
+ .category-box(v-if="showCategorySelect")
+ .form-check(
+ v-for="group in categoryOptions",
+ :key="group.key",
+ )
+ label.custom-control.custom-checkbox
+ input.custom-control-input(type="checkbox", :value='group.key' v-model="workingChallenge.categories")
+ span.custom-control-indicator
+ span.custom-control-description(v-once) {{ $t(group.label) }}
+ button.btn.btn-primary(@click.prevent="toggleCategorySelect") {{$t('close')}}
+ // @TODO: Implement in V2 .form-group
label
strong(v-once) {{$t('endDate')}}
b-form-input.end-date-input
.form-group
label
strong(v-once) {{$t('prize')}}
- b-dropdown(:text="$t('sort')", right=true)
- b-dropdown-item(@click='sort(option.value)')
- | Member
+ input(type='number', min='1', :max='maxPrize')
.row.footer-wrap
.col-12.text-center.submit-button-wrapper
- button.btn.btn-primary(v-once) {{$t('createChallenge')}}
+ .alert.alert-warning(v-if='insufficientGemsForTavernChallenge')
+ You do not have enough gems to create a Tavern challenge
+ button.btn.btn-primary(v-once, v-if='creating', @click='createChallenge()') {{$t('createChallenge')}}
+ button.btn.btn-primary(v-once, v-if='!creating', @click='updateChallenge()') {{$t('updateChallenge')}}
.col-12.text-center
p(v-once) {{$t('challengeMinimum')}}
@@ -90,6 +105,14 @@
margin-top: 2em;
margin-bottom: 2em;
}
+
+ .category-wrap {
+ position: relative;
+ }
+
+ .category-box {
+ top: -40px !important;
+ }
}
@@ -99,6 +122,9 @@ import bDropdown from 'bootstrap-vue/lib/components/dropdown';
import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item';
import bFormInput from 'bootstrap-vue/lib/components/form-input';
+import { TAVERN_ID } from '../../../common/script/constants';
+import { mapState } from 'client/libs/store';
+
export default {
props: ['challenge'],
components: {
@@ -108,51 +134,151 @@ export default {
bFormInput,
},
data () {
+ let categoryOptions = [
+ {
+ label: 'animals',
+ key: 'animals',
+ },
+ {
+ label: 'artDesign',
+ key: 'art_design',
+ },
+ {
+ label: 'booksWriting',
+ key: 'books_writing',
+ },
+ {
+ label: 'comicsHobbies',
+ key: 'comics_hobbies',
+ },
+ {
+ label: 'diyCrafts',
+ key: 'diy_crafts',
+ },
+ {
+ label: 'education',
+ key: 'education',
+ },
+ {
+ label: 'foodCooking',
+ key: 'food_cooking',
+ },
+ {
+ label: 'healthFitness',
+ key: 'health_fitness',
+ },
+ {
+ label: 'music',
+ key: 'music',
+ },
+ {
+ label: 'relationship',
+ key: 'relationship',
+ },
+ {
+ label: 'scienceTech',
+ key: 'science_tech ',
+ },
+ ];
+ let hashedCategories = {};
+ categoryOptions.forEach((category) => {
+ hashedCategories[category.key] = category.label;
+ });
+ let categoriesHashByKey = hashedCategories;
+
return {
creating: true,
charactersRemaining: 250,
- workingChallenge: {
- name: '',
- description: '',
- information: '',
- },
+ workingChallenge: {},
+ showCategorySelect: false,
+ categoryOptions,
+ categoriesHashByKey,
+ groups: [],
};
},
- mounted () {
- if (this.challenge) {
- this.workingChallenge = this.challenge;
- this.creating = false;
- }
+ async mounted () {
+ this.$root.$on('shown::modal', () => {
+ if (this.challenge) {
+ Object.assign(this.workingChallenge, this.challenge);
+ this.workingChallenge.categories = [];
+ this.creating = false;
+ }
+ });
+
+ this.groups = await this.$store.dispatch('guilds:getMyGuilds');
+ this.ressetWorkingChallenge();
+ },
+ watch: {
+ user () {
+ if (!this.challenge) this.workingChallenge.leader = this.user._id;
+ },
},
computed: {
+ ...mapState({user: 'user.data'}),
maxPrize () {
- // var groupBalance = 0;
- // var group = _.find($scope.groups, { _id: gid });
- //
- // if (group && group.balance && group.leader === User.user._id) {
- // groupBalance = group.balance * 4;
- // }
- //
- // return groupBalance;
- // return userBalance + availableGroupBalance;
+ let userBalance = this.user.balance || 0;
+ userBalance = userBalance * 4;
+
+ let groupBalance = 0;
+ let group = find(this.groups, { _id: this.workingChallenge.group });
+
+ if (group && group.balance && group.leader === this.user._id) {
+ groupBalance = group.balance * 4;
+ }
+
+ return userBalance + groupBalance;
},
insufficientGemsForTavernChallenge () {
- // var balance = User.user.balance || 0;
- // var isForTavern = $scope.newChallenge.group == TAVERN_ID;
- //
- // if (isForTavern) {
- // return balance <= 0;
- // } else {
- // return false;
- // }
+ let balance = this.user.balance || 0;
+ let isForTavern = this.workingChallenge.group === TAVERN_ID;
+
+ if (isForTavern) {
+ return balance <= 0;
+ } else {
+ return false;
+ }
},
},
methods: {
+ ressetWorkingChallenge () {
+ this.workingChallenge = {
+ name: '',
+ description: '',
+ information: '',
+ categories: [],
+ group: '',
+ dailys: [],
+ habits: [],
+ leader: '',
+ members: [],
+ official: false,
+ prize: 1,
+ rewards: [],
+ shortName: '',
+ todos: [],
+ };
+ },
createChallenge () {
- // this.$store.dispatch('challenges:createChallenge', {challenge: this.workingChallenge});
+ if (!this.workingChallenge.name) alert('Name is required');
+ if (!this.workingChallenge.description) alert('Description is required');
+
+ this.workingChallenge.timestamp = new Date().getTime();
+
+ this.$store.dispatch('challenges:createChallenge', {challenge: this.workingChallenge});
+
+ this.ressetWorkingChallenge();
+ this.$root.$emit('hide::modal', 'challenge-modal');
},
updateChallenge () {
- // this.$store.dispatch('challenges:updateChallenge', {challenge: this.workingChallenge});
+ this.$emit('updatedChallenge', {
+ challenge: this.workingChallenge,
+ });
+ this.$store.dispatch('challenges:updateChallenge', {challenge: this.workingChallenge});
+ this.ressetWorkingChallenge();
+ this.$root.$emit('hide::modal', 'challenge-modal');
+ },
+ toggleCategorySelect () {
+ this.showCategorySelect = !this.showCategorySelect;
},
},
};
diff --git a/website/client/components/challenges/findChallenges.vue b/website/client/components/challenges/findChallenges.vue
index 551c38b9b9..bf6ddb2588 100644
--- a/website/client/components/challenges/findChallenges.vue
+++ b/website/client/components/challenges/findChallenges.vue
@@ -8,14 +8,14 @@
.col-md-8.text-left
h1(v-once) {{$t('findChallenges')}}
.col-md-4
- span.dropdown-label {{ $t('sortBy') }}
- b-dropdown(:text="$t('sort')", right=true)
- b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}
+ // @TODO: implement sorting span.dropdown-label {{ $t('sortBy') }}
+ b-dropdown(:text="$t('sort')", right=true)
+ b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}
button.btn.btn-secondary.create-challenge-button(@click='createChallenge()')
.svg-icon.positive-icon(v-html="icons.positiveIcon")
span(v-once) {{$t('createChallenge')}}
.row
- .col-6(v-for='challenge in challenges', v-if='!memberOf(challenge)')
+ .col-6(v-for='challenge in filteredChallenges', v-if='!memberOf(challenge)')
challenge-item(:challenge='challenge')
@@ -48,10 +48,12 @@ import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item';
import Sidebar from './sidebar';
import ChallengeItem from './challengeItem';
import challengeModal from './challengeModal';
+import challengeUtilities from 'client/mixins/challengeUtilities';
import positiveIcon from 'assets/svg/positive.svg';
export default {
+ mixins: [challengeUtilities],
components: {
Sidebar,
ChallengeItem,
@@ -65,7 +67,31 @@ export default {
positiveIcon,
}),
challenges: [],
- sortOptions: [],
+ sort: 'none',
+ sortOptions: [
+ {
+ text: this.$t('none'),
+ value: 'none',
+ },
+ {
+ text: this.$t('participants'),
+ value: 'participants',
+ },
+ {
+ text: this.$t('name'),
+ value: 'name',
+ },
+ {
+ text: this.$t('end_date'),
+ value: 'end_date',
+ },
+ {
+ text: this.$t('start_date'),
+ value: 'start_date',
+ },
+ ],
+ search: '',
+ filters: {},
};
},
mounted () {
@@ -75,16 +101,25 @@ export default {
},
computed: {
...mapState({user: 'user.data'}),
+ filteredChallenges () {
+ let search = this.search;
+ let filters = this.filters;
+ let user = this.$store.state.user.data;
+ // @TODO: Move this to the server
+ return this.challenges.filter((challenge) => {
+ return this.filterChallenge(challenge, filters, search, user);
+ });
+ },
},
methods: {
memberOf (challenge) {
return this.user.challenges.indexOf(challenge._id) !== -1;
},
- updateSearch () {
-
+ updateSearch (eventData) {
+ this.search = eventData.searchTerm;
},
- updateFilters () {
-
+ updateFilters (eventData) {
+ this.filters = eventData;
},
createChallenge () {
this.$root.$emit('show::modal', 'challenge-modal');
diff --git a/website/client/components/challenges/groupChallenges.vue b/website/client/components/challenges/groupChallenges.vue
index 81169d9818..65a20f4d0c 100644
--- a/website/client/components/challenges/groupChallenges.vue
+++ b/website/client/components/challenges/groupChallenges.vue
@@ -1,11 +1,12 @@
div
+ challenge-modal
.row.no-quest-section(v-if='challenges.length === 0')
.col-12.text-center
.svg-icon.challenge-icon(v-html="icons.challengeIcon")
h4(v-once) {{ $t('haveNoChallenges') }}
p(v-once) {{ $t('challengeDescription') }}
- button.btn.btn-secondary(v-once) {{ $t('createChallenge') }}
+ button.btn.btn-secondary(v-once, @click='createChallenge()') {{ $t('createChallenge') }}
.col-12.challenge-item(v-for='challenge in challenges')
.row
.col-9
@@ -77,12 +78,17 @@ div
diff --git a/website/client/components/challenges/myChallenges.vue b/website/client/components/challenges/myChallenges.vue
index 76aaff8ea6..6f01251623 100644
--- a/website/client/components/challenges/myChallenges.vue
+++ b/website/client/components/challenges/myChallenges.vue
@@ -8,9 +8,9 @@
.col-md-8.text-left
h1(v-once) {{$t('myChallenges')}}
.col-md-4
- span.dropdown-label {{ $t('sortBy') }}
- b-dropdown(:text="$t('sort')", right=true)
- b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}
+ // @TODO: implement sorting span.dropdown-label {{ $t('sortBy') }}
+ b-dropdown(:text="$t('sort')", right=true)
+ b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}
button.btn.btn-secondary.create-challenge-button(@click='createChallenge()')
.svg-icon.positive-icon(v-html="icons.positiveIcon")
span(v-once) {{$t('createChallenge')}}
@@ -70,11 +70,13 @@ import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item';
import Sidebar from './sidebar';
import ChallengeItem from './challengeItem';
import challengeModal from './challengeModal';
+import challengeUtilities from 'client/mixins/challengeUtilities';
import challengeIcon from 'assets/svg/challenge.svg';
import positiveIcon from 'assets/svg/positive.svg';
export default {
+ mixins: [challengeUtilities],
components: {
Sidebar,
ChallengeItem,
@@ -89,7 +91,33 @@ export default {
positiveIcon,
}),
challenges: [],
- sortOptions: [],
+ sort: 'none',
+ sortOptions: [
+ {
+ text: this.$t('none'),
+ value: 'none',
+ },
+ {
+ text: this.$t('participants'),
+ value: 'participants',
+ },
+ {
+ text: this.$t('name'),
+ value: 'name',
+ },
+ {
+ text: this.$t('end_date'),
+ value: 'end_date',
+ },
+ {
+ text: this.$t('start_date'),
+ value: 'start_date',
+ },
+ ],
+ search: '',
+ filters: {
+ roles: ['member'], // This is required for my challenges
+ },
};
},
mounted () {
@@ -98,10 +126,12 @@ export default {
computed: {
...mapState({user: 'user.data'}),
filteredChallenges () {
+ let search = this.search;
+ let filters = this.filters;
+ let user = this.$store.state.user.data;
+ // @TODO: Move this to the server
return this.challenges.filter((challenge) => {
- let isMember = this.memberOf(challenge);
- // @TODO: Other filters
- return isMember;
+ return this.filterChallenge(challenge, filters, search, user);
});
},
},
@@ -109,11 +139,11 @@ export default {
memberOf (challenge) {
return this.user.challenges.indexOf(challenge._id) !== -1;
},
- updateSearch () {
-
+ updateSearch (eventData) {
+ this.search = eventData.searchTerm;
},
- updateFilters () {
-
+ updateFilters (eventData) {
+ this.filters = eventData;
},
createChallenge () {
this.$root.$emit('show::modal', 'challenge-modal');
diff --git a/website/client/components/challenges/sidebar.vue b/website/client/components/challenges/sidebar.vue
index a5011e7293..a3c0aeaf2f 100644
--- a/website/client/components/challenges/sidebar.vue
+++ b/website/client/components/challenges/sidebar.vue
@@ -28,11 +28,11 @@
.form-group
h3 Ownership
.form-check(
- v-for="group in guildSizeOptions",
+ v-for="group in ownershipOptions",
:key="group.key",
)
label.custom-control.custom-checkbox
- input.custom-control-input(type="checkbox", :value='group.key' v-model="guildSizeFilters")
+ input.custom-control-input(type="checkbox", :value='group.key' v-model="ownershipFilters")
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t(group.label) }}
@@ -76,13 +76,13 @@ export default {
label: 'not_participating',
key: 'not_participating',
},
- {
- label: 'either',
- key: 'either',
- },
+ // {
+ // label: 'either',
+ // key: 'either',
+ // },
],
- guildSizeFilters: [],
- guildSizeOptions: [
+ ownershipFilters: [],
+ ownershipOptions: [
{
label: 'owned',
key: 'owned',
@@ -91,10 +91,10 @@ export default {
label: 'not_owned',
key: 'not_owned',
},
- {
- label: 'either',
- key: 'either',
- },
+ // {
+ // label: 'either',
+ // key: 'either',
+ // },
],
searchTerm: '',
};
@@ -106,7 +106,7 @@ export default {
roleFilters: function roleFilters () {
this.emitFilters();
},
- guildSizeFilters: function guildSizeFilters () {
+ ownershipFilters: function ownershipFilters () {
this.emitFilters();
},
searchTerm: throttle(function searchTerm (newSearch) {
@@ -120,7 +120,7 @@ export default {
this.$emit('filter', {
categories: this.categoryFilters,
roles: this.roleFilters,
- guildSize: this.guildSizeFilters,
+ ownership: this.ownershipFilters,
});
},
},
diff --git a/website/client/components/creatorIntro.vue b/website/client/components/creatorIntro.vue
index d15bf55967..360d2adf3a 100644
--- a/website/client/components/creatorIntro.vue
+++ b/website/client/components/creatorIntro.vue
@@ -1,207 +1,208 @@
-#creator-background
- #creator-modal
- .section.row.welcome-section(v-if='modalPage == 1')
- .col-6.offset-3.text-center
- h3(v-once) {{$t('welcomeTo')}}
- .svg-icon.logo(v-html='icons.logoPurple')
+b-modal#avatar-modal(title="", size='md', :hide-header='true', :hide-footer='true')
+ .section.row.welcome-section(v-if='modalPage == 1')
+ .col-6.offset-3.text-center
+ h3(v-once) {{$t('welcomeTo')}}
+ .svg-icon.logo(v-html='icons.logoPurple')
+ .section.row
+ .col-6.offset-3
+ .user-creation-bg
+ avatar(:member='user')
+
+ div(v-if='modalPage == 2')
.section.row
- .col-6.offset-3
- .user-creation-bg
- avatar(:member='user')
+ .col-12.text-center
+ button.btn.btn-secondary(v-once) {{$t('randomize')}}
+ .section.row.text-center.customize-menu
+ .col-3
+ .menu-item(@click='changeTopPage("body", "size")')
+ .svg-icon(v-html='icons.bodyIcon')
+ strong(v-once) {{$t('body')}}
+ .col-3
+ .menu-item(@click='changeTopPage("skin", "color")')
+ .svg-icon(v-html='icons.skinIcon')
+ strong(v-once) {{$t('skin')}}
+ .col-3
+ .menu-item(@click='changeTopPage("hair", "color")')
+ .svg-icon(v-html='icons.hairIcon')
+ strong(v-once) {{$t('hair')}}
+ .col-3
+ .menu-item(@click='changeTopPage("extra", "glasses")')
+ .svg-icon(v-html='icons.accessoriesIcon')
+ strong(v-once) {{$t('extra')}}
+ .section.customize-section(v-if='activeTopPage === "body"')
+ .row.sub-menu
+ .col-2.offset-4.sub-menu-item(@click='changeSubPage("size")', :class='{active: activeSubPage === "size"}')
+ strong(v-once) {{$t('size')}}
+ .col-2.sub-menu-item(@click='changeSubPage("shirt")', :class='{active: activeSubPage === "shirt"}')
+ strong(v-once) {{$t('shirt')}}
+ .row(v-if='activeSubPage === "size"')
+ .col-12.customize-options.size-options
+ .slim_shirt_black.option(@click='set({"preferences.size":"slim"})', :class='{active: user.preferences.size === "slim"}')
+ .broad_shirt_black.option(@click='set({"preferences.size":"broad"})', :class='{active: user.preferences.size === "broad"}')
+ .row(v-if='activeSubPage === "shirt"')
+ .col-12.customize-options
+ .slim_shirt_black.option(@click='set({"preferences.shirt":"black"})', :class='{active: user.preferences.shirt === "black"}')
+ .slim_shirt_blue.option(@click='set({"preferences.shirt":"blue"})', :class='{active: user.preferences.shirt === "blue"}')
+ .slim_shirt_green.option(@click='set({"preferences.shirt":"green"})', :class='{active: user.preferences.shirt === "green"}')
+ .slim_shirt_pink.option(@click='set({"preferences.shirt":"pink"})', :class='{active: user.preferences.shirt === "pink"}')
+ .slim_shirt_white.option(@click='set({"preferences.shirt":"white"})', :class='{active: user.preferences.shirt === "white"}')
+ .slim_shirt_yellow.option(@click='set({"preferences.shirt":"yellow"})', :class='{active: user.preferences.shirt === "yellow"}')
- div(v-if='modalPage == 2')
- .section.row
- .col-12.text-center
- button.btn.btn-secondary(v-once) {{$t('randomize')}}
- .section.row.text-center.customize-menu
- .col-3
- .menu-item(@click='changeTopPage("body", "size")')
- .svg-icon(v-html='icons.bodyIcon')
- strong(v-once) {{$t('body')}}
- .col-3
- .menu-item(@click='changeTopPage("skin", "color")')
- .svg-icon(v-html='icons.skinIcon')
- strong(v-once) {{$t('skin')}}
- .col-3
- .menu-item(@click='changeTopPage("hair", "color")')
- .svg-icon(v-html='icons.hairIcon')
- strong(v-once) {{$t('hair')}}
- .col-3
- .menu-item(@click='changeTopPage("extra", "glasses")')
- .svg-icon(v-html='icons.accessoriesIcon')
- strong(v-once) {{$t('extra')}}
- .section.customize-section(v-if='activeTopPage === "body"')
- .row.sub-menu
- .col-2.offset-4.sub-menu-item(@click='changeSubPage("size")', :class='{active: activeSubPage === "size"}')
- strong(v-once) {{$t('size')}}
- .col-2.sub-menu-item(@click='changeSubPage("shirt")', :class='{active: activeSubPage === "shirt"}')
- strong(v-once) {{$t('shirt')}}
- .row(v-if='activeSubPage === "size"')
- .col-12.customize-options.size-options
- .slim_shirt_black.option(@click='set({"preferences.size":"slim"})', :class='{active: user.preferences.size === "slim"}')
- .broad_shirt_black.option(@click='set({"preferences.size":"broad"})', :class='{active: user.preferences.size === "broad"}')
- .row(v-if='activeSubPage === "shirt"')
- .col-12.customize-options
- .slim_shirt_black.option(@click='set({"preferences.shirt":"black"})', :class='{active: user.preferences.shirt === "black"}')
- .slim_shirt_blue.option(@click='set({"preferences.shirt":"blue"})', :class='{active: user.preferences.shirt === "blue"}')
- .slim_shirt_green.option(@click='set({"preferences.shirt":"green"})', :class='{active: user.preferences.shirt === "green"}')
- .slim_shirt_pink.option(@click='set({"preferences.shirt":"pink"})', :class='{active: user.preferences.shirt === "pink"}')
- .slim_shirt_white.option(@click='set({"preferences.shirt":"white"})', :class='{active: user.preferences.shirt === "white"}')
- .slim_shirt_yellow.option(@click='set({"preferences.shirt":"yellow"})', :class='{active: user.preferences.shirt === "yellow"}')
-
- .section.customize-section(v-if='activeTopPage === "skin"')
- .row.sub-menu
- .col-6.offset-3.text-center.sub-menu-item(:class='{active: activeSubPage === "color"}')
- strong(v-once) {{$t('color')}}
- .row
- .col-12.customize-options
- .skin_ddc994.option(@click='set({"preferences.skin":"ddc994"})', :class='{active: user.preferences.skin === "ddc994"}')
- .skin_f5a76e.option(@click='set({"preferences.skin":"f5a76e"})', :class='{active: user.preferences.skin === "f5a76e"}')
- .skin_ea8349.option(@click='set({"preferences.skin":"ea8349"})', :class='{active: user.preferences.skin === "ea8349"}')
- .skin_c06534.option(@click='set({"preferences.skin":"c06534"})', :class='{active: user.preferences.skin === "c06534"}')
- .skin_98461a.option(@click='set({"preferences.skin":"98461a"})', :class='{active: user.preferences.skin === "98461a"}')
- .skin_915533.option(@click='set({"preferences.skin":"915533"})', :class='{active: user.preferences.skin === "915533"}')
- .skin_c3e1dc.option(@click='set({"preferences.skin":"c3e1dc"})', :class='{active: user.preferences.skin === "c3e1dc"}')
- .skin_6bd049.option(@click='set({"preferences.skin":"6bd049"})', :class='{active: user.preferences.skin === "6bd049"}')
-
- .section.customize-section(v-if='activeTopPage === "hair"')
- .row.sub-menu
- .col-2.offset-3.text-center.sub-menu-item(@click='changeSubPage("color")', :class='{active: activeSubPage === "color"}')
- strong(v-once) {{$t('color')}}
- .col-2.text-center.sub-menu-item(@click='changeSubPage("bangs")', :class='{active: activeSubPage === "bangs"}')
- strong(v-once) {{$t('bangs')}}
- .col-2.text-center.sub-menu-item(@click='changeSubPage("ponytail")', :class='{active: activeSubPage === "ponytail"}')
- strong(v-once) {{$t('ponytail')}}
- .row(v-if='activeSubPage === "color"')
- .col-12.customize-options
- .hair_bangs_1_white.option(@click='set({"preferences.hair.color": "white"})', :class='{active: user.preferences.hair.color === "white"}')
- .hair_bangs_1_brown.option(@click='set({"preferences.hair.color": "brown"})', :class='{active: user.preferences.hair.color === "brown"}')
- .hair_bangs_1_blond.option(@click='set({"preferences.hair.color": "blond"})', :class='{active: user.preferences.hair.color === "blond"}')
- .hair_bangs_1_red.option(@click='set({"preferences.hair.color": "red"})', :class='{active: user.preferences.hair.color === "red"}')
- .hair_bangs_1_black.option(@click='set({"preferences.hair.color": "black"})', :class='{active: user.preferences.hair.color === "black"}')
- .row(v-if='activeSubPage === "bangs"')
- .col-12.customize-options
- .head_0.option(@click='set({"preferences.hair.bangs": 0})', :class="[{ active: user.preferences.hair.bangs === 0 }, 'hair_bangs_0_' + user.preferences.hair.color]")
- .option(@click='set({"preferences.hair.bangs": 1})', :class="[{ active: user.preferences.hair.bangs === 1 }, 'hair_bangs_1_' + user.preferences.hair.color]")
- .option(@click='set({"preferences.hair.bangs": 2})',:class="[{ active: user.preferences.hair.bangs === 2 }, 'hair_bangs_2_' + user.preferences.hair.color]")
- .option(@click='set({"preferences.hair.bangs": 3})', :class="[{ active: user.preferences.hair.bangs === 3 }, 'hair_bangs_3_' + user.preferences.hair.color]")
- .option(@click='set({"preferences.hair.bangs": 4})', :class="[{ active: user.preferences.hair.bangs === 4 }, 'hair_bangs_4_' + user.preferences.hair.color]")
- .row(v-if='activeSubPage === "ponytail"')
- .col-12.customize-options
- .head_0.option(@click='set({"preferences.hair.base": 0})', :class="[{ active: user.preferences.hair.base === 0 }, 'hair_base_0_' + user.preferences.hair.color]")
- .hair_base_1_blond.option(@click='set({"preferences.hair.base": 1})', :class="[{ active: user.preferences.hair.base === 1 }, 'hair_base_1_' + user.preferences.hair.color]")
- .hair_base_3_blond.option(@click='set({"preferences.hair.base": 3})', :class="[{ active: user.preferences.hair.base === 3 }, 'hair_base_3_' + user.preferences.hair.color]")
-
- .section.container.customize-section(v-if='activeTopPage === "extra"')
- .row.sub-menu
- .col-4.text-center.sub-menu-item(@click='changeSubPage("glasses")', :class='{active: activeSubPage === "glasses"}')
- strong(v-once) {{$t('glasses')}}
- .col-4.text-center.sub-menu-item(@click='changeSubPage("wheelchair")', :class='{active: activeSubPage === "wheelchair"}')
- strong(v-once) {{$t('wheelchair')}}
- .col-4.text-center.sub-menu-item(@click='changeSubPage("flower")', :class='{active: activeSubPage === "flower"}')
- strong(v-once) {{$t('flower')}}
- .row(v-if='activeSubPage === "glasses"')
- .col-12.customize-options
- .eyewear_special_blackTopFrame.option(@click='equip("eyewear_special_blackTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_blackTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_blackTopFrame"}')
- .eyewear_special_blueTopFrame.option(@click='equip("eyewear_special_blueTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_blueTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_blueTopFrame"}')
- .eyewear_special_greenTopFrame.option(@click='equip("eyewear_special_greenTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_greenTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_greenTopFrame"}')
- .eyewear_special_pinkTopFrame.option(@click='equip("eyewear_special_pinkTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_pinkTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_pinkTopFrame"}')
- .eyewear_special_redTopFrame.option(@click='equip("eyewear_special_redTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_redTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_redTopFrame"}')
- .eyewear_special_whiteTopFrame.option(@click='equip("eyewear_special_whiteTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_whiteTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_whiteTopFrame"}')
- .eyewear_special_yellowTopFrame.option(@click='equip("eyewear_special_yellowTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_yellowTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_yellowTopFrame"}')
- .row(v-if='activeSubPage === "wheelchair"')
- .col-12.customize-options.weelchairs
- .option(@click='set({"preferences.chair": "none"})', :class='{active: user.preferences.chair === "none"}')
- | None
- .option(@click='set({"preferences.chair": "black"})', :class='{active: user.preferences.chair === "black"}')
- .button_chair_black
- .option(@click='set({"preferences.chair": "blue"})', :class='{active: user.preferences.chair === "blue"}')
- .button_chair_blue
- .option(@click='set({"preferences.chair": "green"})', :class='{active: user.preferences.chair === "green"}')
- .button_chair_green
- .option(@click='set({"preferences.chair": "pink"})', :class='{active: user.preferences.chair === "pink"}')
- .button_chair_pink
- .option(@click='set({"preferences.chair": "red"})', :class='{active: user.preferences.chair === "red"}')
- .button_chair_red
- .option(@click='set({"preferences.chair": "yellow"})', :class='{active: user.preferences.chair === "yellow"}')
- .button_chair_yellow
- .row(v-if='activeSubPage === "flower"')
- .col-12.customize-options
- .head_0.option(@click='set({"preferences.hair.flower":0})', :class='{active: user.preferences.hair.flower === 0}')
- .hair_flower_1.option(@click='set({"preferences.hair.flower":1})', :class='{active: user.preferences.hair.flower === 1}')
- .hair_flower_2.option(@click='set({"preferences.hair.flower":2})', :class='{active: user.preferences.hair.flower === 2}')
- .hair_flower_3.option(@click='set({"preferences.hair.flower":3})', :class='{active: user.preferences.hair.flower === 3}')
- .hair_flower_4.option(@click='set({"preferences.hair.flower":4})', :class='{active: user.preferences.hair.flower === 4}')
- .hair_flower_5.option(@click='set({"preferences.hair.flower":5})', :class='{active: user.preferences.hair.flower === 5}')
- .hair_flower_6.option(@click='set({"preferences.hair.flower":6})', :class='{active: user.preferences.hair.flower === 6}')
-
- .container.interests-section(v-if='modalPage == 3')
- .section.row
- .col-12.text-center
- h2 I want to work on:
- .section.row
- .col-4.offset-2
- div
- label.custom-control.custom-checkbox
- input.custom-control-input(type="checkbox")
- span.custom-control-indicator
- span.custom-control-description(v-once) {{ $t('work') }}
- div
- label.custom-control.custom-checkbox
- input.custom-control-input(type="checkbox")
- span.custom-control-indicator
- span.custom-control-description(v-once) {{ $t('excercise') }}
- div
- label.custom-control.custom-checkbox
- input.custom-control-input(type="checkbox")
- span.custom-control-indicator
- span.custom-control-description(v-once) {{ $t('health') }}
- div
- label.custom-control.custom-checkbox
- input.custom-control-input(type="checkbox")
- span.custom-control-indicator
- span.custom-control-description(v-once) {{ $t('school') }}
- .col-4
- div
- label.custom-control.custom-checkbox
- input.custom-control-input(type="checkbox")
- span.custom-control-indicator
- span.custom-control-description(v-once) {{ $t('chores') }}
- div
- label.custom-control.custom-checkbox
- input.custom-control-input(type="checkbox")
- span.custom-control-indicator
- span.custom-control-description(v-once) {{ $t('creativity') }}
- div
- label.custom-control.custom-checkbox
- input.custom-control-input(type="checkbox")
- span.custom-control-indicator
- span.custom-control-description(v-once) {{ $t('budgeting') }}
-
- .section.row.justin-message-section(:class='{top: modalPage > 1}')
- .col-9
- .justin-message(v-if='modalPage == 1')
- p(v-once) {{$t('justinIntroMessage1')}}
- p(v-once) {{$t('justinIntroMessage2')}}
- .justin-message(v-if='modalPage > 1')
- p(v-once) {{$t('justinIntroMessage3')}}
-
- .section.container.footer
+ .section.customize-section(v-if='activeTopPage === "skin"')
+ .row.sub-menu
+ .col-6.offset-3.text-center.sub-menu-item(:class='{active: activeSubPage === "color"}')
+ strong(v-once) {{$t('color')}}
.row
- .col-3.offset-1.text-center
- div(v-if='modalPage > 1', @click='prev()')
- .prev-arrow
- .prev(v-once) {{$t('prev')}}
- .col-4.text-center.circles
- .circle(:class="{active: modalPage === 1}")
- .circle(:class="{active: modalPage === 2}")
- .circle(:class="{active: modalPage === 3}")
- .col-3.text-center
- div(v-if='modalPage < 3', @click='next()')
- .next(v-once) {{$t('next')}}
- .next-arrow
+ .col-12.customize-options
+ .skin_ddc994.option(@click='set({"preferences.skin":"ddc994"})', :class='{active: user.preferences.skin === "ddc994"}')
+ .skin_f5a76e.option(@click='set({"preferences.skin":"f5a76e"})', :class='{active: user.preferences.skin === "f5a76e"}')
+ .skin_ea8349.option(@click='set({"preferences.skin":"ea8349"})', :class='{active: user.preferences.skin === "ea8349"}')
+ .skin_c06534.option(@click='set({"preferences.skin":"c06534"})', :class='{active: user.preferences.skin === "c06534"}')
+ .skin_98461a.option(@click='set({"preferences.skin":"98461a"})', :class='{active: user.preferences.skin === "98461a"}')
+ .skin_915533.option(@click='set({"preferences.skin":"915533"})', :class='{active: user.preferences.skin === "915533"}')
+ .skin_c3e1dc.option(@click='set({"preferences.skin":"c3e1dc"})', :class='{active: user.preferences.skin === "c3e1dc"}')
+ .skin_6bd049.option(@click='set({"preferences.skin":"6bd049"})', :class='{active: user.preferences.skin === "6bd049"}')
+
+ .section.customize-section(v-if='activeTopPage === "hair"')
+ .row.sub-menu
+ .col-2.offset-3.text-center.sub-menu-item(@click='changeSubPage("color")', :class='{active: activeSubPage === "color"}')
+ strong(v-once) {{$t('color')}}
+ .col-2.text-center.sub-menu-item(@click='changeSubPage("bangs")', :class='{active: activeSubPage === "bangs"}')
+ strong(v-once) {{$t('bangs')}}
+ .col-2.text-center.sub-menu-item(@click='changeSubPage("ponytail")', :class='{active: activeSubPage === "ponytail"}')
+ strong(v-once) {{$t('ponytail')}}
+ .row(v-if='activeSubPage === "color"')
+ .col-12.customize-options
+ .hair_bangs_1_white.option(@click='set({"preferences.hair.color": "white"})', :class='{active: user.preferences.hair.color === "white"}')
+ .hair_bangs_1_brown.option(@click='set({"preferences.hair.color": "brown"})', :class='{active: user.preferences.hair.color === "brown"}')
+ .hair_bangs_1_blond.option(@click='set({"preferences.hair.color": "blond"})', :class='{active: user.preferences.hair.color === "blond"}')
+ .hair_bangs_1_red.option(@click='set({"preferences.hair.color": "red"})', :class='{active: user.preferences.hair.color === "red"}')
+ .hair_bangs_1_black.option(@click='set({"preferences.hair.color": "black"})', :class='{active: user.preferences.hair.color === "black"}')
+ .row(v-if='activeSubPage === "bangs"')
+ .col-12.customize-options
+ .head_0.option(@click='set({"preferences.hair.bangs": 0})', :class="[{ active: user.preferences.hair.bangs === 0 }, 'hair_bangs_0_' + user.preferences.hair.color]")
+ .option(@click='set({"preferences.hair.bangs": 1})', :class="[{ active: user.preferences.hair.bangs === 1 }, 'hair_bangs_1_' + user.preferences.hair.color]")
+ .option(@click='set({"preferences.hair.bangs": 2})',:class="[{ active: user.preferences.hair.bangs === 2 }, 'hair_bangs_2_' + user.preferences.hair.color]")
+ .option(@click='set({"preferences.hair.bangs": 3})', :class="[{ active: user.preferences.hair.bangs === 3 }, 'hair_bangs_3_' + user.preferences.hair.color]")
+ .option(@click='set({"preferences.hair.bangs": 4})', :class="[{ active: user.preferences.hair.bangs === 4 }, 'hair_bangs_4_' + user.preferences.hair.color]")
+ .row(v-if='activeSubPage === "ponytail"')
+ .col-12.customize-options
+ .head_0.option(@click='set({"preferences.hair.base": 0})', :class="[{ active: user.preferences.hair.base === 0 }, 'hair_base_0_' + user.preferences.hair.color]")
+ .hair_base_1_blond.option(@click='set({"preferences.hair.base": 1})', :class="[{ active: user.preferences.hair.base === 1 }, 'hair_base_1_' + user.preferences.hair.color]")
+ .hair_base_3_blond.option(@click='set({"preferences.hair.base": 3})', :class="[{ active: user.preferences.hair.base === 3 }, 'hair_base_3_' + user.preferences.hair.color]")
+
+ .section.container.customize-section(v-if='activeTopPage === "extra"')
+ .row.sub-menu
+ .col-4.text-center.sub-menu-item(@click='changeSubPage("glasses")', :class='{active: activeSubPage === "glasses"}')
+ strong(v-once) {{$t('glasses')}}
+ .col-4.text-center.sub-menu-item(@click='changeSubPage("wheelchair")', :class='{active: activeSubPage === "wheelchair"}')
+ strong(v-once) {{$t('wheelchair')}}
+ .col-4.text-center.sub-menu-item(@click='changeSubPage("flower")', :class='{active: activeSubPage === "flower"}')
+ strong(v-once) {{$t('flower')}}
+ .row(v-if='activeSubPage === "glasses"')
+ .col-12.customize-options
+ .eyewear_special_blackTopFrame.option(@click='equip("eyewear_special_blackTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_blackTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_blackTopFrame"}')
+ .eyewear_special_blueTopFrame.option(@click='equip("eyewear_special_blueTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_blueTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_blueTopFrame"}')
+ .eyewear_special_greenTopFrame.option(@click='equip("eyewear_special_greenTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_greenTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_greenTopFrame"}')
+ .eyewear_special_pinkTopFrame.option(@click='equip("eyewear_special_pinkTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_pinkTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_pinkTopFrame"}')
+ .eyewear_special_redTopFrame.option(@click='equip("eyewear_special_redTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_redTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_redTopFrame"}')
+ .eyewear_special_whiteTopFrame.option(@click='equip("eyewear_special_whiteTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_whiteTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_whiteTopFrame"}')
+ .eyewear_special_yellowTopFrame.option(@click='equip("eyewear_special_yellowTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_yellowTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_yellowTopFrame"}')
+ .row(v-if='activeSubPage === "wheelchair"')
+ .col-12.customize-options.weelchairs
+ .option(@click='set({"preferences.chair": "none"})', :class='{active: user.preferences.chair === "none"}')
+ | None
+ .option(@click='set({"preferences.chair": "black"})', :class='{active: user.preferences.chair === "black"}')
+ .button_chair_black
+ .option(@click='set({"preferences.chair": "blue"})', :class='{active: user.preferences.chair === "blue"}')
+ .button_chair_blue
+ .option(@click='set({"preferences.chair": "green"})', :class='{active: user.preferences.chair === "green"}')
+ .button_chair_green
+ .option(@click='set({"preferences.chair": "pink"})', :class='{active: user.preferences.chair === "pink"}')
+ .button_chair_pink
+ .option(@click='set({"preferences.chair": "red"})', :class='{active: user.preferences.chair === "red"}')
+ .button_chair_red
+ .option(@click='set({"preferences.chair": "yellow"})', :class='{active: user.preferences.chair === "yellow"}')
+ .button_chair_yellow
+ .row(v-if='activeSubPage === "flower"')
+ .col-12.customize-options
+ .head_0.option(@click='set({"preferences.hair.flower":0})', :class='{active: user.preferences.hair.flower === 0}')
+ .hair_flower_1.option(@click='set({"preferences.hair.flower":1})', :class='{active: user.preferences.hair.flower === 1}')
+ .hair_flower_2.option(@click='set({"preferences.hair.flower":2})', :class='{active: user.preferences.hair.flower === 2}')
+ .hair_flower_3.option(@click='set({"preferences.hair.flower":3})', :class='{active: user.preferences.hair.flower === 3}')
+ .hair_flower_4.option(@click='set({"preferences.hair.flower":4})', :class='{active: user.preferences.hair.flower === 4}')
+ .hair_flower_5.option(@click='set({"preferences.hair.flower":5})', :class='{active: user.preferences.hair.flower === 5}')
+ .hair_flower_6.option(@click='set({"preferences.hair.flower":6})', :class='{active: user.preferences.hair.flower === 6}')
+
+ .container.interests-section(v-if='modalPage == 3')
+ .section.row
+ .col-12.text-center
+ h2 I want to work on:
+ .section.row
+ .col-4.offset-2
+ div
+ label.custom-control.custom-checkbox
+ input.custom-control-input(type="checkbox")
+ span.custom-control-indicator
+ span.custom-control-description(v-once) {{ $t('work') }}
+ div
+ label.custom-control.custom-checkbox
+ input.custom-control-input(type="checkbox")
+ span.custom-control-indicator
+ span.custom-control-description(v-once) {{ $t('excercise') }}
+ div
+ label.custom-control.custom-checkbox
+ input.custom-control-input(type="checkbox")
+ span.custom-control-indicator
+ span.custom-control-description(v-once) {{ $t('health') }}
+ div
+ label.custom-control.custom-checkbox
+ input.custom-control-input(type="checkbox")
+ span.custom-control-indicator
+ span.custom-control-description(v-once) {{ $t('school') }}
+ .col-4
+ div
+ label.custom-control.custom-checkbox
+ input.custom-control-input(type="checkbox")
+ span.custom-control-indicator
+ span.custom-control-description(v-once) {{ $t('chores') }}
+ div
+ label.custom-control.custom-checkbox
+ input.custom-control-input(type="checkbox")
+ span.custom-control-indicator
+ span.custom-control-description(v-once) {{ $t('creativity') }}
+ div
+ label.custom-control.custom-checkbox
+ input.custom-control-input(type="checkbox")
+ span.custom-control-indicator
+ span.custom-control-description(v-once) {{ $t('budgeting') }}
+
+ .section.row.justin-message-section(:class='{top: modalPage > 1}')
+ .col-9
+ .justin-message(v-if='modalPage == 1')
+ p(v-once) {{$t('justinIntroMessage1')}}
+ p(v-once) {{$t('justinIntroMessage2')}}
+ .justin-message(v-if='modalPage > 1')
+ p(v-once) {{$t('justinIntroMessage3')}}
+
+ .section.container.footer
+ .row
+ .col-3.offset-1.text-center
+ div(v-if='modalPage > 1', @click='prev()')
+ .prev-arrow
+ .prev(v-once) {{$t('prev')}}
+ .col-4.text-center.circles
+ .circle(:class="{active: modalPage === 1}")
+ .circle(:class="{active: modalPage === 2}")
+ .circle(:class="{active: modalPage === 3}")
+ .col-3.text-center
+ div(v-if='modalPage < 3', @click='next()')
+ .next(v-once) {{$t('next')}}
+ .next-arrow
+ div(v-if='modalPage === 3', @click='done()')
+ button.btn.btn-primary.next(v-once) {{$t('done')}}
diff --git a/website/client/components/groups/groupFormModal.vue b/website/client/components/groups/groupFormModal.vue
index 95cc9243c3..9b4e7b9d82 100644
--- a/website/client/components/groups/groupFormModal.vue
+++ b/website/client/components/groups/groupFormModal.vue
@@ -4,12 +4,12 @@
.form-group
label
strong(v-once) {{$t('name')}}*
- b-form-input(type="text", :placeholder="$t('newGuildPlaceHolder')", v-model="newGuild.name")
+ b-form-input(type="text", :placeholder="$t('newGuildPlaceHolder')", v-model="workingGuild.name")
- .form-group(v-if='newGuild.id && members.length > 0')
+ .form-group(v-if='workingGuild.id && members.length > 0')
label
strong(v-once) {{$t('guildLeader')}}*
- select.form-control(v-model="newGuild.newLeader")
+ select.form-control(v-model="workingGuild.newLeader")
option(v-for='member in members', :value="member._id") {{ member.profile.name }}
.form-group
@@ -17,29 +17,29 @@
strong(v-once) {{$t('privacySettings')}}*
br
label.custom-control.custom-checkbox
- input.custom-control-input(type="checkbox", v-model="newGuild.onlyLeaderCreatesChallenges")
+ input.custom-control-input(type="checkbox", v-model="workingGuild.onlyLeaderCreatesChallenges")
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t('onlyLeaderCreatesChallenges') }}
b-tooltip.icon(:content="$t('privateDescription')")
.svg-icon(v-html='icons.information')
- br
- label.custom-control.custom-checkbox
- input.custom-control-input(type="checkbox", v-model="newGuild.guildLeaderCantBeMessaged")
+ // br
+ // @TODO Implement in V2 label.custom-control.custom-checkbox
+ input.custom-control-input(type="checkbox", v-model="workingGuild.guildLeaderCantBeMessaged")
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t('guildLeaderCantBeMessaged') }}
br
label.custom-control.custom-checkbox(v-if='!creatingParty')
- input.custom-control-input(type="checkbox", v-model="newGuild.privateGuild")
+ input.custom-control-input(type="checkbox", v-model="workingGuild.privateGuild")
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t('privateGuild') }}
b-tooltip.icon(:content="$t('privateDescription')")
.svg-icon(v-html='icons.information')
- br
- label.custom-control.custom-checkbox(v-if='!creatingParty')
- input.custom-control-input(type="checkbox", v-model="newGuild.allowGuildInvationsFromNonMembers")
+ // br
+ // @TODO: Implement in v2 label.custom-control.custom-checkbox(v-if='!creatingParty')
+ input.custom-control-input(type="checkbox", v-model="workingGuild.allowGuildInvationsFromNonMembers")
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t('allowGuildInvationsFromNonMembers') }}
@@ -47,14 +47,14 @@
label
strong(v-once) {{$t('description')}}*
div.description-count {{charactersRemaining}} {{ $t('charactersRemaining') }}
- b-form-input(type="text", textarea :placeholder="creatingParty ? $t('partyDescriptionPlaceHolder') : $t('guildDescriptionPlaceHolder')", v-model="newGuild.description")
+ b-form-input(type="text", textarea :placeholder="creatingParty ? $t('partyDescriptionPlaceHolder') : $t('guildDescriptionPlaceHolder')", v-model="workingGuild.description")
- .form-group(v-if='newGuild.id && !creatingParty')
+ .form-group(v-if='workingGuild.id && !creatingParty')
label
strong(v-once) {{$t('guildInformation')}}*
- b-form-input(type="text", textarea, :placeholder="$t('guildInformationPlaceHolder')", v-model="newGuild.guildInformation")
+ b-form-input(type="text", textarea, :placeholder="$t('guildInformationPlaceHolder')", v-model="workingGuild.guildInformation")
- .form-group(v-if='creatingParty && !newGuild.id')
+ .form-group(v-if='creatingParty && !workingGuild.id')
span
toggleSwitch(:label="$t('inviteMembersNow')", v-model='inviteMembers')
@@ -62,20 +62,20 @@
label
strong(v-once) {{$t('categories')}}*
div.category-wrap(@click.prevent="toggleCategorySelect")
- span.category-select(v-if='newGuild.categories.length === 0') {{$t('none')}}
- .category-label(v-for='category in newGuild.categories') {{$t(categoriesHashByKey[category])}}
+ span.category-select(v-if='workingGuild.categories.length === 0') {{$t('none')}}
+ .category-label(v-for='category in workingGuild.categories') {{$t(categoriesHashByKey[category])}}
.category-box(v-if="showCategorySelect")
.form-check(
v-for="group in categoryOptions",
:key="group.key",
)
label.custom-control.custom-checkbox
- input.custom-control-input(type="checkbox", :value='group.key' v-model="newGuild.categories")
+ input.custom-control-input(type="checkbox", :value='group.key' v-model="workingGuild.categories")
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t(group.label) }}
button.btn.btn-primary(@click.prevent="toggleCategorySelect") {{$t('close')}}
- .form-group(v-if='inviteMembers && !newGuild.id')
+ .form-group(v-if='inviteMembers && !workingGuild.id')
label
strong(v-once) Invite via Email or User ID
p Invite users via a valid email or 36-digit User ID. If an email isn’t registered yet, we’ll invite them to join.
@@ -92,8 +92,8 @@
div.item-with-icon(v-if='!creatingParty')
.svg-icon(v-html="icons.gem")
span.count 4
- button.btn.btn-primary.btn-md(v-if='!newGuild.id', :disabled='!newGuild.name || !newGuild.description') {{ creatingParty ? $t('createParty') : $t('createGuild') }}
- button.btn.btn-primary.btn-md(v-if='newGuild.id', :disabled='!newGuild.name || !newGuild.description') {{ creatingParty ? $t('updateParty') : $t('updateGuild') }}
+ button.btn.btn-primary.btn-md(v-if='!workingGuild.id', :disabled='!workingGuild.name || !workingGuild.description') {{ creatingParty ? $t('createParty') : $t('createGuild') }}
+ button.btn.btn-primary.btn-md(v-if='workingGuild.id', :disabled='!workingGuild.name || !workingGuild.description') {{ creatingParty ? $t('updateParty') : $t('updateGuild') }}
.gem-description(v-once, v-if='!creatingParty') {{ $t('guildGemCostInfo') }}
@@ -157,6 +157,12 @@ import toggleSwitch from 'client/components/ui/toggleSwitch';
import gemIcon from 'assets/svg/gem.svg';
import informationIcon from 'assets/svg/information.svg';
+// @TODO: Not sure the best way to pass party creating status
+// Since we need the modal in the header, passing props doesn't work
+// because we can't import the create group in the index of groups
+// I think state is the correct spot, but maybe we should separate into
+// two modals?
+
export default {
components: {
bModal,
@@ -169,7 +175,7 @@ export default {
},
data () {
let data = {
- newGuild: {
+ workingGuild: {
id: '',
name: '',
type: 'guild',
@@ -231,7 +237,6 @@ export default {
],
showCategorySelect: false,
members: [],
- creatingParty: true,
inviteMembers: false,
newMemberToInvite: {
value: '',
@@ -254,33 +259,37 @@ export default {
return data;
},
mounted () {
+ // @TODO: do we need this? Maybe us computed. If we need, then make it on show a specific modal
this.$root.$on('shown::modal', () => {
let editingGroup = this.$store.state.editingGroup;
- if (!editingGroup) return;
- this.newGuild.name = editingGroup.name;
- this.newGuild.type = editingGroup.type;
- this.newGuild.privacy = editingGroup.privacy;
- if (editingGroup.description) this.newGuild.description = editingGroup.description;
- this.newGuild.id = editingGroup._id;
- this.newGuild.newLeader = editingGroup.leader._id;
- this.getMembers();
+ if (!editingGroup._id) return;
+ this.workingGuild.name = editingGroup.name;
+ this.workingGuild.type = editingGroup.type;
+ this.workingGuild.privacy = editingGroup.privacy;
+ if (editingGroup.description) this.workingGuild.description = editingGroup.description;
+ if (editingGroup._id) this.workingGuild.id = editingGroup._id;
+ if (editingGroup.leader._id) this.workingGuild.newLeader = editingGroup.leader._id;
+ if (editingGroup._id) this.getMembers();
});
},
computed: {
charactersRemaining () {
- return 500 - this.newGuild.description.length;
+ return 500 - this.workingGuild.description.length;
},
title () {
if (this.creatingParty) return this.$t('createParty');
- if (!this.newGuild.id) return this.$t('createGuild');
+ if (!this.workingGuild.id) return this.$t('createGuild');
return this.$t('updateGuild');
},
+ creatingParty () {
+ return this.$store.state.groupFormOptions.createParty;
+ },
},
methods: {
async getMembers () {
- if (!this.newGuild.id) return;
+ if (!this.workingGuild.id) return;
let members = await this.$store.dispatch('members:getGroupMembers', {
- groupId: this.newGuild.id,
+ groupId: this.workingGuild.id,
includeAllPublicFields: true,
});
this.members = members;
@@ -300,49 +309,50 @@ export default {
this.showCategorySelect = !this.showCategorySelect;
},
async submit () {
- if (this.$store.state.user.data.balance < 1 && !this.newGuild.id) {
+ if (this.$store.state.user.data.balance < 1 && !this.workingGuild.id) {
// @TODO: Add proper notifications
alert('Not enough gems');
return;
// @TODO return $rootScope.openModal('buyGems', {track:"Gems > Create Group"});
}
- if (!this.newGuild.name || !this.newGuild.description) {
+ if (!this.workingGuild.name || !this.workingGuild.description) {
// @TODO: Add proper notifications
alert('Enter a name and description');
return;
}
- if (this.newGuild.description.length > 500) {
+ if (this.workingGuild.description.length > 500) {
// @TODO: Add proper notifications
alert('Description is too long');
return;
}
// @TODO: Add proper notifications
- if (!this.newGuild.id && !confirm(this.$t('confirmGuild'))) return;
+ if (!this.workingGuild.id && !confirm(this.$t('confirmGuild'))) return;
- if (!this.newGuild.privateGuild) {
- this.newGuild.privacy = 'public';
+ if (!this.workingGuild.privateGuild) {
+ this.workingGuild.privacy = 'public';
}
- if (!this.newGuild.onlyLeaderCreatesChallenges) {
- this.newGuild.leaderOnly = {
+ if (!this.workingGuild.onlyLeaderCreatesChallenges) {
+ this.workingGuild.leaderOnly = {
challenges: true,
};
}
- if (this.newGuild.id) {
- await this.$store.dispatch('guilds:update', {group: this.newGuild});
+ if (this.workingGuild.id) {
+ await this.$store.dispatch('guilds:update', {group: this.workingGuild});
// @TODO: this doesn't work because of the async resource
// if (updatedGroup.type === 'party') this.$store.state.party = {data: updatedGroup};
} else {
- await this.$store.dispatch('guilds:create', {group: this.newGuild});
+ await this.$store.dispatch('guilds:create', {group: this.workingGuild});
+ this.$store.state.user.balance -= 1;
}
this.$store.state.editingGroup = {};
- this.newGuild = {
+ this.workingGuild = {
name: '',
type: 'guild',
privacy: 'private',
diff --git a/website/client/components/groups/groupPlan.vue b/website/client/components/groups/groupPlan.vue
index 782d235729..c4b74b3e3d 100644
--- a/website/client/components/groups/groupPlan.vue
+++ b/website/client/components/groups/groupPlan.vue
@@ -83,6 +83,7 @@ div
+
diff --git a/website/client/components/userMenu/profile.vue b/website/client/components/userMenu/profile.vue
index cb1f839714..e043e46160 100644
--- a/website/client/components/userMenu/profile.vue
+++ b/website/client/components/userMenu/profile.vue
@@ -1,68 +1,245 @@
-.standard-page
+b-modal#profile(title="Profile", size='lg', :hide-footer="true")
.row
- .col-8
- .header
- h1 {{user.profile.name}}
- h4
- strong User Id:
- | {{user._id}}
- .col-4
- button.btn.btn-secondary(@click='editing = !editing') Edit
- .row(v-if='!editing')
- .col-8
- .about
- h2 About
- p {{user.profile.blurb}}
- .photo
- h2 Photo
- img.img-rendering-auto(v-if='user.profile.imageUrl', :src='user.profile.imageUrl')
+ .col-6.offset-3.text-center.nav
+ .nav-item(@click='selectedPage = "profile"', :class="{active: selectedPage === 'profile'}") Profile
+ .nav-item(@click='selectedPage = "achievements"', :class="{active: selectedPage === 'achievements'}") Achievements
+ .nav-item(@click='selectedPage = "stats"', :class="{active: selectedPage === 'stats'}") Stats
+ .standard-page(v-show='selectedPage === "profile"')
+ .row
+ .col-8
+ .header
+ h1 {{user.profile.name}}
+ h4
+ strong User Id:
+ | {{user._id}}
+ .col-4
+ button.btn.btn-secondary(@click='editing = !editing') Edit
+ .row(v-if='!editing')
+ .col-8
+ .about
+ h2 About
+ p {{user.profile.blurb}}
+ .photo
+ h2 Photo
+ img.img-rendering-auto(v-if='user.profile.imageUrl', :src='user.profile.imageUrl')
- .col-4
- .info
- h2 info
+ .col-4
+ .info
+ h2 info
+ div
+ strong Joined:
+ | {{user.auth.timestamps.created}}
+ div
+ strong Total Log Ins:
+ span {{ $t('totalCheckins', {count: user.loginIncentives}) }}
+ div
+ | {{getProgressDisplay()}}
+ .progress
+ .progress-bar(role='progressbar', :aria-valuenow='incentivesProgress', aria-valuemin='0', aria-valuemax='100', :style='{width: incentivesProgress + "%"}')
+ span.sr-only {{ incentivesProgress }}% Complete
+ // @TODO: Implement in V2 .social
+
+ .row(v-if='editing')
+ h1 Edit Profile
+ .col-12
+ .alert.alert-info.alert-sm(v-html='$t("communityGuidelinesWarning", managerEmail)')
+
+ // TODO use photo-upload instead: https://groups.google.com/forum/?fromgroups=#!topic/derbyjs/xMmADvxBOak
+ .form-group
+ label {{ $t('displayName') }}
+ input.form-control(type='text', :placeholder="$t('fullName')", v-model='editingProfile.name')
+ .form-group
+ label {{ $t('photoUrl') }}
+ input.form-control(type='url', v-model='editingProfile.imageUrl', :placeholder="$t('imageUrl')")
+ .form-group
+ label {{ $t('about') }}
+ textarea.form-control(rows=5, :placeholder="$t('displayBlurbPlaceholder')", v-model='editingProfile.blurb')
+ // include ../../shared/formatting-help
+ .form-group
+ label Facebook
+ input.form-control(type='text', placeholder="Paste your link here", v-model='editingProfile.facebook')
+ .form-group
+ label Instagram
+ input.form-control(type='text', placeholder="Paste your link here", v-model='editingProfile.instagram')
+ .form-group
+ label Twitter
+ input.form-control(type='text', placeholder="Paste your link here", v-model='editingProfile.twitter')
+
+ .col-3.offset-6.text.center
+ button.btn.btn-primary(@click='save()') {{ $t("save") }}
+ button.btn.btn-warning(@click='editing = false') {{ $t("cancel") }}
+ .standard-page.container(v-show='selectedPage === "achievements"')
+ .row(v-for='(category, key) in achievements')
+ h2.col-12 {{ $t(key+'Achievs') }}
+ .col-3.text-center(v-for='achievment in category.achievements')
+ div.achievement-container(:data-popover-html='achievment.title + achievment.text',
+ popover-placement='achievPopoverPlacement',
+ popover-append-to-body='achievAppendToBody')
+ div(popover-trigger='mouseenter',
+ :data-popover-html='achievment.title + achievment.text',
+ popover-placement='achievPopoverPlacement',
+ popover-append-to-body='achievAppendToBody')
+ .achievement(:class='achievment.icon + "2x"', v-if='achievment.earned')
+ .counter.badge.badge-info.stack-count(v-if='achievment.optionalCount') {{achievment.optionalCount}}
+ .achievement(class='achievement-unearned2x', v-if='!achievment.earned')
+ .row
+ .col-6
+ h2 Challeges Won
+ div(v-for='chal in user.achievements.challenges')
+ span {{chal}}
+ .col-6
+ h2 Quests Completed
+ div(v-for='(value, key) in user.achievements.quests')
+ span {{ content.quests[k].text() }}
+ span {{ value }}
+ .standard-page(v-show='selectedPage === "stats"')
+ h1 Stats
+ .row
+ .col-6
+ h2.text-center Equipment
+ .well.row
+ .col-4
+ .col-6
+ h2.text-center Costume
+ .row
+ .col-6
+ h2.text-center Pet
+ .col-6
+ h2.text-center Mount
+ .row#attributes
+ hr.col-12
+ h2.col-12 Attributes
+ .row.col-6(v-for="(statInfo, stat) in stats")
+ .col-4.attribute-label
+ span.hint(:popover-title='$t(statInfo.title)', popover-placement='right',
+ :popover='$t(statInfo.popover)', popover-trigger='mouseenter')
+ div {{ $t(statInfo.title) }}
+ strong.number {{ statsComputed[stat] }}
+ .col-6
+ ul.bonus-stats
+ li
+ strong Level:
+ | {{statsComputed.levelBonus[stat]}}
+ li
+ strong Equipment:
+ | {{statsComputed.gearBonus[stat]}}
+ li
+ strong Class:
+ | {{statsComputed.classBonus[stat]}}
+ li
+ strong Allocated:
+ | {{user.stats[stat]}}
+ li
+ strong Buffs:
+ | {{user.stats.buffs[stat]}}
+
+ .row
+ .col-4
div
- strong Joined:
- | {{user.auth.timestamps.created}}
+ h3 Basics
+ ul
+ li Health: {{user.stats.hp}}/{{user.stats.maxHealth}}
+ li Mana: {{user.stats.mp}}/{{user.stats.maxMP}}
+ li Gold: {{user.stats.gp}}
+ li Level: {{user.stats.lvl}}
+ li Experience: {{user.stats.exp}}
+
+ div(v-if='user.flags.itemsEnabled')
+ h3 Battle Gear
+ ul
+ li(v-for='(key, itemType) in user.items.gear.equipped', v-if='flatGear[key]')
+ strong {{ flatGear[key].text() }}
+ strong(v-if='flatGear[key].str || flatGear[key].con || flatGear[key].per || flatGear[key].int') :
+ span(v-for='stat in ["str","con","per","int"]', v-if='flatGear[key][stat]') {{flatGear[key][stat]}} {{ $t(stat) }}
+
+ div(v-if='user.preferences.costume')
+ h4(v-once) {{ $t('costume') }}
+ div
+ div(ng-repeat='(key, itemType) in user.items.gear.costume')
+ strong {{flatGear[key].text()}}
+
div
- strong Total Log Ins:
- span {{ $t('totalCheckins', {count: user.loginIncentives}) }}
- div
- | {{getProgressDisplay()}}
- .progress
- .progress-bar(role='progressbar', :aria-valuenow='incentivesProgress', aria-valuemin='0', aria-valuemax='100', :style='{width: incentivesProgress + "%"}')
- span.sr-only {{ incentivesProgress }}% Complete
- // @TODO: Implement in V2 .social
+ h3 Background
+ ul
+ li(v-if='!user.preferences.background') None
+ li(v-if='user.preferences.background') {{ user.preferences.background }}
- .row(v-if='editing')
- h1 Edit Profile
- .col-12
- .alert.alert-info.alert-sm(v-html='$t("communityGuidelinesWarning", managerEmail)')
+ div(ng-if='user.flags.dropsEnabled')
+ h3(v-once) {{ $t('pets') }}
+ ul
+ li(ng-if='user.items.currentPet')
+ | {{ $t('activePet') }}:
+ | {{ formatAnimal(user.items.currentPet, 'pet') }}
+ li
+ | {{ $t('petsFound') }}:
+ | {{ totalCount(user.items.pets) }}
+ li
+ | {{ $t('beastMasterProgress') }}:
+ | {{ beastMasterProgress(user.items.pets) }}
- // TODO use photo-upload instead: https://groups.google.com/forum/?fromgroups=#!topic/derbyjs/xMmADvxBOak
- .form-group
- label {{ $t('displayName') }}
- input.form-control(type='text', :placeholder="$t('fullName')", v-model='editingProfile.name')
- .form-group
- label {{ $t('photoUrl') }}
- input.form-control(type='url', v-model='editingProfile.imageUrl', :placeholder="$t('imageUrl')")
- .form-group
- label {{ $t('about') }}
- textarea.form-control(rows=5, :placeholder="$t('displayBlurbPlaceholder')", v-model='editingProfile.blurb')
- // include ../../shared/formatting-help
- .form-group
- label Facebook
- input.form-control(type='text', placeholder="Paste your link here", v-model='editingProfile.facebook')
- .form-group
- label Instagram
- input.form-control(type='text', placeholder="Paste your link here", v-model='editingProfile.instagram')
- .form-group
- label Twitter
- input.form-control(type='text', placeholder="Paste your link here", v-model='editingProfile.twitter')
+ h3(v-once) {{ $t('mounts') }}
+ ul
+ li(v-if='user.items.currentMount')
+ | {{ $t('activeMount') }}:
+ | {{ formatAnimal(user.items.currentMount, 'mount') }}
+ li
+ | {{ $t('mountsTamed') }}:
+ | {{ totalCount(user.items.mounts) }}
+ li
+ | {{ $t('mountMasterProgress') }}:
+ | {{ mountMasterProgress(user.items.mounts) }}
- .col-3.offset-6.text.center
- button.btn.btn-primary(@click='save()') {{ $t("save") }}
- button.btn.btn-warning(@click='editing = false') {{ $t("cancel") }}
+ .col-4(v-if='user.flags.classSelected && !user.preferences.disableClasses')
+ h3(v-once) {{ $t('characterBuild') }}
+ h4(v-once) {{ $t('class') + ': ' }}
+ span {{ classText }}
+ button.btn.btn-danger.btn-xs(@click='changeClass(null)', v-once) {{ $t('changeClass') }}
+ small.cost 3
+ span.Pet_Currency_Gem1x.inline-gems
+
+ div
+ div
+ p(v-if='userLevel100Plus', v-once) {{ $t('noMoreAllocate') }}
+ p(v-if='user.stats.points || userLevel100Plus')
+ strong.inline
+ | {{user.stats.points}}
+ strong.hint(popover-trigger='mouseenter',
+ popover-placement='right', :popover="$t('levelPopover')") {{ $t('unallocated') }}
+ div
+ fieldset.auto-allocate
+ .checkbox
+ label
+ input(type='checkbox', v-model='user.preferences.automaticAllocation',
+ @change='set({"preferences.automaticAllocation": user.preferences.automaticAllocation, "preferences.allocationMode": "taskbased"})')
+ span.hint(popover-trigger='mouseenter', popover-placement='right', :popover="$t('autoAllocationPop')") {{ $t('autoAllocation') }}
+ form(v-if='user.preferences.automaticAllocation', style='margin-left:1em')
+ .radio
+ label
+ input(type='radio', name='allocationMode', value='flat', v-model='user.preferences.allocationMode',
+ @change='set({"preferences.allocationMode": "flat"})')
+ span.hint(popover-trigger='mouseenter', popover-placement='right', :popover="$t('evenAllocationPop')") {{ $t('evenAllocation') }}
+ .radio
+ label
+ input(type='radio', name='allocationMode', value='classbased',
+ v-model='user.preferences.allocationMode', @change='set({"preferences.allocationMode": "classbased"})')
+ span.hint(popover-trigger='mouseenter', popover-placement='right', :popover="$t('classAllocationPop')") {{ $t('classAllocation') }}
+ .radio
+ label
+ input(type='radio', name='allocationMode', value='taskbased', v-model='user.preferences.allocationMode', @change='set({"preferences.allocationMode": "taskbased"})')
+ span.hint(popover-trigger='mouseenter', popover-placement='right', :popover="$t('taskAllocationPop')") {{ $t('taskAllocation') }}
+ div(v-if='user.preferences.automaticAllocation && !(user.preferences.allocationMode === "taskbased") && (user.stats.points > 0)')
+ button.btn.btn-primary.btn-xs(@click='allocateNow({})', popover-trigger='mouseenter', popover-placement='right', :popover="$t('distributePointsPop')")
+ span.glyphicon.glyphicon-download
+ |
+ | {{ $t('distributePoints') }}
+ .row(v-for='(statInfo, stat) in allocateStatsList')
+ .col-8
+ span.hint(popover-trigger='mouseenter', popover-placement='right', :popover='$t(statInfo.popover)')
+ | {{ $t(statInfo.title) + user.stats[stat] }}
+ .col-4(v-if='user.stats.points', @click='allocate(stat)')
+ button.btn.btn-primary(popover-trigger='mouseenter', popover-placement='right',
+ :popover='$t(statInfo.allocatepop)') +
diff --git a/website/client/components/userMenu/stats.vue b/website/client/components/userMenu/stats.vue
index 7584f57a05..2b4af50f14 100644
--- a/website/client/components/userMenu/stats.vue
+++ b/website/client/components/userMenu/stats.vue
@@ -169,12 +169,10 @@