[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:
negue
2017-08-17 00:34:25 +02:00
committed by Keith Holliday
parent 88e6cf7d8a
commit f5cf27a79e
18 changed files with 302 additions and 73 deletions

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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")

View File

@@ -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")

View File

@@ -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()) {

View 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;
}
},
},
};

View File

@@ -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>

View File

@@ -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 {

View File

@@ -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) => {

View File

@@ -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,
}, },

View File

@@ -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: {

View File

@@ -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;
}); });
}, },
}, },

View File

@@ -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(

View File

@@ -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(

View File

@@ -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>

View File

@@ -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;
}, },
}; };
} }

View File

@@ -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,
}, },
}); });

View File

@@ -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;