feat(event): countdown banners for limited availability items

This commit is contained in:
Sabe Jones
2021-04-07 12:24:24 -05:00
parent 1b0b31cd80
commit cdaa504db4
7 changed files with 191 additions and 40 deletions
@@ -161,16 +161,10 @@
</button>
</div>
</div>
<div
<countdown-banner
v-if="item.event && item.owned == null"
class="limitedTime"
>
<span
class="svg-icon inline icon-16 clock-icon"
v-html="icons.clock"
></span>
<span class="limitedString">{{ limitedString }}</span>
</div>
:endDate = "endDate"
/>
<div
v-if="item.key === 'rebirth_orb' && item.value > 0 && user.stats.lvl >= 100"
class="free-rebirth d-flex align-items-center"
@@ -399,6 +393,7 @@ import svgWhiteClock from '@/assets/svg/clock-white.svg';
import BalanceInfo from './balanceInfo.vue';
import PinBadge from '@/components/ui/pinBadge';
import CountdownBanner from './countdownBanner';
import currencyMixin from './_currencyMixin';
import notifications from '@/mixins/notifications';
import buyMixin from '@/mixins/buy';
@@ -432,6 +427,7 @@ export default {
Item,
Avatar,
PinBadge,
CountdownBanner,
},
mixins: [buyMixin, currencyMixin, notifications, numberInvalid, spellsMixin],
props: {
@@ -462,6 +458,7 @@ export default {
selectedAmountToBuy: 1,
isPinned: false,
endDate: seasonalShopConfig.dateRange.end,
};
},
computed: {
@@ -494,9 +491,6 @@ export default {
}
return this.item.notes;
},
limitedString () {
return this.$t('limitedOffer', { date: moment(seasonalShopConfig.dateRange.end).format('LL') });
},
gemsLeft () {
if (!this.user.purchased.plan) return 0;
return planGemLimits.convCap
@@ -0,0 +1,84 @@
<template>
<div class="limitedTime">
<span
class="svg-icon inline icon-16"
v-html="icons.clock"
></span>
<span class="limitedString"> {{ limitedString }} </span>
</div>
</template>
<style lang="scss" scoped>
@import '~@/assets/scss/colors.scss';
.limitedTime {
height: 32px;
background-color: $purple-300;
width: calc(100% + 30px);
margin: 0 -15px; // the modal content has its own padding
font-size: 12px;
line-height: 1.33;
text-align: center;
color: $white;
display: flex;
align-items: center;
justify-content: center;
.limitedString {
height: 16px;
margin-left: 8px;
}
}
</style>
<script>
import moment from 'moment';
import svgClock from '@/assets/svg/clock.svg';
export default {
props: {
endDate: {
type: String,
},
},
data () {
return {
icons: Object.freeze({
clock: svgClock,
}),
timer: '',
limitedString: '',
};
},
mounted () {
this.countdownString();
this.timer = setInterval(this.countdownString, 30000);
},
methods: {
countdownString () {
const diffDuration = moment.duration(moment(this.endDate).diff(moment()));
if (diffDuration.days() > 0) {
this.limitedString = this.$t('limitedAvailabilityDays', {
days: diffDuration.days(),
hours: diffDuration.hours(),
minutes: diffDuration.minutes(),
});
} else {
this.limitedString = this.$t('limitedAvailabilityHours', {
hours: diffDuration.hours(),
minutes: diffDuration.minutes(),
});
}
},
cancelAutoUpdate () {
clearInterval(this.timer);
},
},
beforeDestroy () {
this.cancelAutoUpdate();
},
};
</script>
@@ -48,6 +48,12 @@ export default {
},
mixins: [pinUtils],
props: ['hideLocked', 'hidePinned', 'searchBy', 'sortBy', 'category'],
data () {
return {
timer: '',
limitedString: '',
};
},
computed: {
...mapState({
content: 'content',
@@ -60,9 +66,6 @@ export default {
return planGemLimits.convCap
+ this.user.purchased.plan.consecutive.gemCapExtra - this.user.purchased.plan.gemsBought;
},
limitedString () {
return this.$t('limitedOffer', { date: moment(seasonalShopConfig.dateRange.end).format('LL') });
},
sortedMarketItems () {
let result = _map(this.category.items, e => ({
...e,
@@ -103,10 +106,36 @@ export default {
return result;
},
},
mounted () {
this.countdownString();
this.timer = setInterval(this.countdownString, 30000);
},
methods: {
itemSelected (item) {
this.$root.$emit('buyModal::showItem', item);
},
countdownString () {
const diffDuration = moment.duration(moment(seasonalShopConfig.dateRange.end).diff(moment()));
if (diffDuration.days() > 0) {
this.limitedString = this.$t('limitedAvailabilityDays', {
days: diffDuration.days(),
hours: diffDuration.hours(),
minutes: diffDuration.minutes(),
});
} else {
this.limitedString = this.$t('limitedAvailabilityHours', {
hours: diffDuration.hours(),
minutes: diffDuration.minutes(),
});
}
},
cancelAutoUpdate () {
clearInterval(this.timer);
},
},
beforeDestroy () {
this.cancelAutoUpdate();
},
};
</script>
@@ -84,16 +84,10 @@
>
<questDialogDrops :item="item" />
</div>
<div
<countdown-banner
v-if="item.event"
class="limitedTime"
>
<span
class="svg-icon inline icon-16 clock-icon"
v-html="icons.clock"
></span>
<span class="limitedString">{{ limitedString }}</span>
</div>
:endDate="endDate"
/>
<div
slot="modal-footer"
class="clearfix"
@@ -268,7 +262,6 @@
</style>
<script>
import moment from 'moment';
import { mapState } from '@/libs/store';
import seasonalShopConfig from '@/../../common/script/libs/shops-seasonal.config';
@@ -285,6 +278,7 @@ import notifications from '@/mixins/notifications';
import buyMixin from '@/mixins/buy';
import numberInvalid from '@/mixins/numberInvalid';
import PinBadge from '@/components/ui/pinBadge';
import CountdownBanner from '../countdownBanner';
import questDialogDrops from './questDialogDrops';
import questDialogContent from './questDialogContent';
@@ -295,6 +289,7 @@ export default {
PinBadge,
questDialogDrops,
questDialogContent,
CountdownBanner,
},
mixins: [buyMixin, currencyMixin, notifications, numberInvalid],
props: {
@@ -321,6 +316,7 @@ export default {
isPinned: false,
selectedAmountToBuy: 1,
endDate: seasonalShopConfig.dateRange.end,
};
},
computed: {
@@ -344,9 +340,6 @@ export default {
if (this.priceType === 'hourglasses') return this.icons.hourglass;
return this.icons.gem;
},
limitedString () {
return this.$t('limitedOffer', { date: moment(seasonalShopConfig.dateRange.end).format('LL') });
},
},
watch: {
item: function itemChanged () {
@@ -143,6 +143,8 @@ export default {
starHalf: svgStarHalf,
starEmpty: svgStarEmpty,
}),
timer: '',
limitedString: '',
};
},
computed: {
@@ -153,9 +155,10 @@ export default {
return 1;
},
limitedString () {
return this.$t('limitedOffer', { date: moment(seasonalShopConfig.dateRange.end).format('LL') });
},
},
mounted () {
this.countdownString();
this.timer = setInterval(this.countdownString, 30000);
},
methods: {
stars () {
@@ -182,6 +185,28 @@ export default {
}
return collect.text;
},
countdownString () {
const diffDuration = moment.duration(moment(seasonalShopConfig.dateRange.end).diff(moment()));
if (diffDuration.days() > 0) {
this.limitedString = this.$t('limitedAvailabilityDays', {
days: diffDuration.days(),
hours: diffDuration.hours(),
minutes: diffDuration.minutes(),
});
} else {
this.limitedString = this.$t('limitedAvailabilityHours', {
hours: diffDuration.hours(),
minutes: diffDuration.minutes(),
});
}
},
cancelAutoUpdate () {
clearInterval(this.timer);
},
},
beforeDestroy () {
this.cancelAutoUpdate();
},
};
</script>
@@ -291,16 +291,18 @@ export default {
},
},
data () {
return Object.freeze({
return {
itemId: uuid(),
icons: {
icons: Object.freeze({
gems: svgGem,
gold: svgGold,
lock: svgLock,
hourglasses: svgHourglasses,
clock: svgClock,
},
});
}),
timer: '',
limitedString: '',
};
},
computed: {
showNotes () {
@@ -314,10 +316,10 @@ export default {
}
return 'gold';
},
limitedString () {
return this.item.owned === false ? ''
: this.$t('limitedOffer', { date: moment(seasonalShopConfig.dateRange.end).format('LL') });
},
},
mounted () {
this.countdownString();
this.timer = setInterval(this.countdownString, 30000);
},
methods: {
click () {
@@ -338,6 +340,28 @@ export default {
locked: this.item.locked,
};
},
countdownString () {
const diffDuration = moment.duration(moment(seasonalShopConfig.dateRange.end).diff(moment()));
if (diffDuration.days() > 0) {
this.limitedString = this.$t('limitedAvailabilityDays', {
days: diffDuration.days(),
hours: diffDuration.hours(),
minutes: diffDuration.minutes(),
});
} else {
this.limitedString = this.$t('limitedAvailabilityHours', {
hours: diffDuration.hours(),
minutes: diffDuration.minutes(),
});
}
},
cancelAutoUpdate () {
clearInterval(this.timer);
},
},
beforeDestroy () {
this.cancelAutoUpdate();
},
};
</script>
+3 -1
View File
@@ -125,5 +125,7 @@
"welcome3": "Progress in life and the game!",
"welcome3notes": "As you improve your life, your avatar will level up and unlock pets, quests, equipment, and more!",
"imReady": "Enter Habitica",
"limitedOffer": "Available until <%= date %>"
"limitedOffer": "Available until <%= date %>",
"limitedAvailabilityDays": "Available for <%= days %>d <%= hours %>h <%= minutes %>m",
"limitedAvailabilityHours": "Available for <%= hours %>h <%= minutes %>m"
}