test: improve checkout select

This commit is contained in:
nate 2026-03-25 23:43:58 +04:00
parent 56bd48b0cc
commit 98965ca2f3
1 changed files with 87 additions and 82 deletions

View File

@ -30,101 +30,106 @@
</div>
<% if (!invoice) { %>
<% if (plan !== 'free') { %>
<div class="mb-6 rounded-lg border border-border-subtle bg-surface px-4 py-3 text-xs text-gray-400">
Buying a higher tier? Your current plan pauses and picks back up once the new one expires. If you'd rather combine them, reach out to support.
</div>
<% } %>
<!-- ─── Step 1: Plan & coin selection (form, works without JS) ─── -->
<form action="/dashboard/checkout" method="POST" class="space-y-6">
<!-- ─── Plan & coin selection ─── -->
<form action="/dashboard/checkout" method="POST">
<!-- Single hidden field submitted to server -->
<input type="hidden" name="plan" id="plan-value" value="pro">
<!-- Plan type selector (not submitted, drives UI) -->
<input type="radio" name="_planType" value="pro" id="plan-pro" class="hidden" checked>
<input type="radio" name="_planType" value="lifetime" id="plan-lifetime" class="hidden">
<div class="plan-labels grid grid-cols-2 gap-4">
<label for="plan-pro"
class="cursor-pointer text-left bg-surface border-2 border-border-subtle hover:border-blue-500/40 rounded-xl p-5 transition-colors">
<div class="text-xs text-gray-500 uppercase tracking-wider font-mono mb-1">Pro</div>
<div class="text-2xl font-bold text-gray-100">From $12<span class="text-sm font-normal text-gray-500">/mo</span></div>
<div class="text-xs text-gray-500 mt-2">200800 monitors, 5s intervals</div>
</label>
<% if (hasLifetime) { %>
<div class="text-left bg-surface border-2 border-border-subtle rounded-xl p-5 opacity-50 cursor-not-allowed relative">
<span class="absolute top-3 right-3 text-[10px] font-semibold px-2 py-0.5 rounded-full bg-gray-500/15 text-gray-500 border border-gray-500/20">Owned</span>
<div class="text-xs text-gray-500 uppercase tracking-wider font-mono mb-1">Lifetime</div>
<div class="text-2xl font-bold text-gray-400">$<%= lifetimeBase %></div>
<div class="text-xs text-gray-600 mt-2">You already have Lifetime</div>
</div>
<% } else { %>
<label for="plan-lifetime"
class="cursor-pointer text-left bg-surface border-2 border-border-subtle hover:border-yellow-500/40 rounded-xl p-5 transition-colors relative">
<span class="absolute top-3 right-3 text-[10px] font-semibold px-2 py-0.5 rounded-full bg-yellow-500/15 text-yellow-500 border border-yellow-500/20">Launch Deal</span>
<div class="text-xs text-yellow-500/70 uppercase tracking-wider font-mono mb-1">Lifetime</div>
<% if (lifetimeDiscount > 0) { %>
<div class="text-2xl font-bold text-gray-100">$<%= lifetimePrice.toFixed(0) %> <span class="text-sm font-normal text-gray-600 line-through">$<%= lifetimeBase %></span></div>
<div class="text-xs text-green-400/70 mt-1">You've paid us $<%= totalSpent.toFixed(0) %>, so we've credited $<%= lifetimeDiscount.toFixed(0) %> toward lifetime</div>
<% } else { %>
<div class="text-2xl font-bold text-gray-100">$<%= lifetimeBase %></div>
<% } %>
<div class="text-xs text-gray-500 mt-2">One-time, 200 monitors forever</div>
</label>
<% } %>
</div>
<div class="card-static overflow-hidden">
<!-- Pro tier + months (visible only when pro selected, via CSS) -->
<div id="pro-options" class="hidden space-y-4">
<div>
<label class="block text-sm text-gray-400 mb-2">Tier</label>
<div id="tier-selector" class="grid grid-cols-3 gap-2">
<button type="button" class="tier-btn text-center bg-surface border-2 border-blue-500/50 rounded-lg py-2.5 transition-colors" data-plan="pro">
<div class="text-sm font-semibold text-gray-200">1x</div>
<div class="text-xs text-gray-500">200 monitors · $12/mo</div>
</button>
<button type="button" class="tier-btn text-center bg-surface border-2 border-border-subtle hover:border-blue-500/40 rounded-lg py-2.5 transition-colors" data-plan="pro2x">
<div class="text-sm font-semibold text-gray-200">2x</div>
<div class="text-xs text-gray-500">400 monitors · $24/mo</div>
</button>
<button type="button" class="tier-btn text-center bg-surface border-2 border-border-subtle hover:border-blue-500/40 rounded-lg py-2.5 transition-colors" data-plan="pro4x">
<div class="text-sm font-semibold text-gray-200">4x</div>
<div class="text-xs text-gray-500">800 monitors · $48/mo</div>
</button>
<!-- Section: Choose plan -->
<div class="px-6 py-4 border-b divider">
<h2 class="text-sm font-medium text-gray-300">Choose a plan</h2>
</div>
<div class="px-6 py-5">
<div class="plan-labels grid grid-cols-2 gap-3">
<label for="plan-pro"
class="cursor-pointer text-left border-2 border-border-subtle hover:border-blue-500/40 rounded-xl p-4 transition-colors">
<div class="text-sm text-gray-400 mb-1">Pro</div>
<div class="text-xl font-bold text-gray-100">From $12<span class="text-sm font-normal text-gray-500">/mo</span></div>
<div class="text-sm text-gray-500 mt-1.5">200 to 800 monitors, 5s intervals</div>
</label>
<% if (hasLifetime) { %>
<div class="text-left border-2 border-border-subtle rounded-xl p-4 opacity-40 cursor-not-allowed relative">
<span class="absolute top-3 right-3 text-[10px] font-semibold px-2 py-0.5 rounded-full bg-gray-500/15 text-gray-500 border border-gray-500/20">Owned</span>
<div class="text-sm text-gray-500 mb-1">Lifetime</div>
<div class="text-xl font-bold text-gray-500">$<%= lifetimeBase %></div>
<div class="text-sm text-gray-600 mt-1.5">Already included in your plan</div>
</div>
<% } else { %>
<label for="plan-lifetime"
class="cursor-pointer text-left border-2 border-border-subtle hover:border-yellow-500/40 rounded-xl p-4 transition-colors relative">
<span class="absolute top-3 right-3 text-[10px] font-semibold px-2 py-0.5 rounded-full bg-yellow-500/15 text-yellow-500 border border-yellow-500/20">Launch Deal</span>
<div class="text-sm text-yellow-500/70 mb-1">Lifetime</div>
<% if (lifetimeDiscount > 0) { %>
<div class="text-xl font-bold text-gray-100">$<%= lifetimePrice.toFixed(0) %> <span class="text-sm font-normal text-gray-600 line-through">$<%= lifetimeBase %></span></div>
<div class="text-sm text-green-400/70 mt-1.5">$<%= lifetimeDiscount.toFixed(0) %> credited from previous payments</div>
<% } else { %>
<div class="text-xl font-bold text-gray-100">$<%= lifetimeBase %></div>
<div class="text-sm text-gray-500 mt-1.5">Pay once, use forever</div>
<% } %>
</label>
<% } %>
</div>
<!-- Pro tier + months (visible only when pro selected, via CSS) -->
<div id="pro-options" class="hidden mt-5 space-y-4">
<div>
<div class="text-sm text-gray-400 mb-2">Tier</div>
<div id="tier-selector" class="grid grid-cols-3 gap-2">
<button type="button" class="tier-btn text-center border-2 border-blue-500/50 rounded-lg py-3 transition-colors" data-plan="pro">
<div class="text-sm font-semibold text-gray-200">1x</div>
<div class="text-sm text-gray-500">200 mon · $12/mo</div>
</button>
<button type="button" class="tier-btn text-center border-2 border-border-subtle hover:border-blue-500/40 rounded-lg py-3 transition-colors" data-plan="pro2x">
<div class="text-sm font-semibold text-gray-200">2x</div>
<div class="text-sm text-gray-500">400 mon · $24/mo</div>
</button>
<button type="button" class="tier-btn text-center border-2 border-border-subtle hover:border-blue-500/40 rounded-lg py-3 transition-colors" data-plan="pro4x">
<div class="text-sm font-semibold text-gray-200">4x</div>
<div class="text-sm text-gray-500">800 mon · $48/mo</div>
</button>
</div>
</div>
<div>
<div class="text-sm text-gray-400 mb-2">Duration</div>
<select id="months-select" name="months" class="w-full input-base px-4 py-2.5 text-sm text-gray-100">
<% for (let i = 1; i <= 12; i++) { %>
<option value="<%= i %>" data-base="<%= i * 12 %>"><%= i %> month<%= i > 1 ? 's' : '' %> — $<%= i * 12 %></option>
<% } %>
</select>
</div>
</div>
</div>
<div>
<label class="block text-sm text-gray-400 mb-2">How many months?</label>
<select id="months-select" name="months" class="input-base px-4 py-2.5 text-gray-100">
<% for (let i = 1; i <= 12; i++) { %>
<option value="<%= i %>" data-base="<%= i * 12 %>"><%= i %> month<%= i > 1 ? 's' : '' %> — $<%= i * 12 %></option>
<% } %>
</select>
<!-- Section: Pay with -->
<div class="px-6 py-4 border-t divider">
<div class="text-sm text-gray-400 mb-3">Pay with</div>
<div class="grid grid-cols-3 gap-2">
<% coins.forEach(function(c, i) { %>
<input type="radio" name="coin" value="<%= c.id %>" id="coin-<%= c.id %>" class="hidden coin-radio" <%= i === 0 ? 'checked' : '' %>>
<label for="coin-<%= c.id %>"
class="cursor-pointer flex items-center justify-center gap-2 border-2 border-border-subtle hover:border-border-strong rounded-lg px-3 py-2.5 transition-colors">
<span class="text-sm font-medium text-gray-300"><%= c.ticker %></span>
<span class="text-sm text-gray-600"><%= c.label %></span>
</label>
<% }) %>
</div>
</div>
</div>
<!-- Coin selection -->
<div>
<label class="block text-sm text-gray-400 mb-2">Pay with</label>
<div class="grid grid-cols-3 gap-2">
<% coins.forEach(function(c, i) { %>
<input type="radio" name="coin" value="<%= c.id %>" id="coin-<%= c.id %>" class="hidden coin-radio" <%= i === 0 ? 'checked' : '' %>>
<label for="coin-<%= c.id %>"
class="cursor-pointer flex items-center gap-2 bg-surface border-2 border-border-subtle hover:border-border-strong rounded-lg px-3 py-2.5 transition-colors text-left">
<span class="text-sm font-medium text-gray-300"><%= c.ticker %></span>
<span class="text-xs text-gray-600"><%= c.label %></span>
</label>
<% }) %>
<!-- Submit -->
<div class="px-6 py-4 border-t divider">
<button type="submit" class="w-full btn-primary py-3 text-sm">Continue to Payment</button>
<% if (plan !== 'free') { %>
<p class="text-sm text-gray-600 text-center mt-3">Buying a higher tier? Your current plan pauses and picks back up once the new one expires. If you'd rather combine them, reach out to support.</p>
<% } %>
</div>
</div>
<button type="submit"
class="w-full btn-primary py-3">
Continue to Payment
</button>
</form>
<% } else { %>