Working on v3
This commit is contained in:
parent
8b8d20837f
commit
4837bd210e
|
|
@ -77,7 +77,6 @@ class SubscriptionPurchaseController extends Controller
|
||||||
|
|
||||||
public function v3(Subscription $subscription, Request $request)
|
public function v3(Subscription $subscription, Request $request)
|
||||||
{
|
{
|
||||||
// Todo: Prerequirement checks for subscription.
|
|
||||||
|
|
||||||
return view('billing-portal.v3.index', [
|
return view('billing-portal.v3.index', [
|
||||||
'subscription' => $subscription,
|
'subscription' => $subscription,
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ class Login extends Component
|
||||||
|
|
||||||
auth()->guard('contact')->loginUsingId($contact->id, true);
|
auth()->guard('contact')->loginUsingId($contact->id, true);
|
||||||
|
|
||||||
$this->dispatch('purchase.context', property: 'contact', value: $contact);
|
// $this->dispatch('purchase.context', property: 'contact', value: $contact);
|
||||||
$this->dispatch('purchase.next');
|
$this->dispatch('purchase.next');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,6 +96,7 @@ class Login extends Component
|
||||||
{
|
{
|
||||||
$code = rand(100000, 999999);
|
$code = rand(100000, 999999);
|
||||||
$email_hash = "subscriptions:otp:{$this->email}";
|
$email_hash = "subscriptions:otp:{$this->email}";
|
||||||
|
$contact = auth()->guard('contact')->user();
|
||||||
|
|
||||||
Cache::put($email_hash, $code, 600);
|
Cache::put($email_hash, $code, 600);
|
||||||
|
|
||||||
|
|
@ -103,7 +104,7 @@ class Login extends Component
|
||||||
$cc->email = $this->email;
|
$cc->email = $this->email;
|
||||||
|
|
||||||
$nmo = new NinjaMailerObject();
|
$nmo = new NinjaMailerObject();
|
||||||
$nmo->mailable = new OtpCode($this->subscription()->company, $this->context['contact'] ?? null, $code);
|
$nmo->mailable = new OtpCode($this->subscription()->company, $contact ?? null, $code);
|
||||||
$nmo->company = $this->subscription()->company;
|
$nmo->company = $this->subscription()->company;
|
||||||
$nmo->settings = $this->subscription()->company->settings;
|
$nmo->settings = $this->subscription()->company->settings;
|
||||||
$nmo->to_user = $cc;
|
$nmo->to_user = $cc;
|
||||||
|
|
@ -140,7 +141,7 @@ class Login extends Component
|
||||||
if ($contact) {
|
if ($contact) {
|
||||||
auth()->guard('contact')->loginUsingId($contact->id, true);
|
auth()->guard('contact')->loginUsingId($contact->id, true);
|
||||||
|
|
||||||
$this->dispatch('purchase.context', property: 'contact', value: $contact);
|
// $this->dispatch('purchase.context', property: 'contact', value: $contact);
|
||||||
$this->dispatch('purchase.next');
|
$this->dispatch('purchase.next');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -162,7 +163,7 @@ class Login extends Component
|
||||||
|
|
||||||
if ($attempt) {
|
if ($attempt) {
|
||||||
|
|
||||||
$this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user());
|
// $this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user());
|
||||||
$this->dispatch('purchase.next');
|
$this->dispatch('purchase.next');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,7 +173,7 @@ class Login extends Component
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
if (auth()->guard('contact')->check()) {
|
if (auth()->guard('contact')->check()) {
|
||||||
$this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user());
|
// $this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user());
|
||||||
$this->dispatch('purchase.next');
|
$this->dispatch('purchase.next');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ class Register extends Component
|
||||||
|
|
||||||
auth()->guard('contact')->loginUsingId($contact->id, true);
|
auth()->guard('contact')->loginUsingId($contact->id, true);
|
||||||
|
|
||||||
$this->dispatch('purchase.context', property: 'contact', value: $contact);
|
// $this->dispatch('purchase.context', property: 'contact', value: $contact);
|
||||||
$this->dispatch('purchase.next');
|
$this->dispatch('purchase.next');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,7 +112,7 @@ class Register extends Component
|
||||||
|
|
||||||
auth()->guard('contact')->loginUsingId($contact->id, true);
|
auth()->guard('contact')->loginUsingId($contact->id, true);
|
||||||
|
|
||||||
$this->dispatch('purchase.context', property: 'contact', value: $contact);
|
// $this->dispatch('purchase.context', property: 'contact', value: $contact);
|
||||||
$this->dispatch('purchase.next');
|
$this->dispatch('purchase.next');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -161,7 +161,7 @@ class Register extends Component
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
if (auth()->guard('contact')->check()) {
|
if (auth()->guard('contact')->check()) {
|
||||||
$this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user());
|
// $this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user());
|
||||||
$this->dispatch('purchase.next');
|
$this->dispatch('purchase.next');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,10 +125,10 @@ class RegisterOrLogin extends Component
|
||||||
$cc->email = $this->email;
|
$cc->email = $this->email;
|
||||||
|
|
||||||
$nmo = new NinjaMailerObject();
|
$nmo = new NinjaMailerObject();
|
||||||
$nmo->mailable = new OtpCode($this->subscription()->company, $this->context['contact'] ?? null, $code);
|
$nmo->mailable = new OtpCode($this->subscription()->company, $contact, $code);
|
||||||
$nmo->company = $this->subscription()->company;
|
$nmo->company = $this->subscription()->company;
|
||||||
$nmo->settings = $this->subscription()->company->settings;
|
$nmo->settings = $this->subscription()->company->settings;
|
||||||
$nmo->to_user = $cc;
|
$nmo->to_user = $contact;
|
||||||
|
|
||||||
NinjaMailerJob::dispatch($nmo);
|
NinjaMailerJob::dispatch($nmo);
|
||||||
|
|
||||||
|
|
@ -161,7 +161,7 @@ class RegisterOrLogin extends Component
|
||||||
if ($contact) {
|
if ($contact) {
|
||||||
auth()->guard('contact')->loginUsingId($contact->id, true);
|
auth()->guard('contact')->loginUsingId($contact->id, true);
|
||||||
|
|
||||||
$this->dispatch('purchase.context', property: 'contact', value: $contact);
|
// $this->dispatch('purchase.context', property: 'contact', value: $contact);
|
||||||
$this->dispatch('purchase.next');
|
$this->dispatch('purchase.next');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -184,8 +184,6 @@ class RegisterOrLogin extends Component
|
||||||
additional: $this->additional_fields,
|
additional: $this->additional_fields,
|
||||||
);
|
);
|
||||||
|
|
||||||
nlog($data);
|
|
||||||
|
|
||||||
$rules = $service->rules();
|
$rules = $service->rules();
|
||||||
$data = Validator::make($data, $rules)->validate();
|
$data = Validator::make($data, $rules)->validate();
|
||||||
|
|
||||||
|
|
@ -194,7 +192,7 @@ class RegisterOrLogin extends Component
|
||||||
|
|
||||||
auth()->guard('contact')->loginUsingId($contact->id, true);
|
auth()->guard('contact')->loginUsingId($contact->id, true);
|
||||||
|
|
||||||
$this->dispatch('purchase.context', property: 'contact', value: $contact);
|
// $this->dispatch('purchase.context', property: 'contact', value: $contact);
|
||||||
$this->dispatch('purchase.next');
|
$this->dispatch('purchase.next');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -214,7 +212,7 @@ class RegisterOrLogin extends Component
|
||||||
|
|
||||||
auth()->guard('contact')->loginUsingId($contact->id, true);
|
auth()->guard('contact')->loginUsingId($contact->id, true);
|
||||||
|
|
||||||
$this->dispatch('purchase.context', property: 'contact', value: $contact);
|
// $this->dispatch('purchase.context', property: 'contact', value: $contact);
|
||||||
$this->dispatch('purchase.next');
|
$this->dispatch('purchase.next');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -264,7 +262,7 @@ class RegisterOrLogin extends Component
|
||||||
{
|
{
|
||||||
|
|
||||||
if (auth()->guard('contact')->check()) {
|
if (auth()->guard('contact')->check()) {
|
||||||
$this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user());
|
// $this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user());
|
||||||
$this->dispatch('purchase.next');
|
$this->dispatch('purchase.next');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,20 @@ class Coupon extends Component
|
||||||
|
|
||||||
public ?string $couponCode = null;
|
public ?string $couponCode = null;
|
||||||
|
|
||||||
|
public bool $showCouponCode = false;
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
$subscription = $this->subscription();
|
||||||
|
$this->showCouponCode = ($subscription->promo_discount > 0) && (!array_key_exists('valid_coupon',$this->context));
|
||||||
|
|
||||||
|
if(isset($this->context['request_data']['coupon']) && $this->context['request_data']['coupon'] == $this->subscription()->promo_code){
|
||||||
|
$this->showCouponCode = false;
|
||||||
|
$this->dispatch('purchase.context', property: "valid_coupon", value: $this->context['request_data']['coupon']);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#[Computed()]
|
#[Computed()]
|
||||||
public function subscription()
|
public function subscription()
|
||||||
{
|
{
|
||||||
|
|
@ -35,6 +49,7 @@ class Coupon extends Component
|
||||||
|
|
||||||
public function applyCoupon()
|
public function applyCoupon()
|
||||||
{
|
{
|
||||||
|
|
||||||
$this->validate([
|
$this->validate([
|
||||||
'couponCode' => ['required', 'string', 'min:3'],
|
'couponCode' => ['required', 'string', 'min:3'],
|
||||||
]);
|
]);
|
||||||
|
|
@ -42,25 +57,20 @@ class Coupon extends Component
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if($this->couponCode == $this->subscription()->promo_code) {
|
if($this->couponCode == $this->subscription()->promo_code) {
|
||||||
|
$this->showCouponCode = false;
|
||||||
|
$this->dispatch('purchase.context', property: "valid_coupon", value: $this->couponCode);
|
||||||
$this->couponCode = null;
|
$this->dispatch('summary.refresh');
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$this->addError('couponCode', 'Invalid coupon code.');
|
$this->addError('couponCode', ctrans('texts.invalid_coupon'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->addError('couponCode', 'Invalid coupon code.');
|
$this->addError('couponCode', ctrans('texts.invalid_coupon'));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// public function quantity($id, $value): void
|
|
||||||
// {
|
}
|
||||||
// $this->dispatch('purchase.context', property: "bundle.optional_one_time_products.{$id}.quantity", value: $value);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public function render(): \Illuminate\View\View
|
public function render(): \Illuminate\View\View
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -29,17 +29,12 @@ class Methods extends Component
|
||||||
|
|
||||||
public function mount(): void
|
public function mount(): void
|
||||||
{
|
{
|
||||||
nlog($this->subscription_id);
|
|
||||||
|
|
||||||
$total = collect($this->context['products'])->sum('total_raw');
|
$total = collect($this->context['products'])->sum('total_raw');
|
||||||
|
|
||||||
|
|
||||||
$methods = auth()->guard('contact')->user()->client->service()->getPaymentMethods($total); //@todo this breaks down when the cart is in front of the login - we have no context on the user - nor their country/currency()
|
$methods = auth()->guard('contact')->user()->client->service()->getPaymentMethods($total); //@todo this breaks down when the cart is in front of the login - we have no context on the user - nor their country/currency()
|
||||||
|
|
||||||
$this->methods = $methods;
|
$this->methods = $methods;
|
||||||
|
|
||||||
nlog($methods);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleSelect(string $company_gateway_id, string $gateway_type_id)
|
public function handleSelect(string $company_gateway_id, string $gateway_type_id)
|
||||||
|
|
|
||||||
|
|
@ -82,63 +82,99 @@ class Summary extends Component
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->dispatch('purchase.context', property: 'bundle', value: $bundle);
|
$this->dispatch('purchase.context', property: 'bundle', value: $bundle);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function oneTimePurchasesTotal(bool $raw = false)
|
/**
|
||||||
|
* Base calculations for one-time purchases
|
||||||
|
*/
|
||||||
|
#[Computed]
|
||||||
|
public function oneTimePurchasesTotal(): float
|
||||||
{
|
{
|
||||||
if (isset($this->context['bundle']['recurring_products']) === false) {
|
if (!isset($this->context['bundle']['one_time_products'])) {
|
||||||
return 0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$one_time = collect($this->context['bundle']['one_time_products'])->sum(function ($item) {
|
$one_time = collect($this->context['bundle']['one_time_products'])->sum(function ($item) {
|
||||||
return $item['product']['price'] * $item['quantity'];
|
return (float)$item['product']['price'] * (float)$item['quantity'];
|
||||||
});
|
});
|
||||||
|
|
||||||
$one_time_optional = collect($this->context['bundle']['optional_one_time_products'])->sum(function ($item) {
|
$one_time_optional = collect($this->context['bundle']['optional_one_time_products'])->sum(function ($item) {
|
||||||
return $item['product']['price'] * $item['quantity'];
|
return (float)$item['product']['price'] * (float)$item['quantity'];
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($raw) {
|
return (float)$one_time + (float)$one_time_optional;
|
||||||
return $one_time + $one_time_optional;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Number::formatMoney($one_time + $one_time_optional, $this->subscription()->company);
|
/**
|
||||||
|
* Base calculations for recurring purchases
|
||||||
}
|
*/
|
||||||
|
#[Computed]
|
||||||
public function recurringPurchasesTotal(bool $raw = false)
|
public function recurringPurchasesTotal(): float
|
||||||
{
|
{
|
||||||
if (isset($this->context['bundle']['recurring_products']) === false) {
|
if (!isset($this->context['bundle']['recurring_products'])) {
|
||||||
return 0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$recurring = collect($this->context['bundle']['recurring_products'])->sum(function ($item) {
|
$recurring = collect($this->context['bundle']['recurring_products'])->sum(function ($item) {
|
||||||
return $item['product']['price'] * $item['quantity'];
|
return (float)$item['product']['price'] * (float)$item['quantity'];
|
||||||
});
|
});
|
||||||
|
|
||||||
$recurring_optional = collect($this->context['bundle']['optional_recurring_products'])->sum(function ($item) {
|
$recurring_optional = collect($this->context['bundle']['optional_recurring_products'])->sum(function ($item) {
|
||||||
return $item['product']['price'] * $item['quantity'];
|
return (float)$item['product']['price'] * (float)$item['quantity'];
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($raw) {
|
return (float)$recurring + (float)$recurring_optional;
|
||||||
return $recurring + $recurring_optional;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return \sprintf(
|
/**
|
||||||
'%s/%s',
|
* Calculate subtotal before any discounts
|
||||||
Number::formatMoney($recurring + $recurring_optional, $this->subscription()->company),
|
*/
|
||||||
RecurringInvoice::frequencyForKey($this->subscription()->frequency_id ?? 0)
|
#[Computed]
|
||||||
|
protected function calculateSubtotal(): float
|
||||||
|
{
|
||||||
|
return $this->oneTimePurchasesTotal() + $this->recurringPurchasesTotal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate discount amount based on subtotal
|
||||||
|
*/
|
||||||
|
#[Computed]
|
||||||
|
public function discount(): float
|
||||||
|
{
|
||||||
|
if (!isset($this->context['valid_coupon']) ||
|
||||||
|
$this->context['valid_coupon'] != $this->subscription()->promo_code) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$subscription = $this->subscription();
|
||||||
|
$discount = $subscription->promo_discount;
|
||||||
|
|
||||||
|
return $subscription->is_amount_discount
|
||||||
|
? $discount
|
||||||
|
: ($this->calculateSubtotal() * $discount/100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format subtotal for display
|
||||||
|
*/
|
||||||
|
#[Computed]
|
||||||
|
public function subtotal(): string
|
||||||
|
{
|
||||||
|
return Number::formatMoney(
|
||||||
|
$this->calculateSubtotal(),
|
||||||
|
$this->subscription()->company
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Computed()]
|
/**
|
||||||
public function total()
|
* Calculate and format final total
|
||||||
|
*/
|
||||||
|
#[Computed]
|
||||||
|
public function total(): string
|
||||||
{
|
{
|
||||||
return Number::formatMoney(
|
return Number::formatMoney(
|
||||||
collect([
|
$this->calculateSubtotal() - $this->discount(),
|
||||||
$this->oneTimePurchasesTotal(raw: true),
|
|
||||||
$this->recurringPurchasesTotal(raw: true),
|
|
||||||
])->sum(),
|
|
||||||
$this->subscription()->company
|
$this->subscription()->company
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -192,6 +228,23 @@ class Summary extends Component
|
||||||
return $products;
|
return $products;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[On('summary.refresh')]
|
||||||
|
public function refresh()
|
||||||
|
{
|
||||||
|
// nlog("am i refreshing here?");
|
||||||
|
|
||||||
|
// $this->oneTimePurchasesTotal = $this->oneTimePurchasesTotal();
|
||||||
|
// $this->recurringPurchasesTotal = $this->recurringPurchasesTotal();
|
||||||
|
// $this->discount = $this->discount();
|
||||||
|
|
||||||
|
// nlog($this->oneTimePurchasesTotal);
|
||||||
|
// nlog($this->recurringPurchasesTotal);
|
||||||
|
// nlog($this->discount);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
return view('billing-portal.v3.summary');
|
return view('billing-portal.v3.summary');
|
||||||
|
|
|
||||||
|
|
@ -214,10 +214,14 @@ class Subscription extends BaseModel
|
||||||
$in_stock_quantity = data_get($product, 'in_stock_quantity', 0);
|
$in_stock_quantity = data_get($product, 'in_stock_quantity', 0);
|
||||||
$max_limit = 100;
|
$max_limit = 100;
|
||||||
|
|
||||||
if(!$this->use_inventory_management)
|
if (!$this->use_inventory_management) {
|
||||||
return $max_quantity != 0 ? $max_quantity : $max_limit;
|
return min($max_limit, $max_quantity > 0 ? $max_quantity : $max_limit);
|
||||||
|
}
|
||||||
|
|
||||||
return $max_quantity !=0 ? $max_quantity : min($max_limit, $in_stock_quantity);
|
if ($max_quantity > 0) {
|
||||||
|
return min($max_limit, $max_quantity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return min($max_limit, $in_stock_quantity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,6 @@ class UpdatePaymentMethods
|
||||||
|
|
||||||
private function buildPaymentMethodMeta(PaymentMethod $method, $type_id)
|
private function buildPaymentMethodMeta(PaymentMethod $method, $type_id)
|
||||||
{
|
{
|
||||||
nlog($method->type);
|
|
||||||
|
|
||||||
switch ($type_id) {
|
switch ($type_id) {
|
||||||
case GatewayType::CREDIT_CARD:
|
case GatewayType::CREDIT_CARD:
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<livewire:billing-portal.cart.optional-recurring-products
|
<livewire:billing-portal.cart.optional-recurring-products
|
||||||
|
:subscription_id="$this->subscription->hashed_id"
|
||||||
:context="$context"
|
:context="$context"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -24,12 +25,10 @@
|
||||||
:context="$context"
|
:context="$context"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@if($this->subscription->promo_discount > 0)
|
|
||||||
<livewire:billing-portal.cart.coupon
|
<livewire:billing-portal.cart.coupon
|
||||||
:subscription_id="$this->subscription->hashed_id"
|
:subscription_id="$this->subscription->hashed_id"
|
||||||
:context="$context"
|
:context="$context"
|
||||||
/>
|
/>
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<form wire:submit="handleSubmit">
|
<form wire:submit="handleSubmit">
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
<div class="space-y-10">
|
<div class="space-y-10">
|
||||||
|
@if($showCouponCode)
|
||||||
<div>
|
<div>
|
||||||
<div class="flex rounded-lg overflow-hidden border border-gray-300">
|
<div class="flex rounded-lg overflow-hidden border border-gray-300">
|
||||||
<div class="relative flex-grow">
|
<div class="relative flex-grow">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
wire:model.live="couponCode"
|
wire:model="couponCode"
|
||||||
placeholder="Enter coupon code"
|
placeholder="{{ __('texts.promo_code') }}"
|
||||||
class="block w-full px-4 py-2 border-0 outline-none focus:ring-0 sm:text-sm"
|
class="block w-full px-4 py-2 border-0 outline-none focus:ring-0 sm:text-sm"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -14,7 +15,7 @@
|
||||||
wire:loading.attr="disabled"
|
wire:loading.attr="disabled"
|
||||||
class="inline-flex items-center border-l border-gray-300 bg-gray-50 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-primary-500"
|
class="inline-flex items-center border-l border-gray-300 bg-gray-50 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-primary-500"
|
||||||
>
|
>
|
||||||
<span wire:loading.remove wire:target="applyCoupon">Apply</span>
|
<span wire:loading.remove wire:target="applyCoupon">{{ __('texts.apply') }}</span>
|
||||||
<span wire:loading wire:target="applyCoupon">
|
<span wire:loading wire:target="applyCoupon">
|
||||||
<svg class="h-4 w-4 animate-spin" viewBox="0 0 24 24">
|
<svg class="h-4 w-4 animate-spin" viewBox="0 0 24 24">
|
||||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"/>
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"/>
|
||||||
|
|
@ -27,4 +28,5 @@
|
||||||
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
|
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -29,15 +29,15 @@
|
||||||
|
|
||||||
<div class="flex flex-col-reverse space-y-3">
|
<div class="flex flex-col-reverse space-y-3">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
@if($subscription->use_inventory_management && $product['in_stock_quantity'] <= 0)
|
@if($this->subscription->use_inventory_management && $product['in_stock_quantity'] <= 0)
|
||||||
<p class="text-sm font-light text-red-500 text-right mr-2 mt-2">{{ ctrans('texts.out_of_stock') }}</p>
|
<p class="text-sm font-light text-red-500 text-right mr-2 mt-2">{{ ctrans('texts.out_of_stock') }}</p>
|
||||||
@else
|
@else
|
||||||
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
|
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<select id="{{ $product['hashed_id'] }}" wire:change="quantity($event.target.id, $event.target.value)" class="rounded-md border-gray-300 shadow-sm sm:text-sm" {{ $subscription->use_inventory_management && $product['in_stock_quantity'] < 1 ? 'disabled' : '' }}>
|
<select id="{{ $product['hashed_id'] }}" wire:change="quantity($event.target.id, $event.target.value)" class="rounded-md border-gray-300 shadow-sm sm:text-sm" {{ $this->subscription->use_inventory_management && $product['in_stock_quantity'] < 1 ? 'disabled' : '' }}>
|
||||||
<option {{ $entry['quantity'] == '0' ? 'selected' : '' }} value="0" selected="selected">0</option>
|
<option {{ $entry['quantity'] == '0' ? 'selected' : '' }} value="0" selected="selected">0</option>
|
||||||
@for ($i = 1; $i <= $subscription->maxQuantity($product); $i++)
|
@for ($i = 1; $i <= $this->subscription->maxQuantity($product); $i++)
|
||||||
<option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option>
|
<option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option>
|
||||||
@endfor
|
@endfor
|
||||||
</select>
|
</select>
|
||||||
|
|
|
||||||
|
|
@ -23,22 +23,22 @@
|
||||||
|
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<h2 class="text-lg font-medium">{{ $product['product_key'] }}</h2>
|
<h2 class="text-lg font-medium">{{ $product['product_key'] }}</h2>
|
||||||
<p class="block text-sm">{{ \App\Utils\Number::formatMoney($product['price'], $this->subscription['company']) }} / <span class="lowercase">{{ App\Models\RecurringInvoice::frequencyForKey($subscription->frequency_id) }}</span></p>
|
<p class="block text-sm">{{ \App\Utils\Number::formatMoney($product['price'], $this->subscription['company']) }} / <span class="lowercase">{{ App\Models\RecurringInvoice::frequencyForKey($this->subscription->frequency_id) }}</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col-reverse space-y-3">
|
<div class="flex flex-col-reverse space-y-3">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
|
|
||||||
@if($subscription->use_inventory_management && $product['in_stock_quantity'] <= 0)
|
@if($this->subscription->use_inventory_management && $product['in_stock_quantity'] <= 0)
|
||||||
<p class="text-sm font-light text-red-500 text-right mr-2 mt-2">{{ ctrans('texts.out_of_stock') }}</p>
|
<p class="text-sm font-light text-red-500 text-right mr-2 mt-2">{{ ctrans('texts.out_of_stock') }}</p>
|
||||||
@else
|
@else
|
||||||
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
|
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<select id="{{ $product['hashed_id'] }}" wire:change="quantity($event.target.id, $event.target.value)" class="rounded-md border-gray-300 shadow-sm sm:text-sm" {{ $subscription->use_inventory_management && $product['in_stock_quantity'] < 1 ? 'disabled' : '' }}>
|
<select id="{{ $product['hashed_id'] }}" wire:change="quantity($event.target.id, $event.target.value)" class="rounded-md border-gray-300 shadow-sm sm:text-sm" {{ $this->subscription->use_inventory_management && $product['in_stock_quantity'] < 1 ? 'disabled' : '' }}>
|
||||||
<option {{ $entry['quantity'] == '0' ? 'selected' : '' }} value="0" selected="selected">0</option>
|
<option {{ $entry['quantity'] == '0' ? 'selected' : '' }} value="0" selected="selected">0</option>
|
||||||
@for ($i = 1; $i <= $subscription->maxQuantity($product); $i++)
|
@for ($i = 1; $i <= $this->subscription->maxQuantity($product); $i++)
|
||||||
<option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option>
|
<option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option>
|
||||||
@endfor
|
@endfor
|
||||||
</select>
|
</select>
|
||||||
|
|
|
||||||
|
|
@ -23,14 +23,14 @@
|
||||||
|
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<h2 class="text-lg font-medium">{{ $product['product_key'] }}</h2>
|
<h2 class="text-lg font-medium">{{ $product['product_key'] }}</h2>
|
||||||
<p class="block text-sm">{{ \App\Utils\Number::formatMoney($product['price'], $this->subscription['company']) }} / <span class="lowercase">{{ App\Models\RecurringInvoice::frequencyForKey($subscription->frequency_id) }}</span></p>
|
<p class="block text-sm">{{ \App\Utils\Number::formatMoney($product['price'], $this->subscription['company']) }} / <span class="lowercase">{{ App\Models\RecurringInvoice::frequencyForKey($this->subscription->frequency_id) }}</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col-reverse space-y-3">
|
<div class="flex flex-col-reverse space-y-3">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
@if($subscription->per_seat_enabled)
|
@if($this->subscription->per_seat_enabled)
|
||||||
@if($subscription->use_inventory_management && $product['in_stock_quantity'] < 1)
|
@if($this->subscription->use_inventory_management && $product['in_stock_quantity'] < 1)
|
||||||
<p class="text-sm font-light text-red-500 text-right mr-2 mt-2">{{ ctrans('texts.out_of_stock') }}</p>
|
<p class="text-sm font-light text-red-500 text-right mr-2 mt-2">{{ ctrans('texts.out_of_stock') }}</p>
|
||||||
@else
|
@else
|
||||||
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
|
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
|
||||||
|
|
@ -40,19 +40,13 @@
|
||||||
id="{{ $product['hashed_id'] }}"
|
id="{{ $product['hashed_id'] }}"
|
||||||
class="rounded-md border-gray-300 shadow-sm sm:text-sm"
|
class="rounded-md border-gray-300 shadow-sm sm:text-sm"
|
||||||
wire:change="quantity($event.target.id, $event.target.value)"
|
wire:change="quantity($event.target.id, $event.target.value)"
|
||||||
{{ $subscription->use_inventory_management && $product['in_stock_quantity'] < 1 ? 'disabled' : '' }}
|
{{ $this->subscription->use_inventory_management && $product['in_stock_quantity'] < 1 ? 'disabled' : '' }}
|
||||||
>
|
>
|
||||||
<option {{ $entry['quantity'] == '1' ? 'selected' : '' }} value="1">1</option>
|
<option {{ $entry['quantity'] == '1' ? 'selected' : '' }} value="1">1</option>
|
||||||
|
|
||||||
@if($subscription->max_seats_limit > 1)
|
@for ($i = 1; $i <= $this->subscription->maxQuantity($product); $i++)
|
||||||
@for ($i = 2; $i <= ($subscription->use_inventory_management ? min($this->subscription->max_seats_limit,$product['in_stock_quantity']) : $subscription->max_seats_limit); $i++)
|
|
||||||
<option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option>
|
<option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option>
|
||||||
@endfor
|
@endfor
|
||||||
@else
|
|
||||||
@for ($i = 2; $i <= ($subscription->use_inventory_management ? min($product['in_stock_quantity'], min(100,$product['max_quantity'])) : min(100,$product['max_quantity'])); $i++)
|
|
||||||
<option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option>
|
|
||||||
@endfor
|
|
||||||
@endif
|
|
||||||
</select>
|
</select>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,27 @@
|
||||||
<div class="space-y-2 mt-4 border-t pt-2">
|
<div class="space-y-2 mt-4 border-t pt-2">
|
||||||
<div class="flex justify-between text-sm">
|
<div class="flex justify-between text-sm">
|
||||||
<span class="uppercase">{{ ctrans('texts.one_time_purchases') }}</span>
|
<span class="uppercase">{{ ctrans('texts.one_time_purchases') }}</span>
|
||||||
<span>{{ $this->oneTimePurchasesTotal() }}</span>
|
<span>{{ \App\Utils\Number::formatMoney($this->oneTimePurchasesTotal(), $this->subscription->company) }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-between text-sm">
|
<div class="flex justify-between text-sm">
|
||||||
<span class="uppercase">{{ ctrans('texts.recurring_purchases') }}</span>
|
<span class="uppercase">{{ ctrans('texts.recurring_purchases') }}</span>
|
||||||
<span>{{ $this->recurringPurchasesTotal() }}</span>
|
<span>{{ \App\Utils\Number::formatMoney($this->recurringPurchasesTotal(), $this->subscription->company) }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="flex justify-between text-sm uppercase border-t pt-2">
|
||||||
class="flex justify-between text-sm uppercase border-t pt-2"
|
<span>{{ ctrans('texts.subtotal') }}</span>
|
||||||
>
|
<span>{{ $this->subtotal() }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if($this->discount() > 0)
|
||||||
|
<div class="flex justify-between text-sm uppercase">
|
||||||
|
<span>{{ ctrans('texts.discount') }}</span>
|
||||||
|
<span class="font-semibold">{{ \App\Utils\Number::formatMoney($this->discount(), $this->subscription->company) }}</span>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="flex justify-between text-sm uppercase border-t pt-2">
|
||||||
<span>{{ ctrans('texts.total') }}</span>
|
<span>{{ ctrans('texts.total') }}</span>
|
||||||
<span class="font-semibold">{{ $this->total() }}</span>
|
<span class="font-semibold">{{ $this->total() }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue