Skip to content

Commit

Permalink
Add 2-Year license offer
Browse files Browse the repository at this point in the history
  • Loading branch information
pilotmoon committed May 24, 2024
1 parent e84acd0 commit 42b7d5a
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 17 deletions.
58 changes: 50 additions & 8 deletions site/src/Buy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,32 @@ function trackBuy(button) {
</a><br>
<span :class="$style.price">{{ roundPrice(store.masPrice.value) }}</span>
</div> -->
<div :class="$style.box" :hidden="!isLizhi || store.isLoadedForCoupon === null">
<div :class="$style.box">
<div :class="$style.product"><img src="/icon128.png"> PopClip for macOS</div>
<span :class="$style.title">Lifetime Personal License</span><br>
<span :class="$style.subtitle">Lifetime updates<br></span>
<span :class="$style.title">2-Year Personal License</span><br>
<span :class="$style.subtitle">2 years of updates<br></span>
<span :class="$style.subtitle">✅ Use on all your Macs<br></span>
<span :class="$style.subtitle">✅ Keep the last version you receive<br></span>
<span :class="$style.small"><a href="/terms">Full license terms</a><br></span>
<span v-if="isLizhi" :class="$style.subtitle">Buy from DIGITALYCHEE<br></span>
<a :href="store.lizhiUrl.value" target="_blank" @click="trackBuy('DIGITALYCHEE')">
<img :class="$style.buybadge" src="/badge-lizhi.svg" alt="Buy from DIGITALYCHEE Store">
</a><br>
<span :class="$style.price">{{ roundPrice(store.lizhiPrice.value) }}</span>
<span v-if="isLizhi" :class="$style.subtitle">Buy from Paddle<br></span>
<AaButton :class="$style.buybutton" @click="trackBuy('Paddle'); openPaddleCheckout()" theme="brand"
size="medium">
Buy with
<Icon size=18><CreditCard /></Icon>
<Icon size=18><Paypal /></Icon>
<Icon size=32><ApplePay /></Icon>
</AaButton><br>
<div :class="$style.prices">
<span v-if="store.paddleProducts.value.popclip_2year?.isDiscounted" :class="$style.listPrice">{{ roundPrice(store.paddleProducts.value.popclip_2year.displayListPrice ?? "") }}</span>
<span :class="$style.price">{{ roundPrice(store.paddleProducts.value.popclip_2year?.displayPrice ?? "") }}</span>
<span v-if="store.paddleProducts.value.popclip_2year?.isTaxed" :class="$style.tax">+ tax</span>
</div>
<div v-if="store.paddleProducts.value.popclip_2year?.isDiscounted && store.paddleProducts.value.popclip_2year?.message" :class="$style.priceMessage">
<span>{{ store.paddleProducts.value.popclip_2year?.message }}</span>
</div>
<div v-if="store.paddleProducts.value.popclip_2year?.coupon" :class="$style.couponInfo">
<span>{{ `Coupon "${store.paddleProducts.value.popclip_2year?.coupon ?? ""}" applied` }}</span>
</div>
<span :class="$style.subtitle">One-time purchase<br></span>
</div>
<div :class="$style.box">
Expand All @@ -111,12 +126,29 @@ function trackBuy(button) {
<div :class="$style.prices">
<span v-if="store.paddleProducts.value.popclip?.isDiscounted" :class="$style.listPrice">{{ roundPrice(store.paddleProducts.value.popclip.displayListPrice ?? "") }}</span>
<span :class="$style.price">{{ roundPrice(store.paddleProducts.value.popclip?.displayPrice ?? "") }}</span>
<span v-if="store.paddleProducts.value.popclip?.isTaxed" :class="$style.tax">+ tax</span>
</div>
<div v-if="store.paddleProducts.value.popclip?.isDiscounted && store.paddleProducts.value.popclip?.message" :class="$style.priceMessage">
<span>{{ store.paddleProducts.value.popclip?.message }}</span>
</div>
<div v-if="store.paddleProducts.value.popclip?.coupon" :class="$style.couponInfo">
<span>{{ `Coupon "${store.paddleProducts.value.popclip?.coupon ?? ""}" applied` }}</span>
</div>
<span :class="$style.subtitle">One-time purchase<br></span>
</div>
<div :class="$style.box" :hidden="!isLizhi || store.isLoadedForCoupon === null">
<div :class="$style.product"><img src="/icon128.png"> PopClip for macOS</div>
<span :class="$style.title">Lifetime Personal License</span><br>
<span :class="$style.subtitle">✅ Lifetime updates<br></span>
<span :class="$style.subtitle">✅ Use on all your Macs<br></span>
<span :class="$style.small"><a href="/terms">Full license terms</a><br></span>
<span v-if="isLizhi" :class="$style.subtitle">Buy from DIGITALYCHEE<br></span>
<a :href="store.lizhiUrl.value" target="_blank" @click="trackBuy('DIGITALYCHEE')">
<img :class="$style.buybadge" src="/badge-lizhi.svg" alt="Buy from DIGITALYCHEE Store">
</a><br>
<span :class="$style.price">{{ roundPrice(store.lizhiPrice.value) }}</span><br>
<span :class="$style.subtitle">One-time purchase<br></span>
</div>
</div>
<div :class="store.isLoadedForCoupon !== null ? $style.infoLine : $style.infoLineLoading">
{{ store.isLoadedForCoupon !== null ? `Showing prices for ${getFlagEmoji(store.countryCode.value)} ${store.countryName.value}` :
Expand Down Expand Up @@ -193,6 +225,16 @@ function trackBuy(button) {
text-decoration: line-through;
}
.box span.tax {
font-size: 14px;
}
.box div.priceMessage {
font-size: 14px;
color: var(--vp-c-purple-2);
}
.box div.couponInfo {
font-size: 14px;
font-weight: 600;
Expand Down
35 changes: 27 additions & 8 deletions site/src/composables/useStoreState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export async function loadStore() {

log("Loading prices", { coupon });
const fetchResponse = await fetch(
`${config.pilotmoon.frontendRoot}/store/getProducts?products=${config.pilotmoon.paddleProducts}&coupons=${coupon}`,
`${config.pilotmoon.frontendRoot}/store/getProducts?products=${Object.keys(config.pilotmoon.paddleProducts)}&coupons=${coupon}`,
);
if (!fetchResponse.ok) {
log("Failed to load prices");
Expand All @@ -100,10 +100,12 @@ export async function loadStore() {

const ZProcessedProduct = z.object({
isDiscounted: z.boolean(),
isTaxed: z.boolean(),
displayPrice: z.string(),
displayListPrice: z.string(),
displayDiscount: z.string().nullable(),
coupon: z.string().nullable(),
message: z.string().nullable(),
});
type ProcessedProduct = z.infer<typeof ZProcessedProduct>;

Expand All @@ -127,21 +129,38 @@ function preprocessProducts(productData: ProductsResult) {
);
}
const displayPrice = formatCurrency(
product.paddleData.price.gross,
product.paddleData.price.net,
product.paddleData.currency,
);
const displayListPrice = formatCurrency(
product.paddleData.list_price.gross,
product.paddleData.currency,
);
const isDiscounted =
product.paddleData.price.gross < product.paddleData.list_price.gross;
let displayListPrice: string;
let isDiscounted = false;
let message: string | null = null;
const productConfig = config.pilotmoon.paddleProducts[productData.products[key].product];
if (productConfig.fullPrice) {
displayListPrice = formatCurrency(
productConfig.fullPrice,
productConfig.fullPriceCurrency,
);
message = productConfig.message;
isDiscounted = product.paddleData.price.net < productConfig.fullPrice;
}
else {
displayListPrice = formatCurrency(
product.paddleData.list_price.net,
product.paddleData.currency,
);
isDiscounted =
product.paddleData.price.net < product.paddleData.list_price.net;
}
const isTaxed = product.paddleData.price.net < product.paddleData.price.gross;
const processed: ProcessedProduct = {
isTaxed,
isDiscounted,
displayPrice,
displayListPrice,
displayDiscount,
coupon,
message,
};
result[key] = processed;
}
Expand Down
11 changes: 10 additions & 1 deletion site/src/config/config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
{
"pilotmoon": {
"paddleProducts": "popclip",
"paddleProducts": {
"popclip_2year": {

},
"popclip": {
"fullPrice": 30,
"fullPriceCurrency": "USD",
"message": "New pricing - transitonal offer"
}
},
"iconsRoot": "https://icons.popclip.app",
"apiRoot": "https://api.pilotmoon.com/v2",
"frontendRoot": "https://api.pilotmoon.com/frontend",
Expand Down

0 comments on commit 42b7d5a

Please sign in to comment.