wip: new pricing

This commit is contained in:
Andras Bacsai 2024-04-12 15:48:56 +02:00
parent 1581e0e439
commit 7b4d8a8f05
9 changed files with 212 additions and 70 deletions

View File

@ -159,8 +159,12 @@ public function events(Request $request)
$feedback = data_get($data, 'cancellation_details.feedback'); $feedback = data_get($data, 'cancellation_details.feedback');
$comment = data_get($data, 'cancellation_details.comment'); $comment = data_get($data, 'cancellation_details.comment');
$lookup_key = data_get($data, 'items.data.0.price.lookup_key'); $lookup_key = data_get($data, 'items.data.0.price.lookup_key');
if (str($lookup_key)->contains('ultimate')) { if (str($lookup_key)->contains('ultimate') || str($lookup_key)->contains('dynamic')) {
if (str($lookup_key)->contains('dynamic')) {
$quantity = data_get($data, 'items.data.0.quantity', 2);
} else {
$quantity = data_get($data, 'items.data.0.quantity', 10); $quantity = data_get($data, 'items.data.0.quantity', 10);
}
$team = data_get($subscription, 'team'); $team = data_get($subscription, 'team');
$team->update([ $team->update([
'custom_server_limit' => $quantity, 'custom_server_limit' => $quantity,

View File

@ -39,6 +39,12 @@ public function subscribeStripe($type)
case 'ultimate-yearly': case 'ultimate-yearly':
$priceId = config('subscription.stripe_price_id_ultimate_yearly'); $priceId = config('subscription.stripe_price_id_ultimate_yearly');
break; break;
case 'dynamic-monthly':
$priceId = config('subscription.stripe_price_id_dynamic_monthly');
break;
case 'dynamic-yearly':
$priceId = config('subscription.stripe_price_id_dynamic_yearly');
break;
default: default:
$priceId = config('subscription.stripe_price_id_basic_monthly'); $priceId = config('subscription.stripe_price_id_basic_monthly');
break; break;
@ -72,6 +78,13 @@ public function subscribeStripe($type)
]; ];
$payload['line_items'][0]['quantity'] = 10; $payload['line_items'][0]['quantity'] = 10;
} }
if (str($type)->contains('dynamic')) {
$payload['line_items'][0]['adjustable_quantity'] = [
'enabled' => true,
'minimum' => 2,
];
$payload['line_items'][0]['quantity'] = 2;
}
if (!data_get($team, 'subscription.stripe_trial_already_ended')) { if (!data_get($team, 'subscription.stripe_trial_already_ended')) {
if (config('constants.limits.trial_period') > 0) { if (config('constants.limits.trial_period') > 0) {

View File

@ -7,7 +7,7 @@
// The release version of your application // The release version of your application
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
'release' => '4.0.0-beta.256', 'release' => '4.0.0-beta.257',
// When left empty or `null` the Laravel environment will be used // When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'), 'environment' => config('app.env'),

View File

@ -20,6 +20,9 @@
'stripe_price_id_ultimate_monthly_old' => env('STRIPE_PRICE_ID_ULTIMATE_MONTHLY_OLD', null), 'stripe_price_id_ultimate_monthly_old' => env('STRIPE_PRICE_ID_ULTIMATE_MONTHLY_OLD', null),
'stripe_price_id_ultimate_yearly_old' => env('STRIPE_PRICE_ID_ULTIMATE_YEARLY_OLD', null), 'stripe_price_id_ultimate_yearly_old' => env('STRIPE_PRICE_ID_ULTIMATE_YEARLY_OLD', null),
'stripe_price_id_dynamic_monthly' => env('STRIPE_PRICE_ID_DYNAMIC_MONTHLY', null),
'stripe_price_id_dynamic_yearly' => env('STRIPE_PRICE_ID_DYNAMIC_YEARLY', null),
// Paddle // Paddle
'paddle_vendor_id' => env('PADDLE_VENDOR_ID', null), 'paddle_vendor_id' => env('PADDLE_VENDOR_ID', null),
'paddle_vendor_auth_code' => env('PADDLE_VENDOR_AUTH_CODE', null), 'paddle_vendor_auth_code' => env('PADDLE_VENDOR_AUTH_CODE', null),

View File

@ -1,3 +1,3 @@
<?php <?php
return '4.0.0-beta.256'; return '4.0.0-beta.257';

View File

@ -58,6 +58,8 @@ services:
- STRIPE_PRICE_ID_PRO_YEARLY - STRIPE_PRICE_ID_PRO_YEARLY
- STRIPE_PRICE_ID_ULTIMATE_MONTHLY - STRIPE_PRICE_ID_ULTIMATE_MONTHLY
- STRIPE_PRICE_ID_ULTIMATE_YEARLY - STRIPE_PRICE_ID_ULTIMATE_YEARLY
- STRIPE_PRICE_ID_DYNAMIC_MONTHLY
- STRIPE_PRICE_ID_DYNAMIC_YEARLY
- STRIPE_PRICE_ID_BASIC_MONTHLY_OLD - STRIPE_PRICE_ID_BASIC_MONTHLY_OLD
- STRIPE_PRICE_ID_BASIC_YEARLY_OLD - STRIPE_PRICE_ID_BASIC_YEARLY_OLD
- STRIPE_PRICE_ID_PRO_MONTHLY_OLD - STRIPE_PRICE_ID_PRO_MONTHLY_OLD

View File

@ -0,0 +1,67 @@
<x-pricing-plans>
@if (config('subscription.provider') === 'stripe')
<x-slot:basic>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-basic" class="w-full h-10 buyme"
wire:click="subscribeStripe('basic-monthly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-basic" class="w-full h-10 buyme"
wire:click="subscribeStripe('basic-yearly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
</x-slot:basic>
<x-slot:pro>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme"
wire:click="subscribeStripe('pro-monthly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme"
wire:click="subscribeStripe('pro-yearly')"> {{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
</x-slot:pro>
<x-slot:ultimate>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-ultimate" class="w-full h-10 buyme"
wire:click="subscribeStripe('ultimate-monthly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-ultimate" class="w-full h-10 buyme"
wire:click="subscribeStripe('ultimate-yearly')"> {{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
</x-slot:ultimate>
@endif
@if (config('subscription.provider') === 'paddle')
<x-paddle />
@endif
@if (config('subscription.provider') === 'lemon')
<x-slot:basic>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-basic"
class="w-full h-10 buyme" wire:click="getSubscriptionLink('basic-monthly')"> Subscribe
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-basic"
class="w-full h-10 buyme" wire:click="getSubscriptionLink('basic-yearly')"> Subscribe
</x-forms.button>
</x-slot:basic>
<x-slot:pro>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-pro"
class="w-full h-10 buyme" wire:click="getSubscriptionLink('pro-monthly')"> Subscribe
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme"
wire:click="getSubscriptionLink('pro-yearly')"> Subscribe
</x-forms.button>
</x-slot:pro>
<x-slot:ultimate>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-ultimate"
class="w-full h-10 buyme" wire:click="getSubscriptionLink('ultimate-monthly')"> Subscribe
</x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-ultimate"
class="w-full h-10 buyme" wire:click="getSubscriptionLink('ultimate-yearly')"> Subscribe
</x-forms.button>
</x-slot:ultimate>
@endif
</x-pricing-plans>

View File

@ -1,67 +1,120 @@
<x-pricing-plans> <div x-data="{ selected: 'monthly' }" class="w-full pb-20">
@if (config('subscription.provider') === 'stripe') <div class="max-w-2xl px-6 mx-auto lg:px-8">
<x-slot:basic> <div class="flex justify-center">
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-basic" class="w-full h-10 buyme" <fieldset
wire:click="subscribeStripe('basic-monthly')"> class="grid grid-cols-2 p-1 text-xs font-semibold leading-5 text-center rounded dark:text-white gap-x-1 bg-white/5">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }} <legend class="sr-only">Payment frequency</legend>
</x-forms.button> <label class="cursor-pointer rounded px-2.5 py-1"
:class="selected === 'monthly' ? 'bg-coollabs-100 text-white' : ''">
<input type="radio" x-on:click="selected = 'monthly'" name="frequency" value="monthly"
class="sr-only">
<span>Monthly</span>
</label>
<label class="cursor-pointer rounded px-2.5 py-1"
:class="selected === 'yearly' ? 'bg-coollabs-100 text-white' : ''">
<input type="radio" x-on:click="selected = 'yearly'" name="frequency" value="annually"
class="sr-only">
<span>Annually</span>
</label>
</fieldset>
</div>
<div x-show="selected === 'monthly'" class="flex justify-center h-10 mt-3 text-sm leading-6 ">
<div>Save <span class="font-bold text-black dark:text-warning">10%</span> annually with the yearly plans.
</div>
</div>
<div x-show="selected === 'yearly'" class="flex justify-center h-10 mt-3 text-sm leading-6 ">
<div>
</div>
</div>
<div class="flow-root mt-12">
<div class="pb-10 text-xl text-center">For the detailed list of features, please visit our landing page: <a
class="font-bold underline dark:text-white" href="https://coolify.io">coolify.io</a></div>
<div
class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-neutral-200 dark:divide-coolgray-500 isolate gap-y-16 sm:mx-auto lg:-mx-8 lg:mt-0 lg:max-w-none lg:grid-cols-1 lg:divide-x lg:divide-y-0 xl:-mx-4">
<div class="pt-16 lg:px-8 lg:pt-0 xl:px-14">
<h3 id="tier-dynamic" class="text-4xl font-semibold leading-7 dark:text-white">Dynamic</h3>
<p class="flex items-baseline mt-6 gap-x-1">
<span x-show="selected === 'monthly'" x-cloak>
<span class="text-4xl font-bold tracking-tight dark:text-white">$5</span>
<span class="text-sm font-semibold leading-6 "> for the first 2 servers</span>
</span>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-basic" class="w-full h-10 buyme" <span x-show="selected === 'yearly'" x-cloak>
wire:click="subscribeStripe('basic-yearly')"> <span class="text-4xl font-bold tracking-tight dark:text-white">$4</span>
{{ $isTrial ? 'Start Trial' : 'Subscribe' }} <span class="text-sm font-semibold leading-6 ">/month + VAT</span>
</x-forms.button> </span>
</x-slot:basic> </p>
<x-slot:pro> <p class="flex items-baseline gap-x-1">
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme" <span x-show="selected === 'monthly'" x-cloak>
wire:click="subscribeStripe('pro-monthly')"> <span class="text-2xl font-bold tracking-tight dark:text-white">$3</span>
{{ $isTrial ? 'Start Trial' : 'Subscribe' }} <span class="text-sm font-semibold leading-6 "> for any additional</span>
</x-forms.button> </span>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme" <span x-show="selected === 'yearly'" x-cloak>
wire:click="subscribeStripe('pro-yearly')"> {{ $isTrial ? 'Start Trial' : 'Subscribe' }} <span class="text-4xl font-bold tracking-tight dark:text-white">$4</span>
</x-forms.button> <span class="text-sm font-semibold leading-6 ">/month + VAT</span>
</x-slot:pro> </span>
<x-slot:ultimate> </p>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-ultimate" class="w-full h-10 buyme" <span x-show="selected === 'monthly'" x-cloak>
wire:click="subscribeStripe('ultimate-monthly')"> <span>billed monthly (+VAT)</span>
{{ $isTrial ? 'Start Trial' : 'Subscribe' }} </span>
</x-forms.button> <span x-show="selected === 'yearly'" x-cloak>
<span>billed annually</span>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-ultimate" class="w-full h-10 buyme" </span>
wire:click="subscribeStripe('ultimate-yearly')"> {{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button>
</x-slot:ultimate>
@endif
@if (config('subscription.provider') === 'paddle')
<x-paddle />
@endif
@if (config('subscription.provider') === 'lemon')
<x-slot:basic>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-basic" <x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-basic"
class="w-full h-10 buyme" wire:click="getSubscriptionLink('basic-monthly')"> Subscribe class="w-full h-10 buyme" wire:click="subscribeStripe('dynamic-monthly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button> </x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-basic" <x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-basic"
class="w-full h-10 buyme" wire:click="getSubscriptionLink('basic-yearly')"> Subscribe class="w-full h-10 buyme" wire:click="subscribeStripe('dynamic-yearly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button> </x-forms.button>
</x-slot:basic> <p class="mt-10 text-sm leading-6 dark:text-white h-[6.5rem]">Begin hosting your own services in the
<x-slot:pro> cloud.
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-pro" </p>
class="w-full h-10 buyme" wire:click="getSubscriptionLink('pro-monthly')"> Subscribe <ul role="list" class="space-y-3 text-sm leading-6 ">
</x-forms.button> <li class="flex">
<svg class="flex-none w-5 h-6 mr-3 dark:text-warning" viewBox="0 0 20 20"
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme" fill="currentColor" aria-hidden="true">
wire:click="getSubscriptionLink('pro-yearly')"> Subscribe <path fill-rule="evenodd"
</x-forms.button> d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.775 0 001.137-.089l4-5.5z"
</x-slot:pro> clip-rule="evenodd" />
<x-slot:ultimate> </svg>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-ultimate" Connect <span class="px-1 font-bold dark:text-white">2</span> servers
class="w-full h-10 buyme" wire:click="getSubscriptionLink('ultimate-monthly')"> Subscribe </li>
</x-forms.button> <li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 dark:text-warning" viewBox="0 0 20 20" fill="currentColor"
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-ultimate" aria-hidden="true">
class="w-full h-10 buyme" wire:click="getSubscriptionLink('ultimate-yearly')"> Subscribe <path fill-rule="evenodd"
</x-forms.button> d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
</x-slot:ultimate> clip-rule="evenodd" />
@endif </svg>
</x-pricing-plans> Included Email System
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 dark:text-warning" viewBox="0 0 20 20" fill="currentColor"
aria-hidden="true">
<path fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
clip-rule="evenodd" />
</svg>
Email Support
</li>
<li class="flex font-bold dark:text-white gap-x-3">
<svg width="512" height="512" class="flex-none w-5 h-6 text-green-600"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2">
<path
d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3-5a9 9 0 0 0 6-8a3 3 0 0 0-3-3a9 9 0 0 0-8 6a6 6 0 0 0-5 3" />
<path d="M7 14a6 6 0 0 0-3 6a6 6 0 0 0 6-3m4-8a1 1 0 1 0 2 0a1 1 0 1 0-2 0" />
</g>
</svg>
+ All upcoming features
</li>
</ul>
</div>
</div>
</div>
</div>
</div>

View File

@ -1,7 +1,7 @@
{ {
"coolify": { "coolify": {
"v4": { "v4": {
"version": "4.0.0-beta.256" "version": "4.0.0-beta.257"
} }
} }
} }