feat: pricing plans ans subs

This commit is contained in:
Andras Bacsai 2023-07-27 16:22:13 +02:00
parent 97e2a5d30b
commit c7fc00095c
8 changed files with 308 additions and 34 deletions

View File

@ -2,13 +2,16 @@
use Illuminate\Support\Carbon;
function getSubscriptionLink()
function getSubscriptionLink($id)
{
$checkout_id = config("coolify.lemon_squeezy_checkout_id_$id");
if (!$checkout_id) {
return null;
}
$user_id = auth()->user()->id;
$team_id = auth()->user()->currentTeam()->id ?? null;
$email = auth()->user()->email ?? null;
$name = auth()->user()->name ?? null;
$checkout_id = config('coolify.lemon_squeezy_checkout_id');
$url = "https://store.coollabs.io/checkout/buy/$checkout_id?";
if ($user_id) {
$url .= "&checkout[custom][user_id]={$user_id}";

View File

@ -4,7 +4,9 @@
'self_hosted' => env('SELF_HOSTED', true),
'license_url' => 'https://license.coolify.io',
'lemon_squeezy_webhook_secret' => env('LEMON_SQUEEZY_WEBHOOK_SECRET'),
'lemon_squeezy_checkout_id' => env('LEMON_SQUEEZY_CHECKOUT_ID'),
'lemon_squeezy_checkout_id_1' => env('LEMON_SQUEEZY_CHECKOUT_ID_1'),
'lemon_squeezy_checkout_id_2' => env('LEMON_SQUEEZY_CHECKOUT_ID_2'),
'lemon_squeezy_checkout_id_3' => env('LEMON_SQUEEZY_CHECKOUT_ID_3'),
'mux_enabled' => env('MUX_ENABLED', true),
'dev_webhook' => env('SERVEO_URL'),
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),

View File

@ -32,7 +32,9 @@ services:
- PHP_PM_MAX_SPARE_SERVERS=10
- SELF_HOSTED
- LEMON_SQUEEZY_WEBHOOK_SECRET
- LEMON_SQUEEZY_CHECKOUT_ID
- LEMON_SQUEEZY_CHECKOUT_ID_1
- LEMON_SQUEEZY_CHECKOUT_ID_2
- LEMON_SQUEEZY_CHECKOUT_ID_3
ports:
- "${APP_PORT:-8000}:80"
expose:

View File

@ -15,7 +15,7 @@ .scrollbar {
@apply scrollbar-thumb-coollabs-100 scrollbar-track-coolgray-200 scrollbar-w-2;
}
.main {
@apply max-w-screen-xl pt-4 pl-24 pr-10 mx-auto;
@apply pt-4 pl-24 pr-10 mx-auto;
}
.label-text,
label {
@ -109,3 +109,7 @@ tr td {
tr td:first-child {
@apply pl-4 pr-3 font-bold sm:pl-6;
}
.buyme {
@apply block px-3 py-2 mt-10 text-sm font-semibold leading-6 text-center text-white rounded-md shadow-sm bg-coolgray-200 hover:bg-coolgray-300 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-coolgray-200;
}

View File

@ -32,7 +32,7 @@
<div class="fixed top-3 left-4" id="vue">
<magic-bar></magic-bar>
</div>
<main class="main">
<main class="main max-w-screen-2xl">
{{ $slot }}
</main>
<x-version class="fixed left-2 bottom-1" />

View File

@ -12,7 +12,7 @@
<path d="M3 21h18" />
<path d="M5 21v-16a2 2 0 0 1 2 -2h7.5m2.5 10.5v7.5" />
<path d="M14 7h7m-3 -3l3 3l-3 3" />
</svg> Logout</button>
</svg></button>
</form>
</li>
</ul>

View File

@ -0,0 +1,254 @@
<div x-data="{ selected: 'monthly' }" class="w-full">
<div class="px-6 mx-auto lg:px-8">
<div class="flex justify-center mt-5">
<fieldset
class="grid grid-cols-2 p-1 text-xs font-semibold leading-5 text-center rounded-full gap-x-1 ring-1 ring-inset ring-coolgray-500">
<legend class="sr-only">Payment frequency</legend>
<label class="cursor-pointer rounded-full 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-full 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="text-2xl font-bold text-warning">20%</span> with the
yearly plan
</div>
</div>
<div x-show="selected === 'yearly'" class="flex justify-center h-10 mt-3 text-sm leading-6 ">
<div>Congratulations! 🎉 You are saving money with this choice!
</div>
</div>
<div class="flow-root mt-12">
<div
class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap-y-16 sm:mx-auto lg:-mx-8 lg:mt-0 lg:max-w-none lg:grid-cols-4 lg:divide-x lg:divide-y-0 xl:-mx-4">
<div class="px-8 pt-16 lg:pt-0">
<h3 id="tier-basic" class="text-base font-semibold leading-7 text-white">Unlimited Trial</h3>
<p class="flex items-baseline mt-6 gap-x-1">
<span x-show="selected === 'monthly'" x-cloak>
<span class="text-5xl font-bold tracking-tight text-white">Free</span>
</span>
<span x-show="selected === 'yearly'" x-cloak>
<span class="text-5xl font-bold tracking-tight text-white">Still Free </span>
</span>
</p>
<a href="https://github.com/coollabsio/coolify" aria-describedby="tier-basic" class="buyme">Get
Started</a>
<p class="pb-6 mt-10 text-sm leading-6 text-white">Start self-hosting without limits with our OSS
version.</p>
<ul role="list" class="space-y-3 text-sm leading-6 ">
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
Same features as the paid version
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
You need to take care of everything
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
If you brave enough, you can do it!
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
Community Support
</li>
</ul>
</div>
<div class="pt-16 lg:px-8 lg:pt-0 xl:px-14">
<h3 id="tier-basic" class="text-base font-semibold leading-7 text-white">Basic</h3>
<p class="flex items-baseline mt-6 gap-x-1">
<span x-show="selected === 'monthly'" x-cloak>
<span class="text-5xl font-bold tracking-tight text-white">$15</span>
<span class="text-sm font-semibold leading-6 ">/monthly</span>
</span>
<span x-show="selected === 'yearly'" x-cloak>
<span class="text-5xl font-bold tracking-tight text-white">$144</span>
<span class="text-sm font-semibold leading-6 ">/yearly</span>
</span>
</p>
<a href="{{ getSubscriptionLink(1) }}" aria-describedby="tier-basic" class="buyme">Subscribe</a>
<p class="pb-6 mt-10 text-sm leading-6 text-white">Start self-hosting in the cloud with a single
server.
</p>
<ul role="list" class="space-y-3 text-sm leading-6 ">
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
1 server
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
Unlimited Deployments
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
30 days of backups
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
Basic Support
</li>
</ul>
</div>
<div class="pt-16 lg:px-8 lg:pt-0 xl:px-14">
<h3 id="tier-essential" class="text-base font-semibold leading-7 text-white">Essential</h3>
<p class="flex items-baseline mt-6 gap-x-1">
<span x-show="selected === 'monthly'" x-cloak>
<span class="text-5xl font-bold tracking-tight text-white">$30</span>
<span class="text-sm font-semibold leading-6 ">/monthly</span>
</span>
<span x-show="selected === 'yearly'" x-cloak>
<span class="text-5xl font-bold tracking-tight text-white">$288</span>
<span class="text-sm font-semibold leading-6 ">/yearly</span>
</span>
</p>
<a href="{{ getSubscriptionLink(2) }}" aria-describedby="tier-essential"
class="buyme">Subscribe</a>
<p class="mt-10 text-sm leading-6 text-white">Scale your business or self-hosting environment.</p>
<ul role="list" class="mt-6 space-y-3 text-sm leading-6 ">
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
5 servers
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
Unlimited Deployments
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
30 days of backups
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
Basic Support
</li>
</ul>
</div>
<div class="pt-16 lg:px-8 lg:pt-0 xl:px-14">
<h3 id="tier-growth" class="text-base font-semibold leading-7 text-white">Growth</h3>
<p class="flex items-baseline mt-6 gap-x-1">
<span x-show="selected === 'monthly'" x-cloak>
<span class="text-5xl font-bold tracking-tight text-white">$60</span>
<span class="text-sm font-semibold leading-6 ">/monthly</span>
</span>
<span x-show="selected === 'yearly'" x-cloak>
<span class="text-5xl font-bold tracking-tight text-white">$576</span>
<span class="text-sm font-semibold leading-6 ">/yearly</span>
</span>
</p>
<a href="{{ getSubscriptionLink(3) }}" aria-describedby="tier-growth"
class="buyme">Subscribe</a>
<p class="mt-10 text-sm leading-6 text-white">Deploy complex infrastuctures and
manage them easily in one place.</p>
<ul role="list" class="mt-6 space-y-3 text-sm leading-6 ">
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
Unlimited servers
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
Unlimited deployments
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 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>
30 days of backups
</li>
<li class="flex font-bold text-white gap-x-3">
<svg class="flex-none w-5 h-6 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>
Priority Support
</li>
</ul>
</div>
</div>
</div>
</div>
</div>

View File

@ -1,33 +1,42 @@
<x-layout-subscription>
@if ($settings->is_resale_license_active)
<div class="flex gap-2">
<h3>Subscription</h3>
<livewire:switch-team />
<div class="flex justify-center mx-10">
<div>
<div class="flex gap-2">
<h3>Subscription</h3>
<livewire:switch-team />
</div>
<div class="flex items-center pb-8">
<span>Currently active team: <span
class="text-warning">{{ session('currentTeam.name') }}</span></span>
</div>
<x-pricing-plans />
{{-- @if (data_get(
auth()->user()->currentTeam(),
'subscription',
))
<div>Status: {{ auth()->user()->currentTeam()->subscription->lemon_status }}</div>
<div>Type: {{ auth()->user()->currentTeam()->subscription->lemon_variant_name }}</div>
@if (auth()->user()->currentTeam()->subscription->lemon_status === 'cancelled')
<div class="pb-4">Subscriptions ends at: {{ getEndDate() }}</div>
<x-forms.button><a class="text-white" href="{{ getSubscriptionLink() }}">Subscribe
Again</a>
</x-forms.button>
@else
<div class="pb-4">Renews at: {{ getRenewDate() }}</div>
@endif
<x-forms.button><a class="text-white" href="{{ getPaymentLink() }}">Update Payment Details</a>
</x-forms.button>
@else
<x-forms.button class="mt-4"><a class="text-white" href="{{ getSubscriptionLink() }}">Subscribe
Now</a>
</x-forms.button>
@endif
<x-forms.button><a class="text-white" href="https://app.lemonsqueezy.com/my-orders">Manage My
Subscription</a>
</x-forms.button> --}}
</div>
</div>
<div class="flex items-center pb-8">
<span>Currently active team: {{ session('currentTeam.name') }}</span>
</div>
@if (data_get(auth()->user()->currentTeam(),
'subscription'))
<div>Status: {{ auth()->user()->currentTeam()->subscription->lemon_status }}</div>
<div>Type: {{ auth()->user()->currentTeam()->subscription->lemon_variant_name }}</div>
@if (auth()->user()->currentTeam()->subscription->lemon_status === 'cancelled')
<div class="pb-4">Subscriptions ends at: {{ getEndDate() }}</div>
<x-forms.button><a class="text-white" href="{{ getSubscriptionLink() }}">Subscribe
Again</a>
</x-forms.button>
@else
<div class="pb-4">Renews at: {{ getRenewDate() }}</div>
@endif
<x-forms.button><a class="text-white" href="{{ getPaymentLink() }}">Update Payment Details</a>
</x-forms.button>
@else
<x-forms.button class="mt-4"><a class="text-white" href="{{ getSubscriptionLink() }}">Subscribe Now</a>
</x-forms.button>
@endif
<x-forms.button><a class="text-white" href="https://app.lemonsqueezy.com/my-orders">Manage My
Subscription</a>
</x-forms.button>
@else
<div class="px-10">Resale license is not active. Please contact your instance admin.</div>
@endif