mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
wip
This commit is contained in:
parent
dade7bad0a
commit
4350816804
@ -15,11 +15,16 @@ namespace App\Http\Controllers\ClientPortal;
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\BillingSubscription;
|
use App\Models\BillingSubscription;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class BillingSubscriptionPurchaseController extends Controller
|
class BillingSubscriptionPurchaseController extends Controller
|
||||||
{
|
{
|
||||||
public function index(BillingSubscription $billing_subscription)
|
public function index(BillingSubscription $billing_subscription)
|
||||||
{
|
{
|
||||||
return view('billing-portal.purchase', ['billing_subscription' => $billing_subscription]);
|
return view('billing-portal.purchase', [
|
||||||
|
'billing_subscription' => $billing_subscription,
|
||||||
|
'hash' => Str::uuid()->toString(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,21 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
use App\Models\BillingSubscription;
|
use App\Factory\ClientFactory;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Repositories\ClientContactRepository;
|
||||||
|
use App\Repositories\ClientRepository;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Symfony\Component\HttpClient\HttpClient;
|
|
||||||
|
|
||||||
class BillingPortalPurchase extends Component
|
class BillingPortalPurchase extends Component
|
||||||
{
|
{
|
||||||
public $authenticated = false;
|
public $hash;
|
||||||
|
|
||||||
|
public $heading_text = 'Log in';
|
||||||
|
|
||||||
public $email;
|
public $email;
|
||||||
|
|
||||||
@ -19,14 +24,21 @@ class BillingPortalPurchase extends Component
|
|||||||
|
|
||||||
public $billing_subscription;
|
public $billing_subscription;
|
||||||
|
|
||||||
|
public $contact;
|
||||||
|
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
'email' => ['required', 'email'],
|
'email' => ['required', 'email'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public $company_gateway_id;
|
||||||
|
|
||||||
|
public $payment_method_id;
|
||||||
|
|
||||||
public $steps = [
|
public $steps = [
|
||||||
'passed_email' => false,
|
'passed_email' => false,
|
||||||
'existing_user' => false,
|
'existing_user' => false,
|
||||||
'fetched_payment_methods' => false,
|
'fetched_payment_methods' => false,
|
||||||
|
'fetched_client' => false,
|
||||||
];
|
];
|
||||||
|
|
||||||
public $methods = [];
|
public $methods = [];
|
||||||
@ -35,10 +47,6 @@ class BillingPortalPurchase extends Component
|
|||||||
{
|
{
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
|
||||||
// Search for existing e-mail (note on multiple databases).
|
|
||||||
// If existing e-mail found, offer to login with password.
|
|
||||||
// If not, create a new contact e-mail.
|
|
||||||
|
|
||||||
$contact = ClientContact::where('email', $this->email)->first();
|
$contact = ClientContact::where('email', $this->email)->first();
|
||||||
|
|
||||||
if ($contact && $this->steps['existing_user'] === false) {
|
if ($contact && $this->steps['existing_user'] === false) {
|
||||||
@ -48,48 +56,61 @@ class BillingPortalPurchase extends Component
|
|||||||
if ($contact && $this->steps['existing_user']) {
|
if ($contact && $this->steps['existing_user']) {
|
||||||
$attempt = Auth::guard('contact')->attempt(['email' => $this->email, 'password' => $this->password]);
|
$attempt = Auth::guard('contact')->attempt(['email' => $this->email, 'password' => $this->password]);
|
||||||
|
|
||||||
if ($attempt) {
|
return $attempt
|
||||||
return $this->getPaymentMethods($contact);
|
? $this->getPaymentMethods($contact)
|
||||||
} else {
|
: session()->flash('message', 'These credentials do not match our records.');
|
||||||
session()->flash('message', 'These credentials do not match our records.');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->steps['existing_user'] = false;
|
$this->steps['existing_user'] = false;
|
||||||
|
|
||||||
$contact = $this->createBlankClient();
|
$contact = $this->createBlankClient();
|
||||||
$this->getPaymentMethods($contact);
|
|
||||||
|
if ($contact && $contact instanceof ClientContact) {
|
||||||
|
$this->getPaymentMethods($contact);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createBlankClient()
|
protected function createBlankClient()
|
||||||
{
|
{
|
||||||
$company = Company::find($this->billing_subscription->company_id);
|
$company = Company::first();
|
||||||
|
$user = User::first();
|
||||||
|
|
||||||
$http_client = HttpClient::create();
|
$client_repo = new ClientRepository(new ClientContactRepository());
|
||||||
|
$client_data = [
|
||||||
|
'name' => 'Client Name',
|
||||||
|
'contacts' => [
|
||||||
|
['email' => $this->email],
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
// $response = $http_client->request('GET', '/api/v1/contacts', [
|
$client = $client_repo->save($client_data, ClientFactory::create($company->id, $user->id));
|
||||||
// 'headers' => [
|
|
||||||
// 'X-Api-Token' => 'company-test-token',
|
|
||||||
// 'X-Requested-With' => 'XmlHttpRequest',
|
|
||||||
// ],
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
// dd($response->toArray());
|
return $client->contacts->first();
|
||||||
|
|
||||||
return ClientContact::where('email', $this->email)->first();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getPaymentMethods(ClientContact $contact): self
|
protected function getPaymentMethods(ClientContact $contact): self
|
||||||
{
|
{
|
||||||
|
Cache::put($this->hash, ['email' => $this->email ?? $this->contact->email, 'url' => url()->current()]);
|
||||||
|
|
||||||
$this->steps['fetched_payment_methods'] = true;
|
$this->steps['fetched_payment_methods'] = true;
|
||||||
|
|
||||||
$this->methods = $contact->client->service()->getPaymentMethods(1000);
|
$this->methods = $contact->client->service()->getPaymentMethods(1000);
|
||||||
|
|
||||||
|
$this->heading_text = 'Pick a payment method';
|
||||||
|
|
||||||
|
Auth::guard('contact')->login($contact);
|
||||||
|
|
||||||
|
$this->contact = $contact;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
|
if ($this->contact instanceof ClientContact) {
|
||||||
|
$this->getPaymentMethods($this->contact);
|
||||||
|
}
|
||||||
|
|
||||||
return render('components.livewire.billing-portal-purchase');
|
return render('components.livewire.billing-portal-purchase');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
public/css/app.css
vendored
2
public/css/app.css
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"/js/app.js": "/js/app.js?id=696e8203d5e8e7cf5ff5",
|
"/js/app.js": "/js/app.js?id=696e8203d5e8e7cf5ff5",
|
||||||
"/css/app.css": "/css/app.css?id=4d371a145027af1ba28e",
|
"/css/app.css": "/css/app.css?id=8d3e488939aa216c7a1c",
|
||||||
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=a09bb529b8e1826f13b4",
|
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=a09bb529b8e1826f13b4",
|
||||||
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1",
|
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1",
|
||||||
"/js/clients/linkify-urls.js": "/js/clients/linkify-urls.js?id=0dc8c34010d09195d2f7",
|
"/js/clients/linkify-urls.js": "/js/clients/linkify-urls.js?id=0dc8c34010d09195d2f7",
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
@extends('portal.ninja2020.layout.clean')
|
@extends('portal.ninja2020.layout.clean')
|
||||||
|
@section('meta_title', $billing_subscription->product->product_key)
|
||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
@livewire('billing-portal-purchase', ['billing_subscription' => $billing_subscription])
|
@livewire('billing-portal-purchase', ['billing_subscription' => $billing_subscription, 'contact' => auth('contact')->user(), 'hash' => $hash])
|
||||||
@stop
|
@stop
|
||||||
|
|
||||||
|
@push('footer')
|
||||||
|
<script>
|
||||||
|
function updateGatewayFields(companyGatewayId, paymentMethodId) {
|
||||||
|
document.getElementById('company_gateway_id').value = companyGatewayId;
|
||||||
|
document.getElementById('payment_method_id').value = paymentMethodId;
|
||||||
|
document.getElementById('payment-method-form').submit();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
@ -8,7 +8,9 @@
|
|||||||
@include('portal.ninja2020.components.general.sidebar.mobile')
|
@include('portal.ninja2020.components.general.sidebar.mobile')
|
||||||
|
|
||||||
<!-- Static sidebar for desktop -->
|
<!-- Static sidebar for desktop -->
|
||||||
@include('portal.ninja2020.components.general.sidebar.desktop')
|
@unless(request()->query('sidebar') === 'hidden')
|
||||||
|
@include('portal.ninja2020.components.general.sidebar.desktop')
|
||||||
|
@endunless
|
||||||
|
|
||||||
<div class="flex flex-col w-0 flex-1 overflow-hidden">
|
<div class="flex flex-col w-0 flex-1 overflow-hidden">
|
||||||
@include('portal.ninja2020.components.general.sidebar.header')
|
@include('portal.ninja2020.components.general.sidebar.header')
|
||||||
@ -34,4 +36,4 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -29,8 +29,7 @@
|
|||||||
<div class="col-span-12 lg:col-span-6 bg-white lg:shadow-lg lg:h-screen">
|
<div class="col-span-12 lg:col-span-6 bg-white lg:shadow-lg lg:h-screen">
|
||||||
<div class="grid grid-cols-12 flex flex-col p-10 lg:mt-48 lg:ml-16">
|
<div class="grid grid-cols-12 flex flex-col p-10 lg:mt-48 lg:ml-16">
|
||||||
<div class="col-span-12 w-full lg:col-span-6">
|
<div class="col-span-12 w-full lg:col-span-6">
|
||||||
<h2 class="text-2xl font-bold tracking-wide">Payment details</h2>
|
<h2 class="text-2xl font-bold tracking-wide">{{ $heading_text }}</h2>
|
||||||
|
|
||||||
@if (session()->has('message'))
|
@if (session()->has('message'))
|
||||||
@component('portal.ninja2020.components.message')
|
@component('portal.ninja2020.components.message')
|
||||||
{{ session('message') }}
|
{{ session('message') }}
|
||||||
@ -38,43 +37,56 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if($this->steps['fetched_payment_methods'])
|
@if($this->steps['fetched_payment_methods'])
|
||||||
<div class="flex items-center space-x-4 mt-4 text-sm">
|
<div class="flex items-center mt-4 text-sm">
|
||||||
|
<form action="{{ route('client.payments.process', ['hash' => $hash, 'sidebar' => 'hidden']) }}" method="post"
|
||||||
|
id="payment-method-form">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" name="action" value="payment">
|
||||||
|
<input type="hidden" name="company_gateway_id" id="company_gateway_id">
|
||||||
|
<input type="hidden" name="payment_method_id" id="payment_method_id">
|
||||||
|
</form>
|
||||||
|
|
||||||
@foreach($this->methods as $method)
|
@foreach($this->methods as $method)
|
||||||
<button
|
<button
|
||||||
class="pb-2 border-b-2 border-transparent hover:border-blue-600">{{ $method['label'] }}</button>
|
data-company-gateway-id="{{ $method['company_gateway_id'] }}"
|
||||||
|
data-payment-method-id="{{ $method['gateway_type_id'] }}"
|
||||||
|
onclick="updateGatewayFields(this.dataset.companyGatewayId, this.dataset.paymentMethodId);"
|
||||||
|
class="p-4 border rounded mr-4 hover:border-blue-600">
|
||||||
|
{{ $method['label'] }}
|
||||||
|
</button>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@else
|
||||||
|
<form wire:submit.prevent="authenticate" class="mt-8">
|
||||||
|
@csrf
|
||||||
|
|
||||||
<form wire:submit.prevent="authenticate" class="mt-8">
|
<label for="email_address">
|
||||||
@csrf
|
<span class="input-label">E-mail address</span>
|
||||||
|
<input wire:model.defer="email" type="email" class="input w-full"/>
|
||||||
|
|
||||||
<label for="email_address">
|
@error('email')
|
||||||
<span class="input-label">E-mail address</span>
|
|
||||||
<input wire:model="email" type="email" class="input w-full"/>
|
|
||||||
|
|
||||||
@error('email')
|
|
||||||
<p class="validation validation-fail block w-full" role="alert">
|
|
||||||
{{ $message }}
|
|
||||||
</p>
|
|
||||||
@enderror
|
|
||||||
</label>
|
|
||||||
|
|
||||||
@if($steps['existing_user'])
|
|
||||||
<label for="password" class="block mt-2">
|
|
||||||
<span class="input-label">Password</span>
|
|
||||||
<input wire:model="password" type="password" class="input w-full" autofocus/>
|
|
||||||
|
|
||||||
@error('password')
|
|
||||||
<p class="validation validation-fail block w-full" role="alert">
|
<p class="validation validation-fail block w-full" role="alert">
|
||||||
{{ $message }}
|
{{ $message }}
|
||||||
</p>
|
</p>
|
||||||
@enderror
|
@enderror
|
||||||
</label>
|
</label>
|
||||||
@endif
|
|
||||||
|
|
||||||
<button type="submit" class="button button-block bg-primary text-white mt-4">Next</button>
|
@if($steps['existing_user'])
|
||||||
</form>
|
<label for="password" class="block mt-2">
|
||||||
|
<span class="input-label">Password</span>
|
||||||
|
<input wire:model.defer="password" type="password" class="input w-full" autofocus/>
|
||||||
|
|
||||||
|
@error('password')
|
||||||
|
<p class="validation validation-fail block w-full" role="alert">
|
||||||
|
{{ $message }}
|
||||||
|
</p>
|
||||||
|
@enderror
|
||||||
|
</label>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<button type="submit" class="button button-block bg-primary text-white mt-4">Next</button>
|
||||||
|
</form>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user