1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 05:02:36 +01:00

- Bundle qty without ability to increment/decrement value

- One time & subs 
- A table with all products included in subscription (qty, price, notes) 
- Two tables, one for subscriptions, one for one-time purchases 
- If no products, no table 
- Remove quantity from cached data that is being sent 
- Remove "billing_subscription_id" from data sent 
This commit is contained in:
Benjamin Beganović 2021-03-25 16:52:03 +01:00
parent 0173d0fe46
commit ed4fff2385
9 changed files with 79 additions and 59 deletions

View File

@ -139,13 +139,6 @@ class BillingPortalPurchase extends Component
*/ */
public $request_data; public $request_data;
/**
* Price of product.
*
* @var string
*/
public $price;
/** /**
* Handle user authentication * Handle user authentication
* *
@ -291,8 +284,6 @@ class BillingPortalPurchase extends Component
'email' => $this->email ?? $this->contact->email, 'email' => $this->email ?? $this->contact->email,
'client_id' => $this->contact->client->id, 'client_id' => $this->contact->client->id,
'invoice_id' => $this->invoice->id, 'invoice_id' => $this->invoice->id,
'quantity' => $this->quantity,
'subscription_id' => $this->subscription->id,
now()->addMinutes(60)] now()->addMinutes(60)]
); );

View File

@ -54,7 +54,7 @@ class Subscription extends BaseModel
'deleted_at' => 'timestamp', 'deleted_at' => 'timestamp',
]; ];
public function service() public function service(): SubscriptionService
{ {
return new SubscriptionService($this); return new SubscriptionService($this);
} }
@ -68,9 +68,4 @@ class Subscription extends BaseModel
{ {
return $this->belongsTo(User::class); return $this->belongsTo(User::class);
} }
public function product(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Product::class);
}
} }

2
public/css/app.css vendored

File diff suppressed because one or more lines are too long

View File

@ -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=1481aa442df903f3c38b", "/css/app.css": "/css/app.css?id=9525909664b98602bd2a",
"/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",

View File

@ -1,8 +1,8 @@
@extends('portal.ninja2020.layout.clean') @extends('portal.ninja2020.layout.clean')
@section('meta_title', $billing_subscription->product->product_key) @section('meta_title', ctrans('texts.purchase'))
@section('body') @section('body')
@livewire('billing-portal-purchase', ['billing_subscription' => $billing_subscription, 'contact' => auth('contact')->user(), 'hash' => $hash, 'request_data' => $request_data, 'price' => $billing_subscription->product->price]) @livewire('billing-portal-purchase', ['subscription' => $subscription, 'contact' => auth('contact')->user(), 'hash' => $hash, 'request_data' => $request_data])
@stop @stop
@push('footer') @push('footer')

View File

@ -1,48 +1,79 @@
<div class="grid grid-cols-12"> <div class="grid grid-cols-12">
<div class="col-span-12 lg:col-span-6 bg-gray-50 shadow-lg lg:h-screen flex flex-col items-center"> <div class="col-span-12 lg:col-span-6 bg-gray-50 flex flex-col items-center">
<div class="w-full p-10 lg:w-1/2 lg:mt-48 lg:p-0"> <div class="w-full p-10 lg:w-1/2 lg:mt-24 lg:p-0">
<img class="h-8" src="{{ $billing_subscription->company->present()->logo }}" <img class="h-8" src="{{ $subscription->company->present()->logo }}"
alt="{{ $billing_subscription->company->present()->name }}"> alt="{{ $subscription->company->present()->name }}">
<h1 id="billing-page-company-logo" class="text-3xl font-bold tracking-wide mt-8"> <div class="mt-6">
{{ $billing_subscription->product->product_key }} <p
</h1> class="mb-4 uppercase leading-4 tracking-wide inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-primary text-white">
Subscription
<p class="my-6">{{ $billing_subscription->product->notes }}</p> </p>
<h1 id="billing-page-company-logo" class="text-3xl font-bold tracking-wide">
<span class="text-sm uppercase font-bold">{{ ctrans('texts.price') }}:</span> Invoice Ninja Pro+
</h1>
<div class="flex space-x-2">
<h1 class="text-2xl font-bold tracking-wide">{{ App\Utils\Number::formatMoney($price, $billing_subscription->company) }}</h1>
@if($billing_subscription->is_recurring)
<span class="text-xs uppercase">/ {{ \App\Models\RecurringInvoice::frequencyForKey($billing_subscription->frequency_id) }}</span>
@endif
</div> </div>
@if(!empty($subscription->product_ids))
<div class="flex flex-col mt-8">
<span
class="mb-4 uppercase leading-4 tracking-wide inline-flex items-center rounded-full text-xs font-medium">
One-time purchases:
</span>
@if($billing_subscription->per_seat_enabled && $billing_subscription->max_seats_limit > 1) <div class="flex items-center justify-between mb-4 bg-white rounded px-6 py-4 shadow-sm border">
<div class="flex mt-4 space-x-4 items-center"> <div class="text-sm">Pro+ plan</div>
<span class="text-sm">{{ ctrans('texts.qty') }}</span> <div data-ref="price-and-quantity-container">
<button wire:click="updateQuantity('decrement')" class="bg-gray-100 border rounded p-1"> <span data-ref="price">$10</span>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" <span data-ref="quantity" class="text-sm">(1x)</span>
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" </div>
class="feather feather-minus"> </div>
<line x1="5" y1="12" x2="19" y2="12"></line> <div class="flex items-center justify-between mb-4 bg-white rounded px-6 py-4 shadow-sm border">
</svg> <div class="text-sm">Another awesome product</div>
</button> <div data-ref="price-and-quantity-container">
<button>{{ $quantity }}</button> <span data-ref="price">$5</span>
<button wire:click="updateQuantity('increment')" class="bg-gray-100 border rounded p-1"> <span data-ref="quantity" class="text-sm">(2x)</span>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" </div>
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" </div>
class="feather feather-plus">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
</div> </div>
@endif @endif
@if(!empty($subscription->recurring_product_ids))
<div class="flex flex-col mt-8">
<span
class="mb-4 uppercase leading-4 tracking-wide inline-flex items-center rounded-full text-xs font-medium">
Recurring purchases:
</span>
<div class="flex items-center justify-between mb-4 bg-white rounded px-6 py-4 shadow-sm border">
<div class="text-sm">Pro+ plan</div>
<div data-ref="price-and-quantity-container">
<span data-ref="price">$10</span>
<span data-ref="quantity" class="text-sm">(1x)</span>
</div>
</div>
<div class="flex items-center justify-between mb-4 bg-white rounded px-6 py-4 shadow-sm border">
<div class="text-sm">Another awesome product</div>
<div data-ref="price-and-quantity-container">
<span data-ref="price">$5</span>
<span data-ref="quantity" class="text-sm">(2x)</span>
</div>
</div>
</div>
@endif
<div class="relative mt-8">
<div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-gray-300"></div>
</div>
<div class="relative flex justify-center text-sm leading-5">
<h1 class="text-2xl font-bold tracking-wide bg-gray-50 px-6 py-0">
{{ ctrans('texts.total') }}: {{ App\Utils\Number::formatMoney(20, $subscription->company) }}
</h1>
</div>
</div>
@if(auth('contact')->user()) @if(auth('contact')->user())
<a href="{{ route('client.invoices.index') }}" class="block mt-16 inline-flex items-center space-x-2"> <a href="{{ route('client.invoices.index') }}" class="block mt-16 inline-flex items-center space-x-2">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
@ -58,7 +89,7 @@
</div> </div>
</div> </div>
<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: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">{{ $heading_text ?? ctrans('texts.login') }}</h2> <h2 class="text-2xl font-bold tracking-wide">{{ $heading_text ?? ctrans('texts.login') }}</h2>
@ -140,7 +171,7 @@
</form> </form>
@endif @endif
@if(!empty($billing_subscription->promo_code) && !$billing_subscription->trial_enabled) @if(!empty($subscription->promo_code) && !$subscription->trial_enabled)
<div class="relative mt-8"> <div class="relative mt-8">
<div class="absolute inset-0 flex items-center"> <div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-gray-300"></div> <div class="w-full border-t border-gray-300"></div>

View File

@ -76,7 +76,7 @@ Route::group(['middleware' => ['auth:contact', 'locale', 'check_client_existence
Route::get('logout', 'Auth\ContactLoginController@logout')->name('logout'); Route::get('logout', 'Auth\ContactLoginController@logout')->name('logout');
}); });
Route::get('client/subscription/{billing_subscription}/purchase', 'ClientPortal\BillingSubscriptionPurchaseController@index')->name('client.subscription.purchase'); Route::get('client/subscription/{subscription}/purchase', 'ClientPortal\SubscriptionPurchaseController@index')->name('client.subscription.purchase');
Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'client.'], function () { Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'client.'], function () {
/*Invitation catches*/ /*Invitation catches*/

3
tailwind.config.js vendored
View File

@ -1,6 +1,9 @@
const defaultTheme = require("tailwindcss/defaultTheme"); const defaultTheme = require("tailwindcss/defaultTheme");
module.exports = { module.exports = {
future: {
purgeLayersByDefault: true
},
purge: [ purge: [
'./resources/views/portal/ninja2020/**/*.blade.php', './resources/views/portal/ninja2020/**/*.blade.php',
'./resources/views/email/template/**/*.blade.php', './resources/views/email/template/**/*.blade.php',