fix: checkout UX — no auto-select payment method, stable price table during loading, add spacing before submit button

This commit is contained in:
Usman Baig
2026-03-27 22:04:09 +01:00
parent a9cf1484fd
commit 6aea24f018
2 changed files with 13 additions and 13 deletions

View File

@@ -57,7 +57,7 @@ const mollieFieldBase =
export default function PaymentForm({ plan, interval, limit, country, vatId }: PaymentFormProps) {
const router = useRouter()
const [selectedMethod, setSelectedMethod] = useState('card')
const [selectedMethod, setSelectedMethod] = useState('')
const [mollieReady, setMollieReady] = useState(false)
const [mollieError, setMollieError] = useState(false)
const [formError, setFormError] = useState<string | null>(null)
@@ -141,6 +141,11 @@ export default function PaymentForm({ plan, interval, limit, country, vatId }: P
setSubmitted(true)
setFormError(null)
if (!selectedMethod) {
setFormError('Please select a payment method')
return
}
if (!country) {
setFormError('Please select your country')
return
@@ -319,8 +324,8 @@ export default function PaymentForm({ plan, interval, limit, country, vatId }: P
{/* Submit */}
<button
type="submit"
disabled={submitting || (isCard && !mollieReady && !mollieError)}
className="w-full rounded-lg bg-brand-orange px-4 py-3 text-sm font-semibold text-white transition-colors hover:bg-brand-orange/90 disabled:opacity-50 disabled:cursor-not-allowed"
disabled={submitting || !selectedMethod || (isCard && !mollieReady && !mollieError)}
className="mt-4 w-full rounded-lg bg-brand-orange px-4 py-3 text-sm font-semibold text-white transition-colors hover:bg-brand-orange/90 disabled:opacity-50 disabled:cursor-not-allowed"
>
{submitting ? 'Processing...' : 'Start free trial'}
</button>

View File

@@ -185,13 +185,8 @@ export default function PlanSummary({ plan, interval, limit, country, vatId, onC
</div>
{/* Price breakdown */}
<div className="pt-2 border-t border-neutral-800">
{vatLoading && !vatResult ? (
<div className="flex items-center gap-2 text-sm text-neutral-400">
<div className="h-4 w-4 animate-spin rounded-full border-2 border-neutral-600 border-t-white" />
Calculating VAT...
</div>
) : vatResult ? (
<div className={`pt-2 border-t border-neutral-800 transition-opacity duration-200 ${vatLoading ? 'opacity-50' : 'opacity-100'}`}>
{vatResult ? (
<div className="space-y-1.5 text-sm">
<div className="flex justify-between text-neutral-400">
<span>Subtotal ({tierLabel} pageviews)</span>
@@ -220,15 +215,15 @@ export default function PlanSummary({ plan, interval, limit, country, vatId, onC
<div className="space-y-1.5 text-sm">
<div className="flex justify-between text-neutral-400">
<span>Subtotal ({tierLabel} pageviews)</span>
<span>&euro;{isYearly ? baseDisplay.toFixed(2) : baseDisplay.toFixed(2)}</span>
<span>&euro;{baseDisplay.toFixed(2)}</span>
</div>
<div className="flex justify-between text-neutral-500 text-xs">
<span>VAT</span>
<span>Select country</span>
<span>{vatLoading ? 'Calculating...' : 'Select country'}</span>
</div>
<div className="flex justify-between font-semibold text-white pt-1 border-t border-neutral-800">
<span>Total {isYearly ? '/year' : '/mo'} <span className="font-normal text-neutral-500 text-xs">excl. VAT</span></span>
<span>&euro;{isYearly ? baseDisplay.toFixed(2) : baseDisplay.toFixed(2)}</span>
<span>&euro;{baseDisplay.toFixed(2)}</span>
</div>
{isYearly && (
<p className="text-xs text-neutral-500">&euro;{(baseDisplay / 12).toFixed(2)}/mo &middot; Save 1 month</p>