mirror of
https://github.com/sudoxnym/habitica-self-host.git
synced 2026-04-14 19:47:03 +00:00
Backgrounds / BuyModal / misc (#9009)
* remove buyModal from all views / move to app.vue - show party member selection if card was bought * add .btn style to 'show more' / 'show less' * prevent adding duplicate pinned items - reset pinned gear on rebirth * remove hourglass in items * fix unequip gear from drawer * fix bought item notification * fix background in avatar - avatar position in buyModal
This commit is contained in:
parent
19789eb7ab
commit
87d57dab13
18 changed files with 187 additions and 338 deletions
|
|
@ -10,6 +10,21 @@
|
|||
app-menu
|
||||
.container-fluid
|
||||
app-header
|
||||
buyModal(
|
||||
:item="selectedItemToBuy",
|
||||
:withPin="false",
|
||||
@change="resetItemToBuy($event)",
|
||||
@buyPressed="customPurchase($event)",
|
||||
:genericPurchase="genericPurchase(selectedItemToBuy)",
|
||||
|
||||
)
|
||||
selectMembersModal(
|
||||
:item="selectedCardToBuy",
|
||||
:group="user.party",
|
||||
@change="resetCardToBuy($event)",
|
||||
@memberSelected="memberSelected($event)",
|
||||
)
|
||||
|
||||
div(:class='{sticky: user.preferences.stickyHeader}')
|
||||
router-view
|
||||
app-footer
|
||||
|
|
@ -50,8 +65,12 @@ import AppFooter from './components/appFooter';
|
|||
import notificationsDisplay from './components/notifications';
|
||||
import snackbars from './components/snackbars/notifications';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import BuyModal from './components/shops/buyModal.vue';
|
||||
import SelectMembersModal from 'client/components/selectMembersModal.vue';
|
||||
import notifications from 'client/mixins/notifications';
|
||||
|
||||
export default {
|
||||
mixins: [notifications],
|
||||
name: 'app',
|
||||
components: {
|
||||
AppMenu,
|
||||
|
|
@ -59,10 +78,14 @@ export default {
|
|||
AppFooter,
|
||||
notificationsDisplay,
|
||||
snackbars,
|
||||
BuyModal,
|
||||
SelectMembersModal,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isUserLoaded: false,
|
||||
selectedItemToBuy: null,
|
||||
selectedCardToBuy: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -76,6 +99,10 @@ export default {
|
|||
},
|
||||
},
|
||||
created () {
|
||||
this.$root.$on('buyModal::showItem', (item) => {
|
||||
this.selectedItemToBuy = item;
|
||||
});
|
||||
|
||||
// Set up Error interceptors
|
||||
axios.interceptors.response.use((response) => {
|
||||
if (this.user) {
|
||||
|
|
@ -112,6 +139,44 @@ export default {
|
|||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetItemToBuy ($event) {
|
||||
if (!$event) {
|
||||
this.selectedItemToBuy = null;
|
||||
}
|
||||
},
|
||||
resetCardToBuy ($event) {
|
||||
if (!$event) {
|
||||
this.selectedCardToBuy = null;
|
||||
}
|
||||
},
|
||||
itemSelected (item) {
|
||||
this.selectedItemToBuy = item;
|
||||
},
|
||||
genericPurchase (item) {
|
||||
if (!item)
|
||||
return false;
|
||||
|
||||
if (item.purchaseType === 'card')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
},
|
||||
customPurchase (item) {
|
||||
if (item.purchaseType === 'card') {
|
||||
if (this.user.party._id) {
|
||||
this.selectedCardToBuy = item;
|
||||
} else {
|
||||
this.error(this.$t('errorNotInParty'));
|
||||
}
|
||||
}
|
||||
},
|
||||
memberSelected (member) {
|
||||
this.$store.dispatch('user:castSpell', {key: this.selectedCardToBuy.key, targetId: member.id});
|
||||
this.selectedCardToBuy = null;
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -166,6 +166,10 @@ export default {
|
|||
|
||||
let allowToShowBackground = !this.avatarOnly || this.withBackground;
|
||||
|
||||
if (this.overrideAvatarGear && this.overrideAvatarGear.background) {
|
||||
return `background_${this.overrideAvatarGear.background}`;
|
||||
}
|
||||
|
||||
if (background && allowToShowBackground) {
|
||||
return `background_${this.member.preferences.background}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
|
|||
strong {{set.text}}
|
||||
.col-12(v-if='showPlainBackgroundBlurb(set.identifier, set.items)') {{ $t('incentiveBackgroundsUnlockedWithCheckins') }}
|
||||
.col-4.text-center.customize-option.background-button(v-for='bg in set.items',
|
||||
@click='unlock("background." + bg.key)',
|
||||
@click='backgroundSelected(bg)',
|
||||
:popover-title='bg.text',
|
||||
:popover='bg.notes',
|
||||
popover-trigger='mouseenter')
|
||||
|
|
@ -664,7 +664,7 @@ import hairIcon from 'assets/svg/hair.svg';
|
|||
import backgroundsIcon from 'assets/svg/backgrounds.svg';
|
||||
import gem from 'assets/svg/gem.svg';
|
||||
import pin from 'assets/svg/pin.svg';
|
||||
import { isPinned } from 'common/script/ops/pinnedGearUtils';
|
||||
import isPinned from 'common/script/libs/isPinned';
|
||||
|
||||
let tasksByCategory = {
|
||||
work: [
|
||||
|
|
@ -998,6 +998,9 @@ export default {
|
|||
this.text(this.$t('unpinnedItem', {item: bg.text}));
|
||||
}
|
||||
},
|
||||
backgroundSelected (bg) {
|
||||
this.$root.$emit('buyModal::showItem', bg);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@
|
|||
starBadge(
|
||||
:selected="true",
|
||||
:show="!costume || user.preferences.costume",
|
||||
@click="equip(context.item)",
|
||||
@click="equipItem(context.item)",
|
||||
)
|
||||
div(
|
||||
v-for="group in itemsGroups",
|
||||
|
|
|
|||
|
|
@ -300,15 +300,6 @@ export default {
|
|||
});
|
||||
}
|
||||
|
||||
if (this.user.purchased.plan.consecutive.trinkets) {
|
||||
specialArray.push({
|
||||
key: 'timeTravelers',
|
||||
class: 'inventory_special_trinket',
|
||||
text: this.$t('mysticHourglassPopover'),
|
||||
quantity: this.user.purchased.plan.consecutive.trinkets,
|
||||
});
|
||||
}
|
||||
|
||||
return itemsByType;
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -19,11 +19,30 @@
|
|||
|
||||
div.inner-content
|
||||
slot(name="item", :item="item")
|
||||
div(v-if="showAvatar")
|
||||
avatar(
|
||||
:member="user",
|
||||
:avatarOnly="true",
|
||||
:hideClassBadge="true",
|
||||
:withBackground="true",
|
||||
:overrideAvatarGear="getAvatarOverrides(item)",
|
||||
:spritesMargin="'0px auto 0px -24px'",
|
||||
)
|
||||
item.flat.bordered-item(
|
||||
:item="item",
|
||||
:itemContentClass="item.class",
|
||||
:showPopover="false",
|
||||
v-else-if="item.key != 'gem'"
|
||||
)
|
||||
|
||||
h4.title {{ itemText }}
|
||||
div.text(v-html="itemNotes")
|
||||
|
||||
slot(name="additionalInfo", :item="item")
|
||||
equipmentAttributesGrid.bordered(
|
||||
v-if="showAttributesGrid",
|
||||
:item="item"
|
||||
)
|
||||
|
||||
div(:class="{'notEnough': !this.enoughCurrency(getPriceClass(), item.value)}")
|
||||
span.svg-icon.inline.icon-32(aria-hidden="true", v-html="icons[getPriceClass()]")
|
||||
|
|
@ -58,6 +77,11 @@
|
|||
#buy-modal {
|
||||
@include centeredModal();
|
||||
|
||||
.avatar {
|
||||
cursor: default;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -169,11 +193,21 @@
|
|||
import currencyMixin from './_currencyMixin';
|
||||
import notifications from 'client/mixins/notifications';
|
||||
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
import EquipmentAttributesGrid from './market/equipmentAttributesGrid.vue';
|
||||
|
||||
import Item from 'client/components/inventory/item';
|
||||
import Avatar from 'client/components/avatar';
|
||||
|
||||
export default {
|
||||
mixins: [currencyMixin, notifications],
|
||||
components: {
|
||||
bModal,
|
||||
BalanceInfo,
|
||||
EquipmentAttributesGrid,
|
||||
Item,
|
||||
Avatar,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
|
@ -187,6 +221,15 @@
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
showAvatar () {
|
||||
return ['backgrounds', 'gear', 'mystery_set'].includes(this.item.purchaseType);
|
||||
},
|
||||
|
||||
showAttributesGrid () {
|
||||
return this.item.purchaseType === 'gear';
|
||||
},
|
||||
|
||||
itemText () {
|
||||
if (this.item.text instanceof Function) {
|
||||
return this.item.text();
|
||||
|
|
@ -214,7 +257,9 @@
|
|||
key: this.item.key,
|
||||
currency: this.item.currency,
|
||||
});
|
||||
|
||||
this.purchased(this.item.text);
|
||||
this.$root.$emit('buyModal::boughtItem', this.item);
|
||||
}
|
||||
|
||||
this.$emit('buyPressed', this.item);
|
||||
|
|
@ -224,7 +269,9 @@
|
|||
this.$root.$emit('show::modal', 'buy-gems');
|
||||
},
|
||||
togglePinned () {
|
||||
this.$emit('togglePinned', this.item);
|
||||
if (!this.$store.dispatch('user:togglePinnedItem', {type: this.item.pinType, path: this.item.path})) {
|
||||
this.text(this.$t('unpinnedItem', {item: this.item.text}));
|
||||
}
|
||||
},
|
||||
hideDialog () {
|
||||
this.$root.$emit('hide::modal', 'buy-modal');
|
||||
|
|
@ -232,10 +279,35 @@
|
|||
getPriceClass () {
|
||||
if (this.priceType && this.icons[this.priceType]) {
|
||||
return this.priceType;
|
||||
} else if (this.item.currency && this.icons[this.item.currency]) {
|
||||
return this.item.currency;
|
||||
} else {
|
||||
return 'gold';
|
||||
}
|
||||
},
|
||||
getAvatarOverrides (item) {
|
||||
switch (item.purchaseType) {
|
||||
case 'gear':
|
||||
return {
|
||||
[item.type]: item.key,
|
||||
};
|
||||
case 'backgrounds':
|
||||
return {
|
||||
background: item.key,
|
||||
};
|
||||
case 'mystery_set': {
|
||||
let gear = {};
|
||||
|
||||
item.items.map((setItem) => {
|
||||
gear[setItem.type] = setItem.key;
|
||||
});
|
||||
|
||||
return gear;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
},
|
||||
},
|
||||
props: {
|
||||
item: {
|
||||
|
|
|
|||
|
|
@ -227,49 +227,6 @@
|
|||
:show="true",
|
||||
:count="userItems[drawerTabs[selectedDrawerTab].contentType][ctx.item.key] || 0"
|
||||
)
|
||||
|
||||
buyModal(
|
||||
:item="selectedGearToBuy",
|
||||
priceType="gold",
|
||||
:withPin="true",
|
||||
@change="resetGearToBuy($event)",
|
||||
@togglePinned="togglePinned($event)",
|
||||
)
|
||||
template(slot="item", scope="ctx")
|
||||
div
|
||||
avatar(
|
||||
:member="user",
|
||||
:avatarOnly="true",
|
||||
:withBackground="true",
|
||||
:overrideAvatarGear="memberOverrideAvatarGear(selectedGearToBuy)",
|
||||
:spritesMargin="'0px auto 0px'",
|
||||
)
|
||||
|
||||
template(slot="additionalInfo", scope="ctx")
|
||||
equipmentAttributesGrid.bordered(:item="ctx.item")
|
||||
|
||||
buyModal(
|
||||
:item="selectedItemToBuy",
|
||||
:priceType="selectedItemToBuy ? selectedItemToBuy.currency : ''",
|
||||
@change="resetItemToBuy($event)",
|
||||
@togglePinned="togglePinned($event)",
|
||||
@buyPressed="purchaseCallback($event)",
|
||||
:genericPurchase="selectedItemToBuy != null && selectedItemToBuy.key != 'rebirth_orb'"
|
||||
)
|
||||
template(slot="item", scope="ctx")
|
||||
item.flat.bordered-item(
|
||||
:item="ctx.item",
|
||||
:itemContentClass="ctx.item.class",
|
||||
:showPopover="false",
|
||||
v-if="ctx.item.key != 'gem'"
|
||||
)
|
||||
|
||||
selectMembersModal(
|
||||
:item="selectedCardToBuy",
|
||||
:group="user.party",
|
||||
@change="resetCardToBuy($event)",
|
||||
@memberSelected="memberSelected($event)",
|
||||
)
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
@ -504,10 +461,6 @@ export default {
|
|||
selectedSortItemsBy: 'AZ',
|
||||
|
||||
selectedItemToSell: null,
|
||||
selectedGearToBuy: null,
|
||||
selectedItemToBuy: null,
|
||||
|
||||
selectedCardToBuy: null,
|
||||
|
||||
hideLocked: false,
|
||||
hidePinned: false,
|
||||
|
|
@ -756,21 +709,6 @@ export default {
|
|||
this.selectedItemToSell = null;
|
||||
}
|
||||
},
|
||||
resetGearToBuy ($event) {
|
||||
if (!$event) {
|
||||
this.selectedGearToBuy = null;
|
||||
}
|
||||
},
|
||||
resetItemToBuy ($event) {
|
||||
if (!$event) {
|
||||
this.selectedItemToBuy = null;
|
||||
}
|
||||
},
|
||||
resetCardToBuy ($event) {
|
||||
if (!$event) {
|
||||
this.selectedCardToBuy = null;
|
||||
}
|
||||
},
|
||||
isGearLocked (gear) {
|
||||
if (gear.klass !== this.userStats.class) {
|
||||
return true;
|
||||
|
|
@ -778,47 +716,24 @@ export default {
|
|||
|
||||
return false;
|
||||
},
|
||||
memberOverrideAvatarGear (gear) {
|
||||
return {
|
||||
[gear.type]: gear.key,
|
||||
};
|
||||
},
|
||||
togglePinned (item) {
|
||||
if (!this.$store.dispatch('user:togglePinnedItem', {type: item.pinType, path: item.path})) {
|
||||
this.$parent.showUnpinNotification(item);
|
||||
}
|
||||
},
|
||||
itemSelected (item) {
|
||||
if (item.purchaseType === 'card') {
|
||||
if (this.user.party._id) {
|
||||
this.selectedCardToBuy = item;
|
||||
} else {
|
||||
this.error(this.$t('errorNotInParty'));
|
||||
}
|
||||
} else {
|
||||
this.selectedItemToBuy = item;
|
||||
}
|
||||
this.$root.$emit('buyModal::showItem', item);
|
||||
},
|
||||
featuredItemSelected (item) {
|
||||
if (item.purchaseType === 'gear' && !item.locked) {
|
||||
this.selectedGearToBuy = item;
|
||||
if (item.purchaseType === 'gear') {
|
||||
this.gearSelected(item);
|
||||
} else {
|
||||
this.itemSelected(item);
|
||||
}
|
||||
},
|
||||
gearSelected (item) {
|
||||
if (!item.locked) {
|
||||
this.selectedGearToBuy = item;
|
||||
}
|
||||
},
|
||||
memberSelected (member) {
|
||||
this.$store.dispatch('user:castSpell', {key: this.selectedCardToBuy.key, targetId: member.id});
|
||||
this.selectedCardToBuy = null;
|
||||
},
|
||||
async purchaseCallback (item) {
|
||||
if (item.key === 'rebirth_orb') {
|
||||
await this.$store.dispatch('user:rebirth');
|
||||
window.location.reload(true);
|
||||
this.$root.$emit('buyModal::showItem', item);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@
|
|||
:price="ctx.item.value",
|
||||
:priceType="ctx.item.currency",
|
||||
:emptyItem="false",
|
||||
@click="selectedItemToBuy = ctx.item"
|
||||
@click="selectItemToBuy(ctx.item)"
|
||||
)
|
||||
span(slot="popoverContent", scope="ctx")
|
||||
div
|
||||
|
|
@ -106,23 +106,6 @@
|
|||
)
|
||||
span.svg-icon.inline.icon-12.color(v-html="icons.pin")
|
||||
|
||||
buyModal(
|
||||
:item="selectedItemToBuy",
|
||||
:priceType="selectedItemToBuy ? selectedItemToBuy.currency : ''",
|
||||
:withPin="true",
|
||||
@change="resetItemToBuy($event)",
|
||||
@buyPressed="buyItem($event)"
|
||||
)
|
||||
template(slot="item", scope="scope")
|
||||
div
|
||||
avatar(
|
||||
:member="user",
|
||||
:avatarOnly="true",
|
||||
:withBackground="true",
|
||||
:overrideAvatarGear="memberOverrideAvatarGear(scope.item)",
|
||||
:spritesMargin="'0px auto 0px'",
|
||||
)
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
@ -326,8 +309,6 @@
|
|||
sortItemsBy: ['AZ', 'sortByNumber'],
|
||||
selectedSortItemsBy: 'AZ',
|
||||
|
||||
selectedItemToBuy: null,
|
||||
|
||||
hidePinned: false,
|
||||
|
||||
backgroundUpdate: new Date(),
|
||||
|
|
@ -436,37 +417,19 @@
|
|||
getGrouped (entries) {
|
||||
return _groupBy(entries, 'group');
|
||||
},
|
||||
resetItemToBuy ($event) {
|
||||
if (!$event) {
|
||||
this.selectedItemToBuy = null;
|
||||
}
|
||||
},
|
||||
togglePinned (item) {
|
||||
if (!this.$store.dispatch('user:togglePinnedItem', {type: item.pinType, path: item.path})) {
|
||||
this.$parent.showUnpinNotification(item);
|
||||
}
|
||||
},
|
||||
buyItem (item) {
|
||||
if (item.purchaseType === 'set_mystery') {
|
||||
this.$store.dispatch('shops:purchaseMysterySet', {key: item.key});
|
||||
} else {
|
||||
this.$store.dispatch('shops:purchaseHourglassItem', {type: item.purchaseType, key: item.key});
|
||||
}
|
||||
|
||||
this.backgroundUpdate = new Date();
|
||||
},
|
||||
memberOverrideAvatarGear (set) {
|
||||
let gear = {};
|
||||
|
||||
set.items.map((item) => {
|
||||
gear[item.type] = item.key;
|
||||
});
|
||||
|
||||
return gear;
|
||||
selectItemToBuy (item) {
|
||||
this.$root.$emit('buyModal::showItem', item);
|
||||
},
|
||||
},
|
||||
created () {
|
||||
this.$store.dispatch('shops:fetchTimeTravelers');
|
||||
this.$root.$on('buyModal::boughtItem', () => {
|
||||
this.backgroundUpdate = new Date();
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -77,42 +77,6 @@
|
|||
@openBuyDialog="openBuyDialog($event)"
|
||||
)
|
||||
|
||||
buyModal(
|
||||
:item="selectedItemToBuy",
|
||||
:priceType="selectedItemToBuy ? selectedItemToBuy.currency : ''",
|
||||
@change="resetItemToBuy($event)",
|
||||
@buyPressed="buyItem($event)",
|
||||
@togglePinned="togglePinned($event)"
|
||||
)
|
||||
template(slot="item", scope="ctx")
|
||||
div(v-if="ctx.item.purchaseType === 'gear'")
|
||||
avatar.inline(
|
||||
:member="user",
|
||||
:avatarOnly="true",
|
||||
:withBackground="true",
|
||||
:overrideAvatarGear="memberOverrideAvatarGear(ctx.item)"
|
||||
)
|
||||
|
||||
item.flat(
|
||||
:item="ctx.item",
|
||||
:itemContentClass="ctx.item.class",
|
||||
:showPopover="false",
|
||||
v-else
|
||||
)
|
||||
|
||||
template(slot="additionalInfo", scope="ctx")
|
||||
equipmentAttributesGrid.bordered(
|
||||
:item="ctx.item",
|
||||
v-if="ctx.item.purchaseType === 'gear'"
|
||||
)
|
||||
|
||||
selectMembersModal(
|
||||
:item="selectedCardToBuy",
|
||||
:group="user.party",
|
||||
@change="resetCardToBuy($event)",
|
||||
@memberSelected="memberSelectedToSendCard($event)",
|
||||
)
|
||||
|
||||
spells
|
||||
</template>
|
||||
|
||||
|
|
@ -323,11 +287,7 @@ import cloneDeep from 'lodash/cloneDeep';
|
|||
import { mapState, mapActions } from 'client/libs/store';
|
||||
import taskDefaults from 'common/script/libs/taskDefaults';
|
||||
|
||||
import BuyModal from 'client/components/shops/buyModal.vue';
|
||||
import Item from 'client/components/inventory/item.vue';
|
||||
import Avatar from 'client/components/avatar';
|
||||
import EquipmentAttributesGrid from 'client/components/shops/market/equipmentAttributesGrid.vue';
|
||||
import SelectMembersModal from 'client/components/selectMembersModal.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -335,12 +295,8 @@ export default {
|
|||
TaskModal,
|
||||
bDropdown,
|
||||
bDropdownItem,
|
||||
BuyModal,
|
||||
Item,
|
||||
Avatar,
|
||||
EquipmentAttributesGrid,
|
||||
spells,
|
||||
SelectMembersModal,
|
||||
},
|
||||
directives: {
|
||||
markdown,
|
||||
|
|
@ -367,9 +323,6 @@ export default {
|
|||
newTag: null,
|
||||
editingTask: null,
|
||||
creatingTask: null,
|
||||
|
||||
selectedItemToBuy: null,
|
||||
selectedCardToBuy: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -488,36 +441,8 @@ export default {
|
|||
if (this.temporarilySelectedTags.indexOf(tagId) !== -1) return true;
|
||||
return false;
|
||||
},
|
||||
resetItemToBuy ($event) {
|
||||
if (!$event) {
|
||||
this.selectedItemToBuy = null;
|
||||
}
|
||||
},
|
||||
resetCardToBuy ($event) {
|
||||
if (!$event) {
|
||||
this.selectedCardToBuy = null;
|
||||
}
|
||||
},
|
||||
memberOverrideAvatarGear (gear) {
|
||||
return {
|
||||
[gear.type]: gear.key,
|
||||
};
|
||||
},
|
||||
buyItem (item) {
|
||||
if (item.purchaseType === 'card') {
|
||||
this.selectedCardToBuy = item;
|
||||
} else if (item.currency === 'gold') {
|
||||
this.$store.dispatch('shops:buyItem', {key: item.key});
|
||||
} else {
|
||||
this.$store.dispatch('shops:purchase', {type: item.purchaseType, key: item.key});
|
||||
}
|
||||
},
|
||||
openBuyDialog (rewardItem) {
|
||||
this.selectedItemToBuy = rewardItem;
|
||||
},
|
||||
memberSelectedToSendCard (member) {
|
||||
this.$store.dispatch('user:castSpell', {key: this.selectedCardToBuy.key, targetId: member.id});
|
||||
this.selectedCardToBuy = null;
|
||||
openBuyDialog (item) {
|
||||
this.$root.$emit('buyModal::showItem', item);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
div(v-if="items.length === 0")
|
||||
p(v-once) {{ noItemsLabel }}
|
||||
|
||||
.btn-flat.btn-show-more(
|
||||
.btn.btn-flat.btn-show-more(
|
||||
@click="toggleItemsToShow()",
|
||||
v-if="items.length > itemsPerRow"
|
||||
) {{ showAll ? $t('showLess') : $t('showMore') }}
|
||||
|
|
|
|||
|
|
@ -1,105 +0,0 @@
|
|||
<template lang="pug">
|
||||
.standard-page
|
||||
h1 {{ $t('backgrounds') }}
|
||||
div.customize-menu(v-for='set in backgroundShopSets')
|
||||
h2 {{set.text}}
|
||||
div(v-if='showPlainBackgroundBlurb(set.identifier, set.items)') {{ $t('incentiveBackgroundsUnlockedWithCheckins') }}
|
||||
div(v-if='!ownsSet("background", set.items) && set.identifier !== "incentiveBackgrounds"')
|
||||
//+gemCost(7)
|
||||
button.btn.btn-primary(@click='unlock(setKeys("background", set.items))') {{ $t('unlockSet', {cost: 15}) }}
|
||||
span.Pet_Currency_Gem1x.inline-gems
|
||||
button.customize-option(v-for='bg in set.items',
|
||||
type='button',
|
||||
:class='[`background_${bg.key}`, backgroundLockedStatus(bg.key)]',
|
||||
ng-click='unlock("background." + bg.key)',
|
||||
:popover-title='bg.text',
|
||||
:popover='bg.notes',
|
||||
popover-trigger='mouseenter')
|
||||
i.glyphicon.glyphicon-lock(ng-if='!user.purchased.background[bg.key]')
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
.customize-menu {
|
||||
margin-top: 4em;
|
||||
margin-bottom: 4em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import map from 'lodash/map';
|
||||
import get from 'lodash/get';
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
import { getBackgroundShopSets } from '../../../common/script/libs/shops';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
let backgroundShopSets = getBackgroundShopSets();
|
||||
|
||||
return {
|
||||
backgroundShopSets,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
methods: {
|
||||
showPlainBackgroundBlurb (identifier, set) {
|
||||
return identifier === 'incentiveBackgrounds' && !this.ownsSet('background', set);
|
||||
},
|
||||
ownsSet (type, set) {
|
||||
let setOwnedByUser = find(set, (value, key) => {
|
||||
if (type === 'background') key = value.key;
|
||||
return this.user.purchased[type][key];
|
||||
});
|
||||
|
||||
return Boolean(setOwnedByUser);
|
||||
},
|
||||
/**
|
||||
* For gem-unlockable preferences, (a) if owned, select preference (b) else, purchase
|
||||
* @param path: User.preferences <-> User.purchased maps like User.preferences.skin=abc <-> User.purchased.skin.abc.
|
||||
* Pass in this paramater as "skin.abc". Alternatively, pass as an array ["skin.abc", "skin.xyz"] to unlock sets
|
||||
*/
|
||||
unlock (path) {
|
||||
let fullSet = path.indexOf(',') !== -1;
|
||||
let isBackground = Boolean(path.indexOf('background.'));
|
||||
|
||||
let cost;
|
||||
|
||||
if (isBackground) {
|
||||
cost = fullSet ? 3.75 : 1.75; // (Backgrounds) 15G per set, 7G per individual
|
||||
} else {
|
||||
cost = fullSet ? 1.25 : 0.5; // (Hair, skin, etc) 5G per set, 2G per individual
|
||||
}
|
||||
|
||||
let loginIncentives = ['background.blue', 'background.green', 'background.red', 'background.purple', 'background.yellow', 'background.violet'];
|
||||
if (!loginIncentives.contains(loginIncentives)) {
|
||||
if (fullSet) {
|
||||
if (confirm(window.env.t('purchaseFor', {cost: cost * 4})) !== true) return;
|
||||
// @TODO: implement gem modal
|
||||
// if (this.user.balance < cost) return $rootScope.openModal('buyGems');
|
||||
} else if (!get(this.user, `purchased.${path}`)) {
|
||||
if (confirm(window.env.t('purchaseFor', {cost: cost * 4})) !== true) return;
|
||||
// @TODO: implement gem modal
|
||||
// if (this.user.balance < cost) return $rootScope.openModal('buyGems');
|
||||
}
|
||||
}
|
||||
// @TODO: Add when we implment the user calls
|
||||
// User.unlock({ query:{ path: path } });
|
||||
},
|
||||
setKeys (type, _set) {
|
||||
return map(_set, (v, k) => {
|
||||
if (type === 'background') k = v.key;
|
||||
return `${type}.${k}`;
|
||||
}).join(',');
|
||||
},
|
||||
backgroundLockedStatus (bgKey) {
|
||||
let backgroundClass = 'background-locked';
|
||||
if (this.user.purchased.background[bgKey]) backgroundClass = 'background-unlocked';
|
||||
return backgroundClass;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -87,7 +87,7 @@ export default {
|
|||
this.notify(`${this.sign(val)} ${this.round(val)}`, 'mp', 'glyphicon glyphicon-fire', this.sign(val));
|
||||
},
|
||||
purchased (itemName) {
|
||||
this.notify(this.$t('purchasedItem', {
|
||||
this.text(this.$t('purchasedItem', {
|
||||
itemName,
|
||||
}));
|
||||
},
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ const VideosPage = () => import(/* webpackChunkName: "static" */'./components/st
|
|||
const RegisterLogin = () => import(/* webpackChunkName: "auth" */'./components/auth/registerLogin');
|
||||
|
||||
// User Pages
|
||||
const BackgroundsPage = () => import(/* webpackChunkName: "user" */'./components/userMenu/backgrounds');
|
||||
// const StatsPage = () => import(/* webpackChunkName: "user" */'./components/userMenu/stats');
|
||||
// const AchievementsPage = () => import(/* webpackChunkName: "user" */'./components/userMenu/achievements');
|
||||
const ProfilePage = () => import(/* webpackChunkName: "user" */'./components/userMenu/profilePage');
|
||||
|
|
@ -195,7 +194,6 @@ const router = new VueRouter({
|
|||
path: '/user',
|
||||
component: ParentPage,
|
||||
children: [
|
||||
{ name: 'backgrounds', path: 'backgrounds', component: BackgroundsPage },
|
||||
{ name: 'stats', path: 'stats', component: ProfilePage },
|
||||
{ name: 'achievements', path: 'achievements', component: ProfilePage },
|
||||
{ name: 'profile', path: 'profile', component: ProfilePage },
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ export function purchase (store, params) {
|
|||
|
||||
export function purchaseMysterySet (store, params) {
|
||||
const user = store.state.user.data;
|
||||
let opResult = buyMysterySetOp(user, {params});
|
||||
let opResult = buyMysterySetOp(user, {params, noConfirm: true});
|
||||
|
||||
return {
|
||||
result: opResult,
|
||||
|
|
@ -134,6 +134,10 @@ export function genericPurchase (store, params) {
|
|||
default:
|
||||
if (params.pinType === 'quests' && params.currency === 'gold') {
|
||||
return buyQuestItem(store, params);
|
||||
} else if (params.key === 'rebirth_orb') {
|
||||
return store.dispatch('user:rebirth');
|
||||
} else if (params.currency === 'hourglasses') {
|
||||
return purchaseHourglassItem(store, params);
|
||||
} else {
|
||||
return purchase(store, params);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,10 @@ export function openMysteryItem () {
|
|||
return axios.post('/api/v3/user/open-mystery-item');
|
||||
}
|
||||
|
||||
export function rebirth () {
|
||||
return axios.post('/api/v3/user/rebirth');
|
||||
export async function rebirth () {
|
||||
let result = await axios.post('/api/v3/user/rebirth');
|
||||
|
||||
window.location.reload(true);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ module.exports = function buyMysterySet (user, req = {}, analytics) {
|
|||
throw new NotFound(i18n.t('mysterySetNotFound', req.language));
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined' && window.confirm) { // TODO move to client
|
||||
if (typeof window !== 'undefined' && !req.noConfirm && window.confirm) { // TODO move to client
|
||||
if (!window.confirm(i18n.t('hourglassBuyEquipSetConfirm'))) return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,16 @@ function addPinnedGearByClass (user) {
|
|||
for (let item of newPinnedItems) {
|
||||
let itemInfo = getItemInfo(user, 'marketGear', item);
|
||||
|
||||
user.pinnedItems.push({
|
||||
type: 'marketGear',
|
||||
path: itemInfo.path,
|
||||
const foundIndex = user.pinnedItems.findIndex(pinnedItem => {
|
||||
return pinnedItem.path === itemInfo.path;
|
||||
});
|
||||
|
||||
if (foundIndex === -1) {
|
||||
user.pinnedItems.push({
|
||||
type: 'marketGear',
|
||||
path: itemInfo.path,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import {
|
|||
NotAuthorized,
|
||||
} from '../libs/errors';
|
||||
import equip from './equip';
|
||||
import { removePinnedGearByClass } from './pinnedGearUtils';
|
||||
|
||||
|
||||
const USERSTATSLIST = ['per', 'int', 'con', 'str', 'points', 'gp', 'exp', 'mp'];
|
||||
|
||||
|
|
@ -46,6 +48,8 @@ module.exports = function rebirth (user, tasks = [], req = {}, analytics) {
|
|||
}
|
||||
});
|
||||
|
||||
removePinnedGearByClass(user);
|
||||
|
||||
let stats = user.stats;
|
||||
stats.buffs = {};
|
||||
stats.hp = 50;
|
||||
|
|
|
|||
Loading…
Reference in a new issue