Skip to content

Commit

Permalink
Merge branch 'release/2.33.0' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Lakeyzer committed Nov 17, 2024
2 parents a582b7a + 294e230 commit 2c3c930
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 8 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.32.0",
"version": "2.33.0",
"name": "shieldmaiden",
"description": "A Dungeons and Dragons Combat Tracker",
"productName": "Shieldmaiden",
Expand Down
184 changes: 184 additions & 0 deletions src/components/PromoBanner.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
<template>
<a
v-if="show_banner"
class="promo-banner"
href="https://www.patreon.com/shieldmaidenapp/membership"
target="_blank"
rel="noopener"
>
<button v-if="closable" class="no-thanks" @click.stop.prevent="show_banner = false">
no thanks
</button>
<div class="promo-banner__body">
<div class="discount">
<div class="discount__percentage">{{ discount }}</div>
<div class="discount__off">OFF</div>
</div>
<div>
<div class="code">
Use promo code
<div>{{ code }}</div>
</div>
</div>
</div>
<div class="promo-banner__footer">
<div class="remaining">
Get your first month with a <strong>{{ discount }}%</strong> discount.
<template v-if="hours_remaining <= 1">Less than </template>
<span class="remaining__count">{{
days_remaining ? days_remaining : hours_remaining
}}</span>
{{ days_remaining ? "days" : "hours" }} left.
</div>
<span class="btn bg-patreon-red">Subscribe now!</span>
</div>
</a>
</template>

<script>
import { mapGetters } from "vuex";
export default {
name: "PromoBanner",
props: {
closable: {
type: Boolean,
default: true,
},
},
data() {
return {
code: "SHIELDMAIDEN80",
discount: 80,
now: new Date(),
start: new Date("2024-11-15T00:00:00Z"),
end: new Date("2024-12-03T07:59:59Z"),
showSetter: undefined,
timer: null,
};
},
computed: {
...mapGetters(["tier"]),
show_banner: {
get() {
const show =
(this.tier?.price === "Free" || !this.tier) &&
this.now >= this.start &&
this.now <= this.end;
return this.showSetter !== undefined ? this.showSetter : show;
},
set(newVal) {
this.showSetter = newVal;
},
},
days_remaining() {
const diff = this.end - this.now;
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
return days >= 1 ? days : undefined;
},
hours_remaining() {
const diff = this.end - this.now;
const hours = Math.floor(diff / (1000 * 60 * 60));
return hours;
},
},
mounted() {
if (this.show_banner) {
this.$emit("discount", this.discount);
}
this.timer = setInterval(() => {
this.now = new Date();
}, 60000);
},
beforeDestroy() {
clearInterval(this.timer);
},
};
</script>
<style lang="scss" scoped>
.promo-banner {
display: block;
border-radius: $border-radius;
background-color: $neutral-9;
color: $white;
position: relative;
.no-thanks {
position: absolute;
line-height: normal;
color: $neutral-5;
font-size: 12px;
padding: 5px;
top: 0;
right: 0;
&:hover {
color: $neutral-4;
}
}
&__body {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
width: 100%;
padding: 15px 25px;
column-gap: 25px;
row-gap: 10px;
.code {
color: $neutral-2;
> div {
color: $white;
display: inline-block;
text-transform: uppercase;
font-weight: bold;
background-color: $neutral-6;
border-radius: $border-radius-small;
padding: 5px 10px;
font-size: 20px;
}
}
.discount {
display: flex;
align-items: center;
&__percentage {
font-size: 80px;
line-height: 80px;
font-weight: bold;
}
&__off {
font-weight: bold;
font-size: 30px;
line-height: 30px;
opacity: 0.8;
&:before {
content: "%";
display: block;
}
}
}
}
&__footer {
border-bottom-left-radius: inherit;
border-bottom-right-radius: inherit;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
padding: 15px 25px;
gap: 15px;
background-color: $neutral-6-transparent;
.remaining {
font-size: 18px;
&__count {
font-weight: bold;
color: $patreon-red;
}
}
}
}
</style>
41 changes: 37 additions & 4 deletions src/components/Tiers.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<template>
<div>
<q-no-ssr>
<PromoBanner class="mb-5" :closable="false" @discount="setDiscount" />
</q-no-ssr>
<div v-if="!loading">
<hk-card-deck>
<template v-for="(t, key) in tiers">
Expand All @@ -14,11 +17,21 @@
</div>
<div class="card-body">
<div class="top">
<span class="price" :class="{ 'patreon-red': t.name === 'Free' }">{{
t.price
}}</span>
<span
class="price"
:class="{
'patreon-red': t.name === 'Free',
strike: discount && t.name !== 'Free',
}"
>{{ t.price }}</span
>
<span v-if="discount && t.name !== 'Free'" class="price"
>${{ discountPrice(t.price) }}</span
>
<em v-if="t.price === 'Free'" class="neutral-2 sub">forever</em>
<em v-else class="neutral-2 sub">per month</em>
<em v-else class="neutral-2 sub">{{
discount ? "the first month" : "per month"
}}</em>
</div>
<ul>
<li v-for="(benefit, key) in default_benefits" :key="key">
Expand Down Expand Up @@ -130,13 +143,18 @@
import { mapGetters } from "vuex";
import { db } from "src/firebase";
import { legacy_tiers } from "src/utils/generalConstants";
import PromoBanner from "./PromoBanner.vue";
export default {
name: "Tiers",
components: {
PromoBanner,
},
data() {
return {
loading: true,
show_storage: false,
discount: undefined,
default_benefits: [
"Combat tracker",
"Encounter builder",
Expand Down Expand Up @@ -191,6 +209,13 @@ export default {
tier: t.name,
});
},
setDiscount(discount) {
this.discount = discount;
},
discountPrice(price) {
price = Number(price.slice(1));
return (price * (1 - this.discount / 100)).toFixed(2);
},
},
};
</script>
Expand All @@ -210,10 +235,18 @@ export default {
.top {
padding: 15px;
.price {
font-size: 25px;
font-weight: bold;
margin-right: 5px;
&.strike {
text-decoration: line-through;
font-weight: normal;
color: $neutral-2;
font-size: 20px;
}
}
i.sub {
display: block;
Expand Down
2 changes: 1 addition & 1 deletion src/css/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,7 @@ html body {
}

.breadcrumb {
margin-bottom: 20px;
margin-bottom: 1rem;
background: $neutral-6;
border-radius: $border-radius;
padding: 10px 15px;
Expand Down
3 changes: 3 additions & 0 deletions src/layouts/authenticated.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<OverEncumbered v-if="show_overencumbered" />
<div class="row q-col-gutter-md">
<div class="col-12" :class="{ 'col-md-9': width > 978 && $route.meta.side !== false }">
<PromoBanner class="mb-3" />
<router-view :key="$route.fullPath" />
<slot />
</div>
Expand All @@ -27,6 +28,7 @@ import ContentSideRight from "src/components/ContentSideRight";
import OverEncumbered from "src/components/userContent/OverEncumbered";
import PaymentDeclined from "src/components/PaymentDeclined.vue";
import PatreonLinkDialog from "src/components/dialogs/PatreonLinkDialog.vue";
import PromoBanner from "src/components/PromoBanner.vue";
export default {
name: "AuthenticatedLayout",
Expand All @@ -36,6 +38,7 @@ export default {
ContentSideRight,
OverEncumbered,
PaymentDeclined,
PromoBanner,
},
preFetch({ store, redirect }) {
if (!store.getters.user) {
Expand Down

0 comments on commit 2c3c930

Please sign in to comment.