Skip to content

Commit

Permalink
Merge branch 'fix/range-slider-currency' into 'master'
Browse files Browse the repository at this point in the history
fix: Add currency support for price range.

Closes storefront#86

See merge request schema/origin-storefront!32
  • Loading branch information
by-tim committed Apr 19, 2021
2 parents e4e058a + f2ac8ec commit 515f831
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module.exports = {
plugins: ['prettier'],
// add your custom rules here
rules: {
'no-console': 'off',
'no-console': 'warn',
'arrow-parens': ['error', 'as-needed'],
'object-shorthand': 'off',
'vue/no-v-html': 'off',
Expand Down
41 changes: 35 additions & 6 deletions components/FilterPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,16 @@
<div v-for="filter in filters" :key="filter.id">
<!-- Label -->
<span class="label-xs-bold-faded uppercase">{{ filter.label }}</span>
<!-- Range slider input -->
<!-- Price range slider input -->
<div v-if="filter.type === 'range'" class="w-full pt-4 pb-10">
<RangeSlider
:filter="filter"
:filter-state="localFilterState"
:is-price="filter.id === 'price'"
@change="updateFilter"
/>
</div>

<!-- Checkbox input -->
<div v-else class="pt-4 pb-8">
<InputSelect
Expand Down Expand Up @@ -120,6 +122,7 @@

<script>
// Helpers
import { mapState } from 'vuex'
import { mergeFilterState, listActiveFilters } from '~/modules/swell'
export default {
Expand All @@ -143,9 +146,16 @@ export default {
},
computed: {
...mapState(['currency']),
currencyObj() {
return this.$swell.currency.get(this.currency)
},
activeFilters() {
return listActiveFilters(this.filters, this.localFilterState)
},
activeFilterCountLabel() {
const count = this.activeFilters.length
return `${count} filter${count === 1 ? '' : 's'} active`
Expand Down Expand Up @@ -174,13 +184,32 @@ export default {
activeRangeLabel(filter) {
const [lower, upper] = filter.options
const prefix = filter.id === 'price' ? '$' : ''
return prefix + lower.label + '' + upper.label
let lowerLabel = lower.label
let upperLabel = upper.label
if (filter.id === 'price') {
const { rate } = this.currencyObj
const lowerPrice = lower.value * rate
const upperPrice = upper.value * rate
lowerLabel = new Intl.NumberFormat('default', {
style: 'currency',
currency: this.currency,
currencyDisplay: 'narrowSymbol',
maximumFractionDigits: 0
}).format(lowerPrice)
upperLabel = new Intl.NumberFormat('default', {
style: 'decimal',
maximumFractionDigits: 0
}).format(upperPrice)
}
return lowerLabel + '' + upperLabel
}
}
}
</script>

<style lang="postcss" scoped>
</style>
<style lang="postcss" scoped></style>
67 changes: 62 additions & 5 deletions components/RangeSlider.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
:value="value"
:min="slider.minValue"
:max="slider.maxValue"
:interval="filter.interval"
:interval="slider.interval"
:clickable="false"
tooltip="always"
tooltip-placement="bottom"
:tooltip-formatter="'${value}'"
:tooltip-formatter="'{value}'"
:process-style="slider.processStyle"
:rail-style="slider.railStyle"
:dot-size="20"
Expand All @@ -21,14 +21,17 @@
</template>

<template v-slot:tooltip="{ value: rangeValue }">
<div class="label-sm">${{ rangeValue }}</div>
<div class="label-sm">{{ formatTooltip(rangeValue) }}</div>
</template>
</vue-slider>
</ClientOnly>
</div>
</template>

<script>
// Helpers
import { mapState } from 'vuex'
// Components
import 'vue-slider-component/dist-css/vue-slider-component.css'
import 'vue-slider-component/theme/default.css'
Expand All @@ -44,6 +47,14 @@ export default {
filterState: {
type: Object,
default: () => ({})
},
isPrice: {
type: Boolean,
default: false
},
withIntervals: {
type: Boolean,
default: false
}
},
Expand All @@ -54,12 +65,43 @@ export default {
},
computed: {
...mapState(['currency']),
currencyObj() {
return this.$swell.currency.get(this.currency)
},
slider() {
const [min, max] = this.filter.options
let minValue = min.value
let maxValue = max.value
let interval = 1
if (this.withIntervals) {
if (minValue === maxValue) return
interval = Math.ceil((maxValue - minValue) / 10) || 1
if (interval > 1000) {
interval = 1000
} else if (interval > 100) {
interval = 100
} else if (interval > 10) {
interval = 10
}
if (maxValue % interval > 0) {
maxValue = interval + maxValue - (maxValue % interval)
}
if (minValue % interval > 0) {
minValue = minValue - (minValue % interval)
}
while (((maxValue - minValue) / interval) % 1 > 0) {
maxValue++
}
}
return {
minValue: min.value,
maxValue: max.value,
minValue,
maxValue,
interval,
railStyle: { background: this.$swell.settings.get('colors.primary.light') },
processStyle: { background: this.$swell.settings.get('colors.primary.darkest') }
}
Expand All @@ -75,6 +117,21 @@ export default {
},
methods: {
formatTooltip(value) {
if (this.isPrice) {
const { rate } = this.currencyObj
const price = value * rate
return new Intl.NumberFormat('default', {
style: 'currency',
currency: this.currency,
currencyDisplay: 'narrowSymbol',
maximumFractionDigits: 0
}).format(price)
}
return value
},
setValue() {
const [min, max] = this.filter.options
const stateValue = this.filterState[this.filter.id]
Expand Down
10 changes: 9 additions & 1 deletion pages/categories/_slug.vue
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
import get from 'lodash/get'
import pageMeta from '~/mixins/pageMeta'
import { getFilterStateFromQuery } from '~/modules/swell'
import { mapState } from 'vuex'
// Calculate product limit from category rows/cols
function getProductLimit(category) {
Expand Down Expand Up @@ -182,6 +183,7 @@ export default {
},
computed: {
...mapState(['currency']),
settings() {
return get(this, 'category.content', {})
},
Expand All @@ -206,7 +208,13 @@ export default {
watch: {
// Call the update method when the URL query changes
'$route.query': 'updateProductsFiltered'
'$route.query': 'updateProductsFiltered',
// Grab new filter value ranges when currency is chanegd
currency() {
if (!this.currency) return
this.filters = this.$swell.products.filters(this.products, { currency: this.currency })
}
},
created() {
Expand Down

0 comments on commit 515f831

Please sign in to comment.