diff --git a/app/Http/Controllers/WalletBalanceController.php b/app/Http/Controllers/WalletBalanceController.php new file mode 100644 index 0000000..29d4267 --- /dev/null +++ b/app/Http/Controllers/WalletBalanceController.php @@ -0,0 +1,40 @@ +user()->public_id; + + $minor = Cache::remember("wallet_balance:{$publicId}", now()->addSeconds(30), function () use ($billing, $publicId) { + try { + return $billing->balanceMinor($publicId); + } catch (\Throwable) { + return null; + } + }); + + if ($minor === null) { + return response()->json(['available' => false]); + } + + $currency = (string) config('billing.currency', 'GHS'); + + return response()->json([ + 'available' => true, + 'balance_minor' => $minor, + 'currency' => $currency, + 'formatted' => $currency.' '.number_format($minor / 100, 2), + ]); + } +} diff --git a/app/Support/UserProfileMenu.php b/app/Support/UserProfileMenu.php index 3228d49..2806cdb 100644 --- a/app/Support/UserProfileMenu.php +++ b/app/Support/UserProfileMenu.php @@ -43,6 +43,11 @@ class UserProfileMenu ]; } + + if (Route::has((string) config("billing.wallet_balance_route", "wallet.balance"))) { + $items[] = ["type" => "wallet"]; + } + if (self::userIsAdmin($user)) { $adminHref = self::platformUrl('account', 'admin'); diff --git a/config/billing.php b/config/billing.php index 322961f..395303b 100644 --- a/config/billing.php +++ b/config/billing.php @@ -4,5 +4,7 @@ return [ 'api_url' => env('BILLING_API_URL', 'https://ladill.com/api/billing'), 'api_key' => env('BILLING_API_KEY_MINI'), 'service' => 'mini', + 'wallet_balance_route' => 'wallet.balance', + 'currency' => 'GHS', 'platform_settings_connection' => env('BILLING_PLATFORM_SETTINGS_CONNECTION', 'platform'), ]; diff --git a/resources/js/app.js b/resources/js/app.js index f65cb5a..90dfca5 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -302,6 +302,26 @@ Alpine.data('topbarSearch', (config = {}) => ({ }, })); + +// Wallet balance peek for the avatar dropdown. +Alpine.data('walletWidget', (config = {}) => ({ + display: '…', + async load() { + if (! config.url) { + this.display = 'View wallet'; + + return; + } + try { + const res = await fetch(config.url, { headers: { Accept: 'application/json', 'X-Requested-With': 'XMLHttpRequest' } }); + const data = await res.json(); + this.display = data.available ? data.formatted : 'View wallet'; + } catch (e) { + this.display = 'View wallet'; + } + }, +})); + window.Alpine = Alpine; registerLadillConfirmStore(Alpine); diff --git a/resources/views/partials/afia-button.blade.php b/resources/views/partials/afia-button.blade.php index f8eede3..0588ba6 100644 --- a/resources/views/partials/afia-button.blade.php +++ b/resources/views/partials/afia-button.blade.php @@ -8,7 +8,7 @@ @if ($handler === 'openAfia') @click="openAfia()" @else - @click="$dispatch('afia-open')" + @click="window.dispatchEvent(new CustomEvent('afia-open'))" @endif @class([ 'inline-flex shrink-0 items-center justify-center gap-2 rounded-xl bg-gradient-to-r from-indigo-700 via-blue-600 to-emerald-400 text-sm font-semibold text-white shadow-sm transition hover:opacity-95', diff --git a/resources/views/partials/topbar-qr.blade.php b/resources/views/partials/topbar-qr.blade.php index 3e697c4..30909f0 100644 --- a/resources/views/partials/topbar-qr.blade.php +++ b/resources/views/partials/topbar-qr.blade.php @@ -123,7 +123,7 @@
+ class="absolute right-0 z-50 mt-2 w-64 rounded-xl border border-slate-200 bg-white shadow-lg"> @include('partials.user-profile-menu', [ 'items' => \App\Support\UserProfileMenu::items($user), ]) diff --git a/resources/views/partials/topbar.blade.php b/resources/views/partials/topbar.blade.php index d094e1e..a0ae239 100644 --- a/resources/views/partials/topbar.blade.php +++ b/resources/views/partials/topbar.blade.php @@ -255,7 +255,7 @@
+ class="absolute right-0 z-50 mt-2 w-64 rounded-xl border border-slate-200 bg-white shadow-lg"> @include('partials.user-profile-menu', [ 'items' => \App\Support\UserProfileMenu::items($user), ]) diff --git a/resources/views/partials/user-profile-menu.blade.php b/resources/views/partials/user-profile-menu.blade.php index ee7e421..c78cb3e 100644 --- a/resources/views/partials/user-profile-menu.blade.php +++ b/resources/views/partials/user-profile-menu.blade.php @@ -53,6 +53,8 @@ @if ($onNavigate) @click="{{ $onNavigate }}" @endif> {{ $item['label'] }} + @elseif (($item['type'] ?? '') === 'wallet') + @includeIf('partials.wallet-widget') @elseif (($item['type'] ?? '') === 'logout') @if ($variant !== 'sheet')
diff --git a/resources/views/partials/wallet-widget.blade.php b/resources/views/partials/wallet-widget.blade.php new file mode 100644 index 0000000..8661874 --- /dev/null +++ b/resources/views/partials/wallet-widget.blade.php @@ -0,0 +1,23 @@ +{{-- Wallet balance peek (links to the account wallet on account.ladill.com). --}} +@php + $balanceRoute = (string) config('billing.wallet_balance_route', 'wallet.balance'); + $balanceUrl = \Illuminate\Support\Facades\Route::has($balanceRoute) ? route($balanceRoute) : null; +@endphp +@if ($balanceUrl) + + + + + + + + + Wallet balance + + + + + +@endif diff --git a/routes/web.php b/routes/web.php index faefe59..47a95ae 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,6 +1,7 @@ name('qr.p Route::get('/q/{shortCode}/pay/callback', [PaymentController::class, 'callback'])->name('qr.public.payment.callback'); Route::middleware(['auth', 'platform.session'])->group(function () { + Route::get('/wallet/balance', [WalletBalanceController::class, 'balance'])->name('wallet.balance'); Route::get('/notifications', [NotificationController::class, 'index'])->name('notifications.index'); Route::get('/notifications/unread', [NotificationController::class, 'unread'])->name('notifications.unread'); Route::post('/notifications/{id}/read', [NotificationController::class, 'markAsRead'])->name('notifications.mark-read');