Deploy Ladill Mini / deploy (push) Successful in 1m10s
Paystack blocks iframes, so checkout uses a popup beside the sheet/modal chrome. Opening about:blank on the user tap keeps that window from being blocked after the async initiate response.
125 lines
5.8 KiB
PHP
125 lines
5.8 KiB
PHP
@props([
|
|
'id',
|
|
'title' => 'Add credits',
|
|
'description' => '',
|
|
'topupAction',
|
|
'minTopup' => 5,
|
|
'suggestedAmount' => 10,
|
|
'ladillWalletBalance' => 0,
|
|
'serviceBalance' => null,
|
|
'serviceBalanceLabel' => 'Current balance',
|
|
'openOnLoad' => false,
|
|
'returnUrl' => null,
|
|
])
|
|
|
|
@php
|
|
// Single-wallet (siloing step 2): there is one Ladill wallet, so "pay from
|
|
// wallet into service credits" is a meaningless round-trip — top up the one
|
|
// wallet directly (Paystack). Transfer option removed.
|
|
$canPayFromWallet = false;
|
|
@endphp
|
|
|
|
<x-modal :name="$id" :show="$openOnLoad" maxWidth="md">
|
|
<div class="flex min-h-full flex-col sm:min-h-0">
|
|
<div class="border-b border-slate-100 px-5 py-4 pr-12 sm:px-6 sm:pr-14">
|
|
<h2 class="text-lg font-semibold text-slate-900">{{ $title }}</h2>
|
|
@if($description)
|
|
<p class="mt-1 text-sm text-slate-500">{{ $description }}</p>
|
|
@endif
|
|
</div>
|
|
|
|
<form action="{{ $topupAction }}" method="POST" class="flex flex-1 flex-col p-5 sm:p-6"
|
|
x-data="{
|
|
method: 'paystack',
|
|
showSheet: false,
|
|
checkoutUrl: '',
|
|
loading: false,
|
|
errorMsg: '',
|
|
async submitTopup(event) {
|
|
if (this.method !== 'paystack') return;
|
|
|
|
event.preventDefault();
|
|
this.loading = true; window.LadillPayCheckout?.prepare?.();
|
|
this.errorMsg = '';
|
|
|
|
try {
|
|
const res = await fetch(event.target.action, {
|
|
method: 'POST',
|
|
headers: { 'Accept': 'application/json' },
|
|
body: new FormData(event.target),
|
|
});
|
|
const data = await res.json();
|
|
if (!res.ok || data.error || !data.checkout_url) {
|
|
this.errorMsg = data.error || 'Unable to start payment. Please try again.';
|
|
this.loading = false;
|
|
return;
|
|
}
|
|
|
|
this.checkoutUrl = data.checkout_url;
|
|
this.showSheet = true;
|
|
this.loading = false;
|
|
} catch (error) {
|
|
window.LadillPayCheckout?.cancel?.(); this.errorMsg = 'Network error. Please try again.';
|
|
this.loading = false;
|
|
}
|
|
},
|
|
}"
|
|
@submit="submitTopup($event)">
|
|
@csrf
|
|
@if($returnUrl)
|
|
<input type="hidden" name="return_url" value="{{ $returnUrl }}">
|
|
@endif
|
|
|
|
@if($serviceBalance !== null)
|
|
<div class="mb-4 rounded-xl border border-slate-200 bg-slate-50 px-4 py-3 text-center">
|
|
<p class="text-xl font-bold text-slate-900">GHS {{ number_format((float) $serviceBalance, 2) }}</p>
|
|
<p class="text-xs text-slate-500">{{ $serviceBalanceLabel }}</p>
|
|
</div>
|
|
@endif
|
|
|
|
<div x-show="errorMsg" x-cloak class="mb-4 rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-700" x-text="errorMsg"></div>
|
|
|
|
<div>
|
|
<label class="text-sm font-medium text-slate-700">Amount (GHS)</label>
|
|
<input type="number" name="amount" min="{{ $minTopup }}" max="5000" step="0.01"
|
|
value="{{ $suggestedAmount }}"
|
|
class="mt-1.5 block w-full rounded-xl border border-slate-200 px-3 py-2.5 text-sm focus:border-indigo-400 focus:ring-1 focus:ring-indigo-400"
|
|
required>
|
|
<p class="mt-1.5 text-xs text-slate-500">Minimum GHS {{ number_format($minTopup, 2) }}</p>
|
|
</div>
|
|
|
|
<input type="hidden" name="payment_method" value="paystack" @if($canPayFromWallet) x-model="method" @endif>
|
|
|
|
@if($canPayFromWallet)
|
|
<div class="mt-4">
|
|
<p class="mb-2 text-xs font-medium text-slate-600">Payment method</p>
|
|
<div class="flex rounded-xl border border-slate-200 bg-white p-0.5 text-sm">
|
|
<button type="button" @click="method = 'paystack'"
|
|
:class="method === 'paystack' ? 'bg-indigo-600 text-white' : 'text-slate-600'"
|
|
class="flex-1 rounded-lg py-2 font-medium transition">Paystack</button>
|
|
<button type="button" @click="method = 'wallet'"
|
|
:class="method === 'wallet' ? 'bg-indigo-600 text-white' : 'text-slate-600'"
|
|
class="flex-1 rounded-lg py-2 font-medium transition">Wallet (GHS {{ number_format($ladillWalletBalance, 2) }})</button>
|
|
</div>
|
|
</div>
|
|
@else
|
|
<p class="mt-4 text-xs text-slate-500">Pay with Paystack.</p>
|
|
@endif
|
|
|
|
<div class="mt-6 flex flex-col gap-2 sm:mt-auto sm:flex-row sm:justify-end">
|
|
<button type="button" @click="$dispatch('close-modal', '{{ $id }}')"
|
|
data-close-modal="{{ $id }}"
|
|
class="hidden rounded-xl border border-slate-200 px-4 py-2.5 text-sm font-medium text-slate-700 hover:bg-slate-50 sm:inline-flex">
|
|
Cancel
|
|
</button>
|
|
<button type="submit" :disabled="loading"
|
|
class="btn-primary w-full sm:w-auto">
|
|
<span x-text="loading ? 'Processing…' : 'Add credits'">Add credits</span>
|
|
</button>
|
|
</div>
|
|
|
|
@include('partials.paystack-sheet')
|
|
</form>
|
|
</div>
|
|
</x-modal>
|