mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 22:27:26 +01:00
Refactor/market vue (#10601)
* extract inventoryDrawer from market * show scrollbar only if needed * extract featuredItemsHeader / pinUtils * extract pageLayout * extract layoutSection / filterDropdown - fix sortByNumber * rollback sortByNumber order-fix * move equipment lists out of the layout-section (for now) * refactor sellModal * extract checkbox * extract equipment section * extract category row * revert scroll - remove sellModal item template * fix(lint): commas and semis * Created category item component (#10613) * extract filter sidebar * fix gemCount - fix raising the item count if the item wasn't previously owned * fixes #10659 * remove unneeded method
This commit is contained in:
@@ -29,7 +29,6 @@ div
|
|||||||
buyModal(
|
buyModal(
|
||||||
:item="selectedItemToBuy || {}",
|
:item="selectedItemToBuy || {}",
|
||||||
:withPin="true",
|
:withPin="true",
|
||||||
@change="resetItemToBuy($event)",
|
|
||||||
@buyPressed="customPurchase($event)",
|
@buyPressed="customPurchase($event)",
|
||||||
:genericPurchase="genericPurchase(selectedItemToBuy)",
|
:genericPurchase="genericPurchase(selectedItemToBuy)",
|
||||||
|
|
||||||
@@ -567,13 +566,6 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resetItemToBuy ($event) {
|
|
||||||
// @TODO: Do we need this? I think selecting a new item
|
|
||||||
// overwrites. @negue might know
|
|
||||||
if (!$event && this.selectedItemToBuy.purchaseType !== 'card') {
|
|
||||||
this.selectedItemToBuy = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemSelected (item) {
|
itemSelected (item) {
|
||||||
this.selectedItemToBuy = item;
|
this.selectedItemToBuy = item;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ div
|
|||||||
triggers="hover",
|
triggers="hover",
|
||||||
placement="top",
|
placement="top",
|
||||||
)
|
)
|
||||||
h4.popover-content-title {{ item.text() }}
|
h4.popover-content-title {{ itemName || item.text() }}
|
||||||
div.popover-content-text(v-html="item.notes()")
|
div.popover-content-text(v-html="item.notes()")
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -45,6 +45,9 @@ export default {
|
|||||||
itemContentClass: {
|
itemContentClass: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
|
itemName: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
active: {
|
active: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -145,47 +145,17 @@
|
|||||||
.btn.btn-flat.btn-show-more(@click="setShowMore(mountGroup.key)", v-if='mountGroup.key !== "specialMounts"')
|
.btn.btn-flat.btn-show-more(@click="setShowMore(mountGroup.key)", v-if='mountGroup.key !== "specialMounts"')
|
||||||
| {{ $_openedItemRows_isToggled(mountGroup.key) ? $t('showLess') : $t('showMore') }}
|
| {{ $_openedItemRows_isToggled(mountGroup.key) ? $t('showLess') : $t('showMore') }}
|
||||||
|
|
||||||
drawer(:title="$t('quickInventory')",
|
inventoryDrawer
|
||||||
:errorMessage="(!hasDrawerTabItems(selectedDrawerTab)) ? ((selectedDrawerTab === 0) ? $t('noFoodAvailable') : $t('noSaddlesAvailable')) : null")
|
template(slot="item", slot-scope="ctx")
|
||||||
div(slot="drawer-header")
|
foodItem(
|
||||||
.drawer-tab-container
|
:item="ctx.item",
|
||||||
.drawer-tab.text-right
|
:itemCount="ctx.itemCount",
|
||||||
a.drawer-tab-text(
|
:itemContentClass="ctx.itemClass",
|
||||||
@click="selectedDrawerTab = 0",
|
:active="currentDraggingFood === ctx.item",
|
||||||
:class="{'drawer-tab-text-active': selectedDrawerTab === 0}",
|
@itemDragEnd="onDragEnd()",
|
||||||
) {{ drawerTabs[0].label }}
|
@itemDragStart="onDragStart($event, ctx.item)",
|
||||||
.clearfix
|
@itemClick="onFoodClicked($event, ctx.item)"
|
||||||
.drawer-tab.float-left
|
)
|
||||||
a.drawer-tab-text(
|
|
||||||
@click="selectedDrawerTab = 1",
|
|
||||||
:class="{ 'drawer-tab-text-active': selectedDrawerTab === 1 }",
|
|
||||||
) {{ drawerTabs[1].label }}
|
|
||||||
|
|
||||||
#petLikeToEatStable.drawer-help-text(v-once)
|
|
||||||
| {{ $t('petLikeToEat') + ' ' }}
|
|
||||||
span.svg-icon.inline.icon-16(v-html="icons.information")
|
|
||||||
b-popover(
|
|
||||||
target="petLikeToEatStable"
|
|
||||||
placement="top"
|
|
||||||
)
|
|
||||||
.popover-content-text(v-html="$t('petLikeToEatText')", v-once)
|
|
||||||
drawer-slider(
|
|
||||||
:items="drawerTabs[selectedDrawerTab].items",
|
|
||||||
:scrollButtonsVisible="hasDrawerTabItems(selectedDrawerTab)",
|
|
||||||
slot="drawer-slider",
|
|
||||||
:itemWidth=94,
|
|
||||||
:itemMargin=24,
|
|
||||||
:itemType="selectedDrawerTab"
|
|
||||||
)
|
|
||||||
template(slot="item", slot-scope="context")
|
|
||||||
foodItem(
|
|
||||||
:item="context.item",
|
|
||||||
:itemCount="userItems.food[context.item.key]",
|
|
||||||
:active="currentDraggingFood == context.item",
|
|
||||||
@itemDragEnd="onDragEnd()",
|
|
||||||
@itemDragStart="onDragStart($event, context.item)",
|
|
||||||
@itemClick="onFoodClicked($event, context.item)"
|
|
||||||
)
|
|
||||||
hatchedPetDialog(:hideText="true")
|
hatchedPetDialog(:hideText="true")
|
||||||
div.foodInfo(ref="dragginFoodInfo")
|
div.foodInfo(ref="dragginFoodInfo")
|
||||||
div(v-if="currentDraggingFood != null")
|
div(v-if="currentDraggingFood != null")
|
||||||
@@ -284,9 +254,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-slider .items {
|
|
||||||
height: 114px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-backdrop.fade.show {
|
.modal-backdrop.fade.show {
|
||||||
background-color: $purple-50;
|
background-color: $purple-50;
|
||||||
@@ -386,6 +353,7 @@
|
|||||||
import StarBadge from 'client/components/ui/starBadge';
|
import StarBadge from 'client/components/ui/starBadge';
|
||||||
import CountBadge from 'client/components/ui/countBadge';
|
import CountBadge from 'client/components/ui/countBadge';
|
||||||
import DrawerSlider from 'client/components/ui/drawerSlider';
|
import DrawerSlider from 'client/components/ui/drawerSlider';
|
||||||
|
import InventoryDrawer from 'client/components/shared/inventoryDrawer';
|
||||||
|
|
||||||
import ResizeDirective from 'client/directives/resize.directive';
|
import ResizeDirective from 'client/directives/resize.directive';
|
||||||
import DragDropDirective from 'client/directives/dragdrop.directive';
|
import DragDropDirective from 'client/directives/dragdrop.directive';
|
||||||
@@ -425,6 +393,7 @@
|
|||||||
MountRaisedModal,
|
MountRaisedModal,
|
||||||
WelcomeModal,
|
WelcomeModal,
|
||||||
HatchingModal,
|
HatchingModal,
|
||||||
|
InventoryDrawer,
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
resize: ResizeDirective,
|
resize: ResizeDirective,
|
||||||
|
|||||||
169
website/client/components/shared/inventoryDrawer.vue
Normal file
169
website/client/components/shared/inventoryDrawer.vue
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
drawer.inventoryDrawer(
|
||||||
|
:title="$t('quickInventory')"
|
||||||
|
:errorMessage="inventoryDrawerErrorMessage(selectedDrawerItemType)"
|
||||||
|
)
|
||||||
|
div(slot="drawer-header")
|
||||||
|
drawer-header-tabs(
|
||||||
|
:tabs="filteredTabs",
|
||||||
|
@changedPosition="tabSelected($event)"
|
||||||
|
)
|
||||||
|
div(slot="right-item")
|
||||||
|
#petLikeToEatMarket.drawer-help-text(v-once)
|
||||||
|
| {{ $t('petLikeToEat') + ' ' }}
|
||||||
|
span.svg-icon.inline.icon-16(v-html="icons.information")
|
||||||
|
b-popover(
|
||||||
|
target="petLikeToEatMarket",
|
||||||
|
:placement="'top'",
|
||||||
|
)
|
||||||
|
.popover-content-text(v-html="$t('petLikeToEatText')", v-once)
|
||||||
|
|
||||||
|
drawer-slider(
|
||||||
|
v-if="hasOwnedItemsForType(selectedDrawerItemType)"
|
||||||
|
:items="ownedItems(selectedDrawerItemType) || []",
|
||||||
|
slot="drawer-slider",
|
||||||
|
:itemWidth=94,
|
||||||
|
:itemMargin=24,
|
||||||
|
:itemType="selectedDrawerTab"
|
||||||
|
)
|
||||||
|
template(slot="item", slot-scope="ctx")
|
||||||
|
slot(
|
||||||
|
name="item",
|
||||||
|
:item="ctx.item",
|
||||||
|
:itemClass="getItemClass(selectedDrawerContentType, ctx.item.key)",
|
||||||
|
:itemCount="userItems[selectedDrawerContentType][ctx.item.key] || 0",
|
||||||
|
:itemName="getItemName(selectedDrawerItemType, ctx.item)",
|
||||||
|
:itemType="selectedDrawerItemType"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {mapState} from 'client/libs/store';
|
||||||
|
import inventoryUtils from 'client/mixins/inventoryUtils';
|
||||||
|
import svgInformation from 'assets/svg/information.svg';
|
||||||
|
import _filter from 'lodash/filter';
|
||||||
|
|
||||||
|
import CountBadge from 'client/components/ui/countBadge';
|
||||||
|
import Item from 'client/components/inventory/item';
|
||||||
|
import Drawer from 'client/components/ui/drawer';
|
||||||
|
import DrawerSlider from 'client/components/ui/drawerSlider';
|
||||||
|
import DrawerHeaderTabs from 'client/components/ui/drawerHeaderTabs';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [inventoryUtils],
|
||||||
|
components: {
|
||||||
|
Item,
|
||||||
|
CountBadge,
|
||||||
|
Drawer,
|
||||||
|
DrawerSlider,
|
||||||
|
DrawerHeaderTabs,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
defaultSelectedTab: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
showEggs: Boolean,
|
||||||
|
showPotions: Boolean,
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
drawerTabs: [
|
||||||
|
{
|
||||||
|
key: 'eggs',
|
||||||
|
label: this.$t('eggs'),
|
||||||
|
show: () => this.showEggs,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'food',
|
||||||
|
label: this.$t('foodTitle'),
|
||||||
|
show: () => true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'hatchingPotions',
|
||||||
|
label: this.$t('hatchingPotions'),
|
||||||
|
show: () => this.showPotions,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'special',
|
||||||
|
contentType: 'food',
|
||||||
|
label: this.$t('special'),
|
||||||
|
show: () => true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selectedDrawerTab: this.defaultSelectedTab,
|
||||||
|
|
||||||
|
icons: Object.freeze({
|
||||||
|
information: svgInformation,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
content: 'content',
|
||||||
|
userItems: 'user.data.items',
|
||||||
|
}),
|
||||||
|
selectedDrawerItemType () {
|
||||||
|
return this.filteredTabs[this.selectedDrawerTab].key;
|
||||||
|
},
|
||||||
|
selectedDrawerContentType () {
|
||||||
|
return this.filteredTabs[this.selectedDrawerTab].contentType ||
|
||||||
|
this.selectedDrawerItemType;
|
||||||
|
},
|
||||||
|
filteredTabs () {
|
||||||
|
return this.drawerTabs.filter(t => t.show());
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
ownedItems (type) {
|
||||||
|
let mappedItems = _filter(this.content[type], i => {
|
||||||
|
return this.userItems[type][i.key] > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'food':
|
||||||
|
return _filter(mappedItems, f => {
|
||||||
|
return f.key !== 'Saddle';
|
||||||
|
});
|
||||||
|
case 'special':
|
||||||
|
if (this.userItems.food.Saddle) {
|
||||||
|
return _filter(this.content.food, f => {
|
||||||
|
return f.key === 'Saddle';
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return mappedItems;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tabSelected ($event) {
|
||||||
|
this.selectedDrawerTab = $event;
|
||||||
|
},
|
||||||
|
hasOwnedItemsForType (type) {
|
||||||
|
return this.ownedItems(type).length > 0;
|
||||||
|
},
|
||||||
|
inventoryDrawerErrorMessage (type) {
|
||||||
|
if (!this.hasOwnedItemsForType(type)) {
|
||||||
|
switch (type) {
|
||||||
|
case 'food': return this.$t('noFoodAvailable');
|
||||||
|
case 'special': return this.$t('noSaddlesAvailable');
|
||||||
|
default:
|
||||||
|
// @TODO: Change any places using similar locales from `pets.json` and use these new locales from 'inventory.json'
|
||||||
|
return this.$t('noItemsAvailableForType', {type: this.$t(`${type}ItemType`)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.inventoryDrawer {
|
||||||
|
.drawer-slider {
|
||||||
|
height: 126px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
126
website/client/components/shops/featuredItemsHeader.vue
Normal file
126
website/client/components/shops/featuredItemsHeader.vue
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
div.featuredItems
|
||||||
|
.background(:class="{broken: broken}")
|
||||||
|
.background(:class="{cracked: broken, broken: broken}")
|
||||||
|
div.npc
|
||||||
|
div.featured-label
|
||||||
|
span.rectangle
|
||||||
|
span.text {{npcName}}
|
||||||
|
span.rectangle
|
||||||
|
div.content
|
||||||
|
div.featured-label.with-border
|
||||||
|
span.rectangle
|
||||||
|
span.text {{ featuredText }}
|
||||||
|
span.rectangle
|
||||||
|
|
||||||
|
div.items.margin-center
|
||||||
|
shopItem(
|
||||||
|
v-for="item in featuredItems",
|
||||||
|
:key="item.key",
|
||||||
|
:item="item",
|
||||||
|
:price="item.value",
|
||||||
|
:itemContentClass="'shop_'+item.key",
|
||||||
|
:emptyItem="false",
|
||||||
|
:popoverPosition="'top'",
|
||||||
|
@click="featuredItemSelected(item)"
|
||||||
|
)
|
||||||
|
template(slot="itemBadge", slot-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")
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ShopItem from './shopItem';
|
||||||
|
|
||||||
|
import pinUtils from 'client/mixins/pinUtils';
|
||||||
|
|
||||||
|
import svgPin from 'assets/svg/pin.svg';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [pinUtils],
|
||||||
|
props: {
|
||||||
|
broken: Boolean,
|
||||||
|
npcName: String,
|
||||||
|
featuredText: String,
|
||||||
|
featuredItems: Array,
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
ShopItem,
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
icons: Object.freeze({
|
||||||
|
pin: svgPin,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
featuredItemSelected (item) {
|
||||||
|
this.$emit('featuredItemSelected', item);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.featuredItems {
|
||||||
|
height: 216px;
|
||||||
|
|
||||||
|
.background {
|
||||||
|
width: 100%;
|
||||||
|
height: 216px;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
z-index: 1; // Always cover background.
|
||||||
|
}
|
||||||
|
|
||||||
|
.npc {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 216px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.background.broken {
|
||||||
|
background: url('~assets/images/npc/broken/market_broken_background.png');
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
.background.cracked {
|
||||||
|
background: url('~assets/images/npc/broken/market_broken_layer.png');
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
.broken .npc {
|
||||||
|
background: url('~assets/images/npc/broken/market_broken_npc.png');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.featured-label {
|
||||||
|
margin: 24px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 768px) {
|
||||||
|
.featuredItems .content {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -11,17 +11,11 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import SecondaryMenu from 'client/components/secondaryMenu';
|
import SecondaryMenu from 'client/components/secondaryMenu';
|
||||||
import notifications from 'client/mixins/notifications';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [notifications],
|
|
||||||
components: {
|
components: {
|
||||||
SecondaryMenu,
|
SecondaryMenu,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {},
|
||||||
showUnpinNotification (item) {
|
|
||||||
this.text(this.$t('unpinnedItem', {item: item.text}));
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
52
website/client/components/shops/market/categoryItem.vue
Normal file
52
website/client/components/shops/market/categoryItem.vue
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
div
|
||||||
|
countBadge(
|
||||||
|
v-if="item.showCount !== false",
|
||||||
|
:show="true",
|
||||||
|
:count="count"
|
||||||
|
)
|
||||||
|
.badge.badge-pill.badge-purple.gems-left(v-if='item.key === "gem"')
|
||||||
|
| {{ gemsLeft }}
|
||||||
|
span.badge.badge-pill.badge-item.badge-svg(
|
||||||
|
:class="{'item-selected-badge': item.pinned, 'hide': !item.pinned}",
|
||||||
|
@click.prevent.stop="togglePinned(item)"
|
||||||
|
)
|
||||||
|
span.svg-icon.inline.icon-12.color(v-html="icons.pin")
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapState } from 'client/libs/store';
|
||||||
|
import CountBadge from 'client/components/ui/countBadge';
|
||||||
|
|
||||||
|
import svgPin from 'assets/svg/pin.svg';
|
||||||
|
import planGemLimits from 'common/script/libs/planGemLimits';
|
||||||
|
import pinUtils from '../../../mixins/pinUtils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [pinUtils],
|
||||||
|
props: ['item'],
|
||||||
|
components: {
|
||||||
|
CountBadge,
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
icons: Object.freeze({
|
||||||
|
pin: svgPin,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
user: 'user.data',
|
||||||
|
userItems: 'user.data.items',
|
||||||
|
}),
|
||||||
|
count () {
|
||||||
|
return this.userItems[this.item.purchaseType][this.item.key];
|
||||||
|
},
|
||||||
|
gemsLeft () {
|
||||||
|
if (!this.user.purchased.plan) return 0;
|
||||||
|
return planGemLimits.convCap + this.user.purchased.plan.consecutive.gemCapExtra - this.user.purchased.plan.gemsBought;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
94
website/client/components/shops/market/categoryRow.vue
Normal file
94
website/client/components/shops/market/categoryRow.vue
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
div.items
|
||||||
|
shopItem(v-for="item in sortedMarketItems",
|
||||||
|
:key="item.key",
|
||||||
|
:item="item",
|
||||||
|
:emptyItem="false",
|
||||||
|
:popoverPosition="'top'",
|
||||||
|
@click="itemSelected(item)")
|
||||||
|
span(slot="popoverContent")
|
||||||
|
strong(v-if='item.key === "gem" && gemsLeft === 0') {{ $t('maxBuyGems') }}
|
||||||
|
h4.popover-content-title {{ item.text }}
|
||||||
|
template(slot="itemBadge", slot-scope="ctx")
|
||||||
|
category-item(:item='ctx.item')
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapState } from 'client/libs/store';
|
||||||
|
import pinUtils from 'client/mixins/pinUtils';
|
||||||
|
import planGemLimits from 'common/script/libs/planGemLimits';
|
||||||
|
|
||||||
|
import ShopItem from '../shopItem';
|
||||||
|
import CategoryItem from './CategoryItem';
|
||||||
|
|
||||||
|
import _filter from 'lodash/filter';
|
||||||
|
import _sortBy from 'lodash/sortBy';
|
||||||
|
import _map from 'lodash/map';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [pinUtils],
|
||||||
|
props: ['hideLocked', 'hidePinned', 'searchBy', 'sortBy', 'category'],
|
||||||
|
components: {
|
||||||
|
CategoryItem,
|
||||||
|
ShopItem,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
content: 'content',
|
||||||
|
user: 'user.data',
|
||||||
|
userItems: 'user.data.items',
|
||||||
|
userStats: 'user.data.stats',
|
||||||
|
}),
|
||||||
|
gemsLeft () {
|
||||||
|
if (!this.user.purchased.plan) return 0;
|
||||||
|
return planGemLimits.convCap + this.user.purchased.plan.consecutive.gemCapExtra - this.user.purchased.plan.gemsBought;
|
||||||
|
},
|
||||||
|
sortedMarketItems () {
|
||||||
|
let result = _map(this.category.items, (e) => {
|
||||||
|
return {
|
||||||
|
...e,
|
||||||
|
pinned: this.isPinned(e),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
result = _filter(result, (item) => {
|
||||||
|
if (this.hidePinned && item.pinned) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.searchBy) {
|
||||||
|
let foundPosition = item.text.toLowerCase().indexOf(this.searchBy);
|
||||||
|
if (foundPosition === -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
switch (this.sortBy) {
|
||||||
|
case 'AZ': {
|
||||||
|
result = _sortBy(result, ['text']);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'sortByNumber': {
|
||||||
|
result = _sortBy(result, item => {
|
||||||
|
if (item.showCount === false) return 0;
|
||||||
|
|
||||||
|
return this.userItems[item.purchaseType][item.key] || 0;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
itemSelected (item) {
|
||||||
|
this.$root.$emit('buyModal::showItem', item);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
167
website/client/components/shops/market/equipmentSection.vue
Normal file
167
website/client/components/shops/market/equipmentSection.vue
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
layout-section(:title="$t('equipment')")
|
||||||
|
div(slot="filters")
|
||||||
|
filter-dropdown(
|
||||||
|
:label="$t('class')",
|
||||||
|
:initialItem="selectedGearCategory",
|
||||||
|
:items="marketGearCategories",
|
||||||
|
:withIcon="true",
|
||||||
|
@selected="selectedGroupGearByClass = $event.id"
|
||||||
|
)
|
||||||
|
span(slot="item", slot-scope="ctx")
|
||||||
|
span.svg-icon.inline.icon-16(v-html="icons[ctx.item.id]")
|
||||||
|
span.text {{ getClassName(ctx.item.id) }}
|
||||||
|
|
||||||
|
filter-dropdown(
|
||||||
|
:label="$t('sortBy')",
|
||||||
|
:initialItem="selectedSortGearBy",
|
||||||
|
:items="sortGearBy",
|
||||||
|
@selected="selectedSortGearBy = $event"
|
||||||
|
)
|
||||||
|
span(slot="item", slot-scope="ctx")
|
||||||
|
span.text {{ $t(ctx.item.id) }}
|
||||||
|
|
||||||
|
itemRows(
|
||||||
|
:items="sortedGearItems",
|
||||||
|
:itemWidth=94,
|
||||||
|
:itemMargin=24,
|
||||||
|
:type="'gear'",
|
||||||
|
:noItemsLabel="$t('noGearItemsOfClass')",
|
||||||
|
slot="content"
|
||||||
|
)
|
||||||
|
template(slot="item", slot-scope="ctx")
|
||||||
|
shopItem(
|
||||||
|
:key="ctx.item.key",
|
||||||
|
:item="ctx.item",
|
||||||
|
:emptyItem="userItems.gear[ctx.item.key] === undefined",
|
||||||
|
:popoverPosition="'top'",
|
||||||
|
@click="gearSelected(ctx.item)"
|
||||||
|
)
|
||||||
|
|
||||||
|
template(slot="itemBadge", slot-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")
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {mapState} from 'client/libs/store';
|
||||||
|
import LayoutSection from 'client/components/ui/layoutSection';
|
||||||
|
import FilterDropdown from 'client/components/ui/filterDropdown';
|
||||||
|
import ItemRows from 'client/components/ui/itemRows';
|
||||||
|
import ShopItem from '../shopItem';
|
||||||
|
|
||||||
|
import shops from 'common/script/libs/shops';
|
||||||
|
|
||||||
|
import svgPin from 'assets/svg/pin.svg';
|
||||||
|
import svgWarrior from 'assets/svg/warrior.svg';
|
||||||
|
import svgWizard from 'assets/svg/wizard.svg';
|
||||||
|
import svgRogue from 'assets/svg/rogue.svg';
|
||||||
|
import svgHealer from 'assets/svg/healer.svg';
|
||||||
|
|
||||||
|
import _filter from 'lodash/filter';
|
||||||
|
import _sortBy from 'lodash/sortBy';
|
||||||
|
|
||||||
|
const sortGearTypes = ['sortByType', 'sortByPrice', 'sortByCon', 'sortByPer', 'sortByStr', 'sortByInt'].map(g => ({id: g}));
|
||||||
|
|
||||||
|
const sortGearTypeMap = {
|
||||||
|
sortByType: 'type',
|
||||||
|
sortByPrice: 'value',
|
||||||
|
sortByCon: 'con',
|
||||||
|
sortByStr: 'str',
|
||||||
|
sortByInt: 'int',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['hideLocked', 'hidePinned', 'searchBy'],
|
||||||
|
components: {
|
||||||
|
LayoutSection,
|
||||||
|
FilterDropdown,
|
||||||
|
ItemRows,
|
||||||
|
ShopItem,
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
sortGearBy: sortGearTypes,
|
||||||
|
selectedSortGearBy: sortGearTypes[0],
|
||||||
|
selectedGroupGearByClass: '',
|
||||||
|
icons: Object.freeze({
|
||||||
|
pin: svgPin,
|
||||||
|
warrior: svgWarrior,
|
||||||
|
wizard: svgWizard,
|
||||||
|
rogue: svgRogue,
|
||||||
|
healer: svgHealer,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
content: 'content',
|
||||||
|
user: 'user.data',
|
||||||
|
userItems: 'user.data.items',
|
||||||
|
userStats: 'user.data.stats',
|
||||||
|
}),
|
||||||
|
marketGearCategories () {
|
||||||
|
return shops.getMarketGearCategories(this.user).map(c => {
|
||||||
|
c.id = c.identifier;
|
||||||
|
|
||||||
|
return c;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
selectedGearCategory () {
|
||||||
|
return this.marketGearCategories.filter(c => c.id === this.selectedGroupGearByClass)[0];
|
||||||
|
},
|
||||||
|
sortedGearItems () {
|
||||||
|
let category = _filter(this.marketGearCategories, ['identifier', this.selectedGroupGearByClass]);
|
||||||
|
|
||||||
|
let result = _filter(category[0].items, (gear) => {
|
||||||
|
if (this.hideLocked && gear.locked) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.hidePinned && gear.pinned) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.searchBy) {
|
||||||
|
let foundPosition = gear.text.toLowerCase().indexOf(this.searchBy);
|
||||||
|
if (foundPosition === -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hide already owned
|
||||||
|
return !this.userItems.gear.owned[gear.key];
|
||||||
|
});
|
||||||
|
|
||||||
|
// first all unlocked
|
||||||
|
// then the selected sort
|
||||||
|
result = _sortBy(result, [(item) => item.locked, sortGearTypeMap[this.selectedSortGearBy.id]]);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getClassName (classType) {
|
||||||
|
if (classType === 'wizard') {
|
||||||
|
return this.$t('mage');
|
||||||
|
} else {
|
||||||
|
return this.$t(classType);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
gearSelected (item) {
|
||||||
|
if (!item.locked) {
|
||||||
|
this.$root.$emit('buyModal::showItem', item);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.selectedGroupGearByClass = this.userStats.class;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
46
website/client/components/shops/market/filter.vue
Normal file
46
website/client/components/shops/market/filter.vue
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.form
|
||||||
|
h2(v-once) {{ $t('filter') }}
|
||||||
|
.form-group
|
||||||
|
checkbox(
|
||||||
|
v-for="category in categories",
|
||||||
|
:key="category.identifier",
|
||||||
|
:id="`category-${category.identifier}`",
|
||||||
|
:checked.sync="viewOptions[category.identifier].selected",
|
||||||
|
:text="category.text"
|
||||||
|
)
|
||||||
|
div.form-group.clearfix
|
||||||
|
h3.float-left(v-once) {{ $t('hideLocked') }}
|
||||||
|
toggle-switch.float-right(
|
||||||
|
v-model="lockedChecked",
|
||||||
|
@change="$emit('update:hideLocked', $event)"
|
||||||
|
)
|
||||||
|
div.form-group.clearfix
|
||||||
|
h3.float-left(v-once) {{ $t('hidePinned') }}
|
||||||
|
toggle-switch.float-right(
|
||||||
|
v-model="pinnedChecked",
|
||||||
|
@change="$emit('update:hidePinned', $event)"
|
||||||
|
)
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Checkbox from 'client/components/ui/checkbox';
|
||||||
|
import toggleSwitch from 'client/components/ui/toggleSwitch';
|
||||||
|
export default {
|
||||||
|
props: ['hidePinned', 'hideLocked', 'categories', 'viewOptions'],
|
||||||
|
components: {
|
||||||
|
Checkbox,
|
||||||
|
toggleSwitch,
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
lockedChecked: this.hideLocked,
|
||||||
|
pinnedChecked: this.hidePinned,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,245 +1,79 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
.row.market
|
page-layout.market
|
||||||
.standard-sidebar.d-none.d-sm-block
|
div(slot="sidebar")
|
||||||
.form-group
|
.form-group
|
||||||
input.form-control.input-search(type="text", v-model="searchText", :placeholder="$t('search')")
|
input.form-control.input-search(type="text", v-model="searchText", :placeholder="$t('search')")
|
||||||
.form
|
market-filter(
|
||||||
h2(v-once) {{ $t('filter') }}
|
:categories="categories",
|
||||||
.form-group
|
:hideLocked.sync="hideLocked",
|
||||||
.form-check(
|
:hidePinned.sync="hidePinned",
|
||||||
v-for="category in categories",
|
:viewOptions="viewOptions"
|
||||||
:key="category.identifier",
|
)
|
||||||
)
|
div(slot="page")
|
||||||
.custom-control.custom-checkbox
|
featured-items-header(
|
||||||
input.custom-control-input(type="checkbox", v-model="viewOptions[category.identifier].selected", :id="`category-${category.identifier}`")
|
:broken="broken",
|
||||||
label.custom-control-label(v-once, :for="`category-${category.identifier}`") {{ category.text }}
|
:npcName="'Alex'",
|
||||||
div.form-group.clearfix
|
:featuredText="market.featured.text",
|
||||||
h3.float-left(v-once) {{ $t('hideLocked') }}
|
:featuredItems="market.featured.items"
|
||||||
toggle-switch.float-right(
|
@featuredItemSelected="featuredItemSelected($event)"
|
||||||
v-model="hideLocked",
|
)
|
||||||
)
|
|
||||||
div.form-group.clearfix
|
|
||||||
h3.float-left(v-once) {{ $t('hidePinned') }}
|
|
||||||
toggle-switch.float-right(
|
|
||||||
v-model="hidePinned",
|
|
||||||
)
|
|
||||||
.standard-page
|
|
||||||
div.featuredItems
|
|
||||||
.background(:class="{broken: broken}")
|
|
||||||
.background(:class="{cracked: broken, broken: broken}")
|
|
||||||
div.npc
|
|
||||||
div.featured-label
|
|
||||||
span.rectangle
|
|
||||||
span.text Alex
|
|
||||||
span.rectangle
|
|
||||||
div.content
|
|
||||||
div.featured-label.with-border
|
|
||||||
span.rectangle
|
|
||||||
span.text {{ market.featured.text }}
|
|
||||||
span.rectangle
|
|
||||||
|
|
||||||
div.items.margin-center
|
|
||||||
shopItem(
|
|
||||||
v-for="item in market.featured.items",
|
|
||||||
:key="item.key",
|
|
||||||
:item="item",
|
|
||||||
:price="item.value",
|
|
||||||
:itemContentClass="'shop_'+item.key",
|
|
||||||
:emptyItem="false",
|
|
||||||
:popoverPosition="'top'",
|
|
||||||
@click="featuredItemSelected(item)"
|
|
||||||
)
|
|
||||||
template(slot="itemBadge", slot-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-4.page-header(v-once) {{ $t('market') }}
|
h1.mb-4.page-header(v-once) {{ $t('market') }}
|
||||||
|
|
||||||
.clearfix(v-if="viewOptions['equipment'].selected")
|
equipment-section(
|
||||||
h2.float-left.mb-3.filters-title
|
v-if="viewOptions['equipment'].selected",
|
||||||
| {{ $t('equipment') }}
|
:hidePinned="hidePinned",
|
||||||
|
:hideLocked="hideLocked",
|
||||||
.filters.float-right
|
:searchBy="searchTextThrottled"
|
||||||
span.dropdown-label {{ $t('class') }}
|
|
||||||
b-dropdown(right=true)
|
|
||||||
span.dropdown-icon-item(slot="text")
|
|
||||||
span.svg-icon.inline.icon-16(v-html="icons[selectedGroupGearByClass]")
|
|
||||||
span.text {{ getClassName(selectedGroupGearByClass) }}
|
|
||||||
|
|
||||||
b-dropdown-item(
|
|
||||||
v-for="gearCategory in marketGearCategories",
|
|
||||||
@click="selectedGroupGearByClass = gearCategory.identifier",
|
|
||||||
:active="selectedGroupGearByClass === gearCategory.identifier",
|
|
||||||
:key="gearCategory.identifier"
|
|
||||||
)
|
|
||||||
span.dropdown-icon-item
|
|
||||||
span.svg-icon.inline.icon-16(v-html="icons[gearCategory.identifier]")
|
|
||||||
span.text {{ gearCategory.text }}
|
|
||||||
|
|
||||||
span.dropdown-label {{ $t('sortBy') }}
|
|
||||||
b-dropdown(:text="$t(selectedSortGearBy)", right=true)
|
|
||||||
b-dropdown-item(
|
|
||||||
v-for="sort in sortGearBy",
|
|
||||||
@click="selectedSortGearBy = sort",
|
|
||||||
:active="selectedSortGearBy === sort",
|
|
||||||
:key="sort"
|
|
||||||
) {{ $t(sort) }}
|
|
||||||
|
|
||||||
br
|
|
||||||
|
|
||||||
itemRows(
|
|
||||||
:items="filteredGear(selectedGroupGearByClass, searchTextThrottled, selectedSortGearBy, hideLocked, hidePinned)",
|
|
||||||
:itemWidth=94,
|
|
||||||
:itemMargin=24,
|
|
||||||
:type="'gear'",
|
|
||||||
:noItemsLabel="$t('noGearItemsOfClass')",
|
|
||||||
v-if="viewOptions['equipment'].selected"
|
|
||||||
)
|
)
|
||||||
template(slot="item", slot-scope="ctx")
|
|
||||||
shopItem(
|
layout-section(:title="$t('items')")
|
||||||
:key="ctx.item.key",
|
div(slot="filters")
|
||||||
:item="ctx.item",
|
filter-dropdown(
|
||||||
:emptyItem="userItems.gear[ctx.item.key] === undefined",
|
:label="$t('sortBy')",
|
||||||
:popoverPosition="'top'",
|
:initialItem="selectedSortItemsBy",
|
||||||
@click="gearSelected(ctx.item)"
|
:items="sortItemsBy",
|
||||||
|
@selected="selectedSortItemsBy = $event"
|
||||||
)
|
)
|
||||||
|
span(slot="item", slot-scope="ctx")
|
||||||
template(slot="itemBadge", slot-scope="ctx")
|
span.text {{ $t(ctx.item.id) }}
|
||||||
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")
|
|
||||||
|
|
||||||
.clearfix
|
|
||||||
h2.float-left.mb-3
|
|
||||||
| {{ $t('items') }}
|
|
||||||
|
|
||||||
div.float-right
|
|
||||||
span.dropdown-label {{ $t('sortBy') }}
|
|
||||||
b-dropdown(:text="$t(selectedSortItemsBy)", right=true)
|
|
||||||
b-dropdown-item(
|
|
||||||
v-for="sort in sortItemsBy",
|
|
||||||
@click="selectedSortItemsBy = sort",
|
|
||||||
:active="selectedSortItemsBy === sort",
|
|
||||||
:key="sort"
|
|
||||||
) {{ $t(sort) }}
|
|
||||||
|
|
||||||
|
|
||||||
div(
|
div(
|
||||||
v-for="category in categories",
|
v-for="category in categories",
|
||||||
v-if="viewOptions[category.identifier].selected && category.identifier !== 'equipment'"
|
v-if="viewOptions[category.identifier].selected && category.identifier !== 'equipment'"
|
||||||
)
|
)
|
||||||
h4 {{ category.text }}
|
h4 {{ category.text }}
|
||||||
|
category-row(
|
||||||
div.items
|
:hidePinned="hidePinned",
|
||||||
shopItem(
|
:hideLocked="hideLocked",
|
||||||
v-for="item in sortedMarketItems(category, selectedSortItemsBy, searchTextThrottled, hidePinned)",
|
:searchBy="searchTextThrottled",
|
||||||
:key="item.key",
|
:sortBy="selectedSortItemsBy.id",
|
||||||
:item="item",
|
:category="category"
|
||||||
:emptyItem="false",
|
|
||||||
:popoverPosition="'top'",
|
|
||||||
@click="itemSelected(item)"
|
|
||||||
)
|
)
|
||||||
span(slot="popoverContent")
|
|
||||||
strong(v-if='item.key === "gem" && gemsLeft === 0') {{ $t('maxBuyGems') }}
|
|
||||||
h4.popover-content-title {{ item.text }}
|
|
||||||
template(slot="itemBadge", slot-scope="ctx")
|
|
||||||
countBadge(
|
|
||||||
v-if="item.showCount != false",
|
|
||||||
:show="userItems[item.purchaseType][item.key] != 0",
|
|
||||||
:count="userItems[item.purchaseType][item.key] || 0"
|
|
||||||
)
|
|
||||||
.badge.badge-pill.badge-purple.gems-left(v-if='item.key === "gem"')
|
|
||||||
| {{ gemsLeft }}
|
|
||||||
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")
|
|
||||||
|
|
||||||
keys-to-kennel(v-if='category.identifier === "special"')
|
keys-to-kennel(v-if='category.identifier === "special"')
|
||||||
|
|
||||||
div.fill-height
|
div.fill-height
|
||||||
|
|
||||||
//- @TODO: Create new InventoryDrawer component and re-use in 'inventory/stable' component.
|
inventoryDrawer(:showEggs="true", :showPotions="true")
|
||||||
drawer(
|
|
||||||
:title="$t('quickInventory')"
|
|
||||||
:errorMessage="inventoryDrawerErrorMessage(selectedDrawerItemType)"
|
|
||||||
)
|
|
||||||
div(slot="drawer-header")
|
|
||||||
drawer-header-tabs(
|
|
||||||
:tabs="drawerTabs",
|
|
||||||
@changedPosition="tabSelected($event)"
|
|
||||||
)
|
|
||||||
div(slot="right-item")
|
|
||||||
#petLikeToEatMarket.drawer-help-text(v-once)
|
|
||||||
| {{ $t('petLikeToEat') + ' ' }}
|
|
||||||
span.svg-icon.inline.icon-16(v-html="icons.information")
|
|
||||||
b-popover(
|
|
||||||
target="petLikeToEatMarket",
|
|
||||||
:placement="'top'",
|
|
||||||
)
|
|
||||||
.popover-content-text(v-html="$t('petLikeToEatText')", v-once)
|
|
||||||
|
|
||||||
drawer-slider(
|
|
||||||
v-if="hasOwnedItemsForType(selectedDrawerItemType)"
|
|
||||||
:items="ownedItems(selectedDrawerItemType) || []",
|
|
||||||
slot="drawer-slider",
|
|
||||||
:itemWidth=94,
|
|
||||||
:itemMargin=24,
|
|
||||||
:itemType="selectedDrawerTab"
|
|
||||||
)
|
|
||||||
template(slot="item", slot-scope="ctx")
|
|
||||||
item(
|
|
||||||
:item="ctx.item",
|
|
||||||
:itemContentClass="getItemClass(selectedDrawerItemType, ctx.item.key)",
|
|
||||||
popoverPosition="top",
|
|
||||||
@click="selectedItemToSell = ctx.item"
|
|
||||||
)
|
|
||||||
template(slot="itemBadge", slot-scope="ctx")
|
|
||||||
countBadge(
|
|
||||||
:show="true",
|
|
||||||
:count="userItems[drawerTabs[selectedDrawerTab].contentType][ctx.item.key] || 0"
|
|
||||||
)
|
|
||||||
span(slot="popoverContent")
|
|
||||||
h4.popover-content-title {{ getItemName(selectedDrawerItemType, ctx.item) }}
|
|
||||||
|
|
||||||
sellModal(
|
|
||||||
:item="selectedItemToSell",
|
|
||||||
:itemType="selectedDrawerItemType",
|
|
||||||
:itemCount="selectedItemToSell != null ? userItems[drawerTabs[selectedDrawerTab].contentType][selectedItemToSell.key] : 0",
|
|
||||||
:text="selectedItemToSell != null ? getItemName(selectedDrawerItemType, selectedItemToSell) : ''",
|
|
||||||
@change="resetItemToSell($event)"
|
|
||||||
)
|
|
||||||
template(slot="item", slot-scope="ctx")
|
template(slot="item", slot-scope="ctx")
|
||||||
item.flat(
|
item(
|
||||||
:item="ctx.item",
|
:item="ctx.item",
|
||||||
:itemContentClass="getItemClass(selectedDrawerItemType, ctx.item.key)",
|
:itemContentClass="ctx.itemClass",
|
||||||
:showPopover="false"
|
popoverPosition="top",
|
||||||
|
@click="sellItem(ctx)"
|
||||||
)
|
)
|
||||||
template(slot="itemBadge", slot-scope="ctx")
|
countBadge(
|
||||||
countBadge(
|
slot="itemBadge"
|
||||||
:show="true",
|
:show="true",
|
||||||
:count="userItems[drawerTabs[selectedDrawerTab].contentType][ctx.item.key] || 0"
|
:count="ctx.itemCount"
|
||||||
)
|
)
|
||||||
|
h4.popover-content-title(slot="popoverContent") {{ ctx.itemName }}
|
||||||
|
|
||||||
|
sellModal
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '~client/assets/scss/colors.scss';
|
@import '~client/assets/scss/colors.scss';
|
||||||
@import '~client/assets/scss/variables.scss';
|
@import '~client/assets/scss/variables.scss';
|
||||||
|
|
||||||
.market .drawer-slider {
|
|
||||||
min-height: 60px;
|
|
||||||
|
|
||||||
.message {
|
|
||||||
top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fill-height {
|
.fill-height {
|
||||||
height: 38px; // button + margin + padding
|
height: 38px; // button + margin + padding
|
||||||
}
|
}
|
||||||
@@ -250,10 +84,6 @@
|
|||||||
height: 48px;
|
height: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.featured-label {
|
|
||||||
margin: 24px auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-wrapper.bordered-item .item {
|
.item-wrapper.bordered-item .item {
|
||||||
width: 112px;
|
width: 112px;
|
||||||
height: 112px;
|
height: 112px;
|
||||||
@@ -265,43 +95,15 @@
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.standard-page {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.featuredItems {
|
.featuredItems {
|
||||||
height: 216px;
|
|
||||||
|
|
||||||
.background {
|
.background {
|
||||||
background: url('~assets/images/npc/#{$npc_market_flavor}/market_background.png');
|
background: url('~assets/images/npc/#{$npc_market_flavor}/market_background.png');
|
||||||
|
|
||||||
background-repeat: repeat-x;
|
background-repeat: repeat-x;
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 216px;
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
z-index: 1; // Always cover background.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.npc {
|
.npc {
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 216px;
|
|
||||||
background: url('~assets/images/npc/#{$npc_market_flavor}/market_banner_npc.png');
|
background: url('~assets/images/npc/#{$npc_market_flavor}/market_banner_npc.png');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
|
|
||||||
@@ -312,23 +114,6 @@
|
|||||||
left: 80px;
|
left: 80px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.background.broken {
|
|
||||||
background: url('~assets/images/npc/broken/market_broken_background.png');
|
|
||||||
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
|
|
||||||
.background.cracked {
|
|
||||||
background: url('~assets/images/npc/broken/market_broken_layer.png');
|
|
||||||
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
|
|
||||||
.broken .npc {
|
|
||||||
background: url('~assets/images/npc/broken/market_broken_npc.png');
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,20 +121,6 @@
|
|||||||
right: -.5em;
|
right: -.5em;
|
||||||
top: -.5em;
|
top: -.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 768px) {
|
|
||||||
.featuredItems .content {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filters, .filters-title {
|
|
||||||
float: none;
|
|
||||||
button {
|
|
||||||
margin-right: 4em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
@@ -358,14 +129,18 @@
|
|||||||
|
|
||||||
import ShopItem from '../shopItem';
|
import ShopItem from '../shopItem';
|
||||||
import KeysToKennel from './keysToKennel';
|
import KeysToKennel from './keysToKennel';
|
||||||
|
import EquipmentSection from './equipmentSection';
|
||||||
|
import CategoryRow from './categoryRow';
|
||||||
import Item from 'client/components/inventory/item';
|
import Item from 'client/components/inventory/item';
|
||||||
import CountBadge from 'client/components/ui/countBadge';
|
import CountBadge from 'client/components/ui/countBadge';
|
||||||
import Drawer from 'client/components/ui/drawer';
|
|
||||||
import DrawerSlider from 'client/components/ui/drawerSlider';
|
|
||||||
import DrawerHeaderTabs from 'client/components/ui/drawerHeaderTabs';
|
|
||||||
import ItemRows from 'client/components/ui/itemRows';
|
import ItemRows from 'client/components/ui/itemRows';
|
||||||
import toggleSwitch from 'client/components/ui/toggleSwitch';
|
|
||||||
import Avatar from 'client/components/avatar';
|
import Avatar from 'client/components/avatar';
|
||||||
|
import InventoryDrawer from 'client/components/shared/inventoryDrawer';
|
||||||
|
import FeaturedItemsHeader from '../featuredItemsHeader';
|
||||||
|
import PageLayout from 'client/components/ui/pageLayout';
|
||||||
|
import LayoutSection from 'client/components/ui/layoutSection';
|
||||||
|
import FilterDropdown from 'client/components/ui/filterDropdown';
|
||||||
|
import MarketFilter from './filter';
|
||||||
|
|
||||||
import SellModal from './sellModal.vue';
|
import SellModal from './sellModal.vue';
|
||||||
import EquipmentAttributesGrid from '../../inventory/equipment/attributesGrid.vue';
|
import EquipmentAttributesGrid from '../../inventory/equipment/attributesGrid.vue';
|
||||||
@@ -374,52 +149,45 @@
|
|||||||
import svgPin from 'assets/svg/pin.svg';
|
import svgPin from 'assets/svg/pin.svg';
|
||||||
import svgGem from 'assets/svg/gem.svg';
|
import svgGem from 'assets/svg/gem.svg';
|
||||||
import svgInformation from 'assets/svg/information.svg';
|
import svgInformation from 'assets/svg/information.svg';
|
||||||
import svgWarrior from 'assets/svg/warrior.svg';
|
|
||||||
import svgWizard from 'assets/svg/wizard.svg';
|
|
||||||
import svgRogue from 'assets/svg/rogue.svg';
|
|
||||||
import svgHealer from 'assets/svg/healer.svg';
|
|
||||||
|
|
||||||
import getItemInfo from 'common/script/libs/getItemInfo';
|
import getItemInfo from 'common/script/libs/getItemInfo';
|
||||||
import isPinned from 'common/script/libs/isPinned';
|
|
||||||
import shops from 'common/script/libs/shops';
|
import shops from 'common/script/libs/shops';
|
||||||
import planGemLimits from 'common/script/libs/planGemLimits';
|
|
||||||
|
|
||||||
import _filter from 'lodash/filter';
|
import _filter from 'lodash/filter';
|
||||||
import _sortBy from 'lodash/sortBy';
|
|
||||||
import _map from 'lodash/map';
|
import _map from 'lodash/map';
|
||||||
import _throttle from 'lodash/throttle';
|
import _throttle from 'lodash/throttle';
|
||||||
|
|
||||||
const sortGearTypes = ['sortByType', 'sortByPrice', 'sortByCon', 'sortByPer', 'sortByStr', 'sortByInt'];
|
const sortItems = ['AZ', 'sortByNumber'].map(g => ({id: g}));
|
||||||
|
|
||||||
import notifications from 'client/mixins/notifications';
|
import notifications from 'client/mixins/notifications';
|
||||||
import buyMixin from 'client/mixins/buy';
|
import buyMixin from 'client/mixins/buy';
|
||||||
import currencyMixin from '../_currencyMixin';
|
import currencyMixin from '../_currencyMixin';
|
||||||
|
import inventoryUtils from 'client/mixins/inventoryUtils';
|
||||||
const sortGearTypeMap = {
|
import pinUtils from 'client/mixins/pinUtils';
|
||||||
sortByType: 'type',
|
|
||||||
sortByPrice: 'value',
|
|
||||||
sortByCon: 'con',
|
|
||||||
sortByStr: 'str',
|
|
||||||
sortByInt: 'int',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [notifications, buyMixin, currencyMixin],
|
mixins: [notifications, buyMixin, currencyMixin, inventoryUtils, pinUtils],
|
||||||
components: {
|
components: {
|
||||||
ShopItem,
|
ShopItem,
|
||||||
KeysToKennel,
|
KeysToKennel,
|
||||||
Item,
|
Item,
|
||||||
CountBadge,
|
CountBadge,
|
||||||
Drawer,
|
|
||||||
DrawerSlider,
|
|
||||||
DrawerHeaderTabs,
|
|
||||||
ItemRows,
|
ItemRows,
|
||||||
toggleSwitch,
|
|
||||||
|
|
||||||
SellModal,
|
SellModal,
|
||||||
EquipmentAttributesGrid,
|
EquipmentAttributesGrid,
|
||||||
Avatar,
|
Avatar,
|
||||||
|
|
||||||
|
InventoryDrawer,
|
||||||
|
FeaturedItemsHeader,
|
||||||
|
PageLayout,
|
||||||
|
LayoutSection,
|
||||||
|
FilterDropdown,
|
||||||
|
EquipmentSection,
|
||||||
|
CategoryRow,
|
||||||
|
MarketFilter,
|
||||||
|
|
||||||
SelectMembersModal,
|
SelectMembersModal,
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -438,24 +206,10 @@ export default {
|
|||||||
pin: svgPin,
|
pin: svgPin,
|
||||||
gem: svgGem,
|
gem: svgGem,
|
||||||
information: svgInformation,
|
information: svgInformation,
|
||||||
warrior: svgWarrior,
|
|
||||||
wizard: svgWizard,
|
|
||||||
rogue: svgRogue,
|
|
||||||
healer: svgHealer,
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
selectedDrawerTab: 0,
|
sortItemsBy: sortItems,
|
||||||
selectedDrawerItemType: 'eggs',
|
selectedSortItemsBy: sortItems[0],
|
||||||
|
|
||||||
selectedGroupGearByClass: '',
|
|
||||||
|
|
||||||
sortGearBy: sortGearTypes,
|
|
||||||
selectedSortGearBy: 'sortByType',
|
|
||||||
|
|
||||||
sortItemsBy: ['AZ', 'sortByNumber'],
|
|
||||||
selectedSortItemsBy: 'AZ',
|
|
||||||
|
|
||||||
selectedItemToSell: null,
|
|
||||||
|
|
||||||
hideLocked: false,
|
hideLocked: false,
|
||||||
hidePinned: false,
|
hidePinned: false,
|
||||||
@@ -474,120 +228,79 @@ export default {
|
|||||||
userStats: 'user.data.stats',
|
userStats: 'user.data.stats',
|
||||||
userItems: 'user.data.items',
|
userItems: 'user.data.items',
|
||||||
}),
|
}),
|
||||||
marketGearCategories () {
|
|
||||||
return shops.getMarketGearCategories(this.user);
|
|
||||||
},
|
|
||||||
market () {
|
market () {
|
||||||
return shops.getMarketShop(this.user);
|
return shops.getMarketShop(this.user);
|
||||||
},
|
},
|
||||||
categories () {
|
categories () {
|
||||||
if (this.market) {
|
if (!this.market) return [];
|
||||||
let categories = [
|
|
||||||
...this.market.categories,
|
|
||||||
];
|
|
||||||
|
|
||||||
categories.push({
|
let categories = [
|
||||||
identifier: 'equipment',
|
...this.market.categories,
|
||||||
text: this.$t('equipment'),
|
|
||||||
});
|
|
||||||
|
|
||||||
categories.push({
|
|
||||||
identifier: 'cards',
|
|
||||||
text: this.$t('cards'),
|
|
||||||
items: _map(_filter(this.content.cardTypes, (value) => {
|
|
||||||
return value.yearRound;
|
|
||||||
}), (value) => {
|
|
||||||
return {
|
|
||||||
...getItemInfo(this.user, 'card', value),
|
|
||||||
showCount: false,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
let specialItems = [{
|
|
||||||
...getItemInfo(this.user, 'fortify'),
|
|
||||||
showCount: false,
|
|
||||||
}];
|
|
||||||
|
|
||||||
if (this.user.purchased.plan.customerId) {
|
|
||||||
let gemItem = getItemInfo(this.user, 'gem');
|
|
||||||
|
|
||||||
specialItems.push({
|
|
||||||
...gemItem,
|
|
||||||
showCount: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.user.flags.rebirthEnabled) {
|
|
||||||
let rebirthItem = getItemInfo(this.user, 'rebirth_orb');
|
|
||||||
|
|
||||||
specialItems.push({
|
|
||||||
showCount: false,
|
|
||||||
...rebirthItem,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (specialItems.length > 0) {
|
|
||||||
categories.push({
|
|
||||||
identifier: 'special',
|
|
||||||
text: this.$t('special'),
|
|
||||||
items: specialItems,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
categories.map((category) => {
|
|
||||||
if (!this.viewOptions[category.identifier]) {
|
|
||||||
this.$set(this.viewOptions, category.identifier, {
|
|
||||||
selected: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return categories;
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
drawerTabs () {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
key: 'eggs',
|
|
||||||
contentType: 'eggs',
|
|
||||||
label: this.$t('eggs'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'food',
|
|
||||||
contentType: 'food',
|
|
||||||
label: this.$t('foodTitle'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'hatchingPotions',
|
|
||||||
contentType: 'hatchingPotions',
|
|
||||||
label: this.$t('hatchingPotions'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'special',
|
|
||||||
contentType: 'food',
|
|
||||||
label: this.$t('special'),
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
},
|
|
||||||
gemsLeft () {
|
categories.push({
|
||||||
if (!this.user.purchased.plan) return 0;
|
identifier: 'equipment',
|
||||||
return planGemLimits.convCap + this.user.purchased.plan.consecutive.gemCapExtra - this.user.purchased.plan.gemsBought;
|
text: this.$t('equipment'),
|
||||||
|
});
|
||||||
|
|
||||||
|
categories.push({
|
||||||
|
identifier: 'cards',
|
||||||
|
text: this.$t('cards'),
|
||||||
|
items: _map(_filter(this.content.cardTypes, (value) => {
|
||||||
|
return value.yearRound;
|
||||||
|
}), (value) => {
|
||||||
|
return {
|
||||||
|
...getItemInfo(this.user, 'card', value),
|
||||||
|
showCount: false,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
let specialItems = [{
|
||||||
|
...getItemInfo(this.user, 'fortify'),
|
||||||
|
showCount: false,
|
||||||
|
}];
|
||||||
|
|
||||||
|
if (this.user.purchased.plan.customerId) {
|
||||||
|
let gemItem = getItemInfo(this.user, 'gem');
|
||||||
|
|
||||||
|
specialItems.push({
|
||||||
|
...gemItem,
|
||||||
|
showCount: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.user.flags.rebirthEnabled) {
|
||||||
|
let rebirthItem = getItemInfo(this.user, 'rebirth_orb');
|
||||||
|
|
||||||
|
specialItems.push({
|
||||||
|
showCount: false,
|
||||||
|
...rebirthItem,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (specialItems.length > 0) {
|
||||||
|
categories.push({
|
||||||
|
identifier: 'special',
|
||||||
|
text: this.$t('special'),
|
||||||
|
items: specialItems,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
categories.map((category) => {
|
||||||
|
if (!this.viewOptions[category.identifier]) {
|
||||||
|
this.$set(this.viewOptions, category.identifier, {
|
||||||
|
selected: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return categories;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getClassName (classType) {
|
sellItem (itemScope) {
|
||||||
if (classType === 'wizard') {
|
this.$root.$emit('sellItem', itemScope);
|
||||||
return this.$t('mage');
|
|
||||||
} else {
|
|
||||||
return this.$t(classType);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tabSelected ($event) {
|
|
||||||
this.selectedDrawerTab = $event;
|
|
||||||
this.selectedDrawerItemType = this.drawerTabs[$event].key;
|
|
||||||
},
|
},
|
||||||
ownedItems (type) {
|
ownedItems (type) {
|
||||||
let mappedItems = _filter(this.content[type], i => {
|
let mappedItems = _filter(this.content[type], i => {
|
||||||
@@ -620,133 +333,18 @@ export default {
|
|||||||
return this.$t('noItemsAvailableForType', { type: this.$t(`${type}ItemType`) });
|
return this.$t('noItemsAvailableForType', { type: this.$t(`${type}ItemType`) });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getItemClass (type, itemKey) {
|
|
||||||
switch (type) {
|
|
||||||
case 'food':
|
|
||||||
case 'special':
|
|
||||||
return `Pet_Food_${itemKey}`;
|
|
||||||
case 'eggs':
|
|
||||||
return `Pet_Egg_${itemKey}`;
|
|
||||||
case 'hatchingPotions':
|
|
||||||
return `Pet_HatchingPotion_${itemKey}`;
|
|
||||||
default:
|
|
||||||
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) {
|
|
||||||
let category = _filter(this.marketGearCategories, ['identifier', groupByClass]);
|
|
||||||
|
|
||||||
let result = _filter(category[0].items, (gear) => {
|
|
||||||
if (hideLocked && gear.locked) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (hidePinned && gear.pinned) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchBy) {
|
|
||||||
let foundPosition = gear.text.toLowerCase().indexOf(searchBy);
|
|
||||||
if (foundPosition === -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// hide already owned
|
|
||||||
return !this.userItems.gear.owned[gear.key];
|
|
||||||
});
|
|
||||||
|
|
||||||
// first all unlocked
|
|
||||||
// then the selected sort
|
|
||||||
result = _sortBy(result, [(item) => item.locked, sortGearTypeMap[sortBy]]);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
sortedMarketItems (category, sortBy, searchBy, hidePinned) {
|
|
||||||
let result = _map(category.items, (e) => {
|
|
||||||
return {
|
|
||||||
...e,
|
|
||||||
pinned: isPinned(this.user, e),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
result = _filter(result, (item) => {
|
|
||||||
if (hidePinned && item.pinned) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchBy) {
|
|
||||||
let foundPosition = item.text.toLowerCase().indexOf(searchBy);
|
|
||||||
if (foundPosition === -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
switch (sortBy) {
|
|
||||||
case 'AZ': {
|
|
||||||
result = _sortBy(result, ['text']);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'sortByNumber': {
|
|
||||||
result = _sortBy(result, item => {
|
|
||||||
if (item.showCount === false) return 0;
|
|
||||||
|
|
||||||
return this.userItems[item.purchaseType][item.key] || 0;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
resetItemToSell ($event) {
|
|
||||||
if (!$event) {
|
|
||||||
this.selectedItemToSell = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isGearLocked (gear) {
|
|
||||||
if (gear.klass !== this.userStats.class) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
togglePinned (item) {
|
|
||||||
if (!this.$store.dispatch('user:togglePinnedItem', {type: item.pinType, path: item.path})) {
|
|
||||||
this.$parent.showUnpinNotification(item);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemSelected (item) {
|
itemSelected (item) {
|
||||||
this.$root.$emit('buyModal::showItem', item);
|
this.$root.$emit('buyModal::showItem', item);
|
||||||
},
|
},
|
||||||
featuredItemSelected (item) {
|
featuredItemSelected (item) {
|
||||||
if (item.purchaseType === 'gear') {
|
if (item.purchaseType === 'gear') {
|
||||||
this.gearSelected(item);
|
if (!item.locked) {
|
||||||
|
this.itemSelected(item);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.itemSelected(item);
|
this.itemSelected(item);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
gearSelected (item) {
|
|
||||||
if (!item.locked) {
|
|
||||||
this.$root.$emit('buyModal::showItem', item);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
this.selectedGroupGearByClass = this.userStats.class;
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
b-modal#sell-modal(
|
b-modal#sell-modal(
|
||||||
:visible="item != null",
|
|
||||||
:hide-header="true",
|
:hide-header="true",
|
||||||
@change="onChange($event)"
|
@change="onChange($event)"
|
||||||
)
|
)
|
||||||
@@ -8,30 +7,37 @@
|
|||||||
span.svg-icon.inline.icon-10(aria-hidden="true", v-html="icons.close", @click="hideDialog()")
|
span.svg-icon.inline.icon-10(aria-hidden="true", v-html="icons.close", @click="hideDialog()")
|
||||||
|
|
||||||
div.content(v-if="item")
|
div.content(v-if="item")
|
||||||
|
div.inner-content
|
||||||
|
item.flat(
|
||||||
|
:item="item",
|
||||||
|
:itemContentClass="itemContextToSell.itemClass",
|
||||||
|
:showPopover="false"
|
||||||
|
)
|
||||||
|
countBadge(
|
||||||
|
slot="itemBadge",
|
||||||
|
:show="true",
|
||||||
|
:count="itemContextToSell.itemCount"
|
||||||
|
)
|
||||||
|
|
||||||
div.inner-content(v-if="item.sellWarningNote")
|
h4.title {{ itemContextToSell.itemName }}
|
||||||
slot(name="item", :item="item")
|
|
||||||
|
|
||||||
h4.title {{ text ? text : item.text() }}
|
div(v-if="item.sellWarningNote")
|
||||||
div.text {{ item.sellWarningNote() }}
|
div.text {{ item.sellWarningNote() }}
|
||||||
br
|
br
|
||||||
|
|
||||||
div.inner-content(v-else)
|
div(v-once)
|
||||||
slot(name="item", :item="item")
|
div.text {{ item.notes() }}
|
||||||
|
|
||||||
h4.title {{ text ? text : item.text() }}
|
div
|
||||||
div.text {{ item.notes() }}
|
b.how-many-to-sell {{ $t('howManyToSell') }}
|
||||||
|
|
||||||
div
|
div
|
||||||
b.how-many-to-sell {{ $t('howManyToSell') }}
|
b-input.itemsToSell(type="number", v-model="selectedAmountToSell", :max="itemContextToSell.itemCount", min="1", @keyup.native="preventNegative($event)", step="1")
|
||||||
|
|
||||||
div
|
span.svg-icon.inline.icon-32(aria-hidden="true", v-html="icons.gold")
|
||||||
b-input.itemsToSell(type="number", v-model="selectedAmountToSell", :max="itemCount", min="1", @keyup.native="preventNegative($event)", step="1")
|
span.value {{ item.value }}
|
||||||
|
|
||||||
span.svg-icon.inline.icon-32(aria-hidden="true", v-html="icons.gold")
|
button.btn.btn-primary(@click="sellItems()") {{ $t('sell') }}
|
||||||
span.value {{ item.value }}
|
|
||||||
|
|
||||||
button.btn.btn-primary(@click="sellItems()") {{ $t('sell') }}
|
|
||||||
|
|
||||||
div.clearfix(slot="modal-footer")
|
div.clearfix(slot="modal-footer")
|
||||||
span.balance.float-left {{ $t('yourBalance') }}
|
span.balance.float-left {{ $t('yourBalance') }}
|
||||||
@@ -119,14 +125,19 @@
|
|||||||
import svgGem from 'assets/svg/gem.svg';
|
import svgGem from 'assets/svg/gem.svg';
|
||||||
|
|
||||||
import BalanceInfo from '../balanceInfo.vue';
|
import BalanceInfo from '../balanceInfo.vue';
|
||||||
|
import Item from 'client/components/inventory/item';
|
||||||
|
import CountBadge from 'client/components/ui/countBadge';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
BalanceInfo,
|
BalanceInfo,
|
||||||
|
Item,
|
||||||
|
CountBadge,
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
selectedAmountToSell: 1,
|
selectedAmountToSell: 1,
|
||||||
|
itemContextToSell: null,
|
||||||
|
|
||||||
icons: Object.freeze({
|
icons: Object.freeze({
|
||||||
close: svgClose,
|
close: svgClose,
|
||||||
@@ -135,6 +146,20 @@
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
item () {
|
||||||
|
return this.itemContextToSell && this.itemContextToSell.item;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.$root.$on('sellItem', (itemCtx) => {
|
||||||
|
this.itemContextToSell = itemCtx;
|
||||||
|
this.$root.$emit('bv::show::modal', 'sell-modal');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
destroyed () {
|
||||||
|
this.$root.$off('sellItem');
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onChange ($event) {
|
onChange ($event) {
|
||||||
this.$emit('change', $event);
|
this.$emit('change', $event);
|
||||||
@@ -155,7 +180,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.$store.dispatch('shops:sellItems', {
|
this.$store.dispatch('shops:sellItems', {
|
||||||
type: this.itemType,
|
type: this.itemContextToSell.itemType,
|
||||||
key: this.item.key,
|
key: this.item.key,
|
||||||
amount: this.selectedAmountToSell,
|
amount: this.selectedAmountToSell,
|
||||||
});
|
});
|
||||||
@@ -165,19 +190,5 @@
|
|||||||
this.$root.$emit('bv::hide::modal', 'sell-modal');
|
this.$root.$emit('bv::hide::modal', 'sell-modal');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
props: {
|
|
||||||
item: {
|
|
||||||
type: Object,
|
|
||||||
},
|
|
||||||
itemType: {
|
|
||||||
type: String,
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
type: String,
|
|
||||||
},
|
|
||||||
itemCount: {
|
|
||||||
type: Number,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -339,6 +339,7 @@
|
|||||||
import toggleSwitch from 'client/components/ui/toggleSwitch';
|
import toggleSwitch from 'client/components/ui/toggleSwitch';
|
||||||
import Avatar from 'client/components/avatar';
|
import Avatar from 'client/components/avatar';
|
||||||
import buyMixin from 'client/mixins/buy';
|
import buyMixin from 'client/mixins/buy';
|
||||||
|
import pinUtils from 'client/mixins/pinUtils';
|
||||||
import currencyMixin from '../_currencyMixin';
|
import currencyMixin from '../_currencyMixin';
|
||||||
|
|
||||||
import BuyModal from './buyQuestModal.vue';
|
import BuyModal from './buyQuestModal.vue';
|
||||||
@@ -357,7 +358,7 @@
|
|||||||
import _map from 'lodash/map';
|
import _map from 'lodash/map';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [buyMixin, currencyMixin],
|
mixins: [buyMixin, currencyMixin, pinUtils],
|
||||||
components: {
|
components: {
|
||||||
ShopItem,
|
ShopItem,
|
||||||
Item,
|
Item,
|
||||||
@@ -474,11 +475,6 @@ export default {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
togglePinned (item) {
|
|
||||||
if (!this.$store.dispatch('user:togglePinnedItem', {type: item.pinType, path: item.path})) {
|
|
||||||
this.$parent.showUnpinNotification(item);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selectItem (item) {
|
selectItem (item) {
|
||||||
if (item.locked) return;
|
if (item.locked) return;
|
||||||
|
|
||||||
|
|||||||
@@ -294,6 +294,7 @@
|
|||||||
import Avatar from 'client/components/avatar';
|
import Avatar from 'client/components/avatar';
|
||||||
import buyMixin from 'client/mixins/buy';
|
import buyMixin from 'client/mixins/buy';
|
||||||
import currencyMixin from '../_currencyMixin';
|
import currencyMixin from '../_currencyMixin';
|
||||||
|
import pinUtils from 'client/mixins/pinUtils';
|
||||||
|
|
||||||
import svgPin from 'assets/svg/pin.svg';
|
import svgPin from 'assets/svg/pin.svg';
|
||||||
import svgWarrior from 'assets/svg/warrior.svg';
|
import svgWarrior from 'assets/svg/warrior.svg';
|
||||||
@@ -318,7 +319,7 @@
|
|||||||
import shops from 'common/script/libs/shops';
|
import shops from 'common/script/libs/shops';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [buyMixin, currencyMixin],
|
mixins: [buyMixin, currencyMixin, pinUtils],
|
||||||
components: {
|
components: {
|
||||||
ShopItem,
|
ShopItem,
|
||||||
Item,
|
Item,
|
||||||
@@ -514,11 +515,6 @@
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
togglePinned (item) {
|
|
||||||
if (!this.$store.dispatch('user:togglePinnedItem', {type: item.pinType, path: item.path})) {
|
|
||||||
this.$parent.showUnpinNotification(item);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemSelected (item) {
|
itemSelected (item) {
|
||||||
if (item.locked) return;
|
if (item.locked) return;
|
||||||
this.$root.$emit('buyModal::showItem', item);
|
this.$root.$emit('buyModal::showItem', item);
|
||||||
|
|||||||
@@ -240,8 +240,10 @@
|
|||||||
import isPinned from 'common/script/libs/isPinned';
|
import isPinned from 'common/script/libs/isPinned';
|
||||||
import shops from 'common/script/libs/shops';
|
import shops from 'common/script/libs/shops';
|
||||||
|
|
||||||
|
import pinUtils from 'client/mixins/pinUtils';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [pinUtils],
|
||||||
components: {
|
components: {
|
||||||
ShopItem,
|
ShopItem,
|
||||||
Item,
|
Item,
|
||||||
@@ -369,11 +371,6 @@
|
|||||||
getGrouped (entries) {
|
getGrouped (entries) {
|
||||||
return _groupBy(entries, 'group');
|
return _groupBy(entries, 'group');
|
||||||
},
|
},
|
||||||
togglePinned (item) {
|
|
||||||
if (!this.$store.dispatch('user:togglePinnedItem', {type: item.pinType, path: item.path})) {
|
|
||||||
this.$parent.showUnpinNotification(item);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selectItemToBuy (item) {
|
selectItemToBuy (item) {
|
||||||
this.$root.$emit('buyModal::showItem', item);
|
this.$root.$emit('buyModal::showItem', item);
|
||||||
},
|
},
|
||||||
|
|||||||
26
website/client/components/ui/checkbox.vue
Normal file
26
website/client/components/ui/checkbox.vue
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.form-check
|
||||||
|
.custom-control.custom-checkbox
|
||||||
|
input.custom-control-input(type="checkbox", v-model="isChecked", :id="id")
|
||||||
|
label.custom-control-label(v-once, :for="id") {{ text }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
checked: Boolean,
|
||||||
|
id: String,
|
||||||
|
text: String,
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
isChecked: this.checked,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
isChecked (after) {
|
||||||
|
this.$emit('update:checked', after);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
span.badge.badge-pill.badge-item.badge-count(
|
span.badge.badge-pill.badge-item.badge-count(
|
||||||
v-if="show && count != 0",
|
v-if="show && count > 0",
|
||||||
) {{ count }}
|
) {{ count }}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
45
website/client/components/ui/filterDropdown.vue
Normal file
45
website/client/components/ui/filterDropdown.vue
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
span
|
||||||
|
span.dropdown-label {{ label }}
|
||||||
|
b-dropdown(right=true)
|
||||||
|
span(slot="text", :class="{'dropdown-icon-item': withIcon}")
|
||||||
|
slot(name="item", :item="selectedItem")
|
||||||
|
|
||||||
|
b-dropdown-item(
|
||||||
|
v-for="item in items",
|
||||||
|
@click="selectItem(item)",
|
||||||
|
:active="selectedItem.id === item.id",
|
||||||
|
:key="item.id"
|
||||||
|
)
|
||||||
|
span(:class="{'dropdown-icon-item': withIcon}")
|
||||||
|
slot(name="item", :item="item")
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
label: String,
|
||||||
|
items: Array,
|
||||||
|
initialItem: Object,
|
||||||
|
withIcon: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
selectedItem: this.initialItem,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
selectItem (item) {
|
||||||
|
this.selectedItem = item;
|
||||||
|
this.$emit('selected', item);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
33
website/client/components/ui/layoutSection.vue
Normal file
33
website/client/components/ui/layoutSection.vue
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
div
|
||||||
|
.clearfix
|
||||||
|
h2.float-left.mb-3.filters-title {{ title }}
|
||||||
|
|
||||||
|
.filters.float-right
|
||||||
|
slot(name="filters")
|
||||||
|
|
||||||
|
br
|
||||||
|
|
||||||
|
slot(name="content")
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
title: String,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@media only screen and (max-width: 768px) {
|
||||||
|
.filters, .filters-title {
|
||||||
|
float: none;
|
||||||
|
button {
|
||||||
|
margin-right: 4em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
25
website/client/components/ui/pageLayout.vue
Normal file
25
website/client/components/ui/pageLayout.vue
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.row
|
||||||
|
.standard-sidebar.d-none.d-sm-block(v-if="showSidebar")
|
||||||
|
slot(name="sidebar")
|
||||||
|
.standard-page
|
||||||
|
slot(name="page")
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
showSidebar: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
.standard-page {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
27
website/client/mixins/inventoryUtils.js
Normal file
27
website/client/mixins/inventoryUtils.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
getItemClass (type, itemKey) {
|
||||||
|
switch (type) {
|
||||||
|
case 'food':
|
||||||
|
case 'special':
|
||||||
|
return `Pet_Food_${itemKey}`;
|
||||||
|
case 'eggs':
|
||||||
|
return `Pet_Egg_${itemKey}`;
|
||||||
|
case 'hatchingPotions':
|
||||||
|
return `Pet_HatchingPotion_${itemKey}`;
|
||||||
|
default:
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
19
website/client/mixins/pinUtils.js
Normal file
19
website/client/mixins/pinUtils.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import notifications from 'client/mixins/notifications';
|
||||||
|
import isPinned from 'common/script/libs/isPinned';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [notifications],
|
||||||
|
methods: {
|
||||||
|
isPinned (item) {
|
||||||
|
return isPinned(this.user, item);
|
||||||
|
},
|
||||||
|
togglePinned (item) {
|
||||||
|
if (!this.$store.dispatch('user:togglePinnedItem', {type: item.pinType, path: item.path})) {
|
||||||
|
this.showUnpinNotification(item);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showUnpinNotification (item) {
|
||||||
|
this.text(this.$t('unpinnedItem', {item: item.text}));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -104,6 +104,7 @@ function getClassName (classType, language) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Refactor the `.locked` logic
|
||||||
shops.checkMarketGearLocked = function checkMarketGearLocked (user, items) {
|
shops.checkMarketGearLocked = function checkMarketGearLocked (user, items) {
|
||||||
let result = filter(items, ['pinType', 'marketGear']);
|
let result = filter(items, ['pinType', 'marketGear']);
|
||||||
let availableGear = map(updateStore(user), (item) => getItemInfo(user, 'marketGear', item).path);
|
let availableGear = map(updateStore(user), (item) => getItemInfo(user, 'marketGear', item).path);
|
||||||
@@ -116,12 +117,6 @@ shops.checkMarketGearLocked = function checkMarketGearLocked (user, items) {
|
|||||||
gear.locked = true;
|
gear.locked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO: I'm not sure what the logic for locking is supposed to be
|
|
||||||
// But, I am pretty sure if we pin an armoire item, it needs to be unlocked
|
|
||||||
if (gear.klass === 'armoire') {
|
|
||||||
gear.locked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Boolean(gear.specialClass) && Boolean(gear.set)) {
|
if (Boolean(gear.specialClass) && Boolean(gear.set)) {
|
||||||
let currentSet = gear.set === seasonalShopConfig.pinnedSets[gear.specialClass];
|
let currentSet = gear.set === seasonalShopConfig.pinnedSets[gear.specialClass];
|
||||||
|
|
||||||
@@ -132,7 +127,6 @@ shops.checkMarketGearLocked = function checkMarketGearLocked (user, items) {
|
|||||||
gear.locked = !gear.canOwn(user);
|
gear.locked = !gear.canOwn(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let itemOwned = user.items.gear.owned[gear.key];
|
let itemOwned = user.items.gear.owned[gear.key];
|
||||||
|
|
||||||
if (itemOwned === false && !availableGear.includes(gear.path)) {
|
if (itemOwned === false && !availableGear.includes(gear.path)) {
|
||||||
@@ -140,6 +134,12 @@ shops.checkMarketGearLocked = function checkMarketGearLocked (user, items) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gear.owned = itemOwned;
|
gear.owned = itemOwned;
|
||||||
|
|
||||||
|
// @TODO: I'm not sure what the logic for locking is supposed to be
|
||||||
|
// But, I am pretty sure if we pin an armoire item, it needs to be unlocked
|
||||||
|
if (gear.klass === 'armoire') {
|
||||||
|
gear.locked = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -188,7 +188,8 @@ shops.getMarketGearCategories = function getMarketGear (user, language) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let specialNonClassGear = filter(content.gear.flat, (gear) => {
|
let specialNonClassGear = filter(content.gear.flat, (gear) => {
|
||||||
return !user.items.gear.owned[gear.key] &&
|
return user.items.gear.owned[gear.key] === false ||
|
||||||
|
!user.items.gear.owned[gear.key] &&
|
||||||
content.classes.indexOf(gear.klass) === -1 &&
|
content.classes.indexOf(gear.klass) === -1 &&
|
||||||
content.classes.indexOf(gear.specialClass) === -1 &&
|
content.classes.indexOf(gear.specialClass) === -1 &&
|
||||||
(gear.canOwn && gear.canOwn(user));
|
(gear.canOwn && gear.canOwn(user));
|
||||||
|
|||||||
Reference in New Issue
Block a user