diff --git a/website/client/app.vue b/website/client/app.vue
index 295ff26a71..7002bdb5c8 100644
--- a/website/client/app.vue
+++ b/website/client/app.vue
@@ -29,7 +29,6 @@ div
buyModal(
:item="selectedItemToBuy || {}",
:withPin="true",
- @change="resetItemToBuy($event)",
@buyPressed="customPurchase($event)",
: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) {
this.selectedItemToBuy = item;
},
diff --git a/website/client/components/inventory/stable/foodItem.vue b/website/client/components/inventory/stable/foodItem.vue
index dfb15032f5..e858763ab4 100644
--- a/website/client/components/inventory/stable/foodItem.vue
+++ b/website/client/components/inventory/stable/foodItem.vue
@@ -17,7 +17,7 @@ div
triggers="hover",
placement="top",
)
- h4.popover-content-title {{ item.text() }}
+ h4.popover-content-title {{ itemName || item.text() }}
div.popover-content-text(v-html="item.notes()")
@@ -45,6 +45,9 @@ export default {
itemContentClass: {
type: String,
},
+ itemName: {
+ type: String,
+ },
active: {
type: Boolean,
},
diff --git a/website/client/components/inventory/stable/index.vue b/website/client/components/inventory/stable/index.vue
index a308d5908b..8619555884 100644
--- a/website/client/components/inventory/stable/index.vue
+++ b/website/client/components/inventory/stable/index.vue
@@ -145,47 +145,17 @@
.btn.btn-flat.btn-show-more(@click="setShowMore(mountGroup.key)", v-if='mountGroup.key !== "specialMounts"')
| {{ $_openedItemRows_isToggled(mountGroup.key) ? $t('showLess') : $t('showMore') }}
- drawer(:title="$t('quickInventory')",
- :errorMessage="(!hasDrawerTabItems(selectedDrawerTab)) ? ((selectedDrawerTab === 0) ? $t('noFoodAvailable') : $t('noSaddlesAvailable')) : null")
- div(slot="drawer-header")
- .drawer-tab-container
- .drawer-tab.text-right
- a.drawer-tab-text(
- @click="selectedDrawerTab = 0",
- :class="{'drawer-tab-text-active': selectedDrawerTab === 0}",
- ) {{ drawerTabs[0].label }}
- .clearfix
- .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)"
- )
+ inventoryDrawer
+ template(slot="item", slot-scope="ctx")
+ foodItem(
+ :item="ctx.item",
+ :itemCount="ctx.itemCount",
+ :itemContentClass="ctx.itemClass",
+ :active="currentDraggingFood === ctx.item",
+ @itemDragEnd="onDragEnd()",
+ @itemDragStart="onDragStart($event, ctx.item)",
+ @itemClick="onFoodClicked($event, ctx.item)"
+ )
hatchedPetDialog(:hideText="true")
div.foodInfo(ref="dragginFoodInfo")
div(v-if="currentDraggingFood != null")
@@ -284,9 +254,6 @@
}
}
- .drawer-slider .items {
- height: 114px;
- }
.modal-backdrop.fade.show {
background-color: $purple-50;
@@ -386,6 +353,7 @@
import StarBadge from 'client/components/ui/starBadge';
import CountBadge from 'client/components/ui/countBadge';
import DrawerSlider from 'client/components/ui/drawerSlider';
+ import InventoryDrawer from 'client/components/shared/inventoryDrawer';
import ResizeDirective from 'client/directives/resize.directive';
import DragDropDirective from 'client/directives/dragdrop.directive';
@@ -425,6 +393,7 @@
MountRaisedModal,
WelcomeModal,
HatchingModal,
+ InventoryDrawer,
},
directives: {
resize: ResizeDirective,
diff --git a/website/client/components/shared/inventoryDrawer.vue b/website/client/components/shared/inventoryDrawer.vue
new file mode 100644
index 0000000000..a2fa8fd83d
--- /dev/null
+++ b/website/client/components/shared/inventoryDrawer.vue
@@ -0,0 +1,169 @@
+
+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"
+ )
+
+
+
+
+
+
+
diff --git a/website/client/components/shops/featuredItemsHeader.vue b/website/client/components/shops/featuredItemsHeader.vue
new file mode 100644
index 0000000000..04ccc614ad
--- /dev/null
+++ b/website/client/components/shops/featuredItemsHeader.vue
@@ -0,0 +1,126 @@
+
+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")
+
+
+
+
+
+
diff --git a/website/client/components/shops/index.vue b/website/client/components/shops/index.vue
index 71d7b2c608..5c275f7a82 100644
--- a/website/client/components/shops/index.vue
+++ b/website/client/components/shops/index.vue
@@ -11,17 +11,11 @@
diff --git a/website/client/components/shops/market/categoryItem.vue b/website/client/components/shops/market/categoryItem.vue
new file mode 100644
index 0000000000..bdd4546ca9
--- /dev/null
+++ b/website/client/components/shops/market/categoryItem.vue
@@ -0,0 +1,52 @@
+
+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")
+
+
+
diff --git a/website/client/components/shops/market/categoryRow.vue b/website/client/components/shops/market/categoryRow.vue
new file mode 100644
index 0000000000..d35758fda2
--- /dev/null
+++ b/website/client/components/shops/market/categoryRow.vue
@@ -0,0 +1,94 @@
+
+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')
+
+
+
diff --git a/website/client/components/shops/market/equipmentSection.vue b/website/client/components/shops/market/equipmentSection.vue
new file mode 100644
index 0000000000..a0bbd70493
--- /dev/null
+++ b/website/client/components/shops/market/equipmentSection.vue
@@ -0,0 +1,167 @@
+
+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")
+
+
+
+
+
diff --git a/website/client/components/shops/market/filter.vue b/website/client/components/shops/market/filter.vue
new file mode 100644
index 0000000000..2f32c507ed
--- /dev/null
+++ b/website/client/components/shops/market/filter.vue
@@ -0,0 +1,46 @@
+
+.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)"
+ )
+
+
+
+
+
diff --git a/website/client/components/shops/market/index.vue b/website/client/components/shops/market/index.vue
index c075987fed..ccf3f432de 100644
--- a/website/client/components/shops/market/index.vue
+++ b/website/client/components/shops/market/index.vue
@@ -1,245 +1,79 @@
- .row.market
- .standard-sidebar.d-none.d-sm-block
+ page-layout.market
+ div(slot="sidebar")
.form-group
input.form-control.input-search(type="text", v-model="searchText", :placeholder="$t('search')")
- .form
- h2(v-once) {{ $t('filter') }}
- .form-group
- .form-check(
- v-for="category in categories",
- :key="category.identifier",
- )
- .custom-control.custom-checkbox
- input.custom-control-input(type="checkbox", v-model="viewOptions[category.identifier].selected", :id="`category-${category.identifier}`")
- label.custom-control-label(v-once, :for="`category-${category.identifier}`") {{ category.text }}
- div.form-group.clearfix
- h3.float-left(v-once) {{ $t('hideLocked') }}
- toggle-switch.float-right(
- 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")
+ market-filter(
+ :categories="categories",
+ :hideLocked.sync="hideLocked",
+ :hidePinned.sync="hidePinned",
+ :viewOptions="viewOptions"
+ )
+ div(slot="page")
+ featured-items-header(
+ :broken="broken",
+ :npcName="'Alex'",
+ :featuredText="market.featured.text",
+ :featuredItems="market.featured.items"
+ @featuredItemSelected="featuredItemSelected($event)"
+ )
h1.mb-4.page-header(v-once) {{ $t('market') }}
- .clearfix(v-if="viewOptions['equipment'].selected")
- h2.float-left.mb-3.filters-title
- | {{ $t('equipment') }}
-
- .filters.float-right
- 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"
+ equipment-section(
+ v-if="viewOptions['equipment'].selected",
+ :hidePinned="hidePinned",
+ :hideLocked="hideLocked",
+ :searchBy="searchTextThrottled"
)
- 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)"
+
+ layout-section(:title="$t('items')")
+ div(slot="filters")
+ filter-dropdown(
+ :label="$t('sortBy')",
+ :initialItem="selectedSortItemsBy",
+ :items="sortItemsBy",
+ @selected="selectedSortItemsBy = $event"
)
-
- 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")
-
- .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) }}
-
-
+ span(slot="item", slot-scope="ctx")
+ span.text {{ $t(ctx.item.id) }}
div(
v-for="category in categories",
v-if="viewOptions[category.identifier].selected && category.identifier !== 'equipment'"
)
h4 {{ category.text }}
-
- div.items
- shopItem(
- v-for="item in sortedMarketItems(category, selectedSortItemsBy, searchTextThrottled, hidePinned)",
- :key="item.key",
- :item="item",
- :emptyItem="false",
- :popoverPosition="'top'",
- @click="itemSelected(item)"
+ category-row(
+ :hidePinned="hidePinned",
+ :hideLocked="hideLocked",
+ :searchBy="searchTextThrottled",
+ :sortBy="selectedSortItemsBy.id",
+ :category="category"
)
- 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"')
-
div.fill-height
- //- @TODO: Create new InventoryDrawer component and re-use in 'inventory/stable' component.
- 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)"
- )
+ inventoryDrawer(:showEggs="true", :showPotions="true")
template(slot="item", slot-scope="ctx")
- item.flat(
+ item(
:item="ctx.item",
- :itemContentClass="getItemClass(selectedDrawerItemType, ctx.item.key)",
- :showPopover="false"
+ :itemContentClass="ctx.itemClass",
+ popoverPosition="top",
+ @click="sellItem(ctx)"
)
- template(slot="itemBadge", slot-scope="ctx")
- countBadge(
- :show="true",
- :count="userItems[drawerTabs[selectedDrawerTab].contentType][ctx.item.key] || 0"
- )
+ countBadge(
+ slot="itemBadge"
+ :show="true",
+ :count="ctx.itemCount"
+ )
+ h4.popover-content-title(slot="popoverContent") {{ ctx.itemName }}
+
+ sellModal
@@ -358,14 +129,18 @@
import ShopItem from '../shopItem';
import KeysToKennel from './keysToKennel';
+ import EquipmentSection from './equipmentSection';
+ import CategoryRow from './categoryRow';
import Item from 'client/components/inventory/item';
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 toggleSwitch from 'client/components/ui/toggleSwitch';
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 EquipmentAttributesGrid from '../../inventory/equipment/attributesGrid.vue';
@@ -374,52 +149,45 @@
import svgPin from 'assets/svg/pin.svg';
import svgGem from 'assets/svg/gem.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 isPinned from 'common/script/libs/isPinned';
import shops from 'common/script/libs/shops';
- import planGemLimits from 'common/script/libs/planGemLimits';
import _filter from 'lodash/filter';
- import _sortBy from 'lodash/sortBy';
import _map from 'lodash/map';
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 buyMixin from 'client/mixins/buy';
import currencyMixin from '../_currencyMixin';
-
- const sortGearTypeMap = {
- sortByType: 'type',
- sortByPrice: 'value',
- sortByCon: 'con',
- sortByStr: 'str',
- sortByInt: 'int',
- };
+ import inventoryUtils from 'client/mixins/inventoryUtils';
+ import pinUtils from 'client/mixins/pinUtils';
export default {
- mixins: [notifications, buyMixin, currencyMixin],
+ mixins: [notifications, buyMixin, currencyMixin, inventoryUtils, pinUtils],
components: {
ShopItem,
KeysToKennel,
Item,
CountBadge,
- Drawer,
- DrawerSlider,
- DrawerHeaderTabs,
+
ItemRows,
- toggleSwitch,
SellModal,
EquipmentAttributesGrid,
Avatar,
+ InventoryDrawer,
+ FeaturedItemsHeader,
+ PageLayout,
+ LayoutSection,
+ FilterDropdown,
+ EquipmentSection,
+ CategoryRow,
+ MarketFilter,
+
SelectMembersModal,
},
watch: {
@@ -438,24 +206,10 @@ export default {
pin: svgPin,
gem: svgGem,
information: svgInformation,
- warrior: svgWarrior,
- wizard: svgWizard,
- rogue: svgRogue,
- healer: svgHealer,
}),
- selectedDrawerTab: 0,
- selectedDrawerItemType: 'eggs',
-
- selectedGroupGearByClass: '',
-
- sortGearBy: sortGearTypes,
- selectedSortGearBy: 'sortByType',
-
- sortItemsBy: ['AZ', 'sortByNumber'],
- selectedSortItemsBy: 'AZ',
-
- selectedItemToSell: null,
+ sortItemsBy: sortItems,
+ selectedSortItemsBy: sortItems[0],
hideLocked: false,
hidePinned: false,
@@ -474,120 +228,79 @@ export default {
userStats: 'user.data.stats',
userItems: 'user.data.items',
}),
- marketGearCategories () {
- return shops.getMarketGearCategories(this.user);
- },
market () {
return shops.getMarketShop(this.user);
},
categories () {
- if (this.market) {
- let categories = [
- ...this.market.categories,
- ];
+ if (!this.market) return [];
- categories.push({
- identifier: 'equipment',
- 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'),
- },
+ let categories = [
+ ...this.market.categories,
];
- },
- gemsLeft () {
- if (!this.user.purchased.plan) return 0;
- return planGemLimits.convCap + this.user.purchased.plan.consecutive.gemCapExtra - this.user.purchased.plan.gemsBought;
+
+ categories.push({
+ identifier: 'equipment',
+ 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: {
- getClassName (classType) {
- if (classType === 'wizard') {
- return this.$t('mage');
- } else {
- return this.$t(classType);
- }
- },
- tabSelected ($event) {
- this.selectedDrawerTab = $event;
- this.selectedDrawerItemType = this.drawerTabs[$event].key;
+ sellItem (itemScope) {
+ this.$root.$emit('sellItem', itemScope);
},
ownedItems (type) {
let mappedItems = _filter(this.content[type], i => {
@@ -620,133 +333,18 @@ export default {
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) {
this.$root.$emit('buyModal::showItem', item);
},
featuredItemSelected (item) {
if (item.purchaseType === 'gear') {
- this.gearSelected(item);
+ if (!item.locked) {
+ this.itemSelected(item);
+ }
} else {
this.itemSelected(item);
}
},
- gearSelected (item) {
- if (!item.locked) {
- this.$root.$emit('buyModal::showItem', item);
- }
- },
- },
- created () {
- this.selectedGroupGearByClass = this.userStats.class;
},
};
diff --git a/website/client/components/shops/market/sellModal.vue b/website/client/components/shops/market/sellModal.vue
index a3c2f654da..128208e2b7 100644
--- a/website/client/components/shops/market/sellModal.vue
+++ b/website/client/components/shops/market/sellModal.vue
@@ -1,6 +1,5 @@
b-modal#sell-modal(
- :visible="item != null",
:hide-header="true",
@change="onChange($event)"
)
@@ -8,30 +7,37 @@
span.svg-icon.inline.icon-10(aria-hidden="true", v-html="icons.close", @click="hideDialog()")
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")
- slot(name="item", :item="item")
+ h4.title {{ itemContextToSell.itemName }}
- h4.title {{ text ? text : item.text() }}
- div.text {{ item.sellWarningNote() }}
- br
+ div(v-if="item.sellWarningNote")
+ div.text {{ item.sellWarningNote() }}
+ br
- div.inner-content(v-else)
- slot(name="item", :item="item")
+ div(v-once)
+ div.text {{ item.notes() }}
- h4.title {{ text ? text : item.text() }}
- div.text {{ item.notes() }}
+ div
+ b.how-many-to-sell {{ $t('howManyToSell') }}
- div
- b.how-many-to-sell {{ $t('howManyToSell') }}
+ div
+ b-input.itemsToSell(type="number", v-model="selectedAmountToSell", :max="itemContextToSell.itemCount", min="1", @keyup.native="preventNegative($event)", step="1")
- div
- b-input.itemsToSell(type="number", v-model="selectedAmountToSell", :max="itemCount", min="1", @keyup.native="preventNegative($event)", step="1")
+ span.svg-icon.inline.icon-32(aria-hidden="true", v-html="icons.gold")
+ span.value {{ item.value }}
- span.svg-icon.inline.icon-32(aria-hidden="true", v-html="icons.gold")
- span.value {{ item.value }}
-
- button.btn.btn-primary(@click="sellItems()") {{ $t('sell') }}
+ button.btn.btn-primary(@click="sellItems()") {{ $t('sell') }}
div.clearfix(slot="modal-footer")
span.balance.float-left {{ $t('yourBalance') }}
@@ -119,14 +125,19 @@
import svgGem from 'assets/svg/gem.svg';
import BalanceInfo from '../balanceInfo.vue';
+ import Item from 'client/components/inventory/item';
+ import CountBadge from 'client/components/ui/countBadge';
export default {
components: {
BalanceInfo,
+ Item,
+ CountBadge,
},
data () {
return {
selectedAmountToSell: 1,
+ itemContextToSell: null,
icons: Object.freeze({
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: {
onChange ($event) {
this.$emit('change', $event);
@@ -155,7 +180,7 @@
}
this.$store.dispatch('shops:sellItems', {
- type: this.itemType,
+ type: this.itemContextToSell.itemType,
key: this.item.key,
amount: this.selectedAmountToSell,
});
@@ -165,19 +190,5 @@
this.$root.$emit('bv::hide::modal', 'sell-modal');
},
},
- props: {
- item: {
- type: Object,
- },
- itemType: {
- type: String,
- },
- text: {
- type: String,
- },
- itemCount: {
- type: Number,
- },
- },
};
diff --git a/website/client/components/shops/quests/index.vue b/website/client/components/shops/quests/index.vue
index f63b93fa94..7194137872 100644
--- a/website/client/components/shops/quests/index.vue
+++ b/website/client/components/shops/quests/index.vue
@@ -339,6 +339,7 @@
import toggleSwitch from 'client/components/ui/toggleSwitch';
import Avatar from 'client/components/avatar';
import buyMixin from 'client/mixins/buy';
+ import pinUtils from 'client/mixins/pinUtils';
import currencyMixin from '../_currencyMixin';
import BuyModal from './buyQuestModal.vue';
@@ -357,7 +358,7 @@
import _map from 'lodash/map';
export default {
- mixins: [buyMixin, currencyMixin],
+ mixins: [buyMixin, currencyMixin, pinUtils],
components: {
ShopItem,
Item,
@@ -474,11 +475,6 @@ export default {
return false;
},
- togglePinned (item) {
- if (!this.$store.dispatch('user:togglePinnedItem', {type: item.pinType, path: item.path})) {
- this.$parent.showUnpinNotification(item);
- }
- },
selectItem (item) {
if (item.locked) return;
diff --git a/website/client/components/shops/seasonal/index.vue b/website/client/components/shops/seasonal/index.vue
index f0fb13b237..689c7bf05f 100644
--- a/website/client/components/shops/seasonal/index.vue
+++ b/website/client/components/shops/seasonal/index.vue
@@ -294,6 +294,7 @@
import Avatar from 'client/components/avatar';
import buyMixin from 'client/mixins/buy';
import currencyMixin from '../_currencyMixin';
+ import pinUtils from 'client/mixins/pinUtils';
import svgPin from 'assets/svg/pin.svg';
import svgWarrior from 'assets/svg/warrior.svg';
@@ -318,7 +319,7 @@
import shops from 'common/script/libs/shops';
export default {
- mixins: [buyMixin, currencyMixin],
+ mixins: [buyMixin, currencyMixin, pinUtils],
components: {
ShopItem,
Item,
@@ -514,11 +515,6 @@
return false;
},
- togglePinned (item) {
- if (!this.$store.dispatch('user:togglePinnedItem', {type: item.pinType, path: item.path})) {
- this.$parent.showUnpinNotification(item);
- }
- },
itemSelected (item) {
if (item.locked) return;
this.$root.$emit('buyModal::showItem', item);
diff --git a/website/client/components/shops/timeTravelers/index.vue b/website/client/components/shops/timeTravelers/index.vue
index f236dd9a93..5a01e08cf7 100644
--- a/website/client/components/shops/timeTravelers/index.vue
+++ b/website/client/components/shops/timeTravelers/index.vue
@@ -240,8 +240,10 @@
import isPinned from 'common/script/libs/isPinned';
import shops from 'common/script/libs/shops';
+ import pinUtils from 'client/mixins/pinUtils';
export default {
+ mixins: [pinUtils],
components: {
ShopItem,
Item,
@@ -369,11 +371,6 @@
getGrouped (entries) {
return _groupBy(entries, 'group');
},
- togglePinned (item) {
- if (!this.$store.dispatch('user:togglePinnedItem', {type: item.pinType, path: item.path})) {
- this.$parent.showUnpinNotification(item);
- }
- },
selectItemToBuy (item) {
this.$root.$emit('buyModal::showItem', item);
},
diff --git a/website/client/components/ui/checkbox.vue b/website/client/components/ui/checkbox.vue
new file mode 100644
index 0000000000..ee0ea51ed5
--- /dev/null
+++ b/website/client/components/ui/checkbox.vue
@@ -0,0 +1,26 @@
+
+ .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 }}
+
+
+
diff --git a/website/client/components/ui/countBadge.vue b/website/client/components/ui/countBadge.vue
index 8a003fea41..14bef71a4c 100644
--- a/website/client/components/ui/countBadge.vue
+++ b/website/client/components/ui/countBadge.vue
@@ -1,6 +1,6 @@
span.badge.badge-pill.badge-item.badge-count(
- v-if="show && count != 0",
+ v-if="show && count > 0",
) {{ count }}
diff --git a/website/client/components/ui/filterDropdown.vue b/website/client/components/ui/filterDropdown.vue
new file mode 100644
index 0000000000..d1ebd52b3b
--- /dev/null
+++ b/website/client/components/ui/filterDropdown.vue
@@ -0,0 +1,45 @@
+
+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")
+
+
+
+
+
diff --git a/website/client/components/ui/layoutSection.vue b/website/client/components/ui/layoutSection.vue
new file mode 100644
index 0000000000..11c527c492
--- /dev/null
+++ b/website/client/components/ui/layoutSection.vue
@@ -0,0 +1,33 @@
+
+div
+ .clearfix
+ h2.float-left.mb-3.filters-title {{ title }}
+
+ .filters.float-right
+ slot(name="filters")
+
+ br
+
+ slot(name="content")
+
+
+
+
+
+
diff --git a/website/client/components/ui/pageLayout.vue b/website/client/components/ui/pageLayout.vue
new file mode 100644
index 0000000000..9981923d53
--- /dev/null
+++ b/website/client/components/ui/pageLayout.vue
@@ -0,0 +1,25 @@
+
+.row
+ .standard-sidebar.d-none.d-sm-block(v-if="showSidebar")
+ slot(name="sidebar")
+ .standard-page
+ slot(name="page")
+
+
+
+
+
diff --git a/website/client/mixins/inventoryUtils.js b/website/client/mixins/inventoryUtils.js
new file mode 100644
index 0000000000..87385a0aa4
--- /dev/null
+++ b/website/client/mixins/inventoryUtils.js
@@ -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();
+ }
+ },
+ },
+};
diff --git a/website/client/mixins/pinUtils.js b/website/client/mixins/pinUtils.js
new file mode 100644
index 0000000000..b003754b01
--- /dev/null
+++ b/website/client/mixins/pinUtils.js
@@ -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}));
+ },
+ },
+};
diff --git a/website/common/script/libs/shops.js b/website/common/script/libs/shops.js
index 68243c98ee..dc21fe20ae 100644
--- a/website/common/script/libs/shops.js
+++ b/website/common/script/libs/shops.js
@@ -104,6 +104,7 @@ function getClassName (classType, language) {
}
}
+// TODO Refactor the `.locked` logic
shops.checkMarketGearLocked = function checkMarketGearLocked (user, items) {
let result = filter(items, ['pinType', 'marketGear']);
let availableGear = map(updateStore(user), (item) => getItemInfo(user, 'marketGear', item).path);
@@ -116,12 +117,6 @@ shops.checkMarketGearLocked = function checkMarketGearLocked (user, items) {
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)) {
let currentSet = gear.set === seasonalShopConfig.pinnedSets[gear.specialClass];
@@ -132,7 +127,6 @@ shops.checkMarketGearLocked = function checkMarketGearLocked (user, items) {
gear.locked = !gear.canOwn(user);
}
-
let itemOwned = user.items.gear.owned[gear.key];
if (itemOwned === false && !availableGear.includes(gear.path)) {
@@ -140,6 +134,12 @@ shops.checkMarketGearLocked = function checkMarketGearLocked (user, items) {
}
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) => {
- 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.specialClass) === -1 &&
(gear.canOwn && gear.canOwn(user));