mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 14:17:22 +01:00
[WIP] Client/multiple fixes shops (#8956)
* reposition FlyingPigs and Hydra * hide count-badge if 0 * fix sortBy hatchable (ignore already hatched pets) * always show animal name * featuredItems, use shopItem objects * fix egg / potion names in market * buyModals: check for price, mark it if not enough available / change buy-button opacity / show purchaseGems button * save itemRows open/collapsed state during session, refactor itemRows for some more performance * pin featured items * show bordered items in market buyModal * fix popover margins / paddings * position pinned items popovers to the left
This commit is contained in:
@@ -54,6 +54,12 @@
|
|||||||
|
|
||||||
.flat .item {
|
.flat .item {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bordered-item .item {
|
||||||
|
background: $gray-700 !important;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-content .item:hover {
|
.drawer-content .item:hover {
|
||||||
|
|||||||
@@ -21,10 +21,17 @@
|
|||||||
line-height: 1.14;
|
line-height: 1.14;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popover-content-text {
|
.popover-content-text:not(:last-child) {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.popover-content-title:last-child {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
.popover-content-text:last-child {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.popover-content-attr {
|
.popover-content-attr {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|||||||
@@ -99,6 +99,7 @@
|
|||||||
:items="sortItems(items[group.key], selectedSortGearBy)",
|
:items="sortItems(items[group.key], selectedSortGearBy)",
|
||||||
:itemWidth=94,
|
:itemWidth=94,
|
||||||
:itemMargin=24,
|
:itemMargin=24,
|
||||||
|
:type="group.key",
|
||||||
:noItemsLabel="$t('noGearItemsOfType', { type: group.label })"
|
:noItemsLabel="$t('noGearItemsOfType', { type: group.label })"
|
||||||
)
|
)
|
||||||
template(slot="item", scope="context")
|
template(slot="item", scope="context")
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
:items="items[group.key]",
|
:items="items[group.key]",
|
||||||
:itemWidth=94,
|
:itemWidth=94,
|
||||||
:itemMargin=24,
|
:itemMargin=24,
|
||||||
|
:type="group.key",
|
||||||
:noItemsLabel="$t('noGearItemsOfType', { type: $t(group.key) })"
|
:noItemsLabel="$t('noGearItemsOfType', { type: $t(group.key) })"
|
||||||
)
|
)
|
||||||
template(slot="item", scope="context")
|
template(slot="item", scope="context")
|
||||||
@@ -67,6 +68,7 @@
|
|||||||
:items="items[group.key]",
|
:items="items[group.key]",
|
||||||
:itemWidth=94,
|
:itemWidth=94,
|
||||||
:itemMargin=24,
|
:itemMargin=24,
|
||||||
|
:type="group.key",
|
||||||
:noItemsLabel="$t('noGearItemsOfType', { type: $t(group.key) })"
|
:noItemsLabel="$t('noGearItemsOfType', { type: $t(group.key) })"
|
||||||
)
|
)
|
||||||
template(slot="item", scope="context")
|
template(slot="item", scope="context")
|
||||||
@@ -94,6 +96,7 @@
|
|||||||
:items="items[group.key]",
|
:items="items[group.key]",
|
||||||
:itemWidth=94,
|
:itemWidth=94,
|
||||||
:itemMargin=24,
|
:itemMargin=24,
|
||||||
|
:type="group.key",
|
||||||
:noItemsLabel="$t('noGearItemsOfType', { type: $t(group.key) })"
|
:noItemsLabel="$t('noGearItemsOfType', { type: $t(group.key) })"
|
||||||
)
|
)
|
||||||
template(slot="item", scope="context")
|
template(slot="item", scope="context")
|
||||||
|
|||||||
@@ -84,6 +84,7 @@
|
|||||||
:items="pets(petGroup, hideMissing, selectedSortBy, searchTextThrottled)",
|
:items="pets(petGroup, hideMissing, selectedSortBy, searchTextThrottled)",
|
||||||
:itemWidth=94,
|
:itemWidth=94,
|
||||||
:itemMargin=24,
|
:itemMargin=24,
|
||||||
|
:type="petGroup.key",
|
||||||
)
|
)
|
||||||
template(slot="item", scope="context")
|
template(slot="item", scope="context")
|
||||||
div(
|
div(
|
||||||
@@ -99,14 +100,12 @@
|
|||||||
:popoverPosition="'top'",
|
:popoverPosition="'top'",
|
||||||
:progress="context.item.progress",
|
:progress="context.item.progress",
|
||||||
:emptyItem="!context.item.isOwned()",
|
:emptyItem="!context.item.isOwned()",
|
||||||
:showPopover="context.item.isOwned() || context.item.isHatchable()",
|
:showPopover="true",
|
||||||
:highlightBorder="highlightPet == context.item.key",
|
:highlightBorder="highlightPet == context.item.key",
|
||||||
@click="petClicked(context.item)"
|
@click="petClicked(context.item)"
|
||||||
)
|
)
|
||||||
span(slot="popoverContent")
|
span(slot="popoverContent")
|
||||||
div(v-if="context.item.isOwned()")
|
div.hatchablePopover(v-if="context.item.isHatchable()")
|
||||||
h4.popover-content-title {{ context.item.name }}
|
|
||||||
div.hatchablePopover(v-else-if="context.item.isHatchable()")
|
|
||||||
h4.popover-content-title {{ context.item.name }}
|
h4.popover-content-title {{ context.item.name }}
|
||||||
div.popover-content-text(v-html="$t('haveHatchablePet', { potion: context.item.potionName, egg: context.item.eggName })")
|
div.popover-content-text(v-html="$t('haveHatchablePet', { potion: context.item.potionName, egg: context.item.eggName })")
|
||||||
div.potionEggGroup
|
div.potionEggGroup
|
||||||
@@ -115,6 +114,9 @@
|
|||||||
div.potionEggBackground
|
div.potionEggBackground
|
||||||
div(:class="'Pet_Egg_'+context.item.eggKey")
|
div(:class="'Pet_Egg_'+context.item.eggKey")
|
||||||
|
|
||||||
|
div(v-else)
|
||||||
|
h4.popover-content-title {{ context.item.name }}
|
||||||
|
|
||||||
template(slot="itemBadge", scope="context")
|
template(slot="itemBadge", scope="context")
|
||||||
starBadge(
|
starBadge(
|
||||||
:selected="context.item.key === currentPet",
|
:selected="context.item.key === currentPet",
|
||||||
@@ -138,6 +140,7 @@
|
|||||||
:items="mounts(mountGroup, hideMissing, selectedSortBy, searchTextThrottled)",
|
:items="mounts(mountGroup, hideMissing, selectedSortBy, searchTextThrottled)",
|
||||||
:itemWidth=94,
|
:itemWidth=94,
|
||||||
:itemMargin=24,
|
:itemMargin=24,
|
||||||
|
:type="mountGroup.key",
|
||||||
)
|
)
|
||||||
template(slot="item", scope="context")
|
template(slot="item", scope="context")
|
||||||
mountItem(
|
mountItem(
|
||||||
@@ -146,7 +149,7 @@
|
|||||||
:key="context.item.key",
|
:key="context.item.key",
|
||||||
:popoverPosition="'top'",
|
:popoverPosition="'top'",
|
||||||
:emptyItem="!context.item.isOwned()",
|
:emptyItem="!context.item.isOwned()",
|
||||||
:showPopover="context.item.isOwned()",
|
:showPopover="true",
|
||||||
@click="selectMount(context.item)"
|
@click="selectMount(context.item)"
|
||||||
)
|
)
|
||||||
span(slot="popoverContent")
|
span(slot="popoverContent")
|
||||||
@@ -273,11 +276,18 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stable .item .item-content.Pet {
|
.stable .item .item-content.Pet:not(.FlyingPig) {
|
||||||
position: absolute;
|
|
||||||
top: -28px;
|
top: -28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stable .item .item-content.FlyingPig {
|
||||||
|
top: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stable .item .item-content.Pet-Dragon-Hydra {
|
||||||
|
top: -16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.hatchablePopover {
|
.hatchablePopover {
|
||||||
width: 180px
|
width: 180px
|
||||||
}
|
}
|
||||||
@@ -833,7 +843,7 @@
|
|||||||
|
|
||||||
getPetItemClass (pet) {
|
getPetItemClass (pet) {
|
||||||
if (pet.isOwned()) {
|
if (pet.isOwned()) {
|
||||||
return `Pet Pet-${pet.key}`;
|
return `Pet Pet-${pet.key} ${pet.eggKey}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pet.mountOwned()) {
|
if (pet.mountOwned()) {
|
||||||
|
|||||||
25
website/client/components/shops/_currencyMixin.js
Normal file
25
website/client/components/shops/_currencyMixin.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { mapState, mapGetters } from 'client/libs/store';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
userGems: 'user:gems',
|
||||||
|
}),
|
||||||
|
...mapState({
|
||||||
|
userHourglasses: 'user.data.purchased.plan.consecutive.trinkets',
|
||||||
|
userGold: 'user.data.stats.gp',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
enoughCurrency (currency, amount) {
|
||||||
|
switch (currency) {
|
||||||
|
case 'gold':
|
||||||
|
return this.userGold >= amount;
|
||||||
|
case 'gems':
|
||||||
|
return this.userGems >= amount;
|
||||||
|
case 'hourglasses':
|
||||||
|
return this.userHourglasses >= amount;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
div
|
div
|
||||||
.svg-icon(v-if="withHourglass",v-html="icons.hourglasses")
|
span(
|
||||||
span(v-if="withHourglass") {{userHourglasses | roundBigNumber}}
|
v-for="currency of currencies",
|
||||||
|
:key="currency.key"
|
||||||
.svg-icon(v-html="icons.gem")
|
)
|
||||||
span {{userGems | roundBigNumber}}
|
.svg-icon(v-html="currency.icon")
|
||||||
.svg-icon(v-html="icons.gold")
|
span(:class="{'notEnough': currency.notEnough}") {{ currency.value | roundBigNumber}}
|
||||||
span {{userGold | roundBigNumber}}
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -31,15 +30,21 @@ span {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notEnough {
|
||||||
|
color: #f23035 !important;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState, mapGetters } from 'client/libs/store';
|
|
||||||
import svgGem from 'assets/svg/gem.svg';
|
import svgGem from 'assets/svg/gem.svg';
|
||||||
import svgGold from 'assets/svg/gold.svg';
|
import svgGold from 'assets/svg/gold.svg';
|
||||||
import svgHourglasses from 'assets/svg/hourglass.svg';
|
import svgHourglasses from 'assets/svg/hourglass.svg';
|
||||||
|
|
||||||
|
import currencyMixin from './_currencyMixin';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [currencyMixin],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
icons: Object.freeze({
|
icons: Object.freeze({
|
||||||
@@ -50,18 +55,48 @@ span {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
currencies () {
|
||||||
userGems: 'user:gems',
|
let currencies = [];
|
||||||
}),
|
|
||||||
...mapState({
|
if (this.withHourglass) {
|
||||||
userHourglasses: 'user.data.purchased.plan.consecutive.trinkets',
|
currencies.push({
|
||||||
userGold: 'user.data.stats.gp',
|
type: 'hourglasses',
|
||||||
}),
|
icon: this.icons.hourglasses,
|
||||||
|
value: this.userHourglasses,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
currencies.push({
|
||||||
|
type: 'gems',
|
||||||
|
icon: this.icons.gem,
|
||||||
|
value: this.userGems,
|
||||||
|
});
|
||||||
|
|
||||||
|
currencies.push({
|
||||||
|
type: 'gold',
|
||||||
|
icon: this.icons.gold,
|
||||||
|
value: this.userGold,
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let currency of currencies) {
|
||||||
|
if (currency.type === this.currencyNeeded && !this.enoughCurrency(this.currencyNeeded, this.amountNeeded)) {
|
||||||
|
currency.notEnough = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return currencies;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
withHourglass: {
|
withHourglass: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
},
|
},
|
||||||
|
currencyNeeded: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
amountNeeded: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -25,15 +25,28 @@
|
|||||||
|
|
||||||
slot(name="additionalInfo", :item="item")
|
slot(name="additionalInfo", :item="item")
|
||||||
|
|
||||||
div
|
div(:class="{'notEnough': !this.enoughCurrency(getPriceClass(), item.value)}")
|
||||||
span.svg-icon.inline.icon-32(aria-hidden="true", v-html="icons[getSvgClass()]")
|
span.svg-icon.inline.icon-32(aria-hidden="true", v-html="icons[getPriceClass()]")
|
||||||
span.value(:class="getSvgClass()") {{ item.value }}
|
span.value(:class="getPriceClass()") {{ item.value }}
|
||||||
|
|
||||||
button.btn.btn-primary(@click="buyItem()") {{ $t('buyNow') }}
|
button.btn.btn-primary(
|
||||||
|
@click="purchaseGems()",
|
||||||
|
v-if="getPriceClass() === 'gems' && !this.enoughCurrency(getPriceClass(), item.value)"
|
||||||
|
) {{ $t('purchaseGems') }}
|
||||||
|
|
||||||
|
button.btn.btn-primary(
|
||||||
|
@click="buyItem()",
|
||||||
|
v-else,
|
||||||
|
:class="{'notEnough': !this.enoughCurrency(getPriceClass(), item.value)}"
|
||||||
|
) {{ $t('buyNow') }}
|
||||||
|
|
||||||
div.clearfix(slot="modal-footer")
|
div.clearfix(slot="modal-footer")
|
||||||
span.balance.float-left {{ $t('yourBalance') }}
|
span.balance.float-left {{ $t('yourBalance') }}
|
||||||
balanceInfo(:withHourglass="getSvgClass() === 'hourglasses'").float-right
|
balanceInfo(
|
||||||
|
:withHourglass="getPriceClass() === 'hourglasses'",
|
||||||
|
:currencyNeeded="getPriceClass()",
|
||||||
|
:amountNeeded="item.value"
|
||||||
|
).float-right
|
||||||
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
@@ -136,7 +149,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notEnough {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@@ -150,8 +166,10 @@
|
|||||||
import svgPin from 'assets/svg/pin.svg';
|
import svgPin from 'assets/svg/pin.svg';
|
||||||
|
|
||||||
import BalanceInfo from './balanceInfo.vue';
|
import BalanceInfo from './balanceInfo.vue';
|
||||||
|
import currencyMixin from './_currencyMixin';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [currencyMixin],
|
||||||
components: {
|
components: {
|
||||||
bModal,
|
bModal,
|
||||||
BalanceInfo,
|
BalanceInfo,
|
||||||
@@ -191,13 +209,16 @@
|
|||||||
this.$emit('buyPressed', this.item);
|
this.$emit('buyPressed', this.item);
|
||||||
this.hideDialog();
|
this.hideDialog();
|
||||||
},
|
},
|
||||||
|
purchaseGems () {
|
||||||
|
this.$root.$emit('show::modal', 'buy-gems');
|
||||||
|
},
|
||||||
togglePinned () {
|
togglePinned () {
|
||||||
this.$emit('togglePinned', this.item);
|
this.$emit('togglePinned', this.item);
|
||||||
},
|
},
|
||||||
hideDialog () {
|
hideDialog () {
|
||||||
this.$root.$emit('hide::modal', 'buy-modal');
|
this.$root.$emit('hide::modal', 'buy-modal');
|
||||||
},
|
},
|
||||||
getSvgClass () {
|
getPriceClass () {
|
||||||
if (this.priceType && this.icons[this.priceType]) {
|
if (this.priceType && this.icons[this.priceType]) {
|
||||||
return this.priceType;
|
return this.priceType;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -53,6 +53,12 @@
|
|||||||
:popoverPosition="'top'",
|
:popoverPosition="'top'",
|
||||||
@click="selectedGearToBuy = item"
|
@click="selectedGearToBuy = item"
|
||||||
)
|
)
|
||||||
|
template(slot="itemBadge", scope="ctx")
|
||||||
|
span.badge.badge-pill.badge-item.badge-svg(
|
||||||
|
:class="{'item-selected-badge': ctx.item.pinned, 'hide': !ctx.item.pinned}",
|
||||||
|
@click.prevent.stop="togglePinned(ctx.item)"
|
||||||
|
)
|
||||||
|
span.svg-icon.inline.icon-12.color(v-html="icons.pin")
|
||||||
|
|
||||||
h1.mb-0.page-header(v-once) {{ $t('market') }}
|
h1.mb-0.page-header(v-once) {{ $t('market') }}
|
||||||
|
|
||||||
@@ -92,8 +98,7 @@
|
|||||||
:items="filteredGear(selectedGroupGearByClass, searchTextThrottled, selectedSortGearBy, hideLocked, hidePinned)",
|
:items="filteredGear(selectedGroupGearByClass, searchTextThrottled, selectedSortGearBy, hideLocked, hidePinned)",
|
||||||
:itemWidth=94,
|
:itemWidth=94,
|
||||||
:itemMargin=24,
|
:itemMargin=24,
|
||||||
:showAllLabel="$t('showAllGeneric', { type: getClassName(selectedGroupGearByClass) + ' '+$t('equipment') })",
|
:type="'gear'",
|
||||||
:showLessLabel="$t('showLessGeneric', { type: getClassName(selectedGroupGearByClass) + ' '+$t('equipment') })"
|
|
||||||
)
|
)
|
||||||
template(slot="item", scope="ctx")
|
template(slot="item", scope="ctx")
|
||||||
shopItem(
|
shopItem(
|
||||||
@@ -146,7 +151,7 @@
|
|||||||
|
|
||||||
template(slot="itemBadge", scope="ctx")
|
template(slot="itemBadge", scope="ctx")
|
||||||
countBadge(
|
countBadge(
|
||||||
:show="true",
|
:show="userItems[item.purchaseType][item.key] != 0",
|
||||||
:count="userItems[item.purchaseType][item.key] || 0"
|
:count="userItems[item.purchaseType][item.key] || 0"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -196,12 +201,13 @@
|
|||||||
:count="userItems[drawerTabs[selectedDrawerTab].contentType][ctx.item.key] || 0"
|
:count="userItems[drawerTabs[selectedDrawerTab].contentType][ctx.item.key] || 0"
|
||||||
)
|
)
|
||||||
span(slot="popoverContent")
|
span(slot="popoverContent")
|
||||||
h4.popover-content-title {{ ctx.item.text() }}
|
h4.popover-content-title {{ getItemName(selectedDrawerItemType, ctx.item) }}
|
||||||
|
|
||||||
sellModal(
|
sellModal(
|
||||||
:item="selectedItemToSell",
|
:item="selectedItemToSell",
|
||||||
:itemType="selectedDrawerItemType",
|
:itemType="selectedDrawerItemType",
|
||||||
:itemCount="selectedItemToSell != null ? userItems[drawerTabs[selectedDrawerTab].contentType][selectedItemToSell.key] : 0",
|
:itemCount="selectedItemToSell != null ? userItems[drawerTabs[selectedDrawerTab].contentType][selectedItemToSell.key] : 0",
|
||||||
|
:text="selectedItemToSell != null ? getItemName(selectedDrawerItemType, selectedItemToSell) : ''",
|
||||||
@change="resetItemToSell($event)"
|
@change="resetItemToSell($event)"
|
||||||
)
|
)
|
||||||
template(slot="item", scope="ctx")
|
template(slot="item", scope="ctx")
|
||||||
@@ -244,7 +250,7 @@
|
|||||||
@togglePinned="togglePinned($event)"
|
@togglePinned="togglePinned($event)"
|
||||||
)
|
)
|
||||||
template(slot="item", scope="ctx")
|
template(slot="item", scope="ctx")
|
||||||
item.flat(
|
item.flat.bordered-item(
|
||||||
:item="ctx.item",
|
:item="ctx.item",
|
||||||
:itemContentClass="ctx.item.class",
|
:itemContentClass="ctx.item.class",
|
||||||
:showPopover="false"
|
:showPopover="false"
|
||||||
@@ -302,6 +308,11 @@
|
|||||||
padding: 24px 24px 10px;
|
padding: 24px 24px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item-wrapper.bordered-item .item {
|
||||||
|
width: 112px;
|
||||||
|
height: 112px;
|
||||||
|
}
|
||||||
|
|
||||||
.market {
|
.market {
|
||||||
.avatar {
|
.avatar {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
@@ -398,6 +409,7 @@
|
|||||||
import _filter from 'lodash/filter';
|
import _filter from 'lodash/filter';
|
||||||
import _sortBy from 'lodash/sortBy';
|
import _sortBy from 'lodash/sortBy';
|
||||||
import _map from 'lodash/map';
|
import _map from 'lodash/map';
|
||||||
|
import _get from 'lodash/get';
|
||||||
import _throttle from 'lodash/throttle';
|
import _throttle from 'lodash/throttle';
|
||||||
|
|
||||||
import _isPinned from '../_isPinned';
|
import _isPinned from '../_isPinned';
|
||||||
@@ -520,7 +532,10 @@ export default {
|
|||||||
|
|
||||||
featuredItems () {
|
featuredItems () {
|
||||||
return featuredItems.market.map(i => {
|
return featuredItems.market.map(i => {
|
||||||
return getItemInfo(this.user, 'marketGear', this.content.gear.flat[i]);
|
let newItem = getItemInfo(this.user, i.type, _get(this.content, i.path));
|
||||||
|
newItem.pinned = _isPinned(this.user, newItem);
|
||||||
|
|
||||||
|
return newItem;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -571,6 +586,16 @@ export default {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getItemName (type, item) {
|
||||||
|
switch (type) {
|
||||||
|
case 'eggs':
|
||||||
|
return this.$t('egg', {eggType: item.text()});
|
||||||
|
case 'hatchingPotions':
|
||||||
|
return this.$t('potion', {potionType: item.text()});
|
||||||
|
default:
|
||||||
|
return item.text();
|
||||||
|
}
|
||||||
|
},
|
||||||
filteredGear (groupByClass, searchBy, sortBy, hideLocked, hidePinned) {
|
filteredGear (groupByClass, searchBy, sortBy, hideLocked, hidePinned) {
|
||||||
let result = _filter(this.content.gear.flat, ['klass', groupByClass]);
|
let result = _filter(this.content.gear.flat, ['klass', groupByClass]);
|
||||||
result = _map(result, (e) => {
|
result = _map(result, (e) => {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
div.inner-content
|
div.inner-content
|
||||||
slot(name="item", :item="item")
|
slot(name="item", :item="item")
|
||||||
|
|
||||||
h4.title {{ item.text() }}
|
h4.title {{ text ? text : item.text() }}
|
||||||
div.text {{ item.notes() }}
|
div.text {{ item.notes() }}
|
||||||
|
|
||||||
div
|
div
|
||||||
@@ -176,6 +176,9 @@
|
|||||||
itemType: {
|
itemType: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
itemCount: {
|
itemCount: {
|
||||||
type: Number,
|
type: Number,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -29,7 +29,17 @@
|
|||||||
span.svg-icon.inline.icon-32(aria-hidden="true", v-html="(priceType === 'gems') ? icons.gem : icons.gold")
|
span.svg-icon.inline.icon-32(aria-hidden="true", v-html="(priceType === 'gems') ? icons.gem : icons.gold")
|
||||||
span.value(:class="priceType") {{ item.value }}
|
span.value(:class="priceType") {{ item.value }}
|
||||||
|
|
||||||
button.btn.btn-primary(@click="buyItem()") {{ $t('buyNow') }}
|
button.btn.btn-primary(
|
||||||
|
@click="purchaseGems()",
|
||||||
|
v-if="priceType === 'gems' && !this.enoughCurrency(priceType, item.value)"
|
||||||
|
) {{ $t('purchaseGems') }}
|
||||||
|
|
||||||
|
|
||||||
|
button.btn.btn-primary(
|
||||||
|
@click="buyItem()",
|
||||||
|
v-else,
|
||||||
|
:class="{'notEnough': !this.enoughCurrency(priceType, item.value)}"
|
||||||
|
) {{ $t('buyNow') }}
|
||||||
|
|
||||||
div.right-sidebar(v-if="item.drop")
|
div.right-sidebar(v-if="item.drop")
|
||||||
h3(v-once) {{ $t('rewards') }}
|
h3(v-once) {{ $t('rewards') }}
|
||||||
@@ -46,7 +56,10 @@
|
|||||||
|
|
||||||
div.clearfix(slot="modal-footer")
|
div.clearfix(slot="modal-footer")
|
||||||
span.balance.float-left {{ $t('yourBalance') }}
|
span.balance.float-left {{ $t('yourBalance') }}
|
||||||
balanceInfo.float-right
|
balanceInfo(
|
||||||
|
:currencyNeeded="priceType",
|
||||||
|
:amountNeeded="item.value"
|
||||||
|
).float-right
|
||||||
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
@@ -186,6 +199,12 @@
|
|||||||
color: $white;
|
color: $white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.notEnough {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@@ -202,8 +221,10 @@
|
|||||||
import svgExperience from 'assets/svg/experience.svg';
|
import svgExperience from 'assets/svg/experience.svg';
|
||||||
|
|
||||||
import BalanceInfo from '../balanceInfo.vue';
|
import BalanceInfo from '../balanceInfo.vue';
|
||||||
|
import currencyMixin from '../_currencyMixin';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [currencyMixin],
|
||||||
components: {
|
components: {
|
||||||
bModal,
|
bModal,
|
||||||
BalanceInfo,
|
BalanceInfo,
|
||||||
@@ -284,6 +305,10 @@
|
|||||||
return `Unknown type: ${drop.type}`;
|
return `Unknown type: ${drop.type}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
purchaseGems () {
|
||||||
|
this.$root.$emit('show::modal', 'buy-gems');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
item: {
|
item: {
|
||||||
|
|||||||
@@ -59,6 +59,14 @@
|
|||||||
h4.popover-content-title {{ item.text }}
|
h4.popover-content-title {{ item.text }}
|
||||||
.popover-content-text(v-html="item.notes")
|
.popover-content-text(v-html="item.notes")
|
||||||
|
|
||||||
|
template(slot="itemBadge", scope="ctx")
|
||||||
|
span.badge.badge-pill.badge-item.badge-svg(
|
||||||
|
:class="{'item-selected-badge': ctx.item.pinned, 'hide': !ctx.item.pinned}",
|
||||||
|
@click.prevent.stop="togglePinned(ctx.item)"
|
||||||
|
)
|
||||||
|
span.svg-icon.inline.icon-12.color(v-html="icons.pin")
|
||||||
|
|
||||||
|
|
||||||
h1.mb-0.page-header(v-once) {{ $t('quests') }}
|
h1.mb-0.page-header(v-once) {{ $t('quests') }}
|
||||||
|
|
||||||
.clearfix
|
.clearfix
|
||||||
@@ -84,6 +92,7 @@
|
|||||||
:items="questItems(category, selectedSortItemsBy, searchTextThrottled, hideLocked, hidePinned)",
|
:items="questItems(category, selectedSortItemsBy, searchTextThrottled, hideLocked, hidePinned)",
|
||||||
:itemWidth=94,
|
:itemWidth=94,
|
||||||
:itemMargin=24,
|
:itemMargin=24,
|
||||||
|
:type="'pet_quests'",
|
||||||
)
|
)
|
||||||
template(slot="item", scope="ctx")
|
template(slot="item", scope="ctx")
|
||||||
shopItem(
|
shopItem(
|
||||||
@@ -338,6 +347,7 @@
|
|||||||
import _throttle from 'lodash/throttle';
|
import _throttle from 'lodash/throttle';
|
||||||
import _groupBy from 'lodash/groupBy';
|
import _groupBy from 'lodash/groupBy';
|
||||||
import _map from 'lodash/map';
|
import _map from 'lodash/map';
|
||||||
|
import _get from 'lodash/get';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -403,7 +413,10 @@ export default {
|
|||||||
|
|
||||||
featuredItems () {
|
featuredItems () {
|
||||||
return featuredItems.quests.map(i => {
|
return featuredItems.quests.map(i => {
|
||||||
return getItemInfo(this.user, 'quest', this.content.quests[i]);
|
let newItem = getItemInfo(this.user, i.type, _get(this.content, i.path));
|
||||||
|
newItem.pinned = _isPinned(this.user, newItem);
|
||||||
|
|
||||||
|
return newItem;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -78,6 +78,7 @@
|
|||||||
:items="travelersItems(category, selectedSortItemsBy, searchTextThrottled, hidePinned)",
|
:items="travelersItems(category, selectedSortItemsBy, searchTextThrottled, hidePinned)",
|
||||||
:itemWidth=94,
|
:itemWidth=94,
|
||||||
:itemMargin=24,
|
:itemMargin=24,
|
||||||
|
:type="category.identifier",
|
||||||
)
|
)
|
||||||
template(slot="item", scope="ctx")
|
template(slot="item", scope="ctx")
|
||||||
shopItem(
|
shopItem(
|
||||||
|
|||||||
@@ -25,7 +25,8 @@
|
|||||||
:item="reward",
|
:item="reward",
|
||||||
:key="reward.key",
|
:key="reward.key",
|
||||||
:highlightBorder="reward.isSuggested",
|
:highlightBorder="reward.isSuggested",
|
||||||
@click="openBuyDialog(reward)"
|
@click="openBuyDialog(reward)",
|
||||||
|
:popoverPosition="'left'"
|
||||||
)
|
)
|
||||||
|
|
||||||
.column-background(
|
.column-background(
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
.item-rows
|
.item-rows
|
||||||
div.items(v-resize="500", @resized="currentWidth = $event.width")
|
div.items(v-resize="500", @resized="setCurrentWidth($event)")
|
||||||
template(v-for="item in itemsToShow(showAll)")
|
template(v-for="item in itemsToShow(showAll)")
|
||||||
slot(
|
slot(
|
||||||
name="item",
|
name="item",
|
||||||
:item="item",
|
:item="item"
|
||||||
)
|
)
|
||||||
|
|
||||||
div(v-if="items.length === 0")
|
div(v-if="items.length === 0")
|
||||||
p(v-once) {{ noItemsLabel }}
|
p(v-once) {{ noItemsLabel }}
|
||||||
|
|
||||||
.btn-flat.btn-show-more(
|
.btn-flat.btn-show-more(
|
||||||
@click="showAll = !showAll",
|
@click="toggleItemsToShow()",
|
||||||
v-if="items.length > itemsPerRow()"
|
v-if="items.length > itemsPerRow"
|
||||||
) {{ showAll ? $t('showLess') : $t('showMore') }}
|
) {{ showAll ? $t('showLess') : $t('showMore') }}
|
||||||
|
|
||||||
div.fill-height(v-else)
|
div.fill-height(v-else)
|
||||||
@@ -27,14 +27,22 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ResizeDirective from 'client/directives/resize.directive';
|
import ResizeDirective from 'client/directives/resize.directive';
|
||||||
|
import { mapState } from 'client/libs/store';
|
||||||
|
|
||||||
import _take from 'lodash/take';
|
import _take from 'lodash/take';
|
||||||
import _drop from 'lodash/drop';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
directives: {
|
directives: {
|
||||||
resize: ResizeDirective,
|
resize: ResizeDirective,
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
openedItemRows: 'openedItemRows',
|
||||||
|
}),
|
||||||
|
itemsPerRow () {
|
||||||
|
return Math.floor(this.currentWidth / (this.itemWidth + this.itemMargin));
|
||||||
|
},
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
currentWidth: 0,
|
currentWidth: 0,
|
||||||
@@ -44,27 +52,47 @@
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
itemsToShow (showAll) {
|
toggleItemsToShow () {
|
||||||
let itemsPerRow = this.itemsPerRow();
|
this.showAll = !this.showAll;
|
||||||
let rowsToShow = showAll ? Math.ceil(this.items.length / itemsPerRow) : 1;
|
|
||||||
let result = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < rowsToShow; i++) {
|
let array = this.$store.state.openedItemRows;
|
||||||
let skipped = _drop(this.items, i * itemsPerRow);
|
if (this.showAll) {
|
||||||
let row = _take(skipped, itemsPerRow);
|
array.push(this.type);
|
||||||
result = result.concat(row);
|
} else {
|
||||||
|
let index = array.indexOf(this.type);
|
||||||
|
|
||||||
|
if (index > -1) {
|
||||||
|
array.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemsToShow (showAll) {
|
||||||
|
let itemsLength = this.items.length;
|
||||||
|
|
||||||
|
if (itemsLength === 0)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
let itemsPerRow = this.itemsPerRow;
|
||||||
|
|
||||||
|
if (showAll || itemsLength <= itemsPerRow) {
|
||||||
|
return this.items;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return _take(this.items, itemsPerRow);
|
||||||
},
|
},
|
||||||
itemsPerRow () {
|
setCurrentWidth ($event) {
|
||||||
return Math.floor(this.currentWidth / (this.itemWidth + this.itemMargin));
|
if (this.currentWidth !== $event.width) {
|
||||||
|
this.currentWidth = $event.width;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
items: {
|
items: {
|
||||||
type: Array,
|
type: Array,
|
||||||
},
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
itemWidth: {
|
itemWidth: {
|
||||||
type: Number,
|
type: Number,
|
||||||
},
|
},
|
||||||
@@ -75,5 +103,8 @@
|
|||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
created () {
|
||||||
|
this.showAll = this.openedItemRows.includes(this.type);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default function createAnimal (egg, potion, type, content, userItems) {
|
|||||||
return type === 'pet' && this.isOwned() && !this.mountOwned();
|
return type === 'pet' && this.isOwned() && !this.mountOwned();
|
||||||
},
|
},
|
||||||
isHatchable () {
|
isHatchable () {
|
||||||
return userItems.eggs[egg.key] > 0 && userItems.hatchingPotions[potion.key] > 0;
|
return !this.isOwned() & userItems.eggs[egg.key] > 0 && userItems.hatchingPotions[potion.key] > 0;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ export default function () {
|
|||||||
constants: deepFreeze({...commonConstants, DAY_MAPPING}),
|
constants: deepFreeze({...commonConstants, DAY_MAPPING}),
|
||||||
hideHeader: false,
|
hideHeader: false,
|
||||||
viewingMembers: [],
|
viewingMembers: [],
|
||||||
|
openedItemRows: [],
|
||||||
castingSpell: false,
|
castingSpell: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,19 +1,40 @@
|
|||||||
const featuredItems = {
|
const featuredItems = {
|
||||||
market: [
|
market: [
|
||||||
'head_armoire_vikingHelm',
|
{
|
||||||
'weapon_special_1',
|
type: 'armoire',
|
||||||
'shield_special_0',
|
path: 'armoire',
|
||||||
'armor_warrior_5',
|
},
|
||||||
],
|
{
|
||||||
quests: [
|
type: 'hatchingPotion',
|
||||||
'dilatoryDistress1',
|
path: 'hatchingPotions.Golden',
|
||||||
'dilatoryDistress2',
|
},
|
||||||
'dilatoryDistress3',
|
{
|
||||||
],
|
type: 'food',
|
||||||
seasonal: 'summerMage',
|
path: 'food.Saddle',
|
||||||
timeTravelers: [
|
},
|
||||||
|
],
|
||||||
|
quests: [
|
||||||
|
{
|
||||||
|
type: 'quest',
|
||||||
|
path: 'quests.gryphon',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'quest',
|
||||||
|
path: 'quests.dilatoryDistress1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'quest',
|
||||||
|
path: 'quests.nudibranch',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'quest',
|
||||||
|
path: 'quests.taskwoodsTerror1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
seasonal: 'summerMage',
|
||||||
|
timeTravelers: [
|
||||||
// TODO
|
// TODO
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export default featuredItems;
|
export default featuredItems;
|
||||||
|
|||||||
Reference in New Issue
Block a user