New payment flow

This commit is contained in:
David Bomba 2024-06-24 14:38:53 +10:00 committed by Benjamin Beganović
parent 0fc7a27cf4
commit 0f27b8474c
8 changed files with 203 additions and 24 deletions

104
app/Livewire/InvoicePay.php Normal file
View File

@ -0,0 +1,104 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Livewire;
use App\Livewire\Terms;
use Livewire\Component;
use App\Utils\HtmlEngine;
use App\Libraries\MultiDB;
use App\Livewire\Signature;
use Livewire\Attributes\On;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Reactive;
class InvoicePay extends Component
{
public $invitation_id;
public $db;
public $settings;
private $invite;
private $variables;
public $terms_accepted = false;
public $signature_accepted = false;
#[On('signature-captured')]
public function signatureCaptured($base64)
{
nlog("signature captured");
$this->signature_accepted = true;
$this->invite = \App\Models\InvoiceInvitation::withTrashed()->find($this->invitation_id)->withoutRelations();
$this->invite->signature_base64 = $base64;
$this->invite->signature_date = now()->addSeconds($this->invite->contact->client->timezone_offset());
$this->invite->save();
}
#[On('terms-accepted')]
public function termsAccepted()
{
nlog("Terms accepted");
$this->invite = \App\Models\InvoiceInvitation::withTrashed()->find($this->invitation_id)->withoutRelations();
$this->terms_accepted =true;
}
#[Computed()]
public function component(): string
{
if(!$this->terms_accepted)
return Terms::class;
if(!$this->signature_accepted)
return Signature::class;
}
#[Computed()]
public function componentUniqueId(): string
{
return "purchase-".md5(time());
}
public function mount()
{
MultiDB::setDb($this->db);
// @phpstan-ignore-next-line
$this->invite = \App\Models\InvoiceInvitation::with('invoice','contact.client','company')->withTrashed()->find($this->invitation_id);
$invoice = $this->invite->invoice;
$company = $this->invite->company;
$contact = $this->invite->contact;
$client = $this->invite->contact->client;
$this->variables = ($this->invite && auth()->guard('contact')->user()->client->getSetting('show_accept_invoice_terms')) ? (new HtmlEngine($this->invite))->generateLabelsAndValues() : false;
$this->settings = $client->getMergedSettings();
}
public function render()
{
return render('components.livewire.invoice-pay', [
'context' => [
'settings' => $this->settings,
'invoice' => $this->invite->invoice,
'variables' => $this->variables,
],
]);
}
}

View File

@ -0,0 +1,25 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Livewire;
use Livewire\Component;
class Signature extends Component
{
public function render()
{
return render('components.livewire.signature');
}
}

35
app/Livewire/Terms.php Normal file
View File

@ -0,0 +1,35 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Livewire;
use Livewire\Component;
class Terms extends Component
{
public $invoice;
public $context;
public $variables;
public function mount()
{
$this->invoice = $this->context['invoice'];
$this->variables = $this->context['variables'];
}
public function render()
{
return render('components.livewire.terms');
}
}

1
public/build/assets/app-8e387ada.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -240,7 +240,11 @@
"src": "resources/js/setup/setup.js" "src": "resources/js/setup/setup.js"
}, },
"resources/sass/app.scss": { "resources/sass/app.scss": {
<<<<<<< HEAD
"file": "assets/app-fee1da41.css", "file": "assets/app-fee1da41.css",
=======
"file": "assets/app-8e387ada.css",
>>>>>>> 3e760e6cc6 (New payment flow)
"isEntry": true, "isEntry": true,
"src": "resources/sass/app.scss" "src": "resources/sass/app.scss"
} }

View File

@ -0,0 +1,3 @@
<div>
@livewire($this->component,['context' => $context], key($this->componentUniqueId()))
</div>

View File

@ -1,13 +1,15 @@
<div class=""> <div style="w-full">
<div class="bg-white p-6 rounded-lg shadow-lg"> <div class="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-6">
<h2 class="text-xl text-center py-0 px-4">{{ ctrans('texts.sign_here_ux_tip') }}</h2> <div class="bg-white p-6 rounded-lg shadow-lg w-full max-w-md">
<canvas id="signature-pad" class="border border-gray-300 w-full h-64"></canvas> <h2 class="text-xl text-center mx-auto py-4 px-4">{{ ctrans('texts.sign_here_ux_tip') }}</h2>
<div class="flex justify-between items-center px-4 py-4"> <canvas id="signature-pad" class="border border-gray-300 w-full h-64"></canvas>
<button id="clear-signature" class="px-4 py-2 mr-6 bg-red-500 text-white rounded">{{ ctrans('texts.clear') }}</button> <div class="flex justify-between px-4 py-4">
<button id="save-button" class="button button-primary bg-primary hover:bg-primary-darken">{{ ctrans('texts.next') }}</button> <button id="clear-signature" class="px-4 bg-red-500 text-white rounded">{{ ctrans('texts.clear') }}</button>
<button id="save-button" class="button button-primary bg-primary hover:bg-primary-darken inline-flex items-center">{{ ctrans('texts.next') }}</button>
</div>
</div> </div>
</div> </div>
@assets @assets
<script src="{{ asset('vendor/signature_pad@5/signature_pad.umd.min.js') }}"></script> <script src="{{ asset('vendor/signature_pad@5/signature_pad.umd.min.js') }}"></script>
@endassets @endassets

View File

@ -1,23 +1,28 @@
<div class="pb-8"> <div>
<div class="bg-white p-6 rounded-lg shadow-lg"> <div class="bg-color: white">
<h2 class="text-xl text-center py-0 px-4">{{ ctrans('texts.terms') }}</h2> <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<div class="mt-0 h-64 overflow-y-auto"> <h3 class="text-xl leading-6 font-medium text-gray-900">
<div class="py-0"> {{ ctrans('texts.terms') }}
<p class="text-sm leading-6 font-medium text-gray-500">{{ ctrans('texts.invoice') }} {{ $invoice->number }}:</p> </h3>
@if($variables && $invoice->terms) <div class="mt-4 h-64 overflow-y-auto">
<h5 data-ref="entity-terms">{!! $invoice->parseHtmlVariables('terms', $variables) !!}</h5> <div class="mb-4">
@elseif($invoice->terms) <p class="text-sm leading-6 font-medium text-gray-500">{{ ctrans('texts.invoice') }} {{ $invoice->number }}:</p>
<h5 data-ref="entity-terms" class="text-sm leading-5 text-gray-900">{!! $invoice->terms !!}</h5> @if($variables && $invoice->terms)
@else <h5 data-ref="entity-terms">{!! $invoice->parseHtmlVariables('terms', $variables) !!}</h5>
<i class="text-sm leading-5 text-gray-500">{{ ctrans('texts.not_specified') }}</i> @elseif($invoice->terms)
@endif <h5 data-ref="entity-terms" class="text-sm leading-5 text-gray-900">{!! $invoice->terms !!}</h5>
@else
<i class="text-sm leading-5 text-gray-500">{{ ctrans('texts.not_specified') }}</i>
@endif
</div>
</div> </div>
</div> </div>
<div class="flex justify-end items-center px-4 py-4"> </div>
<button id="accept-terms-button" class="button button-primary bg-primary hover:bg-primary-darken float-end">{{ ctrans('texts.next') }}</button> <div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
<div class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto" x-data>
<button id="accept-terms-button" class="button button-primary bg-primary hover:bg-primary-darken inline-flex items-center">{{ ctrans('texts.next') }}</button>
</div> </div>
</div> </div>
@script @script
<script> <script>