diff --git a/app/Http/Controllers/Frontdesk/ProController.php b/app/Http/Controllers/Frontdesk/ProController.php new file mode 100644 index 0000000..4d2d8cb --- /dev/null +++ b/app/Http/Controllers/Frontdesk/ProController.php @@ -0,0 +1,89 @@ +organization($request); + $canManage = app(FrontdeskPermissions::class)->isAdmin($this->member($request)); + $settings = $organization->settings ?? []; + $expiresAt = ! empty($settings['plan_expires_at']) + ? Carbon::parse($settings['plan_expires_at']) + : null; + + return view('frontdesk.pro.index', [ + 'organization' => $organization, + 'isPro' => $plans->isPro($organization), + 'canManage' => $canManage, + 'priceMinor' => $plans->proPriceMinor(), + 'currency' => (string) config('billing.currency', 'GHS'), + 'planExpiresAt' => $expiresAt, + 'proFeatures' => [ + 'Unlimited branches & kiosk devices', + 'Unlimited host email alerts', + 'Webhooks & calendar (iCal) feeds', + 'Scheduled report exports', + 'Custom badge templates', + ], + ]); + } + + public function subscribe(Request $request, PlanService $plans, BillingClient $billing): RedirectResponse + { + $this->authorizeAbility($request, 'settings.manage'); + $organization = $this->organization($request); + + if ($plans->isPro($organization)) { + return redirect()->route('frontdesk.pro.index') + ->with('success', 'Your organization is already on Frontdesk Pro.'); + } + + $priceMinor = $plans->proPriceMinor(); + $ownerRef = $organization->owner_ref; + + try { + if (! $billing->canAfford($ownerRef, $priceMinor)) { + return redirect()->route('frontdesk.pro.index') + ->with('error', 'Insufficient wallet balance. Top up your Ladill wallet to upgrade to Pro.'); + } + + $charged = $billing->debit( + $ownerRef, + $priceMinor, + 'frontdesk_pro', + 'frontdesk-pro-'.$organization->id.'-'.now()->format('Y-m-d-His'), + 'Ladill Frontdesk Pro — monthly subscription', + ); + } catch (\Throwable) { + return redirect()->route('frontdesk.pro.index') + ->with('error', 'Could not process upgrade. Please try again.'); + } + + if (! $charged) { + return redirect()->route('frontdesk.pro.index') + ->with('error', 'Insufficient wallet balance. Top up your Ladill wallet to upgrade to Pro.'); + } + + $settings = $organization->settings ?? []; + $settings['plan'] = 'pro'; + $settings['plan_expires_at'] = now()->addMonth()->toIso8601String(); + $organization->update(['settings' => $settings]); + + return redirect()->route('frontdesk.pro.index') + ->with('success', 'Welcome to Frontdesk Pro — active for one month.'); + } +} diff --git a/app/Http/Controllers/Frontdesk/WalletController.php b/app/Http/Controllers/Frontdesk/WalletController.php index a34bf32..e0db2e6 100644 --- a/app/Http/Controllers/Frontdesk/WalletController.php +++ b/app/Http/Controllers/Frontdesk/WalletController.php @@ -5,8 +5,7 @@ namespace App\Http\Controllers\Frontdesk; use App\Http\Controllers\Controller; use App\Http\Controllers\Frontdesk\Concerns\ScopesToAccount; use App\Services\Billing\BillingClient; -use App\Services\Frontdesk\PlanService; -use Illuminate\Http\RedirectResponse; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; @@ -39,44 +38,4 @@ class WalletController extends Controller 'formatted' => $currency.' '.number_format($minor / 100, 2), ]); } - - public function upgrade(Request $request, PlanService $plans, BillingClient $billing): RedirectResponse - { - $this->authorizeAbility($request, 'settings.manage'); - $organization = $this->organization($request); - - if ($plans->isPro($organization)) { - return back()->with('success', 'Your organization is already on Frontdesk Pro.'); - } - - $priceMinor = $plans->proPriceMinor(); - $ownerRef = $organization->owner_ref; - - try { - if (! $billing->canAfford($ownerRef, $priceMinor)) { - return back()->with('error', 'Insufficient wallet balance. Top up your Ladill wallet to upgrade to Pro.'); - } - - $charged = $billing->debit( - $ownerRef, - $priceMinor, - 'frontdesk_pro', - 'frontdesk-pro-'.$organization->id.'-'.now()->format('Y-m'), - 'Ladill Frontdesk Pro — monthly subscription', - ); - } catch (\Throwable) { - return back()->with('error', 'Could not process upgrade. Please try again.'); - } - - if (! $charged) { - return back()->with('error', 'Insufficient wallet balance. Top up your Ladill wallet to upgrade to Pro.'); - } - - $settings = $organization->settings ?? []; - $settings['plan'] = 'pro'; - $settings['plan_expires_at'] = now()->addMonth()->toIso8601String(); - $organization->update(['settings' => $settings]); - - return back()->with('success', 'Upgraded to Frontdesk Pro for one month.'); - } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 383e659..940edc1 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,9 +2,13 @@ namespace App\Providers; +use App\Models\User; +use App\Services\Frontdesk\OrganizationResolver; +use App\Services\Frontdesk\PlanService; use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Http\Request; use Illuminate\Support\Facades\RateLimiter; +use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider @@ -29,5 +33,20 @@ class AppServiceProvider extends ServiceProvider RateLimiter::for('device-heartbeat', function (Request $request) { return Limit::perMinute(60)->by((string) ($request->header('X-Device-Token') ?? $request->ip())); }); + + View::composer('partials.sidebar', function ($view) { + /** @var User|null $user */ + $user = auth()->user(); + $isPro = false; + + if ($user) { + $organization = app(OrganizationResolver::class)->resolveForUser($user); + if ($organization) { + $isPro = app(PlanService::class)->isPro($organization); + } + } + + $view->with('isPro', $isPro); + }); } } diff --git a/app/Services/Frontdesk/PlanService.php b/app/Services/Frontdesk/PlanService.php index 679f572..702eb20 100644 --- a/app/Services/Frontdesk/PlanService.php +++ b/app/Services/Frontdesk/PlanService.php @@ -78,6 +78,6 @@ class PlanService public function proPriceMinor(): int { - return (int) config('frontdesk.plans.pro.price_minor', 9900); + return (int) config('frontdesk.plans.pro.price_minor', 10000); } } diff --git a/config/frontdesk.php b/config/frontdesk.php index 9549520..5e50a37 100644 --- a/config/frontdesk.php +++ b/config/frontdesk.php @@ -132,7 +132,7 @@ return [ ], 'pro' => [ 'label' => 'Pro', - 'price_minor' => (int) env('FRONTDESK_PRO_PRICE_MINOR', 9900), + 'price_minor' => (int) env('FRONTDESK_PRO_PRICE_MINOR', 10000), 'max_branches' => null, 'max_kiosk_devices' => null, 'free_emails_per_month' => env('FRONTDESK_PRO_FREE_EMAILS_PER_MONTH') !== null diff --git a/resources/views/frontdesk/integrations/upgrade.blade.php b/resources/views/frontdesk/integrations/upgrade.blade.php index 7f3690f..7f2215b 100644 --- a/resources/views/frontdesk/integrations/upgrade.blade.php +++ b/resources/views/frontdesk/integrations/upgrade.blade.php @@ -6,12 +6,9 @@
- GHS {{ number_format($proPriceMinor / 100, 2) }} / month from your Ladill wallet — unlimited branches and kiosks, integrations, scheduled reports, and more. + GHS {{ number_format($proPriceMinor / 100, 0) }} / month from your Ladill wallet — unlimited branches and kiosks, integrations, scheduled reports, and more.
- + View Pro plansTop up your wallet if you need more balance.
diff --git a/resources/views/frontdesk/pro/index.blade.php b/resources/views/frontdesk/pro/index.blade.php new file mode 100644 index 0000000..54e1e80 --- /dev/null +++ b/resources/views/frontdesk/pro/index.blade.php @@ -0,0 +1,59 @@ +Everything in Free, plus unlimited scale, integrations, and unlimited host email alerts.
+{{ $currency }} {{ $price }} / month
+SMS host alerts still bill at Ladill platform rates from your wallet.
+ @elseif ($canManage) + +Billed monthly from your Ladill wallet. Host SMS remains pay-as-you-go on every plan.
+ @else +Ask an organization administrator to upgrade this workspace to Pro.
+ @endif +